U-Boot
The second-stage bootloader on most embedded Linux devices. It brings up the board, loads the kernel, and offers an interactive shell that is frequently the fastest way to own the system.
U-Boot (Das U-Boot) is the second-stage bootloader used by the overwhelming majority of embedded Linux devices: routers, cameras, NAS boxes, industrial gateways, set-top boxes. It initialises RAM and the essential peripherals, locates a kernel in flash or over the network, and jumps to it. It also ships an interactive command shell, and that shell is often the single most productive target on the whole board.
Where it sits
The mask ROM inside the SoC runs first and is immutable. It finds U-Boot in flash and jumps to it. U-Boot then sets up the board and loads the kernel. Everything after the mask ROM lives in writable flash, which is precisely why the boot chain is an attack surface rather than a formality.
The interactive prompt
On boot U-Boot prints a banner and counts down an autoboot delay, usually one to three seconds. Interrupt it (any key, or a specific one the banner names) and you land at a prompt:
U-Boot 2016.01 (Mar 14 2019 - 09:22:41)
Hit any key to stop autoboot: 0
=>
That prompt is reached over the board's serial console, which is why UART discovery matters so much. From it:
printenv # dump the whole environment: bootargs, bootcmd, mtdparts
setenv bootargs '... init=/bin/sh'
saveenv # persist to flash (if the environment is writable)
boot # run bootcmd
md 0x80000000 100 # memory display
sf probe; sf read ... # read raw SPI flash into RAM
tftpboot 0x80000000 zImage
Why it matters
printenv alone is a full reconnaissance report. It tells you the flash partition layout (mtdparts), where the kernel and rootfs live, the console device, and the exact kernel command line the vendor intends. mtdparts in particular is what lets you dump the right offsets afterwards.
Then there is the classic escalation: append init=/bin/sh (or single) to bootargs and boot. The kernel starts, mounts the rootfs, and runs your shell as PID 1 instead of the vendor init. No password, no login, root on the device. If the environment is writable the change survives a reboot; if not, it still lasts for this boot, which is usually enough to dump the filesystem or plant a key.
U-Boot can also read and write raw flash (sf, nand), so a board with an open prompt and no other exposed interface can still be fully imaged.
Hardening, and how it fails
- Autoboot delay set to 0. Reduces the window rather than closing it; a key sent during reset sometimes still lands, and the delay is itself an environment variable.
CONFIG_AUTOBOOT_KEYED. Requires a specific string to interrupt. The string is in the U-Boot binary you can dump from flash.- Console disabled or
silent=1. The UART pads are still there and the environment variable is still settable if flash is writable. - Verified boot. The real defence: U-Boot checks a signature on the kernel image (FIT with signed hashes) and refuses an unsigned one. This is what stops the
init=/bin/shtrick from being useful, provided the signature coversbootargstoo. Many deployments sign the kernel and leave the command line unauthenticated, which defeats the entire scheme.
From Linux
On a running device with a shell, fw_printenv and fw_setenv read and write the same environment from userspace, configured by /etc/fw_env.config. That file also reveals where the environment lives in flash.
Pitfalls
- Saving a broken environment can brick the boot. Note the original values before
saveenv, and prefer a one-shotsetenvplusbootwhen you only need this boot. uImageis U-Boot's own container format: a 64-byte header (load address, entry point, CRC, OS and architecture) wrapped around a usually compressed kernel. Editing the payload without recomputing the CRC makes the image unbootable.- Two boards of the same model can run different U-Boot builds with different commands compiled in.
helpon the target is the authority, not the upstream documentation.
What it pairs with
You reach the prompt over uart, usually through a usb-uart adapter after finding the header with a logic-analyzer or a multimetre. What you dump from it goes to binwalk. The wider boot chain and its trust model are in bootloader and secure-boot.
Further reading
Used in these courses
**Beginner** probe lab. Clip onto a U-Boot serial console, find the non-default baud, dump the bootloader environment to leak a provisioning secret, then read the fused OTP key and unlock the secure region. Model B: bring your own probe CLI, flags travel over the line.
UART: From Signal to ShellUART is the most common debug interface left exposed on IoT devices. This course takes you from understanding the electrical signal all the way to getting a root shell - the exact path a hardware hacker follows in the field. Every major embedded device you'll ever audit has UART. Learn it once, use it everywhere.