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.

Quick reference
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; bootcmd runs 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

What I learned

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.