Compare commits
10 Commits
f449b56b05
...
67539f7351
| Author | SHA1 | Date | |
|---|---|---|---|
| 67539f7351 | |||
| 22ea0dd0f1 | |||
| 74e4ead780 | |||
| 4ff0511da1 | |||
| 444a39d8d0 | |||
| 6875e8bada | |||
| 124e9f5e72 | |||
| 2087cba49c | |||
| 40943bbd51 | |||
| fda762acc8 |
+14
-14
@@ -1,22 +1,22 @@
|
||||
.syntax unified
|
||||
.cpu cortex-a7
|
||||
.thumb
|
||||
@ maze entry logger: record lr/sp to mailbox 0x08006964, return 0.
|
||||
@ Guard: if lr is outside known-good SBL/stub ranges, spin with
|
||||
@ interrupts disabled instead of jumping into the void (post-mortem
|
||||
@ via vec trap regs).
|
||||
@ maze entry logger: ring buffer of 8 (lr,sp) at MAILBOX, return 0.
|
||||
@ Preserves all regs except r0 (return value) and r12 (IP, clobber-ok).
|
||||
.text
|
||||
.global maze_stub
|
||||
maze_stub:
|
||||
movw r12, #:lower16:0x08006964
|
||||
movt r12, #:upper16:0x08006964
|
||||
str lr, [r12]
|
||||
str sp, [r12, #4]
|
||||
push {r0-r3}
|
||||
movw r12, #:lower16:0x08006890
|
||||
movt r12, #:upper16:0x08006890
|
||||
ldr r0, [r12, #32]
|
||||
add r0, #1
|
||||
and r0, #7
|
||||
str r0, [r12, #32]
|
||||
lsl r0, #3
|
||||
add r0, r12
|
||||
str lr, [r0]
|
||||
str sp, [r0, #4]
|
||||
pop {r0-r3}
|
||||
movs r0, #0
|
||||
lsr r12, lr, #24
|
||||
cmp r12, #0x08
|
||||
bne maze_hang
|
||||
bx lr
|
||||
maze_hang:
|
||||
cpsid i
|
||||
b maze_hang
|
||||
|
||||
Executable
+25
@@ -0,0 +1,25 @@
|
||||
#!/bin/bash
|
||||
# run-sbl.sh — запуск SBL1 на машине saimaa (пути постоянные, не /tmp).
|
||||
# Использование: ./qemu/run-sbl.sh [bXX] [extra-qemu-args...]
|
||||
# bXX — вариант патча (по умолчанию b17)
|
||||
set -e
|
||||
cd "$(dirname "$0")/.."
|
||||
QEMU=~/qemu-src/qemu-8.2.2/build/qemu-system-arm
|
||||
B=${1:-b17}
|
||||
IMG=fw/img/emmc-real.img
|
||||
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 "и: python3 tools/mkimage.py --user fw/img/user-real.bin $IMG"
|
||||
exit 1
|
||||
fi
|
||||
shift 2>/dev/null || true
|
||||
# timeout для тестовых прогонов (0 = без ограничения)
|
||||
T=${T:-15}
|
||||
if [ "$T" != "0" ]; then
|
||||
exec timeout "$T" "$QEMU" -M saimaa,sbl1="fw/img/patch/img0_${B}.elf",sblmain=0x802f63f \
|
||||
-m 512 -display none -monitor none -serial file:uart.log \
|
||||
-drive file="$IMG",if=sd,format=raw "$@" 2>&1
|
||||
fi
|
||||
exec "$QEMU" -M saimaa,sbl1="fw/img/patch/img0_${B}.elf",sblmain=0x802f63f \
|
||||
-m 512 -display none -monitor none -serial file:uart.log \
|
||||
-drive file="$IMG",if=sd,format=raw "$@" 2>&1
|
||||
+41
-21
@@ -35,6 +35,10 @@
|
||||
/* High DDRLOW for our stubs (SBL heap reuses 0x0806xxxx) */
|
||||
#define SAIMAA_DDRHI_BASE 0x08610000
|
||||
#define SAIMAA_DDRHI_SIZE 0x00FF0000 /* ..0x09600000 */
|
||||
/* Stubs carve-out inside DDRHI (SBL heap overwrites plain RAM):
|
||||
* maze+S6+banner+mailbox live here, set read-only after implant. */
|
||||
#define SAIMAA_STUBS_BASE 0x08800000
|
||||
#define SAIMAA_STUBS_SIZE 0x00000300
|
||||
#define SAIMAA_IMEM_BASE 0x08600000
|
||||
#define SAIMAA_IMEM_SIZE 0x00010000
|
||||
#define SAIMAA_DDRH_A_BASE 0x80000000
|
||||
@@ -94,6 +98,9 @@ static void saimaa_tmr_init(Object *obj)
|
||||
sysbus_init_mmio(dev, &s->iomem);
|
||||
}
|
||||
|
||||
/* Stubs region handle for set_readonly after scaffold implant. */
|
||||
static MemoryRegion *saimaa_stubs_mr;
|
||||
|
||||
/* ---- minimal MSM UARTDM stub: TX prints, status always ready ---- */
|
||||
#define TYPE_SAIMAA_VEC "saimaa-vec"
|
||||
#define TYPE_SAIMAA_UART "saimaa-uart"
|
||||
@@ -115,8 +122,8 @@ static uint64_t saimaa_vec_read(void *opaque, hwaddr off, unsigned size)
|
||||
int th = cpu ? cpu->env.thumb : 0;
|
||||
uint32_t mb0 = 0, mb1 = 0;
|
||||
if (saimaa_vec_n < 3) {
|
||||
cpu_physical_memory_read(0x08006964, &mb0, 4);
|
||||
cpu_physical_memory_read(0x08006968, &mb1, 4);
|
||||
cpu_physical_memory_read(0x08006890, &mb0, 4);
|
||||
cpu_physical_memory_read(0x08006894, &mb1, 4);
|
||||
}
|
||||
fprintf(stderr, "saimaa-vec: %s off=0x%x pc=0x%lx",
|
||||
size == 2 ? "fetch?" : "read",
|
||||
@@ -248,19 +255,27 @@ static void saimaa_machine_init(MachineState *machine)
|
||||
{ "saimaa.rpm", SAIMAA_RPM_BASE, SAIMAA_RPM_SIZE },
|
||||
{ "saimaa.ocimem", SAIMAA_OCIMEM_BASE, SAIMAA_OCIMEM_SIZE },
|
||||
{ "saimaa.ddrlow", SAIMAA_DDRLOW_BASE, SAIMAA_DDRLOW_SIZE },
|
||||
{ "saimaa.ddrhi", SAIMAA_DDRHI_BASE, SAIMAA_DDRHI_SIZE },
|
||||
{ "saimaa.ddrhi_lo", SAIMAA_DDRHI_BASE,
|
||||
SAIMAA_STUBS_BASE - SAIMAA_DDRHI_BASE },
|
||||
{ "saimaa.stubs", SAIMAA_STUBS_BASE, SAIMAA_STUBS_SIZE },
|
||||
{ "saimaa.ddrhi_hi", SAIMAA_STUBS_BASE + SAIMAA_STUBS_SIZE,
|
||||
SAIMAA_DDRHI_BASE + SAIMAA_DDRHI_SIZE -
|
||||
(SAIMAA_STUBS_BASE + SAIMAA_STUBS_SIZE) },
|
||||
{ "saimaa.imem", SAIMAA_IMEM_BASE, SAIMAA_IMEM_SIZE },
|
||||
{ "saimaa.ddrhigh_a", SAIMAA_DDRH_A_BASE, SAIMAA_DDRH_A_SIZE },
|
||||
{ "saimaa.ddrhigh_b", SAIMAA_DDRH_B_BASE, SAIMAA_DDRH_B_SIZE },
|
||||
{ "saimaa.mystrom", SAIMAA_MYSTROM_BASE, SAIMAA_MYSTROM_SIZE },
|
||||
{ "saimaa.smem", SAIMAA_SMEM_BASE, SAIMAA_SMEM_SIZE },
|
||||
};
|
||||
for (i = 0; i < 10; i++) {
|
||||
for (i = 0; i < ARRAY_SIZE(rams); i++) {
|
||||
MemoryRegion *ram = g_new(MemoryRegion, 1);
|
||||
memory_region_init_ram(ram, NULL, rams[i].n, rams[i].s,
|
||||
&error_fatal);
|
||||
memory_region_add_subregion_overlap(sysmem, rams[i].b, ram,
|
||||
memory_region_add_subregion_overlap(sysmem, rams[i].b, ram,
|
||||
1);
|
||||
if (!strcmp(rams[i].n, "saimaa.stubs")) {
|
||||
saimaa_stubs_mr = ram;
|
||||
}
|
||||
if (!strcmp(rams[i].n, "saimaa.mystrom")) {
|
||||
/* Mystery handler ROM: ARM mov r0,#0; bx lr repeating,
|
||||
* so unknown blx targets return 0 instead of faulting. */
|
||||
@@ -440,8 +455,8 @@ static void saimaa_machine_init(MachineState *machine)
|
||||
* (sp values from cpu traces, b10 image) */
|
||||
{
|
||||
uint32_t magic = 0x00000000; /* IMEM poll spins WHILE equal */
|
||||
uint32_t S = 0x08006900, STUB = 0x08006910; /* in-code zeros, safe from heap */
|
||||
uint32_t STUBV = 0x08006911; /* odd: blx stays Thumb */
|
||||
uint32_t S = 0x08006820, STUB = 0x08006830; /* in-code zeros, safe from heap */
|
||||
uint32_t STUBV = 0x08006831; /* odd: blx stays Thumb */
|
||||
uint32_t w;
|
||||
uint16_t h0 = 0x2000, h1 = 0x4770; /* movs r0,#0; bx lr */
|
||||
uint32_t v;
|
||||
@@ -451,19 +466,21 @@ static void saimaa_machine_init(MachineState *machine)
|
||||
w = S + 8;
|
||||
cpu_physical_memory_write(S, &w, 4);
|
||||
/* [struct+4] is another fn ptr (e.g. 0x801b72e ldr r3,[r0,#4]
|
||||
* with r0 = maze S via POOLS redirect); point at STUB too */
|
||||
cpu_physical_memory_write(S + 4, &STUB, 4);
|
||||
cpu_physical_memory_write(S + 8, &STUB, 4);
|
||||
* with r0 = maze S via POOLS redirect); point at STUB too.
|
||||
* NOTE: ODD (STUBV) — blx to even would switch to ARM! */
|
||||
cpu_physical_memory_write(S + 4, &STUBV, 4);
|
||||
cpu_physical_memory_write(S + 8, &STUBV, 4);
|
||||
{
|
||||
/* from qemu/maze.S: mailbox logger + lr-range guard.
|
||||
* Bad lr (not 0x08xxxxxx) spins with IRQs off instead of
|
||||
* jumping into the void. 36 bytes. */
|
||||
static const uint8_t mb[] = {
|
||||
0x46, 0xf6, 0x64, 0x1c, 0xc0, 0xf6, 0x00, 0x0c,
|
||||
0xcc, 0xf8, 0x00, 0xe0, 0xcc, 0xf8, 0x04, 0xd0,
|
||||
0x00, 0x20, 0x4f, 0xea, 0x1e, 0x6c, 0xbc, 0xf1,
|
||||
0x08, 0x0f, 0x00, 0xd1, 0x70, 0x47, 0x72, 0xb6,
|
||||
0xfd, 0xe7, 0x00, 0x00,
|
||||
0x0f, 0xb4, 0x46, 0xf6, 0x90, 0x0c, 0xc0, 0xf6,
|
||||
0x00, 0x0c, 0xdc, 0xf8, 0x20, 0x00, 0x00, 0xf1,
|
||||
0x01, 0x00, 0x00, 0xf0, 0x07, 0x00, 0xcc, 0xf8,
|
||||
0x20, 0x00, 0x4f, 0xea, 0xc0, 0x00, 0x60, 0x44,
|
||||
0xc0, 0xf8, 0x00, 0xe0, 0xc0, 0xf8, 0x04, 0xd0,
|
||||
0x0f, 0xbc, 0x00, 0x20, 0x70, 0x47,
|
||||
};
|
||||
size_t k;
|
||||
for (k = 0; k < sizeof(mb); k += 4) {
|
||||
@@ -476,7 +493,7 @@ static void saimaa_machine_init(MachineState *machine)
|
||||
cpu_physical_memory_write(0x087c29d18, &S, 4);
|
||||
cpu_physical_memory_write(0x08050b28, &S, 4);
|
||||
cpu_physical_memory_write(0x08070000, &S, 4);
|
||||
/* S6 stublet at 0x08006934: rebuild popped frame regs,
|
||||
/* S6 stublet at 0x0800685e: rebuild popped frame regs,
|
||||
* return to 0x8013ba5 (b14 redirects 0x8017afc pop here) */
|
||||
{
|
||||
static const uint8_t s6[] = {
|
||||
@@ -490,10 +507,10 @@ static void saimaa_machine_init(MachineState *machine)
|
||||
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(0x08006934 + k, &word, 4);
|
||||
cpu_physical_memory_write(0x0800685e + k, &word, 4);
|
||||
}
|
||||
}
|
||||
/* Banner stub at 0x08006942: print r0 string via UARTDM
|
||||
/* Banner stub at 0x0800686c: print r0 string via UARTDM
|
||||
* (b16 redirects 0x802f690 blx here). Built from qemu/banner.S:
|
||||
* push frame, print loop, ldr pc,=0x802f694 (callee noreturn).
|
||||
* 28 bytes total. */
|
||||
@@ -510,13 +527,13 @@ static void saimaa_machine_init(MachineState *machine)
|
||||
uint32_t word = 0;
|
||||
size_t n = sizeof(bn) - k < 4 ? sizeof(bn) - k : 4;
|
||||
__builtin_memcpy(&word, &bn[k], n);
|
||||
cpu_physical_memory_write(0x08006942 + k, &word, 4);
|
||||
cpu_physical_memory_write(0x0800686c + k, &word, 4);
|
||||
}
|
||||
}
|
||||
/* stack zone defaults to plain-stub addr: every register
|
||||
* popped from untouched stack becomes callable (returns 0). */
|
||||
{
|
||||
uint32_t fill = 0x08006911;
|
||||
uint32_t fill = 0x08006831;
|
||||
uint32_t a;
|
||||
for (a = 0x085F0000; a < 0x08600000; a += 4) {
|
||||
cpu_physical_memory_write(a, &fill, 4);
|
||||
@@ -595,6 +612,9 @@ static void saimaa_machine_init(MachineState *machine)
|
||||
printf("saimaa: uefi tables live\n");
|
||||
}
|
||||
printf("saimaa: slots live\n");
|
||||
/* Freeze stubs: any SBL write here now faults loudly
|
||||
* (data abort with DFAR) instead of silent corruption. */
|
||||
memory_region_set_readonly(saimaa_stubs_mr, true);
|
||||
}
|
||||
printf("saimaa: SBL1 %s loaded (%zd bytes), entry 0x%lx\n",
|
||||
sms->sbl1, sz, (unsigned long)entry);
|
||||
@@ -604,7 +624,7 @@ static void saimaa_machine_init(MachineState *machine)
|
||||
|
||||
static void saimaa_post_reset(void *opaque)
|
||||
{
|
||||
uint32_t S = 0x08006900;
|
||||
uint32_t S = 0x08006820;
|
||||
(void)opaque;
|
||||
/* Re-apply pokes that live inside ROM-covered ranges (rom_reset
|
||||
* restores file bytes over them). */
|
||||
|
||||
+5
-5
@@ -148,7 +148,7 @@ def main():
|
||||
(0x8016184, 'fdf790fc', 'c046c046'),
|
||||
(0x801B76C, '280b0508', '00000708'),
|
||||
(0x8006684, '01f807bd', '46c046c0'),
|
||||
(0x8017AFC, 'bde8fc87', 'eef71abf'),
|
||||
(0x8017AFC, 'bde8fc87', 'eef7afbe'),
|
||||
]:
|
||||
assert hx(d, va) == exp, (hex(va), hx(d, va))
|
||||
set4(d, va, new)
|
||||
@@ -174,8 +174,8 @@ def main():
|
||||
(0x8016184, 'fdf790fc', 'c046c046'),
|
||||
(0x801B76C, '280b0508', '00000708'),
|
||||
(0x8006684, '01f807bd', '46c046c0'),
|
||||
(0x8017AFC, 'bde8fc87', 'eef71abf'),
|
||||
(0x802F690, '9847fee7', 'd7f757b9'),
|
||||
(0x8017AFC, 'bde8fc87', 'eef7afbe'),
|
||||
(0x802F690, '9847fee7', 'd7f7ecb8'),
|
||||
]:
|
||||
assert hx(d, va) == exp, (hex(va), hx(d, va))
|
||||
set4(d, va, new)
|
||||
@@ -200,7 +200,7 @@ def main():
|
||||
(0x8016184, 'fdf790fc', 'c046c046'),
|
||||
(0x801B76C, '280b0508', '00000708'),
|
||||
(0x8006684, '01f807bd', '46c046c0'),
|
||||
(0x8017AFC, 'bde8fc87', 'eef71abf'),
|
||||
(0x8017AFC, 'bde8fc87', 'eef7afbe'),
|
||||
]:
|
||||
assert hx(d, va) == exp, (hex(va), hx(d, va))
|
||||
set4(d, va, new)
|
||||
@@ -245,7 +245,7 @@ def main():
|
||||
(0x8016184, 'fdf790fc', 'c046c046'),
|
||||
(0x801B76C, '280b0508', '00000708'),
|
||||
(0x8006684, '01f807bd', '46c046c0'),
|
||||
(0x8017AFC, 'bde8fc87', 'eef71abf'),
|
||||
(0x8017AFC, 'bde8fc87', 'eef7afbe'),
|
||||
(0x802F690, '9847fee7', 'c046c046'),
|
||||
]:
|
||||
assert hx(d, va) == exp, (hex(va), hx(d, va))
|
||||
|
||||
Reference in New Issue
Block a user