#!/usr/bin/env python3 """RK3588 SPI image pre-flash integrity check. Verifies a u-boot-rockchip-spi*.bin image *before* the user commits to a maskrom-recovery-prone flash. Catches the class of silent-build failures that brick boards: - missing idbloader (binman packed 0xFF where RKNS wrapper should be) - truncated idbloader (less than the declared payload region) - mkimage-rejected TPL blob that left the SPL slot empty Does NOT execute code — pure static parsing. Fast and safe. Exit codes: 0 = image has a valid-looking idbloader; safe to flash 1 = file unreadable / too small 2 = missing RKNS wrapper at 0x8000 (the "today's bug" case) 3 = wrapper present but surrounding region is all 0xFF (payload missing) Usage: rk3588_spi_check.py """ import argparse, hashlib, struct import sys IDBL_OFFSET = 0x8000 RKNS_MAGIC = 0x534E4B52 # "RKNS" LE — rkspi boot header TPL_OFFSET = 0x8800 # plaintext DDR blob (TPL) starts here in rkspi layout TPL_ENTRY = bytes.fromhex("01000014") # first 4 bytes of the RK3588 DDR blob entry PAYLOAD_END = 0x60000 # stock u-boot places next section here def die(code, msg): print(f"FAIL: {msg}", file=sys.stderr) sys.exit(code) def main(path, blob_path=None): with open(path, "rb") as f: data = f.read() print(f"SPI image: {path} size=0x{len(data):x} ({len(data)} B)") if len(data) < PAYLOAD_END: die(1, f"image too small ({len(data)} < 0x{PAYLOAD_END:x})") wrapper = struct.unpack_from("