Bootloaders
U-Boot
The most widely used open-source bootloader in embedded Linux — see Fundamentals for where it sits in the boot chain. This page covers U-Boot itself: its environment, shell, and the standard commands used to get a kernel running.
- What it is
- The most common open-source full bootloader for embedded Linux — loads the kernel/DTB and hands off control.
- Mental model
- An interactive shell that runs briefly before Linux does, just long enough to fetch and boot the kernel.
- Key numbers
- Environment variables persist in flash until
saveenv;bootcmdruns automatically unless interrupted. - Reach for it when
- You're bringing up new hardware, debugging a boot failure, or need to override boot behavior interactively.
Dropping into the U-Boot shell
Most boards print a countdown ("Hit any key to stop autoboot") on the serial console. Interrupting it during that window drops you into an interactive shell instead of continuing the default boot sequence — the standard way to debug or override boot behavior without reflashing anything.
The environment
U-Boot keeps a set of persistent key-value variables (the environment), stored in flash separately from the bootloader binary itself, that control boot behavior. A handful matter on almost every board:
- bootcmd
- The command sequence run automatically if the countdown isn't interrupted.
- bootargs
- The Linux kernel command line, passed at boot — see Linux → Boot.
- bootdelay
- Seconds to wait for a keypress before autobooting.
- fdtaddr / fdt_addr
- RAM address the device tree blob is loaded to.
=> printenv bootcmd
=> setenv bootargs "console=ttyS0,115200 root=/dev/mmcblk0p2 rw"
=> saveenv # persist changes to flash
A typical boot sequence
# load the kernel and device tree from an SD card partition into RAM
load mmc 0:1 ${kernel_addr_r} zImage
load mmc 0:1 ${fdt_addr_r} board.dtb
# set the kernel command line
setenv bootargs console=ttyS0,115200 root=/dev/mmcblk0p2 rw rootwait
# hand off to the kernel — never returns on success
bootz ${kernel_addr_r} - ${fdt_addr_r}
bootz boots a raw zImage; bootm boots a
U-Boot-wrapped uImage (or a FIT image, which can bundle kernel + DTB +
initramfs together with signature verification for secure boot setups).
Boot device probing
bootcmd commonly encodes a fallback order — try one boot
device, then another, then drop to a recovery/network boot — rather
than hardcoding a single source. Distro-style boot scripts (like the
"distro_bootcmd" used by many mainline U-Boot configs) generalize this
into scanning each available device for a standard boot script file.
Real-world applications
- SBC dev boards — Raspberry Pi (via its own bootloader lineage), BeagleBone, and most ARM SBCs either use U-Boot directly or something conceptually identical.
- A/B failsafe updates —
bootcmdfallback logic is commonly used to try a newly-updated partition and revert to the previous known-good one if it fails to boot. - Network/PXE boot for provisioning — U-Boot's network boot support is widely used in factory/lab environments to image many boards without individually flashing storage.
- Yocto/Buildroot-based products — both major embedded Linux build systems generate and configure U-Boot as a standard part of the image.
saveenv is easy to forget — changes made with
setenv only live in RAM until you explicitly persist
them. A board that "loses" your bootarg changes after a power cycle
almost always just means saveenv was never run.