Rockchip Boot Process Explained: BootROM, TPL, SPL, BL31, U-Boot and Linux
A stage-by-stage walkthrough of how a Rockchip SoC boots, where each piece lives on flash, and how to tell from the serial log which stage failed.
Applies to: All Rockchip SoCs
Understanding the boot chain is the fastest way to debug a board that "doesn't boot". Each stage has a job, a location on the boot media, and a characteristic line in the serial log.
The chain at a glance
BootROM (in SoC)
└─► TPL / DDR init ← rkbin DDR blob or open-source TPL
└─► SPL ← U-Boot SPL (or Rockchip miniloader)
└─► BL31 ← Trusted Firmware-A (EL3), optional BL32 OP-TEE
└─► U-Boot proper
└─► Linux kernel + DTB (+ initramfs)
└─► rootfs / Android
1. BootROM
Mask-programmed into the SoC. It probes boot devices in a fixed order (typically SPI flash, then eMMC, then SD; exact order is SoC-specific), looking for a valid ID block at sector 64. If it finds nothing, it enters MaskROM mode on USB.
2. TPL: DDR initialisation
The BootROM loads the first stage into the SoC's internal SRAM, which is only a few hundred KB. Its only job is to train and initialise DRAM. On newer SoCs (RK3568, RK3588, RK3576) this is a closed binary from rkbin, e.g. rk3588_ddr_lp4_2112MHz_lp5_2400MHz_v1.xx.bin. On RK3399 and some older SoCs, mainline U-Boot has an open-source TPL.
Serial log clue: DDR type, frequency and size, e.g. DDR ... LPDDR4X, 2112MHz ... 8GB.
3. SPL
With DRAM up, SPL loads the next stages from boot media: BL31, optional OP-TEE, and U-Boot proper, usually packed as a FIT image (u-boot.itb).
Serial log clue: U-Boot SPL 20xx.xx ... Trying to boot from MMC1.
4. BL31 (TF-A) and OP-TEE
Trusted Firmware-A runs at EL3 and provides PSCI (CPU on/off, suspend) and secure monitor services. Linux cannot bring up secondary CPUs without it. OP-TEE (BL32) is optional and used for secure-world services.
Serial log clue: INFO: Preloader serial: 2, NOTICE: BL31: v2.x.
5. U-Boot proper
Initialises more hardware (display, USB, network if enabled) and finds the kernel. Mainline Rockchip boards typically use distro boot / bootstd: they look for extlinux/extlinux.conf or boot.scr on each device. Android builds use the vendor U-Boot and Android boot images.
6. Linux
U-Boot loads the kernel Image, the DTB (and overlays) and optionally an initramfs, then jumps to the kernel. From here, failures are kernel-side: wrong DTB, missing storage driver, bad root= argument.
Where it all lives on flash
| Sector (512 B) | Offset | Content |
|---|---|---|
| 0 | 0 | GPT (partition table) |
| 64 | 32 KB | idbloader.img (TPL + SPL) |
| 16384 | 8 MB | u-boot.itb (U-Boot + BL31 + optional OP-TEE) |
| 32768 | 16 MB | boot partition (kernel, DTB, extlinux) |
Mainline U-Boot also produces a single u-boot-rockchip.bin that combines idbloader and u-boot.itb for writing at sector 64:
sudo dd if=u-boot-rockchip.bin of=/dev/sdX seek=64 conv=notrunc,fsync
Reading a failed boot
- Nothing on UART, board shows up as MaskROM on USB: no valid loader found. Reflash idbloader.
- Stops after DDR lines: SPL cannot find or load u-boot.itb, or DDR is unstable (wrong blob for your memory type).
- Stops after "NOTICE: BL31": U-Boot proper crashed, often a DTB mismatch in U-Boot.
- "Starting kernel ..." then silence: wrong console settings (
console=ttyS2,1500000on many SoCs), wrong DTB, orearlyconneeded to see more.
The debug UART on most modern Rockchip SoCs runs at 1,500,000 baud. Use a USB-UART adapter that supports it (CP2102N, CH343, FT232H).
Spotted an error or have something to add? Suggest an improvement.