#!/usr/bin/env python3 """Map every GPIO write in the RT-4D app: find calls to the low-level GPIO helpers and back-resolve (port, mask, state) from the preceding instructions.""" import struct, re, capstone, os BASE = 0x08002800 P = "/home/viktor/claude/rt-4d/stock-fw/rt4d_stock_v3.25_abs_0x08002800.bin" IMG = open(P, "rb").read() md = capstone.Cs(capstone.CS_ARCH_ARM, capstone.CS_MODE_THUMB) PORTS = {0x40020000: "GPIOA", 0x40020400: "GPIOB", 0x40020800: "GPIOC", 0x40020C00: "GPIOD", 0x40021000: "GPIOE", 0x40021400: "GPIOF", 0x40021800: "GPIOG"} # low-level writers discovered by disassembly HELPERS = {0x08021C6E: "gpio_set_state(port,mask,state)", 0x08021C56: "gpio_bsrr_write(port,mask)", 0x08021C4C: "set_bit0(reg,val)"} def word(va): o = va - BASE return struct.unpack_from(" 14: win.pop(0) if ins.mnemonic == "bl" and ins.op_str.startswith("#"): tgt = int(ins.op_str[1:], 16) if tgt in HELPERS: regs = {} for p in win[:-1]: mm = re.match(r"(r\d+)", p.op_str) dst = mm.group(1) if mm else None if not dst: continue v = lit_of(p) if v is not None: regs[dst] = v elif p.mnemonic in ("movs", "mov.w", "mov") and "#" in p.op_str: try: regs[dst] = int(p.op_str.split("#")[1], 0) except Exception: pass elif p.mnemonic == "movw" and "#" in p.op_str: try: regs[dst] = int(p.op_str.split("#")[1], 0) except Exception: pass hits.append((ins.address, HELPERS[tgt], regs.get("r0"), regs.get("r1"), regs.get("r2"))) return hits if __name__ == "__main__": rows = scan() print(f"{len(rows)} GPIO-helper call sites\n") print(f"{'site':<12}{'helper':<32}{'r0(port/reg)':<22}{'r1(mask/val)':<14}{'r2'}") for site, h, r0, r1, r2 in rows: pn = PORTS.get(r0, f"0x{r0:08X}" if r0 is not None else "?") mask = f"0x{r1:X}" if r1 is not None else "?" bit = "" if r1 and r1 and (r1 & (r1 - 1)) == 0: bit = f" (bit{r1.bit_length()-1})" print(f"0x{site:08X} {h:<32}{pn:<22}{mask+bit:<14}{r2 if r2 is not None else ''}")