Understanding Bootloader: How U-Boot Boots Linux in One Article

“From powering on to logging into the shell, every power button you press is accompanied by a Bootloader ritual happening behind the scenes.”

Understanding: How U-Boot Boots Linux?

When you press the power button on an embedded device, from that moment on, the SoC undergoes a complete and complex boot process: ROM → Bootloader → Linux Kernel → Rootfs → User Space.

At the core of all this is the Bootloader — U-Boot.

If you have ever trimmed, ported, or customized device booting, you must have experienced:

  • Tweaking the boot order

  • DDR initialization failures

  • Kernel not starting

  • Stalling after printing “Starting kernel …”

  • Incorrect device tree

  • Incorrect initrd

  • Incorrect addresses

  • A single typo in the boot command can cause a hang

In this article, we will thoroughly explain: How U-Boot boots Linux step by step?

Table of Contents

  1. What is a Bootloader?

  2. Why has U-Boot become the industry standard?

  3. U-Boot Two-Stage Architecture: What do SPL / TPL do?

  4. Complete Flowchart of U-Boot Booting Linux

  5. How U-Boot prepares the “three essentials” for the Kernel

  6. Differences between boot commands “bootm”, “bootz”, and “booti”

  7. Common boot issues and troubleshooting techniques

  8. Conclusion: Understanding U-Boot booting means understanding half of embedded systems

1️⃣ What is a Bootloader?

In one sentence:

A Bootloader is the “system” before the system starts.

When you press the power button, the CPU fetches the first instruction from a predefined address, and this instruction cannot be Linux (because Linux is too large to fit in ROM).

Therefore, a “small program” must first run to complete the basic hardware initialization and ultimately hand over control to the Linux Kernel.

Bootloader = System Boot Manager + Kernel Mover + Hardware Initialization Engineer.

2️⃣ Why has U-Boot become the industry standard?

Because it has:

  • Support for almost all mainstream architectures (ARM/MIPS/RISC-V/x86…)

  • Powerful command line and interactive capabilities

  • Rich drivers (network/storage/serial/USB/SPI Flash)

  • Support for device trees

  • Support for FOTA (real OTA upgrades)

  • Strong customization capabilities

  • Unlimited customization

In one sentence: Whatever you want to do, U-Boot can basically do it.

3️⃣ U-Boot Two-Stage Architecture: What do SPL / TPL do?

As the complexity of modern SoCs increases, the Bootloader itself is divided into two to three stages:

① TPL (Tiny Program Loader)

Responsible for minimal initialization, such as:

  • Powering on the CPU power domain

  • Power-on sequence

  • Timing configuration required before DRAM initialization

  • Running in SRAM

② SPL (Secondary Program Loader)

When DRAM is not initialized, U-Boot successfully completes its most important task:

Initializing DRAM so that the next step of U-Boot can run in DRAM!

③ U-Boot Official Version (u-boot.bin)

Responsible for:

  • NAND/NOR/EMMC/SD drivers

  • Parsing environment variables

  • Loading Kernel / DTB / initramfs

  • Network boot (tftpboot, nfs)

  • Booting the system

So the structure is as follows:

ROM → TPL → SPL → U-Boot → Linux

4️⃣ Complete Flowchart of U-Boot Booting Linux

Below is the most classic and core process (widely recognized in the industry):

1. Power on → CPU reset → ROM Code execution
2. ROM loads SPL/TPL to SRAM
3. SPL initializes minimal hardware (especially DRAM)
4. SPL loads U-Boot official version to DRAM
5. U-Boot official version runs, initializing peripherals (serial, network, storage)
6. Parsing environment variables, selecting boot method (normal / OTA / recovery)
7. Loading kernel image (Image/zImage/uImage) into memory
8. Loading device tree (dtb) to specified address
9. Optional: Loading initramfs
10. Constructing "boot parameters structure" required by the Kernel
11. Calling boot command (bootm/bootz/booti)
12. Jumping to kernel entry (start_kernel)
13. Linux takes over the system

The most important step in this process is:

Putting the Kernel, DTB, and initramfs all in their correct memory addresses!

If the addresses are even slightly wrong, the kernel will not start.

5️⃣ U-Boot Needs to Prepare the “Three Essentials” for Linux Boot

📌 (1) Kernel Image

Common formats:

  • <span>zImage</span> (ARM)

  • <span>Image</span> (ARM64)

  • <span>uImage</span> (U-Boot legacy format)

  • <span>vmlinuz</span> (x86)

U-Boot is only responsible for moving, not for understanding the content.

📌 (2) DTB (Device Tree)

Includes:

  • Interrupts

  • Memory

  • CPU

  • Device addresses

  • Driver binding information

Without a device tree, the kernel does not know what the world looks like.

📌 (3) initramfs (optional)

Some systems (e.g., initrd boot) require it:

  • File system

  • init script

  • Modules

  • Initial boot environment for the root file system

6️⃣ Boot Commands: What are the Differences between bootm / bootz / booti?

This is a part that many engineers often confuse:

Command Applicable Image Scenario
bootm <span>uImage</span> Old format image
bootz <span>zImage</span> Commonly used in ARM32
booti <span>Image</span> (ARM64) Mainstream boot command for ARM64 Linux

For example:

booti ${kernel_addr} - ${fdt_addr}
bootz 80000 - 82000
bootm 0x20000000 0x21000000 0x22000000

If the addresses are wrong, it will directly report:

Bad Linux ARM64 Image magic!
Kernel image corrupted?!

7️⃣ Common Boot Failure Troubleshooting Techniques (Practical Experience)

These are the pitfalls you will encounter 90% of the time in actual work:

① Stuck at “Starting kernel …”

Must check:

  • <span>console=</span> parameter is passed correctly

  • Is UART defined correctly in the device tree?

  • Are the addresses aligned?

  • Is the kernel entry address correct?

  • Is the MMU incorrectly enabled?

② Device Tree Loading Error

U-Boot reports:

ERROR: fdt checksum mismatch

This indicates that the dtb is corrupted or the address is wrong.

③ Kernel Address Overlap

Common issue:

kernel_addr = 0x80000
fdt_addr = 0x81000
initrd_addr = 0x82000

This can easily lead to overlaps, causing random crashes.

④ DDR Not Initialized Correctly

Symptoms:

  • Random boot failures

  • Boot crashes during kernel decompression

  • Inherent offsets are unstable

Recommendation: Do more DRAM training in SPL.

⑤ Root File System Cannot Be Mounted

Error:

VFS: Unable to mount root fs

Troubleshooting order:

  1. Kernel command line

  2. Does initramfs exist?

  3. Are device nodes created?

  4. Storage controller configuration in the device tree

8️⃣ Conclusion: Understanding U-Boot Booting Means Understanding Half of Embedded Systems

The essence of U-Boot is:

  • Initializing DRAM correctly

  • Placing the kernel, DTB, and initramfs at the correct addresses

  • Preparing parameters for the kernel

  • Jumping to the kernel entry

  • Handing over control to Linux

As long as you fully understand the bridging process from Bootloader to Kernel, you will be able to:

  • Customize your own boot system

  • Port Linux to new hardware

  • Troubleshoot most boot failures

  • Optimize boot time

  • Implement secure boot and OTA

You will truly open the door to the world of embedded systems.

#Embedded Panorama Series #Linux Kernel Architecture #Performance Optimization Practice

If you want to continue reading this series

The next article will be:

👉 Embedded Systems Panorama: In-Depth Analysis of Linux Kernel Boot Mechanism

Leave a Comment