aboutsummaryrefslogtreecommitdiffstats

Attack plan: the ROM_SW boot window (enabled by bridge-resident probing)

Why this plan exists now

Two facts from this project, previously fatal in combination:

  • ROM_SW (direct SPI engine: CNTL 0x5A3A0 / STATUS 0x5A3A4 / COMMAND 0x5A3A8 / DATA 0x5A3B0) is open from power-on and gated once sOS boots (romless.py: "engine may be gated after SOS boot").
  • CARD-STATE notes: "open_gpu() costs ~2 s … the PSP gates ROM_SW in < 2 s, so the ROM_SW race is unwinnable."

The race was unwinnable only because of USB round-trip latency. Bridge-resident 8051 code driving the TLP engine (ADDR 0xB218-0xB21F, DATA 0xB220-0xB223, trigger 0xB296) is in position from link-up, with microsecond cadence and no host in the loop. The premise that killed this experiment no longer holds.

The prize, stated precisely

We already have unrestricted flash access when the PSP fails to boot (BIOS-1 + romless.py). ROM_SW during the boot window is different in one important way: it is flash write access while the PSP is mid-boot.

That makes the real target a boot-time TOCTOU against firmware verification: if the PSP verifies a flash region and later re-reads it for use, modifying it in between defeats the signature check without breaking any crypto. Classic verify-then-use over a mutable backing store.

It also unblocks the standing entry "Cannot write 0x7000 or any flash by any available path while the PSP boots" — 0x7000 sits in a gap no descriptor covers.

Phase order — cheapest refutation first

Deliberately front-loaded with the step most likely to kill the plan, because this session repeatedly showed static checks killing leads for free.

Phase 0 — STATIC, free, and may end the plan

Does the PSP ever re-read a flash region after verifying it? We have all six modules reversed. Enumerate the boot path's flash reads (fw_tail_scan, tsu_*, vbios_flash_verify, bl_* image loads) and determine whether any region is read twice with a verification in between, or whether every consumer works from the single in-SRAM copy taken at verify time.

  • If every path is verify-from-the-copy -> there is no TOCTOU, and the whole plan reduces to "write 0x7000 during boot", which is a curiosity, not an attack. Stop here.
  • If any path re-reads -> continue, with a named target region.

Note: this is the same property that killed the TLV double-fetch (snapshot before use). The prior should be that AMD does this correctly; Phase 0 exists to find out cheaply rather than after building firmware.

Phase 1 — OBSERVE, zero risk

Bridge-resident poller sampling from link-up:

  • ROM_SW_STATUS (is the engine answering?)
  • PSP C2PMSG_35 / _33 / _64 (boot-stage transitions)
  • timestamped into XDATA, streamed to the host afterwards.

Deliverable: the PSP boot timeline at microsecond resolution, and specifically when ROM_SW gates and how long the window is. This is valuable on its own — it is the observability we have lacked all session — and it is pure reading.

Phase 2 — REACH, read-only

Inside the measured window, issue a ROM_SW read (e.g. JEDEC ID, opcode 0x9F, or a sector read) and confirm it completes rather than timing out. Proves the engine is genuinely reachable pre-gate. Still no writes.

Kill criterion: if reads time out even with perfect timing, the window is not actually open to us and the plan ends.

Phase 3 — ACT, destructive; requires Phases 0 and 2 to have succeeded

Only with a named re-read target from Phase 0 and a confirmed window from Phase 2: write the target region mid-boot and observe whether the PSP consumes the modified content.

Run this on BIOS-1, the spare slot, not the working BIOS-2 image. The physical dual-BIOS switch is the recovery path, and flash_BIOS2_KNOWNGOOD_20260917.bin plus flash_BIOS1_STUCK_20260917.bin are both archived.

Safety rails

  • Phases 0-2 involve no flash writes at all.
  • Phase 3 is confined to BIOS-1; BIOS-2 is never written.
  • Do not re-run fw_live.py ifwi-all (associated with the first erasure).
  • Verify card health (LTSSM, MEMSIZE) after every hardware phase.

Honest expectation

Phase 0 is more likely than not to end this. Every comparable path in this firmware has turned out to snapshot-then-verify, and that is exactly the property that defeats a boot-time TOCTOU. The plan is still worth running because Phase 0 is free, and because Phase 1 delivers a microsecond boot timeline regardless of the outcome — an artifact we want independently of this attack.