Pull to refresh

RISC'овый Debian под QEMU

Reading time 10 min
Views 22K

Для встраиваемых систем на базе процессоров с архитектурами MIPS и ARM нередко используются специализированные генераторы дистрибутивов ОС GNU/Linux: buildroot, openwrt и прочие Yocto.
Но иногда интересно запустить на такой системе универсальную ОС Debian. Установить Debian на ЭВМ с процессором архитектуры x86/amd64 — дело несложное, а вот со встраиваемыми системами, поверьте, у нас не всё так однозначно...
В данной публикации я расскажу как можно при помощи debootstrap установить, а затем как при помощи QEMU запустить ОС Debian для ЭВМ с процессорами MIPS и ARM.


Введение


Операционные системы GNU/Linux чаще всего состоят по крайней мере из двух компонентов: ядра ОС (kernel) и пользовательских программ (userspace). Ядро Linux (да, да, это именно ядро называется Linux!) непосредственно взаимодействует с аппаратурой и обеспечивает доступ пользовательских программ к аппаратным ресурсам ЭВМ при помощи абстрактных интерфейсов.
В то время как ядро оказывается сильно привязано к конкретному семейству SoC или даже к конкретной плате, приложения пользователя оказываются гораздо более «отвязными» компонентами; их исполняемые файлы оказываются привязаны лишь к конкретной версии системы команд процессора (например, MIPS-I или MIPS32r2), да к версии программных интерфейсов ядра.
Такое положение дел оборачивается следующим: одни и те же приложения становится возможным запускать на совершенно разных SoC, на совершенно разных платах, главное обеспечить, чтобы программные интерфейсы ядра были одинаковы.
Такая «отвязность» приложений может быть очень полезна на практике. Например, в публикации Raspbian и QEMU описывается запуск ОС Raspbian для Raspberry Pi на эмулируемой при помощи QEMU плате ARM Versatile.

План действий


Из вышесказанного понятно, что для запуска Debian на эмулируемой плате с процессором MIPS (или ARM) нам понадобятся:
  • ядро Linux, которое запустится на QEMU;
  • образ корневой файловой системы Debian (т.е. упомянутые выше приложения).

Ядро Linux мы соберём при помощи кросс-средств разработки самостоятельно, а формирование образа корневой файловой системы Debian доверим программе debootstrap.
В качестве инструментальной ЭВМ (ЭВМ, на которой будем проводить кросс-компиляцию и запуск эмулятора QEMU) будем использовать ЭВМ с процессором архитектуры x86_64, работающую под управлением Debian Linux версии testing.
Почему именно Debian testing?
Потому, что Debian testing из коробки поддерживает сравнительную свежую версию QEMU и кросс-компиляторы как для MIPS, так и для ARM.

Все действия по сборке ядра и формированию образа корневой файловой системы выполняются из командной строки, не требуют вмешательства оператора и легко могут быть помещены внутрь скрипта.
Команды, которые надо выполнить от имени пользователя root предварены символом #, команды, которые не нуждаются в привилегиях суперпользователя предварены символом $.
Например:
  • команда для установки ПО исполняется от имени пользователя root:
    # aptitude install -y binfmt-support qemu qemu-user-static debootstrap
  • команда для сборки ядра linux может быть выполнена от имени непривилегированного пользователя:
    $ make

Как быстро соорудить требуемую инструментальную ЭВМ?
Требуемую инструментальную ЭВМ легко соорудить при помощи ПО виртуализации (VMWare, VirtualBox или QEMU/KVM).
Для этого:
  • скачайте образ сетевого установочного диска debian-8.3.0-amd64-netinst.iso,
  • создайте виртуальную ЭВМ со следующими минимальными параметрами: ОЗУ: 1 ГБ, НЖМД: 8 ГБ; подключите к виртуальной ЭВМ установочный загрузочный диск Debian;
  • запустите виртуальную ЭВМ с загрузкой инсталлятора Debian с установочного диска;
  • установите на НЖМД виртуальной ЭВМ ОС Debian в почти минимальной конфигурации (к примеру, для запуска QEMU нет никакой необходимости ставить компоненты web-сервера и графического пользовательского интерфейса):


  • загрузите свежеустановленную ОС Debian, и залогиньтесь как пользователь root;
  • подключите возможность установки пакетов Debian версии testing, для этого в командной строке выполните
    # echo "deb http://ftp.ru.debian.org/debian/ testing main non-free contrib" \
            >> /etc/apt/sources.list
    # apt-get update

Примечание: по-хорошему, лучше бы после apt-get update сделать ещё и apt-get dist-upgrade, но если хотите использовать виртуальную машину только для запуска Debian MIPS/ARM, то делать это вовсе необязательно.



Debian для MIPS


Демонстрацию работы Debian для MIPS под QEMU будем проводить на виртуальной плате MIPS Malta с процессором архитектуры MIPS32R2 в режиме big-endian.

Сборка ядра Linux для QEMU Malta


Сперва озаботимся получением исходных текстов ядра — скачаем их с kernel.org:
$ wget https://cdn.kernel.org/pub/linux/kernel/v4.x/linux-4.4.3.tar.xz

Распаковываем архив и переходим в каталог linux-4.4.3:
$ tar fx linux-4.4.3.tar.xz
$ cd linux-4.4.3

Устанавливаем инструментальные средства (toolchain) для MIPS:
# aptitude install -y gcc-mips-linux-gnu

Кроме toolchain для MIPS для сборки ядра Linux понадобятся дополнительные инструментальные средства:
# aptitude install -y make gcc gawk

Подготовимся к сборке под MIPS:
$ export ARCH=mips
$ export CROSS_COMPILE=mips-linux-gnu-

Переменная ARCH объясняет системе сборки ядра (Kbuild), что все платформено-зависимые компоненты ядра брать в каталоге arch/mips, а переменная CROSS_COMPILE явно указывает Kbuild, каким компилятором (а точнее toolchain) пользоваться — их на машине может быть несколько, а Kbuild любит точность.
Замечание про ARCH и CROSS_COMPILE
В принципе этого можно не делать, а каждый раз устанавливать переменные ARCH и CROSS_COMPILE в командной строке make, но тогда строка make будет выглядеть несколько громоздко.

Замечание про out of tree build
Описываемый ниже порядок сборки ядра Linux называется in tree build, т.е. скомпилированные объектные файлы попадают в те же каталоги, в которых находятся файлы с исходными текстами. Kbuild позволяется использовать порядок сборки out of tree build, при котором объектные файлы попадают в отдельный каталог, что позволяет собирать из одних и тех же исходных текстов сразу несколько разных вариантов ядра, при этом объектные файлы разных вариантов ядра не будут конфликтовать. Подробности см., например, тут.

Теперь выберем конфигурацию для ядра на основе заготовленной конфигурации для платы Malta.
Заготовке конфигурационного файла для платы Malta arch/mips/configs/malta_defconfig, которая поставляется в linux-4.4.3 не подходит по двум причинам:
  • конфигурация рассчитана на плату Maltа в режиме little-endian, а хотелось бы использовать режиме big-endian.
  • в конфигурации malta_defconfig не включены опции (CONFIG_FHANDLE и CONFIG_CGROUPS), без которых Debian 8 попросту не загрузится.

На основе malta_defconfig создадим потребную нам заготовку конфигурационного файла malta-big_defconfig, которая не будет обладать указанными недостатками:
$ sed "s/CONFIG_CPU_LITTLE_ENDIAN=y/CONFIG_CPU_BIG_ENDIAN=y/" \
        < arch/mips/configs/malta_defconfig \
        > arch/mips/configs/malta-big_defconfig
$ echo "CONFIG_FHANDLE=y" >> arch/mips/configs/malta-big_defconfig
$ echo "CONFIG_CGROUPS=y" >> arch/mips/configs/malta-big_defconfig

Теперь из заготовки сгенерируем собственно конфигурационный файл ядра .config:
$ make malta-big_defconfig

И запустим процесс сборки:
$ make

Примечание: Если в вашей инструментальной ЭВМ более одного процессорного ядра, то стоит их использовать. Для того, чтобы распараллелить работу make используется опция -j, аргументом которой является количество задач (команд) которое make будет пытаться запускать одновременно. Так что на 4-процессорной инструментальной ЭВМ имеет смысл запускать make так: $ make -j 4

В результате получим файл ядра vmlinux. Проверим его работоспособность под QEMU!
Установим QEMU:
# aptitude install -y qemu-system

Запустим свежесобранное ядро под QEMU, предварительно покинув каталог linux-4.4.3:
$ cd ..
$ qemu-system-mips -nodefaults -nographic -kernel linux-4.4.3/vmlinux -serial stdio
Linux version 4.4.3 (user@debian) (gcc version 5.3.1 20160205 (Debian 5.3.1-8) )
earlycon: Early serial console at I/O port 0x3f8 (options '38400n8')
bootconsole [uart0] enabled
Config serial console: console=ttyS0,38400n8r
CPU0 revision is: 00019300 (MIPS 24Kc)
FPU revision is: 00739300
MIPS: machine is mti,malta

...
Kernel panic - not syncing: VFS: Unable to mount root fs on unknown-block(0,0)

Как видно, ядро успешно прошло инициализацию и попыталось смонтировать корневую файловую систему, что, впрочем, не получилось.
Создадим же нужную корневую файловую систему!

Создание корневой файловой системы для MIPS


Создание корневой файловой системы Debian поэтому начнём с установки debootstrap и необходимых для его работы компонентов:
# aptitude install -y binfmt-support qemu qemu-user-static debootstrap

Теперь запустим первую стадию debootstrap:
# debootstrap --foreign --arch=mips jessie debian-jessie-mips/ \
        http://ftp.ru.debian.org/debian/

На первой стадии debootstrap скачает необходимые для минимальной корневой файловой системы пакеты Debian версии jessie (stable) с сайта ftp.ru.debian.org/debian (официальное российское «зеркало» Debian) для 32-разрядной архитектуры MIPS big-endian (опции --foreign и --arch=mips), и распакует их в каталог debian-jessie-mips/.
По итогам работы первой стадии debootstrap в каталоге debian-jessie-mips/ будет сформирована файловая система, очень похожая на настоящую, её даже можно попробовать использовать для загрузки. Однако компоненты корневой файловой системы (пакеты Debian) на этой стадии ещё не настроены.
Для проведения настройки необходимо запустить вторую стадию debootstrap. На этой стадии понадобится запускать программы для MIPS, так что придётся использовать специальный вариант QEMU, так называемый usermode qemu, который обеспечивает запуск отдельных программ для Linux MIPS под Linux amd64.
Подложим статически собранный эмулятор системы с процессором архитектуры MIPS внутрь корневой файловой системы и запустим debootstrap внутри корневой файловой системы при помощи chroot:
# cp /usr/bin/qemu-mips-static debian-jessie-mips/usr/bin/
# DEBIAN_FRONTEND=noninteractive DEBCONF_NONINTERACTIVE_SEEN=true \
        LC_ALL=C LANGUAGE=C LANG=C \
        PATH=/usr/local/bin:/usr/bin:/bin:/usr/local/sbin:/usr/sbin:/sbin \
        chroot debian-jessie-mips/ /debootstrap/debootstrap --second-stage

По окончании работы второй стадии debootstrap компоненты корневой файловой системы Debian настроены, и осталось нанести последние штрихи (например, поправить кое-какие файлы в /etc, скажем, настроить hostnamе и сеть, добавить пользователей и т.д.).
Но для данного демонстрационного примеры мы ограничимся установкой тривиального пароля 123 для пользователя root:
# echo 'root:123' | chroot debian-jessie-mips/ chpasswd

Вот теперь корневую файловую систему можно считать настроенной — пора заметать следы. Для сохранности заархивируем корневую файловую систему:
# rm debian-jessie-mips/usr/bin/qemu-mips-static
# tar czf debian-jessie-mips.tar.gz -C debian-jessie-mips .

Для запуска под эмулятором корневую файловую систему придётся поместить на виртуальный накопитель (в случае Malta это виртуальный IDE-диск).
Оценим, какого размера диск нам придётся создать:
# du -sh debian-jessie-mips/
284M    debian-jessie-mips/

Раз корневая файловая система занимает менее 300 МБ, то вполне можно выделить для её хранения виртуальный диск на 512 МБ. Создадим файл виртуального диска, создадим на нём файловую систему ext2, на которую и скопируем нашу корневую файловую систему:
$ dd if=/dev/zero bs=1M count=512 of=debian-jessie-mips.ext2
$ /sbin/mke2fs -F debian-jessie-mips.ext2

# mkdir ext2
# mount debian-jessie-mips.ext2 ext2/
# tar xf debian-jessie-mips.tar.gz -C ext2/
# umount ext2/
# rmdir ext2/

Теперь запустим Debian Linux под QEMU:
$ qemu-system-mips -nodefaults -nographic -kernel linux-4.4.3/vmlinux \
        -serial stdio -hda debian-jessie-mips.ext2 -append "root=/dev/sda"

После появления приглашения login: можно залогиниться root'ом (пароль — 123) и проверить тип процессора:


Debian для ARM


Демонстрацию работы Debian для ARM под QEMU будем проводить на виртуальной плате ARM Versatile PB.
Действия по сборке ядра Linux и созданию корневой файловой системы почти полностью аналогичны таковым для MIPS, так что приведу только последовательность команд для достижения результата с минимальными комментариями.
Будем считать, что мы начинаем работать на «чистой» инструментальной ЭВМ.

Сборка ядра Linux для ARM Versatile PB


$ wget https://cdn.kernel.org/pub/linux/kernel/v4.x/linux-4.4.3.tar.xz
$ tar fx linux-4.4.3.tar.xz
$ cd linux-4.4.3

# aptitude install -y gcc-arm-linux-gnueabi
# aptitude install -y make gcc gawk

$ export ARCH=arm
$ export CROSS_COMPILE=arm-linux-gnueabi-

С заготовкой конфигурации ядра для Versatile придётся повозиться, так как эмулируемое QEMU встроенное ПЗУ Versatile PB весьма невелико (64 МБ). К счастью, эмулируемая Versatile PB имеет контроллер PCI, к которому можно подключить виртуальный контроллер SCSI. Однако поддержку указанной аппаратуры придётся включить в ядре принудительно:
$ cp arch/arm/configs/versatile_defconfig arch/arm/configs/versatile-debian_defconfig
$ echo "CONFIG_FHANDLE=y" >> arch/arm/configs/versatile-debian_defconfig
$ echo "CONFIG_CGROUPS=y" >> arch/arm/configs/versatile-debian_defconfig
$ echo "CONFIG_DEVTMPFS=y" >> arch/arm/configs/versatile-debian_defconfig
$ echo "CONFIG_TMPFS=y" >> arch/arm/configs/versatile-debian_defconfig
$ echo "CONFIG_PCI=y" >> arch/arm/configs/versatile-debian_defconfig
$ echo "CONFIG_SCSI=y" >> arch/arm/configs/versatile-debian_defconfig
$ echo "CONFIG_BLK_DEV_SD=y" >> arch/arm/configs/versatile-debian_defconfig
$ echo "CONFIG_SCSI_SYM53C8XX_2=y" >> arch/arm/configs/versatile-debian_defconfig

$ make versatile-debian_defconfig
$ make

# aptitude install -y qemu-system

В отличии от платы MIPS Malta поддержка загрузки vmlinux для Versatile PB не реализована, поддерживается загрузка образов zImage:
$ cd ..
$ qemu-system-arm -nodefaults -nographic -M versatilepb \
        -kernel linux-4.4.3/arch/arm/boot/zImage \
        -append "console=ttyAMA0" -serial stdio
...
Uncompressing Linux... done, booting the kernel.
Booting Linux on physical CPU 0x0
Linux version 4.4.3 (antony@debian) (gcc version 5.3.1 20160205 (Debian 5.3.1-8) )
CPU: ARM926EJ-S [41069265] revision 5 (ARMv5TEJ), cr=00093177
CPU: VIVT data cache, VIVT instruction cache
Machine: ARM-Versatile PB
...
Kernel panic - not syncing: VFS: Unable to mount root fs on unknown-block(0,0)


Создание корневой файловой системы для ARM


# aptitude install -y binfmt-support qemu qemu-user-static debootstrap
# debootstrap --foreign --arch=armel jessie debian-jessie-armel \
        http://ftp.ru.debian.org/debian/
# cp /usr/bin/qemu-arm-static debian-jessie-armel/usr/bin/
# DEBIAN_FRONTEND=noninteractive DEBCONF_NONINTERACTIVE_SEEN=true \
        LC_ALL=C LANGUAGE=C LANG=C \
        PATH=/usr/local/bin:/usr/bin:/bin:/usr/local/sbin:/usr/sbin:/sbin \
        chroot debian-jessie-armel/ /debootstrap/debootstrap --second-stage
# echo 'root:123' | chroot debian-jessie-armel/ chpasswd
# rm debian-jessie-armel/usr/bin/qemu-arm-static
# tar czf debian-jessie-armel.tar.gz -C debian-jessie-armel .

# du -sh debian-jessie-armel/
270M    debian-jessie-armel/

$ dd if=/dev/zero bs=1M count=512 of=debian-jessie-armel.ext2
$ /sbin/mke2fs -F debian-jessie-armel.ext2

# mkdir ext2
# mount debian-jessie-armel.ext2 ext2/
# tar xf debian-jessie-armel.tar.gz -C ext2/
# umount ext2/
# rmdir ext2/

$ qemu-system-arm -nodefaults -nographic -M versatilepb \
        -kernel linux-4.4.3/arch/arm/boot/zImage \
        -append "console=ttyAMA0 root=/dev/sda" \
        -serial stdio -hda debian-jessie-armel.ext2

Результаты проверки типа процессора (напоминаю, пароль — 123):


Заключение


Как видно установка и запуск Debian для MIPS и ARM — дело не такое и сложное.
Запуск Debian на реальной плате с процессором архитектуры MIPS или ARM как правило оказывается делом более хлопотным, и достоин отдельной публикации.

Ссылки


Tags:
Hubs:
+21
Comments 10
Comments Comments 10

Articles