Correct the FIT alignment to 512, and stop gating on 2048
054790dclaimed the vendor aligns FIT sub-images to 0x800 and made that a build gate. Both were wrong, and the reasoning was thin: two payloads from one build, generalised into an invariant. What U-Boot actually requires. IMAGE_ALIGN_SIZE is 512 (include/image.h:955-958) and the read is blk_off = (FIT_ALIGN(fdt_totalsize) + offset) / blksz (arch/arm/mach-rockchip/fit.c:331), a truncating divide by the 512-byte eMMC block. So the metadata size must be a multiple of 512 -- otherwise FIT_ALIGN rounds it up and EVERY payload is read late, including ones whose own position is perfectly aligned -- and each data-position must be a multiple of 512. Nothing in the FIT or RESC path references 2048. Why the 2048 gate was actively harmful: of the eight boot.img files on this machine, four are 512-aligned but sit at data-position % 2048 = 1536, including vendor RELEASE_TEST builds that boot. The gate would have rejected images the vendor shipped. 0x800 is the vendor's -p value -- the file position of the FIRST payload -- not an alignment;054790dmoved it into the -B slot. And it broke the build inside the SDK. mk-bootimg.sh resolves mkimage with a bare `command -v`, project/build.sh:64 prepends the SDK tool directory to PATH, and the SDK vendors mkimage 2017.09, which has no -B and exits 255 with "invalid option -- 'B'" under set -euo pipefail. The 6.18 image built only because it was made from a normal shell that found host mkimage 2025.01. The flag is now feature-detected; the vendor packer 512-aligns natively, so omitting it there is correct rather than a fallback. 9387cff's -B 0x200 was right, and better derived than054790dcredited: the proven image's resource sits at 8748544, a multiple of 512 but not of 1024 or 2048, which pins the alignment at exactly 512 rather than bounding it. The gate now asserts what U-Boot enforces -- metadata % 512 and every data-position % 512 -- and the embedded-data guard drops from 65536 to >= 4096 to match FIT_FDT_MAX_SIZE (SZ_4K, fit.c:24). At 65536 a 5000-byte header passed the build and returned "No fit blob" on a panel. The already-flashed 6.18 boot.img is unaffected: 2048 is a multiple of 512, so it satisfies the real requirement, which is why it booted. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01T2D2KtdgwbhbF6Mo64eUrn
This commit is contained in:
+48
-27
@@ -130,38 +130,59 @@ cat > "$WORKDIR/boot.its" <<'ITS'
|
|||||||
};
|
};
|
||||||
ITS
|
ITS
|
||||||
|
|
||||||
# - SUB-IMAGE ALIGNMENT (`-B 0x800`). `-p` only places the FIRST payload; the
|
# - SUB-IMAGE ALIGNMENT (`-B 0x200`). `-p` places only the FIRST payload; the
|
||||||
# rest are packed contiguously, and U-Boot reads each one by dividing its
|
# rest are packed contiguously. U-Boot reads each with
|
||||||
# data-position by the 512-byte block size with a TRUNCATING divide. A
|
# `blk_off = (FIT_ALIGN(fdt_totalsize) + offset) / blksz` (fit.c:331), a
|
||||||
# payload that is not block-aligned is therefore read from the wrong offset:
|
# truncating divide by the 512-byte eMMC block, where FIT_ALIGN rounds to
|
||||||
# the RESC loader's sha256 fails and logo.bmp silently does not load
|
# IMAGE_ALIGN_SIZE = 512 (include/image.h:955-958). So TWO things must hold:
|
||||||
# (observed 2026-09-01, flare-edge 9387cff).
|
# the metadata size must be a multiple of 512, or FIT_ALIGN(T) != T and
|
||||||
|
# EVERY payload is read late by the difference; and each data-position must
|
||||||
|
# be a multiple of 512, or the divide drops the remainder.
|
||||||
#
|
#
|
||||||
# MEASURED, both directions. Without -B, this script produced kernel at
|
# Measured: without -B this script emitted the kernel at data-position
|
||||||
# 0x9A94 (data-position % 512 = 148) -- misaligned, exactly the failing
|
# 0x9A94 (% 512 = 148) with metadata 1064 (% 512 = 40) -- both faults at
|
||||||
# shape. The vendor images that actually boot this board are aligned to
|
# once. flare-edge 9387cff hit exactly this on hardware: "resource: sha256
|
||||||
# 0x800, not merely to 512: boot.img has fdt/kernel/resource at 0x800,
|
# Bad hash" then "No resource file: logo.bmp", fixed by -B 0x200 and
|
||||||
# 0x12800, 0x3A7800 and recovery.img at 0x800, 0x12800, 0x3F8800 -- every
|
# confirmed by a clean boot.
|
||||||
# one a multiple of 2048.
|
|
||||||
#
|
#
|
||||||
# 9387cff recorded `-B 0x200` from that failure. It is right but weaker than
|
# 512, NOT 2048. An earlier revision of this comment claimed the vendor
|
||||||
# it needed to be: it was inferred from noticing the proven image was
|
# aligns to 0x800 and gated on it. That was drawn from two payloads in one
|
||||||
# "512-aligned" without checking for a larger factor. 0x800 satisfies
|
# build. Across the vendor's own release images on this machine, every
|
||||||
# everything 0x200 does (every 0x800 multiple is a 0x200 multiple) and
|
# data-position is a multiple of 512 and only some are multiples of 2048
|
||||||
# additionally reproduces the vendor layout exactly, for at most 2 KiB of
|
# (four of eight RELEASE_TEST boot.img files sit at % 2048 = 1536), so a
|
||||||
# padding. When the two disagree, match the image that is known to boot.
|
# 2048 gate rejects images the vendor shipped and U-Boot boots. 0x800 is the
|
||||||
echo "== FIT (external data, -E -p 0x800 -B 0x800)"
|
# vendor's -p value -- the absolute position of the first payload -- not an
|
||||||
( cd "$WORKDIR" && mkimage -f boot.its -E -p 0x800 -B 0x800 boot.img >/dev/null )
|
# alignment.
|
||||||
|
#
|
||||||
|
# The flag is feature-detected because the SDK vendors mkimage 2017.09,
|
||||||
|
# which has no -B at all and dies with "invalid option -- 'B'". Its packer
|
||||||
|
# already 512-aligns, so omitting the flag there is correct rather than a
|
||||||
|
# fallback. project/build.sh prepends the SDK tool dir to PATH, so that
|
||||||
|
# binary IS what a build inside the SDK environment resolves.
|
||||||
|
if mkimage 2>&1 | grep -q -- '-B '; then
|
||||||
|
_align_flag="-B 0x200"
|
||||||
|
else
|
||||||
|
_align_flag=""
|
||||||
|
echo "== mkimage has no -B (vendor 2017.09); it 512-aligns natively"
|
||||||
|
fi
|
||||||
|
echo "== FIT (external data, -E -p 0x800 ${_align_flag:-no -B})"
|
||||||
|
( cd "$WORKDIR" && mkimage -f boot.its -E -p 0x800 ${_align_flag} boot.img >/dev/null )
|
||||||
|
|
||||||
# Every payload must land on a 0x800 boundary. This is the check that would have
|
# Assert what U-Boot actually requires, on every build: the failure is silent --
|
||||||
# caught the unaligned build before it reached a panel, so it runs on every
|
# a misread offset does not fail the build, it fails on a panel, and sometimes
|
||||||
# build rather than living in a separate tool nobody remembers to invoke.
|
# only as a missing logo.
|
||||||
|
_meta="$(od -An -tu4 -j4 -N4 --endian=big "$WORKDIR/boot.img" | tr -d ' ')"
|
||||||
|
if [ $(( _meta % 512 )) -ne 0 ]; then
|
||||||
|
echo "FATAL: FIT metadata is $_meta bytes, not a multiple of 512;" >&2
|
||||||
|
echo " FIT_ALIGN would round it up and every payload reads late" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
for _n in fdt kernel resource; do
|
for _n in fdt kernel resource; do
|
||||||
_pos="$(fdtget -t u "$WORKDIR/boot.img" "/images/$_n" data-position 2>/dev/null || true)"
|
_pos="$(fdtget -t u "$WORKDIR/boot.img" "/images/$_n" data-position 2>/dev/null || true)"
|
||||||
[ -n "$_pos" ] || continue
|
[ -n "$_pos" ] || continue
|
||||||
if [ $(( _pos % 2048 )) -ne 0 ]; then
|
if [ $(( _pos % 512 )) -ne 0 ]; then
|
||||||
echo "FATAL: /images/$_n data-position $_pos is not 0x800-aligned;" >&2
|
echo "FATAL: /images/$_n data-position $_pos is not 512-aligned;" >&2
|
||||||
echo " U-Boot's block divide would read it from the wrong offset" >&2
|
echo " U-Boot's truncating block divide would read the wrong offset" >&2
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
@@ -171,7 +192,7 @@ done
|
|||||||
# a panel that will not come back.
|
# a panel that will not come back.
|
||||||
meta="$(od -An -tu4 -j4 -N4 --endian=big "$WORKDIR/boot.img" | tr -d ' ')"
|
meta="$(od -An -tu4 -j4 -N4 --endian=big "$WORKDIR/boot.img" | tr -d ' ')"
|
||||||
total="$(stat -c %s "$WORKDIR/boot.img")"
|
total="$(stat -c %s "$WORKDIR/boot.img")"
|
||||||
if [ "${meta:-0}" -gt 65536 ] || [ "${meta:-0}" -ge "$total" ]; then
|
if [ "${meta:-0}" -ge 4096 ] || [ "${meta:-0}" -ge "$total" ]; then
|
||||||
echo "FATAL: FIT metadata is ${meta} bytes of a ${total}-byte image: that is an" >&2
|
echo "FATAL: FIT metadata is ${meta} bytes of a ${total}-byte image: that is an" >&2
|
||||||
echo " embedded-data FIT and U-Boot will report 'No fit blob'." >&2
|
echo " embedded-data FIT and U-Boot will report 'No fit blob'." >&2
|
||||||
exit 1
|
exit 1
|
||||||
|
|||||||
Reference in New Issue
Block a user