#!/usr/bin/env bash # SPDX-License-Identifier: LGPL-2.1-or-later # -*- mode: shell-script; indent-tabs-mode: nil; sh-basic-offset: 4; -*- # ex: ts=8 sw=4 sts=4 et filetype=sh set -eux set -o pipefail SYSUPDATE=/lib/systemd/systemd-sysupdate SYSUPDATED=/lib/systemd/systemd-sysupdated SECTOR_SIZES=(512 4096) WORKDIR="$(mktemp -d /var/tmp/test-72-XXXXXX)" CONFIGDIR="/run/sysupdate.d" BACKING_FILE="$WORKDIR/joined.raw" export SYSTEMD_ESP_PATH="$WORKDIR/esp" export SYSTEMD_XBOOTLDR_PATH="$WORKDIR/xbootldr" export SYSTEMD_PAGER=cat export SYSTEMD_LOG_LEVEL=debug if [[ ! -x "$SYSUPDATE" ]]; then echo "no systemd-sysupdate" >/skipped exit 77 fi # Loopback devices may not be supported. They are used because sfdisk cannot # change the sector size of a file, and we want to test both 512 and 4096 byte # sectors. If loopback devices are not supported, we can only test one sector # size, and the underlying device is likely to have a sector size of 512 bytes. if [[ ! -e /dev/loop-control ]]; then echo "No loopback device support" SECTOR_SIZES=(512) fi # Set up sysupdated drop-in pointing at the correct definitions and setting # no verification of images. mkdir -p /run/systemd/system/systemd-sysupdated.service.d cat >/run/systemd/system/systemd-sysupdated.service.d/override.conf<SHA256SUMS) } new_version() { local sector_size="${1:?}" local version="${2:?}" # Create a pair of random partition payloads, and compress one dd if=/dev/urandom of="$WORKDIR/source/part1-$version.raw" bs="$sector_size" count=2048 dd if=/dev/urandom of="$WORKDIR/source/part2-$version.raw" bs="$sector_size" count=2048 gzip -k -f "$WORKDIR/source/part2-$version.raw" # Create a random "UKI" payload echo $RANDOM >"$WORKDIR/source/uki-$version.efi" # Create a random extra payload echo $RANDOM >"$WORKDIR/source/uki-extra-$version.efi" # Create tarball of a directory mkdir -p "$WORKDIR/source/dir-$version" echo $RANDOM >"$WORKDIR/source/dir-$version/foo.txt" echo $RANDOM >"$WORKDIR/source/dir-$version/bar.txt" tar --numeric-owner -C "$WORKDIR/source/dir-$version/" -czf "$WORKDIR/source/dir-$version.tar.gz" . update_checksums } update_now() { # Update to newest version. First there should be an update ready, then we # do the update, and then there should not be any ready anymore "$SYSUPDATE" --verify=no check-new "$SYSUPDATE" --verify=no update (! "$SYSUPDATE" --verify=no check-new) } verify_version() { local block_device="${1:?}" local sector_size="${2:?}" local version="${3:?}" local part1_number="${4:?}" local gpt_reserved_sectors part2_number part1_offset part2_offset part2_number=$(( part1_number + 2 )) gpt_reserved_sectors=$((1024 * 1024 / sector_size)) part1_offset=$(((part1_number - 1) * 2048 + gpt_reserved_sectors)) part2_offset=$(((part2_number - 1) * 2048 + gpt_reserved_sectors)) # Check the partitions dd if="$block_device" bs="$sector_size" skip="$part1_offset" count=2048 | cmp "$WORKDIR/source/part1-$version.raw" dd if="$block_device" bs="$sector_size" skip="$part2_offset" count=2048 | cmp "$WORKDIR/source/part2-$version.raw" # Check the UKI cmp "$WORKDIR/source/uki-$version.efi" "$WORKDIR/xbootldr/EFI/Linux/uki_$version+3-0.efi" test -z "$(ls -A "$WORKDIR/esp/EFI/Linux")" # Check the extra efi cmp "$WORKDIR/source/uki-extra-$version.efi" "$WORKDIR/xbootldr/EFI/Linux/uki_$version.efi.extra.d/extra.addon.efi" } verify_version_current() { local version="${3:?}" verify_version "$@" # Check the directories cmp "$WORKDIR/source/dir-$version/foo.txt" "$WORKDIR/dirs/current/foo.txt" cmp "$WORKDIR/source/dir-$version/bar.txt" "$WORKDIR/dirs/current/bar.txt" } for sector_size in "${SECTOR_SIZES[@]}"; do # Disk size of: # - 1MB for GPT # - 4 partitions of 2048 sectors each # - 1MB for backup GPT disk_size=$((sector_size * 2048 * 4 + 1024 * 1024 * 2)) rm -f "$BACKING_FILE" truncate -s "$disk_size" "$BACKING_FILE" if [[ -e /dev/loop-control ]]; then blockdev="$(losetup --find --show --sector-size "$sector_size" "$BACKING_FILE")" else blockdev="$BACKING_FILE" fi sfdisk "$blockdev" <"$CONFIGDIR/01-first.conf" <"$CONFIGDIR/02-second.conf" <"$CONFIGDIR/03-third.conf" <"$CONFIGDIR/04-fourth.conf" <"$CONFIGDIR/05-fifth.conf" <"$CONFIGDIR/02-second.conf" <"$CONFIGDIR/03-third.conf" <