diff --git a/RESEARCH.md b/RESEARCH.md index a2c4682..2564660 100644 --- a/RESEARCH.md +++ b/RESEARCH.md @@ -547,3 +547,39 @@ Panel shows the U-Boot banner (white/light-gray text on black, portrait path or early crash; backlit black = reached handoff but driver probe failed. The x0-FDT-zeros trap is bypassed: U-Boot uses its embedded DTB and never reads the handoff FDT. + +## Round 12 — first U-Boot boot: pitch black; diagnostic wrapper + +Reboot with Round-11 payload `1fc74a0a…`: **pitch black, no backlight**. +Per the Round-11 decision tree the video driver's probe never ran (the +OVL/backlight revival is its first act). So either the image never +executed (but Round 10 proved the handoff path, and only the payload +contents changed) or U-Boot died between entry and the video probe — a +wide window (PIE fixup, relocation, DM scan, and notably `initr_env` +(MMC/clock probe) runs before `stdio_add_devices` in board_r.c, i.e. +before video probe and the banner). + +### Localization flash (payload `9955943c…`) + +The wrapper itself now carries the life sign, independent of U-Boot: +`uboot-wrapper.S` (linked at +0x40 inside the Image, immediate-encoded +PIC, no relocations) runs before U-Boot proper: + +1. OVL revival + backlight (identical writes to the stub's stage0); +2. reads OVL_L0_ADDR, fills the scanout (guarded >= 0x40000000) with + full-screen green (0x8ca000 bytes = 1200*1920*4); +3. branches (imm26 patched at build time) to U-Boot's entry at + +0x40+wrapper_len (116 bytes). + +Layout verified by disassembly before flashing: header +(code0 b +0x40, image_size 0x6d9ac, flags bit3, magic), wrapper +instruction sequence, patched tail branch, U-Boot intact at +0xB4. +Payload flashed, cmp + on-device vbutil verify OK. + +### Decision tree + +| observation | meaning | +|---|---| +| green screen + backlight | wrapper ran; U-Boot crashed before video probe | +| dark, no backlight | wrapper never executed — handoff/boot-path problem with THIS image | +| U-Boot banner | everything works (banner replaces the green) | diff --git a/build-uboot-payload.sh b/build-uboot-payload.sh index cbdfece..43bcbc0 100755 --- a/build-uboot-payload.sh +++ b/build-uboot-payload.sh @@ -1,53 +1,67 @@ #!/bin/sh -# build-uboot-payload.sh — wrap /home/vhaudiquet/u-boot/u-boot.bin with the -# 64-byte arm64 Image header (same contract as stub.S: depthcharge jumps to -# the first byte of the image, so code0 must branch past the header) and -# pack it into a dev-signed depthcharge FIT for mmcblk0p1. +# build-uboot-payload.sh — build the krane U-Boot payload for mmcblk0p1: # -# Image header layout (linux/Documentation/arch/arm64/booting.rst, verified -# against depthcharge src/arch/arm/boot64.c): -# 0x00 code0 b +0x40 (branch past header; entry point) -# 0x04 code1 0 -# 0x08 text_offset 0 (image sits AT the 2 MiB-aligned base) -# 0x10 image_size header + u-boot.bin size (LE, patched below) -# 0x18 flags bit3 = place anywhere (KASLR slot math) -# 0x20..0x37 reserved 0 -# 0x38 magic 0x644d5241 "ARM\x64" -# 0x3c res5 0 +# 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 + green fill, +# then branch to U-Boot; branch imm26 patched below) +# 0x0040+ uboot.bin (u-boot-nodtb.bin + embedded control DTB) +# +# then pack with mkdepthcharge (devkeys) and verify. set -e cd "$(dirname "$0")" UBOOT_BIN="${UBOOT_BIN:-/home/vhaudiquet/u-boot/u-boot.bin}" DTB="${DTB:-krane-sku176.dtb}" -OUT_IMG=krane-uboot.bin +WRAP_IMG=krane-uboot.bin OUT_PAYLOAD=krane-uboot-payload.bin -python3 - "$UBOOT_BIN" "$OUT_IMG" <<'EOF' +# 1. assemble the diagnostic wrapper (raw binary, no relocations) +aarch64-linux-gnu-gcc -c uboot-wrapper.S -o uboot-wrapper.o +aarch64-linux-gnu-objcopy -O binary uboot-wrapper.o uboot-wrapper.bin +WRAP_LEN=$(stat -c %s uboot-wrapper.bin) + +# 2. header + wrapper + u-boot, patch both branches +python3 - "$UBOOT_BIN" "$WRAP_IMG" "$WRAP_LEN" <<'EOF' import struct, sys -src, out = sys.argv[1], sys.argv[2] -uboot = open(src, 'rb').read() +uboot_path, out, wrap_len = sys.argv[1], sys.argv[2], int(sys.argv[3]) +uboot = open(uboot_path, 'rb').read() +wrapper = open('uboot-wrapper.bin', 'rb').read() +assert len(wrapper) == wrap_len + +# wrapper entry at 0x40, U-Boot entry right after the wrapper +wrap_off = 0x40 +uboot_off = wrap_off + wrap_len +total = uboot_off + len(uboot) hdr = bytearray(64) -# code0: b .+0x40 => 0x14000000 | (0x40 >> 2) -hdr[0:4] = struct.pack('> 2) | 0x14000000) # code0: b +0x40 +struct.pack_into('= 0x40000000) */ + mov w5, #0x4000 + movk w5, #0x4000, lsl #16 + cmp w4, w5 + b.lo 1f + /* fill the scanout with green (0x0000ff00): 0x8ca000/4 words */ + mov w2, #0xff00 + mov x6, #0x2800 + movk x6, #0x23, lsl #16 +2: str w2, [x4], #4 + subs x6, x6, #1 + b.ne 2b +1: b . /* PATCHED: branch to U-Boot entry */ diff --git a/uboot-wrapper.bin b/uboot-wrapper.bin new file mode 100644 index 0000000..147e799 Binary files /dev/null and b/uboot-wrapper.bin differ