diff --git a/RESEARCH.md b/RESEARCH.md index e25f8c3..3c9c7e9 100644 --- a/RESEARCH.md +++ b/RESEARCH.md @@ -1429,3 +1429,36 @@ load-bearing options (USB/PHY/CONSOLE/PREBOOT), not just the new one. | USB lines present but no keys | keyboard enumeration issue — transcribe the `Bus ...` line | Awaiting user reboot report. + +## Round 37 — Round 36 VERIFIED (landscape + keyboard work); stub-free payload + +User confirmed Round 36 fully works (landscape upright, keyboard +functional). User took over the config: `.config` hand-tuned with +VIDEO_FONT_16X32 (bigger console font), CONFIG_CHROMEOS=y, +VIDEO_ANSI off — the defconfig re-run must therefore NOT be executed +blindly anymore (documented in U-BOOT.md). + +### Stub removal (payload `cc014efa…`) + +The entry shim kept only the load-bearing part: OVL_EN/OVL0_2L_EN=1, +backlight GPIOs 43/176 on, patched branch to U-Boot. Removed the +diagnostic phase (magenta fill, 3-blink train, 5 s hold, delay +subroutine). The shim itself cannot be removed: depthcharge jumps to +payload+0x40 and U-Boot's PIE fixup needs runtime _start 4K-aligned +so U-Boot stays at image offset 0x1000. The build script's single +`b .` search-and-patch still applies (the patched branch is now the +only instruction after the revival writes). + +### Verification + +U-Boot built with the user's .config untouched; `_start` still +0x4C001000 == __image_copy_start; wrapper now 64 bytes (0x40..0x1000), +runtime _start 0x40001000. Payload `cc014efa…` flashed, cmp OK, +vbutil body verification succeeded. + +### Handoff + +New `U-BOOT.md` in this repo: boot chain, payload layout constants, +build/flash/verify command sequences, recovery paths, U-Boot tree +state (kept features vs WIP/temporary), rotation and keyboard notes. +The user owns the U-Boot config and further development. diff --git a/U-BOOT.md b/U-BOOT.md new file mode 100644 index 0000000..bff79ce --- /dev/null +++ b/U-BOOT.md @@ -0,0 +1,162 @@ +# U-Boot on krane — final state and operating manual + +Status as of 2026-08-30 (RESEARCH.md Rounds 1–36). Milestones reached: +payload pipeline → framebuffer console → **USB pogo keyboard at the +prompt → landscape (rotated 270°) console**, all verified on the +device. The user owns the U-Boot config from here on. + +## Boot chain + +``` +BootROM → coreboot → TF-A BL31 → depthcharge (.12573.351.0) + → krane-uboot-payload.bin @ 0x40000000 (mmcblk0p1, devkeys) + → entry shim @ 0x40000040 → U-Boot _start @ 0x40001000 + → banner + vidconsole3 prompt on the panel + usbkbd input +``` + +The SPI firmware is never modified; only the kernel partition +`mmcblk0p1` is reflashed. + +## Payload layout (LOAD-BEARING constants) + +| offset | content | +|---|---| +| 0x0000 | 64-byte arm64 Image header (code0 = `b +0x40`, image_size, flags bit3, magic `ARM\x64` at 0x38) | +| 0x0040 | `uboot-wrapper.S` entry shim (OVL_EN=1, OVL0_2L_EN=1, backlight GPIOs 43/176 on, `b` to U-Boot — imm26 patched at build time) | +| 0x1000 | `u-boot.bin` contiguous (no interior padding) | + +- `CONFIG_TEXT_BASE=0x4C001000` (8-aligned, so no linker fill skews + `_start`); the file is placed so runtime `_start = 0x40001000` + (4K-aligned — required by U-Boot's PIE fixup, checked by the build + script via `u-boot.sym`: `_start == __image_copy_start`). +- The shim cannot be removed: depthcharge jumps to payload+0x40, and + U-Boot cannot execute there (PIE/alignment). The diagnostic magenta + fill + blink train + 5 s hold were removed in Round 37; the shim now + only revives the display and branches. + +## Build + +### U-Boot + +```sh +cd /home/vhaudiquet/u-boot +export CROSS_COMPILE=aarch64-linux-gnu- ARCH=arm +make mt8183_kukui_krane_defconfig # ONLY when changing the defconfig +make -j8 +``` + +**Warning:** re-running the defconfig regenerates `.config` and wipes +any hand edits. If you tune `.config` directly (like the current +16×32 font setup), just run `make -j8`. After ANY defconfig edit + +re-run, verify the full load-bearing set in `.config`: + +```sh +grep -E "CONFIG_USB=|DM_USB|XHCI|USB_KEYBOARD|USB_STORAGE|CMD_USB|USE_PREBOOT|PREBOOT=|PHY_MTK_TPHY|VIDEO_MT8183|CONSOLE_ROTATION|TEXT_BASE" .config +grep -E " _start$|__image_copy_start" u-boot.sym # both 0x4c001000 +``` + +(Round 36 lesson: an elided-line edit dropped `CONFIG_USB=y` and USB +silently disappeared.) + +### Payload + +```sh +cd /home/vhaudiquet/krane-fb-stub +./build-uboot-payload.sh +``` + +Assembles header + wrapper + `u-boot.bin` → `krane-uboot-payload.bin`, +packs with mkdepthcharge (devkeys, `PYTHONPATH=/root/krane-fb-stub/src/depthcharge-tools`), +asserts `_start == 0x4C001000` from `u-boot.sym`, prints sha256. + +### Flash + verify (always all three) + +```sh +SZ=$(stat -c%s krane-uboot-payload.bin) +dd if=krane-uboot-payload.bin of=/dev/mmcblk0p1 bs=4M conv=fsync +cmp -n $SZ krane-uboot-payload.bin /dev/mmcblk0p1 && echo CMP-OK +futility vbutil_kernel --verify /dev/mmcblk0p1 # "Body verification succeeded" +``` + +Then: reboot → depthcharge dev menu → "Internal storage". + +### Recovery + +- Backup of the original kernel partition: + `~/mmcblk0p1-pmos-backup.img` (sha256 `20951a54…`), also on the USB + stick (sda3). `dd` it back to `mmcblk0p1` to restore pmOS's FIT. +- pmOS still boots from the USB stick (sda) via the depthcharge menu. +- pmOS chroot lives on `mmcblk0p3`. + +## U-Boot tree state (branch `krane`, on top of mainline 527115ef) + +Kept features (upstreamable): + +- `drivers/video/mt8183_scanout.c` — UCLASS_VIDEO scanout driver on + the upstream `ovl0@14008000` node: revives the depthcharge scanout + (OVL_EN/OVL0_2L_EN + backlight GPIOs), parses the coreboot table + LBIO at `0xffed9000`, falls back to `OVL_L0_ADDR` (0x14008f40), + sets `uc_priv->rot = 3` (270° CW landscape console). +- `board/mediatek/mt8183/mt8183.c` — `get_page_table_size()` override + (0x40000): the fb and coreboot-table dynamic mappings exhaust the + default page-table budget (Round 31). Any new post-reloc + `mmu_map_region` relies on this headroom. +- `arch/arm/dts/mt8183-kukui-krane-sku176-u-boot.dtsi` — overlay (NOT + a DT fork): adds `simple-mfd` to the mtu3 ssusb node (so DM scans + its children and binds xhci — Round 34) and `ippc` reg + `phys` on + `usb@11200000` (what `xhci-mtk.c` expects; upstream puts those on + the parent for Linux's mtu3 driver). +- `board/mediatek/mt8183/krane.env` — `stdin=serial,usbkbd`, + `stdout=serial,vidconsole`, `stderr=serial,vidconsole`. +- defconfig: USB stack (`USB`, `DM_USB`, `USB_XHCI_HCD`, + `USB_XHCI_MTK`, `USB_KEYBOARD`, `USB_STORAGE`, `CMD_USB`), + `PHY_MTK_TPHY`, `USE_PREBOOT` (preboot defaults to `usb start`), + `CONSOLE_ROTATION`, `ENV_IS_NOWHERE` + `ENV_SOURCE_FILE="krane"`. + +Still WIP/temporary in the tree (revert before upstreaming; see +`git log --oneline | grep -i wip`): + +- fb text logger + diag bands (`krane_fb_log`/`krane_diag_band` in + mt8183_scanout.c, band calls in video-uclass.c/board_f.c/main.c/ + mt8183.c), abort dump hook in `interrupts_64.c` (`do_sync` draws + ESR/ELR/FAR on the panel), +- `CONFIG_PANIC_HANG=y` (freeze + dump on abort; production wants it + off — otherwise panic silently resets), +- `CONFIG_WATCHDOG_AUTOSTART=n` (decide for production), +- `CONFIG_BOARD_LATE_INIT=y` (only used by a diag band). + +## Behavior notes + +- Console: 16×32 font (user's `.config`), white-on-black, rotated + 270° CW ⇒ landscape 60×75 text grid. To change rotation: + `uc_priv->rot` in `mt8183_scanout_probe` (0=portrait-native, + 1/3=the two landscape orientations, 2=upside-down portrait). +- Keyboard: pogo keyboard = USB HID behind the GL610 hub on + `usb@11200000`. Enumeration happens at preboot (`usb start`); the + usb_kbd probe re-muxes `stdin` from the env. If keys die, first + check `.config` still has the full USB set (Round 36). +- USB stick (sda) enumerates too (`USB_STORAGE`) — distro_bootcmd is + the next milestone. +- MMIO 0x0–0x20000000 is pre-mapped device memory (armv8-mem-map.c); + only DRAM-above-0x40000000/`0xffed9000` regions need dynamic + `mmu_map_region` (done in the scanout driver). + +## The 2021-era display handoff (why the shim exists) + +depthcharge (device-era, R93) `display_cleanup()` before the jump: +`clear_screen(black)`, backlight GPIOs low, `OVL_EN=0` (0x14008000+0xc), +`OVL0_2L_EN=0` (+0x100c). `OVL_L0_ADDR` (+0xf40) still holds the menu +scanout address. Both the shim and the scanout driver undo this; the +panel/DSI link is never reinitialized. + +## Quick reference + +```sh +# change rotation / code, then: +cd /home/vhaudiquet/u-boot && export CROSS_COMPILE=aarch64-linux-gnu- ARCH=arm && make -j8 +cd /home/vhaudiquet/krane-fb-stub && ./build-uboot-payload.sh +SZ=$(stat -c%s krane-uboot-payload.bin) && \ + dd if=krane-uboot-payload.bin of=/dev/mmcblk0p1 bs=4M conv=fsync && \ + cmp -n $SZ krane-uboot-payload.bin /dev/mmcblk0p1 && \ + futility vbutil_kernel --verify /dev/mmcblk0p1 +``` diff --git a/build-uboot-payload.sh b/build-uboot-payload.sh index 46e6e6c..35f4154 100755 --- a/build-uboot-payload.sh +++ b/build-uboot-payload.sh @@ -4,8 +4,8 @@ # 0x0000 64-byte arm64 Image header (code0 = b +0x40, image_size, # flags bit3, magic at 0x38 — booting.rst contract, verified # against depthcharge src/arch/arm/boot64.c) -# 0x0040 uboot-wrapper.S (diagnostic: revive display + magenta fill + -# blink train, then branch to U-Boot; branch imm26 patched) +# 0x0040 uboot-wrapper.S (entry shim: revive display, branch to +# U-Boot; branch imm26 patched) # 0x0040+ uboot.bin (u-boot-nodtb.bin + embedded control DTB), # contiguous — NO interior padding. # diff --git a/krane-uboot-payload.bin b/krane-uboot-payload.bin index 18821b9..c020926 100644 Binary files a/krane-uboot-payload.bin and b/krane-uboot-payload.bin differ diff --git a/krane-uboot.bin b/krane-uboot.bin index 00b5eac..ea043b1 100644 Binary files a/krane-uboot.bin and b/krane-uboot.bin differ diff --git a/uboot-wrapper.S b/uboot-wrapper.S index 87aff77..96bfe34 100644 --- a/uboot-wrapper.S +++ b/uboot-wrapper.S @@ -1,24 +1,24 @@ /* - * krane diagnostic wrapper — runs before U-Boot proper after the + * krane payload entry shim — runs at 0x40000040 right after the * depthcharge handoff (MMU off, caches off; position-independent: * immediate-encoded addresses only). * - * Purpose: prove that the payload actually executes and revive the - * display before U-Boot gets a chance to crash, so a dark screen can be - * attributed unambiguously: - * - magenta screen + backlight on, 3 slow blinks, magenta held ~5 s, - * then U-Boot takes over: wrapper ran - * - blink train repeating periodically: watchdog reset loop - * - dark screen, no blink train: wrapper never executed + * depthcharge's display_cleanup() stops the overlay engines and drops + * the backlight before jumping to the payload; this shim undoes those + * writes so the screen stays alive until U-Boot's scanout driver + * probes (the driver repeats the revival itself). The shim cannot be + * removed: depthcharge jumps to payload+0x40, while U-Boot's PIE + * fixup needs its runtime _start 4K-aligned — so U-Boot sits at image + * offset 0x1000 and this shim branches there (branch imm26 patched at + * build time by build-uboot-payload.sh). * - * Register sources (all verified on device, see RESEARCH.md rounds 4/10): - * OVL0 base 0x14008000: OVL_EN @ +0x000c, OVL0_2L_EN @ +0x100c, - * OVL_L0_ADDR @ +0x0f40 (depthcharge device-era mtk_ddp.c). + * Register sources (all verified on device, RESEARCH.md rounds 4/10): + * OVL0 base 0x14008000: OVL_EN @ +0x000c, OVL0_2L_EN @ +0x100c + * (device-era depthcharge mtk_ddp.c offsets). * GPIO controller 0x10005000, dout block +0x100, 16 B per 32-pin - * group, set @ +4 / rst @ +8 (mt8183.h GpioRegs): - * DISP_PWM = pin 43 (bit 11, set 0x10005114 / rst 0x10005118), - * EN_LCD_BL = pin 176 (bit 16, set 0x10005154 / rst 0x10005158). - * Scanout geometry: 1200*1920, 32bpp xRGB, 0x8ca000 bytes. + * group, set @ +4 (mt8183.h GpioRegs): + * DISP_PWM = pin 43 (bit 11, set 0x10005114), + * EN_LCD_BL = pin 176 (bit 16, set 0x10005154). */ .text @@ -43,59 +43,4 @@ _start: mov w3, #0x5154 movk w3, #0x1000, lsl #16 str w2, [x3] - /* live scanout address: OVL_L0_ADDR = 0x14008f40 */ - mov w3, #0x8f40 - movk w3, #0x1400, lsl #16 - ldr w4, [x3] - /* fill only when the address looks like DRAM (>= 0x40000000) */ - mov w5, #0x4000 - movk w5, #0x4000, lsl #16 - cmp w4, w5 - b.lo 1f - /* fill the scanout with magenta (0x00ff00ff): 0x8ca000/4 words */ - mov w2, #0xff - movk w2, #0xff00, lsl #16 - mov x6, #0x2800 - movk x6, #0x23, lsl #16 -2: str w2, [x4], #4 - subs x6, x6, #1 - b.ne 2b - /* blink the backlight 3x: repeating trains reveal a reset loop */ - mov w11, #3 -6: mov w2, #0x800 - mov w3, #0x5118 - movk w3, #0x1000, lsl #16 - str w2, [x3] - mov w2, #0x10000 - mov w3, #0x5158 - movk w3, #0x1000, lsl #16 - str w2, [x3] - bl delay - mov w2, #0x800 - mov w3, #0x5114 - movk w3, #0x1000, lsl #16 - str w2, [x3] - mov w2, #0x10000 - mov w3, #0x5154 - movk w3, #0x1000, lsl #16 - str w2, [x3] - bl delay - subs w11, w11, #1 - b.ne 6b - /* hold magenta for ~5 s so the phase cannot be missed */ - mov w12, #20 -7: bl delay - subs w12, w12, #1 - b.ne 7b 1: b . /* PATCHED: branch to U-Boot entry */ - - /* ~250 ms delay using the arch timer */ -delay: - mrs x7, cntfrq_el0 - lsr x7, x7, #2 - mrs x8, cntvct_el0 - add x8, x8, x7 -9: mrs x9, cntvct_el0 - cmp x9, x8 - b.lo 9b - ret