3.6. Below UEFI — execution state and hardware register surface¶
XBL → ABL hand-off contract (bounded) describes the hand-off as seen through the UEFI/DXE protocol layer (BlockIo, RamPartition, PON, ChipInfo, …). This page describes the same moment one level lower: the machine state the SoC is in when XBL’s BDS transfers control to the application in the ABOOT FV — the execution state, reserved memory, and (below) which parts of the picture below the DXE service layer are still knowable only with a live device. The register-level map of the peripheral blocks themselves lives on their own standing pages (pointed to below), not here.
All addresses/IRQs/clock indices are taken from this unit’s own artifacts: the
board device tree (artifacts/boot_a/board.dts, i.e. the boot_a DTB), XBL
strings/memory-map (_READONLY/lun1/xbl_a.bin), and the parsed GPT. Where a
value is a standard programming model rather than a device-specific datum, that
is called out.
3.6.1. Execution state at ABL dispatch¶
- Exception level
EL1, non-secure. XBLCore/UEFI runs at EL1: XBL’s own exception handlers print
ELR-EL1,ESR-EL1,SCTLR,TTBR0and logSVC executed in AArch64(strings inxbl_a.bin). EL2 is occupied by the Qualcomm hypervisor (hyp_a, Open questions and limits of analysis) and EL3 by TZ (tz_a), both established by PBL/SBL before UEFI. So the application in the ABOOT FV is entered at EL1 with EL2/EL3 already owned by Qualcomm firmware — an OS kernel launched from here is likewise entered at EL1 (this SoC does not hand the kernel EL2).- MMU and caches
On. UEFI configures the MMU through EDK2
ArmMmuLib(ArmMmuLibCore.c,ArmConfigureMmuinxbl_a.bin) with a flat, mostly cached mapping; the translation tables live in the XBL working set at MMU PageTables ``0x9FF8D000`` (size ``0x3000``) (XBL memory-map entry,WRITE_BACK_XN).SCTLR_EL1/TTBR0_EL1are live. Device MMIO windows are mappedUNCACHEABLE/NS_DEVICE(e.g.SMMU 0x15000000); RAM is mappedWRITE_BACK.- Already initialised by XBL (not re-done downstream)
DDR training, the clock trees, PMIC sequencing and the USB/UFS PHYs are all completed inside XBL and are deliberately out of scope of this doc set — XBL stays untouched by anything running in the ABL slot. The UFS host controller is likewise already live (below); GIC-v3 and the architected timer are running too (next).
- Interrupt/DAIF and GIC
The GIC-v3 is initialised and the architected timer runs; UEFI services interrupts at EL1. A payload that leaves the UEFI environment inherits this state and is responsible for masking (
DAIF) and for any GIC teardown it needs before entering an OS.- Hand-off to an OS kernel (arm64 boot protocol)
The standard contract from this state is: place the FDT and images in the kernel window (below), disable the MMU (
SCTLR_EL1.M=0) and clean+invalidate the D-cache, mask interrupts, and branch to the kernel entry withx0 = physical FDT,x1=x2=x3=0, at EL1. Inside UEFI this is whatExitBootServices+ the loader’sPreparePlatformHardwareperform; the same teardown is required of anything that reaches the kernel without them. The kernel-side view of this ABI is in Kernel/DTB/ramdisk load and the kernel hand-off.
3.6.2. Reserved memory¶
The DRAM carve-outs a post-XBL payload must not overwrite are enumerated (with
exact base/size) from XBL’s own platform memory-map in XBL → ABL hand-off contract (bounded)
Q4; the DTB’s own /reserved-memory carve-out map (per-coprocessor windows,
QSEE/secure pools, display framebuffers) is decoded in Base kernel device tree (the SoC boot contract). The load window for an OS is Kernel ``0xA2400000`` size ``0x8000000``
(128 MB); the ABOOT FV itself is ``0x9FA00000`` size ``0x200000``. How the
actual DRAM base/size is discovered at runtime (the base DTB /memory node
is only a placeholder) is under “DRAM discovery without UEFI” in
What is fully mapped vs. what still needs a live device below.
3.6.3. Peripheral register surface — delegated¶
The register windows, clocks, pins and interrupt/IOMMU details of the SoC blocks that stay live at this hand-off point are documented on their own standing pages rather than repeated here, each noting the “state at hand-off” fact where it matters: the UFS host controller in Storage controllers — UFS, ICE, and SDCC, the GENI/QUP serial engines and console UART in QUP/GENI serial-engine bus map (what is wired where) (pin/clock detail also in Pin control — TLMM and the PMIC GPIOs and Clock tree — GCC, domain CCs, RPMh), the GCC/RPMh clock tree in Clock tree — GCC, domain CCs, RPMh, the TLMM/PMIC pin control in Pin control — TLMM and the PMIC GPIOs, and the GIC-v3/PDC/architected -timer and apps-SMMU/GPU-SMMU register windows in Base kernel device tree (the SoC boot contract). What follows is the boundary those pages don’t cover: which parts of that picture are only knowable with a live device.
3.6.4. What is fully mapped vs. what still needs a live device¶
For operating below the DXE layer, the static-analysis boundary falls in a specific place. Mapped to register fidelity from the dump: the execution state (EL1, MMU/cache, page-table base), every block’s register windows / IRQs / clocks / pins, the reserved-memory map, the partition/LBA layout, and the kernel-entry ABI. What a single static dump cannot fix — the items that separate “have the map” from “have working code”:
- Storage read path (UFS)
The register windows are known and the controller is live at hand-off (UEFI keeps
EFI_BLOCK_IOfunctional untilExitBootServices, so the link is up and the device is initialised). But the device-specific init/link-startup sequence is not recoverable statically: XBL does not reference the UFS base0x1D84000as a literal (it is formed viaADRP/ADD, so the driver code is not constant-addressable) and the UFS driver is string-sparse (onlyNumGears). So a register-level reader has two routes, both needing on-device validation — reuse the live controller (submit your own UTRD to the running host controller) or re-run UFS init (the sequence would come from a UFSHCI/ufs-qcommodel, not from this device’s images). The PHY itself is already trained by XBL and is not the implementer’s problem.- UFS DMA vs. the SMMU
UFS transfer descriptors are physical/IOVA addresses. The UFS DT node has no
iommusproperty (unlike the QUP nodes), and XBL logsUfsSmmuConfigForOtherBootDev = 1— so XBL sets up the UFS stream on the apps-SMMU (0x15000000) itself. Whether that stream is left in bypass / identity or an active translation context is not extractable, and a structural decode ofdevcfgpins down why.devcfg_ais an ELF64/AArch64 image (entry0x1c003000) carrying a DALProp-style pointer-linked node tree across two domains —0x1c003000(the QSEE address space) and0x805fd000— its first word is already an absolute node pointer (0x1c003040). The access-control item names are present as a string pool:/ac/smmu+disable_smmu_ac,/ac/xpu+disable_xpu_ac/xpu_silent_log/tlmm_xpu_protection,disable_security_stream_check,OEM_disable_rpmb_autoprovisioning— but each item’s boolean value is reached only through the tree’s relocated node pointers, not stored beside the name (noDALPcontainer signature and no static offset/pointer resolves to a name string). So the values are genuinely not recoverable by static matching — this remains the single most load-bearing unknown for a bare-metal read, settled only by a live probe or a full DALProp graph walk (the container is now identified; Secure world and coprocessors (TZ, HYP, trustlets)).- DRAM discovery without UEFI
The base DTB
/memoryis empty, so RAM base/size must be read at runtime. Inside UEFI:EFI_RAMPARTITION_Protocol(XBL → ABL hand-off contract (bounded)). Without UEFI: the SMEM region at0x80900000(size0x200000) holds the RAM partition table in the standard Qualcomm SMEM TOC format (XBL validatesSMEM_PARTITION_HEADER_ID,toc->version == 1,num_entries≤SMEM_MAX_PARTITIONS). The format is known; the values are runtime (SMEM is SRAM/DDR, not in any flash dump).- Left-state of non-boot blocks
The exact clock-gating XBL leaves each non-boot block in (which GCC gates are on; whether the console SE’s
se-clkis running), whether the console SE physically drives TX before the OS (theboot_logger_uartbuffer may not be flushed to the pad), and the SMMU stream state for non-UFS masters — all runtime, not in the dump.
Readiness. Operating inside the UEFI/DXE environment (reusing BlockIo, RamPartition, etc.) is specified down to register-level fidelity by this dump — the execution state above plus XBL → ABL hand-off contract (bounded) leaves no known static gap for that mode of operation. Operating bare-metal (register only, no DXE) is mapped but not turnkey: the UFS submission path and its SMMU stream mode are the two items that a static single-dump analysis structurally cannot close, and would be settled only by live bring-up.
- Source:
artifacts/boot_a/board.dts(board DTB) for all node addresses/IRQs/clocks/pins;_READONLY/lun1/xbl_a.binfor EL/MMU evidence, the platform memory-map, and UFS/console log strings; parsed GPT and Partition map and checksums for the UFS LUN/LBA layout.- Cross-refs:
XBL → ABL hand-off contract (bounded) (UEFI-protocol view of the same hand-off), Kernel/DTB/ramdisk load and the kernel hand-off (kernel-entry ABI), Partition map and checksums, Open questions and limits of analysis, Storage controllers — UFS, ICE, and SDCC (UFS register surface), QUP/GENI serial-engine bus map (what is wired where) (GENI/QUP console), Clock tree — GCC, domain CCs, RPMh (GCC/RPMh), Pin control — TLMM and the PMIC GPIOs (TLMM), Base kernel device tree (the SoC boot contract) (GIC/PDC/timer, apps-SMMU).