# Review of `new/` — Routes A and B verified against the firmware Independent verification of the other researcher's Route A and Route B, done in IDA against `sys_drv2.elf`. Their claims are **[D]**-tagged static analysis; this records which parts I could confirm, which I could not, and what I found instead. ## Confirmed: the mailbox model and the host-open set `off_E2579C` is the MP0 register block + `0x10000`, so their §1.2 offset formula (`N>=64 -> 0x10A00 + 4*(N-64)`) is directly checkable. It holds: | mailbox | dword index | handler found | |---|---|---| | **112/113** | 688/689 | **`platform_range_get`** (Route A target) | | **115** | 691 | **`tsu_mailbox_dispatch`** (Route B / §4.1 target) | | 117 / 118 / 125 | 693/694/701 | irq scan + dispatch | | perm word 112-127 | 430 | `init_mailbox_state`, `irq_enable_group1/2/3`, `tsu_mailbox_task` | Their §1.3 claim that the firmware opens these to the host itself is confirmed: five OR-only RMWs, `|= 0xF` (112,113) in `init_mailbox_state` and `|= 0x3C0` (115,116) in **`tsu_mailbox_task`** — the flash/update task opening its own mailbox. Their §1.5 command encoding is also confirmed: `platform_range_get` takes the command id from `BYTE1` (bits 15:8) with bit31 as submit, exactly as documented. ## Route A — the claimed defect is REAL, but one level deeper than stated They describe the mailbox-112 handler as having "a physical-range composition path that ignores the return status of the mapping call". **That part does not hold** for `platform_reg_write` (`0xE0F06C`): * it **does** check the `SVC 0x7D` map return (`MOVS R4, R0; BEQ locret`); * it **does** bounds-check: `v11 + v3 <= base + 1380` where `v11 = base + off + 812`, i.e. `host_offset + host_len <= 568` inside a 1380-byte mapping. No 32-bit wrap is reachable (both fields are 16-bit, base is a low PSP address). But their **"paging cursor that advances by a caller-supplied length with no clamp and is never reset"** is confirmed, in the sink `msmu_handle_param` (`0xE0F1B4`), `a1 == 1` path: ```c v17 = *(_DWORD *)(base + 808); // cursor phys_range_compose3(a2, v17, a3); // composes a range AT the cursor ... *(_DWORD *)(v14 + 808) += a3; // cursor += caller length, never reset here ``` `a3` is bounded per call (`v15[203] >= a3`, and `<=568` upstream), but the **cursor is cumulative and unbounded** — every command-2 submission walks it further, and `phys_range_compose3` composes at wherever it has reached. That is a genuine walk-off primitive, reachable from a mailbox the firmware grants the host by design. ## Route B — interface confirmed, contents not yet probed `tsu_mailbox_dispatch` (`0xE1C948`) is a real dispatcher: command byte in BYTE2 of the status word at `off_E2579C + 2764` (= mailbox 115), unknown commands return `0xFFFF000A`, and the handled set includes `flash_ctx_set` (cmd 2/3), `tsu_parse_rom_image` (cmd 4), `flash_info_get` (cmd 11) and `desc_slot_alloc` (cmd 18) — matching their §4.1 table. **Never probed by us:** our earlier "C2P mailbox not host-reachable" result tested C2PMSG_35/36, a different pair. 115/116 is untested surface. ## HARDWARE RESULT — Route A is NOT host-reachable; Route B IS Measured directly on the card. The permission array itself is **not host-readable** (`0x0381069C..0x038106B8` all return the byte-swapped index), so it was probed behaviourally instead: write a non-palindromic bit31-set pattern to each mailbox and read it back. Writes that land read back EXACT; writes that are not decoded read back byte-swapped, the same signature as a dead SMN read. | mailbox | behaviour | meaning | |---|---|---| | **112, 113** | BYTESWAP | **Route A: host writes do NOT land** | | **115, 116** | **EXACT** | **Route B (TSU flash/update): host CAN write** | | 118 | EXACT | display channel open | | 122 | EXACT | open (not in their §1.3 list) | | 125 | EXACT | platform id open | | 108-111, 114, 117, 119-121, 123-124, 126-127 | BYTESWAP | not host-decoded | Measured open set `{115, 116, 118, 122, 125}` vs their §1.3 prediction `{112, 113, 115, 116, 117, 118, 125}`: **four agree** (115, 116, 118, 125), 112/113/117 do not, and 122 is open but unlisted. **So Route A cannot be driven from the host on this card** — its mailboxes are not decoded for us, regardless of the `|= 0xF` the firmware performs. The unbounded-cursor defect in `msmu_handle_param` is real but not host-reachable by this path. **Route B's interface is confirmed open**, which is the more valuable half: mailbox 115 also reads `0x80000000` (bit31 set = completed), so the TSU task has run and is idle. ### Two test-design errors caught en route 1. First write-test used `0xA5A5A5A5`/`0x5A5A5A5A` — both **byteswap-invariant**, so they could not distinguish a real write from the artifact. Re-run with `0x12345678`. 2. An earlier decode of the permission array printed an "open set" from **mirror values** — pure garbage. Always check a read against its byte-swapped index before decoding it. ## Recommended order 1. **Read the permission array** (`0x0381069C..0x038106B8`) — free, no writes, and it says which of these interfaces is actually open right now. Expect `0x0C003FCF` in the word covering 112-127. 2. **Route B liveness only**: TSU commands `0x01` and `0x0B` (read-only). Do **not** run `0x04` with an update image without an external programmer attached. 3. **Route A**: submit command 6 (the no-op/`v1=1` case) first to confirm the channel answers, then command 2 once, and re-read the cursor's effect before repeating. -------------------------------------------------------------------------------- ## Validity guard (`regguard.py`) Three times in this project a dead access path produced a confident wrong answer: an "open mailbox" set decoded from byte-swapped mirrors; `navi31_bench.py`'s `cmd_scan` reporting **80** open mailboxes from eight identical reads of the PSP heartbeat counter; and a write-test "confirming" access using `0xA5A5A5A5` / `0x5A5A5A5A`, which are **byteswap-invariant** and cannot distinguish a real readback from a swapping artifact. All three are mechanically detectable, so they are now a function call rather than something to remember: * `classify_read(read_fn, addrs)` -> `REAL / MIRROR / ALIAS / DEAD / UNSTABLE` (requires >= 3 distinct addresses so aliasing is detectable at all) * `is_writable(read_fn, write_fn, addr)` -> `WRITABLE / BYTESWAP / IGNORED / MIXED`, using patterns asserted at import time to be non-palindromic * `guard_decode(words, addrs, decoder)` -> **raises** instead of decoding an artifact `test_regguard.py` validates it against cases whose truth was established by other means -- 13/13 pass: | case | expected | got | |---|---|---| | perm array via BAR | ALIAS | ALIAS | | perm array via SMN | MIRROR | MIRROR | | Route C window via SMN | MIRROR | MIRROR | | known-real SMN addrs | USABLE | USABLE | | mbx115/116 | WRITABLE | WRITABLE | | mbx112/113 | BYTESWAP | BYTESWAP | | `guard_decode` on both bad word sets | refuse | refused | Any future register result in this project should go through it before being interpreted.