From: Caleb James DeLisle Date: Mon, 25 May 2026 13:40:18 +0000 (+0000) Subject: econet: tclinux-trx.sh make rootfs optional and move padding to kernel X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=04c747b3fcc40b7d37583e9ee2b4b75782018b46;p=thirdparty%2Fopenwrt.git econet: tclinux-trx.sh make rootfs optional and move padding to kernel The TRX header contains a checksum of the full kernel and rootfs length. Vendor OS uses a raw squashfs on the NAND and relies on the BMT to resolve bad block issues. OpenWrt typically uses UBI on NAND and places the root squashfs inside of that. Since UBI changes over time, checksumming over it would cause a boot failure later on. However, vendor TRX installers typically the entire file as uploaded, without regard for the declared kernel and rootfs lengths. Make --rootfs optional so that a UBI rootfs can be appended but excluded from the checksum. Secondly, this script previously prepended padding to the rootfs in order to move the beginning of the rootfs 4MB away from the TRX header (the max kernel size). That prepended padding was included in the rootfs length/checksum. There is a bug https://econet-linux.pkt.wiki/en/bootloader#a-length-bug in some versions of the bootloader which causes the bootloader to always use the length of the first kernel, even if it is booting the second. The impact of this is if the second slot kernel is larger than the first, it will fail to boot. Smaller is okay because LZMA will stop when it is done. Move padding from rootfs to kernel and include it in the length/checksum of the kernel so that the kernel will always register as being 4MB-minus-TRX-header in length. Therefore if A/B upgrading is used in the future, this bug will not occur even if an upgrade with a larger kernel is installed into slot B. Signed-off-by: Caleb James DeLisle Link: https://github.com/openwrt/openwrt/pull/23533 Signed-off-by: Jonas Jelonek --- diff --git a/target/linux/econet/image/tclinux-trx.sh b/target/linux/econet/image/tclinux-trx.sh index 3750e9112da..3f28ba86f93 100755 --- a/target/linux/econet/image/tclinux-trx.sh +++ b/target/linux/econet/image/tclinux-trx.sh @@ -3,8 +3,14 @@ set -e -# This is not necessary, but it makes finding the rootfs easier. -PAD_ROOTFS_OFFSET_TO=4194304 +# Maximum kernel size +# NOTE: We ff-pad the kernel and specify the fully padded length as the kernel +# size in the TRX header. This works around a bug wherein the bootloader +# reads the kernel length from the kernel in slot A, when it is booting +# slot B. By including the padding in the length, the kernel length is +# always the same, and the LZMA decompressor stops when it's done anyway. +# See: https://econet-linux.pkt.wiki/en/bootloader#a-length-bug +PAD_ROOTFS_OFFSET_TO=$((4 * 1024 * 1024)) # Constant HDRLEN=256 @@ -20,7 +26,7 @@ SYNTAX: $0 --kernel --rootfs --version [options] Options: --kernel Path to kernel lzma file (required) - --rootfs Path to rootfs squashfs file (required) + --rootfs Path to rootfs squashfs file --version Version string, max 31 chars (required) --endian Endianness: 'be' for big endian, 'le' for little endian (default: be) --model Model/platform name, max 31 chars (default: empty) @@ -69,7 +75,6 @@ done # Validate required arguments [ -n "$kernel" ] || die "Missing required argument: --kernel" -[ -n "$rootfs" ] || die "Missing required argument: --rootfs" [ -n "$version" ] || die "Missing required argument: --version" # Validate endianness @@ -81,28 +86,27 @@ esac which zytrx >/dev/null || die "zytrx not found in PATH $PATH" [ -f "$kernel" ] || die "Kernel file not found: $kernel" -[ -f "$rootfs" ] || die "Rootfs file not found: $rootfs" +[ -z "$rootfs" ] || [ -f "$rootfs" ] || die "Rootfs file not found: $rootfs" [ "$(echo "$version" | wc -c)" -lt 32 ] || die "Version string too long: $version" [ -z "$model" ] || [ "$(printf '%s' "$model" | wc -c)" -lt 32 ] || die "Model string too long: $model" kernel_len=$(stat -c '%s' "$kernel") header_plus_kernel_len=$(($HDRLEN + $kernel_len)) -rootfs_len=$(stat -c '%s' "$rootfs") - -if [ "$PAD_ROOTFS_OFFSET_TO" -gt "$header_plus_kernel_len" ]; then - padding_len=$(($PAD_ROOTFS_OFFSET_TO - $header_plus_kernel_len)) -else - padding_len=0 +rootfs_len=0 +if [ -f "$rootfs" ]; then + rootfs_len=$(stat -c '%s' "$rootfs") fi +[ "$PAD_ROOTFS_OFFSET_TO" -gt "$header_plus_kernel_len" ] || die "kernel is too large" + +padding_len=$(($PAD_ROOTFS_OFFSET_TO - $header_plus_kernel_len)) + echo "endian: $endian" >&2 echo "padding_len: $padding_len" >&2 -padded_rootfs_len=$(($padding_len + $rootfs_len)) +padded_kernel_len=$(($padding_len + $kernel_len)) -echo "padded_rootfs_len: $padded_rootfs_len" >&2 - -total_len=$(($header_plus_kernel_len + $padded_rootfs_len)) +total_len=$(($PAD_ROOTFS_OFFSET_TO + $rootfs_len)) echo "total_len: $total_len" >&2 @@ -135,7 +139,9 @@ trx_crc32() { outtmpfile=$(mktemp) cat "$kernel" > "$tmpfile" padding >> "$tmpfile" - cat "$rootfs" >> "$tmpfile" + if [ -f "$rootfs" ]; then + cat "$rootfs" >> "$tmpfile" + fi # We just need a CRC-32/JAMCRC of the concatnated files # There's no readily available tool for this, but zytrx does create one when # creating their TRX header, so we just use that. @@ -174,10 +180,10 @@ tclinux_trx_hdr() { head -c 32 /dev/zero | to_hex # kernel length - hex32 "$kernel_len" + hex32 "$padded_kernel_len" # rootfs length - hex32 "$padded_rootfs_len" + hex32 "$rootfs_len" # romfile length (0) hex32 0 @@ -200,4 +206,6 @@ tclinux_trx_hdr() { tclinux_trx_hdr | from_hex cat "$kernel" padding -cat "$rootfs" +if [ -f "$rootfs" ]; then + cat "$rootfs" +fi