========================================================== Below UEFI — execution state and hardware register surface ========================================================== :doc:`/xbl/handoff` 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. 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``, ``TTBR0`` and log ``SVC executed in AArch64`` (strings in ``xbl_a.bin``). EL2 is occupied by the Qualcomm hypervisor (``hyp_a``, :doc:`/open-questions`) 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``, ``ArmConfigureMmu`` in ``xbl_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_EL1`` are live. Device MMIO windows are mapped ``UNCACHEABLE``/``NS_DEVICE`` (e.g. ``SMMU 0x15000000``); RAM is mapped ``WRITE_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 with ``x0 = physical FDT``, ``x1=x2=x3=0``, at EL1. Inside UEFI this is what ``ExitBootServices`` + the loader's ``PreparePlatformHardware`` perform; the same teardown is required of anything that reaches the kernel without them. The kernel-side view of this ABI is in :doc:`/abl/bootlinux`. 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 :doc:`/xbl/handoff` Q4; the DTB's own ``/reserved-memory`` carve-out map (per-coprocessor windows, QSEE/secure pools, display framebuffers) is decoded in :doc:`/boot/base-dtb`. 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. 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 :doc:`/soc/storage`, the GENI/QUP serial engines and console UART in :doc:`/boot/qup-buses` (pin/clock detail also in :doc:`/soc/pinctrl` and :doc:`/soc/clocks`), the GCC/RPMh clock tree in :doc:`/soc/clocks`, the TLMM/PMIC pin control in :doc:`/soc/pinctrl`, and the GIC-v3/PDC/architected -timer and apps-SMMU/GPU-SMMU register windows in :doc:`/boot/base-dtb`. What follows is the boundary those pages don't cover: which parts of that picture are only knowable with a live device. 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_IO`` functional until ``ExitBootServices``, 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 base ``0x1D84000`` as a literal (it is formed via ``ADRP``/``ADD``, so the driver code is not constant-addressable) and the UFS driver is string-sparse (only ``NumGears``). 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-qcom`` model, 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** ``iommus`` property (unlike the QUP nodes), and XBL logs ``UfsSmmuConfigForOtherBootDev = 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 of ``devcfg`` pins down *why*. ``devcfg_a`` is an **ELF64/AArch64** image (entry ``0x1c003000``) carrying a **DALProp-style pointer-linked node tree** across two domains — ``0x1c003000`` (the QSEE address space) and ``0x805fd000`` — 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 (no ``DALP`` container 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; :doc:`/trustzone/secure-world`). DRAM discovery without UEFI The base DTB ``/memory`` is empty, so RAM base/size must be read at runtime. Inside UEFI: ``EFI_RAMPARTITION_Protocol`` (:doc:`/xbl/handoff`). Without UEFI: the **SMEM** region at ``0x80900000`` (size ``0x200000``) holds the RAM partition table in the standard Qualcomm SMEM TOC format (XBL validates ``SMEM_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-clk`` is running), whether the console SE physically drives TX before the OS (the ``boot_logger_uart`` buffer 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 :doc:`/xbl/handoff` 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.bin`` for EL/MMU evidence, the platform memory-map, and UFS/console log strings; parsed GPT and :doc:`/partition-map` for the UFS LUN/LBA layout. :Cross-refs: :doc:`/xbl/handoff` (UEFI-protocol view of the same hand-off), :doc:`/abl/bootlinux` (kernel-entry ABI), :doc:`/partition-map`, :doc:`/open-questions`, :doc:`/soc/storage` (UFS register surface), :doc:`/boot/qup-buses` (GENI/QUP console), :doc:`/soc/clocks` (GCC/RPMh), :doc:`/soc/pinctrl` (TLMM), :doc:`/boot/base-dtb` (GIC/PDC/timer, apps-SMMU).