================================================== Secure world and coprocessors (TZ, HYP, trustlets) ================================================== Structural reverse engineering of the images PIL loads *beside* and *below* the HLOS: the TrustZone secure monitor (``tz_a``), the hypervisor (``hyp_a``), the TZ device config (``devcfg_a``), the QSEE trustlets (``keymaster``, ``uefisecapp``, ``featenabler``, ``mdtpsecapp``), and the two service coprocessors (``aop_a``, ``qupfw_a``). The exception-level *narrative* and where these sit in the boot order is in :doc:`/boot/boot-chain`; this page is the per-image evidence — ELF container, load geometry, and the disassembly that pins each one to its exception level or processor. The ADSP/CDSP DSPs are a separate subsystem in :doc:`/audio/dsp-firmware`; the signing envelope common to all of these is in :doc:`/boot/secure-boot`. Every image below is an MBN/ELF whose PH0 is the Qualcomm hash-table segment (``p_flags`` top byte ``0x07``) and whose second ``PT_NULL`` (``0x02200000``) carries the signature + certificate chain. On this unit that chain is the public Qualcomm **test** key throughout (``Generated Test Root CA`` / ``General Use Test Key (for testing only)`` / ``SecTools Test User``; attestation root ``QSEE Attestation Root CA 4 SubCA 10``) — identical to XBL/ABL (:doc:`/boot/secure-boot`). Exception-level / processor map =============================== .. list-table:: :header-rows: 1 :widths: 16 10 12 26 36 * - Image - ELF - Entry - Runs at - Evidence * - ``tz_a`` (QSEE) - AArch64 - ``0x14680000`` - **EL3** resident monitor - entry writes ``scr_el3`` / ``sctlr_el3``, reads ``mpidr_el1`` * - ``hyp_a`` (QHEE) - AArch64 - ``0x8004a000`` - **EL2** hypervisor - entry writes ``vbar_el2`` / ``mair_el2`` / ``vmpidr_el2`` * - ``devcfg_a`` - AArch64 - ``0x1c003000`` - EL3 data (TZ) - all-RW segments, no code; config namespace consumed by TZ * - ``keymaster_a`` - AArch64 ``DYN`` - (reloc) - EL1 secure (QSEE app) - ``ATTESTATION_APPLICATION_ID`` / Keymaster attest strings * - ``uefisecapp_a`` - ARM32 ``DYN`` - (reloc) - EL1 secure (QSEE app) - descriptor ``n=qcom.tz.uefisecapp;p=8:…`` * - ``featenabler_a`` - AArch64 ``DYN`` - (reloc) - EL1 secure (QSEE app) - MBN ``DYN`` app, test-key chain * - ``mdtpsecapp_a`` - — (blank) - — - EL1 secure (QSEE app) - partition all-zero on this unit (MDTP not provisioned) * - ``aop_a`` - ARM32 (Thumb) - ``0xb000008`` - Cortex-M (Always-On) - Thumb entry (``ldr/blx/bx`` trampoline), code TCM ``0x0b000000`` * - ``qupfw_a`` - Hexagon (QDSP6) - ``0x0`` - QUPv3 micro-DSP - ``e_machine`` = 164 (QDSP6); 9 paged code segments TZ — ``tz_a`` (QSEE, EL3 resident monitor) ========================================== ``tz_a.bin`` is a 4 MB AArch64 ELF, **entry ``0x14680000``**, 23 program headers. It loads in **two disjoint regions**: - an **EL3 monitor stub in IMEM** — executable at ``0x14680000`` (``0xc034``) and ``0x14690000`` (``0x1818``), immediately adjacent to XBL's own IMEM footprint (``0x146xxxxx``); and - the **QSEE secure OS in the ``0x1c00_0000`` window** — executable segments at ``0x1c00e000``, ``0x1c032000``, ``0x1c301000``, ``0x1c35d000`` plus large RW data/heap segments spanning ``0x1c019000``–``0x1c3d4000`` (~3.5 MB). The entry establishes an EL3 environment — disassembly at ``0x14680000``:: 0x14680000: msr tpidr_el0, x0 0x14680004: msr tpidr_el1, x1 0x14680020: mov x0, #0xe00 0x14680024: msr scr_el3, x0 ; Secure Config Register (NS handling) 0x14680028: isb 0x1468002c: mov x0, #0x1c0 0x14680030: msr daif, x0 ; mask D/A/I/F 0x14680034: mrs x0, sctlr_el3 0x14680040: msr sctlr_el3, x0 ; MMU/cache control at EL3 0x14680064: mrs x0, cntpct_el0 0x14680068: mrs x1, mpidr_el1 ; per-CPU affinity → boot vs secondary Writing ``SCR_EL3`` and ``SCTLR_EL3`` is only possible at EL3. This is the resident secure monitor: after XBL's ``PILDxe`` loads and authenticates it (:doc:`/boot/boot-chain`), **TZ takes ownership of EL3 from the XBL "Sec" monitor** (:doc:`/xbl/el3-monitor`) and owns it for the rest of runtime — every ``SMC`` from the kernel, ABL, or the hypervisor lands here. The SCR value ``0xe00`` matches the value XBL Sec programs, i.e. the same secure-monitor configuration is carried across the hand-off. Version ``TZ.XF.5.10-00304-1``, variant ``SAJAANAAA`` (:doc:`/index`). HYP — ``hyp_a`` (QHEE, EL2 hypervisor) ====================================== ``hyp_a.bin`` is a 512 KB AArch64 ELF, **entry ``0x8004a000``**, one ``RWX`` load segment at ``0x8004a000`` (file ``0x60e08``, reserving ``0x23f000`` ≈ 2.3 MB). The entry establishes an EL2 environment — disassembly:: 0x8004a000: bl … bl ; PC-relative reloc trampoline (chained bl) 0x8004a048: msr vbar_el2, x4 ; EL2 vector base 0x8004a04c: mrs x3, vmpidr_el2 0x8004a08c: msr mair_el2, x4 ; EL2 memory attributes 0x8004a090: mrs x4, id_aa64pfr1_el1 ``VBAR_EL2`` / ``MAIR_EL2`` / ``VMPIDR_EL2`` are EL2-only. This is the Qualcomm hypervisor (QHEE): it installs itself at **EL2**, which is why the Linux kernel on this SoC is entered at **EL1**, never EL2 (:doc:`/boot/boot-chain`). Its string set shows a "hyp manager" that brokers ``SMC`` traffic to trustlets — e.g. ``hyp_manager_lookup_mssecapp_id`` / ``qcom.tz.mssecapp`` (the modem secure app). HYP is built from the same package as TZ (version ``TZ.XF.5.10-00304-1``). After the reloc trampoline the init path (``0x8004a044``) sets ``VBAR_EL2`` = ``0x80090000``, lays out a **per-CPU stack** (``sp = 0x801f5000 − 0x2000·affinity``, the affinity taken from ``VMPIDR_EL2``), programs ``MAIR_EL2``, probes ``ID_AA64PFR1_EL1`` for MTE, brings up the EL2 stage-1 MMU (``TTBR0_EL2`` / ``TCR_EL2`` / ``SCTLR_EL2 = 0x8100f`` = M|A|C|SA|I|WXN) and sets ``CNTHCTL_EL2 = 3`` so EL1 keeps the physical counter/timer. The EL2 vector table -------------------- ``VBAR_EL2`` points at a standard 16-entry AArch64 vector table at ``0x80090000`` (``0x80`` stride) — QHEE's primary EL2 dispatch table. The twelve IRQ / FIQ / SError slots are stubs that push ``x30``/``x0``, load a numeric exception index (``0x9``–``0x17``) and tail-call a common handler at ``0x8004f638``; the four **Sync** slots have real handlers: .. code-block:: text +0x000 Sync EL2t -> b 0x8004a400 +0x200 Sync EL2h -> b 0x8004b004 +0x400 Sync lower A64 -> HLOS trap dispatch (below) <- the kernel's gate +0x600 Sync lower A32 -> same shape as +0x400 +0x080..+0x780 IRQ/FIQ/SError (EL2t/EL2h/lowerA64/lowerA32) -> mov x0,#{9..0x17}; bl 0x8004f638 (common sink) HLOS trap dispatch and stage-2 protection ------------------------------------------ The lower-EL AArch64 Sync entry (``0x80090400``) is where the EL1 kernel traps **into** the hypervisor. It reads the ``VMPIDR_EL2`` affinity, indexes a per-CPU byte table (``0x801cbed0``) for a short settle/erratum spin, ``dsb nsh; isb``, then decodes ``ESR_EL2.EC``: .. code-block:: text EC 0x17 SMC (AArch64) -> 0x8004a468 (SMC service path) EC 0x20 Instruction Abort, lower -> 0x8004ac38 (stage-2 IABT) EC 0x24 Data Abort, lower -> 0x8004adcc (stage-2 DABT) EC 0x18 trapped MSR/MRS (A64) -> 0x8004b19c EC 0x03 trapped MCR/MRC CP15 (A32) -> 0x8004b19c else (incl. HVC EC 0x16) -> 0x8004ad0c The stage-2 abort handler (``0x8004ac38``) saves the full GPR frame, re-reads ``ESR_EL2``, checks the ISS fault-status, reads ``FAR_EL2`` (the faulting IPA) and calls a **registered handler pointer** at ``[0x8004b408]`` with the address — this is QHEE's stage-2 memory-protection check on HLOS accesses. The stage-2 role is confirmed by the string set: ``AC_VM_HYP`` (an access-control VM), ``hyp_enable_dvm`` (distributed virtual memory), ``hyp_ipa_based_safe_eco_swa``, ``hyp_secure_mor_PIL_start``, the ``HypXVersion`` / ``HypXCodeAddr`` / ``HypXSize`` metadata and a ``/dev/hyp`` diag node, plus the "``Failed to … Hypervisor … HLOS Stage 2``" fault strings. Full disassembly in ``artifacts/re_static/item1_aop_hyp.txt``. TZ device config — ``devcfg_a`` =============================== ``devcfg_a.bin`` (128 KB, AArch64 ELF, entry ``0x1c003000``) is **data, not code** — its two load segments are ``RW`` only, placed at ``0x1c003000`` (adjacent to QSEE) and ``0x805fd000``. The payload is a pointer-linked config blob (a DAL "config-DB" structure, **not** a flattened DTB — no ``d00dfeed`` magic) whose node namespace is TZ's view of the hardware: .. list-table:: :header-rows: 1 :widths: 24 76 * - Node - Role * - ``/ac/{heap,smmu,xpu}`` - access-control: secure heap, SMMU, and XPU (memory-protection) config * - ``/dev/{i2c,spi}``, ``/dev/buses/qupac``, ``/core/hwengines/gpi`` - bus/DMA devices TZ owns (QUP access-control, GPI DMA engine) * - ``/tlmm/configs`` - the TLMM pin configurations TZ reserves * - ``/tz/{oem,pmic}`` - OEM TZ knobs and PMIC access * - ``/dev/hyp_config_oem`` - OEM hypervisor config handed to HYP * - ``/dev/DDRSSErrorOEM``, ``/dev/NOCErrorOEM`` - DDR-subsystem and NoC error-reporting policy It also carries the secure-storage path ACL (``/data/vendor/tzstorage/``, ``/mnt/vendor/persist/data/``, ``/data/misc/qsee/``) and references trustlet app IDs it gates (``qcom.tz.hdcp2p2``, ``qcom.tz.tpm``). ``devcfg`` is not read-only in the GPT (:doc:`/partition-map`) — it is an updatable per-board config. QSEE trustlets ============== The trustlets are ELF **``DYN``** (position-independent) objects that TZ loads into the secure EL1 app space on demand, each authenticated by its own MBN hash+signature (test key). They are addressed by name (``qcom.tz.``): .. list-table:: :header-rows: 1 :widths: 18 12 12 22 36 * - Trustlet - ISA - Code size - App ID - Purpose (from strings) * - ``keymaster_a`` - AArch64 - ``0x3584f`` - ``qcom.tz.keymaster`` - Keymaster/KeyMint — key attestation (``ATTESTATION_APPLICATION_ID``), consumed by ABL's AVB path (:doc:`/abl/verified-boot`) * - ``uefisecapp_a`` - ARM32 - ``0x10173`` - ``qcom.tz.uefisecapp`` - UEFI's secure-service peer (secure storage / RPMB / fuse access during boot); descriptor ``p=8:c47728cf3e4089,61,82:6004,b4`` * - ``featenabler_a`` - AArch64 - ``0x9a15`` - ``qcom.tz.featenabler`` - SoC feature-enable (fuse-gated capability enablement) * - ``mdtpsecapp_a`` - — - blank - ``qcom.tz.mdtp`` - Mobile Device Theft Protection — partition all-zero here (not provisioned) The ``keymaster`` PH3 carries the ``0x04000006`` "pointer/relocation" segment flag characteristic of a QSEE ``DYN`` app. ``uefisecapp`` being **32-bit** while ``keymaster``/``featenabler`` are 64-bit reflects Qualcomm's mixed QSEE ABI — the UEFI-era app predates the 64-bit trustlet ABI. ``mssecapp`` (modem secure app, brokered by HYP above) has no standalone partition — it is bundled with the modem (:doc:`/audio/dsp-firmware`). Keymaster/KeyMint trustlet — command interface ---------------------------------------------- The ``keymaster_a`` app (descriptor ``n=keymaster64;o=100;p=8:…``, HAL ``keymaster@4.1-service-qti``) is the device's root key store and attestation authority. Its command dispatcher and internals are recovered from the app's string table (code segment file offset ``0x3000``, ``filesz 0x3584f``); the full extraction is in ``artifacts/re_static/item2_keymaster_interface.txt``. - **Command set.** A legacy Keymaster-4 command enum (29 ids: ``GENERATE_KEY`` / ``GET_KEY_CHARACTERISTICS`` / ``IMPORT_KEY`` / ``EXPORT_KEY`` / ``DELETE_KEY`` / ``DELETE_ALL_KEYS`` / ``BEGIN`` / ``UPDATE`` / ``FINISH`` / ``ATTEST`` / ``GET_VERSION`` / ``SET_ROT`` / ``IMPORT_WRAPPED_KEY`` / ``GET_HMAC_SHARING_PARAMS`` / ``COMPUTE_SHARING_HMAC`` / ``PROVISION_DEVICE_IDS`` …) **and** a newer **KeyMint** ``KM_NEW_*`` enum (61 ids) that adds ``KM_NEW_CONFIGURE`` / ``KM_NEW_VERIFY_AUTHORIZATION`` / ``KM_NEW_SET_EARLY_BOOT_ENDED`` / ``KM_NEW_GET_PRE_SHARED_SECRET`` and a parallel **StrongBox** ``…_SB_*`` sub-family (``SB_GENERATE_KEY`` / ``SB_WRAP`` / ``SB_UNWRAP`` / ``SB_ATTEST_ENCRYPTED`` …). So one TA services both the KM4 HAL and the KeyMint path. - **Gatekeeper is integrated here**, not a separate trustlet: ``gk_generate_user_key`` / ``gk_wrap_key`` / ``gk_unwrap_key`` / ``gk_update_km_auth_list`` / ``gk_storage_init`` / ``open_add_km_partition``. (The Android side still exposes a separate ``gatekeeper@1.0-service-qti`` HAL, but it is backed by this TA.) - **Crypto suite:** AES, 3DES, HMAC, RSA and ECC, each with the ``*_generate/_begin/_update/_finish/_import/_export`` verb set, implemented over the QSEE ``qsee_SW_*`` / ``qsee_rsa_*`` syscall primitives. - **Attestation:** the TA *references* the paths ``/persist/data/rsa_attest_key`` and ``/persist/data/ecc_attest_key``, but on this unit **no such plaintext files exist** in the ``persist`` backup — ``/persist/data/`` instead holds QSEE secure-storage (SFS) blob directories (obfuscated base64url names, live + ``.bak`` pairs), so any provisioned attestation key is inside encrypted secure storage, not on disk in the clear (:doc:`/partition-map`). Provisioning tooling ships in ``/vendor`` (``bin/KmInstallKeybox``, ``bin/StoreKeybox``, ``libkeymasterprovision.so``). Device-ID attestation covers ``ATTESTATION_ID_{BRAND,DEVICE,PRODUCT,SERIAL,IMEI,MEID,MANUFACTURER,MODEL}``; X.509 leaf certs are built in-TA (``write_attestation_cert`` / ``sign_rsa_tbscert``). Android Identity Credential keys are supported. - **Root of trust & HW binding.** ``SET_ROT`` / ``km_set_boot_state`` / ``km_set_vbh`` receive the verified-boot state from ABL (:doc:`/abl/verified-boot`); ``KM_ERROR_ROOT_OF_TRUST_ALREADY_SET`` enforces write-once. Working keys are derived from a **SHK (Secure Hardware Key)** with per-purpose context strings (``KM``/``GK``/``UNIQUEID``/``DEVICEID``/``FILENAME``/``ICE`` "HW Crypto key derived from SHK"). The ``ICE`` context and ``SET_ICE_KEY`` / ``KM_TAG_FBE_ICE`` tie the TA to the inline-crypto FBE path (:doc:`/userspace/security`). Key-blob rollback protection uses **RPMB**. Keymaster/uefisecapp: function-level disassembly ------------------------------------------------- The command-interface RE above (``item2_keymaster_interface.txt``) stopped at the string/command-enum level. This section goes one level deeper — actual instruction-level disassembly of ``keymaster_a.bin`` (AArch64) and ``uefisecapp_a.bin`` (ARM32/Thumb-2), looking for the real crypto primitives, the QSEE command-buffer marshalling, and the top-level SMC/command dispatch shape, the same way :doc:`/xbl/el3-monitor` pins XBL's SMC dispatch table. Full raw disassembly and methodology: ``artifacts/re_static/item_tz_trustlet_funcs.txt``. Both images turn out to have a full **dynamic symbol table** (``DT_SYMTAB``/ ``DT_STRTAB``/``DT_HASH`` via ``PT_DYNAMIC``) despite ``e_shnum == 0`` (no section headers) — unlike the kernel ``Image``, which has no ``kallsyms`` table at all and had to be symbolized by string/xref heuristics instead (:doc:`/display/tcon`), these QSEE apps are not fully stripped once you walk the hash chain by hand (no ``pyelftools``/``lief``/ ``readelf`` equivalent ships in this toolchain, so a small ``DT_HASH`` walker was used). That recovers, for each file, every imported syscall/library call by name and every locally-defined function. ``keymaster_a.bin`` exports exactly **one** local function beyond its GP-TA metadata blob — ``CElfFile_invoke`` (file vaddr ``0x2bd28``, ``0x314`` bytes) — and **imports 69 functions** from ``libcmnlib.so`` (``DT_NEEDED``): the entire ``qsee_SW_Cipher*``/``qsee_SW_Hash*``/``qsee_SW_Hmac*``/ ``qsee_SW_GENERIC_ECC*``/``qsee_rsa_*`` crypto surface, plus ``GPAppLib_{init,appInit,appShutdown,handleRequest}`` and ``CApp_openSession`` — i.e. the **entire GP-TA runtime and command router is an external dependency**, not code in this file. ``libcmnlib.so`` is not a separate partition on this device (no ``lun0``-``5`` file named ``*cmnlib*``) but its strings (``cmnlib``, ``cmnlib64``, ``cmnlib_init``, ``cmnlib_release``) are present, statically embedded, inside ``tz_a.bin`` — so Keymaster's actual per-command switch and its crypto implementation both live inside the resident TZ image, not in the trustlet partition. ``CElfFile_invoke`` disassembles as the standard Qualcomm QSEE **GP-TA registration shim**, not a command dispatcher: gated on an internal ``cmd == 0x1200`` loader convention (unrelated to the KM4/KeyMint command IDs), it zero-fills a 0xd8-byte "TA properties" struct from linker-provided ``ta_*`` symbols (heap/stack address+size, app name, description, storage-file limits, crypto-self-test flag), then calls ``cmnlib_init`` → ``GPAppLib_appInit`` → (an empty, dead ``init_array`` walk — no C++ statics on this build) → ``GPAppLib_init``, logging any failure via ``qsee_log`` at every step. The same shim, structurally identical (same ``{0,0xfffe,0xffff}``/ ``cmd==0x1200`` gate, same memset-then-``cmnlib_init`` flow), is ``uefisecapp``'s ``CElfFile_invoke`` (``0xc640``, ``0x288`` bytes, with a smaller ``0x68``-byte properties struct) — confirming it's a shared per-TA-recompiled loader convention, not bespoke code. An automated census (every ``br``/``blr``/indexed-load instruction across all 48,304 decoded instructions in ``keymaster_a.bin``'s 0x3584f-byte code segment) rules out a monolithic KM4/KeyMint command switch living in this file at all: the largest jump table anywhere in the binary has 24 cases (part of an unrelated internal QSEE-status-code-to-string helper at ``0xd84c``, used by the ``qsee_log`` assertion call sites), there are only 41 ``blr`` (indirect call) instructions total, and only 4 pointer-table-indexed loads (one being the dead ``init_array`` walk above). The real per-command KM4/KM_NEW_*/SB_* router is ``GPAppLib_handleRequest``, which lives in ``cmnlib`` inside ``tz_a.bin`` — that dispatch table was not decoded here; decoding it is a larger reverse-engineering task against the 4 MB TZ image. **Crypto primitives — not found to be implemented in either trustlet.** Per the task of looking for recognizable constants: a byte-exact scan for the AES forward S-box and the SHA-256 round-constant table finds **neither** in ``keymaster_a.bin`` nor ``uefisecapp_a.bin`` — but finds **both**, byte-exact, plus the SHA-1 initial-hash constant, inside ``tz_a.bin``. Every ``qsee_SW_Cipher*``/``qsee_SW_Hash*``/``qsee_rsa_*`` call in both trustlets is a real external call into that TZ-resident crypto core; a custom secure monitor replicating this device's Keymaster crypto surface would need to reimplement (or re-host) code from ``tz_a.bin``, not from either app image. ``uefisecapp_a.bin`` is a different story: **306 dynamic symbols**, ~200 locally defined — it statically links its own UEFI authenticated-variable service, X.509 parser, PKCS7 verifier, and a bignum/RSA library (only the actual modular-exponentiation primitive, ``_secmath_BIGINT_modexp``, is imported from ``cmnlib`` — everything else, ``pbl_BIGINT_{Add,Subtract, Multiply,Divide,Square,ModMult,ModExp,...}``, is local code, unlike keymaster's zero local crypto). This directly answers the "what does uefisecapp back" question: ``TzGetVariable``/``TzSetVariable``/ ``TzGetNextVariableName``/``TzQueryVariableInfo``/``TzDelSecBootVar``/ ``TzSyncVarTables``/``TzVariableInitialize`` plus a full ``TzVariablePolicy{Initialize,Register,Lock,Check,Disable,Dump,IsEnabled, ExitBootServices,IsPrivAuthVarProtectionDisabled,IsSecureBootDisabled}`` family, backing the PK/KEK/db/dbx UEFI Secure Boot variable store (``VariableName{PK,KEK,DB,DBX,SecureBoot,SetupMode}``, ``SetupModeEnabled``/``SecureBootEnabled``) — this is the fastboot-lock/AVB/ UEFI-secure-variable backing service on this device. It also carries ``gen_key_for_rpmb``/ ``register_pkkey``/``register_kekkeys`` for RPMB-backed key material. Unlike keymaster, ``uefisecapp``'s top-level command dispatcher lives inside the TA itself and was fully located: **``svc_uefi_var_entry``** (file vaddr ``0x588`` — dynsym value ``0x589`` with the Thumb bit set, ``0x838`` bytes, the largest structural find in this file). Its dispatch core:: 0x5d8 ldr.w r0, [sb] ; r0 = caller's UEFI command ID 0x5dc sub.w r0, r0, #0x8000 ; command space is 0x8000-based 0x5e0 cmp r0, #0x18 0x5e2 bhi.w #0xc90 ; out of range -> shared "other" block 0x5e6 tbh [pc, r0, lsl #1] ; Thumb-2 table-branch-halfword, ; 25 cases (cmd 0x8000-0x8018) Decoding the halfword table directly from the file bytes and resolving every case body's ``bl`` target against the recovered dynamic-symbol table gives a concrete command-ID → implementation map — an SMC/QSEE dispatch loop shaped like XBL's, but one level up the secure-world stack and keyed by UEFI-variable-service command rather than XBL SiP function ID: .. list-table:: :header-rows: 1 :widths: 12 30 * - Command - Resolved handler * - ``0x8000`` - ``TzGetVariable`` * - ``0x8001`` - ``TzSetVariable`` (``0xbe8`` bytes — the largest function in the file) * - ``0x8003`` - ``TzQueryVariableInfo`` * - ``0x800a`` - ``TzVariablePolicyExitBootServices`` * - ``0x800b`` - ``TzSyncVarTables`` * - ``0x800c`` - ``DumpLogBuffer`` (a debug/diagnostic command, not a variable op) * - ``0x8017`` - ``TzVariablePolicyLock`` * - ``0x8004,5,7,8,9`` / ``0x800f-0x8013`` - converge on a shared block (``0xc90``) that re-switches internally to ``TzVariablePolicy{Disable,IsEnabled,Initialize,Register,Dump}``, ``TzVariableInitialize``, ``TzGetNextVariableName`` The remaining slots (``0x8002``, ``0x8006``, ``0x800d``, ``0x800e``, ``0x8014``, ``0x8016``, ``0x8018``) were confirmed to share the same parameter-validation preamble as every resolved case but their specific ``Tz*`` callee was not pinned down — see *Honest limits*. A sibling function, ``svc_uefi_auth_entry`` (``0xc484``, ``0x198`` bytes, next to the PKCS7/X.509 verification code), is inferred — based on its name and location — to be the authenticated-variable-update (``EFI_VARIABLE_AUTHENTICATION_2`` / db-dbx signed-update) entry point; this is unconfirmed, as it was not disassembled. Honest limits ^^^^^^^^^^^^^ - ``keymaster_a.bin``: only its single exported function (``CElfFile_invoke``) was function-by-function disassembled; the ~35 KB of code implementing the actual per-command KM4/KeyMint crypto/key-management logic has no local symbols to anchor on (this file exports exactly one) and was not walked instruction-by-instruction — the jump-table/indirect-call census (which rules out a *dispatcher* living here) stands in for full coverage, not full coverage itself. ~20 runs of consecutive function pointers were found in ``.data`` via relocation analysis (plausible C++ vtables) but not decoded. - ``uefisecapp_a.bin``: 7 of 25 top-level ``svc_uefi_var_entry`` command slots are resolved directly, 7 more one level down through the shared ``0xc90`` block (14/25 effectively identified); the rest were traced structurally but not resolved to a named callee, and ``svc_uefi_auth_entry`` was located and sized but not disassembled at all. Neither TA's RPMB key-derivation call target (inside ``gen_key_for_rpmb``) was resolved to a name. - No live-device tracing anywhere — purely static, cross-checked instruction-by-instruction against each file's own recovered dynamic-symbol and relocation tables, plus a byte-exact constant scan against ``tz_a.bin``. :Source: ``artifacts/re_static/item_tz_trustlet_funcs.txt`` (full disassembly + methodology); ``_READONLY/lun4/{keymaster,uefisecapp,tz}_a.bin``. :Method: ``artifacts/re_static/mbn.py``/``elfdis.py`` for ELF layout and per-function Capstone disassembly (AArch64 for keymaster, Thumb-2 for uefisecapp — called per-region, not as one linear pass, which desyncs on Thumb: an odd/Thumb-bit-set vaddr passed straight through computes an off-by-one file offset and silently mis-disassembles, the same class of trap as the kernel funcmap nearest-symbol mis-snap); a hand-rolled ``DT_HASH``/``DT_SYMTAB``/``DT_JMPREL``/``DT_RELA`` walker for dynamic-symbol and PLT/GOT/relocation recovery in the absence of ``pyelftools``/``lief``/``readelf``; a Capstone-based jump-table/indirect-call census script (ad hoc) for the keymaster negative result; a plain byte-exact scan for the AES-sbox/SHA-K constants. :Cross-refs: :doc:`/xbl/el3-monitor` (the SMC-dispatch-table structural analogy), :doc:`/abl/verified-boot` (AVB/fastboot-lock consumer of uefisecapp's UEFI-variable service). Coprocessors — AOP and QUP ========================== Two service processors are loaded early and outlive the OS boot: AOP — ``aop_a`` (Always-On Processor, Cortex-M) 32-bit ARM ELF, **Thumb** entry. The AOP is the always-on micro-controller that runs RPMh / resource-state and low-power coordination for the SoC. Version ``AOP.HO.2.0-00069``. Full internals — addresses, the Cortex-M vector table, the RPMh ARC rails, the Cx-retention FSM, the DDR manager and the QMP/message-RAM channel — are in :doc:`/soc/aop`. QUP — ``qupfw_a`` (QUPv3 serial-engine firmware, Hexagon) Hexagon **QDSP6** ELF (``e_machine`` = 164), 81 KB, nine paged code segments (segment flag ``0x08000007``) loading from ``0x1000``. This is the microcode the GENI/QUPv3 serial engines execute to implement I²C/SPI/UART protocols — the firmware side of the GENI hardware documented in :doc:`/boot/qup-buses`. The GENI engines are inert until XBL loads this image, so any bare-metal payload that wants QUP-backed I²C/SPI/UART inherits (or must re-load) it. :Source: ``_READONLY/lun4/{tz_a,hyp_a,devcfg_a,keymaster_a,uefisecapp_a, featenabler_a,mdtpsecapp_a,aop_a,qupfw_a}.bin`` — ELF program headers (``mbn_dump.py``), Capstone disassembly of the ``tz_a`` (``0x14680000``) and ``hyp_a`` (``0x8004a000``) entries (``eldis.py``), and image strings for versions / app IDs / cert chain. :Cross-refs: :doc:`/boot/boot-chain`, :doc:`/xbl/el3-monitor`, :doc:`/soc/aop`, :doc:`/partition-map`, :doc:`/index`, :doc:`/audio/dsp-firmware`, :doc:`/boot/below-uefi`, :doc:`/boot/base-dtb`, :doc:`/boot/secure-boot`, :doc:`/abl/verified-boot`.