aboutsummaryrefslogtreecommitdiffstats
path: root/psp_out/smn_name.py
blob: 8fca8ceb5e0d13ee88ff2902c2bbd15d64b8ba23 (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
#!/usr/bin/env python3
"""Name an SMN address from the NV22_A0 memory map.

No hardware access whatsoever -- this is a lookup table, and is the safe way to
get value out of a memory map. FINDING-NO-PSP-MEMORY-APERTURE.md left several
decoding SMN bases recorded as "small, unidentified"; a naming dictionary turns
those into leads without touching the card.

    python3 smn_name.py 0x1300000 0x10100000 ...
    python3 smn_name.py --block MP_MP0MMU

The map is NV22_A0 and the card is NV31, so a name is a HYPOTHESIS about what
lives at an address, never a confirmation. Anything acted on must be checked
against the card in small batches with a health check, per the rule in
FINDING-NO-PSP-MEMORY-APERTURE.md.
"""
import os
import sys

MAP = os.path.expanduser("~/nv22_a0_memmap.txt")


def load():
    rows = []
    with open(MAP) as fh:
        for line in fh:
            if line.startswith("#"):
                continue
            p = line.split()
            if len(p) < 4 or not p[0].startswith("0x"):
                continue
            try:
                addr = int(p[0], 16)
            except ValueError:
                continue
            rows.append((addr, p[2], p[3]))
    return rows


def name_at(rows, addr, window=0x10000):
    exact = [r for r in rows if r[0] == addr]
    if exact:
        return exact, 0
    near = [r for r in rows if 0 <= addr - r[0] < window]
    if not near:
        return [], None
    best = max(r[0] for r in near)
    return [r for r in near if r[0] == best], addr - best


def main():
    rows = load()
    args = sys.argv[1:]
    if not args:
        print(__doc__)
        return 2
    if args[0] == "--block":
        pref = args[1].upper()
        seen = set()
        for a, kind, nm in sorted(rows):
            base = nm.split(".")[0].upper()
            if base.startswith(pref) and nm not in seen:
                seen.add(nm)
                print("  %#010x  %-6s %s" % (a, kind, nm))
        return 0
    for s in args:
        addr = int(s, 0)
        hits, delta = name_at(rows, addr)
        if not hits:
            print("%#012x : no NV22 row within 64K below it" % addr)
            continue
        tag = "exact" if delta == 0 else "base+%#x" % delta
        names = sorted({h[2].split("[")[0] for h in hits})
        print("%#012x : %-10s %s" % (addr, tag, ", ".join(names[:4])))
    return 0


if __name__ == "__main__":
    sys.exit(main())