===================================== XBL → ABL hand-off contract (bounded) ===================================== This page answers exactly four questions about how XBL locates, authenticates, and hands control to ABL, and what execution environment ABL inherits. It is **not** a full XBL reverse engineering: DDR training, PMIC sequencing, clock trees and the rest of the XBL/SBL loader are not covered here — a from-scratch ABL replacement does not require modifying XBL. Only the hand-off surface an ABL replacement must satisfy is covered. This page takes the UEFI/DXE-protocol view; the same hand-off at the register level — exception level, MMU/cache state, and the bare addresses/IRQs/clocks/pins of the SoC blocks below the OS — is in :doc:`/boot/below-uefi`. ``xbl_a.bin`` is an AArch64 ELF ``EXEC`` (entry ``0x14817908``, 16 program headers). The XBLCore/Sec loader occupies the ``R E`` LOAD segment at vaddr ``0x14817000`` (file ``0x3000``); the UEFI firmware volume (DxeCore + drivers + the embedded platform config) is the large segment at vaddr ``0x9fc00000`` (file ``0x7e7a0``). Citations below give the file offset and, where it maps cleanly, the loaded vaddr. The build is ``BOOT.XF.3.3-00340`` / XBLCore ``Sec.dll`` (:doc:`/index`). Q1 — Dispatch mechanism (named BDS boot app, not generic FV scan) ================================================================= XBL does **not** generically dispatch "any valid FV/FFS/PE it finds". It runs a platform BDS (Boot Device Selection) that launches one **named** boot application: - ``Loading DxeCore at 0x%10p EntryPoint=0x%10p`` / ``DxeCore returned`` (file ``0xa912f``, UEFI-FD segment ≈ vaddr ``0x9fc2a98f``) — XBLCore loads and enters the standard EDK2 DxeCore, which runs the DXE dispatcher and then BDS. - The embedded platform config carries ``## Default app to boot in platform BDS init`` → ``DefaultBDSBootApp = "LinuxLoader"`` (file ``0xbaf0c`` ≈ vaddr ``0x9fc3c76c``). BDS launches the application whose name is ``LinuxLoader`` — i.e. a targeted launch of a specific app, configured by name, not a blind scan that executes whatever FV happens to be present. - The ABL image is placed in a dedicated reserved region, ``"ABOOT FV"`` at ``0x9FA00000`` (size ``0x200000``; memory-map entry at file ``0xb8c79``), which matches the ABL ``PT_LOAD`` vaddr ``0x9fa00000`` in :doc:`/abl/container`. XBL loads the ``abl`` partition (a Qualcomm-signed ELF, :doc:`/abl/container`) into this region, then BDS/DxeCore starts the ``LinuxLoader`` application from it — which is ``ModuleEntryPoint`` at RVA ``0x1000`` (:doc:`/abl/linuxloader`). So the chain is: **XBLCore → DxeCore dispatcher → platform BDS → StartImage of the named "LinuxLoader" app in the reserved ABOOT FV**. An ABL replacement must present itself as the ``LinuxLoader`` boot app in that FV, not merely be a valid PE somewhere. The dispatch is **by name**, and both ends are recovered — not from the section-stripped XBLCore image, but from ABL's own container. Parsing ``abl_a.bin`` (ELF32 → outer FV, ``EFI_FIRMWARE_FILE_SYSTEM2`` GUID ``8c8ce578-8a3d-4f1c-9935-896185c32dd3``) → the single ``FIRMWARE_VOLUME_IMAGE`` FFS → its LZMA (``ee4e5898-3914-4259-9d6e-dc7bd79403cf``) GUIDed section decompresses (434,376 bytes) to the inner DXE FV, which contains exactly one application file: - FFS type ``0x09`` (``EFI_FV_FILETYPE_APPLICATION``), GUID ``f536d559-459f-48fa-8bbc-43b554ecae8d``, carrying a ``EFI_SECTION_USER_INTERFACE`` (type ``0x15``) section with the UI name **"LinuxLoader"**. The config token stores the app as the *string* ``"LinuxLoader"`` (not a GUID), and the FFS carries a matching UI-section name — so BDS resolves the boot app by its UI name, not by a hard-coded file GUID. A replacement therefore only needs to be an ``EFI_FV_FILETYPE_APPLICATION`` file whose UI section reads ``LinuxLoader``, packaged in the ABOOT FV; carrying the same file GUID ``f536d559-…`` is harmless but not required for name-based dispatch. (The *mechanism* — named-app launch, not generic dispatch — remains what the config token, the DxeCore/BDS load path, and the dedicated ABOOT FV region establish.) Q2 — ABL authentication (ELF hash-segment, SHA-384) =================================================== XBL authenticates ``abl_a.bin`` with the same MBN/ELF **hash-segment** mechanism that PBL uses on XBL (:doc:`/boot/secure-boot`), not a different or stronger scheme: - The XBLCore code segment contains the Qualcomm boot-auth timestamp labels ``bl_hash_seg_auth_timestamp`` (file ``0x6b0f`` ≈ vaddr ``0x1481ab0f``), ``bl_elf_segs_hash_verify_timestamp`` (file ``0x6b54`` ≈ vaddr ``0x1481ab54``) and ``bl_sec_hash_seg_auth_timestamp`` — the standard sequence that authenticates an image's **hash segment** and then verifies each ELF loadable segment against the per-segment hashes in it. - The per-segment hash is SHA-384 and the hash-segment signature chains to the same Qualcomm test attestation root carried by XBL/ABL/TZ — the string ``XBL Sec Attestation Root CA 4`` (file ``0x2beb87`` ≈ vaddr ``0x149503e7``) and ``Generated Test Attestation CA`` appear in XBL, matching the ECDSA-P384/SHA-384 test chain carved from ``abl_a`` in :doc:`/boot/secure-boot`. So XBL→ABL is **hash-table (SHA-384) integrity plus a signature over the hash segment**, exactly the PBL→XBL pattern. As established in :doc:`/boot/secure-boot`, on this unit the root of trust is the public Qualcomm *test* key and ``SEC_BOOT`` is not fused, so re-computing the ABL hash segment (and re-signing with the public test key) is accepted — the authentication is real but not anchored to a secret. This page confirms the *mechanism* by direct evidence rather than by analogy; the *enforcement weakness* is analysed in :doc:`/boot/secure-boot`. **No nested / EL3 sub-image gate on this path.** The Firehose *programmer* container carries a nested EL3 monitor sub-image that PBL signature-enforces *unconditionally*, regardless of ``SEC_BOOT`` (:doc:`/edl/firehose`) — worth ruling out for ABL, since it would defeat the hash-recompute route. It does not apply: ``abl_a.bin`` is a single ELF/MBN (one ELF magic in the partition) — one hash-table segment (``PT_NULL``, ``0x94`` bytes) plus the UEFI FV ``PT_LOAD`` at ``0x9fa00000``, with no embedded EL3 monitor, exception-vector table, or ``smc``/``sec_img`` sub-container (the only ``QSEE`` string is a Keymaster *call* reference in the LinuxLoader payload, not a loadable image). EL3 on this SoC is ``tz_a``, a separately-signed image loaded by PBL/SBL and never embedded in or launched by ABL. So, based on this analysis, a from-scratch replacement faces only the hash gate above. Q3 — Protocols/services published by ABL-dispatch time ====================================================== By the time BDS starts ``LinuxLoader``, DxeCore has dispatched the platform's DXE drivers. The embedded platform config enumerates the enabled feature blocks, and ABL's own consumption (documented on the ABL/power pages) confirms the producers are live: .. list-table:: :header-rows: 1 :widths: 34 66 * - Service (protocol) - Evidence / consumer * - Block/partition I/O — ``EFI_BLOCK_IO`` / ``EFI_PARTITION`` (GPT), plus ``RAM Partition``, ``LogFs`` and (optionally) splash partitions - Config blocks ``## LogFs partition ##``, ``RAM Partition`` / ``RamPartitionTableLib.c``, ``EnableSecurityHoleForSplashPartition``; ABL ``EnumeratePartitions`` (:doc:`/abl/linuxloader`) relies on these. * - Keypad input — ``EFI_SIMPLE_TEXT_INPUT_EX`` (ButtonsDxe) - Config block ``## Buttons / KeyPad ##``; ABL reads keys through this protocol, GUID ``DD9E7534-7762-4698-8C14-F58517A625AA`` — not found as string bytes in this file's own binary, but independently confirmed by direct disassembly at RVA ``0x4dcb4`` in :doc:`/boot/keys`. * - PMIC Power-On — Pmic PON protocol - ``MD_PMIC_PON.BIN`` / ``Pmic PON stat`` / ``boot_smem_store_pon_status``; ABL reads the PON reason via this protocol (:doc:`/abl/container`). * - USB device — QUSB/DWC3 for fastboot/EDL - Config block ``## USB ##``, ``QUSB_BULK`` / ``QUSB_PORT_PRIM``; ABL's ``FastbootInitialize`` uses the USB device protocol (:doc:`/abl/fastboot`). * - Boot/Runtime Services + SMEM/DAL - Standard EDK2 ``gBS``/``gRT`` from DxeCore; ``SMEM`` region and ``smem`` DAL props (``/core/mproc/smem``) initialised before BDS. ABL therefore inherits a fully-initialised DXE environment: GPT partition access (BlockIo/PartitionDxe), keypad input (SimpleTextInputEx), PMIC PON, USB, display (splash), and live Boot/Runtime Services — it does not re-initialise these. Q4 — Reserved memory carve-outs (from XBL's own map) ==================================================== XBL builds the UEFI memory map from an embedded platform table (header ``#MemBase, MemSize, MemLabel(32 Char.), BuildHob, ResourceType, ResourceAttribute, MemoryType, CacheAttributes`` at file ``0xb890a`` ≈ vaddr ``0x9fc3a16a``). The reserved / carve-out regions an ABL replacement must **never** overwrite, taken directly from that table (not inferred from the DTB): .. list-table:: :header-rows: 1 :widths: 20 16 30 34 * - Base - Size - Label - Note * - ``0x80860000`` - ``0x20000`` - ``AOP CMD DB`` - AOP command DB (RPMh); reserved. * - ``0x80900000`` - ``0x200000`` - ``SMEM`` - Shared memory (inter-processor); reserved. * - ``0x86000000`` - ``0x15800000`` - ``PIL Reserved`` - 344 MB Peripheral-Image-Loader carve-out — modem/ADSP (``modem``), compute-DSP (``dsp``), and other PIL images (:doc:`/audio/dsp-firmware`). * - ``0x0C300000`` - ``0x100000`` - ``AOP_SS_MSG_RAM`` - AOP message RAM (device). * - ``0x9F800000`` / ``0x9FA00000`` / ``0x9FC00000`` - ``0x200000`` each / ``0x300000`` - ``FV Region`` / ``ABOOT FV`` / ``UEFI FD`` - XBL's own FV, the ABL load region, and the UEFI firmware device. * - ``0x9FF00000``…``0x9FFFF000`` - various - ``SEC Heap`` / ``CPU Vectors`` / ``MMU PageTables`` / ``UEFI Stack`` / ``Log Buffer`` / ``Info Blk`` - XBL runtime working set and page tables. * - ``0xA0000000`` - ``0x2400000`` - ``Display Reserved`` - Framebuffer/splash region (:doc:`/display/splash`). * - ``0xA2400000`` - ``0x8000000`` - ``Kernel`` - Kernel load window (:doc:`/abl/bootlinux`). Device MMIO windows (``PMIC ARB SPMI`` ``0x0C400000``, ``TLMM`` ``0x0F000000``, ``APSS_GIC*`` ``0x17A00000``, ``QTIMER`` ``0x17C00000``, USB, MDSS/DISP_CC, etc.) are also in the table as ``MMAP_IO`` device regions. .. note:: **TZ/HYP are secure-world and not in this non-secure UEFI map.** TrustZone and the hypervisor are established by PBL/SBL before UEFI and sit in secure carve-outs protected by XPU; they do not appear as entries in XBL's non-secure memory map above (which is why ``tz``/``hyp`` labels are absent here). Their partitions are inventoried in :doc:`/partition-map` and :doc:`/open-questions`; the ``PIL Reserved`` block is the non-secure modem/DSP carve-out. Provenance ========== :Source: ``../_READONLY/lun1/xbl_a.bin`` (read-only). File offsets: ``DefaultBDSBootApp`` ``0xbaf0c``, ``ABOOT FV`` ``0xb8c79``, ``PIL Reserved`` ``0xb8a8b``, memory-map header ``0xb890a``, ``bl_hash_seg_auth_timestamp`` ``0x6b0f``, ``bl_elf_segs_hash_verify_timestamp`` ``0x6b54``, ``Loading DxeCore at`` ``0xa912f``, ``XBL Sec Attestation Root CA 4`` ``0x2beb87``. Loaded vaddrs derived from the ELF program headers (code segment file ``0x3000``→vaddr ``0x14817000``; UEFI-FD segment file ``0x7e7a0``→vaddr ``0x9fc00000``). :Method: bounded string/constant analysis of ``xbl_a.bin`` (``rabin2``/``readelf`` program headers; ``strings`` + byte-offset ``grep`` for the config, memory-map table and boot-auth timestamp labels). Each of the four questions is answered from a concrete offset in the binary rather than inferred by analogy; the SHA-384/test-chain enforcement semantics are cross-checked against the certs carved in :doc:`/boot/secure-boot`. No full XBL disassembly was performed; the section-stripped XBLCore limits recovery of the exact FFS app GUID (:doc:`/open-questions`). :Cross-refs: :doc:`/boot/secure-boot` (PBL→XBL hash gate, test-key chain), :doc:`/abl/container` (ABL container, ABOOT FV vaddr), :doc:`/abl/linuxloader` (``ModuleEntryPoint``), :doc:`/abl/bootlinux` (kernel window), :doc:`/boot/keys` (ButtonsDxe/SimpleTextInputEx), :doc:`/partition-map`, :doc:`/index`, :doc:`/open-questions`.