$ dmesg | grep -i boot
Hardware
What is it?
A cheat sheet on what an Arm SoC does between power-on and the operating system. First topic: the Arm Trusted Firmware-A (TF-A) secure boot chain, BL1 → BL2 → BL31 / BL32 → BL33, the exception levels and memory regions each stage uses, and where a verification failure stops everything.
// power-on → chain of trust
Anatomy of a secure boot
A walkthrough of a secure boot on an Arm application processor, following the Arm Trusted Firmware-A (TF-A) cold boot: the chain of trust from the reset vector in Trusted ROM, through BL1 and BL2, into the EL3 runtime (BL31), the optional secure payload (BL32) and the non-trusted firmware (BL33) that finally boots the OS in DRAM. Here BL means Boot Loader stage, so BL1 is stage 1, BL2 is stage 2, and BL31, BL32 and BL33 are the three parts of stage 3. The number in the name already tells you the stage, which is why the boxes below only carry the memory and exception-level detail.
Step by step
- 0
Always-on hardware (level 0). Some silicon is present and powered the whole time rather than being a step in the sequence: the CPU and its caches execute whatever the current stage points them at, immutable Trusted ROM holds the very first code, and on-chip Trusted SRAM is where the writable stages (BL1's data, then BL2, then BL31 and BL32) are copied and run. That is why they carry no step number and are tagged as level 0.
- 1
Reset. The primary CPU is released from reset. Its registers are reset to known values and the program counter is set to the reset vector, a fixed address that points into Trusted ROM. On a multicore SoC the other cores are held in a safe state until the primary has done enough setup to bring them up (later handled by PSCI in BL31).
- 2
BL1, Application Processor Trusted ROM (EL3). The application processor is the main CPU cluster that will eventually run the OS (as opposed to a separate System Control Processor that some SoCs use for power and clocks). Immutable code in its Trusted ROM runs first at EL3. It installs exception vectors and runs the CPU reset handler, then brings up the platform: raise the clock/PLL to full speed, enable the Trusted Watchdog (which resets the SoC if boot ever hangs in a loop), set up the console, enable interconnect coherency and the MMU, and configure the flash it loads from. It reads a root-key hash from OTP/eFuses, uses the crypto engine to verify the BL2 image, copies it into Trusted SRAM and hands control to BL2 at Secure-EL1.
- 3
BL2, Trusted Boot Firmware (Secure-EL1). BL2 runs from Trusted SRAM and does the platform security setup, including programming the TrustZone controller (TZC) that splits DRAM and peripherals into secure and non-secure regions. It then loads the later stages (the BL3x images) from the Firmware Image Package (FIP) in flash, verifying each against the same root of trust: the EL3 runtime (BL31), the optional secure payload (BL32) and the non-trusted firmware (BL33). BL2 raises an SMC so BL1 turns off the MMU, flushes caches and jumps to BL31 at EL3.
- 4
BL31, EL3 Runtime Software (EL3). BL31 is the resident EL3 runtime; it never exits. It re-initialises the architecture, sets up the generic interrupt controller (GIC), initialises PSCI power management (secondary-CPU boot, hotplug, idle) and registers the runtime services that the normal world calls into later through the SMC (Secure Monitor Call) instruction. It stays in Trusted SRAM for the life of the system.
- 5
BL32, Secure-EL1 Payload (Secure-EL1, optional). If present, BL32 is the Trusted OS (or other secure payload) running in the secure world at Secure-EL1. BL31 initialises it through a Secure-EL1 Payload Dispatcher (SPD) and routes secure/normal world switches to it over SMCs. It is optional; on AArch32 there is no BL31, and BL32 (for example SP_MIN) plays the EL3 runtime role instead.
- 6
BL33, Non-trusted Firmware (EL2/EL1). BL31 sets up the normal-world context and jumps to BL33 at the highest non-secure exception level (EL2 if available, otherwise EL1). BL33 is normal-world firmware such as UEFI or U-Boot, running from non-secure DRAM. It is the first non-secure code to run, and it goes on to boot the operating system.
Two connections worth calling out
- Debug port (JTAG/SWD) wires into the CPU's own debug access port, independent of the boot code. On a production secure part it is disabled by a fuse or gated behind an authenticated debug challenge, because otherwise it would bypass the entire chain of trust.
- Boot straps and the reset vector a handful of pins latched once at reset (together with the PROGRAMMABLE_RESET_ADDRESS option) decide where the primary CPU starts and which image BL1 loads. It is a one-time hardware input, not something software chooses.
Note: this is one representative TF-A cold boot on AArch64; details vary by platform. BL32 is optional, and on AArch32 the five stages collapse to four (there is no BL31, and BL32 such as SP_MIN plays the EL3 runtime role). Exactly when the clock, watchdog, crypto engine and TrustZone controller are programmed is platform-specific; they are shown at one plausible point in the BL1 / BL2 flow, not as a fixed hardware sequence.