2.1. ABL overview, key handling, fastboot

abl_a.bin is the Applications Bootloader for the Onyx Boox Note Air5 C: a Qualcomm-signed ELF32/ARM container carrying a UEFI Firmware Volume whose payload is the LinuxLoader UEFI application. It reads the power/volume buttons through the PMIC Power-On (PON) protocol, exposes a fastboot command table with no bootloader-unlock command, and enforces AVB (VB2) verified boot.

2.1.1. Deep dives

This page is the ABL overview. The function-level reverse engineering of the DXE is split across dedicated pages:

2.1.2. Container layout

Occupies a 1 MB partition; used bytes end at 0x27000.

  • PT_LOAD at file 0x3000, vaddr 0x9fa00000, size 0x24000 — a UEFI Firmware Volume whose EFI_FIRMWARE_VOLUME_HEADER starts at that same file offset, 0x3000 (FileSystemGuid, little-endian-parsed: 8c8ce578-8a3d-4f1c-9935-896185c32dd3, the well-known EFI_FIRMWARE_FILE_SYSTEM2_GUID); the literal "_FVH" signature sits 0x28 bytes into the header, at 0x3028.

  • The FV holds one LZMA-compressed GUIDed section starting at 0x3078, which decompresses to 434,376 bytes (../artifacts/abl_a/abl_dxe_fv.bin). That blob is the ABL proper.

  • Inside it: the LinuxLoader UEFI application, PE32+ AARCH64, MZ at 0xb8 / PE at 0xf10, ImageBase=0, sections .text (RVA 0x1000, size 0x4d000), .data (RVA 0x4e000), .reloc.

Because ImageBase=0 and file raw offset equals RVA, the handler RVAs below are also file offsets into the DXE blob minus 0xb8.

2.1.3. Build provenance

The image is a DEBUG build; full assert/log strings are present in a production ABL. The embedded debug path is:

/data/jenkins-agent/workspace/sm6350-15-REL/vendor/out/target/product/NoteAir5C/obj/ABL_OBJ/
  Build/DEBUG_CLANG35/AARCH64/QcomModulePkg/Application/LinuxLoader/LinuxLoader/DEBUG/LinuxLoader.dll
  • SoC = SM6350 (Snapdragon 690 5G), codename “lagoon” — confirmed by the sm6350-… build path and DTB qcom,lagoon / msm-id 0x1b2 (434).

  • DEBUG_CLANG35 / DEBUG build: full assert/log strings are present.

2.1.4. Key handling

ABL uses no gpio-keys / GPIO scan table. It reads buttons through the Qualcomm PMIC Power-On (PON) protocol and decodes the PON reason. Evidence strings in the DXE:

  • PON Reason is 0x%x cold_boot[%d] PON1[%d] KPDPWR[%d] CBLPWR[%d] USB[%d] DC[%d] ChgPresent[%d].

  • Pressed down Power key[%d]., Error locating pmic pon protocol: %r, Error getting pon reason

  • Boot-mode selection is time/press based, not a static table: GetBootIntoModeRecovery Power key Down/Up, BootIntoDload detected, BootIntoFastboot detected, BootIntoRecovery detected, Creating fastboot menu keys detect event, Press volume key to select, and press power key to select.

The physical button map lives in the device tree (../artifacts/boot_a/board.dts), under the PMIC qcom,qpnp-power-on@800 node:

PON node

pon-type

linux,code

Meaning

qcom,pon_1

0 (KPDPWR)

0x74 = 116

KEY_POWER

qcom,pon_2

1 (RESIN)

0x72 = 114

KEY_VOLUMEDOWN

interrupt-names = "kpdpwr", "resin". The button matrix is Power (KPDPWR) + Volume-Down (RESIN); the recovery/fastboot/EDL entry combos are decoded in ABL from PON state plus press timing. No gpio-keys node and no separate Volume-Up PON entry appear in this DTB.

Resolved key/timing handler addresses (RVA, LinuxLoader-relative):

  • 0x1d9a8 = ReadKeyStroke (SimpleTextInputEx) — produces the 2/8/0x102 scancodes.

  • 0x2158 = a gBS->Stall wrapper (100 ms/cycle debounce tick).

  • 0x10708 = reboot-into-EDL: sets UEFI var RESET_PARAM="EDL" then gRT->ResetSystem(EfiResetPlatformSpecific,"EDL") (strings RESET_PARAM``@``0x42e9a, EDL``@``0x42eb2).

  • 0x2618 / 0x2640 = debug-log-level gates (read a debug-config byte; guard every printf).

The full boot-mode dispatch state machine built on top of these (the recovery 5-tap, dload/fastboot hold timers, g_mode_flags bit layout) is in Physical keys: power, volume, and the boot-mode dispatcher, not repeated here.

2.1.5. Fastboot command handlers

2.1.5.1. Static command table (cmd_list)

Located by pointer-scan at DXE file 0x4b978 (RVA 0x4b8c0); 16-byte entries {char *name; fn *handler}. There are 14 real commands (the trailing none / snapshotted belong to an adjacent snapshot-merge-state array, not the command list):

#

command

handler RVA

0

oem enable-charger-screen

0x31c18

1

oem disable-charger-screen

0x31c70

2

oem off-mode-charge

0x31cc8

3

oem select-display-panel

0x31e38

4

oem device-info

0x321bc

5

continue

0x3228c

6

reboot

0x3234c

7

reboot-recovery

0x32388

8

reboot-fastboot

0x323e0

9

snapshot-update

0x32438

10

reboot-bootloader

0x32598

11

getvar:

0x325dc

12

download:

0x32888

13

oem display-cmdline

0x32a74

2.1.5.2. Commands registered outside the static array

flash:, erase:, and boot are registered individually (not via the {name,handler} array), so they do not appear as table rows; their strings/paths are present in the image (erase, FLASH, getvar:partition-type, flashall handling, max-download-size, partition-type:, partition-size:, slot-count, has-slot:*, current-slot, is-userspace, is-logical, erase-block-size, serialno).

2.1.5.3. No bootloader-unlock command is exposed

  • No flashing unlock / flashing lock / oem unlock / oem lock / get_unlock_ability command strings exist in this ABL.

  • Internal unlock plumbing is present but not reachable via fastboot: IsAllowUnlock is %d, Creating unlock keys detect event, Failed to update the unlock status: %r.

  • The standard fastboot flashing unlock path is stripped/disabled by the vendor. Combined with devinfo is_unlocked=0, there is no advertised fastboot path to unlock — independent of the test-key-signing condition below.

2.1.6. Verified-boot enforcement

ABL implements AVB (VB2) and sets device state: androidboot.verifiedbootstate=, boot states green / orange / …, Verity mode: %a, ignore_corruption / restart_on_corruption, SetVerifiedBootHash, Your device is corrupt. It can't be trusted and will not boot., State: Unlocked, AvbSlotVerify returned %a, continue boot. AVB is enforced here, but this ABL binary is test-key-signed and unfused (Secure boot and image signing); whether a re-signed, patched ABL would perform that enforcement just as easily has not been empirically verified here by flashing a patched image.

2.1.7. Provenance

Source:

../_READONLY/lun4/abl_a.bin (read-only); decompressed DXE saved to ../artifacts/abl_a/abl_dxe_fv.bin.

Method:

ELF/FV parsed by hand; LZMA GUIDed section decompressed with Python lzma. LinuxLoader PE parsed (PE32+/AARCH64, ImageBase 0, raw==RVA). cmd_list found by scanning the blob for 8-byte LE pointers equal to command-string VAs; the following qword in each 16-byte record is the handler RVA (all land in .text). Key handling read from DXE strings and the DTB qcom,qpnp-power-on node. Handler RVAs validated by pointer-scan of the LinuxLoader PE.

Cross-refs:

Secure boot and image signing (test-key signing, unlock state), Physical keys: power, volume, and the boot-mode dispatcher (boot-mode state machine), ../artifacts/abl_a/abl_dxe_fv.bin (decompressed ABL UEFI FV/DXE), ../artifacts/boot_a/board.dts (PMIC PON node).