Запуск ОСРВ Embox на Banana Pi M1
Об этой операционной системе я узнал на данном ресурсе, из многочисленных публикаций её разработчиков. Для тех кто не в курсе - это отечественная операционная система реального времени для встраиваемых устройств с открытым исходным кодом. Её официальный репозиторий расположен тут. Возникло желание опробовать этот проект в деле. Благодаря документации к проекту на виртуальной машине qemu удалось запустить конфигурации для разных платформ. Однако, виртуальная машина - это не для настоящих джедаев).
Тщательно изучив список поддерживаемых одноплатников, остановил свой выбор на Banana Pi M1 с ARM-процессором Allwinner A20. Плата была заказана на Aliexpress, и когда она прибыла, настало время экспериментов. Но всё, как и ожидалось, оказалось не так просто...
1. Установка загрузчика
У разработчиков имеется публикация о запуске Embox на Rasbery Pi. Однако, когда я с ней ознакомился, меня постигло легкое разочарование. Дело в том, что в ней сначала устанавливается дистрибутив линукса Rasbian, а затем путем манипуляций с образами ядра, вместо ядра линукса, загрузчику U-boot подсовывается образ Embox. По крайней мере я понял именно так. Мне же хотелось другого - настроить U-boot и установить Embox, настроив загрузчик, безо всякой установки линукса (хотя, такой вариант я тоже попробовал, но не прокатило). В своих изысканиях я опирался на материалы вот этой публикации.
Итак, прежде всего получаем код загрузчика с официального репозитория на Github
$ git clone https://github.com/u-boot/u-boot.git u-boot
Далее необходимо получить тулчейн для кросскомпиляции под целевую платформу. Взять его можно вот тут, для облегчения участи приведу прямую ссылку на скачивания того тулчейна, который использовал я. Собственно говоря, это компилятор gcc и прочее хозяйство для сборки под 32-битную платформу ARM, предназначенный для работы на архитектуре x86_64 под GNU/Linux. В моем случае используется дистрибутив ArchLinux. Поэтому я поступил еще проще - установил тулчейн в систему из репозитория AUR. Качаем снапшот со сценарием сборки и пакетирования и
$ tar pxf arm-linux-gnueabihf-gcc13-linaro-bin.tar.gz
$ cd arm-linux-gnueabihf-gcc13-linaro-bin
$ makepkg -si
что приводит к сборке и установки пакета.
Далее, переходим в каталог с кодом u-boot и задаем окружение сборки
$ CROSS_COMPILE=arm-linux-gnueabihf-
$ export CROSS_COMPILE
Теперь выполняем конфигурирование сборки под целевой одноплатник
$ make Bananapi_defconfig
Выхлоп
HOSTCC scripts/basic/fixdep
HOSTCC scripts/kconfig/conf.o
YACC scripts/kconfig/zconf.tab.c
LEX scripts/kconfig/zconf.lex.c
HOSTCC scripts/kconfig/zconf.tab.o
HOSTLD scripts/kconfig/conf
#
# configuration written to .config
#
показывает нам что конфигурирование выполнено. Далее выполняем сборку
$ make; make all
После компиляции, прямо в дереве исходников имеем следующие файлы
Теперь необходимо подготовить носитель, будет располагаться образ Embox и сам загрузчик. Banana Pi M1 достаточно старая плата, поэтому использует SD-карты, которые отыскались в кармашке футляра фотоаппарата супруги. Одну из них я "реквизировал" для дьявольских экспериментов)
Флешку необходимо специальным образом разметить. Разметка выглядит так
№ первого сектора | Размер секции | Назначение |
0 | 8 Кб | 512 байт для MBR и 7680 байт на системные нужды |
8 | 24 Кб | SPL (Вторичный загрузчик) |
32 | 512 Кб | U-Boot |
544 | 128 Кб | Для нужд U-Boot (хранение переменных окружения и прочее) |
672 | 352 Кб | Зарезервировано |
1024 | Не ограничен | Доступно для создания разделов |
Естественно, понадобиться и карт-ридер. Таковой есть на моем ноутбуке, но кросскомпиляцию я выполняю на десктопе, чью возможности гораздо шире лэптопа (i9-10900 KF против Intel 2020М). Поэтому. было принято решение купить карт-ридер c USB. Теперь подключаем карт-ридер, вставляем в него накопитель. Выясняем имя устройства
$ lsblk
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINTS
sda 8:0 0 5,5T 0 disk
├─sda1 8:1 0 128M 0 part
└─sda2 8:2 0 5,5T 0 part /mnt/bigdata
sdb 8:16 0 2,7T 0 disk
└─sdb1 8:17 0 2,7T 0 part /mnt/data
sdc 8:32 0 1,8T 0 disk
├─sdc1 8:33 0 150G 0 part
├─sdc2 8:34 0 195,6G 0 part
├─sdc3 8:35 0 1T 0 part /home
├─sdc4 8:36 0 1K 0 part
├─sdc5 8:37 0 100G 0 part
└─sdc6 8:38 0 390,4G 0 part /home/maisvendoo/ntfs_part
sdd 8:48 1 59,3G 0 disk
sde 8:64 1 0B 0 disk
sdf 8:80 1 0B 0 disk
sr0 11:0 1 1024M 0 rom
nvme0n1 259:0 0 465,8G 0 disk
├─nvme0n1p1 259:1 0 100M 0 part /boot/efi
├─nvme0n1p2 259:2 0 300G 0 part
└─nvme0n1p3 259:3 0 165,7G 0 part /
В моем случае, флешка объемом 64 Гб оказалась устройством с именем /dev/sdd. Ок, запускаем программу разметки
# fdisk /dev/sdd
Создаем новую таблицу MBR
Command (m for help): o
Created a new DOS disklabel with disk identifier 0xa53166ce.
Для запуска Embox нам нужен один раздел, размером от 50 до 100 Мб, отформатированный в FAT, для размещения скрипта загрузчика и образа Embox. Руководствуясь статьей-шпаргалкой я создал раздел на 75 Мб
Command (m for help): n
Partition type
p primary (0 primary, 0 extended, 4 free)
e extended (container for logical partitions)
Select (default p): p
Partition number (1-4, default 1): 1
First sector (2048-7831551, default 2048): 2048
Last sector, +sectors or +size{K,M,G,T,P} (2048-7831551, default 7831551): +75M
Created a new partition 1 of type 'Linux' and of size 75 MiB.
Командой "w" записываем изменения на диск. Далее форматируем этот раздел
$ mkfs.vfat /dev/sdd1
Теперь нам необходимо очистить место для размещения загрузчика. При этом надо позаботиться о том, чтобы не затереть MBR - первые 512 байт, и не затронуть 1024 сектор и далее, исходя из вышеприведенной таблицы. Даем команду
# dd if=/dev/zero of=/dev/sdd bs=1K count=1023 seek=1
Смысл заклинания: записываем нули (устройство /dev/zero) на SD-карту (устройство /dev/sdd) блоками размером 1 Кб (bs=1K), до 1023 сектора (count=1023) пропуская нулевой сектор (seek=1)
Далее, записываем вторичный загрузчик U-boot, используя его образ, расположенный в файле u-boot-sunxi-with-spl.bin, полученный после компиляции
# dd if=u-boot-sunxi-with-spl.bin of=/dev/sdd bs=1024 seek=8
Запись начинаем с восьмого сектора (seek=8), согласно приведенной выше таблице разметки. Ок, загрузчик установлен, можно выполнить первое включение платы. Вставляем SD-карту в разъем на плате, подключаем преобразователь USB <-> USART в соответствии с распиновкой
Подключаемся терминалом к USART
$ minicom -D /dev/ttyUSB0
Даем питание на "банан" и наблюдаем в терминале активность такого рода
Система ожила, загрузчик работоспособен! Далее он в прямом смысле пытается "достучаться до небес", ибо никаких указаний что грузить и откуда он не получил от нас.
Но это не страшно, U-Boot система умная, в чем я не раз убедился в процессе отладки. Сейчас мы его научим грузить Embox.
2. Сборка образа Embox
Идем на официальный репозиторий проекта и делаем в удобном нам месте файловой системы
$ git clone https://github.com/embox/embox.git embox
А дальше я начну излагать свои мытарства. Руководствуясь правилом собирать релиз я перешел на него
4 git checkout v0.6.0
Потом, находясь в корне репозитория, конфигурируем сборку под наш "банан"
$ make confload-platform/banana_pi/bpi_m1
Выхлоп
Config complete
говорит о том что можно собирать
$ make -j20
Да-да-да, у меня 20 логических ядер... Тем не менее, во время сборки можно перекурить (курение вредит вашему здоровью, лучше чаю выпить), в итоге в дереве исходников мы получаем каталоги build/base/bin и conf/. В первом содержится результат сборки
Во втором - скопированы конфиги сборки - далее они пригодятся!
Файл образа ОС - embox.bin, предназначен для запуска на целевой системе. Файл embox - ELF-файл 32-битной ARM, содержащий отладочную информацию. Итак, что делать с собраным ядром? Надо как-то заставить U-Boot его запустить.
3. Настройка загрузки ядра Embox в U-Boot
Ядро embox.bin следует скопировать в загрузочный раздел, который мы создали, тот самый FAT-раздел на 75 Мб.
Мало зная предметную область, чего я только не перепробовал. Да, я запускал линукс через U-Boot на двух моделях Orange Pi, пользуясь вышеупомянутой статьей. Но тут коса нашла на камень. Финт с подменой образа ядра, как в публикации разработчиков по "малине" не прошел. Да, я таки развернул арч на "банане" и он весело и легко загрузился. Перенастройка U-Boot ничего не дала. Задача решалась в несколько подходов с перерывами, что применялось - стыдно сказать и не буду говорить. По пути читались доки по U-Boot, кое какие команды отрабатывали адекватно, но загрузки не было. Тогда я нагуглил что существует телеграмм-чат, где есть и разработчики. Там я задал отчаянное "ЧЯНД!".
В ответ я получил очень быстрый ответ с просьбой показать конфиги сборки. И тут мне дошло... Пока я ждал ответа, нашел вот этот образец для загрузки BPI M2 Zero
Стало ясно, что я загружаю файл не по тому что нужно виртуальному адресу и управление передаю на деревню к дедушке. А где взять этот адрес загрузки? Да в файле conf/lds.conf!
В общем, вооружившись полученной информацией, я перевел U-Boot в командный режим: на сообщении "Hit any key to stop autoboot:" с обратным отсчетом нажмите любую кнопку в терминале. Вывалится приглашение командной строки. Далее смело набралось
=> load mmc 0:1 0x43008040 embox.bin
611916 bytes read in 27 ms (21.6 MiB/s)
Ок, далее
=> go 0x43008040
И о чудо!
Ядро Embox буднично сообщило о начале своей загрузки и... замерло... Но это уже была победа. Далее мне удалось таки загрузится на конфиге BPI M2 Zero, но разработчики приняли во внимание полученную от меня информацию, проконсультировали, внесли поправки в код, и мне удалось загрузить систему на мой аппаратной конфигурации. В итоге это выразилось, в пока еще не принятый пулл-реквест. Пока приведу файл platform/banana_pi/templates/bpi_m1/mods.conf, для удачного запуска из моего форка, с учетом последних коммитов в главный репозиторий.
Теперь напишем скрипт для автоматической загрузки системы. В разделе флешки куда мы положили ядро создаем файл boot.cmd следующего содержания
load mmc 0:1 0x43008040 embox.bin
go 0x43008040
то есть перечисляем команды загрузки. Первая - загружает образ в память по указанному адресу, вторая - передает управление на данный адрес. Далее компилируем скрипт загрузки
$ mkimage -C none -A arm -T script -d boot.cmd boot.scr
образуется бинарный файл boot.scr, который U-Boot ищет в корне загрузочного раздела и разбирая его, выполняет перечисленные там команды. В итоге мы таки получим наш желанный результат
Благодарности
Большое спасибо ребятам из команды Embox, особенно Алексею Жмулину и Антону Бондареву за консультации, информацию, оперативность и приятное общение и взаимодействие. В итоге решилась взаимовыгодная задача - я получил рабочую систему, разработчики - тест на одной из аппаратных платформ. Надеюсь это не последнее сотрудничество в данном ключе. Проект Embox интересен и не типичен для российского IT - открытость и отсутствие токсичного общения - то, что могли бы принять на вооружение многие разработчики отечественного ПО. Удачи проекту, буду следить, и по мере сил поддерживать.
Благодарю за внимание!