Compare commits
17 Commits
dcfdeef917
...
8aef555346
| Author | SHA1 | Date | |
|---|---|---|---|
| 8aef555346 | |||
| d3e2efe7ba | |||
| 3d011f2994 | |||
| 785eb934e6 | |||
| 4fcb316c99 | |||
| 8ce95238e0 | |||
| f46e4e94fe | |||
| 9187bdcff0 | |||
| 5362f0a6f8 | |||
| 503c334b2e | |||
| 2a3bdcd72d | |||
| d0a62a86c8 | |||
| 66b1721b7a | |||
| ae9ad07370 | |||
| 308e8aa2af | |||
| 110a60562c | |||
| 8cd7c85771 |
@@ -144,3 +144,65 @@
|
|||||||
- b28-NOP убрал только +0x1C; `pop.w 0x14` без пушей всё равно марширует.
|
- b28-NOP убрал только +0x1C; `pop.w 0x14` без пушей всё равно марширует.
|
||||||
S18 (10B @0x08006D22): слепой прыжок в sbl_main `0x802F6A9`
|
S18 (10B @0x08006D22): слепой прыжок в sbl_main `0x802F6A9`
|
||||||
(post-dispatcher). Эпилог `pop.w` (4B) → `b.w S18`.
|
(post-dispatcher). Эпилог `pop.w` (4B) → `b.w S18`.
|
||||||
|
|
||||||
|
## b30: epilogue blx (2026-09-13)
|
||||||
|
- sbl_main дошёл до `0x8016320` (logger-ish, грузит магию "SBL1"),
|
||||||
|
тот зовёт shared-эпилог `0x8007280` (Thumb!) через `blx`-imm
|
||||||
|
(чётный → ARM → fault на coprocessor-мусоре). Патч в глобальной
|
||||||
|
BLX2BL (`blx` → `bl`, как остальные). r7="SBL1", r0=SMEM — читает
|
||||||
|
настоящие таблицы!
|
||||||
|
|
||||||
|
## b31: logger-epilogue NOP (2026-09-13)
|
||||||
|
- `0x8016320` зовёт эпилог `0x8007280`, чей pop читает fill/STUBV →
|
||||||
|
maze → stale-lr в logger-mid → снова blx эпилог (голая взаимная
|
||||||
|
рекурсия). Вызов скипается (NOP NOP); sbl_main идёт дальше
|
||||||
|
`0x802F6B0` в свежий код.
|
||||||
|
|
||||||
|
## b32: logger-tail b.w (2026-09-13)
|
||||||
|
- 9-й вызывающий shared-эпилога (`0x8016342 blx`, пропущен статикой):
|
||||||
|
точный `b.w` (флип съезжает +2). r7="SBL1" магика из настоящих таблиц.
|
||||||
|
|
||||||
|
## b33: partition wrap-check (2026-09-13)
|
||||||
|
- Валидатор партиций (`adds; blo success`, line 0x1FD) ассёртит:
|
||||||
|
r0+r4 не враппаются (PBL-таблицы нулевые, r4 stale). `blo` → `b`
|
||||||
|
(2B). TODO(MainOS): настоящие PBL/SMEM partition tables.
|
||||||
|
|
||||||
|
## b34: hang neutralize (2026-09-13)
|
||||||
|
- Assert-hang `0x8018458` (`b .`) достигается напрямую через
|
||||||
|
maze-stale-lr (мимо патченного wrap-check). `b .` → `b success`
|
||||||
|
(2B, в success-путь).
|
||||||
|
|
||||||
|
## b35: sbl_mc hangs (2026-09-13)
|
||||||
|
- Мёртвая assert-fn `sbl_mc.c:320` (`0x802F9A0-b.`, `0x802F9B2-b.`)
|
||||||
|
достигается accident'ом (pop-garbage). Оба hang'а → S19
|
||||||
|
(рестарт post-logger init, bounded table work). 4B `b.w` каждый.
|
||||||
|
- Урок: полный IMEM-poison ломает IMEM-стек (счётчики читают
|
||||||
|
0xFFFFFFFF вместо свежих нулей → underflow → wild-pop). Только
|
||||||
|
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`.
|
||||||
|
|
||||||
|
## b38: S21 table-walker router (2026-09-13)
|
||||||
|
- Голый table-walker (`0x8007916`, mid-входы без пушей) снимает
|
||||||
|
`pop.w 0x28`, читает saved-FP (`0x85FFEB0`) как pc → ARM fill-дрейф
|
||||||
|
(STM-clobbers!). S21 (32B @0x08006D5A): `[sp+0x24]` валиден →
|
||||||
|
исходный pop; иначе `b.w S19`. Эпилог `pop.w` (4B) → `b.w S21`.
|
||||||
|
|
||||||
|
## 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`.
|
||||||
|
|
||||||
|
## maze v2 (2026-09-13)
|
||||||
|
- Maze с чётным lr уходил в ARM-дрейф (STM-clobbers + IMEM fault).
|
||||||
|
Maze v2 (24B): возврат только при odd Thumb lr из DDR, иначе hang
|
||||||
|
громко. Залез на голову S6 (`[B9E,BA4)`, S6 dormant). Vec-maze тоже v2.
|
||||||
|
|||||||
+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:-b29}
|
B=${1:-b38}
|
||||||
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"
|
||||||
|
|||||||
+86
-47
@@ -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,0x08006D80): 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/S21 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,0x08006D80), 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 0x00000200
|
||||||
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)
|
||||||
@@ -167,14 +167,15 @@ struct SaimaaUartState {
|
|||||||
static int saimaa_vec_n;
|
static int saimaa_vec_n;
|
||||||
static uint64_t saimaa_vec_read(void *opaque, hwaddr off, unsigned size)
|
static uint64_t saimaa_vec_read(void *opaque, hwaddr off, unsigned size)
|
||||||
{
|
{
|
||||||
/* Maze blob mirrored at [0,18) for THUMB fetches: null-jump fetches
|
/* Maze blob v2 mirrored at [0,24) for THUMB fetches: null-jump
|
||||||
* (bx r0=0, pop 0, ldr pc,=0) execute the maze and return via lr —
|
* fetches (bx r0=0, pop 0, ldr pc,=0) execute the maze and return
|
||||||
* uni parity (hook_null -> STUB). ARM-mode fetches (real exception
|
* via lr — uni parity (hook_null -> STUB). ARM-mode fetches (real
|
||||||
* entry) keep BKPT vectors below. Data probes elsewhere read 0. */
|
* exception entry) keep BKPT vectors below. Data probes elsewhere
|
||||||
static const uint8_t maze[18] = {
|
* read 0. */
|
||||||
|
static const uint8_t maze[24] = {
|
||||||
0x00, 0x20, 0x4f, 0xea, 0x1e, 0x6c, 0xbc, 0xf1,
|
0x00, 0x20, 0x4f, 0xea, 0x1e, 0x6c, 0xbc, 0xf1,
|
||||||
0x08, 0x0f, 0x00, 0xd1, 0x70, 0x47, 0x72, 0xb6,
|
0x08, 0x0f, 0x03, 0xd1, 0x1e, 0xf0, 0x01, 0x0f,
|
||||||
0xfd, 0xe7,
|
0x00, 0xd0, 0x70, 0x47, 0x72, 0xb6, 0xfd, 0xe7,
|
||||||
};
|
};
|
||||||
{
|
{
|
||||||
ARMCPU *cpu = ARM_CPU(current_cpu);
|
ARMCPU *cpu = ARM_CPU(current_cpu);
|
||||||
@@ -555,13 +556,15 @@ static void saimaa_machine_init(MachineState *machine)
|
|||||||
cpu_physical_memory_write(S + 4, &STUBV, 4);
|
cpu_physical_memory_write(S + 4, &STUBV, 4);
|
||||||
cpu_physical_memory_write(S + 8, &STUBV, 4);
|
cpu_physical_memory_write(S + 8, &STUBV, 4);
|
||||||
{
|
{
|
||||||
/* Minimal maze: movs r0,#0; bx lr (4B). No mailbox, no
|
/* Maze v2 (24B @STUB): movs r0,#0; return 0 via lr ONLY
|
||||||
* guard — vec trap already reports fault state. Less
|
* if lr is odd Thumb in DDR (top 8); even lr (stale
|
||||||
* surface for SBL heap clobbers. */
|
* mid-fn raw addr!) would ARM-drift (STM-clobbers +
|
||||||
|
* IMEM fault), so hang loud instead. Overlaps S6 head
|
||||||
|
* ([B9E,BA4), S6 dormant, documented below). */
|
||||||
static const uint8_t mb[] = {
|
static const uint8_t mb[] = {
|
||||||
0x00, 0x20, 0x4f, 0xea, 0x1e, 0x6c, 0xbc, 0xf1,
|
0x00, 0x20, 0x4f, 0xea, 0x1e, 0x6c, 0xbc, 0xf1,
|
||||||
0x08, 0x0f, 0x00, 0xd1, 0x70, 0x47, 0x72, 0xb6,
|
0x08, 0x0f, 0x03, 0xd1, 0x1e, 0xf0, 0x01, 0x0f,
|
||||||
0xfd, 0xe7,
|
0x00, 0xd0, 0x70, 0x47, 0x72, 0xb6, 0xfd, 0xe7,
|
||||||
};
|
};
|
||||||
size_t k;
|
size_t k;
|
||||||
for (k = 0; k < sizeof(mb); k += 4) {
|
for (k = 0; k < sizeof(mb); k += 4) {
|
||||||
@@ -574,23 +577,11 @@ static void saimaa_machine_init(MachineState *machine)
|
|||||||
cpu_physical_memory_write(0x087c29d18, &S, 4);
|
cpu_physical_memory_write(0x087c29d18, &S, 4);
|
||||||
cpu_physical_memory_write(0x08050b28, &S, 4);
|
cpu_physical_memory_write(0x08050b28, &S, 4);
|
||||||
cpu_physical_memory_write(0x08070000, &S, 4);
|
cpu_physical_memory_write(0x08070000, &S, 4);
|
||||||
/* S6 stublet at 0x08006B9E: rebuild popped frame regs,
|
/* S6 stublet DISABLED (maze v2 overlaps its head [B9E,BA4);
|
||||||
* return to 0x8013ba5 (b14 redirects 0x8017afc pop here) */
|
* S6 dormant, never entered (b14 goes to 0x8005B9E).
|
||||||
{
|
* Bytes kept for reference (would live at 0x08006B9E):
|
||||||
static const uint8_t s6[] = {
|
* ldmia.w sp!,{r2-r9,sl,lr}; movw lr,#0x3ba5;
|
||||||
0xbd, 0xe8, 0xfc, 0x47, /* ldmia.w sp!,{r2-r9,sl,lr} */
|
* movt lr,#0x801; bx lr. */
|
||||||
0x43, 0xf6, 0xa5, 0x3e, /* movw lr,#0x3ba5 */
|
|
||||||
0xc0, 0xf6, 0x01, 0x0e, /* movt lr,#0x801 */
|
|
||||||
0x70, 0x47, /* bx lr */
|
|
||||||
};
|
|
||||||
size_t k;
|
|
||||||
for (k = 0; k < sizeof(s6); k += 4) {
|
|
||||||
uint32_t word = 0;
|
|
||||||
size_t n = sizeof(s6) - k < 4 ? sizeof(s6) - k : 4;
|
|
||||||
__builtin_memcpy(&word, &s6[k], n);
|
|
||||||
cpu_physical_memory_write(0x08006B9E + k, &word, 4);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/* Banner stub at 0x08006BAC: print r0 string via UARTDM
|
/* Banner stub at 0x08006BAC: print r0 string via UARTDM
|
||||||
* (b16 redirects 0x802f690 blx here). Built from qemu/banner.S:
|
* (b16 redirects 0x802f690 blx here). Built from qemu/banner.S:
|
||||||
* push frame, print loop, ldr pc,=0x802f694 (callee noreturn).
|
* push frame, print loop, ldr pc,=0x802f694 (callee noreturn).
|
||||||
@@ -707,6 +698,43 @@ static void saimaa_machine_init(MachineState *machine)
|
|||||||
cpu_physical_memory_write(0x08006D22 + k, &word, 4);
|
cpu_physical_memory_write(0x08006D22 + k, &word, 4);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
/* S21 stublet at 0x08006D5A (32B, b38): table-walker router.
|
||||||
|
* [sp+0x24] valid-code? => original pop.w (legit return);
|
||||||
|
* else b.w S19 (sbl_main post-logger restart). */
|
||||||
|
{
|
||||||
|
static const uint8_t s21[] = {
|
||||||
|
0x09, 0x9b, 0x13, 0xf0, 0x01, 0x0f, 0x09, 0xd0,
|
||||||
|
0x1a, 0x0e, 0x08, 0x2a, 0x01, 0xd1, 0xbd, 0xe8,
|
||||||
|
0xf0, 0x9f, 0x1a, 0x0f, 0x08, 0x2a, 0x01, 0xd1,
|
||||||
|
0xbd, 0xe8, 0xf0, 0x9f, 0xff, 0xf7, 0xd9, 0xbf,
|
||||||
|
};
|
||||||
|
size_t k;
|
||||||
|
for (k = 0; k < sizeof(s21); k += 4) {
|
||||||
|
uint32_t word = 0;
|
||||||
|
size_t n = sizeof(s21) - k < 4 ? sizeof(s21) - k : 4;
|
||||||
|
__builtin_memcpy(&word, &s21[k], n);
|
||||||
|
cpu_physical_memory_write(0x08006D5A + 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. */
|
||||||
@@ -734,6 +762,19 @@ static void saimaa_machine_init(MachineState *machine)
|
|||||||
uint32_t v = 0x08006B8D;
|
uint32_t v = 0x08006B8D;
|
||||||
cpu_physical_memory_write(0x080528D0, &v, 4);
|
cpu_physical_memory_write(0x080528D0, &v, 4);
|
||||||
}
|
}
|
||||||
|
/* PBL dispatcher-table fabrication (b33, moved b37): retarget
|
||||||
|
* literal [0x80164F0] (image: hash blob!) to scratch struct
|
||||||
|
* at 0x08024000 (OCIMEM, out of stack-march paths!) with
|
||||||
|
* [0x18]=2 (ready -> dispatch). Was IMEM 0x08600200
|
||||||
|
* (self-executed when sp marched there!). */
|
||||||
|
{
|
||||||
|
uint32_t v = 0x08024000;
|
||||||
|
cpu_physical_memory_write(0x08024000, &v, 4);
|
||||||
|
v = 0x00000002;
|
||||||
|
cpu_physical_memory_write(0x08024014, &v, 4);
|
||||||
|
v = 0x08024000;
|
||||||
|
cpu_physical_memory_write(0x080164F0, &v, 4);
|
||||||
|
}
|
||||||
/* HW-ready bits (b25/b26): [0x073A100] bits 0,1,2 (SBL
|
/* HW-ready bits (b25/b26): [0x073A100] bits 0,1,2 (SBL
|
||||||
* read-only polls: bit2 poll#1, bit1 poll#2, bit0 gate). */
|
* read-only polls: bit2 poll#1, bit1 poll#2, bit0 gate). */
|
||||||
{
|
{
|
||||||
@@ -747,21 +788,22 @@ static void saimaa_machine_init(MachineState *machine)
|
|||||||
uint32_t v = 0x47702000;
|
uint32_t v = 0x47702000;
|
||||||
cpu_physical_memory_write(0x00221EF8, &v, 4);
|
cpu_physical_memory_write(0x00221EF8, &v, 4);
|
||||||
}
|
}
|
||||||
/* S12-stub (b27, 92B @0x08006964, ARM): blx-to-padding
|
/* S12-stub (b27, 100B @0x08006964, ARM): blx-to-padding
|
||||||
* becomes smart dispatcher: ldr ip,[sp,#4] (=pushed lr);
|
* becomes smart dispatcher: ldr ip,[sp,#4] (=pushed lr);
|
||||||
* ip==STUBV/even/non-code => ip=poll resumption 0x8007779;
|
* ip==STUBV/even/non-code => ip=poll resumption 0x8007779;
|
||||||
* else keep pushed-lr; restore r7 (peripheral base);
|
* else keep pushed-lr (NO add-sp!); restore r7;
|
||||||
* ACK peripheral bit1 ([literal 0x073A100]); bx lr.
|
* ACK peripheral bit1 ([literal 0x073A100]); bx lr.
|
||||||
* PBL would place the real ARM helper here. */
|
* PBL would place the real ARM helper here. */
|
||||||
{
|
{
|
||||||
static const uint8_t s12[] = {
|
static const uint8_t s12[] = {
|
||||||
0x04, 0xc0, 0x9d, 0xe5, 0x8d, 0x3b, 0x06, 0xe3,
|
0x04, 0xc0, 0x9d, 0xe5, 0x8d, 0x3b, 0x06, 0xe3,
|
||||||
0x00, 0x38, 0x40, 0xe3, 0x03, 0x00, 0x5c, 0xe1,
|
0x00, 0x38, 0x40, 0xe3, 0x03, 0x00, 0x5c, 0xe1,
|
||||||
0x07, 0x00, 0x00, 0x0a, 0x01, 0x00, 0x1c, 0xe3,
|
0x09, 0x00, 0x00, 0x0a, 0x01, 0x00, 0x1c, 0xe3,
|
||||||
0x05, 0x00, 0x00, 0x0a, 0x2c, 0x3c, 0xa0, 0xe1,
|
0x07, 0x00, 0x00, 0x0a, 0x2c, 0x3c, 0xa0, 0xe1,
|
||||||
0x08, 0x00, 0x53, 0xe3, 0x04, 0x00, 0x00, 0x0a,
|
0x08, 0x00, 0x53, 0xe3, 0x00, 0x00, 0x00, 0x1a,
|
||||||
0x2c, 0x3e, 0xa0, 0xe1, 0x08, 0x00, 0x53, 0xe3,
|
0x05, 0x00, 0x00, 0xea, 0x2c, 0x3e, 0xa0, 0xe1,
|
||||||
0x01, 0x00, 0x00, 0x0a, 0x79, 0xc7, 0x07, 0xe3,
|
0x08, 0x00, 0x53, 0xe3, 0x00, 0x00, 0x00, 0x1a,
|
||||||
|
0x01, 0x00, 0x00, 0xea, 0x79, 0xc7, 0x07, 0xe3,
|
||||||
0x00, 0xc8, 0x40, 0xe3, 0x00, 0x70, 0x0a, 0xe3,
|
0x00, 0xc8, 0x40, 0xe3, 0x00, 0x70, 0x0a, 0xe3,
|
||||||
0x73, 0x70, 0x40, 0xe3, 0x0c, 0x30, 0x9f, 0xe5,
|
0x73, 0x70, 0x40, 0xe3, 0x0c, 0x30, 0x9f, 0xe5,
|
||||||
0x00, 0x20, 0x93, 0xe5, 0x02, 0x20, 0x82, 0xe3,
|
0x00, 0x20, 0x93, 0xe5, 0x02, 0x20, 0x82, 0xe3,
|
||||||
@@ -808,14 +850,11 @@ static void saimaa_machine_init(MachineState *machine)
|
|||||||
cpu_physical_memory_write(a, &fill, 4);
|
cpu_physical_memory_write(a, &fill, 4);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* IMEM poison [0x8600000,0x8600F00): drift-sink trap (UDF in
|
/* IMEM tripwire [0x8600000,0x8600004): drift-sink trap.
|
||||||
* both modes). IMEM stack [0x8600F00,0x8610000) intact. */
|
* Must stay 4B (wider poison corrupts IMEM-stack reads). */
|
||||||
{
|
{
|
||||||
uint32_t p = 0xFFFFFFFF;
|
uint32_t p = 0xFFFFFFFF;
|
||||||
uint32_t a;
|
cpu_physical_memory_write(0x08600000, &p, 4);
|
||||||
for (a = 0x08600000; a < 0x08600F00; a += 4) {
|
|
||||||
cpu_physical_memory_write(a, &p, 4);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
/* pop-site slots -> stublets (sp values from cpu traces) */
|
/* pop-site slots -> stublets (sp values from cpu traces) */
|
||||||
v = 0x802f65d; /* S1 pop10 @fef0: resume sbl_main */
|
v = 0x802f65d; /* S1 pop10 @fef0: resume sbl_main */
|
||||||
|
|||||||
+1018
File diff suppressed because it is too large
Load Diff
+48
-23
@@ -376,18 +376,23 @@ def main():
|
|||||||
W32(S, S + 8)
|
W32(S, S + 8)
|
||||||
W32(S + 4, STUBV)
|
W32(S + 4, STUBV)
|
||||||
W32(S + 8, STUBV)
|
W32(S + 8, STUBV)
|
||||||
# maze blob (18B)
|
# maze blob (24B @STUB): movs r0,#0; return 0 via lr ONLY if lr is
|
||||||
|
# odd Thumb in DDR (top 8); even lr (stale mid-fn raw addr!) would
|
||||||
|
# ARM-drift (STM-clobbers + IMEM fault), so hang loud instead.
|
||||||
|
# Overlaps S6 head ([B9E,BA4), S6 dormant, documented).
|
||||||
mu.mem_write(STUB, bytes([
|
mu.mem_write(STUB, bytes([
|
||||||
0x00, 0x20, 0x4f, 0xea, 0x1e, 0x6c, 0xbc, 0xf1,
|
0x00, 0x20, 0x4f, 0xea, 0x1e, 0x6c, 0xbc, 0xf1,
|
||||||
0x08, 0x0f, 0x00, 0xd1, 0x70, 0x47, 0x72, 0xb6,
|
0x08, 0x0f, 0x03, 0xd1, 0x1e, 0xf0, 0x01, 0x0f,
|
||||||
0xfd, 0xe7]))
|
0x00, 0xd0, 0x70, 0x47, 0x72, 0xb6, 0xfd, 0xe7]))
|
||||||
print("maze-rb:", bytes(mu.mem_read(STUB, 18)).hex())
|
print("maze-rb:", bytes(mu.mem_read(STUB, 24)).hex())
|
||||||
for a in (0x087c29d18, 0x08050b28, 0x08070000):
|
for a in (0x087c29d18, 0x08050b28, 0x08070000):
|
||||||
W32(a, S)
|
W32(a, S)
|
||||||
# S6 stublet (14B @0x08006B9E)
|
# S6 stublet DISABLED (maze v2 overlaps its head; S6 dormant,
|
||||||
mu.mem_write(0x08006B9E, bytes([
|
# never entered (b14 goes to 0x8005B9E, not here). Bytes kept for
|
||||||
0xbd, 0xe8, 0xfc, 0x47, 0x43, 0xf6, 0xa5, 0x3e,
|
# reference (would live at 0x08006B9E):
|
||||||
0xc0, 0xf6, 0x01, 0x0e, 0x70, 0x47]))
|
# mu.mem_write(0x08006B9E, bytes([
|
||||||
|
# 0xbd, 0xe8, 0xfc, 0x47, 0x43, 0xf6, 0xa5, 0x3e,
|
||||||
|
# 0xc0, 0xf6, 0x01, 0x0e, 0x70, 0x47]))
|
||||||
# banner stub (34B @0x08006BAC, prints r0 via UARTDM)
|
# banner stub (34B @0x08006BAC, prints r0 via UARTDM)
|
||||||
mu.mem_write(0x08006BAC, bytes([
|
mu.mem_write(0x08006BAC, bytes([
|
||||||
0x10, 0xb5, 0x4f, 0xf2, 0x00, 0x03, 0xc0, 0xf2,
|
0x10, 0xb5, 0x4f, 0xf2, 0x00, 0x03, 0xc0, 0xf2,
|
||||||
@@ -426,6 +431,18 @@ 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"))
|
||||||
|
# S21 stublet (32B @0x08006D5A, b38): table-walker router.
|
||||||
|
# [sp+0x24] valid-code? => original pop.w (legit return);
|
||||||
|
# else b.w S19 (sbl_main post-logger restart, bounded table work).
|
||||||
|
mu.mem_write(0x08006D5A, bytes.fromhex(
|
||||||
|
"099b13f0010f09d01a0e082a01d1bde8f09f1a0f082a"
|
||||||
|
"01d1bde8f09ffff7d9bf"))
|
||||||
|
# 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(
|
||||||
@@ -434,6 +451,13 @@ def main():
|
|||||||
# PBL version-table fabrication (b23): [0x080528D0] = STUBV so the
|
# PBL version-table fabrication (b23): [0x080528D0] = STUBV so the
|
||||||
# rollback query's blx calls maze (returns 0 = versions OK).
|
# rollback query's blx calls maze (returns 0 = versions OK).
|
||||||
W32(0x080528D0, STUBV)
|
W32(0x080528D0, STUBV)
|
||||||
|
# PBL dispatcher-table fabrication (b33): [0x80164F0] (literal pool,
|
||||||
|
# image default points at hash blob!) retargeted to scratch struct
|
||||||
|
# at 0x08024000 (OCIMEM, out of stack-march paths!) with [0x18]=2
|
||||||
|
# (ready-flag -> world-switch dispatch; TZ deferred via OCIMEM stub).
|
||||||
|
W32(0x08024000, 0x08024000)
|
||||||
|
W32(0x08024014, 0x00000002)
|
||||||
|
W32(0x080164F0, 0x08024000)
|
||||||
# HW-ready bit fabrication (b25): [0x073A100] bits 0,1,2 = peripheral
|
# HW-ready bit fabrication (b25): [0x073A100] bits 0,1,2 = peripheral
|
||||||
# status done-bits (poll#1 checks bit2 (lsls#29), poll#2 bit1 (lsls#30),
|
# status done-bits (poll#1 checks bit2 (lsls#29), poll#2 bit1 (lsls#30),
|
||||||
# post-poll gate bit0 (lsls#31)). SBL only reads it, never writes.
|
# post-poll gate bit0 (lsls#31)). SBL only reads it, never writes.
|
||||||
@@ -444,17 +468,18 @@ def main():
|
|||||||
# to the dispatcher via stale lr (TZ bringup deferred).
|
# to the dispatcher via stale lr (TZ bringup deferred).
|
||||||
# NOTE: overwrites 4B of real ARM trampoline (recoverable from ELF).
|
# NOTE: overwrites 4B of real ARM trampoline (recoverable from ELF).
|
||||||
mu.mem_write(0x00221EF8, bytes([0x00, 0x20, 0x70, 0x47]))
|
mu.mem_write(0x00221EF8, bytes([0x00, 0x20, 0x70, 0x47]))
|
||||||
# S12-stub (b27, 92B @0x08006964, ARM): blx-to-padding becomes
|
# S12-stub (b27, 100B @0x08006964, ARM): blx-to-padding becomes
|
||||||
# smart dispatcher: ldr ip,[sp,#4] (=pushed lr); ip==STUBV/even/
|
# smart dispatcher: ldr ip,[sp,#4] (=pushed lr); ip==STUBV/even/
|
||||||
# non-code => ip=poll resumption 0x8007779; else keep pushed-lr;
|
# non-code => ip=poll resumption 0x8007779; else keep pushed-lr
|
||||||
# restore r7 (peripheral base, S16 dormant); ACK peripheral bit1
|
# (NO add-sp: marches on mid-entries! un-leak dropped, helper-leak
|
||||||
# ([literal 0x073A100]); bx lr. PBL would place the real helper.
|
# down is harmless); restore r7; ACK peripheral bit1; bx lr.
|
||||||
|
# PBL would place the real ARM helper here.
|
||||||
mu.mem_write(0x08006964, bytes.fromhex(
|
mu.mem_write(0x08006964, bytes.fromhex(
|
||||||
"04c09de58d3b06e3003840e303005ce10700000a0100"
|
"04c09de58d3b06e3003840e303005ce10900000a0100"
|
||||||
"1ce30500000a2c3ca0e1080053e30400000a2c3ea0e1"
|
"1ce30700000a2c3ca0e1080053e30000001a050000ea"
|
||||||
"080053e30100000a79c707e300c840e300700ae37370"
|
"2c3ea0e1080053e30000001a010000ea79c707e300c8"
|
||||||
"40e30c309fe5002093e5022082e3002083e51eff2fe1"
|
"40e300700ae3737040e30c309fe5002093e5022082e3"
|
||||||
"00a17300"))
|
"002083e51eff2fe100a17300"))
|
||||||
# S16-stublet (b27, 64B @0x08006CC0): smart return for B66 bx ip.
|
# S16-stublet (b27, 64B @0x08006CC0): smart return for B66 bx ip.
|
||||||
# ip==STUBV (fill/maze, never a legit return) => default;
|
# ip==STUBV (fill/maze, never a legit return) => default;
|
||||||
# ip odd + top 8 (code) => add sp,#8 (pop the helper frame B66
|
# ip odd + top 8 (code) => add sp,#8 (pop the helper frame B66
|
||||||
@@ -466,11 +491,11 @@ def main():
|
|||||||
"60474af20007c0f2730747f2797cc0f6000c6047"))
|
"60474af20007c0f2730747f2797cc0f6000c6047"))
|
||||||
# stack zone fill (STUBV odd)
|
# stack zone fill (STUBV odd)
|
||||||
mu.mem_write(0x085F0000, struct.pack("<I", STUBV) * (0x10000 // 4))
|
mu.mem_write(0x085F0000, struct.pack("<I", STUBV) * (0x10000 // 4))
|
||||||
# IMEM poison [0x8600000,0x8600F00): drift-sink trap. Fill/IMEM-zero
|
# IMEM tripwire [0x8600000,0x8600004): drift-sink trap (UDF).
|
||||||
# sleds (fall-through ldr/movs/andeq) drift silently to IMEM-top
|
# Fill-drift falls through here sequentially; faults LOUDLY at
|
||||||
# fault; poison faults LOUDLY at drift-entry (UDF in both modes).
|
# entry. Must stay 4B: wider poison corrupts IMEM-stack reads
|
||||||
# IMEM stack [0x8600F00,0x8610000) left intact.
|
# (SBL frames live at 0x860000C+, counters underflow on 0xFF!).
|
||||||
mu.mem_write(0x08600000, b"\xff\xff\xff\xff" * (0xF00 // 4))
|
mu.mem_write(0x08600000, b"\xff\xff\xff\xff")
|
||||||
# pop-site slots (sp values from traces)
|
# pop-site slots (sp values from traces)
|
||||||
for a, v in [(0x085FFF14, 0x802f65d), (0x085FFF1C, 0x802f665),
|
for a, v in [(0x085FFF14, 0x802f65d), (0x085FFF1C, 0x802f665),
|
||||||
(0x085FFF44, 0x8013ba5), (0x085FFF5C, 0x802f681),
|
(0x085FFF44, 0x8013ba5), (0x085FFF5C, 0x802f681),
|
||||||
@@ -505,7 +530,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, 0x08006D80 # +S7/S9/S10/S16/S17/S18/S20/S21
|
||||||
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