aboutsummaryrefslogtreecommitdiffstats
path: root/psp_out/access_inventory.py
blob: 7c04a5c257066b2c448ce86514995ee2a7e5b68c (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
"""What can we still reach on the card in its current state? Tested, not assumed.

READ-ONLY except the TSU mailbox liveness command (a documented read-only query)
and a scratch write-readback on an already-open mailbox.

Deliberately does NOT read BAR0 at high offsets: that triggers a TLP error which
wedges PCIe access until a power cycle.
"""
import struct, sys, time
sys.path.insert(0, "/Users/user/dev/amd-psp-re/psp_out")
from regguard import byteswap
from tinygrad.runtime.support.usb import USB3
from tinygrad.runtime.support.system import USBPCIDevice

OK, NO, PART = "YES", "no", "partial"
rows = []
def row(cap, verdict, detail): rows.append((cap, verdict, detail))

# --- bridge -----------------------------------------------------------------
devs = []
for vid, pid in ((0x3801, 0x0001), (0xADD1, 0x0001)): devs += list(USB3.list_devices(vid, pid))
if not devs: sys.exit("no bridge")
gpu = USBPCIDevice("AM", *devs[0])
ctrl = gpu.usb; usb = ctrl.usb
row("USB bridge vendor cmds", OK, "product=%s" % usb.product)
lt = usb.control_read(0xE4, 1, value=0xB450)[0]
row("PCIe link", OK if lt == 0x78 else NO, "LTSSM=%#04x" % lt)

# --- BAR5 MMIO --------------------------------------------------------------
b5 = gpu.map_bar(5, fmt='B')
rd = lambda o: struct.unpack('<I', bytes(b5[o:o+4]))[0]
wr = lambda o, v: b5.__setitem__(slice(o, o+4), struct.pack('<I', v & 0xFFFFFFFF))
row("BAR5 register read", OK, "C2PMSG_115=%#010x" % rd(0x582CC))

# --- SMN window -------------------------------------------------------------
def smn(a): wr(14*4, a); return rd(15*4)
mp0 = smn(0x03810ACC)
row("SMN window -> MP0 block", OK if mp0 == rd(0x582CC) else NO, "0x03810ACC=%#010x (matches BAR5)" % mp0)
for name, addr in (("DF scratch", 0x12400F80), ("Route-C window", 0x21500),
                   ("perm array", 0x0381069C), ("SPI flash regs", 0x0005A384)):
    v = smn(addr)
    row("SMN -> %s" % name, NO if v == byteswap(addr) else OK,
        "%#010x -> %#010x %s" % (addr, v, "(MIRROR = not decoded)" if v == byteswap(addr) else ""))

# --- BAR0 low ---------------------------------------------------------------
try:
    b0 = gpu.map_bar(0)
    row("BAR0 low aperture", PART, "reads %s (high offsets FAULT - avoid)" % bytes(b0[0:8]).hex())
except Exception as e:
    row("BAR0", NO, str(e)[:40])

# --- PSP TSU mailbox --------------------------------------------------------
C2P = lambda n: 0x58224 + 4*(n-73)
def tsu(cmd, arg=0, to=2.0):
    wr(C2P(116), arg); wr(C2P(115), (cmd & 0xFF) << 16); wr(C2P(73), 1)
    t0 = time.time()
    while time.time() - t0 < to:
        v = rd(C2P(115))
        if v & 0x80000000: return v & 0xFFFF, rd(C2P(116))
        time.sleep(0.001)
    return None, None
s, d = tsu(0x0B)
row("PSP TSU mailbox", OK if s == 0 else PART, "flash_info_get -> status=%s data=%s"
    % (("%#06x" % s) if s is not None else "TIMEOUT", ("%#010x" % d) if d is not None else "-"))
s2, d2 = tsu(0x07)
row("  PSP boot state", OK, "transfer_type=%s (0x180 = wants off-chip item 0x80)"
    % (("%#010x" % d2) if d2 is not None else "-"))

# --- memory -----------------------------------------------------------------
ms = rd(0xde3*4)
row("VRAM / memory training", NO if ms == 0 else OK, "mmRCC_CONFIG_MEMSIZE=%#x" % ms)
row("SMU (MP1)", NO, "MP1 C2PMSG_72 via SMN = %#010x" % smn(0x03B10A20))

print("%-28s %-8s %s" % ("CAPABILITY", "USABLE", "DETAIL"))
print("-" * 92)
for c, v, d in rows: print("%-28s %-8s %s" % (c, v, d))