Qualcomm SA8775P · IQ-9075-EVK — Focused Overview

Lemans

Platform · Boot · Projects

The condensed tour: what the platform is, how the bootloaders
are laid out in memory, how the boot sequence runs, and the
open-source projects that make up the stack.

Need the full build/flash/Yocto detail? See the comprehensive deck.

U-Boot SPL TF-A BL31 OP-TEE U-Boot Linux

Agenda

1 · Platform Overview

SoC, board, and the software stack

2 · Build Outputs

The three flashable images & their contents

3 · Boot Loader Maps

Per-stage load addresses & device trees

4 · Boot Sequence

PBL → XBL → SPL → BL31 → OP-TEE → U-Boot → Linux

5 · Projects

U-Boot · TF-A · TEE · Linux kernel

Platform Overview

SoC

  • Qualcomm SA8775P (QCS9075)
  • 8 × Kryo CPU cores (AArch64)
  • Adreno GPU
  • Hexagon DSP
  • Automotive-grade security domains

Board

  • IQ-9075-EVK (Lemans EVK)
  • Engineering validation kit
  • UFS storage
  • Serial: ttyMSM0
  • USB EDL / QDL flash

Software Stack

  • U-Boot SPL (chosen over TF-A BL2 — both open-source)
  • TF-A BL31 (EL3 Secure Monitor)
  • OP-TEE OS (BL32, loaded by SPL)
  • U-Boot proper (BL33 / UEFI)
  • Linux + Buildroot initramfs (UKI)

Notable specifics: SPL signed locally via qtestsign (open-source — no QTI CASS access required); U-Boot proper loaded at 0xaf000000.

Build Outputs Three flashable images

1 · tz.mbn

tz partition · signed U-Boot SPL

  • U-Boot SPL (chosen over TF-A BL2), the first open-source stage
  • SWIV-annotated, then qtestsign-signed (no CASS)
  • Built SPL_LOAD_FIT + SPL_ATF
  • Runs at EL3, text base 0x1c100000

2 · uefi.elf

uefi partition · SPL_ATF boot FIT (a FIT, despite the .elf name)

  • TF-A BL31 — EL3 Secure Monitor @ 0x1c200000
  • OP-TEE OS (BL32) @ 0x1c300000
  • U-Boot proper (BL33) @ 0xaf000000
  • + U-Boot control FDT (fdt-1) — lets the SPL record loadables

3 · efi.bin

esp partition (LUN 0) · FAT32 EFI system partition

  • EFI/BOOT/bootaa64.efi — UEFI fallback entry
  • EFI/Linux/uki.efi — Unified Kernel Image, bundling:
  •   • kernel Image
  •   • lemans-evk-el2.dtb (EL2 device tree)
  •   • Buildroot initramfs + kernel cmdline

make bootimagetz.mbn (signed SPL)
make bootimageuefi.elf (BL31 + OP-TEE + U-Boot FIT)
make efiefi.bin (ESP: UKI + UEFI fallback)

Boot Loader Maps Load Addresses & Device Trees

SPL
0x1c100000 · EL3
BL31
0x1c200000 · EL3
OP-TEE (BL32)
0x1c300000 · S-EL1 · resident
U-Boot (BL33)
0xaf000000 · EL2
Linux
UKI · EL2

BL31 boots OP-TEE (BL32) and U-Boot proper (BL33); OP-TEE stays resident at S-EL1 while U-Boot loads Linux.

Control DTB — U-Boot (fdt-1 in the uefi FIT)

Read by the SPL so it records the FIT loadables into /fit-images, giving BL31 the OP-TEE and U-Boot entry points. u-boot.bin ships with an appended control DTB because BL31 hands off with x0 = MPIDR, not an fdt pointer.

Linux DTB — lemans-evk-el2.dtb

The EL2 variant needed to run Linux at EL2 without the Gunyah hypervisor — bundled into the UKI, no separate flash step. Enables the EL2 watchdog, disables the GPU Zap shader, and remaps IOMMU streams for the remoteprocs.

Full per-stage load-address table & DTB details in the comprehensive deck.

Boot Sequence

PBL — Primary Boot Loader Hardware ROM in SoC. Authenticates and loads XBL from UFS. Cannot be modified.
XBL — eXtensible Boot Loader Qualcomm proprietary. Initialises DDR, clocks, power rails. Loads XBL-SEC.
XBL-SEC — Security Authenticator Verifies the qtestsign signature on tz.mbn using the hash chain embedded in the MBN header before passing control to U-Boot SPL.
U-Boot SPL (tz.mbn) @ 0x1c100000 Runs at EL3. Initialises DRAM. Loads TF-A BL31, OP-TEE (BL32), and U-Boot proper (BL33) from the embedded SPL FIT image. Hands off to TF-A BL31.
TF-A BL31 — Secure Monitor @ 0x1c200000 Runs at EL3. Sets up the Secure Monitor. Loads OP-TEE into Secure EL1 and stages U-Boot proper for Normal World handoff.
SPL FIT → BL31 + BL32 + BL33 SPL unpacks the FIT: BL31 stays at EL3, OP-TEE loads into Secure EL1, U-Boot proper staged for Normal World at 0xaf000000.
BL32 — OP-TEE OS @ 0x1c300000 Initialises in Secure EL1. Sets up Trusted Application infrastructure. Returns control to TF-A BL31 Secure Monitor.
BL33 — U-Boot (UEFI) @ 0xaf000000 Runs at Normal World EL2. Presents UEFI runtime. Reads EFI system partition. Discovers bootaa64.efi fallback, then uki.efi.
UEFI Boot — uki.efi U-Boot loads and executes the Unified Kernel Image. The UKI PE/COFF stub sets up the execution environment.
Linux Kernel (EL2, lemans-evk-el2.dtb) Kernel boots with the EL2-specific device tree. Mounts the embedded initramfs. Loads OP-TEE kernel driver.
Buildroot Initramfs Busybox init, OpenSSH, networking. OP-TEE supplicant bridges TAs between user space and Secure World.
Section 4

Projects

The open-source components built from source

1 · U-Boot

SPL (used instead of BL2) + U-Boot proper (BL33)

2 · TF-A

BL31 — the EL3 Secure Monitor

3 · TEE

OP-TEE OS — Secure World kernel (BL32)

4 · Linux Kernel

EL2 device tree + UKI packaging

Projects · 1 of 4

U-Boot SPL + proper — first open-source boot stage

SPL — chosen over TF-A BL2
  • U-Boot SPL and TF-A BL2 are both open-source first-stage loaders; for this platform we chose to use SPL.
  • Defconfig qcom_lemans_spl_defconfig, text base 0x1c100000, runs at EL3.
  • Built SPL_LOAD_FIT + SPL_ATF: reads the uefi partition FIT and jumps to BL31.
  • BL31=bl31.elf and TEE=tee.elf passed in so the FIT embeds TF-A BL31 + OP-TEE.
  • SWIV-annotated, then signed locally with qtestsigntz.mbn (tz partition). No CASS / remote signing.

SPL signing (make spl)

python3 lemans/security/swiv_build_utility.py \
  .output/spl/u-boot-spl-swiv.elf \
  .output/spl/u-boot-spl.elf lemans

qtestsign -v6 tz \
  -o .output/spl/u-boot-spl.mbn \
  .output/spl/u-boot-spl-swiv.elf
U-Boot proper — BL33 / UEFI
  • Defconfig qcom_lemans_defconfig, text base 0xaf000000, runs at Normal World EL2.
  • Shipped in the FIT as u-boot.bin (nodtb + appended control DTB).
  • Configured in UEFI mode — presents a standard UEFI firmware interface.

Boot behaviour

  • Reads the EFI system partition (FAT32 efi.bin).
  • Falls back to EFI/BOOT/bootaa64.efi.
  • Launches EFI/Linux/uki.efi (the Unified Kernel Image).
  • Hands kernel execution over at EL2 once the UKI is loaded.
Projects · 2 of 4

TF-A BL31 — the EL3 Secure Monitor

What it is

ARM Trusted Firmware BL31 is the runtime Secure Monitor at EL3 — the highest privilege level. It owns the world switch, dispatching Secure Monitor Calls (SMCs) between the Normal World (Linux) and the Secure World (OP-TEE), and stays resident for the life of the system.

Build — BL31 only

  • Platform target: lemans_evkbuild/lemans_evk/release/bl31/bl31.elf.
  • We use U-Boot SPL in place of TF-A BL2 (both open-source) — only BL31 is built here.
  • Passed to U-Boot as BL31= so the SPL FIT carries it; flat bl31.bin is the FIT atf firmware.
Role in the boot chain
  • Loaded by U-Boot SPL from the FIT to 0x1c200000; SPL jumps to it.
  • Initialises the Secure Monitor and EL3 runtime services.
  • Dispatches OP-TEE (BL32) into Secure EL1.
  • Hands off to U-Boot proper (BL33) in the Normal World with x0 = MPIDR (no fdt pointer).
  • Remains resident, mediating every Normal ↔ Secure world SMC at runtime.
Projects · 3 of 4

TEE OP-TEE OS — BL32, Secure World kernel

What it is

OP-TEE is an open-source Trusted Execution Environment that runs in the Arm TrustZone Secure World (Secure EL1). It hosts Trusted Applications (TAs) and services Secure Monitor Calls routed through TF-A BL31.

Configuration

  • Platform: qcom-lemans
  • Output: optee_os/out/arm/core/tee.elf
  • FIT payload: tee-raw.bin @ 0x1c300000
  • Passed to U-Boot as: TEE= (embedded in the SPL FIT)
Role in the boot chain

U-Boot SPL loads TF-A BL31, OP-TEE (BL32), and U-Boot proper (BL33) from the SPL FIT. BL31 dispatches OP-TEE into Secure EL1, then returns to stage U-Boot.

At runtime the Linux kernel talks to OP-TEE via the tee-supplicant daemon and the CONFIG_OPTEE driver — SMCs travel EL0 → EL1 → EL3 → Secure EL1.

Projects · 4 of 4

Linux Kernel + EL2 device tree

Build Config

  • Defconfig: defconfig (override via LINUX_DEFCONFIG)
  • Auto-enabled: CONFIG_TEE, CONFIG_OPTEE
  • Auto-enabled: CONFIG_EFI_BOOT, CONFIG_EFI_ZBOOT
  • Output: arch/arm64/boot/Imagevmlinuz.efi

Console

console=ttyMSM0,115200
qcom_scm.download_mode=1
arm-smmu.disable_bypass=0
clk_ignore_unused
pd_ignore_unused
EL2 Device Tree

lemans-evk-el2.dtb is the Device Tree variant required when running Linux at EL2 without the Gunyah hypervisor.

  • Enables the Qualcomm watchdog at EL2
  • Disables the GPU Zap shader (not needed at EL2)
  • Remaps IOMMU streams for ADSP, CDSP, WPSS remoteprocs
  • Adjusts power domain topology for EL2 operation

Bundled into the UKI alongside the kernel Image and the Buildroot initramfs — no separate flash step required.

Summary

Platform

  • Qualcomm SA8775P / QCS9075 on the IQ-9075-EVK (Lemans EVK)
  • Open firmware: we chose U-Boot SPL over TF-A BL2 (both open-source) as the first open-source stage
  • SPL signed locally via qtestsign — no QTI CASS access required

Boot Loader Map

  • SPL 0x1c100000 · BL31 0x1c200000 · OP-TEE 0x1c300000
  • U-Boot proper 0xaf000000 · Linux via relocatable UKI
  • uefi FIT carries BL31 + OP-TEE + U-Boot proper on the uefi partition

Boot Sequence

  • PBL → XBL → XBL-SEC → SPL (EL3) → BL31 (EL3 monitor)
  • BL31 boots OP-TEE (S-EL1, resident) + U-Boot (EL2) → UKI → Linux (EL2)
  • Control DTB → FIT entry points · EL2 DTB for Linux w/o Gunyah

Projects

  • U-Boot — SPL (used instead of BL2) + proper (BL33 / UEFI)
  • TF-A — BL31, resident EL3 Secure Monitor
  • TEE — OP-TEE OS at Secure EL1 (BL32)
  • Linux — EL2 kernel packaged as a UKI

Full build, flash, UKI, and Yocto detail lives in the comprehensive deck.