From b4abb082ff5ba336cd742b6244cd91bb097b8352 Mon Sep 17 00:00:00 2001 From: Tomaz Zaman Date: Wed, 12 Aug 2026 02:22:47 +0200 Subject: [PATCH 44/72] layerscape: teach the Mono upgrade path to flash gzipped sysupgrade images The next release compresses mono_gateway-dk's sysupgrade.bin with gzip (~44 MB instead of ~470 MB) to cut fleet OTA download size ~10x. The on-device flash path extracts tar members directly, and the shipped busybox tar has no compression autodetect (FEATURE_TAR_AUTODETECT is off), so it must learn to decompress explicitly. platform_do_upgrade_mono now detects the gzip magic and, BEFORE anything is written to the eMMC, strips the fwtool metadata trailer (fwtool -T, input image left untouched) and decompresses the whole stream to tmpfs, checking both exit statuses. gzip validates the deflate structure and the CRC32 of the entire uncompressed tar, so a truncated or corrupted download is refused up front - it can never abort mid-flash. The existing validated-target guard and fifo-based mono_dd_member streaming then operate on the verified plain tar exactly as before; uncompressed images keep taking the direct path, so current and older images flash unchanged. Rollout order matters: the RUNNING system's platform.sh does the flashing, so this change must be on the fleet BEFORE a release ships a gzipped image. On today's firmware a gzipped image fails cleanly pre-write (plain tar cannot read it) and the device reboots unharmed - but it would never install. Ship this first; flip the image recipe in the release after. Co-Authored-By: Claude Opus 4.8 --- .../base-files/lib/upgrade/platform.sh | 38 +++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/target/linux/layerscape/base-files/lib/upgrade/platform.sh b/target/linux/layerscape/base-files/lib/upgrade/platform.sh index 07d96265ae..0f37ae7ffd 100644 --- a/target/linux/layerscape/base-files/lib/upgrade/platform.sh +++ b/target/linux/layerscape/base-files/lib/upgrade/platform.sh @@ -124,6 +124,26 @@ platform_copy_config_sdboot() { umount /mnt fi } +# Decompress a gzipped sysupgrade image ($1) to a plain tar ($2), verifying +# the whole gzip stream (CRC32) before returning success. The fwtool metadata +# trailer sits after the gzip stream, so strip it first with fwtool -T ($1 is +# left untouched) - fed the raw image, gzip's exit status would be ambiguous +# (trailing garbage vs corruption). A bad image fails here, before any dd. +mono_decompress_image() { # image.bin out.tar + local scratch="$2.gz" + fwtool -q -T -i /dev/null "$1" > "$scratch" || { + rm -f "$scratch" + echo "Could not strip the metadata trailer from the image" + return 1 + } + gzip -dc "$scratch" > "$2" || { + rm -f "$scratch" "$2" + echo "Image failed the gzip integrity check" + return 1 + } + rm -f "$scratch" +} + # Stream a sysupgrade tar member to a block device, failing if EITHER tar or dd # fails. A plain "tar | dd || ..." only observes dd's exit status, so a # truncated/erroring tar with a dd that exits 0 would silently write a short @@ -141,6 +161,24 @@ mono_dd_member() { # tar_file board_dir member device platform_do_upgrade_mono() { local tar_file="$1" + + # sysupgrade.bin ships gzipped (~44 MB vs ~470 MB) to cut OTA downloads. + # The shipped busybox tar has no compression autodetect, and streaming a + # decompress into the tar calls below could abort mid-write on a corrupt + # download - so verify and decompress the whole image to tmpfs first, + # then flash unchanged. Non-gzip images keep taking the direct path. + # PID-unique temp names so no operator-supplied image path in /tmp can + # collide with (and be truncated by) our own redirects. + if [ "$(dd if="$tar_file" bs=2 count=1 2>/dev/null | hexdump -v -n 2 -e '1/1 "%02x"')" = "1f8b" ]; then + local gz_tar="/tmp/mono-upgrade.$$.tar" + echo "Verifying and decompressing the sysupgrade image..." + mono_decompress_image "$tar_file" "$gz_tar" || { + echo "Refusing upgrade: image did not decompress cleanly - nothing was written" + return 1 + } + tar_file="$gz_tar" + fi + local board_dir=$(tar tf $tar_file | grep -m 1 '^sysupgrade-.*/$') board_dir=${board_dir%/} -- 2.47.3