13. Open questions and limits of analysis

Scope of this page is the boot chain and hardware below Android userspace. It records which questions the static, single-dump analysis cannot answer, why, and what access would resolve each. Every partition below Android userspace has been opened or accounted for; the remaining unknowns are values that exist only at runtime or in silicon, not in any partition.

Each hardware-silicon question below has been driven to its exact static limit: everything the images do contain (register maps, code paths, config bytes, the precise structural reason a value is absent) has been extracted, so the residual is only the physical read itself. One item (OQ5, the PON reset-type enum) turned out to be fully determined by architecture and is no longer live-gated. The per-item static end, exact residual and read procedure are in Static end of the hardware-silicon ropes.

13.1. Open questions

#

Question

Status

Resolution path

1

Exact VolDown EFI scancode

Inferred SCAN_DOWN = 0x02. Provider is XBL ButtonsDxe, which builds its map at runtime — ConfigureButtonGPIOs() + InitializeKeyMap() then locates PmicPONProtocol (PmicDxe) and PollButtonKeys() — so there is no static scancode literal by construction. ABL carries no scancode assignment (only a printf uses 0x102). Convention + the sole DTB RESIN→KEY_VOLUMEDOWN fix it at 0x02.

Observe the key event on a live device (non-critical).

2

XBL SBL1 fedl / blue-LED exact branch

Getter→branch edge is in a runtime-populated GOT with no static resolution (0 of 1643 ADRPs reach the relevant string pages). An EDL peek of the GOT slot on 2026-09-19 was inconclusive/likely negative (EDL runs a different PBL branch than XBL→ABL, so a normal-boot GOT value isn’t expected to survive into it). Full detail: OQ2 under Static end of the hardware-silicon ropes.

A live memory read during a normal (non-EDL) boot — e.g. a JTAG/debug halt after XBL relocation but before ABL hand-off — not an EDL peek, which runs a different PBL branch entirely.

3

D+→GND electrical outcome

Whether a hard D+→GND short yields chgr_type_det_errfedl on this Type-C board is an electrical question.

Bench cable + serial/EDL observation.

4

PMIC S1 reset-timer OTP default (the ~8 s)

Narrowed to the S1 timer alone: XBL writes reset type/enable and the RESIN S2 timer, but leaves both S1 timers and the KPDPWR S2 timer at PMIC OTP default. Full detail: OQ4 under Static end of the hardware-silicon ropes.

PMIC OTP read (SPMI) or UART.

5

PON S2 reset-type field 0x08 enum name

Resolved (deterministic). The QPNP 4-bit S2 reset-type field admits only 1=WARM_RESET, 4=SHUTDOWN, 5=DVDD_SHUTDOWN, 7=HARD_RESET, 8=DVDD_HARD_RESET, so 0x08 is DVDD_HARD_RESET; only the ASCII name is absent from the binary. No live read needed.

None — architecturally fixed.

6

Secure-boot fuse state (SEC_BOOT / OEM_PK_HASH)

SEC_BOOT not enforced (Firehose fuse read and secure-boot confirmation, Platform config (uefiplat.cfg)); OEM_PK_HASH read non-zero via Sahara (EDL / Firehose interface); the raw QFPROM security corner still faults on peek. Full detail: OQ6 under Static end of the hardware-silicon ropes.

Done via Sahara CMD_EXEC. QFPROM peek cross-check still faults.

8

XBL→ABL boot latency (behind the “~8 s” recovery hold)

Live-read, 2026-09-19 (EDL peek). boot_stats at 0x146aa6b0 is only partially populated — live per-boot tick counters in some slots, never-written poison markers in others (XBL diverts to Sahara/9008 before reaching those KPI stages). Offset→timestamp-name attribution is unresolved. Full detail: OQ8 under Static end of the hardware-silicon ropes.

Further live reads to map field order to name (e.g. correlate against boot_logger_uart.c output over the SE9 UART, Resolved by targeted reverse-engineering item 4), or accept the partial-population result as the static-end.

11

Matching Android-11 ABL source tag

Advanced by RE. The ABL binary self-identifies its build tree: 41 embedded Jenkins paths, all rooted at /data/jenkins-agent/workspace/sm6350-15-REL/vendor/bootable/bootloader/edk2/ (QcomModulePkg + ArmPkg/MdePkg/MdeModulePkg + bundled libavb), so provenance is a specific vendor tree named ``sm6350-15-REL``, not the QSSI12 proxy. No public source drop under that name is known to exist; structural correlation still uses the newer CodeLinaro tag LA.UM.9.12.1.r2-05100-SMxx50.QSSI12.0 and treats the binary as authoritative (see ABL function map and upstream-source correlation). A from-scratch replacement needs no upstream tag.

Onyx/CAF publishing the sm6350-15-REL tree; otherwise not required.

Rows 7 (Firehose programmer availability), 9 (“modem” MPSS = ADSP, not cellular) and 10 (userdata out of scope) were resolved and have been retired from this table; their findings live in Firehose fuse read and secure-boot confirmation, ADSP and CDSP firmware and Partition map and checksums respectively. Surviving row numbers are left unchanged so existing OQ2/OQ4/OQ6/OQ8/OQ11 cross-references stay valid.

The runtime-log route is closed: rawdump.bin and logdump.bin are 100% zero and logfs.bin is an empty FAT12 volume (MSDOS5.0 / LOGFS, no logs), so no captured boot log exists to recover runtime values.

13.2. Resolved by targeted reverse-engineering

These items concern what a minimal ABL replacement still needs to know. Each was closed statically from the dump in ../_READONLY/ — no live device required.

  1. XBL→ABL app-dispatch mechanism and the LinuxLoader FFS identity. Resolved by parsing abl_a.bin (not XBLCore): the inner DXE FV holds one EFI_FV_FILETYPE_APPLICATION file, GUID f536d559-459f-48fa-8bbc-43b554ecae8d, with an EFI_SECTION_USER_INTERFACE name “LinuxLoader”. BDS dispatches by that UI name (the config token is the string "LinuxLoader", not a GUID). A replacement must be an application FFS whose UI section reads LinuxLoader in the ABOOT FV; the file GUID need not match. See XBL → ABL hand-off contract (bounded) Q1.

  2. No nested / EL3-enforced sub-image in the ABL path. abl_a.bin is a single ELF/MBN: one hash-table segment (PT_NULL, 0x94 bytes) plus the UEFI FV PT_LOAD at 0x9fa00000; only one ELF magic in the partition, and no embedded EL3 monitor / vector table / smc-container (the sole QSEE string is a Keymaster call reference, not a payload). The nested-EL3 signature wrinkle proven for the Firehose programmer container does not apply to XBL→ABL: EL3 here is tz_a, signed and loaded separately by PBL. So a rehashed, test-key-signed replacement faces only XBL’s integrity/hash gate (unfused, bypassable — Secure boot and image signing).

  3. GPT partition-type GUIDs. Extracted directly from gpt_main{0..5}.bin for all 6 LUNs (type GUID, unique GUID, and disk GUID per partition). The full table belongs in Partition map and checksums; notable is that every _b slot shares one placeholder type GUID 77036cd4-03d5-42bb-8ed1-37e5a88baa34 while each _a slot carries a distinct type GUID. Name-based lookup (as stock ABL does) needs none of this; it is here for a GUID-based replacement.

  4. Console UART pinout. The active console is the DTB node qcom,qup_uart@98c000compatible = "qcom,msm-geni-console", status = "ok", QUPv3 SE9, reg = <0x98c000 0x4000>, GIC SPI 0x164. Its pin group qupv3_se9_2uart muxes GPIO25 = TX, GPIO26 = RX (TLMM function qup13_f2, 2 mA, 2-wire, no CTS/RTS), 115200 8N1 (console=ttyMSM0). The live /chosen/bootargs sets earlycon=msm_geni_serial,0x98c000 to match. Note the boot_a image header carries a stale earlycon=…,0x888000 — but 0x888000 is SE2, wired as i2c@888000/spi@888000 on this board, and the second console-compatible node @984000 (SE8) is status = "disabled"; the DTB /chosen overrides the stale value at runtime, so 0x98c000 is the real port. XBL contains boot_logger_uart.c and a UARTLogBufferSize log buffer, so probing GPIO25/26 is the concrete channel to capture live XBL/ABL boot output — the resolution path behind OQ8 (boot latency) and a live-observation route for OQ2/OQ4/OQ5. Physical test-point location on the PCB is still unverified (requires opening the device).

13.3. Low-level components examined

All components carrying a signing chain are test-key-signed (General Use Test Key (for testing only)), consistent with Secure boot and image signing.

TZ (tz_a, TZ.XF.5.10-00304-1)

QSEE. Config-item names /secboot/anti_rollback, allow_erase_in_secure_mode, oem_image_encryption_key1_sel / oem_image_encryption_key1 (selectors/names, not key material — keys are fused/runtime). Carries the QSEE attestation keybox (QSEE Attestation Root CA 4 SubCA 1). No plaintext keys or secure-boot fuse value.

HYP (hyp_a, TZ.XF.5.10-00304-1, OEM=CRM)

Qualcomm hypervisor; camera stream/PHY secure protection (CameraSS_DynamicPHYProtect), XPU region unlock plumbing. Does not change the boot-chain findings.

AOP (aop_a, AOP.HO.2.0-00069)

Always-On Processor; build-dated 2024-10-28 (UUID Q_SENTINEL_{…}_20241028_1806). JTAG_ON / JTAG_OFF power-collapse gating of JTAG, IPCC. Power/sleep RSC firmware; no boot-mode or security state of interest.

modem (modem_a, ADSP.VT.5.6-00702.1-BITRA-1, variant bitra.adsp.prodQ)

A multi-subsystem NON-HLOS bundle (ADSP + CDSP + MPSS + NPU), not an ADSP-only image: the ADSP sub-image runs sensors/audio, and real MPSS baseband code is present but dormant (no cellular RF front end). The XML block it carries is ePDG / VoWiFi PDN-throttling config, not thermal. Full breakdown in ADSP and CDSP firmware.

DSP (dsp_a, CDSP.VT.2.6-00570.1-BITRA-1, built 2024-02-07, bitra.cdsp.prodQ)

Compute DSP (Hexagon, C++), SecurePD example. No boot-relevant config.

devcfg (devcfg_a)

SoC security/memory config: XPU access control (/ac/xpu, disable_xpu_ac), camera boot protection (enable_cam_phys_boot_protection, boot_protected_cam_phys), /dev/hyp_config_oem, NoC config, and a Widevine OEMCrypto TZ path (tzdrm/widevine_oemcrypto) implying Widevine L1 DRM via TrustZone. Config, not state.

featenabler (featenabler_a)

The feature-license TZ app (feature license app init, cmnlib) — enables SoC features via signed licenses. Test-key chain.

uefivarstore

Standard UEFI Secure Boot variables (KEK, SetupMode, SecureBoot, dbx) plus counters (BSPowerCycles ≈ 1, RunCycles), indicating a near-factory state. This is UEFI-level Secure Boot, orthogonal to the Qualcomm QFPROM root of trust; it contains no AVB device-state/unlock/verifiedbootstate (those live in devinfo / vbmeta).

Blank / empty (verified)

rawdump (0%), logdump (0%), logfs (empty FAT12), misc/BCB (empty, no pending boot command), apdp (0% — no debug policy stored), secdata (0%), keystore (0%), cdt (0%). mdtp_a has no readable strings (opaque anti-theft image).

ext4 data partitions

persist (sensor calibration / per-device data, incl. the IMU factory calibration and QSEE secure-storage blobs), metadata (FBE metadata-encryption keystore) and onyxconfig (Onyx device-config fs, incl. the factory production-test record) were all extracted and are documented in Partition map and checksums and The Onyx/Boox platform layer. super was likewise extracted down to its four logical partitions (vendor_a/system_a/product_a/ system_ext_a) and is the source for the entire Android userspace (bridge to the firmware) tree. Only userdata remains untouched — it is not present in this dump at all (a factory/EDL backup does not carry user data).

13.4. Boot-chain firmware versions

Full version inventory (XBL/AOP/TZ/HYP/modem, build provenance) is in Onyx Boox Note Air5 C (Qualcomm SM6350); ADSP/CDSP versions and their catalog of capabilities are in ADSP and CDSP firmware; kernel version is in Boot image: kernel, DTB, ramdisk, config.

13.5. Static end of the hardware-silicon ropes

For each hardware-silicon question, the point where static analysis of the dump provably stops — the mechanism recovered, and the single value that can only come from silicon or a live read.

13.5.1. OQ6 — secure-boot / QFPROM fuses

Recovered statically. The QFPROM window is 0x780000/0x7000 (DTB qcom,qfprom, read-only). Linux is given only three binning fuse rows — gpu_speed_bin@6015 (8 bits), feat_conf8@6024 (4 bytes), gpu_gaming_bin@6026 (bit 5) — plus the USB-PHY trim row 0x780268 (3 bits at pos 0x19, via the qusb@88e3000 efuse_addr). The security corner is not mapped to the kernel at all. XBL’s config plane asserts SecurityFlag = 0xC4 (LoadKeymaster|LoadSecApp|CommonMbnLoad; SecBootEnableFlag bit clearPlatform config (uefiplat.cfg)). ABL’s runtime read path is ReadSecurityState → SCM ScmSipSysCallis_secure → prints SECURE BOOT - <state> / DEVICE STATE - <state>; GetFuse/SetFuse are SCM protocols; KeyMasterSetRotAndBootState writes TZ_HLOS_IMG_TAMPER_FUSE / TZ_HLOS_TAMPER_NOTIFY_FUSE. Anti-rollback is AVB Read/WriteRollbackIndex per location + TZ_UPDATE_ROLLBACK_VERSION_ID, stored in DeviceInfo / devinfo.binall-zero here (factory).

Residual (silicon): the fuse bits themselves — SEC_BOOT enable and OEM_PK_HASH. Read by: runtime ReadSecurityState or Sahara CMD_EXEC (OEM_PK_HASH already read non-zero, EDL / Firehose interface); a raw QFPROM peek at 0x780000 faults (XPU-protected) — reconfirmed live, 2026-09-19, with a second independent peek-capable loader (USBError(5), identical to the original finding).

Live-read, 2026-09-19 (``adb shell getprop``, no root). ro.boot.flash.locked = 1, ro.boot.verifiedbootstate = green, ro.boot.veritymode = enforcing. This isn’t the raw QFPROM bit, but it answers the practical question these properties exist for: AVB (software verified boot, via ABL’s bundled libavb) actively checks vbmeta against a real key and passes (green, not orange/unverified) on the stock image, and dm-verity is enforcing on /system. Consistent with — and independent confirmation of — the ABL device_info.is_unlocked = 0 finding (AVB enforcement code path (LoadImageAndAuth / libavb)) and the frp OEM-unlock byte reading 0 (Security and DRM userspace): three independently-read signals now agree the unit is locked at the software/AVB layer, even though the QFPROM SEC_BOOT fuse itself (the hardware root of trust) is not blown. Prediction for a hypothetical replacement bootloader, not something actually tested here: AVB would reject a resigned/modified boot/system under the stock ABL+vbmeta chain, but since ABL itself is unfused and integrity-only (Secure boot and image signing), replacing ABL should remove the AVB check entirely rather than requiring it to be defeated — this follows logically from the above findings but has not been verified by actually building and booting a replacement ABL.

13.5.2. OQ4 — PMIC S1 reset-timer default (the ~8 s)

Recovered statically. Byte-read of the xbl_config PON table (PMIC reset timers, charging and reachability): XBL writes 0x842=0x08/0x843=0x80 (KPDPWR S2 type+enable), 0x84A=0x08/0x84B=0x80 (RESIN S2 type+enable), 0x849=0x06 (RESIN S2 timer), 0x85A=0x08 (PS_HOLD), 0x862/0x863 (gen2 S3). It does not write the S1 timers (0x840, 0x848) or the KPDPWR S2 timer (0x841) — those keep the PMIC OTP default. Master PON is PM6350@USID0 (PMIC reset timers, charging and reachability).

Residual (silicon): the S1-timer OTP magnitude that sets the ~8 s hold-to-reset ceiling. Read by: PMIC OTP/PBS read over SPMI, or timing a live hold.

13.5.3. OQ5 — PON reset-type 0x08 enum

Fully determined — no residual. The 4-bit QPNP S2 reset-type field admits only 1=WARM_RESET, 4=SHUTDOWN, 5=DVDD_SHUTDOWN, 7=HARD_RESET, 8=DVDD_HARD_RESET, so 0x08 is DVDD_HARD_RESET. The binary simply carries no ASCII enum string.

13.5.4. OQ8 — XBL→ABL boot latency

Recovered statically. Shared IMEM base 0x146aa000 (DTB + uefiplat SharedIMEMBaseAddr); boot_stats at @6b0``0x146aa6b0`` (32 B). XBL logs nine named KPI timestamps — pbl_apps_init_timestamp, bootable_media_detect_timestamp, bl_elf_metadata_loading_timestamp, bl_hash_seg_auth_timestamp, bl_elf_loadable_segment_loading_timestamp, bl_elf_segs_hash_verify_timestamp, bl_sec_hash_seg_auth_timestamp, bl_sec_segs_hash_verify_timestamp and pbl_populate_shared_data_and_exit_timestamp — through boot_logger_{ram,timer,uart}.c; ABL adds Load Image %a total time: %lu ms.

Live-read, 2026-09-19 (EDL peek). Two independent 32/40-byte reads at 0x146aa6b0 (across two separate adb reboot edl cycles) each show the same pattern: 5 of 8-9 u32 slots hold small, plausible tick values that differ slightly between the two reads (e.g. 0x00024fcb``→``0x00024f6a, 0x0002f8fa``→``0x0002f8a4), consistent with a genuine live per-boot counter rather than static/cached data. The remaining slots are high-entropy, and one decoded to the literal pattern ``0xdead4ead`` — a poison/debug marker — confirming those fields are simply never written on the EDL boot path (XBL diverts to Sahara/9008 before reaching whatever KPI stage(s) populate them), not a bad read. This closes “is the struct live and readable” definitively; it does not close “which offset is which named timestamp” (the 9 names are known from strings, their field order isn’t).

Residual (runtime, narrowed): the offset→name mapping, and the timestamps for a normal (non-EDL) boot specifically, since EDL only exercises a subset of the KPI stages. Read by: a SE9-UART capture during a normal boot (GPIO25 TX / GPIO26 RX, 0x98c000Resolved by targeted reverse-engineering), which would give both the values and, via the printed KPI names, the offset order.

13.5.5. OQ2 — XBL SBL1 fedl / blue-LED branch

Recovered statically. ELF has 16 program headers; the charger getter’s GOT slot 0x148b81f0 lies in PT_LOAD segment 5 (vaddr 0x1487c000, memsz 0x3d000, filesz 0 — a .bss zero-filled at load, populated by the loader). The getter 0x80735700 and detect loop 0x8074651c are in the file-backed RX segment (0x80735000``+``0x4eeef). A capstone sweep of the RX segments finds 0 of 1624 ADRPs (0 ADR, 0 64-bit literals) reaching the fedl/LED string pages 0x1481d000 / 0x1481f000. Recovered anyway: the fedl reason set — pmi_not_detected, vbus_det_err, vbus_low, chgr_type_det_err, chgr_det_timeout — the blue-LED string not power_key_press, blue led on! (~``0x1481fb13``), and the fully static dload path (DloadCookieAddr = 0x01FD3000 / value 0x10).

Live peek attempted, 2026-09-19 — inconclusive/likely negative. EDL peek of 0x148b81f0 (8 B) returned 0x1483db2c: not in XBL’s RX code segment (0x80735000``+) and adjacent to the address band the EDL programmer's own nested EL3 image occupies (``0x14950000, Firehose fuse read and secure-boot confirmation), so this value most likely belongs to the current Sahara/Firehose session’s own use of that physical memory, not a GOT entry surviving from a prior normal boot. EDL is architecturally a separate PBL branch from XBL→ABL, so this was always a long shot; it does not change the static-end analysis above.

Residual (runtime): the getter→branch edge through the runtime-populated GOT. Read by: a live memory read of the GOT during a normal boot specifically (e.g. JTAG halt after XBL relocation, before ABL hand-off) — not an EDL peek.

13.5.6. OQ1 — VolDown scancode

Recovered statically. Provider is XBL ButtonsDxe: ButtonsInit runs ConfigureButtonGPIOs() + InitializeKeyMap(), locates PmicPONProtocol (PmicDxe), and PollButtonKeys() feeds the SimpleTextInputEx ABL reads. The map is built programmatically, so there is no static scancode literal by construction; ABL carries no scancode assignment (only a printf uses 0x102).

Residual (runtime, non-critical): the exact byte. Convention + the sole DTB RESIN→KEY_VOLUMEDOWN fix VolDown at SCAN_DOWN = 0x02 (Physical keys: power, volume, and the boot-mode dispatcher).

13.5.7. OQ3 — D+→GND electrical outcome

Recovered statically. USB HS PHY is qusb@88e3000 (qusb2phy-v2), with eud_enable_reg = 0x88e2000. XBL’s BC1.2 charger classification is fully readable — SDP/CDP/DCP sources, usb_dp_toggled_for_cdp, APSD re-run, detect loop 0x8074651c (CDP = two D+ toggles) → on failure chgr_type_det_errfedl.

Residual (bench): the analog response of the BC1.2 front-end to an out-of-spec D+→GND short — whether it presents as chgr_type_det_err. Read by: a bench cable + serial/EDL observation.

13.6. Requires a live device or bench — summary

After the above, exactly these residuals remain, none in any partition. Two (OQ8, OQ2) were live-peeked over EDL on 2026-09-19 with a user-supplied peek-capable loader — see each item’s entry above for what that did and didn’t resolve:

  1. QFPROM security fusesSEC_BOOT enable (OQ6); runtime ReadSecurityState during a normal boot, or SE9-UART capture of the printed state. (OEM_PK_HASH itself is already read, and the QFPROM peek fault is now twice-confirmed live — see OQ6 above.)

  2. PMIC S1-timer OTP default — the ~8 s ceiling (OQ4); SPMI OTP read (no flat peek address available, and explicitly bus-hang risk) or a timed hold.

  3. ``boot_stats`` offset→name mapping, and normal-boot timestamp values (OQ8, narrowed) — the struct is confirmed live and partially populated on the EDL path (2 EDL peeks done); a normal-boot SE9-UART capture is what’s left.

  4. Runtime GOT contents from a *normal* boot specifically (OQ2, narrowed) — an EDL peek was tried and is inconclusive/likely negative (EDL runs a different PBL branch than XBL→ABL); needs a live read during an actual XBL→ABL boot (e.g. JTAG), not EDL.

  5. D+→GND analog outcome — bench cable + serial/EDL (OQ3).

  6. VolDown scancode confirmation — a keypress on a live device (OQ1, non-critical).

(OQ5, the reset-type enum, is architecturally determined and needs no read.)

Source:

static analysis of the EDL dump in ../_READONLY/; component version tags and partition contents from the dumped images.

Cross-refs:

Secure boot and image signing, Firehose fuse read and secure-boot confirmation, Onyx Boox Note Air5 C (Qualcomm SM6350), PMIC reset timers, charging and reachability, EDL / 9008 entry and the deep-flash cable.