aboutsummaryrefslogtreecommitdiffstats
path: root/psp_out/PLAN-BOOT-WINDOW-ROMSW.md
blob: 090e9c54e4b1af211c95a71897d93ab3a4594db6 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
# 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.