summaryrefslogtreecommitdiffstats
path: root/firmware/57X-GSP/570.144/trace_all_subsystems.py
diff options
context:
space:
mode:
Diffstat (limited to 'firmware/57X-GSP/570.144/trace_all_subsystems.py')
-rw-r--r--firmware/57X-GSP/570.144/trace_all_subsystems.py279
1 files changed, 279 insertions, 0 deletions
diff --git a/firmware/57X-GSP/570.144/trace_all_subsystems.py b/firmware/57X-GSP/570.144/trace_all_subsystems.py
new file mode 100644
index 0000000..e004791
--- /dev/null
+++ b/firmware/57X-GSP/570.144/trace_all_subsystems.py
@@ -0,0 +1,279 @@
+#!/usr/bin/env python3
+"""
+Trace all subsystems: WPR, Migration, Primary Dispatcher sub-commands
+"""
+
+import struct
+import os
+
+FWIMAGE_PATH = os.path.join(os.path.dirname(os.path.abspath(__file__)), "gsp-570.144.fwimage.bin")
+BASE_ADDR = 0x04000000
+
+def read_binary(path):
+ with open(path, 'rb') as f:
+ return f.read()
+
+def decode_inst(data, offset):
+ if offset + 4 > len(data): return None, 0
+ first16 = struct.unpack('<H', data[offset:offset+2])[0]
+ if (first16 & 0x3) != 0x3:
+ return decode_compressed(first16), 2
+ inst = struct.unpack('<I', data[offset:offset+4])[0]
+ return decode_32bit(inst), 4
+
+def decode_compressed(inst):
+ if (inst & 0xF003) == 0x8002:
+ rd = (inst >> 7) & 0x7; rs2 = (inst >> 10) & 0x7
+ return {'m': 'c.mv', 'rd': rd+8, 'rs2': rs2+8}
+ if (inst & 0xE003) == 0x6001:
+ rd = (inst >> 7) & 0x7
+ imm = ((inst >> 2) & 0x3F) | ((inst >> 12) & 0x1) << 6
+ if imm & 0x40: imm -= 0x80
+ return {'m': 'c.addi', 'rd': rd+8, 'imm': imm}
+ if (inst & 0xF07F) == 0x8067:
+ rs1 = (inst >> 7) & 0x1F
+ return {'m': 'c.jalr', 'rs1': rs1}
+ if (inst & 0xE003) == 0x6003:
+ rd = (inst >> 10) & 0x7; rs1 = (inst >> 7) & 0x7
+ off = ((inst >> 2) & 0x1F) | ((inst >> 13) & 0x3) << 5
+ return {'m': 'c.ld', 'rd': rd+8, 'rs1': rs1+8, 'off': off*8}
+ if (inst & 0xE003) == 0xE000:
+ rs1 = (inst >> 7) & 0x7; rs2 = (inst >> 10) & 0x7
+ off = ((inst >> 2) & 0x1F) | ((inst >> 13) & 0x3) << 5
+ return {'m': 'c.sd', 'rs1': rs1+8, 'rs2': rs2+8, 'off': off*8}
+ return {'m': 'c.unk', 'raw': inst}
+
+def decode_32bit(inst):
+ opcode = inst & 0x7F
+ funct3 = (inst >> 12) & 0x7
+ rd = (inst >> 7) & 0x1F
+ rs1 = (inst >> 15) & 0x1F
+ rs2 = (inst >> 20) & 0x1F
+ funct7 = (inst >> 25) & 0x7F
+ if opcode == 0x13 and funct3 == 0:
+ imm = (inst >> 20) & 0xFFF
+ if imm >= 0x800: imm -= 0x1000
+ return {'m': 'addi', 'rd': rd, 'rs1': rs1, 'imm': imm}
+ if opcode == 0x03 and funct3 == 3:
+ off = (inst >> 20) & 0xFFF
+ if off >= 0x800: off -= 0x1000
+ return {'m': 'ld', 'rd': rd, 'rs1': rs1, 'off': off}
+ if opcode == 0x23 and funct3 == 3:
+ off = ((inst >> 7) & 0x1F) | ((inst >> 25) & 0x7F) << 5
+ return {'m': 'sd', 'rs1': rs1, 'rs2': rs2, 'off': off}
+ if opcode == 0x6F:
+ imm = ((inst >> 31) & 0x1) << 20 | ((inst >> 12) & 0xFF) << 12 | ((inst >> 20) & 0x1) << 11 | ((inst >> 21) & 0x3FF) << 1
+ if imm & 0x100000: imm -= 0x200000
+ return {'m': 'jal', 'rd': rd, 'imm': imm}
+ if opcode == 0x67 and funct3 == 0:
+ imm = (inst >> 20) & 0xFFF
+ if imm >= 0x800: imm -= 0x1000
+ return {'m': 'jalr', 'rd': rd, 'rs1': rs1, 'imm': imm}
+ if opcode == 0x63:
+ imm = ((inst >> 31) & 0x1) << 12 | ((inst >> 7) & 0x1) << 11 | ((inst >> 25) & 0x3F) << 5 | ((inst >> 8) & 0xF) << 1
+ if imm & 0x1000: imm -= 0x2000
+ btype = ['beq','bne','?','?','blt','bge','bltu','bgeu'][funct3]
+ return {'m': btype, 'rs1': rs1, 'rs2': rs2, 'imm': imm}
+ if opcode == 0x37:
+ imm = (inst >> 12) & 0xFFFFF
+ return {'m': 'lui', 'rd': rd, 'imm': imm}
+ if opcode == 0x17:
+ imm = (inst >> 12) & 0xFFFFF
+ return {'m': 'auipc', 'rd': rd, 'imm': imm}
+ if opcode == 0x33:
+ ops = {0:'add', 0x20:'sub', 1:'sll', 4:'xor', 5:'srl', 0x25:'sra', 6:'or', 7:'and'}
+ return {'m': ops.get(funct7, f'arith{funct7}'), 'rd': rd, 'rs1': rs1, 'rs2': rs2}
+ return {'m': 'unk', 'raw': inst}
+
+def trace_function(data, start_addr, max_bytes=2000):
+ offset = start_addr - BASE_ADDR
+ insts = []
+ i = 0
+ while i < max_bytes:
+ idx = offset + i
+ if idx >= len(data): break
+ inst, size = decode_inst(data, idx)
+ if inst is None: i += 2; continue
+ inst['addr'] = BASE_ADDR + idx
+ inst['rel'] = i
+ insts.append(inst)
+ i += size
+ if inst.get('m') in ('ret', 'jalr') and inst.get('rd') == 0 and inst.get('imm', 0) == 0 and inst.get('rs1', 1) == 1:
+ break
+ return insts
+
+def find_string_refs(data, strings):
+ """Find all references to given strings in the binary"""
+ results = {}
+ for s in strings:
+ s_bytes = s.encode('ascii')
+ results[s] = []
+ # Search for string in data
+ for i in range(len(data) - len(s_bytes)):
+ if data[i:i+len(s_bytes)] == s_bytes:
+ results[s].append(BASE_ADDR + i)
+ return results
+
+def find_string_refs_via_loads(data, string_addrs):
+ """Find code that loads addresses of strings"""
+ results = {}
+ for s, addrs in string_addrs.items():
+ results[s] = []
+ for str_addr in addrs:
+ # Look for auipc/addi pairs that compute this address
+ for i in range(0, len(data) - 4, 2):
+ if i + 4 <= len(data):
+ inst = struct.unpack('<I', data[i:i+4])[0]
+ opcode = inst & 0x7F
+ if opcode == 0x17: # auipc
+ rd = (inst >> 7) & 0x1F
+ imm = (inst >> 12) & 0xFFFFF
+ pc = BASE_ADDR + i
+ base = (pc + (imm << 12)) & ~0xFFF
+ # Check next instruction for addi
+ if i + 8 <= len(data):
+ inst2 = struct.unpack('<I', data[i+4:i+8])[0]
+ if (inst2 & 0x7F) == 0x13 and ((inst2 >> 12) & 0x7) == 0:
+ rd2 = (inst2 >> 7) & 0x1F
+ rs1 = (inst2 >> 15) & 0x1F
+ imm2 = (inst2 >> 20) & 0xFFF
+ if imm2 >= 0x800: imm2 -= 0x1000
+ if rd == rd2 and rs1 == rd:
+ computed = base + imm2
+ if computed == str_addr:
+ results[s].append(BASE_ADDR + i)
+ return results
+
+data = read_binary(FWIMAGE_PATH)
+
+# ============================================================
+# 1. TRACE WPR SUBSYSTEM
+# ============================================================
+print("=" * 60)
+print("1. WPR SUBSYSTEM - String References")
+print("=" * 60)
+
+wpr_strings = [
+ "WPR_WRITE_COMPLETE", "WPR_READ_COMPLETE",
+ "WPR_WRITE_TIMEOUT", "WPR_READ_TIMEOUT",
+ "NV_WPR_WRITE_COMPLETE", "NV_WPR_READ_COMPLETE",
+ "NV_WPR_WRITE_TIMEOUT", "NV_WPR_READ_TIMEOUT"
+]
+
+wpr_locs = find_string_refs(data, wpr_strings)
+for s, addrs in wpr_locs.items():
+ if addrs:
+ print(f"\n{s}:")
+ for addr in addrs:
+ print(f" String at 0x{addr:08x}")
+
+# Find code referencing these strings
+wpr_refs = find_string_refs_via_loads(data, wpr_locs)
+for s, addrs in wpr_refs.items():
+ if addrs:
+ print(f"\nCode referencing {s}:")
+ for addr in addrs[:5]:
+ print(f" 0x{addr:08x}")
+
+# ============================================================
+# 2. TRACE BAR SUBSYSTEM
+# ============================================================
+print("\n" + "=" * 60)
+print("2. BAR SUBSYSTEM - String References")
+print("=" * 60)
+
+bar_strings = ["BAR1", "Bar1Rest", "ForceBarAccess", "Bar1Mapping", "Bar1Aperture", "Bar1Size"]
+bar_locs = find_string_refs(data, bar_strings)
+for s, addrs in bar_locs.items():
+ if addrs:
+ print(f"\n{s}:")
+ for addr in addrs:
+ print(f" String at 0x{addr:08x}")
+
+bar_refs = find_string_refs_via_loads(data, bar_locs)
+for s, addrs in bar_refs.items():
+ if addrs:
+ print(f"\nCode referencing {s}:")
+ for addr in addrs[:5]:
+ print(f" 0x{addr:08x}")
+
+# ============================================================
+# 3. DECODE PRIMARY DISPATCHER SUB-COMMANDS (Jump Table at 0x057a3ad8)
+# ============================================================
+print("\n" + "=" * 60)
+print("3. PRIMARY DISPATCHER SUB-COMMANDS (0x057a3ad8)")
+print("=" * 60)
+
+def decode_jal_target(inst, pc):
+ imm = ((inst >> 31) & 0x1) << 20 | ((inst >> 12) & 0xFF) << 12 | ((inst >> 20) & 0x1) << 11 | ((inst >> 21) & 0x3FF) << 1
+ if imm & 0x100000: imm -= 0x200000
+ return pc + imm
+
+jt_base = 0x057a3ad8
+for i in range(32):
+ entry_addr = jt_base + i * 8
+ offset = entry_addr - BASE_ADDR
+ if offset + 8 <= len(data):
+ addi_inst = struct.unpack('<I', data[offset:offset+4])[0]
+ jal_inst = struct.unpack('<I', data[offset+4:offset+8])[0]
+ target = decode_jal_target(jal_inst, entry_addr + 8)
+ print(f" Subcmd {i:2d}: 0x{entry_addr:08x} -> jal 0x{target:08x}")
+
+# ============================================================
+# 4. TRACE MIGRATION (RPC 0x0B) IN DISPATCHERS
+# ============================================================
+print("\n" + "=" * 60)
+print("4. MIGRATION (RPC 0x0B) HANDLERS")
+print("=" * 60)
+
+# Primary dispatcher - look for RPC 0x0B branches
+print("\nPrimary Dispatcher (0x057a1ac0) MIGRATE branches:")
+offset = 0x57a1ac0 - BASE_ADDR
+for i in range(0, 3000, 2):
+ idx = offset + i
+ if idx + 4 <= len(data):
+ inst = struct.unpack('<I', data[idx:idx+4])[0]
+ opcode = inst & 0x7F
+ if opcode == 0x63: # branch
+ funct3 = (inst >> 12) & 0x7
+ rs1 = (inst >> 15) & 0x1F
+ rs2 = (inst >> 20) & 0x1F
+ imm = ((inst >> 31) & 0x1) << 12 | ((inst >> 7) & 0x1) << 11 | ((inst >> 25) & 0x3F) << 5 | ((inst >> 8) & 0xF) << 1
+ if imm & 0x1000: imm -= 0x2000
+ target = BASE_ADDR + idx + imm
+ # Check for nearby addi with imm=11 (MIGRATE)
+ for back in range(2, 20, 2):
+ if idx - back >= 0:
+ prev = struct.unpack('<I', data[idx-back:idx-back+4])[0]
+ if (prev & 0x7F) == 0x13 and ((prev >> 12) & 0x7) == 0:
+ prev_imm = (prev >> 20) & 0xFFF
+ if prev_imm >= 0x800: prev_imm -= 0x1000
+ if prev_imm == 11:
+ btype = ['beq','bne','?','?','blt','bge','bltu','bgeu'][funct3]
+ print(f" 0x{BASE_ADDR+idx:08x}: {btype} x{rs1}, x{rs2}, 0x{target:08x} (RPC=0x0B)")
+
+# Secondary dispatcher
+print("\nSecondary Dispatcher (0x04ed39dc) MIGRATE branches:")
+offset = 0xed39dc
+for i in range(0, 5000, 2):
+ idx = offset + i
+ if idx + 4 <= len(data):
+ inst = struct.unpack('<I', data[idx:idx+4])[0]
+ opcode = inst & 0x7F
+ if opcode == 0x63:
+ funct3 = (inst >> 12) & 0x7
+ rs1 = (inst >> 15) & 0x1F
+ rs2 = (inst >> 20) & 0x1F
+ imm = ((inst >> 31) & 0x1) << 12 | ((inst >> 7) & 0x1) << 11 | ((inst >> 25) & 0x3F) << 5 | ((inst >> 8) & 0xF) << 1
+ if imm & 0x1000: imm -= 0x2000
+ target = BASE_ADDR + idx + imm
+ for back in range(2, 20, 2):
+ if idx - back >= 0:
+ prev = struct.unpack('<I', data[idx-back:idx-back+4])[0]
+ if (prev & 0x7F) == 0x13 and ((prev >> 12) & 0x7) == 0:
+ prev_imm = (prev >> 20) & 0xFFF
+ if prev_imm >= 0x800: prev_imm -= 0x1000
+ if prev_imm == 11:
+ btype = ['beq','bne','?','?','blt','bge','bltu','bgeu'][funct3]
+ print(f" 0x{BASE_ADDR+idx:08x}: {btype} x{rs1}, x{rs2}, 0x{target:08x} (RPC=0x0B)")
+