Trusted Firmware-A (TF-A) is Arm's open source reference secure world firmware for application processors. It boots a system in stages named BL1, BL2, BL31, BL32 and BL33, verifies each image against a key rooted in the chip, then stays at Exception Level 3 as the secure monitor that switches worlds and handles OS power calls.
If you have booted a modern Arm server, a development board, an Arm laptop or many Android and embedded devices, some form of TF-A very likely ran before your bootloader did. This guide goes one level deeper than our posts on coreboot and on the difference between secure, trusted and measured boot. We read the TF-A documentation (built from the tree after the v2.15.0 release), its firmware design, Trusted Board Boot, authentication framework, measured boot, build options, QEMU platform, release, LTS and security handling chapters, the trustedfirmware.org project pages, the OP-TEE documentation, the Linux kernel PSCI binding, the EBBR specification and NIST SP 800-193. Every stage name, build flag and command below comes from those sources. Arm's own PSCI and SMC Calling Convention specifications block scripted downloads, so where we describe them we rely on how the TF-A and Linux documentation quote them.
Key takeaways
- TF-A is not a bootloader for your OS. It is the trusted boot firmware plus a small runtime that stays at EL3 forever. Your OS bootloader (UEFI, U-Boot or a Linux kernel) runs later as BL33, in the normal world.
- On AArch64 a TF-A cold boot runs five steps in order: BL1 (AP Trusted ROM), BL2 (Trusted Boot Firmware), BL31 (EL3 Runtime Software), the optional BL32 (Secure-EL1 Payload, for example OP-TEE) and BL33 (Non-trusted Firmware).
- Trusted Board Boot authenticates every image up to and including BL33 using X.509 v3 certificates whose custom extensions carry public keys and image hashes. The trust anchor is a Root of Trust Public Key (ROTPK), or its hash, held in the chip, plus BL1 in ROM.
- The images and their certificates travel together in a Firmware Image Package (FIP): a table of contents followed by payloads, each identified by a UUID.
fiptoolcreates and inspects it, andcert_createbuilds the certificates. - PSCI is how your OS starts secondary CPUs, idles, suspends, resets and powers off. It reaches BL31 through the SMC instruction under the SMC Calling Convention.
- Measured boot in TF-A records hashes of images and critical data into a TCG event log, and can extend them into a discrete TPM or the Runtime Security Engine (RSE). BL1 is the root of trust for measurement and is not itself measured.
- Security fixes are published as TF-A advisories (TFV-1 to TFV-17 at the time of writing) and backported to LTS branches, but reach your device only after the silicon vendor and device maker rebuild and ship firmware. Ask which TF-A version and LTS branch you are running.
What is Trusted Firmware-A, and who maintains it?
The TF-A documentation describes the project as a reference implementation of secure world software for Armv7-A and Armv8-A, "including a Secure Monitor executing at Exception Level 3". The trustedfirmware.org project page widens that to Armv7-A, Armv8-A and Armv9-A processors. In practice that means the Cortex-A and Neoverse application cores you find in phones, laptops, servers, network appliances, automotive computers and single board computers.
TF-A implements a set of Arm interface standards so that every SoC does not invent its own. The documentation lists:
- the Power State Coordination Interface (PSCI)
- Trusted Board Boot Requirements CLIENT (TBBR-CLIENT)
- the SMC Calling Convention (SMCCC)
- the System Control and Management Interface (SCMI)
- the Software Delegated Exception Interface (SDEI)
- the PSA firmware update specification
The documentation calls it "a suitable starting point for productization" and tells users to do their own security validation, including penetration testing, on any secure world code derived from TF-A. The firmware in your device is a derivative, built and configured by someone else.
How is it governed?
TF-A is one of several projects under the Trusted Firmware umbrella at trustedfirmware.org. The sibling projects listed on the site include Trusted Firmware-M for Cortex-M microcontrollers, OP-TEE, Mbed TLS and TF-PSA-Crypto, Hafnium (the Secure EL2 partition manager), TF-RMM (the reference monitor for Arm Confidential Compute Architecture), MCUboot, Trusted Services, and Rusted Firmware-A (RF-A), which its project page describes as a Rust-first implementation of TF-A for the latest Arm A-class processors and which reached v0.3.0 on 8 October 2026.
The project FAQ says the governance model and the rules for Technical Steering Committee participation and voting are set out in a downloadable project charter, and that Linaro "is a Platinum Member of the Trusted Firmware project and provides governance, hosting and other services". The site footer is copyright Linaro Limited, and member companies join through a membership process. The source of record is the trustedfirmware.org Git and Gerrit servers; the FAQ notes that TF-A is migrating from GitHub to those servers, with a GitHub mirror kept for convenience. Code review happens on Gerrit at review.trustedfirmware.org, and the documentation is published at trustedfirmware-a.readthedocs.io.
How often does TF-A release?
The release process page says the project aims for a release every six months, tagged on the master branch, with a code freeze up to four weeks before. The version is set in the Makefile through VERSION_MAJOR, VERSION_MINOR and VERSION_PATCH, and the patch number only increases for long term support releases. The LTS document explains that releases are cut twice a year, in May and November, and that the project is aiming to support each LTS branch for at least seven years, up from an original plan of five, because firmware stays in the field far longer than a desktop operating system.
| Date | Event | Source |
|---|---|---|
| 21 October 2013 | The ARM-software/arm-trusted-firmware repository is created on GitHub | GitHub repository metadata |
| October 2018 | v2.0 target release window (first week of October) | TF-A release information |
| 20 July 2022 | First draft of the TF-A LTS proposal | TF-A LTS document history |
| March 2024 | Trusted Firmware project wiki deprecated in favour of readthedocs | trustedfirmware.org FAQ |
| 23 March 2026 | Qualcomm joins Trusted Firmware | trustedfirmware.org news |
| 27 May 2026 | TF-A 2.15.0 in the change log; Mbed TLS now included in the TF-A repository | TF-A change log |
| 2 June 2026 | TF-A v2.15 release announced | trustedfirmware.org news |
| 8 October 2026 | Rusted Firmware-A v0.3.0 released | trustedfirmware.org news |
| After v2.17 | ENABLE_RME build option, deprecated in v2.15.0, is due for removal | TF-A release information |
Which devices use TF-A?
The documentation has a full "Platform Ports" chapter covering Arm's own Fixed Virtual Platforms (FVPs) and the Juno development board, the QEMU virt machine, and ports for SoCs from many silicon vendors across mobile, automotive, networking, server and single board computer markets. Two practical consequences follow.
First, the TF-A in a shipping device is usually a vendor fork. The SoC vendor takes an upstream release, adds a platform port and often closed components such as a System Control Processor firmware image or DRAM training code, and ships that as part of a board support package. The device maker then builds it with its own keys.
Second, the TF-A version in a device can lag upstream by years. That is exactly the problem the LTS branches were created to address. The LTS document is blunt about the motivation: device makers want to keep in-market firmware changes small to avoid regressions, but they cannot skip security fixes, and the EU Cyber Resilience Act now pushes manufacturers to keep shipping updates across a product's life.
What are the boot stages BL1, BL2, BL31, BL32 and BL33?
A two minute primer on Arm exception levels
Arm A-profile processors run software at four privilege levels called exception levels, in two security states.
| Level | Normal world (non-secure) | Secure world |
|---|---|---|
| EL0 | Applications | Trusted applications (for example OP-TEE TAs) |
| EL1 | OS kernel (Linux, Windows, an RTOS) | Trusted OS kernel, for example OP-TEE core at S-EL1 |
| EL2 | Hypervisor (KVM, Xen) or UEFI firmware | Secure Partition Manager such as Hafnium at S-EL2 (Armv8.4 and later) |
| EL3 | None: EL3 is always secure | Secure monitor: TF-A BL31 |
EL3 is the most privileged level, and it is where the processor decides which world runs next. The only way for code at a lower level to ask EL3 for something is to raise an exception into it, normally with the Secure Monitor Call (SMC) instruction. That is why a bug in BL31 is so serious: there is nothing above it.
The AArch64 cold boot path
The firmware design document describes the cold boot path as the sequence that starts at power on and runs until control passes to normal world firmware in DRAM. For AArch64 it has five steps.
| Stage | Name in the TF-A docs | Runs at | Lives in | Main job |
|---|---|---|---|---|
| BL1 | AP Trusted ROM | EL3 | ROM, data in trusted SRAM | Reset handling, minimal CPU setup, load and (with TBB) authenticate BL2, then hand BL31's entry point over |
| BL2 | Trusted Boot Firmware | Secure EL1 (or EL3 with RESET_TO_BL2) | Trusted SRAM | Platform setup, load and authenticate SCP_BL2, BL31, BL32 and BL33 |
| BL31 | EL3 Runtime Software | EL3 | Trusted SRAM | Install runtime exception vectors, PSCI, SMC dispatch, initialise BL32, then enter BL33 |
| BL32 | Secure-EL1 Payload (optional) | Secure EL1 (or S-EL2 with an SPMC) | Secure memory | Trusted OS such as OP-TEE, or the test secure payload |
| BL33 | Non-trusted Firmware | EL2 if present, else EL1 | Non-secure DRAM | UEFI (EDK II), U-Boot, or a Linux kernel directly |
On AArch32 the design is different: there are four steps and the EL3 Runtime Software is BL32 (the minimal SP_MIN implementation) rather than BL31.
BL1. Execution begins at the platform's reset vector at EL3. BL1 first decides whether this is a cold boot or a warm boot (a CPU waking from a low power state), sets up simple exception vectors and performs minimal architectural setup. It then prints "Booting Trusted Firmware" on the primary CPU, loads BL2 from platform storage into trusted SRAM and jumps to it at Secure EL1. BL1 only expects one kind of exception afterwards: an SMC from BL2 asking it to run the EL3 runtime image. BL1 is also where the optional Firmware Update (FWU) flow begins when the platform decides the normal images cannot be booted.
BL2. BL2 performs the platform initialisation needed to load the rest: on Arm platforms that includes setting up memory protection and, on systems with a System Control Processor, loading the SCP_BL2 image for the separate power and clock controller. BL2 then loads BL31 into trusted SRAM, the optional BL32 into secure memory, and BL33 into non-secure memory. It does not jump to BL32 or BL33 itself. Instead it records their entry points and the processor state they need, then raises an SMC back to BL1, which turns off the MMU, cleans caches and passes control to BL31 at EL3.
BL31. BL31 replaces BL1's exception vectors with its own, which check every SMC against the SMC Calling Convention before routing it. It initialises per-CPU data, the console, interconnect coherency, the MMU, the generic interrupt controller and the power controller, detects the system topology and starts the runtime services, PSCI first among them. If a BL32 image exists, the matching Secure Payload Dispatcher service initialises it. Finally BL31 sets up a clean EL2 or EL1 context, "ensuring that no secure state information finds its way into the non-secure execution state", and enters BL33 at the highest available exception level.
BL32. The secure payload is optional. On many products it is OP-TEE. BL31 contains a dispatcher (built with the SPD option, for example SPD=opteed) that knows how to start the trusted OS and how to route secure calls and interrupts to it.
BL33. This is the first normal world code. The QEMU platform documentation shows three common choices: EDK II UEFI firmware (QEMU_EFI.fd), U-Boot, or a Linux kernel booted directly by setting ARM_LINUX_KERNEL_AS_BL33=1, in which case BL2 passes the device tree to the kernel in register x0.
Cold boot, warm boot and secondary CPUs
During a cold boot one CPU becomes primary. The others wait in a safe platform specific state until the primary has done enough setup to release them. On QEMU, the docs explain, all CPUs are released together; BL1 picks a primary and parks the secondaries in a polling loop until the normal world asks for them through PSCI CPU_ON. A warm boot is a CPU coming out of a power down state. It does not reload images. It re-enters BL31 through its warm boot entry point, restores its context and returns to wherever the OS asked it to resume.
When the boot ROM is not TF-A's BL1
Many SoCs have their own mask ROM. The firmware design document describes two common integrations:
RESET_TO_BL2: some boot ROMs expect the next stage to run at EL3. Rather than waste memory on a BL1 whose only job would be dropping to Secure EL1, BL2 runs at EL3, includes the reset code itself and jumps directly to the next image. TF-A 2.15.0 reworked this path so platforms handle both EL1 and EL3 BL2 in the same setup hooks.- BL31 only: platforms with an existing trusted boot loader can call
bl31_entrypoint()directly. TF-A documents a stable entry contract (AArch64, EL3, little endian, all interrupts masked) so the two can be updated independently.
If a vendor boot ROM and loader verify BL31, TF-A's Trusted Board Boot code in BL1 and BL2 may not run at all, and the chain of trust you need to audit is the vendor's.
How does Trusted Board Boot build a chain of trust?
Trusted Board Boot (TBB) is the TF-A feature that "prevents malicious firmware from running on the platform by authenticating all firmware images up to and including the normal world bootloader". It implements Arm's Trusted Board Boot Requirements specification, DEN0006D, and pairs with the Firmware Update design.
The trust anchor
A chain of trust starts with components that are trusted without being checked. In TF-A those are:
- The ROTPK, the Root of Trust Public Key, or a hash of it. On Arm development platforms a hash of the ROTPK (SHA-256 by default, selectable with
HASH_ALG) sits in trusted root-key storage registers. A development ROTPK can instead be embedded in BL1 and BL2, which the docs say is "only for development purposes". - BL1, on the assumption that it lives in ROM and cannot be changed.
Everything after that is a certificate or an image.
Key certificates and content certificates
TF-A's certificates follow X.509 v3, but they are not a web PKI. The design document says all certificates are self-signed and that no certificate authority is needed, because trust comes from the content of custom extensions rather than from the issuer field. There are two kinds:
- Key certificates carry a public key that will verify the next certificate.
- Content certificates carry the hash of a boot image (and of its configuration file).
An image is authentic when its computed hash matches the hash in a content certificate whose signature chains back to the ROTPK.
The default TBBR chain of trust uses these keys:
| Key | Signs | Public half stored in |
|---|---|---|
| Root of trust key | Trusted boot firmware certificate (BL2) and trusted key certificate | The ROTPK in the chip (or its hash) |
| Trusted world key | Key certificates for SCP_BL2, BL31 and BL32 | Trusted key certificate |
| Non-trusted world key | Key certificate for BL33 | Trusted key certificate |
| BL3x keys (one each for SCP_BL2, BL31, BL32, BL33) | The content certificate for that image | The matching key certificate |
The certificates themselves are the trusted boot firmware certificate (hash of BL2 and of TB_FW_CONFIG, HW_CONFIG and FW_CONFIG), the trusted key certificate, and a key and content certificate pair for each of the SCP firmware, the SoC firmware (BL31 plus SOC_FW_CONFIG), the trusted OS (BL32 plus TOS_FW_CONFIG) and the non-trusted firmware (BL33 plus NT_FW_CONFIG). The SCP and trusted OS certificates are only required when those images exist.
The verification sequence
The design document gives the order, and the system panics if any step fails:
- BL1 loads the BL2 content certificate, hashes the issuer public key and compares it with the ROTPK hash from the root-key storage registers. If they match, it reads the BL2 hash from the certificate.
- BL1 loads BL2, hashes it and compares it with that value. Only then does it jump.
- BL2 loads the trusted key certificate, checks its issuer key against the ROTPK hash, and saves the trusted world and non-trusted world public keys.
- For each of SCP_BL2, BL31 and BL32, BL2 verifies the key certificate with the trusted world key, saves the image key, then verifies the content certificate with that image key and saves the image hash.
- For BL33, BL2 does the same using the non-trusted world key.
- BL2 hashes each loaded image and compares it with the saved hash.
One note in that section deserves attention: on the Arm development platforms the ROTPK matching operation in step 1 is described as platform specific and "currently unimplemented". On a reference board the chain is a demonstration. On a product, the silicon vendor's port has to implement it against real fuses.
Three default chains of trust
Platforms can define their own chain, and TF-A ships three defaults:
- TBBR: one vendor owns the ROTPK, the trusted world key and the non-trusted world key, so that vendor signs everything.
- Dualroot: for systems where the normal world firmware owner and the secure world firmware owner do not want to share keys. BL33 chains to a second root called the Platform ROTPK (PROTPK).
- CCA: for Arm Confidential Compute Architecture systems, with three roots of trust, one each for the CCA firmware, the secure world firmware and the platform owner firmware, so their supply chains stay independent.
Choosing between them is a supply chain decision: dualroot lets a device maker sign its own BL33 without holding the SoC vendor's secure world key.
Anti-rollback and encryption
The TBBR specification and TF-A's authentication framework also describe non-volatile counters: certificates carry a counter value, and the platform refuses an image whose counter is lower than the value stored in hardware. That is what stops someone from flashing an older, signed but vulnerable BL31. TF-A additionally supports optional authenticated encryption of firmware images (DECRYPTION_SUPPORT=aes_gcm) through the encrypt_fw tool, which addresses the TBBR requirement for firmware confidentiality. Encryption protects the image from being read; it does not replace authentication.
The Firmware Image Package
All of these images and certificates are packed into a Firmware Image Package (FIP). The layout is a table of contents (ToC) header, one ToC entry per payload, an end marker, then the payload data. Each ToC entry holds a UUID that names the image, an offset from the start of the package, a size and flags. The UUIDs are defined in include/tools_share/firmware_image_package.h, shared by the tool and by the firmware. On Arm development platforms the FIP sits at the start of NOR flash, and the platform policy only allows loading a known set of images.
Because BL1 and BL2 parse that ToC from storage an attacker may control, the parser itself is part of the attack surface. Two TF-A advisories concern exactly this class of input: one on X.509 certificate extension validation (TFV-10) and a 2026 one on validation of FIP ToC offsets in BL1 and BL2 (TFV-15). The lesson is general: any code that parses attacker reachable data before authentication must be treated as security critical and kept up to date.
What is the secure world, and what does the secure monitor do?
TrustZone in one paragraph
Arm TrustZone splits the system into a secure state and a non-secure state. Every bus transaction carries a security attribute, so memory and peripherals can be marked secure only. The TF-A design document notes that the Base FVPs and Juno program a TrustZone Controller to carve out a region of DRAM that only the secure state can access, alongside trusted SRAM and ROM. Normal world software, including the Linux kernel and any hypervisor, cannot read that memory no matter how privileged it is.
What BL31 does at runtime
BL31 is the secure monitor. Once the system is running, it is responsible for:
- World switching: saving one world's register context and restoring the other's when an SMC or a routed interrupt requires it. BL31 keeps a per-CPU context for each security state.
- SMC dispatch: checking each SMC against SMCCC and routing it to the right runtime service, such as PSCI, SDEI, the secure payload dispatcher, vendor specific services or, on Arm CCA systems, the dispatcher for TF-RMM.
- Interrupt routing: the interrupt management framework decides whether a secure interrupt that arrives while the normal world runs is taken to EL3 and handed to the secure world.
- Power management: PSCI, plus coordination with the trusted OS so it can save its own state before a CPU powers down.
- Errata and mitigations: applying CPU errata workarounds at reset and exposing mitigation hooks that the OS can call. This sits next to, not instead of, CPU microcode; see how CPU microcode updates load and who signs them.
OP-TEE as BL32
OP-TEE describes itself as a Trusted Execution Environment "designed as companion to a non-secure Linux kernel running on Arm Cortex-A cores using the TrustZone technology". It implements the GlobalPlatform TEE Internal Core API v1.3.1 for trusted applications and the TEE Client API v1.0 for normal world clients. Its design goals are isolation from the non-secure OS and between trusted applications, a small footprint that fits in on-chip memory, and portability.
In a TF-A system OP-TEE is loaded by BL2 as BL32 and started by BL31's OP-TEE dispatcher (SPD=opteed). The QEMU platform page shows OP-TEE split into three images, a header (tee-header_v2.bin as BL32), a pager (BL32 Extra1) and pageable code (BL32 Extra2), which BL2 loads into trusted DRAM when BL32_RAM_LOCATION=tdram is set. Linux talks to OP-TEE through its TEE subsystem driver, which issues SMCs that BL31 forwards to OP-TEE at S-EL1.
Secure partitions, Hafnium and FF-A
Armv8.4 added a secure EL2. That allows a Secure Partition Manager to sit at S-EL2 and isolate several secure partitions from each other, rather than trusting one monolithic trusted OS. The trustedfirmware.org project page points to Hafnium as the open source implementation. In this model BL31 hosts the Secure Partition Manager Dispatcher (SPMD), and the SPM Core (SPMC) runs at S-EL2 (Hafnium), at S-EL1, or at EL3 itself, depending on build options. Messages between partitions and the normal world follow Arm's Firmware Framework for A-profile (FF-A). The TF-A SPM documentation says three SPM implementations coexist in the codebase and only one can be built at a time: an S-EL2 SPMC that manages multiple S-EL1 or S-EL0 partitions with virtualization in the secure world, an EL3 SPMC that manages a single S-EL1 partition, and an SPMC at S-EL1 for cores without the secure EL2 extension. In the S-EL2 case the BL32 build option is repurposed to point at the SPMC image, for example Hafnium. For a security review, the important point is that S-EL2 isolation shrinks the blast radius of a bug in any one secure service. Hardware memory safety features are a separate layer again; see our comparison of Arm MTE and CHERI.
Arm CCA and confidential computing
On processors that implement Arm's Confidential Compute Architecture, TF-A adds a fourth security state for confidential virtual machines, managed by TF-RMM. The design note in the firmware design chapter points readers to a separate RME chapter, and the CCA chain of trust above exists for these systems. If your platform does not use CCA, none of this is built in.
What are PSCI and the SMC Calling Convention, and why do they matter to the OS?
SMCCC: the calling convention
The SMC Calling Convention defines how normal world software asks firmware for something. TF-A's documentation says normal world software "can access TF-A runtime services via the Arm SMC (Secure Monitor Call) instruction" and that the instruction must be used as SMCCC mandates. In outline:
- The caller puts a 32-bit function identifier in register
w0/x0and arguments in the following registers, then executesSMC #0(orHVC #0when the call goes to a hypervisor). - The function identifier encodes whether the call is a fast call (it runs to completion atomically) or a yielding call, whether it uses the 32-bit or 64-bit convention, and which "owning entity" it belongs to: the Arm architecture, CPU services, SiP (silicon partner) services, OEM services, standard secure services such as PSCI, trusted applications or trusted OSes.
- Results come back in
x0and the following registers.
That owning entity split is why TF-A's PSCI header defines PSCI_VERSION as 0x84000000, SYSTEM_OFF as 0x84000008 and SYSTEM_RESET as 0x84000009 (32-bit standard service fast calls), while CPU_ON has both 0x84000003 for AArch32 callers and 0xc4000003 for the 64-bit convention. Silicon vendor calls live in the separate SiP range. BL31 rejects calls whose bit 31 (fast or yielding) and bits 29 to 24 (owning entity number) do not match a registered service.
SMCCC also defines architecture calls that the OS uses to discover firmware mitigations. When the speculative execution issues of 2018 arrived, TF-A advisory TFV-6 described a firmware workaround for the branch target injection variant, exposed as an SMC named SMCCC_ARCH_WORKAROUND_1 for normal world privileged software to call, and the advisory notes that such software depends on the firmware changes being deployed for its own workaround to work. A firmware that does not implement it leaves the kernel unable to apply the mitigation on affected cores.
PSCI: power management through firmware
PSCI is "the interface from normal world software to firmware implementing power management use-cases (for example, secondary CPU boot, hotplug and idle)". BL31 implements it as a runtime service. The functions an OS uses most are:
| PSCI function | What the OS uses it for |
|---|---|
PSCI_VERSION | Discover which PSCI version firmware implements |
CPU_ON | Start a secondary CPU at a given entry point (SMP bring up, CPU hotplug) |
CPU_OFF | Power down the calling CPU (hotplug) |
CPU_SUSPEND | Enter an idle or low power state on this CPU or a whole cluster |
AFFINITY_INFO | Ask whether a CPU is on or off |
SYSTEM_OFF | Power the system off |
SYSTEM_RESET and SYSTEM_RESET2 | Reboot, optionally with an architectural or vendor reset type |
SYSTEM_SUSPEND | Suspend to RAM |
PSCI_FEATURES | Ask which optional functions are present |
Internally, BL31 tracks a tree of power domains (cores, clusters, the system) and a state machine for each node with the states OFF, RUN and RETENTION. Because CPUs can be touched before their caches are on, BL31 uses Lamport's Bakery algorithm for locks during the warm boot path rather than exclusive load and store based spinlocks.
Why the OS cares
On Arm, Linux does not normally start secondary CPUs itself. The device tree cpus nodes say enable-method = "psci", and a psci node with compatible = "arm,psci-1.0" (or arm,psci-0.2) and method = "smc" or "hvc" tells the kernel which conduit to use. The Linux PSCI binding documents those properties. The QEMU platform port even has BL2 edit the QEMU generated device tree to add the PSCI node and CPU enable methods.
When PSCI is wrong, the symptoms look like OS bugs: CPUs that never come online, reboots that hang, suspend that never resumes. For security, PSCI is also an attack surface, because every PSCI call is untrusted input from the normal world into EL3. Several TF-A advisories (TFV-1, TFV-4, TFV-8, TFV-11 and TFV-14) concern how SMC handlers treat that input, from firmware update calls to register handling between SMC clients.
How does TF-A support measured boot?
Trusted Board Boot answers "may this image run?". Measured boot answers "what actually ran?". The TF-A measured boot design document defines it as "computing and securely recording hashes of code and critical data at each stage in the boot chain before the code/data is used", and stresses that it "does not authenticate the code or critical-data". The two are complementary, and our post on secure, trusted and measured boot covers the general difference.
What gets measured
All firmware images (every BLx image and its configuration file) must be measured, plus platform critical data: settings that change the boot path, values that decide which firmware to load, security policies and debug settings, and data that hardware updates. The examples the documentation gives are the list of CPU errata workarounds applied at reset, fuse states such as whether the SoC is in secure mode, and the non-volatile counters that say whether firmware is up to date.
BL1 is treated as the root of trust for measurement and is not measured itself. The measurement platform interfaces are used by BL1 and BL2 only. BL31 does not load images and therefore does not measure any.
Where measurements go
A measurement slot (a PCR in TPM terms) can only be changed by an extend operation, a one way hash of the previous value and the new measurement, so no measurement can be removed or overwritten. TF-A supports three backends:
| Backend | What it is | Notes from the TF-A docs |
|---|---|---|
| TCG event log | A log of each measurement in the crypto agile TCG_PCR_EVENT2 format from the TCG EFI Protocol Specification | Images measured into PCR0, critical data into PCR1, following the Arm Server Base Security Guide |
| Discrete TPM | A TPM chip that extends the same measurements | Lets the TPM attest to the integrity of the event log |
| RSE (Runtime Security Engine) | A separate security subsystem on some Arm reference designs that holds measurements | Earlier documents called it RSS; TF-A 2.15.0 removed host ROTPK retrieval from RSE |
The event log is then handed to the next stage so the OS can read it and a remote verifier can replay it against the PCR values. That replay is what turns measurements into attestation: a verifier compares the reported log with known good hashes and decides whether to release a key or admit the device to a network.
Measured boot versus trusted board boot in TF-A
| Question | Trusted Board Boot | Measured boot |
|---|---|---|
| What does it do on a bad image? | Refuses to boot (panic) | Records it and continues |
| Trust anchor | ROTPK in the chip, BL1 in ROM | BL1 as root of trust for measurement |
| Output | Nothing, unless it fails | Event log and extended PCRs or RSE slots |
| Who acts on the result | The firmware itself | A verifier, a TPM policy or a key release service |
| Build flags | TRUSTED_BOARD_BOOT=1, GENERATE_COT=1 | MEASURED_BOOT=1 plus a backend |
| Protects against | Unsigned or wrongly signed images | Undetected changes to signed but unexpected images and configuration |
Production systems usually want both: authentication so unsigned code never runs, and measurement so a verifier can tell whether the signed code that ran was the expected version and configuration.
How are TF-A security advisories published, and how do fixes reach devices?
The upstream process
The TF-A security handling page says the project discloses all vulnerabilities it finds or is told about as Security Advisories listed in the documentation, and announces new ones on the project mailing list. Researchers are asked not to file security issues in the public tracker or on the mailing list but to follow the trustedfirmware.org security incident process, whose stated goal is to give makers of products that use TF-A time to assess a fix before it is public. The Trusted Firmware Security Center covers reporting, disclosure, handling of embargoed information and registration as a trusted stakeholder, which is how downstream companies get advance notice.
At the time of writing the advisory table runs from TFV-1 to TFV-17. Grouped by mechanism rather than by story, they fall into a few classes:
| Class | Advisories | What it teaches |
|---|---|---|
| Untrusted SMC input reaching EL3 or BL1 | TFV-1, TFV-4, TFV-8, TFV-11, TFV-14 | Every SMC argument is attacker input; firmware update calls are a favourite path |
| Parsing boot inputs before trust is established | TFV-10, TFV-15 | Certificate and FIP parsers run before authentication completes |
| Speculative execution and CPU errata | TFV-6, TFV-7, TFV-9, TFV-13, TFV-16, TFV-17 | Firmware must apply errata workarounds and expose mitigations the OS can call |
| Register, debug and memory attribute handling | TFV-2, TFV-3, TFV-5, TFV-12 | Debug interfaces, timing registers and memory attributes must be configured and switched correctly between worlds |
We list these to show the shape of the risk, not to recount any one bug. Read each advisory on the TF-A site for affected versions and fixes.
LTS backports
The LTS policy sets objective criteria for backporting. No features are backported. Any patch that appears in a security advisory is automatically selected, and patches can only come from the master branch, so master is always a superset of every LTS branch. LTS branches are named like lts-v2.14, and the playbook uses automated dependency update pull requests per LTS branch to keep third party code current. Testing support for LTS comes from the trustedfirmware.org CI.
The long road to the device
Upstream fixing a bug is the first of several steps:
- TF-A merges the fix to master and backports it to the active LTS branches.
- The silicon vendor merges it into the TF-A fork in its board support package, often alongside its own platform code and closed components.
- The device maker rebuilds the FIP, signs the new certificates with its production keys, and bumps the anti-rollback counter if the old image must never boot again.
- The update is delivered: through the OS vendor's firmware channel, a capsule update under UEFI, a vendor tool, or not at all for devices past their support window.
Each hand-off adds delay, and users rarely see which TF-A version they run, so ask for the version, LTS branch and advisory status in procurement. NIST SP 800-193, the Platform Firmware Resiliency Guidelines, frames the same need as protection, detection and recovery for platform firmware, including authenticated updates.
How to see what your device is running
On many boards the TF-A console prints version strings during boot (BL1 prints "Booting Trusted Firmware", and each stage prints a banner with its version and build string). From a running Linux system you can at least confirm what the firmware exposes:
# PSCI and SMCCC versions reported by firmware
dmesg | grep -iE 'psci|smccc'
# Does the device tree describe PSCI and an OP-TEE node?
ls /proc/device-tree/psci 2>/dev/null && cat /proc/device-tree/psci/compatible; echo
ls /proc/device-tree/firmware/ 2>/dev/null
# Is a TEE driver bound (OP-TEE or another TEE)?
ls /sys/bus/tee/devices/ 2>/dev/null; ls -l /dev/tee* 2>/dev/null
# Is there a TPM event log exposed to the OS?
ls /sys/kernel/security/tpm0/ 2>/dev/null
None of these tells you the exact TF-A tag. For that you need the vendor's release notes or the boot console log, which is another reason to ask for it in writing.
Step by step: build TF-A for QEMU with Trusted Board Boot and inspect the FIP
This walkthrough uses the QEMU virt platform, which the TF-A docs support directly. It runs entirely in an emulator, so nothing here touches real flash. The keys it generates are development keys: never ship them.
1. Install the prerequisites
You need an AArch64 cross compiler, GNU Make, OpenSSL development headers (used to build cert_create, encrypt_fw and fiptool) and QEMU. The TF-A prerequisites page lists the tested compiler versions and notes that OpenSSL 4 is not supported; it recommends an OpenSSL release that still receives security updates, typically an LTS release or a distribution maintained one.
# Debian or Ubuntu example; package names vary by distribution
sudo apt install build-essential git gcc-aarch64-linux-gnu \
libssl-dev device-tree-compiler qemu-system-arm
aarch64-linux-gnu-gcc --version
openssl version
qemu-system-aarch64 --version
2. Get the source and pin a release
git clone https://git.trustedfirmware.org/TF-A/trusted-firmware-a.git
cd trusted-firmware-a
git tag --list 'v2.1*' | sort -V | tail -5
git checkout v2.15.0
# Since 2.15.0, Mbed TLS is included in the repository
git submodule update --init --recursive
Pin to a tag, or to an lts-v2.x branch for products, rather than building whatever is on master. Record the commit hash in your build metadata.
3. Get a BL33
Download or build EDK II for QEMU as the platform page describes (QEMU_EFI.fd, built from ArmVirtPkg/ArmVirtQemuKernel.dsc), or use U-Boot built for qemu_arm64. Save it as bl33.bin next to the TF-A tree. Build a Linux Image and a small root file system (the TF-A page uses Buildroot's qemu_aarch64_virt_defconfig) if you want to boot all the way to a shell.
4. Build with Trusted Board Boot enabled
make CROSS_COMPILE=aarch64-linux-gnu- PLAT=qemu \
BL33=../bl33.bin \
TRUSTED_BOARD_BOOT=1 GENERATE_COT=1 \
all fip
ls build/qemu/release/
TRUSTED_BOARD_BOOT=1 builds the authentication framework into BL1 and BL2. GENERATE_COT=1 makes the build run cert_create, which takes the images and keys (PEM files or a PKCS#11 URI when keys live in an HSM), creates any missing keys, writes the certificates in DER format, and hands them to fiptool. The output is bl1.bin and fip.bin, with the individual certificates also left in the build directory.
To add OP-TEE as BL32, build OP-TEE OS for QEMU first and pass its three images plus the dispatcher, exactly as the platform page shows:
make CROSS_COMPILE=aarch64-linux-gnu- PLAT=qemu \
BL32=bl32.bin BL32_EXTRA1=bl32_extra1.bin BL32_EXTRA2=bl32_extra2.bin \
BL33=bl33.bin BL32_RAM_LOCATION=tdram SPD=opteed \
TRUSTED_BOARD_BOOT=1 GENERATE_COT=1 \
all fip
5. Inspect the FIP
# The tool is built with the platform build; build it on its own if needed
make PLAT=qemu fiptool
FIPTOOL=./build/qemu/release/tools/fiptool/fiptool
$FIPTOOL info build/qemu/release/fip.bin
fiptool info prints one line per ToC entry with its name, offset, size and command line option, for example the trusted boot firmware (BL2), the SoC firmware (BL31), the non-trusted firmware (BL33) and each certificate. To look inside:
# unpack writes into the current directory and refuses to overwrite files
mkdir -p /tmp/fip-unpacked
(cd /tmp/fip-unpacked && "$OLDPWD/$FIPTOOL" unpack "$OLDPWD/build/qemu/release/fip.bin")
ls -l /tmp/fip-unpacked
6. Read the certificates
The certificates are ordinary DER encoded X.509, so OpenSSL can print them. The public keys and image hashes appear as non-standard extensions identified by object identifiers.
for c in build/qemu/release/*.crt; do
echo "== $c"
openssl x509 -inform DER -in "$c" -noout -subject -issuer -text \
| sed -n '/X509v3 extensions/,/Signature Algorithm/p' | head -30
done
The build leaves files such as tb_fw.crt, trusted_key.crt, soc_fw_key.crt, soc_fw_content.crt, nt_fw_key.crt and nt_fw_content.crt (plus tos_fw_* when a BL32 is present). You should see the trusted boot firmware certificate holding the BL2 hash, the trusted key certificate holding two public keys, and a key and content pair for BL31 and BL33. Compare the BL31 hash in the SoC firmware content certificate with a hash you compute yourself:
sha256sum build/qemu/release/bl31.bin
7. Assemble a flash image and boot
The QEMU page concatenates BL1 and the FIP into one secure flash image. Warning: dd overwrites whatever of= names without asking. Here the target is a local file, flash.bin; before you adapt these lines for a real board, run ls -l on the output path and confirm it is not a block device such as /dev/mmcblk0 or /dev/sda.
dd if=build/qemu/release/bl1.bin of=flash.bin bs=4096 conv=notrunc
dd if=build/qemu/release/fip.bin of=flash.bin seek=64 bs=4096 conv=notrunc
qemu-system-aarch64 -nographic -machine virt,secure=on -cpu cortex-a57 \
-kernel Image -append 'console=ttyAMA0,38400 keep_bootcon' \
-initrd rootfs.cpio.gz -smp 2 -m 1024 -bios flash.bin -d unimp
secure=on gives the virtual machine the secure world memory and flash TF-A needs. Watch the console: BL1, BL2 and BL31 print notices as they load and authenticate each image.
8. Prove authentication works
Flip one byte in the BL33 payload inside a copy of the FIP and boot again. With Trusted Board Boot built in, BL2 computes a hash that no longer matches the non-trusted firmware content certificate and stops. Use fiptool update to replace one image without rebuilding the package:
cp ../bl33.bin /tmp/bl33-tampered.bin
printf '\x00' | dd of=/tmp/bl33-tampered.bin bs=1 seek=4096 conv=notrunc
cp build/qemu/release/fip.bin /tmp/fip-tampered.bin
$FIPTOOL update --nt-fw /tmp/bl33-tampered.bin /tmp/fip-tampered.bin
Rebuild flash.bin from the tampered FIP and boot it. The boot should halt at BL2 with an authentication error. This is the cheapest test you can run to confirm a chain of trust actually enforces anything.
9. Optional: turn on measured boot
The build options page describes MEASURED_BOOT as a flag that defaults to 0 and "can be enabled with TRUSTED_BOARD_BOOT" so that the code taking measurements is itself trusted. The QEMU platform makefile pulls in the TCG event log driver and QEMU specific BL1 and BL2 measurement code when it is set:
make CROSS_COMPILE=aarch64-linux-gnu- PLAT=qemu \
BL33=../bl33.bin \
TRUSTED_BOARD_BOOT=1 GENERATE_COT=1 MEASURED_BOOT=1 \
all fip
Compare the digests recorded in the event log with sha256sum of the binaries, and check how your platform passes the log to BL33 before building attestation on top of it.
TF-A, UEFI on Arm, U-Boot and coreboot compared
These projects are often described as alternatives. On Arm they are usually layers.
| TF-A | UEFI on Arm (EDK II as BL33) | U-Boot | coreboot | |
|---|---|---|---|---|
| Role in the chain | First mutable stage after ROM, plus the EL3 runtime | Normal world firmware that loads an OS | Normal world bootloader | Hardware init then payload, mostly on x86 and some Arm boards |
| Runs at | EL3, Secure EL1, stays resident at EL3 | EL2 or EL1, exits at OS boot except runtime services | EL2 or EL1 (can also be an earlier stage on some SoCs) | Varies; on Arm it uses TF-A BL31 for EL3 services |
| Stays after OS boots | Yes (BL31, BL32) | Runtime services only | No | No (only tables it leaves behind) |
| Verifies the next stage with | Trusted Board Boot (X.509 chain to ROTPK) | UEFI Secure Boot (db, dbx, KEK, PK) | FIT image signatures, public key in its device tree | vboot (signed firmware slots, root key in read only flash) |
| OS interface | PSCI, SMCCC, SDEI, FF-A | UEFI boot and runtime services, ACPI or device tree | Device tree, bootefi UEFI subset | Payload specific |
| Typical systems | Almost every Armv8 and Armv9 A-profile platform | Arm servers, Arm laptops, SystemReady devices | Embedded boards, routers, many SBCs | Chromebooks, some open firmware laptops |
Two specifications tie these together. EBBR (Embedded Base Boot Requirements) defines a subset of UEFI that U-Boot or EDK II provide so a generic distribution can boot an embedded Arm board. And the Arm server world expects UEFI plus ACPI above TF-A. Either way, TF-A sits underneath, and its chain of trust decides whether the UEFI or U-Boot binary you think you are running is the one that actually started. For U-Boot's own signing model see where the public key lives in U-Boot verified boot.
Common mistakes
- Shipping development keys. TF-A includes development RSA and ECDSA private keys under
plat/arm/board/common/rotpk/so the reference platforms build out of the box, andcert_createwill generate new keys if none are supplied. A product built withARM_ROTPK_LOCATION=devel_rsaor with keys generated on a laptop has a chain of trust that anyone with the source can sign for. Generate production keys in an HSM and pass them by PKCS#11 URI. - Assuming the reference ROTPK check is implemented. On the Arm development platforms the ROTPK matching step is described as unimplemented. Check that your SoC port really compares against fused values.
- Forgetting anti-rollback. Signed but old firmware is still signed. If the non-volatile counters are never incremented, a fixed vulnerability can be reintroduced by flashing the previous release.
- Treating measured boot as protection. Measurements change nothing on their own. Without a verifier that reads the event log and acts on it, measured boot is a log nobody reads.
- Building from master for a product. Use a tagged release or an LTS branch, record the commit, and track the advisory list for that branch.
- Ignoring bundled third party code. A TF-A build pulls in Mbed TLS for certificate parsing and cryptography, libfdt for device trees, compiler runtime code and more. The change log records updates to these, and the build docs warn that the Mbed TLS version must be one that "fixes any known security vulnerabilities".
- Skipping the OpenSSL version check for host tools.
cert_createandfiptoollink OpenSSL on the build machine. The prerequisites page says which versions are supported; an unmaintained OpenSSL on a signing host is a supply chain weakness of its own. - Exposing vendor SMCs without review. SiP services added by a silicon vendor run at EL3 with the same privilege as PSCI. Each one is attack surface that upstream never reviewed.
FAQ
Is Arm Trusted Firmware the same as Trusted Firmware-A?
Yes. The project was originally published by Arm as "ARM Trusted Firmware" and is now Trusted Firmware-A, one of the projects under trustedfirmware.org. The GitHub mirror still carries the older repository name, but the documentation, releases and code review are under the TF-A name.
Is TF-A a bootloader like U-Boot or GRUB?
No. TF-A is secure world firmware. It loads and authenticates the bootloader (BL33), then stays resident at EL3. U-Boot or UEFI runs as BL33 and loads your OS, and GRUB, if used, runs after that.
What is BL31 and why does it stay in memory?
BL31 is the EL3 Runtime Software. It stays in trusted SRAM after boot because it provides runtime services the OS calls through SMC, mainly PSCI power management, and it switches between the normal and secure worlds whenever OP-TEE or another secure payload runs.
Does every Arm device use TF-A?
Most Armv8-A and Armv9-A application processor platforms use TF-A or a vendor fork of it for EL3. Some vendors ship their own EL3 firmware or use TF-A only for BL31 behind their own boot ROM and loader. Microcontrollers based on Cortex-M use Trusted Firmware-M instead, which is a separate project.
Is OP-TEE part of TF-A?
No. OP-TEE is a separate Trusted Firmware project. TF-A loads it as BL32 and its BL31 contains an OP-TEE dispatcher (SPD=opteed) that starts it and routes calls to it. You can build TF-A without any BL32.
What is a FIP file?
A Firmware Image Package is the container TF-A loads images from. It has a table of contents with a UUID, offset and size for each entry, followed by the images and certificates. fiptool info lists its contents and fiptool unpack extracts them.
What is the ROTPK, and where is it stored?
The Root of Trust Public Key is the public key at the top of the chain. Production devices store it, or a hash of it, in hardware that software cannot change, such as the trusted root-key storage registers the TF-A documentation describes for its reference platforms. BL1 and BL2 compare certificate issuer keys against it.
How do I check which PSCI version my Arm board supports?
On Linux, run dmesg | grep -i psci. The kernel normally logs the PSCI version it detected in firmware, and on recent kernels the SMC Calling Convention version too. The device tree psci node under /proc/device-tree/psci shows the compatible string.
Does TF-A support a TPM?
Yes, as a measured boot backend. TF-A can record measurements in a TCG event log and extend them into a discrete TPM, so the TPM can attest to the log. On some Arm reference designs the Runtime Security Engine plays that role instead.
How long is a TF-A release supported?
Regular releases are every six months. Long term support branches receive security backports, and the TF-A LTS policy aims to support each LTS branch for at least seven years, with the caveat that CI infrastructure and maintainer availability may affect that.
Where Safeguard fits
Safeguard does not analyse firmware binaries, sign boot images, manage device fleets or check what runs at EL3 on a board. The fit here is indirect, and it is about the software around the firmware. A TF-A build is itself a supply chain: it vendors Mbed TLS, libfdt and compiler runtime code, its host tools depend on OpenSSL, and the BL33 and OP-TEE images you pair it with carry their own open source dependencies. The repositories, build containers and signing services that produce your firmware are ordinary software projects. Safeguard can scan those repositories, Dockerfiles and container images for known vulnerable components, record an SBOM for them, and evaluate policies and gates in CI, so the build environment that signs your FIP is held to the same standard as your application code.
Firmware has the longest update chain in computing, which makes the parts you control worth keeping clean. The cross compilers, OpenSSL linked host tools, build containers and BL33 and trusted application source that feed a TF-A build are open source dependencies, and they can be patched on your schedule even when the silicon vendor's firmware cannot; the vendor's TF-A fork itself still has to come from the vendor.
Fix it without waiting for upstream
Whatever the vulnerability, most of the risk sits in two gaps. The first is the time between a fix being published and that fix actually running in your production builds. The second, and worse, is the time before any fix exists at all, while a maintainer works out a patch and a release schedule. Waiting through both gaps is a habit, not a requirement. Safeguard gives teams three ways to close them.
1. Autonomous remediation: pull requests, not tickets
When a fixed version exists, Safeguard's Griffin models open a tested, policy gated pull request that moves the affected dependency to the safe version. You can run it on one repository or in bulk across every project that carries the vulnerable version. Remediation covers eight categories, including dependencies, licenses, security posture and findings. Reachability analysis ranks the vulnerable code paths your application actually calls first, so the first pull requests you merge are the ones that matter most. Autonomous remediation ships switched off, with every category set to Manual, so your team decides how much runs on its own and what still needs a human approval.
2. Gold Open Source: the safe version in seconds, free
gold.safeguard.sh is free and needs no login. Search any CVE or package to see affected and fixed versions, CVSS, EPSS, CISA KEV status and a recommended safe version, or use the "Am I affected?" checker. The same data is available through a free read API, README status badges and RSS threat feeds. The safeguard-sh/gold-scan-action GitHub Action can fail a build on a known exploited vulnerability, on any known vulnerability, or never, so a version you have just removed cannot quietly come back in next week's merge.
3. Gold Registry: start from components that are already fixed
registry.safeguard.sh provides hardened, drop in replacements for upstream packages and container images. Every Gold artifact is held continuously to zero exploitable critical or high CVEs, zero malware and a completed license check, with SLSA L3 or higher provenance, a Sigstore signature and a public evidence page you can hand to an auditor. An artifact loses its Gold badge if it regresses. Teams can point their own package directory at the registry so hardened equivalents resolve without changing how developers install anything.
When upstream has no fix yet, or will not ship one, Safeguard first works to get the fix accepted upstream. If the issue is severe or upstream will not move, Safeguard builds a fork, fixes the vulnerability there and publishes a hardened Gold build, so you are not stuck on a maintainer's release schedule. You can also request a hardened, compatibility tested build of a specific package. This fork and patch flow is in early access today, so ask which packages it covers before you plan around it.
| Your situation | What to use |
|---|---|
| A fixed version exists | Autonomous remediation opens the upgrade pull request; Gold Open Source confirms the safe version |
| You need to know today whether you are affected | Gold Open Source lookup and "Am I affected?" checker, free and without login |
| You want vulnerable versions to stop shipping | The Gold scan GitHub Action in CI, plus Safeguard policies and gates |
| Upstream has no fix yet, or will not ship one | A custom Gold request; fork and patch (early access) |
| You want to start clean on new projects | Pull hardened components and images from Gold Registry |
One honest limit: when the vulnerable code lives in a vendor appliance, a hosted service or an operating system runtime you do not build yourself, the fix still has to come from that vendor or distribution. The steps above apply to the open source dependencies and container images you build and ship, which is where most teams carry the largest and least tracked share of their exposure.
See how Safeguard would help
The first demo is a real Safeguard CLI session in a repository: it reads a vulnerability finding, asks before each command, edits the dependency, runs the install and tests with your approval and pushes nothing. The same flow applies to the build tooling repository behind a firmware image, for example a Python based signing helper or the container that hosts your cross compiler.
Click through it at your own pace, or open it full screen.
The second demo sets up the Safeguard runner on your own machine, approves it with a device code and scans from the terminal. Firmware build hosts are often kept off shared CI for good reason, and a local runner lets you scan the build tree where it already lives.
Click through it at your own pace, or open it full screen.
The third demo connects Claude to the Safeguard MCP server with OAuth and lets you choose which tools Claude can use. A firmware engineer can then ask questions about the dependencies in a build repository from the assistant they already use, without granting it more access than they choose.
Click through it at your own pace, or open it full screen.
Download the apps at https://safeguard.sh/download and read the CLI documentation at https://docs.safeguard.sh/docs/cli .
Quick check
Which TF-A stage stays resident after the operating system boots, and at which exception level?
BL31, the EL3 Runtime Software. It stays in trusted SRAM at EL3, provides PSCI and other SMC services, and switches between the normal and secure worlds. A BL32 trusted OS such as OP-TEE also stays resident, in the secure world.
In Trusted Board Boot, what is the difference between a key certificate and a content certificate?
A key certificate carries a public key used to verify the next certificate. A content certificate carries the hash of a boot image and its configuration. An image is accepted when its computed hash matches a content certificate whose signatures chain back to the ROTPK.
Sources
- Trusted Firmware-A documentation home
- TF-A Firmware Design
- TF-A Trusted Board Boot
- TF-A Building FIP images with support for Trusted Board Boot
- TF-A Authentication Framework and Chain of Trust
- TF-A Measured Boot Design
- TF-A Build Options
- TF-A Prerequisites
- TF-A QEMU virt Armv8-A platform
- TF-A PSCI Power Domain Tree design
- TF-A Secure Partition Manager
- TF-A Security Handling
- TF-A Security Advisories
- TF-A Release Processes
- TF-A LTS (Long-Term Support)
- TF-A Change Log and Release Notes
- trustedfirmware.org About
- trustedfirmware.org TF-A project page
- trustedfirmware.org FAQ
- Trusted Firmware Security Center
- OP-TEE documentation: About OP-TEE
- OP-TEE documentation: Core architecture
- TF-A Building Supporting Tools (fiptool, cert_create)
- TF-A Security Advisory TFV-6
- TF-A PSCI function identifiers, include/lib/psci/psci.h (GitHub mirror)
- TF-A QEMU platform makefile, plat/qemu/qemu/platform.mk (GitHub mirror)
- ARM-software/arm-trusted-firmware GitHub mirror
- trustedfirmware.org Rusted Firmware-A project page
- Linux kernel devicetree binding for PSCI
- Embedded Base Boot Requirements (EBBR)
- NIST SP 800-193, Platform Firmware Resiliency Guidelines
Last reviewed: 24 October 2026. TF-A build options, platform support and the advisory list change with every release; check the documentation for the release or LTS branch your firmware is built from.