commit 4abf4713f3f0b0fbe06d4f0c9e30300e4f7cdf70
parent 953367e42d9f600488269c20d5d32ca592ed3cc1
Author: umhau <umhau@example.invalid>
Date: Wed, 21 Oct 2026 12:00:03 +0000
HPM RE: selector 2 byte-swaps the 4CC; node advice corrected
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Diffstat:
1 file changed, 26 insertions(+), 3 deletions(-)
diff --git a/tools/kernel/HPM_RE.md b/tools/kernel/HPM_RE.md
@@ -40,9 +40,14 @@ Notes that de-risk this:
`IOReturn` construction in AppleHPM: **`kIOReturnBadMessageID` (0xe00002c6) is never
built anywhere in the kext.** So the `0xe00002c6` you got for `'Gaid'` did **not**
come from a kernel 4CC filter — it came from the plugin's own userspace wrapper or
- from calling it on the wrong node (you noted you ran it against the `AppleHPMARMI2C`
- parent, whose user client is a different class). Re-try 4CC commands on the
- **AppleHPMDevice** node, the same one where `iecsRead` works.
+ from somewhere else on the path (unresolved).
+ **CORRECTION (vr1, verified on hardware 2026-10-20 22:2x):** the earlier advice here to
+ "re-try on the AppleHPMDevice node" is WRONG. `IOCreatePlugInInterfaceForService` on the
+ AppleHPMDevice (RID 1) node returns 0xe00002c7: AppleHPMLib's personality is
+ `IOProviderClass = AppleHPM`, which only the `AppleHPMARMI2C` parent is. `iecsRead` works
+ on the PARENT (not the Device node). On the parent, `iecsCommand` 'Gaid' and 'DRST' both
+ return 0xe00002c6, with and without the com.apple.USBCEntitlement entitlement, and with no
+ kernel log output. Where 0xe00002c6 originates is still being traced.
- Start gentle (#1/#2) and keep #6 as the fallback you already wanted.
---
@@ -266,3 +271,21 @@ Caveat: everything here is static analysis; argument *values* that are enum-like
(`SOPtype` for sendVDM, `mode` for forceMode, exact DP VDM VDOs) could not be verified
without touching hardware. Start with the data-less `'DRST'` and `forceMode` paths,
which have the least ambiguity.
+
+---
+
+## 8. CORRECTION: selector 2 expects BIG-endian (C multichar) 4CCs (vr1, static, 2026-10-20 ~[time redacted])
+
+- `0xfffffe0009b8c830(this, x1=route, x2=cmd, x3=flags, x4)` matches the user client's
+ `provider+0x8f0(route, cmd, flags, 5)` call by signature (VERIFIED: prologue moves x1..x4 into
+ x21/x23/x20/x22). Reached via vtable only (no direct BL callers), so the +0x8f0 -> 0x9b8c830 link
+ is CONJECTURE until the vtable is resolved.
+- At `0x9b8c970`: `rev w8, w23` (byte-swap cmd), then `this->vtbl[+0x8c0](this, route, 8, &w8, 4)`,
+ i.e. a 4-byte write of the SWAPPED value to register 0x08 (CMD1). VERIFIED in disassembly.
+- Neighbouring code builds 4CCs as BE constants (LE-read 'sMDV' = BE 'VDMs', 'pelS' = 'Slep').
+- So on this path pass 'HRST' = 0x48525354, 'DRST' = 0x44525354, 'Gaid' = 0x47616964.
+ The earlier "4CCs are little-endian ASCII" advice (section 2 / summary) holds for code that stores
+ 4CC bytes directly (e.g. exitPDMode's 'DRST' at 0x9b5bbd4), NOT for selector 2.
+- Consequence: the 'Gaid'/'DRST' (vr1) and 'HRST' (vr0) attempts were sent LE, arrived byte-reversed
+ ('diaG', 'TSRD', 'TSRH'), and !CMD in CMD1 is the chip rejecting those. They remain UNTESTED.
+- Flags bit0 (x3) gates a branch at 0x9b8c8b0 that skips a pre-check; use flags 0.