From 054790dde6f64c34ed275be4586c148c39e0c494 Mon Sep 17 00:00:00 2001 From: Noah Date: Fri, 4 Sep 2026 16:16:33 -0600 Subject: [PATCH] Align every FIT sub-image to 0x800, and check it mkimage -p only places the FIRST payload. The rest are packed contiguously, and U-Boot reads each by dividing its data-position by the 512-byte block size with a truncating divide -- so a payload that is not block-aligned is read from the wrong offset. Measured: without -B this script emitted the kernel at 0x9A94, data-position % 512 = 148, which is exactly the failing shape. That failure is on record. flare-edge 9387cff (2026-09-01) hit it on a boot_b FIT: "unaligned sub-images fail the RESC loader's sha256 and the logo silently falls back to 'No resource file'". It landed on -B 0x200, inferred from noticing the proven image was "512-aligned" without checking for a larger factor. The proven images are aligned to 0x800, not merely to 512. Measured on the pair that boots this board today: boot.img fdt/kernel/resource at 0x800 / 0x12800 / 0x3A7800, recovery.img at 0x800 / 0x12800 / 0x3F8800 -- every one a multiple of 2048. So 0x800 satisfies everything 0x200 does, since every 0x800 multiple is a 0x200 multiple, and additionally reproduces the vendor layout exactly. The cost is at most 2 KiB of padding. Where a remembered rule and a booting image disagree, match the image. The alignment is now also asserted at build time rather than trusted. It runs on every build because the failure it catches is silent -- a wrong offset does not fail the build, it fails on a panel, and only sometimes visibly. Co-Authored-By: Claude Opus 5 (1M context) Claude-Session: https://claude.ai/code/session_01T2D2KtdgwbhbF6Mo64eUrn --- build/mk-bootimg.sh | 37 +++++++++++++++++++++++++++++++++++-- 1 file changed, 35 insertions(+), 2 deletions(-) diff --git a/build/mk-bootimg.sh b/build/mk-bootimg.sh index 642150f..e23cd76 100755 --- a/build/mk-bootimg.sh +++ b/build/mk-bootimg.sh @@ -130,8 +130,41 @@ cat > "$WORKDIR/boot.its" <<'ITS' }; ITS -echo "== FIT (external data, -E -p 0x800)" -( cd "$WORKDIR" && mkimage -f boot.its -E -p 0x800 boot.img >/dev/null ) +# - SUB-IMAGE ALIGNMENT (`-B 0x800`). `-p` only places the FIRST payload; the +# rest are packed contiguously, and U-Boot reads each one by dividing its +# data-position by the 512-byte block size with a TRUNCATING divide. A +# payload that is not block-aligned is therefore read from the wrong offset: +# the RESC loader's sha256 fails and logo.bmp silently does not load +# (observed 2026-09-01, flare-edge 9387cff). +# +# MEASURED, both directions. Without -B, this script produced kernel at +# 0x9A94 (data-position % 512 = 148) -- misaligned, exactly the failing +# shape. The vendor images that actually boot this board are aligned to +# 0x800, not merely to 512: boot.img has fdt/kernel/resource at 0x800, +# 0x12800, 0x3A7800 and recovery.img at 0x800, 0x12800, 0x3F8800 -- every +# one a multiple of 2048. +# +# 9387cff recorded `-B 0x200` from that failure. It is right but weaker than +# it needed to be: it was inferred from noticing the proven image was +# "512-aligned" without checking for a larger factor. 0x800 satisfies +# everything 0x200 does (every 0x800 multiple is a 0x200 multiple) and +# additionally reproduces the vendor layout exactly, for at most 2 KiB of +# padding. When the two disagree, match the image that is known to boot. +echo "== FIT (external data, -E -p 0x800 -B 0x800)" +( cd "$WORKDIR" && mkimage -f boot.its -E -p 0x800 -B 0x800 boot.img >/dev/null ) + +# Every payload must land on a 0x800 boundary. This is the check that would have +# caught the unaligned build before it reached a panel, so it runs on every +# build rather than living in a separate tool nobody remembers to invoke. +for _n in fdt kernel resource; do + _pos="$(fdtget -t u "$WORKDIR/boot.img" "/images/$_n" data-position 2>/dev/null || true)" + [ -n "$_pos" ] || continue + if [ $(( _pos % 2048 )) -ne 0 ]; then + echo "FATAL: /images/$_n data-position $_pos is not 0x800-aligned;" >&2 + echo " U-Boot's block divide would read it from the wrong offset" >&2 + exit 1 + fi +done # A FIT whose metadata swelled to the size of the whole image is an # embedded-data build, which this U-Boot rejects. Catch it here rather than on