The Embedded Linux Boot Chain

July 30, 2026 · visitors

Last time I wrote about DFU as a way to flash firmware over USB. That post skipped a question worth answering on its own: what actually happens between pressing the power button and a shell prompt showing up? DFU is just one branch off this path, so it's worth walking the whole thing once.

The stages

Drawn as a Mermaid flowchart, the chain (with DFU's place in it) looks like this:

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]

And rendered:

Flowchart of the embedded Linux boot chain: power-on resets into the boot ROM, which checks the boot media for a valid image. If none is found (or recovery is forced), it drops into a UART/USB recovery mode. Otherwise it loads the SPL, which loads U-Boot proper. U-Boot can either enter DFU mode to wait for firmware over USB, or load the kernel and device tree, boot Linux, mount the root filesystem, and hand off to init/systemd.

Boot ROM

Baked into the silicon at manufacturing time — nothing about it can be changed after the fact. Its only job is to find something bootable on one of a small set of boot media (eMMC, SD, QSPI flash, sometimes USB) according to boot-mode pins or eFuses, and jump to it. If it can't find anything valid, most SoCs fall back to a minimal UART or USB recovery mode at this stage — the very first place you can talk to the chip at all.

SPL

Short for Secondary Program Loader (U-Boot's term for it; other vendors call it FSBL or similar). It runs from a small amount of on-chip SRAM, before DRAM is even initialized, so it has to be tiny. Its main job is exactly that: bring up DRAM, then load the next stage — full U-Boot — into it.

U-Boot proper

This is the bootloader most people mean when they say "bootloader." It has drivers, a shell, environment variables, network support, and a command interpreter. It's also where DFU actually lives — running dfu 0 mmc 0 (or similar) drops U-Boot into DFU mode instead of continuing the normal boot, which is the mode dfu-util talks to from the host side. Otherwise, it loads the kernel image and device tree blob into memory and jumps to the kernel.

Kernel and userspace

The kernel decompresses itself, brings up the console, probes hardware using the device tree it was handed, and mounts a root filesystem — often the same eMMC or SD card the bootloader booted from, sometimes NFS during development. Once the root filesystem is mounted, the kernel hands off to PID 1 — usually systemd on a Yocto-built image — and that's where "userspace" actually starts.

Why this matters for DFU

DFU only makes sense once you see where it sits: it's a detour U-Boot can take instead of loading the kernel, not a separate thing bolted on top. That's also why DFU can't rescue every failure mode — if the boot ROM itself can't find a valid SPL, you never reach U-Boot at all, and you're relying on whatever recovery mode the boot ROM supports instead (which varies a lot by vendor and is a good topic for another post).

Further reading

Comments