U-Boot/Boot process

From linux-sunxi.org
Jump to navigation Jump to search

This page aims to give an overview of the code that runs when mainline U-Boot gets started on an Allwinner SoC. It helps to understand the boot flow, add support for new SoCs, find the right places to add new code, or to add debug output in case it hangs early.

For now this focuses on 64-bit SoCs, which use a slightly different boot flow from 32-bit SoCs.

General overview

Mainline U-Boot for Allwinner SoCs consists of two parts: the SPL ("secondary program loader", as opposed to the primary loader, which is the BootROM), and the main U-Boot part, called "U-Boot proper".

The reason for this split is that the BootROM can only load code into the small SRAM memories on the chip, and this in not nearly enough to hold a full U-Boot image. So the SPL's main task is to initialise the DRAM, then load U-Boot proper into there, since this has plenty of space. On top of loading the remaining U-Boot code, the SPL can also load other components, namely the DTB, the secure runtime firmware (TF-A), and potentially a management processor firmware like crust.

Conceptually the SPL uses the same code as the rest of the U-Boot, but its image is more selectively compiled, and with different configuration options to drastically limit the image size. This means it just contains the drivers it will need for loading the other images, and those drivers are potentially compiled in a cut-down or restricted version, to keep the image size down.

AArch64 boot flow

crossed out lines show generic code that is never used by sunxi

arch/arm/cpu/armv8/start.S
#include <boot.h> (arch/arm/include/asm/arch-sunxi/boot0.h)
32/64 bit deflector (0xea00001f: tst x0, x0 vs. b #0x84)
AArch32 (SPL initially) AArch64 (U-Boot proper)
save FEL state branch to reset: label (below)
load RVBAR registers with start address
do RMR to switch to 64-bit, start at reset:
(embedded image information data, branched over)
reset: b save_boot_params (no bl here, to avoid clobbering LR)
save_boot_params: b save_boot_params_ret (returns immediately, not used for sunxi)
PIE relocation not used by sunxi
load exception vector address (only U-Boot proper)
determine current exception level
EL3 (SPL) EL2 (proper) EL1 (not used)
(set VBAR_EL3) Route SErrors to EL2 set VBAR_EL1
mask interrupts, set NS bit set VBAR_EL2 Enable FP/SIMD
enable FP/SIMD for EL2 Enable FP/SIMD for EL1
Unmask SError interrupts
initialise CNTFRQ (SPL/EL3 only)
set CPUECTLR_EL1.SMPEN bit
apply ARM core specific erratas
b lowlevel_init
initialise GIC on primary core
intialise GIC on secondary cores
install spin table, catch secondary cores
force use of SP_ELx
b _main (in arch/arm/lib/crt0_64.S)
arch/arm/lib/crt0_64.S
set up initial stack pointer (from CONFIG_SPL_STACK)
call board_init_f_alloc_reserve (in common/init/board_init.c)
subtract early malloc area (SYS_MALLOC_F_LEN == 8KB)
subtract space for global_data (~416 bytes)
re-set stack pointer to grow down from here
set up gd_ptr (in fixed register x18) to use space up from here
call board_init_f_init_reserve (in common/init/board_init.c)
clear global_data struct
set malloc base to point right behind global_data
call debug_uart_init (unusable on sunxi)
call board_init_f in ...
SPL: arch/arm/mach-sunxi/board.c U-Boot proper: common/board_f.c
sunxi SPL specific initialisation (see below) call every function in init_sequence_f[] array
SPL U-Boot proper
call spl_relocate_stack_gd() switch to final stack and GD location
relocate image (to end of DRAM)
call c_runtime_cpu_setup()
clear BSS
branch to board_init_r() in ...
SPL: common/spl/spl.c U-Boot proper: common/board_r.c