Files
vt1200/dwt/mailbox_watch.py
T

95 lines
2.9 KiB
Python

#!/usr/bin/env python3
"""Poll the VT1200 diagnostic handoff cells over rdebug during a boot.
rdebug only exists once the OS/network stack is up, so this cannot see the
level-1 tests themselves. It *can* catch the window between the network stack
starting and the Terminal Manager consuming the diagnostic result:
0x27C190 diagnostic mailbox pointer (Ghidra: FUN_rom_07f5a026 dereferences it)
0x16F0 level-1 dispatcher's transient status code slot
If the mailbox pointer becomes non-zero, the nine fields it points at are
dumped. The log records every value change, so a value that exists only for a
few polls is still captured.
Usage:
python3 dwt/mailbox_watch.py --host 100.103.100.103 --seconds 180
Start it, then power-cycle the terminal.
"""
from __future__ import annotations
import argparse
import struct
import sys
import time
import exploit
MAILBOX = 0x27C190
SLOT = 0x16F0
FIELDS = 9
def u32(rd: exploit.RDebug, bit: int) -> int:
return struct.unpack("<I", rd.peek(bit, 4))[0]
def main(argv):
ap = argparse.ArgumentParser(description=__doc__,
formatter_class=argparse.RawDescriptionHelpFormatter)
ap.add_argument("--host", default="100.103.100.103")
ap.add_argument("--port", type=int, default=771)
ap.add_argument("--seconds", type=float, default=180.0)
ap.add_argument("--out", default=".vt1200-scratch/mailbox-watch.log")
a = ap.parse_args(argv[1:])
deadline = time.time() + a.seconds
log = open(a.out, "w")
rd = None
last_m = last_s = None
def emit(line: str) -> None:
log.write(line + "\n")
log.flush()
emit(f"watch {a.host}:{a.port} for {a.seconds:.0f}s -> {a.out}")
while time.time() < deadline:
if rd is None:
try:
rd = exploit.RDebug(a.host, a.port, 2.0, False)
rd.connect()
emit(f"{time.time():.3f} connected")
except Exception as exc: # noqa: BLE001
time.sleep(0.4)
continue
try:
m = u32(rd, MAILBOX)
s = u32(rd, SLOT)
if m != last_m or s != last_s:
emit(f"{time.time():.3f} mailbox={m:#010x} slot={s:#010x}")
last_m, last_s = m, s
if m:
for i in range(FIELDS):
try:
v = u32(rd, m + 0x20 * i)
except Exception: # noqa: BLE001
break
emit(f" +0x{0x20 * i:03x}: {v:#010x}")
except Exception as exc: # noqa: BLE001
emit(f"{time.time():.3f} lost: {type(exc).__name__}: {exc}")
try:
rd.close()
except Exception: # noqa: BLE001
pass
rd = None
time.sleep(0.2)
if rd is not None:
rd.close()
log.close()
return 0
if __name__ == "__main__":
sys.exit(main(sys.argv))