The blob is position-dependent: entry code at 0x14-0x1c does
(return_addr & 0xFFFFFF00) == 0xFF001000 to validate the caller.
Previously we loaded at 0x0, so the check could never pass and
emu hung at 0x1c forever.
Fixed: load blob at 0xFF001000 (bootrom TPL slot), map SRAM
window 0xFF000000..0xFF100000, let x30 point at RET_STUB outside
the window. Emu now runs through the integrity check, the first
~120 instructions of entry dispatch, and stops at blob+0x10A80
on an MSR/MRS sysreg access Unicorn doesn|t model -- the same
depth ddr_emu2.c (C version) historically reached.
Stock and patched (--sites all) behave identically under both
--stub 0x00 and 0xFF. That|s the regression gate: any future
patch that crashes in the pre-sysreg segment will diverge.
Also added catch-all UC_HOOK_MEM_UNMAPPED with lazy 64KB
page-map + stub fallback so unknown MMIO targets don|t crash
the emu before we know about them.
Executes a raw DDR blob in AArch64 Unicorn with configurable stub
byte (--stub 0x00 / 0xFF) returned for every MMIO read. Intent:
gate real-hardware flashing behind "blob doesn|t crash the emu
under either stubbing regime."
Validated against rk3588_ddr_lp4_1848MHz_lp5_2112MHz_v1.19.bin
(stock) and patch_timeouts_v3.py --sites all output: both reach
max_pc=0xe0 and HALT cleanly via the return stub at RET_STUB,
identical under 0x00 and 0xFF stubs.
Phase 2 of test harness task #31. Phase 1 (spi_check.py,
structural RKNS validation) committed earlier.