Round 37: stub-free entry shim; U-BOOT.md handoff doc; payload cc014efa

The diagnostic wrapper phase (magenta fill, 3-blink train, 5 s hold)
is removed; the shim keeps only the load-bearing display revival
(OVL_EN, OVL0_2L_EN, backlight GPIOs) and the patched branch to
U-Boot. U-BOOT.md documents the boot chain, payload layout constants,
build/flash/verify commands, recovery and the U-Boot tree state.
U-Boot was rebuilt with the user's hand-tuned .config (16x32 font,
CONFIG_CHROMEOS) without re-running the defconfig.
This commit is contained in:
vhaudiquet
2026-08-30 21:12:03 +02:00
parent f62b9a3bf7
commit 2dceb2c8a4
6 changed files with 212 additions and 72 deletions
+33
View File
@@ -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.
+162
View File
@@ -0,0 +1,162 @@
# U-Boot on krane — final state and operating manual
Status as of 2026-08-30 (RESEARCH.md Rounds 136). 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 0x00x20000000 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
```
+2 -2
View File
@@ -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.
#
Binary file not shown.
BIN
View File
Binary file not shown.
+15 -70
View File
@@ -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