цепочка загрузки встраиваемого Linux
July 30, 2026 · – посетителей
В прошлый раз я писал про DFU как способ прошивки firmware через USB. Тот пост оставил без ответа один вопрос, который заслуживает отдельного разбора: что на самом деле происходит между нажатием кнопки питания и появлением приглашения shell? DFU — лишь одно из ответвлений этого пути, так что стоит один раз пройти весь путь целиком.
Этапы
В виде flowchart на Mermaid цепочка (с местом DFU в ней) выглядит так:
flowchart TD
A[Power-on / Reset] --> B[Boot ROM<br/>immutable, on-chip]
B --> C{Valid image on<br/>boot media?}
C -->|No / forced| D[ROM recovery mode<br/>UART / USB]
C -->|Yes| E[SPL<br/>first-stage bootloader]
E --> F[U-Boot<br/>second-stage bootloader]
F --> G{Enter DFU?}
G -->|Yes| H[DFU mode<br/>waiting for firmware over USB]
G -->|No| I[Load kernel + device tree]
I --> J[Linux kernel]
J --> K[Mount root filesystem]
K --> L[init / systemd]
И в отрисованном виде:
Boot ROM
Записана в кремний на этапе производства — после этого в ней ничего нельзя изменить. Её единственная задача — найти хоть что-то загружаемое на одном из небольшого набора носителей загрузки (eMMC, SD, QSPI-флеш, иногда USB) в соответствии с boot-mode пинами или eFuse, и перейти туда. Если ничего подходящего не найдено, большинство SoC на этом этапе переключается в минимальный режим восстановления через UART или USB — самое первое место, где вообще можно "поговорить" с чипом.
SPL
Сокращение от Secondary Program Loader (термин U-Boot; другие производители называют это FSBL или похоже). Он выполняется из небольшого объёма SRAM на кристалле, ещё до инициализации DRAM, поэтому должен быть крошечным. Его основная задача именно в этом: поднять DRAM, а затем загрузить в неё следующий этап — полноценный U-Boot.
U-Boot целиком
Это тот загрузчик, который большинство людей имеет в виду, говоря "загрузчик". У него есть драйверы, shell, переменные окружения, поддержка сети и интерпретатор команд. Именно здесь на самом деле живёт DFU — выполнение dfu 0 mmc 0 (или похожей команды) переводит U-Boot в режим DFU вместо продолжения обычной загрузки, и именно с этим режимом со стороны хоста общается dfu-util. В противном случае он загружает образ ядра и blob device tree в память и передаёт управление ядру.
Ядро и пользовательское пространство
Ядро распаковывает себя, поднимает консоль, опрашивает оборудование, используя переданное ему device tree, и монтирует корневую файловую систему — часто ту же карту eMMC или SD, с которой загружался загрузчик, иногда NFS во время разработки. После монтирования корневой файловой системы ядро передаёт управление процессу с PID 1 — обычно это systemd на образе, собранном с помощью Yocto, — и именно здесь на самом деле начинается "пользовательское пространство".
Почему это важно для DFU
DFU обретает смысл только тогда, когда видно его место в цепочке: это ответвление, которое U-Boot может выбрать вместо загрузки ядра, а не отдельная надстройка сверху. Именно поэтому DFU не может спасти от любого сбоя: если сама boot ROM не может найти валидный SPL, вы вообще никогда не доберётесь до U-Boot и будете зависеть от того, какой режим восстановления поддерживает boot ROM (а это сильно варьируется от производителя к производителю и заслуживает отдельного поста).
Дополнительное чтение
- U-Boot: Generic SPL framework — как собирается SPL и за что он отвечает.
- Trusted Firmware-A: Firmware Design — более сложный многоэтапный процесс загрузки (BL1/BL2/BL31/BL32/BL33), используемый на многих современных Arm SoC с цепочкой безопасной загрузки, который на этих платформах находится ниже U-Boot.
По теме
- Что такое Device Tree? — как железо описывается ядру
- Что такое DFU? — прошивка по USB, когда другого пути не осталось
Комментарии