TECHNICAL BLOG

Deep Dives for Engineers

Detailed technical articles covering the real problems we solve in embedded systems, AI, and robotics engineering.

U-Boot Bootloader: Deep Configuration and Optimization for Embedded Linux
Embedded Systems

U-Boot Bootloader: Deep Configuration and Optimization for Embedded Linux

Worksprout Team Jul 22, 2024 9 min read

A practical guide to configuring U-Boot for custom hardware, optimising boot time, and implementing secure boot on embedded Linux targets.

What U-Boot Does and Why It Matters

Das U-Boot (Universal Bootloader) is the de-facto standard first-stage bootloader for embedded Linux systems. It runs before the kernel, initialises DRAM and peripheral controllers, loads the kernel and device tree from storage or network, and hands control to the kernel with a boot argument string. Getting U-Boot right is foundational: a misconfigured bootloader causes boot failures that are difficult to debug remotely, and a slow bootloader directly inflates the total boot time your end users experience.

Board Configuration: Kconfig and Defconfig

U-Boot uses the same Kconfig system as the Linux kernel. Every supported board has a defconfig file under configs/. To start a build for Raspberry Pi 4:

make CROSS_COMPILE=aarch64-linux-gnu- rpi_4_defconfig
make CROSS_COMPILE=aarch64-linux-gnu- menuconfig
make CROSS_COMPILE=aarch64-linux-gnu- -j$(nproc)

The resulting u-boot.bin (or board-specific variant like u-boot-nodtb.bin) is combined with the ARM Trusted Firmware and any required firmware blobs into the final boot image.

Environment and Boot Script

U-Boot's scripting language is deceptively powerful. A well-structured boot script handles fallback scenarios, network boot, and A/B partition selection without any C code changes:

setenv bootcmd '
  if test "${boot_slot}" = "a"; then
    setenv rootdev /dev/mmcblk0p2
  else
    setenv rootdev /dev/mmcblk0p3
  fi
  load mmc 0:1 ${kernel_addr_r} Image
  load mmc 0:1 ${fdt_addr_r} bcm2711-rpi-4-b.dtb
  setenv bootargs "root=${rootdev} rootwait console=ttyS0,115200"
  booti ${kernel_addr_r} - ${fdt_addr_r}
'
saveenv

Store the environment in a dedicated eMMC partition or SPI NOR flash so it survives rootfs updates cleanly.

Reducing Boot Time

Every millisecond in the bootloader is a millisecond your application cannot start. Common optimisations:

  • Disable CONFIG_AUTOBOOT_STOP_STR countdown in production firmware — it adds a fixed delay.
  • Enable CONFIG_SPL_SERIAL_SUPPORT only if you genuinely need SPL console output; removing it shaves time from the secondary program loader phase.
  • Use CONFIG_OF_EMBED to embed a minimal device tree directly in the U-Boot binary, removing one load step.
  • Prefer booti (for ARM64 Image format) over bootm — it skips the legacy uImage header parsing overhead.
  • Disable unused drivers in Kconfig: USB host, PCIe, and full Ethernet stacks all add initialisation time if your boot path does not need them.

Implementing Secure Boot

Secure boot ensures that only signed firmware runs on your device, protecting against firmware tampering and supply-chain attacks. U-Boot supports this through its Verified Boot mechanism, which uses FIT (Flattened Image Tree) images with embedded RSA signatures.

Generate a 4096-bit RSA key pair and embed the public key in U-Boot at compile time:

openssl genrsa -out dev.key 4096
openssl req -batch -new -x509 -key dev.key -out dev.crt

Create a FIT image source (.its) that references your kernel, initrd, and device tree, then sign and pack it:

mkimage -f kernel.its -K u-boot.dtb -k keys/ -r kernel.itb

With CONFIG_FIT_SIGNATURE=y and the public key embedded in U-Boot's device tree, the bootloader will refuse to boot any kernel image whose signature does not verify against that key.

Network Boot for Development

During board bring-up, booting over TFTP eliminates the flash-reflash cycle and dramatically accelerates iteration speed:

setenv ipaddr 192.168.1.100
setenv serverip 192.168.1.1
tftpboot ${kernel_addr_r} Image
tftpboot ${fdt_addr_r} target.dtb
setenv bootargs "root=/dev/nfs nfsroot=192.168.1.1:/export/rootfs rw ip=dhcp"
booti ${kernel_addr_r} - ${fdt_addr_r}

Conclusion

U-Boot is the foundation every embedded Linux stack rests on. Taking the time to understand its configuration system, scripting language, and security features pays dividends in faster boots, safer deployments, and more robust field upgrades. Treat your boot script and environment layout with the same rigour you apply to your application code — it is equally part of your product.

Share

Worksprout Team

The Worksprout engineering team specialises in embedded Linux, RDK-B broadband platforms, edge AI, and robotics systems. Based in Rajshahi, Bangladesh, we design and deploy production embedded intelligence for clients across South Asia and beyond.

Related Posts

Continue reading — handpicked articles you might enjoy