$ dmesg | grep -i boot
Hardware
What is it?
A cheat sheet on what a chip does between power-on and the OS: the TF-A secure boot chain on Arm, the hardware it relies on and how common chips compare, how PCs do the same with BIOS and UEFI, how the kernel boots, and how secure boot differs from measured boot.
// power-on --> chain of trust
Anatomy of a secure boot
The Trusted Firmware-A (TF-A) cold boot, from the reset vector in ROM to the OS: BL1 verifies BL2, then BL2 verifies every BL3x image. BL stands for Boot Loader stage.
Step by step
- 0
Always-on hardware. The CPU, Trusted ROM and on-chip Trusted SRAM are not steps: ROM holds the first code, and SRAM is where BL1's data, BL2 and BL31 run.
- 1
Reset. The primary core leaves reset at the reset vector in Trusted ROM; the other cores wait until the OS starts them through BL31 (PSCI CPU_ON).
- 2
BL1, Trusted ROM (EL3). Immutable code sets up the exception vectors, the watchdog, the console and the MMU, copies BL2 into Trusted SRAM, then verifies that copy against the root-key hash in OTP, in software or with a crypto engine. Checking the copy, not the flash, ensures the verified bytes are the ones that run. With measured boot it also hashes BL2 into the TPM; BL1 is the root of trust for measurement, so nothing measures BL1 itself.
- 3
BL2, Trusted Boot Firmware (Secure-EL1 or EL3). Initialises DRAM on most real SoCs, programs the TrustZone controller to split memory and peripherals into secure and non-secure, then loads and verifies BL31, BL32 and BL33 from the Firmware Image Package (FIP) in flash. It runs at EL3 when a vendor boot ROM loads it directly, as on the vendor chips below. With measured boot it also measures each image it loads and passes the event log on to BL33 and the OS.
- 4
BL31, EL3 runtime. The resident secure monitor: sets up the interrupt controller and PSCI power management, and handles Secure Monitor Calls (SMC) from the normal world for the life of the system.
- 5
BL32, Trusted OS (Secure-EL1, optional). A Trusted OS such as OP-TEE, reached through BL31 and usually running in secure DRAM. On AArch32 there is no BL31 and BL32 is also the monitor.
- 6
BL33, Non-trusted firmware (EL2/EL1). The first non-secure code, usually U-Boot or UEFI, running from DRAM; it boots the OS. TF-A's chain of trust ends here: BL33 must verify the kernel itself (signed FIT images or UEFI Secure Boot).
Details vary by platform. In hardware, the chain can still be bypassed through an open JTAG/SWD debug port, unprogrammed secure-boot fuses, or bugs in the ROM's USB/UART download modes, which boot-strap pins can select (as in Fusée Gelée). Fault injection is behind most of the breaks in the table below.
// under the microscope
Secure boot hardware on real dies
Neither chip runs TF-A, but their delayered dies show the blocks a boot relies on: boot ROM, OTP fuses and SRAM on the RP2350, flash and SRAM on the STM32L431.

// who verifies what
Common chips compared
| Chip | Used in | CPU | Boot ROM verifies | Root key in | TrustZone | TF-A | Public break |
|---|---|---|---|---|---|---|---|
| Arm Juno / FVPJuno key storage, TF-A build options | Arm's reference development board, FVP software model | Cortex-A72 or A57 (+ A53) | No vendor ROM: TF-A BL1 (in flash) verifies BL2, RSA or ECDSA | Read-only registers (fixed key hash; no OTP) | Yes | BL1, BL2, BL31 (full chain) | none |
| ST STM32MP25ST wiki, TF-A | Digi ConnectCore MP25 industrial edge-AI module | Cortex-A35 (+ M33) | TF-A BL2, ECDSA (P-256 / Brainpool) | OTP (key-table hash) | Yes | BL2, BL31 | none |
| Renesas R-Car Gen3Renesas, TF-A | Toyota / Lexus multimedia (Lexus NX, 2021), Parrot Faurecia cockpit | Cortex-A57 and/or A53 (+ R7) | TF-A BL2, RSA certificates | Fuses (customer's root-key hash, programmed by Renesas) | Yes | BL2, BL31 | none |
| NXP Layerscape LX2160ATF-A, TF-A secure boot | SolidRun HoneyComb LX2 Arm workstation | 16× Cortex-A72 | TF-A BL2, RSA (CSF header) | Fuses (SRK hash) | Yes | BL2, BL31 | none |
| ST STM32MP15ST wiki, TF-A | Kontron industrial / IoT module, Seeed ODYSSEY module | Cortex-A7 (+ M4) | TF-A BL2, ECDSA (P-256 / Brainpool) | OTP (key hash) | Yes | BL2 | none |
| NXP i.MX 8MU-Boot HABv4, TF-A | Google Coral Dev Board, Purism Librem 5 phone | Cortex-A53 (+ M4 or M7) | U-Boot SPL, RSA (HABv4) | eFuses (SRK hash) | Yes | BL31 | none |
| NVIDIA Tegra X1NVIDIA, 34C3 talk, TF-A commit | Nintendo Switch (own secure monitor, not TF-A), NVIDIA Shield TV (2015, 2017), Jetson Nano | Cortex-A57 (+ A53) | BCT + bootloader, RSA or AES-CMAC; ROM runs on an ARM7 boot CPU | Fuses (RSA key hash, or AES Secure Boot Key) | Yes | BL31 (upstream port deprecated in 2026) | Fusée Gelée (2018): USB bug in the boot ROM, unpatchable on shipped chips |
| Raspberry Pi 5 (BCM2712)Pi secure boot, TF-A | Raspberry Pi 5, Pi 500, Compute Module 5 | Cortex-A76 | Bootloader, RSA-2048, signed by Raspberry Pi and counter-signed by the customer | OTP (customer key hash) | In the cores, but no secure memory controller | Minimal BL31, not secure | none |
| Raspberry Pi RP2350Pi white paper | Raspberry Pi Pico 2 | Cortex-M33 (+ Hazard3 RISC-V) | Signed image, ECDSA secp256k1 + SHA-256 | OTP (key hash) | TrustZone-M | None | OTP power glitch (Aedan Cullen); voltage and laser fault injection; FIB readout of the OTP (IOActive) |
| ST STM32L431X-CUBE-SBSFU | Hermetis LoRa air-quality sensor, Andrew Zonenberg's lab hardware | Cortex-M4 | Nothing; ST's X-CUBE-SBSFU adds a software secure boot in flash | none | No | None | none |
| Espressif ESP32Espressif | Shelly Plus 1 smart relay | Xtensa LX6 (not Arm) | Bootloader, AES-based digest (Secure Boot v1); v3 silicon adds RSA-3072 (Secure Boot v2) | eFuses (AES key for v1, RSA key hash for v2) | No | None | Fault injection skips the Secure Boot check (CVE-2019-15894); Voltage glitching read the eFuse keys (2019); CVE-2019-17391 advisory; One EM glitch via the ROM's UART download mode (Raelize, CVE-2020-13629) |
Entries link to their sources; technical columns are sourced under each chip name. “Used in” lists examples; “none” means none known or not applicable.
// BL33 --> firmware you know
BIOS and UEFI
TF-A's chain ends at BL33, which is often a UEFI firmware: the same interface a PC uses to boot. A PC has no TF-A. Intel Boot Guard or AMD's Platform Secure Boot plays the boot ROM's role, and the UEFI firmware itself does BL2's job. Before UEFI, PCs booted with a BIOS, which verified nothing.
The x86 root of trust
Before any PC firmware runs, something the OEM cannot change checks it. Intel spreads the check over signed manifests; AMD gives it to a separate security processor. Both are the same idea as BL1 checking BL2 against a key hash in OTP.
UEFI in six phases
- SEC
Security. Handles every reset, sets up temporary memory (the CPU cache used as RAM) and is the root of trust of the firmware.
- PEI
Pre-EFI Initialization. Small modules initialise permanent memory (DRAM) and describe it in Hand-Off Blocks for the next phase.
- DXE
Driver Execution Environment. Most of the work: drivers for the chipset, buses, consoles and disks, and the Boot and Runtime Services.
- BDS
Boot Device Selection. Applies the boot policy: reads the BootOrder variables and tries each boot option in turn.
- TSL
Transient System Load. The OS loader runs as an EFI application, still using the Boot Services.
- RT
Runtime. Once the OS takes over, only the Runtime Services remain: variables, clock, capsule firmware updates.
On an Arm board, TF-A has already done the reset and DRAM work, and EDK2 starts as BL33. Embedded boards often run U-Boot instead, which implements the subset of UEFI that Arm's EBBR requires. Secure Boot is optional there. Source: TianoCore PI boot flow, UEFI on U-Boot.
Legacy BIOS vs UEFI
| Legacy BIOS | UEFI | |
|---|---|---|
| CPU mode at hand-off | 16-bit real mode, 1 MiB of addressable memory | 32- or 64-bit mode (AArch64 on Arm), flat memory |
| Finds the OS by | Loading sector 0 of the boot disk (the MBR) at 0x7C00 and jumping to it | Running the PE/COFF .efi file named by the BootOrder variables, from a FAT EFI System Partition |
| Disk layout | MBR: 4 primary partitions, 32-bit sector numbers, so 2 TiB with 512-byte sectors | GPT, with 64-bit sector numbers (MBR still allowed) |
| Services to the OS | Real-mode interrupts: INT 13h for disks, INT 10h for video | Boot Services until the OS takes over, then Runtime Services |
| Verifies the loader | No | Yes, with Secure Boot: db, dbx, KEK, PK |
| Hardware root of trust | None in the design | Intel Boot Guard or AMD Platform Secure Boot, if the OEM fuses them |
Sources: MBR (x86), Windows and GPT FAQ, EFI boot stub, PI boot flow.
Secure Boot keys
UEFI Secure Boot continues the chain past the firmware: four key databases decide which OS loader may run.
- PK Platform Key
- The platform owner's key, usually the OEM's. Only it can change the KEK. Enrolling a PK moves the firmware from setup mode, where Secure Boot is off, to user mode.
- KEK Key Exchange Keys
- Keys of OS vendors, such as Microsoft's KEK CA. They sign updates to db and dbx.
- db Allowed signatures
- Certificates and hashes of allowed images. PCs ship Microsoft's Windows CA, and its UEFI CA for third-party loaders such as shim.
- dbx Forbidden signatures
- Revoked certificates and hashes, checked before db: a match blocks the image.
Microsoft's 2011 certificates start expiring in June 2026: PCs need the 2023 CAs to keep receiving db and dbx updates. Source: Secure Boot key guidance.
Public Secure Boot breaks
- BootHole (2020): A buffer overflow in GRUB's parser for grub.cfg, a file nobody signs, ran attacker code with Secure Boot on (CVE-2020-10713).
- BlackLotus (2023): The first bootkit seen in the wild to bypass Secure Boot on fully patched Windows 11, by bringing old, validly signed but vulnerable boot managers that dbx did not yet block (CVE-2022-21894).
- LogoFAIL (2023): Bugs in the image parsers that draw the boot logo during DXE let a crafted logo run code inside the firmware, on x86 and Arm devices.
- PKfail (2024): Hundreds of PC models shipped AMI's test Platform Key, marked "DO NOT TRUST"; one such private key leaked, so anyone holding it could rewrite KEK and db.
// firmware --> kernel --> init
From the loader to the kernel
Arm and PC boots meet here: BL33 or the UEFI firmware hands over to an OS loader, which starts the kernel.
Kernel boot, step by step
- 7
OS loader (EFI application). BL33, or the PC's UEFI firmware, runs an EFI application from the FAT EFI System Partition: shim and GRUB, systemd-boot or the Windows Boot Manager. With Secure Boot on, the firmware checks it against db and dbx first. It loads the kernel, an initramfs and the command line. Linux can skip this stage: with the EFI stub, the kernel image is itself a PE/COFF EFI application. U-Boot can also boot the kernel directly from a signed FIT image.
- 8
Kernel entry. The loader also passes a description of the hardware: a devicetree on embedded boards, ACPI tables on PCs and Arm servers. On arm64 the kernel starts with the MMU off, the devicetree address in register x0, in non-secure EL2 (recommended, for virtualisation) or EL1. It builds its page tables, turns the MMU on, sets up memory, interrupts and the scheduler, and starts the other cores, on Arm through PSCI calls to BL31.
- 9
initramfs, then init. The kernel unpacks the initramfs, a cpio archive, into a RAM filesystem and runs its /init as PID 1. This early userspace finds the real root filesystem, possibly unlocking it with a TPM-sealed key or checking it with dm-verity, then switches to it and runs the real init, usually systemd.
Numbers continue the TF-A steps 0 to 6. Sources: Booting AArch64 Linux, EFI boot stub, initramfs.
Linux under Secure Boot
Microsoft signs shim, a small first-stage loader, with its UEFI CA. shim carries the distribution's certificate and checks GRUB and the kernel against it, or against a Machine Owner Key (MOK) that the user enrolls. GRUB's config file is not signed, which is what BootHole exploited. Since then, shim checks SBAT generation numbers in signed metadata, so a vulnerable version can be revoked by number instead of filling dbx with hashes. With kernel lockdown on, which distributions usually enable under Secure Boot, the kernel loads only signed modules and also refuses /dev/mem, kexec of unsigned kernels and unencrypted hibernation.
// verify vs record
Secure boot vs measured boot
Two mechanisms run along the whole chain, from the root of trust to the kernel, on Arm and PCs alike. Secure boot (then trusted boot, in Windows terms) verifies each stage and stops on a bad signature. Measured boot hashes each stage into a TPM and never blocks, so a key store or a remote server can tell what actually ran.
| Secure + trusted boot | Measured boot | |
|---|---|---|
| Does | verifies a signature | hashes the image, extends a PCR |
| On mismatch | halts or recovers | boots on, the PCR differs |
| Answers | may this code run? | what code did run? |
| Trust anchor | key hash in OTP or ROM | immutable ROM + TPM |
| Used for | blocking unsigned code | key release, attestation |
Naming. Windows splits verification in two: secure boot (UEFI checks the OS loader) and “trusted boot” (the OS loader checks the kernel, drivers and ELAM). TF-A’s “Trusted Board Boot” is the firmware half. Measured boot is separate: it records and never verifies, though some documents (Intel’s tboot) also call it “trusted boot”. TF-A builds both with TRUSTED_BOARD_BOOT=1 and MEASURED_BOOT=1. Sources: TF-A Measured Boot design, Windows boot process.