Files
krane-fb-stub/U-BOOT.md
T

7.6 KiB
Raw Blame History

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

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:

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

cd /home/vhaudiquet/krane-fb-stub
./build-uboot-payload.sh

Assembles header + wrapper + u-boot.binkrane-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)

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-updates, 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 43/176), parses the coreboot table LBIO at 0xffed9000, falls back to OVL_L0_ADDR (0x14008f40), sets uc_priv->rot = 3 (270° CW landscape console). The shared handoff code lives in mt8183_disp.c / mt8183_disp.h.
  • drivers/video/mt8183_display.c — full cold bring-up driver (Kconfig choice VIDEO_MT8183_DISPLAY, now the defconfig default; VIDEO_MT8183_SCANOUT keeps the old behavior): MMSYS display gates, SMI LARB0, panel init via drivers/video/mtk_dsi.c + drivers/phy/phy-mtk-mipi-tx.c + drivers/video/panel_boe_tv101wum.c, overlay scanout of a framebuffer at 0xFC000000 (FDT memreserve + LMB), backlight. Falls back to the handoff revival, logging the stage. Serial prints: [dsi] phase 0/9/F.
  • drivers/gpio/mt8183_gpio.c — minimal MT8183 GPIO driver (dir/dout/ din; pinmux left to firmware) for the panel reset / supply-enable pads.
  • drivers/clk/mediatek/clk-mt8183.c — now also models the MMSYS display gates (CLK_MM_*) as a clock provider on mmsys@14000000.
  • board/mediatek/mt8183/mt8183.cget_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.envstdin=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

# 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