-
Notifications
You must be signed in to change notification settings - Fork 6
RockPro64 boot sequence
This attempts to describe the boot flow using open-source U-Boot and ARM Trusted Firmware only - the boot flow using Rockchip's binary blobs is different, but won't be covered here.
On the RockPro64, when powered on, the RK3399's Boot ROM will look for code with an ID block header in the following locations, in order, and attempt to load and execute the code from the first location found with the correct ID block header:
- At offset 0 bytes in SPI flash
- At offset 0x8000 bytes (64 sectors, a sector is 0x200 bytes) on eMMC
- At offset 0x8000 bytes (64 sectors, a sector is 0x200 bytes) on an SD card
This is the only search order which isn't customisable, as it's hard-coded in the boot ROM. If none of these contain code with the correct ID block header, the boot ROM will go into Maskrom mode where it waits for a connection over USB.
This means, for U-Boot, the idbloader.img containing the U-Boot TPL & SPL code with the ID block header must be in one of these locations. With SPI Flash, there's an additional caveat that the code must be "spread" over the first 2KB of each 4KB block, with the second 2KB of each block unused (this is known as the "rkspi" format in U-Boot's mkimage tool).
The first executable code from U-Boot to be loaded is the TPL (Tertiary Program Loader), this is a small program which has to fit in the CPU's internal SRAM only since the main RAM is not yet initialised. It initialises the LPDDR4 RAM and then returns control to the Boot ROM. When building mainline U-Boot, this is contained in the first part of the built idbloader.img file.
After the TPL returns control to the Boot ROM, the boot ROM loads and executes the U-Boot SPL. When building mainline U-Boot, this is contained in the second part of the built idbloader.img file.
At this point, the Boot ROM's job is finished. The job of the SPL is mainly to figure out where to load U-Boot proper and ARM Trusted Firmware from (these are packaged together in the u-boot.itb file), load them, execute ATF then U-Boot proper. The SPL looks at a value passed from the Boot ROM to figure out which device it was booted from, then tries to load the contents of u-boot.itb from the same device - this is set up by the "u-boot,spl-boot-order" value in arch/arm/dts/rk3399-rockpro64-u-boot.dtsi in the U-Boot source. The location that the SPL searches for u-boot.itb at is configurable at U-Boot build time - the default locations for these builds are:
- For SPI flash, 0x60000 bytes - this is set by configuring CONFIG_SYS_SPI_U_BOOT_OFFS, set to a location slightly after the end of the TPL & SPL in SPI flash.
- For eMMC and SD cards, 0x800000 bytes (16384 sectors), this is the default value for CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR.
The job of this firmware is to set up some security features of the ARM CPU and then pass control to U-Boot proper. However ATF is still present during further boot stages, and can be called by Linux, for example, using the PSCI interface to suspend or reboot the system.
This is the main U-Boot program, its job is to read the U-Boot environment from SPI Flash or eMMC/SD (depending on the build), scan devices for bootable files, load the operating system kernel and start it. This is where support for additional boot devices is added, e.g. support for USB, NVMe, SATA and network boot.
The location U-Boot tries to load the environment from is set at U-Boot build time. The SPI builds in this repository are configured to load environment from SPI Flash, the MMC builds are configured to load it from eMMC.
By default it scans each supported boot device (listed in the boot_targets variable) for an extlinux config file, a U-Boot script, or an EFI boot executable. The order of preference among devices can be changed by changing the boot_targets variable and then saving that to the U-Boot environment in SPI flash or on eMMC.