Add G2 bootloader and EEPROM exploration scripts
boot_baud_probe.py: Probe all standard baud rates during G2 power-on to detect bootloader UART configuration differences. boot_capture.py: Capture and analyze G2 boot sequence output, with optional interrupt sequence injection to explore bootloader entry. ee_dump.py: Dump EEPROM indices from EE> submenu, identifying initialized vs. uninitialized (0x10101 sentinel) entries.
This commit is contained in:
parent
145763fcfb
commit
13a9d804c6
3 changed files with 502 additions and 0 deletions
76
scripts/ee_dump.py
Normal file
76
scripts/ee_dump.py
Normal file
|
|
@ -0,0 +1,76 @@
|
|||
#!/usr/bin/env python3
|
||||
"""Dump all EEPROM indices from Winegard G2 firmware via RS-422."""
|
||||
|
||||
import re
|
||||
import sys
|
||||
import time
|
||||
|
||||
import serial
|
||||
|
||||
PORT = "/dev/ttyUSB2"
|
||||
BAUD = 115200
|
||||
PROMPT = b">"
|
||||
MAX_INDEX = 100 # scan up to this index
|
||||
|
||||
|
||||
def send_cmd(ser: serial.Serial, cmd: str) -> str:
|
||||
"""Send command + CR, read until prompt '>'."""
|
||||
ser.reset_input_buffer()
|
||||
ser.write(f"{cmd}\r".encode("ascii"))
|
||||
buf = bytearray()
|
||||
while True:
|
||||
b = ser.read(1)
|
||||
if len(b) == 0:
|
||||
break # timeout
|
||||
buf.append(b[0])
|
||||
if b[0] == ord(">"):
|
||||
break
|
||||
return buf.decode("utf-8", errors="ignore")
|
||||
|
||||
|
||||
def main():
|
||||
ser = serial.Serial(PORT, BAUD, timeout=3)
|
||||
time.sleep(0.1)
|
||||
|
||||
# Navigate to EE submenu
|
||||
send_cmd(ser, "q") # ensure root
|
||||
resp = send_cmd(ser, "eeprom")
|
||||
if "EE>" not in resp:
|
||||
print(f"Failed to enter EEPROM menu: {resp!r}", file=sys.stderr)
|
||||
ser.close()
|
||||
sys.exit(1)
|
||||
|
||||
print(f"{'Index':>5} {'Decimal':>10} {'Hex':>10} Status")
|
||||
print("-" * 50)
|
||||
|
||||
valid_count = 0
|
||||
for idx in range(MAX_INDEX + 1):
|
||||
resp = send_cmd(ser, f"ee {idx}")
|
||||
|
||||
# Parse response
|
||||
if "Read value" in resp:
|
||||
match = re.search(r"Read value = (\d+)", resp)
|
||||
if match:
|
||||
val = int(match.group(1))
|
||||
print(f"{idx:>5} {val:>10} 0x{val:08X} OK")
|
||||
valid_count += 1
|
||||
elif "Failed to read" in resp:
|
||||
match = re.search(r"val:(\d+)", resp)
|
||||
val_str = match.group(1) if match else "?"
|
||||
val = int(val_str) if val_str != "?" else 0
|
||||
print(f"{idx:>5} {val:>10} 0x{val:08X} INVALID")
|
||||
else:
|
||||
# Unknown response - might be end of range
|
||||
clean = resp.strip().replace("\r\n", " | ")
|
||||
print(f"{idx:>5} {'':>10} {'':>10} ERROR: {clean}")
|
||||
|
||||
print("-" * 50)
|
||||
print(f"Valid entries: {valid_count} / {MAX_INDEX + 1}")
|
||||
|
||||
# Return to root
|
||||
send_cmd(ser, "q")
|
||||
ser.close()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Loading…
Add table
Add a link
Reference in a new issue