b37: S20 clock-dispatcher router
This commit is contained in:
@@ -179,3 +179,13 @@
|
|||||||
- Урок: полный IMEM-poison ломает IMEM-стек (счётчики читают
|
- Урок: полный IMEM-poison ломает IMEM-стек (счётчики читают
|
||||||
0xFFFFFFFF вместо свежих нулей → underflow → wild-pop). Только
|
0xFFFFFFFF вместо свежих нулей → underflow → wild-pop). Только
|
||||||
tripwire 4B на входе дрейфа `[0x8600000,0x8600004)`.
|
tripwire 4B на входе дрейфа `[0x8600000,0x8600004)`.
|
||||||
|
|
||||||
|
## b36: assert-entry to S19 (2026-09-13)
|
||||||
|
- sbl_mc assert-fn входит mid-way (`0x802F9A2`), минуя S19-hang'и.
|
||||||
|
Вход тоже в S19 (ест ldr + половину movw).
|
||||||
|
|
||||||
|
## b37: S20 clock-dispatcher router (2026-09-13)
|
||||||
|
- Голый clock-диспетчер (`0x800EB80`, без пушей) снимает `pop.w 0x30`
|
||||||
|
за проход → марш sp к верху IMEM. S20 (34B @0x08006D38):
|
||||||
|
`[sp+0x2C]` валиден → исходный pop; иначе r0=sl + re-run
|
||||||
|
(идемпотентная математика). Эпилог `pop.w` (4B) → `b.w S20`.
|
||||||
|
|||||||
+1
-1
@@ -5,7 +5,7 @@
|
|||||||
set -e
|
set -e
|
||||||
cd "$(dirname "$0")/.."
|
cd "$(dirname "$0")/.."
|
||||||
QEMU=~/qemu-src/qemu-8.2.2/build/qemu-system-arm
|
QEMU=~/qemu-src/qemu-8.2.2/build/qemu-system-arm
|
||||||
B=${1:-b36}
|
B=${1:-b37}
|
||||||
IMG=fw/img/emmc-real.img
|
IMG=fw/img/emmc-real.img
|
||||||
if [ ! -f "$IMG" ]; then
|
if [ ! -f "$IMG" ]; then
|
||||||
echo "no $IMG — сначала: python3 tools/ffu_extract.py fw/dl/RM1127_059X5R5_orig.ffu --emmc-user fw/img/user-real.bin"
|
echo "no $IMG — сначала: python3 tools/ffu_extract.py fw/dl/RM1127_059X5R5_orig.ffu --emmc-user fw/img/user-real.bin"
|
||||||
|
|||||||
+24
-5
@@ -104,15 +104,15 @@ static void saimaa_tmr_init(Object *obj)
|
|||||||
/* Stubs region handle for set_readonly after scaffold implant. */
|
/* Stubs region handle for set_readonly after scaffold implant. */
|
||||||
static MemoryRegion *saimaa_stubs_mr;
|
static MemoryRegion *saimaa_stubs_mr;
|
||||||
|
|
||||||
/* DDRLOW stub trap [0x08006B80,0x08006D30): serves the scaffolded bytes
|
/* DDRLOW stub trap [0x08006B80,0x08006D60): serves the scaffolded bytes
|
||||||
* (S/maze/S6/banner/S7/S9/S10/S16/S17 stubs) on read/fetch, ignores SBL
|
* (S/maze/S6/banner/S7/S9/S10/S16/S17/S18/S20 stubs) on read/fetch,
|
||||||
* heap-clobber writes. Uni parity: deferred-restore guard in sbl_uni.py
|
* ignores SBL heap-clobber writes. Uni parity: deferred-restore guard
|
||||||
* (wider: [0x080068C0,0x08006D30), also covers PBL stub).
|
* in sbl_uni.py (wider: [0x080068C0,0x08006D60), also covers PBL stub).
|
||||||
* Snapshot is taken AFTER ELF load + all stub writes (readback).
|
* Snapshot is taken AFTER ELF load + all stub writes (readback).
|
||||||
* PBL stub [0x080068C0,0x080068F4) and the ELF-text gap below stay plain
|
* PBL stub [0x080068C0,0x080068F4) and the ELF-text gap below stay plain
|
||||||
* RAM: PBL runs once (if at all), gap holds real hot SBL code. */
|
* RAM: PBL runs once (if at all), gap holds real hot SBL code. */
|
||||||
#define SAIMAA_DSTUB_BASE 0x08006B80
|
#define SAIMAA_DSTUB_BASE 0x08006B80
|
||||||
#define SAIMAA_DSTUB_SIZE 0x000001B0
|
#define SAIMAA_DSTUB_SIZE 0x000001E0
|
||||||
static uint8_t saimaa_dstub_mem[SAIMAA_DSTUB_SIZE];
|
static uint8_t saimaa_dstub_mem[SAIMAA_DSTUB_SIZE];
|
||||||
|
|
||||||
static uint64_t saimaa_dstub_read(void *opaque, hwaddr off, unsigned size)
|
static uint64_t saimaa_dstub_read(void *opaque, hwaddr off, unsigned size)
|
||||||
@@ -707,6 +707,25 @@ static void saimaa_machine_init(MachineState *machine)
|
|||||||
cpu_physical_memory_write(0x08006D22 + k, &word, 4);
|
cpu_physical_memory_write(0x08006D22 + k, &word, 4);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
/* S20 stublet at 0x08006D38 (34B, b37): clock-dispatcher
|
||||||
|
* router. [sp+0x2C] valid-code? => original pop.w (legit);
|
||||||
|
* else r0=sl + b.w dispatcher re-run (idempotent math). */
|
||||||
|
{
|
||||||
|
static const uint8_t s20[] = {
|
||||||
|
0x0b, 0x9b, 0x13, 0xf0, 0x01, 0x0f, 0x09, 0xd0,
|
||||||
|
0x1a, 0x0e, 0x08, 0x2a, 0x01, 0xd1, 0xbd, 0xe8,
|
||||||
|
0xfe, 0x8f, 0x1a, 0x0f, 0x08, 0x2a, 0x01, 0xd1,
|
||||||
|
0xbd, 0xe8, 0xfe, 0x8f, 0x50, 0x46, 0x07, 0xf0,
|
||||||
|
0x13, 0xbf,
|
||||||
|
};
|
||||||
|
size_t k;
|
||||||
|
for (k = 0; k < sizeof(s20); k += 4) {
|
||||||
|
uint32_t word = 0;
|
||||||
|
size_t n = sizeof(s20) - k < 4 ? sizeof(s20) - k : 4;
|
||||||
|
__builtin_memcpy(&word, &s20[k], n);
|
||||||
|
cpu_physical_memory_write(0x08006D38 + k, &word, 4);
|
||||||
|
}
|
||||||
|
}
|
||||||
/* S17 safe-logger (50B @0x08006CF0, b26): print r1-string
|
/* S17 safe-logger (50B @0x08006CF0, b26): print r1-string
|
||||||
* via UARTDM-TF iff r1 in rodata [0x804B800,0x8058000);
|
* via UARTDM-TF iff r1 in rodata [0x804B800,0x8058000);
|
||||||
* pop-return (no leak). Replaces S8 silence with logs. */
|
* pop-return (no leak). Replaces S8 silence with logs. */
|
||||||
|
|||||||
@@ -2171,6 +2171,129 @@ def main():
|
|||||||
|
|
||||||
save(d, 'img0_b36.elf')
|
save(d, 'img0_b36.elf')
|
||||||
|
|
||||||
|
# b37 = b36 + S20 clock-dispatcher router (0x800EB96 pop.w -> b.w):
|
||||||
|
# naked dispatcher (no pushes!) pops 0x30/pass, marching sp to IMEM
|
||||||
|
# top. S20 (34B @0x08006D38, scaffold): [sp+0x2C] valid-code?
|
||||||
|
# original pop.w (legit return); else r0=sl + re-run (idempotent).
|
||||||
|
d = bytearray(base)
|
||||||
|
|
||||||
|
for va, (a, b) in BLX2BL.items():
|
||||||
|
|
||||||
|
set4(d, va, b)
|
||||||
|
|
||||||
|
for va, exp, new in [
|
||||||
|
|
||||||
|
(0x802F664, 'e4f77efc', 'c046c046'),
|
||||||
|
|
||||||
|
(0x802F672, 'e6f7bbfa', 'c046c046'),
|
||||||
|
|
||||||
|
(0x802F678, 'e9f7fef9', 'c046c046'),
|
||||||
|
|
||||||
|
(0x801B71E, '9847fee7', 'c046c046'),
|
||||||
|
|
||||||
|
(0x8008396, 'fef780f9', 'c046c046'),
|
||||||
|
|
||||||
|
(0x8016184, 'fdf790fc', 'c046c046'),
|
||||||
|
|
||||||
|
(0x801B76C, '280b0508', '00000708'),
|
||||||
|
|
||||||
|
(0x8017AFC, 'bde8fc87', 'eef74fb8'),
|
||||||
|
|
||||||
|
(0x802F690, '9847fee7', 'c046c046'),
|
||||||
|
|
||||||
|
(0x801671C, '9847fee7', 'c046c046'),
|
||||||
|
|
||||||
|
(0x8013BAC, 'f8bd0a4a', 'f3f730b8'),
|
||||||
|
|
||||||
|
(0x801B6BE, 'bde8f081', 'ebf7c3ba'),
|
||||||
|
|
||||||
|
(0x8016720, '10bd0000', 'f0f7b2ba'),
|
||||||
|
|
||||||
|
(0x8034810, 'bde8fc87', 'd2f76eba'),
|
||||||
|
|
||||||
|
(0x8007798, 'bde8f08f', 'fff7c3ba'),
|
||||||
|
|
||||||
|
(0x8016334, 'f0f7a4ff', 'c046c046'),
|
||||||
|
|
||||||
|
(0x8016342, 'f0f79eef', 'f0f79dbf'),
|
||||||
|
|
||||||
|
(0x802F9A0, 'ffe70648', 'd7f7c4b9'),
|
||||||
|
|
||||||
|
(0x802F9B2, 'fee78817', 'd7f7bbb9'),
|
||||||
|
|
||||||
|
(0x802F9A2, 'c4b943f2', 'd7f7c3b9'),
|
||||||
|
|
||||||
|
(0x800EB96, 'bde8fe8f', 'f8f7cfb8'),
|
||||||
|
|
||||||
|
]:
|
||||||
|
|
||||||
|
assert hx(d, va) == exp, (hex(va), hx(d, va))
|
||||||
|
|
||||||
|
set4(d, va, new)
|
||||||
|
|
||||||
|
# Full bl idiom at 0x8006682 (bl + pop, 6B) -> NOPs (see b18).
|
||||||
|
o = off(0x8006682)
|
||||||
|
|
||||||
|
assert d[o:o + 6].hex() == '00f001f807bd', hx(d, 0x8006682, 6)
|
||||||
|
|
||||||
|
d[o:o + 6] = bytes.fromhex('c046c046c046')
|
||||||
|
|
||||||
|
o = off(0x8013AA8)
|
||||||
|
|
||||||
|
assert d[o:o + 4].hex() == '07f026be', hx(d, 0x8013AA8)
|
||||||
|
|
||||||
|
d[o:o + 4] = bytes.fromhex('c046c046')
|
||||||
|
|
||||||
|
o = off(0x8013BA6)
|
||||||
|
|
||||||
|
assert d[o:o + 2].hex() == 'b888', (hex(0x8013BA6), hx(d, 0x8013BA6, 2))
|
||||||
|
|
||||||
|
d[o:o + 2] = bytes.fromhex('ff20')
|
||||||
|
|
||||||
|
# Helper-pop S16 chain (see b25).
|
||||||
|
o = off(0x8007B66)
|
||||||
|
|
||||||
|
assert d[o:o + 2].hex() == '10bd', hx(d, 0x8007B66, 2)
|
||||||
|
|
||||||
|
d[o:o + 2] = bytes.fromhex('6047')
|
||||||
|
|
||||||
|
# Clock S11 (see b24).
|
||||||
|
o = off(0x800E988)
|
||||||
|
|
||||||
|
assert d[o:o + 2].hex() == '10bd', hx(d, 0x800E988, 2)
|
||||||
|
|
||||||
|
d[o:o + 2] = bytes.fromhex('7047')
|
||||||
|
|
||||||
|
# Poll re-init skip (see b27).
|
||||||
|
o = off(0x8007748)
|
||||||
|
|
||||||
|
assert d[o:o + 2].hex() == '96b1', hx(d, 0x8007748, 2)
|
||||||
|
|
||||||
|
d[o:o + 2] = bytes.fromhex('14e0')
|
||||||
|
|
||||||
|
# Poll-epilogue add NOP (see b28).
|
||||||
|
o = off(0x8007794)
|
||||||
|
|
||||||
|
assert d[o:o + 2].hex() == '07b0', hx(d, 0x8007794, 2)
|
||||||
|
|
||||||
|
d[o:o + 2] = bytes.fromhex('c046')
|
||||||
|
|
||||||
|
# Partition wrap-check (see b33).
|
||||||
|
o = off(0x801844E)
|
||||||
|
|
||||||
|
assert d[o:o + 2].hex() == '04d3', hx(d, 0x801844E, 2)
|
||||||
|
|
||||||
|
d[o:o + 2] = bytes.fromhex('04e0')
|
||||||
|
|
||||||
|
# Hang-site neutralize (see b34).
|
||||||
|
o = off(0x8018458)
|
||||||
|
|
||||||
|
assert d[o:o + 2].hex() == 'fee7', hx(d, 0x8018458, 2)
|
||||||
|
|
||||||
|
d[o:o + 2] = bytes.fromhex('ffe7')
|
||||||
|
|
||||||
|
save(d, 'img0_b37.elf')
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
+7
-1
@@ -426,6 +426,12 @@ def main():
|
|||||||
# S18 stublet (10B @0x08006D22, b29): poll-epilogue router.
|
# S18 stublet (10B @0x08006D22, b29): poll-epilogue router.
|
||||||
# movw/movt ip + bx ip to sbl_main 0x802f6a9 (post-dispatcher).
|
# movw/movt ip + bx ip to sbl_main 0x802f6a9 (post-dispatcher).
|
||||||
mu.mem_write(0x08006D22, bytes.fromhex("4ff2a96cc0f6020c6047"))
|
mu.mem_write(0x08006D22, bytes.fromhex("4ff2a96cc0f6020c6047"))
|
||||||
|
# S20 stublet (34B @0x08006D38, b37): clock-dispatcher router.
|
||||||
|
# [sp+0x2C] valid-code? => original pop.w (legit return);
|
||||||
|
# else r0=sl (PBL tables) + b.w dispatcher re-run (idempotent math).
|
||||||
|
mu.mem_write(0x08006D38, bytes.fromhex(
|
||||||
|
"0b9b13f0010f09d01a0e082a01d1bde8fe8f1a0f082a"
|
||||||
|
"01d1bde8fe8f504607f013bf"))
|
||||||
# S17 safe-logger (50B @0x08006CF0, b26): print r1-string via
|
# S17 safe-logger (50B @0x08006CF0, b26): print r1-string via
|
||||||
# UARTDM-TF only if r1 in rodata [0x804B800,0x8058000); pop-return.
|
# UARTDM-TF only if r1 in rodata [0x804B800,0x8058000); pop-return.
|
||||||
mu.mem_write(0x08006CF0, bytes.fromhex(
|
mu.mem_write(0x08006CF0, bytes.fromhex(
|
||||||
@@ -513,7 +519,7 @@ def main():
|
|||||||
# --- end parity ---
|
# --- end parity ---
|
||||||
# stub range is readonly on HW/QEMU: ignore SBL heap-clobber writes,
|
# stub range is readonly on HW/QEMU: ignore SBL heap-clobber writes,
|
||||||
# keep maze/stublets intact (restore-on-write with reentrancy guard)
|
# keep maze/stublets intact (restore-on-write with reentrancy guard)
|
||||||
STUB_LO, STUB_HI = 0x080068C0, 0x08006D30 # +S7/S9/S10/S16/S17
|
STUB_LO, STUB_HI = 0x080068C0, 0x08006D60 # +S7/S9/S10/S16/S17/S18/S20
|
||||||
stub_snap = bytes(mu.mem_read(STUB_LO, STUB_HI - STUB_LO))
|
stub_snap = bytes(mu.mem_read(STUB_LO, STUB_HI - STUB_LO))
|
||||||
_inww = [False]
|
_inww = [False]
|
||||||
_swn = [0]
|
_swn = [0]
|
||||||
|
|||||||
Reference in New Issue
Block a user