From 391756e573d42248bf4ad13d5f438703c6c59514 Mon Sep 17 00:00:00 2001 From: vhaudiquet Date: Sun, 30 Aug 2026 12:56:55 +0200 Subject: [PATCH] Round 18: vectors-before-_start discovered; wrapper-only 4K isolator flash --- RESEARCH.md | 23 +++++++++++++++++++++++ build-uboot-payload.sh | 41 +++++++++++++++++++++++++++-------------- uboot-wrapper.S | 18 +++++++++++------- uboot-wrapper.bin | Bin 236 -> 252 bytes 4 files changed, 61 insertions(+), 21 deletions(-) diff --git a/RESEARCH.md b/RESEARCH.md index 64d64c3..a3dc9b4 100644 --- a/RESEARCH.md +++ b/RESEARCH.md @@ -711,3 +711,26 @@ contiguous — wfi hang expected) + 8 KiB zero tail padding → total |---|---| | green | total size innocent → the 0x1000 alignment padding/placement is the killer (re-test padding content) | | black | total size (image_size value) alone gates the handoff | + +## Round 18 — total size ruled out; wrapper-only isolator + +R17 (R16 content + 8 KiB tail pad, total 457964 > dead 453432): +**green** — total size ruled out. The only remaining structural +difference between ran (R12/13/16/17: U-Boot contiguous at 0xB4) and +dead (R14/15: U-Boot at 0x1000 behind interior zero pad): the interior +pad + shifted placement. Also discovered: the U-Boot binary does NOT +start at _start — `arch/arm/cpu/u-boot.lds` places 0x40 bytes of +`.vectors` first, so link _start = 0x4C000140 (all prior alignment math +shifts by 0x40; the PIE requirement is runtime _start ≡ link _start +mod 4K AND start.S's wfi check demands runtime _start ≡ 0 mod 4K, so +link _start must be 4K-aligned too). + +### Test B (payload 9485c59e…, flashed, cmp+vbutil OK, body 0x14000) + +4 KiB image: header + wrapper v3 (magenta + 3 blinks + ~5 s hold) + +zeros to 0x1000 + NO U-Boot, tail branch patched to self (hang): + +| observation | conclusion | +|---|---| +| magenta + blinks + hang | interior pad innocent; the trigger is U-Boot content/placement at 0x1000 | +| black, nothing | depthcharge rejects the padded image before any execution | diff --git a/build-uboot-payload.sh b/build-uboot-payload.sh index e11493f..0432cda 100755 --- a/build-uboot-payload.sh +++ b/build-uboot-payload.sh @@ -4,15 +4,21 @@ # 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) +# 0x0040 uboot-wrapper.S (diagnostic: revive display + magenta fill + +# blink train, then branch to U-Boot; branch imm26 patched) +# 0x0040+ uboot.bin (u-boot-nodtb.bin + embedded control DTB), +# contiguous — NO interior padding. +# +# U-Boot's PIE fixup requires the run-vs-link delta to be 4K-aligned: +# CONFIG_TEXT_BASE must equal 0x4c000000 + the U-Boot file offset. The +# script verifies this against the _start symbol in u-boot.sym. # # then pack with mkdepthcharge (devkeys) and verify. set -e cd "$(dirname "$0")" UBOOT_BIN="${UBOOT_BIN:-/home/vhaudiquet/u-boot/u-boot.bin}" +UBOOT_SYM="${UBOOT_SYM:-/home/vhaudiquet/u-boot/u-boot.sym}" DTB="${DTB:-krane-sku176.dtb}" WRAP_IMG=krane-uboot.bin OUT_PAYLOAD=krane-uboot-payload.bin @@ -22,30 +28,38 @@ 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' +# 2. header + wrapper + u-boot, patch the wrapper's tail branch +python3 - "$UBOOT_BIN" "$UBOOT_SYM" "$WRAP_IMG" "$WRAP_LEN" <<'EOF' import struct, sys -uboot_path, out, wrap_len = sys.argv[1], sys.argv[2], int(sys.argv[3]) +uboot_path, sym_path, out = sys.argv[1], sys.argv[2], sys.argv[3] +wrap_len = int(sys.argv[4]) 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 +# wrapper entry at 0x40, U-Boot right after the wrapper (contiguous) wrap_off = 0x40 uboot_off = wrap_off + wrap_len total = uboot_off + len(uboot) +# verify the U-Boot link address matches its runtime placement +for line in open(sym_path): + parts = line.split() + if len(parts) == 3 and parts[2] == '_start': + start = int(parts[0], 16) + break +else: + raise SystemExit('_start not found in u-boot.sym') +assert start == 0x4c000000 + uboot_off, \ + "TEXT_BASE/_start 0x%x != expected 0x%x" % (start, 0x4c000000 + uboot_off) + hdr = bytearray(64) hdr[0:4] = struct.pack('> 2) | 0x14000000) # code0: b +0x40 struct.pack_into('nIDm9ED?{PJzyCvem>PmufczdH|KR_L$J79P Cst{HH delta 34 pcmeyv_=a&p2-9NbiD6DGybKIeCdw#qu>k38R))fbe