Files
lumia-emulator/docs/sbl-bringup.md
T
2026-09-13 12:05:17 +00:00

116 lines
8.3 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# SBL1 BringUp — статус (2026-09-07)
Цель: выполнить оригинальный SBL1 (RM-1127) в QEMU до баннера `SBL1, Start` на UART.
## Что работает
- Машина `saimaa` (`qemu/saimaa.c`, QEMU 8.2.2 на zern): Cortex-A7×4,
DDRLOW/OCIMEM/IMEM/SMEM/RPM/mystrom, UARTDM-стаб, SDHCI+eMMC 8GiB,
VFP/NEON вкл (CPACR+NSACR+FPEXC), null-page trap, fault-tolerant векторы.
- eMMC-образ с реальной GPT RM-1127 (33 раздела, `tools/mkimage.py`).
- FFU-разбор (`tools/ffu_parse.py`, RKH/MSM/OEM/PlatformID, GPT33).
- `.edp`-нарезка ELF (`tools/edp_carve.py`, 10 образов, `fw/sbl/` в .gitignore).
- `tools/sbl_patch.py` — воспроизводимо генерирует img0_bl..b10.elf из img0.elf.
- Стаблеты компенсации pop (`qemu/stublets.S` → 0x08062000): чинят SP,
повторы попадают в те же слоты. Слоты в `saimaa_machine_init`.
- Указательный maze (`0x08062100`) + scratch (`0x08070000`) для struct-цепочек.
- Трассировка: `-d in_asm,cpu,guest_errors,int` + GDB (только чтение! `continue`
в batch виснет — использовать `interrupt`+`detach`).
## Найденное
- `sbl_main` (Thumb) = `0x802f63e`, баннер `SBL1, Start` зовётся из `0x802f6ae`
через `bl 0x8016320`. Poll IMEM `0x08600944` != `0x53444247` (выходит при 0).
- В `.edp`-копии вызовы `blx imm` ведут в Thumb-код (на HW тоже; QEMU уходит
в ARM → патчим в `bl`, см. sbl_patch.py). Часть вызовов off-by-2/4
(таблица `0x8013aa8`, `bl 0x8018a78``0x8018a7c`).
- FFU-копия SBL1 — другая сборка тех же исходников (структура та же, `bl`
вместо `blx`, полные фреймы). Используется как эталон.
- PBL-контекст (r4-r12) фабрикуется машиной; таблицы собираются частично.
- Текущий фронтир (b10 + canonical scaffold): ~20 уровней init, падеж
в районе `0x80079xx` (див switch по мусорным флагам) — см. свежий трейс.
## Запуск
```
./tools/sbl_patch.py fw/sbl/img0.elf /tmp/p
~/qemu-src/qemu-8.2.2/build/qemu-system-arm \
-M saimaa,sbl1=/tmp/p/img0_b10.elf,sblmain=0x802f63f -m 512 \
-display none -monitor none -serial file:/tmp/uart.log \
-drive file=/tmp/emmc-test.img,if=sd,format=raw
```
## TODO
1. Добить баннер (см. свежий in_asm-хвост).
2. Заменить стаблеты настоящим PBL (нужны дампы с живого тела!).
3. UEFI (img3, EDK2) — отдельный фронт после SBL1.
## b18: S7 и цикл delay-helper (2026-09-12)
Механизм зацикливания (b17, доказан Unicorn-harness `tools/sbl_uni.py`):
- sbl_main → delay-функция `0x8013B78` (256-итераций table-walk, `bl 0x8017AF4`
каждую итерацию) → b14 (`0x8017AFC: b.w 0x8005B9E`) → helper `0x8005BB0`
→ выход `ldr pc,[sp],#0x14` (0x8005BCA) → S3-слот (0x8013BA5, рестарт).
- Эпилог delay (`0x8013BAC: pop {r3-r7,pc}`) снимает 0x18 без push; каждый
S3-рестарт съедает 0x18 живого стека. Маршрут: слоты → fill (STUBV →
pop pc = maze) → pristine IMEM (нули → null-jump → hook_null → maze →
stale lr) → переполнение IMEM (0x8610008).
- Heap SBL (stm в 0x8006684) затирает maze/S6/banner (0, 0x7a, STUBV).
QEMU: dstub-overlay `[0x08006B80,0x08006C50)` (read = снапшот ELF+стабы,
write = игнор). Uni: deferred-restore guard (MEM_WRITE-хук срабатывает
ДО записи, restore надо делать в hook_code!).
- Maze-blob: `movs r0,#0; lsr ip,lr,#24; cmp #8; bne hang; bx lr`
(возврат 0 только для lr из DDRLOW 0x08..., иначе hang).
Фикс b18: патч BAC (`f8bd0a4a``f3f730b8`, `b.w S7`) + S7-стаблет
(52B @ 0x08006C10): `cmp r4,#0xff` → iterate (`0x8013BA5`) или done
(restore r4/r5/sl/fp, возврат в sbl_main `0x802f681`). BAE-путь
(`[r7]==2`) принесён в жертву (r7=0, недостижим).
Фронтир b18: sbl_main возвращается, новый код `0x801Bxxx`
(`strb [r7,#2]`-паттерн, b17-NOP на 0x801B71E), падеж pop'ом пустого
стека у верха IMEM — следующий фронт.
## b18 parity (QEMU == uni, 2026-09-12)
- QEMU поправлен до паритета: dstub-overlay + vec-maze для Thumb
(null-fetch исполняет maze и возвращается) + убран висячий префикс
bl (bogus odd store -> alignment fault, DFAR=0x8006B8D).
- QEMU b18 доходит до того же фронтира, что uni b18 (38961 инстр.):
`0x801Bxxx`, r1=0x80522A4, r2/r3=STUBV, lr=0x801B73F, sp марширует
к верху IMEM. Смерти чуть различаются по таймингу (uni: read
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-данных).
QEMU-паритет: R15=0x223000, sp=0x85FFF00, lr=0x80164CB — там же.
## b24: world-switch stub, clock S11 (2026-09-12)
- Диспетчер (`0x80164C4`-subtree) зовёт ARM jump-table `0x8007158`
(`ldr pc`), та — в OCIMEM-трамплин world-switch `0x221EF8`
(ARM: save regs, `cps MON`, `mrc`, `ldr sp/pc` из PBL-таблиц
`[0x221F6C]=0x223620`/`[0x221F70]=0x223930` → вызов TZ; TZ не загружен).
Вход получается в Thumb → b24-стаб (4B `movs r0,#0; bx lr`):
возврат 0 в диспетчер (TZ deferred). Перезаписывает голову ARM'а
(восстановимо из ELF).
- Дальше: clock-fn `0x800E960` (udiv-подсчёты) с голым выходом
`pop{r4,pc}` (без push, tail-chain через NOP-идиому) → S11 (b24):
вход → `bx lr` (lr = брошенный-но-валидный `0x80076CD`).
- Poll `[0x73A100]` (lsls#29+bpl = проверка bit2!): SBL только читает →
фабрикация bit2=1 (b24 scaffold, обе стороны).
- `blx #0x8006964` в файловые нули паддинга (PBL scratch) → S12v2 (b25
scaffold, ARM! т.к. blx-imm на чётный): preset ip=S16 + ACK bit1
`[0x73A100]` (side effect для poll#2) + `bx lr`. Литерал `[0x8006980]`.
- Helper-pop `0x8007B66` читает scratch (счётчики 0-4 вместо pushed lr,
фреймы съедены null-циклами) → S16v2 (b25 smart): B66 (`pop``bx ip`,
2B) → S16 проверяет ip (odd + top 8 = legit pushed-lr → `bx ip`;
иначе default: restore r7, прыжок `0x8007779`). S12v3 грузит ip из
`[sp+4]` (pushed lr) + ACK bit1. B66-патч в ELF (b25), S12/S16 в scaffold.