====================================================== AOP — the Always-On Processor (RPMh / power back-end) ====================================================== ``aop_a`` is the firmware for the **Always-On Processor**, a small Cortex-M micro-controller in the SoC's always-on (AOSS) power island. It is loaded and authenticated by XBL's PIL very early (before UEFI) and keeps running underneath every later stage — UEFI, ABL, the kernel, and system sleep (the evidence that this makes it load-bearing, and how strongly it supports that conclusion, is under `Relevance to a bootloader replacement`_ below). This page is the AOP-side counterpart to the AP-side interface documented in :doc:`/boot/base-dtb`: there, the kernel's ``qcom,rpmh-rsc`` votes for clocks and regulators through TCS command slots and resolves resource names through ``qcom,cmd-db``; **here** is the processor that services those votes. Everything below is read from ``_READONLY/lun4/aop_a.bin`` (program headers, the Cortex-M vector table, a Thumb disassembly of the reset path, and an image-string census); no code was executed. Identity ======== - ``QC_IMAGE_VERSION_STRING = AOP.HO.2.0-00069`` - ``IMAGE_VARIANT_STRING = AAAAANAZO`` (Version tag also inventoried in :doc:`/index`.) Image structure and Cortex-M evidence ===================================== ELF32, ``e_machine = 40`` (EM_ARM), 7 program headers, MBN-wrapped: .. list-table:: :header-rows: 1 :widths: 8 14 16 14 48 * - PH - Flags - vaddr - filesz - Role * - 0 - ``0x07000000`` - — - 114 - MBN **hash-table** segment (per-segment SHA-384) * - 1 - ``0x02200000`` - ``0x8081d000`` - ``0x1a60`` - **signature + cert chain** (test-key, see :doc:`/boot/secure-boot`) * - 2 - ``R-X`` - ``0x0b000000`` - ``0x142f4`` - **code** (the AOP program, ~81 KiB) * - 3 - ``RW-`` - ``0x0b0e0000`` - ``0x65b8`` - private data (RAM adjacent to code) * - 4 - ``RW-`` - ``0x80800000`` - ``0x8d50`` - shared DDR message-RAM window * - 5 - ``RW-`` - ``0x80810000`` - ``0x10e0`` - shared DDR message-RAM window * - 6 - ``RWX`` - ``0x80818000`` - ``0x4120`` - shared DDR message-RAM window (executable scratch) **Cortex-M, Thumb.** The code segment begins with a Cortex-M vector table: - word[0] = initial **SP = ``0x000E8000``** (AOP internal SRAM) - word[1] = **reset vector = ``0x00000009``** → internal address ``0x8`` with the Thumb bit set. The ELF ``e_entry`` is ``0xb000009`` — the *same* reset handler expressed at the PIL-visible load alias: AOP executes from its own ``0x0``-based address space, and the ELF maps that code to vaddr ``0x0b000000`` for loading, so ``e_entry`` = ``0x0b000000 + 0x8 | 1``. Disassembling the entry as Thumb yields a textbook two-stage C startup and an init loop:: 0x0b000008: ldr r0, [pc, #4] ; -> C runtime init 0x0b00000a: blx r0 0x0b00000c: ldr r0, [pc, #4] ; -> main 0x0b00000e: bx r0 ... 0x0b000018: push {r3-r7, lr} ; init loop: iterate a 5-entry 0x0b000020: cmp r6, #4 ; handler table at [r7], 0x0b000022: bls 0x0b000028 ; calling 0x0b0116ce per entry 0x0b000032: bl 0x0b0116ce The three ``0x808xxxxx`` RW/RWX segments are **not** private AOP memory — they sit inside the ``xbl_aop_mem`` carve-out the AP publishes in its device tree (``0x80700000`` size ``0x160000`` → ``0x80860000``; :doc:`/boot/base-dtb`), with the RPMh **cmd-db** region at ``0x80860000`` immediately above. This is the shared message RAM through which the AP and AOP exchange resource state. What the AOP manages ==================== The image's string tables name the resource domains and services the AOP runs. These are the RPMh/AOSS back-end functions: RPMh **ARC** voltage/clock resources Rail and clock domains each exposed with a ``.lvl`` (voted level/corner) plus internal ``.mol`` / ``.tmr`` state. The full set is recovered from the resource-name pool at image offset ``0xb011c40``: ``cx`` (digital core rail), ``mx`` (memory rail), ``mmcx`` (multimedia Cx), ``lcx`` / ``lmx`` (the "low" Cx/Mx variants), ``gfx`` and ``gpu`` (GPU), ``ebi`` (DDR I/O rail), ``ddr``, ``mss`` (modem), ``qphy`` (a PHY rail) and ``xo`` (crystal oscillator). When the kernel votes through ``rpmh-rsc``, the AOP arbitrates the aggregate request and drives the PMIC to the resulting corner. **VRM / CPR / ACD** regulator sublayer Below the ARC corners, the strings ``vrm``, ``vrm_client``, ``vrm_tcs``, ``arc`` / ``arc_override``, ``m.cx``, ``vrm.mx``, ``bob`` (a boost-bypass regulator), ``limits``, ``acd`` (Adaptive Clock Distribution) and ``cpr`` / ``cprv1`` / ``cprv2`` / ``cprwa`` name the **VRM** (Voltage Regulator Manager) that turns a voted ARC corner into concrete PMIC regulator settings, closed around **CPR** (Core Power Reduction — the process/temperature-adaptive voltage loop) with an ``acd`` clock-stretch companion. RPMh **TCS command sequences** The actual write-command sequences the AOP emits are carried in **Trigger Command Set** slots: ``vrm_tcs`` (to the VRM/PMIC) and ``pdc_tcs`` (to the wake-up controller, below). ``ERR:TCS0`` / ``ERR:TCS1`` are the error tokens logged when a sequence on TCS ring 0/1 fails or times out; ``QMP_TOUT`` guards the AP↔AOP mailbox. So a vote arrives over QMP / shared RAM, the AOP aggregates it across the ARC resources above, and issues the resulting VRM/PDC TCS **sequence** to the PMIC. (The per-resource command *bytes* are runtime- and ``cmd-db``-driven, not a static table in this image — ``cmd-db`` lives in the shared RAM region below, populated at boot rather than flashed.) **Cx retention** finite-state machine ``cx_ret_fsm``, ``cx_ret``, ``cx_mol``, ``CX_RET_XO_PENDING``, ``CX_GT_MOL``, ``CXC_LOCK``/``CXC_UNLK`` — the logic that lowers the Cx rail to a retention voltage during deep sleep (keeping SRAM/logic state alive at minimum power) and restores it on wake, gated on XO availability. **DDR manager** ``DDR_MGR``, ``/pm/ddr``, ``DDR_ON``/``DDR OFF``, ``DDR ISR``, ``Enab DDR``, ``ddr_freq``, ``ddr_temp``, ``ddr_dep``, ``DDRclnCB``, ``AOP DDR Log`` — the AOP owns DDR frequency scaling, self-refresh entry/exit, DDR thermal (``ddr_temp``) and the DDR interrupt handler. This is why DDR training done by XBL stays coherent across sleep: the always-on AOP, not the kernel, manages the DRAM low-power states. **PDC** (Power Domain / wake-up controller) programming ``pdc_global``, ``pdc_seq``, ``pdc_tcs``, ``PDC_IRQ``, ``PDC_WA``, ``wlan_pdc`` — the AOP programs the PDC TCS sequences so that wake-up interrupts (and per-subsystem wake lines) are armed while the APSS/GIC is powered down. Subsystem low-power coordination ``adsp``, ``cdsp``, ``modem``, ``slpi``, ``ipa_pc`` (IPA power-collapse), ``wlan_pdc``, ``MMNOC_ON``/``MMNoCOFF``/``MMNOC_TO`` (multimedia NoC gating) — the AOP coordinates the sleep/collapse of the DSP/modem/WLAN/IPA subsystems and the on-chip interconnect around a system-wide low-power point. **AOSS sleep** solver + **PMIC** path ``/sleep/aoss``, ``AOSS``, ``aoss_slp`` (the sleep-set solver) and ``PMIC CB`` / ``PMICRqCB`` / ``pmic`` (PMIC request callbacks) — the AOP runs the AOSS sleep sequence and issues the resulting PMIC requests. Communication with the AP ========================= Two channels, both matching the device tree: - **QMP mailbox** — ``QMP_TOUT`` (Qualcomm Messaging Protocol timeout) and the ``/sleep/aoss`` service back the DTB ``qcom,aop-qmp-clk`` node: the AP sends clock/sleep messages to the AOP over QMP. - **Shared message RAM** — the ``0x808xxxxx`` windows above, plus the ``cmd-db`` database at ``0x80860000`` that the AOP populates and the AP reads to resolve RPMh resource names to addresses (:doc:`/boot/base-dtb`). Relevance to a bootloader replacement ===================================== The AOP is brought up and authenticated by XBL's PIL like every other coprocessor image; its signature/cert segment chains to the same **test key** as the rest of the boot chain (:doc:`/boot/secure-boot`), so it is not a special authenticity gate the way XBL Sec is (:doc:`/boot/boot-chain`). Practically, though, the evidence above strongly suggests it is **load-bearing**: DDR, the core rails and wake-up all appear to depend on a running AOP. Anything that replaces the *EL1/UEFI* portion of the boot chain inherits an already-running AOP (XBL starts it before UEFI) and, on that evidence, should preserve the RPMh / message-RAM / cmd-db contract rather than re-implement it — the DDR and rail state the payload runs on is apparently the AOP's, not the payload's. Provenance ========== :Source: ``_READONLY/lun4/aop_a.bin`` (read-only). :Method: ``mbn_dump.py`` for the ELF/MBN program headers; a Python read of the Cortex-M vector table (initial SP, reset vector) and a Capstone **Thumb** disassembly of the reset trampoline at ``0x0b000008``; ``strings`` census for the version tag, RPMh ARC resource names, Cx-retention FSM, DDR-manager, PDC, PMIC and QMP tokens. No code executed. :Cross-refs: :doc:`/boot/base-dtb` (AP-side ``rpmh-rsc`` / ``cmd-db`` / QMP), :doc:`/trustzone/secure-world` (coprocessor EL/processor map, PIL load), :doc:`/boot/boot-chain` (PIL bring-up order), :doc:`/boot/secure-boot` (test-key signing), :doc:`/index` (version inventory), :doc:`/soc/pmic` (the PMIC the AOP drives).