1.2.1. 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 Below UEFI — execution state and hardware register surface.

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 (Onyx Boox Note Air5 C (Qualcomm SM6350)).

1.2.1.1. 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 initDefaultBDSBootApp = "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 ABL overview, key handling, fastboot. XBL loads the abl partition (a Qualcomm-signed ELF, ABL overview, key handling, fastboot) into this region, then BDS/DxeCore starts the LinuxLoader application from it — which is ModuleEntryPoint at RVA 0x1000 (ABL entry point and top-level orchestration).

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.)

1.2.1.2. 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 (Secure boot and image signing), 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 Secure boot and image signing.

So XBL→ABL is hash-table (SHA-384) integrity plus a signature over the hash segment, exactly the PBL→XBL pattern. As established in Secure boot and image signing, 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 Secure boot and image signing.

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 (Firehose fuse read and secure-boot confirmation) — 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.

1.2.1.3. 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:

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 (ABL entry point and top-level orchestration) 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 Physical keys: power, volume, and the boot-mode dispatcher.

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 (ABL overview, key handling, fastboot).

USB device — QUSB/DWC3 for fastboot/EDL

Config block ## USB ##, QUSB_BULK / QUSB_PORT_PRIM; ABL’s FastbootInitialize uses the USB device protocol (Fastboot handler internals (FastbootLib)).

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.

1.2.1.4. 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):

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 (ADSP and CDSP 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.

0x9FF000000x9FFFF000

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 (Splash partition).

0xA2400000

0x8000000

Kernel

Kernel load window (Kernel/DTB/ramdisk load and the kernel hand-off).

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 Partition map and checksums and Open questions and limits of analysis; the PIL Reserved block is the non-secure modem/DSP carve-out.

1.2.1.5. 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 Secure boot and image signing. No full XBL disassembly was performed; the section-stripped XBLCore limits recovery of the exact FFS app GUID (Open questions and limits of analysis).

Cross-refs:

Secure boot and image signing (PBL→XBL hash gate, test-key chain), ABL overview, key handling, fastboot (ABL container, ABOOT FV vaddr), ABL entry point and top-level orchestration (ModuleEntryPoint), Kernel/DTB/ramdisk load and the kernel hand-off (kernel window), Physical keys: power, volume, and the boot-mode dispatcher (ButtonsDxe/SimpleTextInputEx), Partition map and checksums, Onyx Boox Note Air5 C (Qualcomm SM6350), Open questions and limits of analysis.