From 85c4b579d326c77cb4ce8bf3dc7368d3537db45d Mon Sep 17 00:00:00 2001 From: Tobias Waldekranz Date: Tue, 6 May 2025 10:17:58 +0200 Subject: [PATCH] ixbin: Add util script to update image contents [skip-ci] --- utils/ixbin | 269 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 269 insertions(+) create mode 100755 utils/ixbin diff --git a/utils/ixbin b/utils/ixbin new file mode 100755 index 000000000..b69285095 --- /dev/null +++ b/utils/ixbin @@ -0,0 +1,269 @@ +#!/bin/sh + +set -e + +usage() +{ + cat <&2 +} + +die() +{ + err "$*" + exit 1 +} + +ensuredeps() +{ + local DEPS="fakeroot mksquashfs unsquashfs awk env mkimage truncate dtc fdtget rauc" + local missing= + + for dep in $DEPS; do + command -v $dep >/dev/null && continue + missing="$missing $dep" + done + + if [ -n "$missing" ]; then + die "Missing dependencies:$missing" + fi +} + +squnpack() +{ + local sq="$WORKDIR"/pkg/rootfs.img + + # Capture the original compression algo and block size for when we + # resquash it later on. + unsquashfs -s "$sq" | awk ' + /^Compression/ { printf(" -comp %s", $2); } + /^Block size/ { printf(" -b %s", $3); } + ' >"$WORKDIR"/mksquash-opts + + $FAKEROOT unsquashfs -d "$WORKDIR"/rootfs "$sq" +} + +sqexec() +{ + $FAKEROOT env -C "$WORKDIR"/rootfs "$@" +} + +sqpack() +{ + $FAKEROOT mksquashfs "$WORKDIR"/rootfs "$WORKDIR"/pkg/rootfs.img \ + $(cat "$WORKDIR"/mksquash-opts) -noappend "$@" +} + +sqsign() +{ + local its="$1" + local keys="$2" + local hsize="$3" + local out="$4" + + mkimage -E -p "$hsize" -B "$hsize" -k "$keys" -f "$its" "$WORKDIR"/sign.itb + truncate -s $(($hsize)) "$WORKDIR"/sign.itb + mv "$WORKDIR"/sign.itb "$out" +} + +sqresign() +{ + local keys="$1" + local sq="$WORKDIR"/pkg/rootfs.img + local itbh="$WORKDIR"/pkg/rootfs.itbh + + signsize=$(printf '0x%x' $(fdtget "$itbh" /images/rootfs data-position)) + + dtc -I dtb -O dts "$itbh" | awk -v sq="$sq" ' + /timestamp =/ || /data-\w+ =/ || /signer-\w+ =/ || /value =/{ + /* Remove old signature */ + next; + } + + /compression = "none"/ { + /* Splice in reference to the squash */ + print; + sub("compression", "data"); + sub("\"none\"", sprintf("/incbin/(\"%s\")", sq)); + print; + next; + } + + { + /* Keep the rest as-is */ + print; + }; + ' >"$WORKDIR"/resign.its + + sqsign "$WORKDIR"/resign.its "$keys" "$signsize" "$itbh" +} + +unpack() +{ + local pkg="$1" + local keys="$2" + WORKDIR=$(readlink -f "$3") + + case "$#" in + 3) + ;; + *) + echo "Usage: ixbin unpack PKG KEYS DIR" >&2 + exit 1 + esac + + local crt=$(ls "$keys"/*.crt | head -n1) + [ -r "$crt" ] || die "No public key found in $keys" + + msg "Setting up working directory" + mkdir -p "$WORKDIR" + cp -a "$keys" "$WORKDIR"/in-keys + + touch "$WORKDIR"/fakeroot-state + FAKEROOT="fakeroot -i $WORKDIR/fakeroot-state -s $WORKDIR/fakeroot-state" + + msg "Unpacking RAUC bundle" + rauc --keyring="$crt" extract "$pkg" "$WORKDIR"/pkg + msg "Unpacking Squash filesystem" + squnpack + msg "OK, $WORKDIR/rootfs can now be modified" +} + +run() +{ + WORKDIR=$(readlink -f "$1") + shift + + [ -r "$WORKDIR"/fakeroot-state ] || \ + die "$WORKDIR does not contain an unpacked image" + FAKEROOT="fakeroot -i $WORKDIR/fakeroot-state -s $WORKDIR/fakeroot-state" + + sqexec "$@" +} + +pack() +{ + WORKDIR=$(readlink -f "$1") + local keys="$2" + local pkg="$3" + + case "$#" in + 3) + ;; + 2) + keys="$WORKDIR"/in-keys + pkg="$2" + ;; + *) + echo "Usage: ixbin pack DIR [KEYS] DIR" >&2 + exit 1 + esac + + [ -r "$WORKDIR"/fakeroot-state ] || \ + die "$WORKDIR does not contain an unpacked image" + + local crt=$(ls "$keys"/*.crt | head -n1) + [ -r "$crt" ] || die "No public key found in $keys" + + local key=$(ls "$keys"/*.key | head -n1) + [ -r "$crt" ] || die "No private key found in $keys" + + FAKEROOT="fakeroot -i $WORKDIR/fakeroot-state -s $WORKDIR/fakeroot-state" + + msg "Packing up Squash filesystem" + sqpack + [ -f "$WORKDIR"/pkg/rootfs.itbh ] && { + msg "Updating Squash filesystem signature" + sqresign "$keys" + } + + msg "Creating RAUC bundle" + rauc --keyring="$crt" --cert="$crt" --key="$key" bundle "$WORKDIR"/pkg "$pkg" + msg "OK, updated bundle available in $pkg" +} + +if [ $# -lt 1 ]; then + usage + exit 1 +fi + +cmd="$1" +shift + +case "$cmd" in + unpack) + ensuredeps + unpack "$@" + ;; + "exec") + ensuredeps + run "$@" + ;; + pack) + ensuredeps + pack "$@" + ;; + help) + usage + ;; + *) + die "Unknown command \"$cmd\"" + ;; +esac