From 830283e12bcbce436047fc17a3d74d260cd84d74 Mon Sep 17 00:00:00 2001 From: lumia-emu Date: Sun, 13 Sep 2026 10:37:18 +0000 Subject: [PATCH] b23: S10 + table poke + S9 baked --- docs/sbl-bringup.md | 15 +++++++++ qemu/saimaa.c | 31 ++++++++++++++++--- tools/sbl_patch.py | 74 +++++++++++++++++++++++++++++++++++++++++++++ tools/sbl_uni.py | 8 ++++- 4 files changed, 122 insertions(+), 6 deletions(-) diff --git a/docs/sbl-bringup.md b/docs/sbl-bringup.md index b2ea868..724be93 100644 --- a/docs/sbl-bringup.md +++ b/docs/sbl-bringup.md @@ -75,3 +75,18 @@ 0x8610000; QEMU: null-jump → maze-hang c lr-top 0x80), регион тот же. - Следующий фронт (оба): лабиринт `0x801B6xx` (логгер, r7=0/r4=0, pop пустого стека). Кандидаты: S8-стаблет, таблица логгера. + +## b21-b23: логгер, S9, S10, rollback (2026-09-12) +- Логгер `0x8034810` = голый `pop.w 0x28` без push (жрал стек) → S8: + вход → `bx lr` (b21). Возврат игнорируется (callers ставят r0=0). +- Лабиринт `0x801B6A0`: счётчик `[r4]++` + `pop.w` на пустых фреймах + (r4/r7=STUBV из fill) → S9 (b22): `[sp+0x14]` ненулевой → исходный + pop; ноль → restore r0/r4/r5/sl/fp + **reset sp=0x085FFF00** + + прыжок в sbl_main `0x802f69d` через ip (без литералов). +- Rollback `boot_rollback_version.c:580` (query всегда `0x302E`) → NOP NOP + (b22, возврат игнорируется). Query зовёт `*table[0x080528D0]` (нули) → + фабрикация: poke STUBV (maze вернёт 0 = версии OK) (b23). +- Rollback выходил боком в helper-mid (`pop{r4,pc}` без push) → S10 (b23): + `movw/movt ip + bx ip` в sbl_main `0x802f6a3`. +- b23: 2M инстр. без падений (sp здоров), sbl_main идёт дальше + (`0x80164C4`-subtree → прыжок в OCIMEM-нули `0x222F84` — фронт PBL-данных). diff --git a/qemu/saimaa.c b/qemu/saimaa.c index 38a551c..4d62a50 100644 --- a/qemu/saimaa.c +++ b/qemu/saimaa.c @@ -104,15 +104,15 @@ static void saimaa_tmr_init(Object *obj) /* Stubs region handle for set_readonly after scaffold implant. */ static MemoryRegion *saimaa_stubs_mr; -/* DDRLOW stub trap [0x08006B80,0x08006C90): serves the scaffolded bytes - * (S/maze/S6/banner/S7/S9 stubs) on read/fetch, ignores SBL heap-clobber - * writes. Uni parity: deferred-restore guard in sbl_uni.py (wider: - * [0x080068C0,0x08006C90), also covers PBL stub). +/* DDRLOW stub trap [0x08006B80,0x08006CA0): serves the scaffolded bytes + * (S/maze/S6/banner/S7/S9/S10 stubs) on read/fetch, ignores SBL + * heap-clobber writes. Uni parity: deferred-restore guard in sbl_uni.py + * (wider: [0x080068C0,0x08006CA0), also covers PBL stub). * Snapshot is taken AFTER ELF load + all stub writes (readback). * 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. */ #define SAIMAA_DSTUB_BASE 0x08006B80 -#define SAIMAA_DSTUB_SIZE 0x00000110 +#define SAIMAA_DSTUB_SIZE 0x00000120 static uint8_t saimaa_dstub_mem[SAIMAA_DSTUB_SIZE]; static uint64_t saimaa_dstub_read(void *opaque, hwaddr off, unsigned size) @@ -677,6 +677,27 @@ static void saimaa_machine_init(MachineState *machine) cpu_physical_memory_write(0x08006C48 + k, &word, 4); } } + /* S10 stublet at 0x08006C88 (10B, b23): rollback-exit router. + * movw/movt ip + bx ip to sbl_main 0x802f6a3. */ + { + static const uint8_t s10[] = { + 0x4f, 0xf2, 0xa3, 0x6c, 0xc0, 0xf6, 0x02, 0x0c, + 0x60, 0x47, + }; + size_t k; + for (k = 0; k < sizeof(s10); k += 4) { + uint32_t word = 0; + size_t n = sizeof(s10) - k < 4 ? sizeof(s10) - k : 4; + __builtin_memcpy(&word, &s10[k], n); + cpu_physical_memory_write(0x08006C88 + k, &word, 4); + } + } + /* PBL version-table fabrication (b23): [0x080528D0] = STUBV + * so the rollback query's blx calls maze (0 = versions OK). */ + { + uint32_t v = 0x08006B8D; + cpu_physical_memory_write(0x080528D0, &v, 4); + } { uint32_t fill = 0x08006B8D; uint32_t a; diff --git a/tools/sbl_patch.py b/tools/sbl_patch.py index 483122d..b8663f5 100644 --- a/tools/sbl_patch.py +++ b/tools/sbl_patch.py @@ -800,6 +800,80 @@ def main(): save(d, 'img0_b22.elf') + # b23 = b22 + S10 (rollback sideways-exit fix): + # 0x8016720 pop{r4,pc} has no matching push; it exits sideways to + # helper-mid (0x8005BBA) instead of sbl_main (0x802f6a3), closing a + # ping-pong cycle (S9->rollback->query->helper->assert->labyrinth). + # Route to S10 (0x08006C88, scaffold): movw/movt ip + bx ip to + # 0x802f6a3. Eats the following NOP (movs r0,r0). + 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'), + + ]: + + 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') + + # Logger S8 (see b21). + o = off(0x8034810) + + assert d[o:o + 4].hex() == 'bde8fc87', hx(d, 0x8034810) + + d[o:o + 2] = bytes.fromhex('7047') + + save(d, 'img0_b23.elf') + diff --git a/tools/sbl_uni.py b/tools/sbl_uni.py index cf94ef0..92fec15 100644 --- a/tools/sbl_uni.py +++ b/tools/sbl_uni.py @@ -325,6 +325,12 @@ def main(): "059b0bb1bde8f081002040f20004c0f2220440f20005c0f2" "220540f2000ac0f6060a41f2000bc0f6060b4ff60073c0f6" "5f039d464ff29d6cc0f6020c6047")) + # S10 stublet (10B @0x08006C88, b23): rollback-exit router. + # movw/movt ip + bx ip to sbl_main 0x802f6a3. + mu.mem_write(0x08006C88, bytes.fromhex("4ff2a36cc0f6020c6047")) + # PBL version-table fabrication (b23): [0x080528D0] = STUBV so the + # rollback query's blx calls maze (returns 0 = versions OK). + W32(0x080528D0, STUBV) # stack zone fill (STUBV odd) mu.mem_write(0x085F0000, struct.pack("