Загрузчик U-Boot
О документе
Данный документ описывает особенности работы загрузчика U-Boot для модулей на базе микросхемы 1892ВА018 (aka СКИФ, Scythian, MCom-03).
Возможности
Поддержка модулей на базе MCom-03:
ROCK Pi N10 с установленным процессорным модулем ELV-MC03-SMARC r1.1;
NGFW-CB r1.0 с установленным процессорным модулем ELV-MC03-SMARC r1.1;
ELV-SMARC-CB r1.0 с установленным процессорным модулем ELV-MC03-SMARC r1.1;
ELV-SMARC-CB r2.10.3 с установленным процессорным модулем ELV-MC03-SMARC r1.1;
ELV-SMARC-CB r3.2.1 с установленным процессорным модулем ELV-MC03-SMARC r1.1;
ELV-SMARC-CB r3.2.1 с установленным процессорным модулем ELV-MC03-SMARC r2.7.1;
Трастфон-Э ОПН r1.1 с установленным процессорным модулем Трастфон-Э ПМ r1.5;
MCom-03 BuB r1.3.x, r1.5.x (aka IPCom BuB).
Загрузчик исполняется на ARM CPU.
Поддержка загрузки ядра Linux по схеме Generic Distro и UEFI.
Поддержка загрузки PXE.
Поддержка UART0.
Поддержка GEMAC0, GEMAC1 (10/100/1000 Мбит/с).
Поддержка SDMMC0, SDMMC1.
Поддержка QSPI0, QSPI1.
Поддержка USB 2.0 и 3.0.
Поддержка переменных окружения в памятях QSPI0, QSPI1.
Поддержка заводских настроек.
Поддержка автоопределения DTB Linux на основе ID EEPROM платы-носителя SMARC.
Исходный код
Git-репозиторий исходного кода загрузчика — https://github.com/elvees/u-boot/tree/mcom03.
Основные файлы поддержки микросхемы:
arch/arm/dts/mcom03*.dts
,board/elvees/
,configs/mcom03*_defconfig
,include/configs/mcom03.h
.
Конфигурация и сборка
В U-Boot используется единый файл конфигурации для всех поддерживаемых модулей —
mcom03_defconfig
.
Результатом сборки исходных кодов загрузчика является образ u-boot.bin
и набор бинарных файлов
Device Tree (DTB). Образ доступен в корневой директории загрузчика после завершения сборки, а DTB —
в директории arch/arm/dts
.
Примечание
Загрузчик, выполняемый до U-Boot, должен загрузить DTB для соответствующей платы в DDR по предопределённому адресу, после чего U-Boot считает DTB из этого адреса.
Для сборки загрузчика на ПК требуется кросс-компилятор aarch64-linux-gnu.
Переменные окружения, влияющие на сборку загрузчика:
CROSS_COMPILE
— префикс кросс-компилятора;PATH
— пути для поиска используемых приложений.
Официальная инструкция по сборке U-Boot https://u-boot.readthedocs.io/en/latest/build/gcc.html.
Пример сборки загрузчика для модуля MCom-03 BuB r1.3.0:
export PATH=<compiler-path>:$PATH
export CROSS_COMPILE=aarch64-linux-
make mcom03_defconfig
make -j $(nproc)
Загрузка ядра Linux
Выбор DTB ядра
Выбор DTB Linux для загрузки ядра осуществляется путём установки U-Boot переменной board
по
следующему алгоритму:
Примечание
ID EEPROM платы-носителя согласно спецификации SMARC HW Specification Version 2.1;
на ROCK Pi N10 отсутствует ID EEPROM.
Внимание
Значение параметра FDT
в extlinux.conf
имеет приоритет выше, чем значение переменной
board
. Подробнее см. Прошивка SD-карты.
Для модулей ELV-MC03-SMARC поддерживаются два варианта загрузки Linux:
с указанием платы-носителя в свойстве
compatible
DTS U-Boot. Данный способ не отличается от запуска других модулей и требует прошивки SBL с нужным DTB U-Boot. Например, для запуска ELV-MC03-SMARC r1.0 на ELV-SMARC-CB r3.3.0 необходимо использоватьsbl-xip-mcom03-elvmc03smarc-r1.0-elvsmarccb-r3.3.0.bin
.с использованием автоматического определения платы-носителя.
Автоматическое определение плат-носителей SMARC
Для поддержки загрузки SMARC-модуля на произвольной плате-носителе необходимо:
прошить QSPI-память SMARC-модуля файлом
sbl-xip-mcom03-elvmc03smarc-<revision>-smarccommoncb-r1.0.bin
, где<revision>
— ревизия модуля SMARC;прошить ID EEPROM платы-носителя строкой с её наименованием.
Имя платы носителя можно получить из имени DTB-файла ядра Linux. Например, для ELV-SMARC-CB r3.3.0
в ID EEPROM необходимо записать строку elvsmarccb-r3.3.0
:
/boot/elvees/mcom03-elvmc03smarc-r2.9.1-elvsmarccb-r3.3.0.dtb
^^^^^^^^^^^^^^^^^
Примечание
DTB в директории /boot/elvees создаются из соответствующих DTS.
Выбор метода загрузки
U-Boot выполняет поиск загрузочных разделов (разделы имеющее флаг boot
) по приоритету
описанному в переменной boot_targets
(usb, mmc1, mmc0 и т. д.). В найденном загрузочном
разделе производится поиск файла /boot/extlinux/extlinux.conf
. Если файл найден, U-Boot
загружает ядро методом Generic Distro. Если /boot/extlinux/extlinux.conf
не найден, то
U-Boot проверяет тип загрузочного раздела. Если тип соответствует ESP, то начинается загрузка
по UEFI. В противном случае выполняется попытка загрузки со следующего загрузочного раздела.
Generic Distro (extlinux.conf)
Подробнее см. Generic Distro. Порядок загрузки:
SD-карта (или eMMC, USB-накопитель) содержит файл
extlinux.conf
, образы ядер Linux, DTB-файлы, rootfs.U-Boot перебирает источники загрузки SDMMC0, SDMMC1, USB, монтирует файловые системы с носителей подключенных к SD-контроллерам MCom-03, USB-контроллерам, проверяет наличие
extlinux.conf
. Порядок носителей определяется переменнойboot_targets
.U-Boot запускает ядро в соответствии с первым обнаруженным
extlinux.conf
(копирует DTB и ядро в ОЗУ, передаёт управление ядру).
В схеме загрузки Distro нет стандартного механизма, с помощью которого можно зафиксировать загрузку с определенного устройства на шине USB. При наличии нескольких подключенных USB-накопителей на одной шине USB при отсутствии загрузочного раздела попытки загрузки прекращаются после первой неудачи. Подробнее см. описание проблемы на GitHub.
UEFI
Подробнее см. UEFI on U-Boot, UEFI Global Variables. Порядок загрузки:
U-Boot ищет файл
ubootefi.var
(хранилище UEFI-переменных).Если файл
ubootefi.var
найден, то U-Boot загружает файл согласно приоритету загрузки, указанному в переменнойBootOrder
. Иначе U-Boot загружает fallback file \EFI\BOOT\bootaa64.efi (загрузчик ОС и т. п.)U-Boot загружает нужный DTB ядра из директории
dtb
в корне ESP.U-Boot передает управление приложению UEFI.
Если на нескольких блочных устройствах будет хотя бы по одному ESP, то загрузка UEFI-приложения
всегда будет производиться с первого найденного ESP-раздела c учетом приоритета загрузки,
описанного в переменной boot_targets
.
Карта памяти
Ниже представлена диаграмма, на которой изображена карта памяти на разных этапах загрузки Linux.
Предупреждение
Карта памяти зависит от параметров сборки и может отличаться от того как представлено на диаграмме в данном документе. Карта может измениться при финальной реализации. Диаграмма предоставлена для ознакомительных целей и в каждом конкретном случае должна проверяться разработчиком конечного продукта.
Переменные окружения
Загрузчик поддерживает настройку через переменные окружения.
Во время запуска загрузчик выполняет поиск переменных окружения, сохраненных в QSPI флеш-памяти:
при успешном обнаружении устанавливаются переменные окружения, сохраненные в QSPI флеш-памяти;
в случае ошибки устанавливаются переменные окружения, заданные по умолчанию в коде U-Boot (см. файл
include/configs/mcom03.h
).
U-Boot использует переменную first_boot_checker для определения первой загрузки после перепрошивки. В случае, если переменная не определена, то U-Boot создаёт переменную и сохраняет все переменные окружения в секцию переменных окружения в QSPI. Принудительное сохранение переменных окружения необходимо для чтения/записи переменных из ОС (утилиты fw_setenv/fw_printenv).
В MCom-03 U-Boot определен ряд переменных окружения, которые могут быть установлены через заводские настройки, переопределены пользователем или через U-Boot DTB:
- board
Имя модуля, используемое для выбора Linux DTB.
Данная переменная устанавливается автоматически, подробнее см. Выбор DTB ядра.
- board_override
Имя модуля, заданное пользователем. См.
board
. Переменная предназначена для отладки и не должна использоваться в готовых изделиях.
- ethaddr
MAC-адрес контроллера Ethernet.
При наличии переменной, U-Boot использует указанный адрес для инициализации контроллерa Ethernet и добавляет свойство
local-mac-address
в узел контроллерa внутри Device Tree. Поиск узла осуществляется посредством псевдонимаethernet
узлаaliases
. Таким образом, U-Boot и Linux используют один MAC-адрес во время работы. При отсутствии переменной U-Boot и Linux генерируют произвольные MAC-адреса независимо.При загрузке модуля выполняется чтение заводских настроек и анализ наличия переменной
factory_eth0_mac
. Если factory_eth0_mac существует, а ethaddr не существует, то ethaddr создаётся и заполняется значением factory_eth0_mac. В противном случае ethaddr не изменяется.
- ethaddr1
MAC-адрес второго контроллера Ethernet. Переменная настраивается аналогично
ethaddr
, при анализе заводских настроек используется factory_eth1_mac.
- factory_board
Имя модуля из заводских настроек.
Переменная создаётся динамически и не должна изменяться пользователем. Переменная не используется в случае отсутствия заводских настроек. См.
board
.
- factory_eth0_mac
MAC-адрес Ethernet из заводских настроек.
Переменная создаётся динамически и не должна изменяться пользователем. Переменная не используется в случае отсутствия заводских настроек. См.
ethaddr
.Важно
MAC-адрес должен использовать двоеточие для разделения групп октетов (
AA:BB:CC:DD:EE:FF
), в противном случае поведение загрузчика неопределено.
- factory_serial
Серийный номер модуля из заводских настроек.
Переменная создаётся динамически и не должна изменяться пользователем. Переменная не используется в случае отсутствия заводских настроек. См. также
serial#
.
- serial#
Серийный номер модуля.
Значение переменной записывается в свойство
serial-number
в DTB (свойство доступно в Linux). При загрузке модуля выполняется чтение заводских настроек и анализ наличия переменнойfactory_serial
. Если factory_serial существует, а serial# не существует, то serial# создаётся и заполняется значением factory_serial. В противном случае serial# не изменяется.
Секция переменных окружения находится в предпоследнем 64 килобайтном секторе флеш-памяти.
Примеры «сброса» секции переменных окружения:
Для очистки секции переменных окружения с использованием mcom03-flash-tools на модуле с флеш-памятью размером 16 МБ:
mcom03-flash --port /dev/ttyUSBx erase qspi0 64K --offset 0xFE_0000
Для копирования переменных по умолчанию в секцию переменных окружения в терминале U-Boot:
env default -a saveenv
Заводские настройки
Заводские настройки — набор параметров, прошиваемых производителем аппаратуры. Заводские настройки используются для установки уникальных идентификаторов экземпляров аппаратуры, калибровочных параметров и идентификаторов моделей аппаратуры. Наличие заводских настроек позволяет унифицировать программное обеспечения для различных моделей аппаратуры.
Перезапись заводских настроек не должна быть возможна без специальных мер по отключению аппаратной защиты (rescue mode или прошивка специальной версией с отключенной защитой).
Поддержка в U-Boot
Блок настроек хранится в микросхеме eMMC в стандартном разделе Boot partition 0 (далее — boot0). Раздел не имеет таблицы разделов и отформатирован в файловую систему EXT4.
Настройки загрузчика хранятся в текстовом файле uboot-factory.env
. В каждой строке
файла содержатся пары <переменная>=<значение>. Имена переменных должны иметь префикс
factory_
и не должны пересекаться со множеством стандартных переменных U-Boot.
В разделе могут храниться прочие файлы, для которых требуется аппаратно гарантировать неизменяемость во время работы ОС Linux и загрузчика.
Загрузчик считывает настройки из раздела boot0 первого eMMC (mmc 0.1:0
) и устанавливает
стандартные переменные окружения U-Boot.
Примечание
Переменные factory_*
имеют меньший приоритет по сравнению со стандартными переменными.
MMC-устройство с блоком заводских настроек должно обнаруживаться первым. Порядок инициализации должен обеспечиваться в DTS. Например, если eMMC-память с разделом заводских настроек подключена к контроллеру SDMMC1, то в DTS загрузчика для модуля должно выполняться переопределение устройств:
#include "mcom03.dtsi"
/ {
model = ...;
compatible = ...;
aliases {
mmc0 = &sdhci1;
....
};
};
Примечание
Аналогичное объявление в DTS ядра Linux гарантирует фиксированное имя устройства
/dev/mmcblk0boot0
в ОС.
При переменной factory_wp=1
U-Boot включает защиту eMMC Power-On Write Protection boot0
раздела. Защита раздела включается до исполнения команд в терминале U-Boot. Данная переменная
игнорируется, если U-Boot собран с опцией CONFIG_MCOM03_EMMC_BOOT_WP_DISABLED=y
.
Если U-Boot собран с опцией CONFIG_MCOM03_DISABLE_FACTORY=y
, то U-Boot не обращается
к разделу boot0.
Первичная прошивка настроек
Включить питание устройства.
Дождаться загрузки Linux на устройстве.
Из командной строки Linux на устройстве выполнить команды:
# by default kernel always mounts MMC boot partition as read-only echo 0 > /sys/block/mmcblk0boot0/force_ro mkfs.ext4 /dev/mmcblk0boot0 mkdir -p /media/factory mount -t auto -o rw,noexec,nodev,nosuid,sync /dev/mmcblk0boot0 /media/factory # NOTE: factory_wp=1 is optional and can be absent # NOTE: <MAC-ADDRESS-...> hex groups *must* be colon-separated (AA:BB:CC..), # behavior is undefined otherwise cat > /media/factory/uboot-factory.env <<EOF factory_wp=1 factory_board=<board> factory_eth0_mac=<MAC-ADDRESS-0> factory_eth1_mac=<MAC-ADDRESS-1> factory_serial=<SERIAL-NUMBER> EOF sync umount /media/factory
Перепрошивка настроек
Собрать U-Boot c опцией
CONFIG_MCOM03_EMMC_BOOT_WP_DISABLED=y
.Прошить QSPI-память.
Сбросить питание устройства.
Выполнить первичную прошивку настроек.
(при необходимости) Прошить QSPI-память образом U-Boot без вышеуказанной опции.
Драйвер QSPI
Драйвер контроллера QSPI реализует ведущее устройство на шине SPI согласно
классу UCLASS_SPI
(см. doc/driver-model/spi-howto.rst
) модели драйверов U-Boot.
Драйвер поддерживает спецификацию ведущего и ведомых устройств на шине SPI согласно
doc/device-tree-bindings/spi/spi-bus.txt
.
Возможности драйвера:
Поддержка до четырех ведомых устройств.
Передача в формате CPHA = 0 (см. флаг
SPI_CPHA
режима).Полярность сигнала синхронизации CPOL = 0 (см. флаг
SPI_CPOL
режима).Сигнал CS в активном состоянии «логический 0» (см. флаг
SPI_CS_HIGH
режима).Передача слов данных старшим битом вперед (см. флаг
SPI_LSB_FIRST
режима).Ведущее устройство на шине SPI (см. флаг
SPI_SLAVE
режима).Пересылка в режиме full-duplex (в режиме NORMAL):
Передача данных по одному выводу на шине SPI (см. флаг
SPI_TX_BYTE
режима).Прием данных по одному выводу на шине SPI (см. флаг
SPI_RX_SLOW
режима).
Пересылка в режиме half-duplex (в режиме QUAD):
Передача данных по 4 линиям на шине SPI (см. флаг
SPI_TX_QUAD
).Прием данных по 4 линиям на шине SPI (см. флаг
SPI_RX_QUAD
).
Ограничения драйвера:
Не поддерживается установка скорости передачи. Частота на шине SPI равна частоте
clk_ext
, которая указывается в свойствеclocks
в device tree. Частотаclk_ext
должна быть не больше частотыclk_axi
на шине AXI.Размер данных должен быть кратен восьми битам.
Передача в формате CPHA = 1 не поддерживается (флаг
SPI_CPHA
режима должен быть равен 0).Полярность сигнала синхронизации CPOL = 1 не поддерживается (флаг
SPI_CPOL
режима должен быть равен 0).Сигнал CS в активном состоянии «логическая 1» не поддерживается (флаг
SPI_CS_HIGH
режима должен быть равен 0).Передача слов данных младшим битом вперед не поддерживается (флаг
SPI_LSB_FIRST
режима должен быть равен 0).Передача/прием данных по одной линии не поддерживается (флаг
SPI_3WIRE
режима должен быть равен 0).Режим loopback не поддерживается (флаг SPI_LOOP режима должен быть равен 0).
Режим ведомого устройства на шине SPI не поддерживается (флаг
SPI_SLAVE
режима должен быть равен 0).Пропуск принятых байтов данных перед преамбулой не поддерживается (флаг
SPI_PREAMBLE
режима должен быть равен 0).Передача данных по двум выводам на шине SPI не поддерживается (флаг
SPI_TX_DUAL
режима должен быть равен 0).Прием данных по двум выводам на шине SPI не поддерживается (флаг
SPI_RX_DUAL
режима должен быть равен 0).
При инициализации драйвер выполняет:
захват и включение тактового сигнала;
вывод контроллера QSPI из состояния сброса;
настройку контактных площадок в подсистеме HSPERIPH для внешних выводов контроллера QSPI1 на микросхеме MCom-03;
начальную настройку контроллера QSPI.
При удалении драйвер выполняет:
выключение тактового сигнала;
ввод контроллера QSPI в состояние сброса.
Поддержка ELV-MC03-SMARC
Загрузчик и переменные окружения размещаются в QSPI0. Загрузчик поддерживает нижеперечисленные интерфейсы модуля. Наименования интерфейсов приведены в соответствии со спецификацией SMARC 2.1. В скобках указаны контроллеры MCom-03.
Интерфейс |
Примечание |
---|---|
eMMC (SDMMC0) |
Поддерживается HS200 |
GBE0, GBE1 |
Два порта Ethernet 10/100/1000 Мбит/с |
SDIO (SDMMC1) |
|
QSPI0 |
Память установлена на SMARC-модуле. Поддерживается только однобитный режим |
SER1 (UART0) |
Консоль MCom-03 |
USB0, USB1, USB2, USB4, USB5 (USB1) |
USB 2.0 или 3.0 в зависимости от порта |
При загрузке с использованием автоматического определения плат-носителей доступны только следующие интерфейсы: SDIO, SER1, USB0, USB1 и GBE0.
Поддержка MCom-03 BuB
Загрузчик и переменные окружения размещаются в QSPI0.
Загрузчик поддерживает следующие интерфейсы модуля:
Интерфейс |
Примечание |
---|---|
eMMC |
Память eMMC подключена к SDMMC1 MCom-03 |
Ethernet |
Два порта Ethernet 10/100/1000 Мб/с |
SD-карта |
Поддерживается Default Speed. SD-карта подключена к SDMMC0 MCom-03 |
QSPI0 |
Подключена съемная Flash-память. Поддерживается только однобитный режим |
QSPI1 |
Подключена съемная Flash-память. Поддерживается только однобитный режим |
UART0 |
Консоль MCom-03 |
USB0 |
Только USB 2.0. Подключен к USB0 MCom-03 |
USB1 |
Только USB 2.0. Подключен к USB1 MCom-03 |
Инструкции по конфигурации
Загрузка Linux по TFTP и NFS
Для загрузки Linux по TFTP и корневой файловой системы по NFS с динамическим получением IP-адреса модулю необходимо:
Настроить на ПК серверы TFTP и NFS:
В качестве директории для NFS-сервера использовать смонтированный образ
rootfs.ext2
.В корне TFTP-сервера необходимо:
Скопировать образ ядра
Image
и директориюelvees
с dtb-файлами для ядра.Создать директорию
pxelinux.cfg
и создать в ней файлdefault-arm-mcom03
с содержимым:TIMEOUT 3 LABEL MCom-03 Buildroot MENU LABEL PXE boot LINUX /Image FDTDIR /elvees APPEND console=ttyS0,115200 root=/dev/nfs rw nfsroot=<ip_address>:/,vers=4,tcp ip=dhcp earlycon
Изменить <ip_address> в файле
default-arm-mcom03
на IP-адрес NFS-сервера. (не рекомендуется использовать имя хоста NFS-сервера вместо IP-адреса).
Включить модуль, дождаться загрузки терминала U-Boot, установить IP-адрес TFTP-сервера:
setenv serverip <ip_address>
Установить переменную
boot_targets
:setenv boot_targets pxe
(Опционально) Сохранить переменные окружения:
saveenv
Выполнить команду загрузки:
boot