Round 12: U-Boot first boot black — diagnostic wrapper with green fill
This commit is contained in:
+36
@@ -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) |
|
||||
|
||||
+40
-26
@@ -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('<I', 0x14000010)
|
||||
# text_offset = 0 (left as zero)
|
||||
struct.pack_into('<Q', hdr, 0x10, 64 + len(uboot)) # image_size
|
||||
struct.pack_into('<Q', hdr, 0x18, 1 << 3) # flags: bit3
|
||||
hdr[0x38:0x3c] = b'ARM\x64' # magic
|
||||
hdr[0:4] = struct.pack('<I', (0x40 >> 2) | 0x14000000) # code0: b +0x40
|
||||
struct.pack_into('<Q', hdr, 0x10, total) # image_size
|
||||
struct.pack_into('<Q', hdr, 0x18, 1 << 3) # flags: bit3
|
||||
hdr[0x38:0x3c] = b'ARM\x64' # magic
|
||||
|
||||
# patch the wrapper's trailing `b .` to jump to the U-Boot entry
|
||||
br_off = wrap_off + wrap_len - 4
|
||||
imm = (uboot_off - br_off) // 4
|
||||
wrapper = bytearray(wrapper)
|
||||
wrapper[-4:] = struct.pack('<I', (imm & 0x03ffffff) | 0x14000000)
|
||||
|
||||
with open(out, 'wb') as f:
|
||||
f.write(hdr)
|
||||
f.write(wrapper)
|
||||
f.write(uboot)
|
||||
print("wrapped: %d = 64 + %d bytes" % (64 + len(uboot), len(uboot)))
|
||||
print("layout: header 64, wrapper %d (0x40..0x%x), uboot %d, total %d" %
|
||||
(wrap_len, uboot_off, len(uboot), total))
|
||||
EOF
|
||||
|
||||
# 3. pack + verify
|
||||
PYTHONPATH=/root/krane-fb-stub/src/depthcharge-tools python3 -m depthcharge_tools.mkdepthcharge \
|
||||
-A arm64 \
|
||||
-o "$OUT_PAYLOAD" \
|
||||
-n "krane u-boot framebuffer console" \
|
||||
-d "$OUT_IMG" \
|
||||
-d "$WRAP_IMG" \
|
||||
-b "$DTB"
|
||||
|
||||
echo "---- verify ----"
|
||||
|
||||
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
* krane diagnostic wrapper — runs before U-Boot proper after the
|
||||
* depthcharge handoff (MMU off, caches off, arbitrary 2 MiB-aligned
|
||||
* load slot; 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:
|
||||
* - green screen + backlight on = wrapper ran, U-Boot crashed later
|
||||
* - dark screen, no backlight = wrapper never executed
|
||||
*
|
||||
* 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).
|
||||
* GPIO controller 0x10005000, dout block +0x100, 16 B per 32-pin
|
||||
* group, set @ +4 (mt8183.h GpioRegs): DISP_PWM = pin 43 (bit 11,
|
||||
* 0x10005114), EN_LCD_BL = pin 176 (bit 16, 0x10005154).
|
||||
* Scanout geometry: 1200*1920*4 bpl-based = 0x8ca000 bytes, xRGB.
|
||||
*/
|
||||
|
||||
.text
|
||||
.globl _start
|
||||
_start:
|
||||
/* OVL_EN = 1 */
|
||||
mov w2, #1
|
||||
mov w3, #0x800c
|
||||
movk w3, #0x1400, lsl #16
|
||||
str w2, [x3]
|
||||
/* OVL0_2L_EN = 1 */
|
||||
mov w3, #0x900c
|
||||
movk w3, #0x1400, lsl #16
|
||||
str w2, [x3]
|
||||
/* backlight on: pin 43 (DISP_PWM), dout set 0x10005114, bit 11 */
|
||||
mov w2, #0x800
|
||||
mov w3, #0x5114
|
||||
movk w3, #0x1000, lsl #16
|
||||
str w2, [x3]
|
||||
/* backlight on: pin 176 (EN_LCD_BL), dout set 0x10005154, bit 16 */
|
||||
mov w2, #0x10000
|
||||
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 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 */
|
||||
Binary file not shown.
Reference in New Issue
Block a user