Phase 03a — Custom UEFI ABL
Status: ✅ Complete — v2.4 stable. Source: LA.UM.7.2.c25 branch of clo/la/abl/tianocore/edk2 (QcomModulePkg).
Why a Custom ABL?
- Stock ABL:
fastboot flash/fastboot boothang at “Sending” — bulk data transfer path broken - Stock ABL:
fastboot oemreturns “unknown command” - Boot mode selection (TWRP vs Android) needed for daily use
- Secure boot is off (fuses not provisioned) — Onyx ships their production ABL signed with qtestsign test keys. Any qtestsign-signed image works.
ABL Version History
| Version | Key Change | Outcome |
|---|---|---|
| v1.0 | Baseline LA.UM.7.2.c25, VERIFIED_BOOT=0 | ❌ FDE bootloop — TrustZone RoT call missing |
| v1.1 | VERIFIED_BOOT=1 | ❌ 05c6:f000 diagnostic mode — AVB1 fails on Magisk-patched boot |
| v1.2 | Cmdline injection (VB params hardcoded) | ❌ FDE loop persists — cmdline not the root cause |
| v1.3 | VBSendRot + EnableDisplayMenu=FALSE + oem reboot-edl | ✅ FDE resolved, display fix, EDL escape works |
| v1.4-v1.6 | USB DMA buffer experiments | ❌ Fastboot bulk hang unresolved; broke getvar |
| v2.0 | Clean source: reverted all flashing fixes, kept v1.3 advances | ✅ Android boots, ADB works |
| v2.1 | Hall sensor GPIO 105 (south tile TLMM) for boot mode selection | ❌ Data abort — raw MmioRead32 on unmapped address |
| v2.2 | GCD memory mapping before MMIO + graceful fallback | ✅ Hall sensor reads work without crash |
| v2.3 | Boot counter logic: 2 consecutive normal boots → Android; cover closed → TWRP | ✅ Boot mode selection fully functional |
| v2.4 | Stability fixes; current stable release | ✅ Confirmed stable — all features working |
Critical Lessons
qtestsign MUST use -v 5 for SDM636
The default -v 3 produces a hash segment that XBL silently rejects — device drops straight to EDL 9008 with no diagnostic output. Always use qtestsign -v 5 abl. Use tools/abl-build which handles this automatically.
Never use raw MmioRead32 without GCD memory mapping
ABL v2.1 used MmioRead32(0x03069004) for TLMM GPIO. The address was not in the UEFI memory map → data abort → ABL crash → device bricked. Recovery required full battery drain + cold-boot PBL 9008. Always call gDS->GetMemorySpaceDescriptor() first; add via AddMemorySpace() + SetMemorySpaceAttributes(EFI_MEMORY_UC) if unmapped.
Fastboot bulk hang = USB hub / autosuspend (not ABL)
After 6+ ABL builds failing to fix “Sending” hang, usbmon capture revealed: the device disconnects from the USB hub before any bulk data is transmitted. The hub’s autosuspend (2s) drops the port during the interactive diagnostic prompt gap. On direct connection with autosuspend disabled, the hang has not been reproduced. All v1.0–v1.6 “Sending” hangs were likely this same disconnect pattern.
Build Infrastructure
tools/abl-build <version>— mandatory wrapper: Docker build + qtestsign -v 5 in one step. Never build or sign manually.tools/docker/abl-builder/Dockerfile— Ubuntu 20.04 + clang + aarch64-linux-gnu + python2 + cryptography- Build flags:
VERIFIED_BOOT=0,USER_BUILD_VARIANT=0(DEBUG),BOARD_BOOTLOADER_PRODUCT_NAME=NoteAir - Output:
builds/abl/abl-v<N>.elf
EDL PBL Timing Rules
- Blacklist qcserial:
/etc/modprobe.d/no-qcserial.conf— otherwise qcserial claims the Sahara interface within ~850ms - Start edl-run before plugging in: PBL sends HELLO in a narrow ~1-2s window after USB enumeration, then goes silent
- One write per Sahara session: second EDL invocation reuses programmer with broken GPT state