mirror of
https://git.k-space.ee/arti/vt1200.git
synced 2026-10-30 12:03:54 +02:00
95 lines
2.9 KiB
Python
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))
|