2023-12-05 17:18:17 +03:00
#!/usr/bin/env bash
# SPDX-License-Identifier: LGPL-2.1-or-later
set -eux
set -o pipefail
if systemd-detect-virt --quiet --container; then
echo "running on container, skipping."
exit 0
fi
if ! command -v bootctl >/dev/null; then
echo "bootctl not found, skipping."
exit 0
fi
2024-02-13 20:16:19 +03:00
if [ [ ! -d /usr/lib/systemd/boot/efi ] ] ; then
echo "sd-boot is not installed, skipping."
exit 0
fi
2023-12-05 17:18:17 +03:00
# shellcheck source=test/units/util.sh
. " $( dirname " $0 " ) " /util.sh
# shellcheck source=test/units/test-control.sh
. " $( dirname " $0 " ) " /test-control.sh
basic_tests( ) {
bootctl " $@ " --help
bootctl " $@ " --version
bootctl " $@ " install --make-entry-directory= yes
bootctl " $@ " remove --make-entry-directory= yes
bootctl " $@ " install --all-architectures
bootctl " $@ " remove --all-architectures
bootctl " $@ " install --make-entry-directory= yes --all-architectures
bootctl " $@ " remove --make-entry-directory= yes --all-architectures
bootctl " $@ " install
( ! bootctl " $@ " update)
bootctl " $@ " update --graceful
bootctl " $@ " is-installed
bootctl " $@ " is-installed --graceful
bootctl " $@ " random-seed
bootctl " $@ "
bootctl " $@ " status
bootctl " $@ " status --quiet
bootctl " $@ " list
bootctl " $@ " list --quiet
bootctl " $@ " list --json= short
bootctl " $@ " list --json= pretty
bootctl " $@ " remove
( ! bootctl " $@ " is-installed)
( ! bootctl " $@ " is-installed --graceful)
}
testcase_bootctl_basic( ) {
2024-02-22 16:00:00 +03:00
assert_in " $( bootctl --print-esp-path) " " ^(/boot/|/efi) $"
assert_in " $( bootctl --print-boot-path) " " ^(/boot/|/efi) $"
2023-12-05 17:18:17 +03:00
bootctl --print-root-device
basic_tests
}
cleanup_image( ) (
set +e
if [ [ -z " ${ IMAGE_DIR :- } " ] ] ; then
return 0
fi
umount " ${ IMAGE_DIR } /root "
if [ [ -n " ${ LOOPDEV :- } " ] ] ; then
losetup -d " ${ LOOPDEV } "
unset LOOPDEV
fi
udevadm settle
rm -rf " ${ IMAGE_DIR } "
unset IMAGE_DIR
return 0
)
testcase_bootctl_image( ) {
IMAGE_DIR = " $( mktemp --directory /tmp/test-bootctl.XXXXXXXXXX) "
trap cleanup_image RETURN
truncate -s 256m " ${ IMAGE_DIR } /image "
cat >" ${ IMAGE_DIR } /partscript " <<EOF
label: gpt
type = C12A7328-F81F-11D2-BA4B-00A0C93EC93B name = esp size = 64M
type = 0FC63DAF-8483-4772-8E79-3D69D8477DE4 name = root size = 64M bootable
type = BC13C2FF-59E6-4262-A352-B275FD6F7172 name = boot
EOF
LOOPDEV = " $( losetup --show -P -f " ${ IMAGE_DIR } /image " ) "
sfdisk " $LOOPDEV " <" ${ IMAGE_DIR } /partscript "
udevadm settle
mkfs.vfat -n esp " ${ LOOPDEV } p1 "
mkfs.ext4 -L root " ${ LOOPDEV } p2 "
mkfs.ext4 -L boot " ${ LOOPDEV } p3 "
mkdir -p " ${ IMAGE_DIR } /root "
mount -t ext4 " ${ LOOPDEV } p2 " " ${ IMAGE_DIR } /root "
mkdir -p " ${ IMAGE_DIR } /root/efi "
mkdir -p " ${ IMAGE_DIR } /root/boot "
mkdir -p " ${ IMAGE_DIR } /root/etc "
mkdir -p " ${ IMAGE_DIR } /root/usr/lib "
if [ [ -f /usr/lib/os-release ] ] ; then
cp /usr/lib/os-release " ${ IMAGE_DIR } /root/usr/lib/. "
ln -s ../usr/lib/os-release " ${ IMAGE_DIR } /root/etc/os-release "
else
cp -a /etc/os-release " ${ IMAGE_DIR } /root/etc/. "
fi
umount " ${ IMAGE_DIR } /root "
assert_eq " $( bootctl --image " ${ IMAGE_DIR } /image " --print-esp-path) " "/run/systemd/mount-rootfs/efi"
assert_eq " $( bootctl --image " ${ IMAGE_DIR } /image " --print-esp-path --esp-path= /efi) " "/run/systemd/mount-rootfs/efi"
assert_eq " $( bootctl --image " ${ IMAGE_DIR } /image " --print-boot-path) " "/run/systemd/mount-rootfs/boot"
assert_eq " $( bootctl --image " ${ IMAGE_DIR } /image " --print-boot-path --boot-path= /boot) " "/run/systemd/mount-rootfs/boot"
# FIXME: This provides spurious result.
bootctl --image " ${ IMAGE_DIR } /image " --print-root-device || :
basic_tests --image " ${ IMAGE_DIR } /image "
}
cleanup_raid( ) (
set +e
if [ [ -z " ${ IMAGE_DIR :- } " ] ] ; then
return 0
fi
systemd-umount " ${ IMAGE_DIR } /root/efi "
systemd-umount " ${ IMAGE_DIR } /root/boot "
systemd-umount " ${ IMAGE_DIR } /root "
mdadm --misc --stop /dev/md/raid-esp
mdadm --misc --stop /dev/md/raid-root
if [ [ -n " ${ LOOPDEV1 :- } " ] ] ; then
mdadm --misc --force --zero-superblock " ${ LOOPDEV1 } p1 "
mdadm --misc --force --zero-superblock " ${ LOOPDEV1 } p2 "
fi
if [ [ -n " ${ LOOPDEV2 :- } " ] ] ; then
mdadm --misc --force --zero-superblock " ${ LOOPDEV2 } p1 "
mdadm --misc --force --zero-superblock " ${ LOOPDEV2 } p2 "
fi
udevadm settle
if [ [ -n " ${ LOOPDEV1 :- } " ] ] ; then
mdadm --misc --force --zero-superblock " ${ LOOPDEV1 } p1 "
mdadm --misc --force --zero-superblock " ${ LOOPDEV1 } p2 "
losetup -d " ${ LOOPDEV1 } "
unset LOOPDEV1
fi
if [ [ -n " ${ LOOPDEV2 :- } " ] ] ; then
mdadm --misc --force --zero-superblock " ${ LOOPDEV2 } p1 "
mdadm --misc --force --zero-superblock " ${ LOOPDEV2 } p2 "
losetup -d " ${ LOOPDEV2 } "
unset LOOPDEV2
fi
udevadm settle
rm -rf " ${ IMAGE_DIR } "
return 0
)
testcase_bootctl_raid( ) {
if ! command -v mdadm >/dev/null; then
echo "mdadm not found, skipping."
return 0
fi
if ! command -v mkfs.btrfs >/dev/null; then
echo "mkfs.btrfs not found, skipping."
return 0
fi
IMAGE_DIR = " $( mktemp --directory /tmp/test-bootctl.XXXXXXXXXX) "
trap cleanup_raid RETURN
truncate -s 256m " ${ IMAGE_DIR } /image1 "
truncate -s 256m " ${ IMAGE_DIR } /image2 "
cat >" ${ IMAGE_DIR } /partscript " <<EOF
label: gpt
type = C12A7328-F81F-11D2-BA4B-00A0C93EC93B name = esp size = 64M
type = 0FC63DAF-8483-4772-8E79-3D69D8477DE4 name = root size = 64M bootable
type = BC13C2FF-59E6-4262-A352-B275FD6F7172 name = boot
EOF
LOOPDEV1 = " $( losetup --show -P -f " ${ IMAGE_DIR } /image1 " ) "
LOOPDEV2 = " $( losetup --show -P -f " ${ IMAGE_DIR } /image2 " ) "
sfdisk " $LOOPDEV1 " <" ${ IMAGE_DIR } /partscript "
sfdisk " $LOOPDEV2 " <" ${ IMAGE_DIR } /partscript "
udevadm settle
echo y | mdadm --create /dev/md/raid-esp --name "raid-esp" " ${ LOOPDEV1 } p1 " " ${ LOOPDEV2 } p1 " -v -f --level= 1 --raid-devices= 2
mkfs.vfat /dev/md/raid-esp
echo y | mdadm --create /dev/md/raid-root --name "raid-root" " ${ LOOPDEV1 } p2 " " ${ LOOPDEV2 } p2 " -v -f --level= 1 --raid-devices= 2
mkfs.ext4 /dev/md/raid-root
mkfs.btrfs -f -M -d raid1 -m raid1 -L "raid-boot" " ${ LOOPDEV1 } p3 " " ${ LOOPDEV2 } p3 "
mkdir -p " ${ IMAGE_DIR } /root "
mount -t ext4 /dev/md/raid-root " ${ IMAGE_DIR } /root "
mkdir -p " ${ IMAGE_DIR } /root/efi "
mount -t vfat /dev/md/raid-esp " ${ IMAGE_DIR } /root/efi "
mkdir -p " ${ IMAGE_DIR } /root/boot "
mount -t btrfs " ${ LOOPDEV1 } p3 " " ${ IMAGE_DIR } /root/boot "
mkdir -p " ${ IMAGE_DIR } /root/etc "
mkdir -p " ${ IMAGE_DIR } /root/usr/lib "
if [ [ -f /usr/lib/os-release ] ] ; then
cp /usr/lib/os-release " ${ IMAGE_DIR } /root/usr/lib/. "
ln -s ../usr/lib/os-release " ${ IMAGE_DIR } /root/etc/os-release "
else
cp -a /etc/os-release " ${ IMAGE_DIR } /root/etc/. "
fi
# find_esp() does not support md RAID partition.
( ! bootctl --root " ${ IMAGE_DIR } /root " --print-esp-path)
( ! bootctl --root " ${ IMAGE_DIR } /root " --print-esp-path --esp-path= /efi)
# If the verification is relaxed, it accepts md RAID partition.
assert_eq " $( SYSTEMD_RELAX_ESP_CHECKS = yes bootctl --root " ${ IMAGE_DIR } /root " --print-esp-path) " " ${ IMAGE_DIR } /root/efi "
assert_eq " $( SYSTEMD_RELAX_ESP_CHECKS = yes bootctl --root " ${ IMAGE_DIR } /root " --print-esp-path --esp-path= /efi) " " ${ IMAGE_DIR } /root/efi "
# find_xbootldr() does not support btrfs RAID, and bootctl tries to fall back to use ESP.
# (but as in the above, the ESP verification is also failed in this case).
( ! bootctl --root " ${ IMAGE_DIR } /root " --print-boot-path)
( ! bootctl --root " ${ IMAGE_DIR } /root " --print-boot-path --boot-path= /boot)
# If the verification for ESP is relaxed, bootctl falls back to use ESP.
assert_eq " $( SYSTEMD_RELAX_ESP_CHECKS = yes bootctl --root " ${ IMAGE_DIR } /root " --print-boot-path) " " ${ IMAGE_DIR } /root/efi "
# If the verification is relaxed, it accepts the xbootldr partition.
assert_eq " $( SYSTEMD_RELAX_XBOOTLDR_CHECKS = yes bootctl --root " ${ IMAGE_DIR } /root " --print-boot-path) " " ${ IMAGE_DIR } /root/boot "
assert_eq " $( SYSTEMD_RELAX_XBOOTLDR_CHECKS = yes bootctl --root " ${ IMAGE_DIR } /root " --print-boot-path --boot-path= /boot) " " ${ IMAGE_DIR } /root/boot "
# FIXME: This provides spurious result.
bootctl --root " ${ IMAGE_DIR } /root " --print-root-device || :
SYSTEMD_RELAX_ESP_CHECKS = yes SYSTEMD_RELAX_XBOOTLDR_CHECKS = yes basic_tests --root " ${ IMAGE_DIR } /root "
}
2024-02-12 19:30:31 +03:00
testcase_bootctl_varlink( ) {
2024-06-20 13:23:53 +03:00
varlinkctl call --collect /run/systemd/io.systemd.BootControl io.systemd.BootControl.ListBootEntries '{}' --graceful= io.systemd.BootControl.NoSuchBootEntry
2024-02-12 19:30:31 +03:00
2024-02-22 16:00:00 +03:00
# We may have UEFI in the test environment.
# If we don't have UEFI then we can test whether bootctl's varlink API fails cleanly.
# If we do have UEFI then the rest of the clean fail tests should be skipped.
if ! ( SYSTEMD_LOG_TARGET = console varlinkctl call --json= short /run/systemd/io.systemd.BootControl io.systemd.BootControl.GetRebootToFirmware '{}' || true ) | & grep -q io.systemd.BootControl.RebootToFirmwareNotSupported; then
return 0
fi
2024-06-20 13:23:53 +03:00
SYSTEMD_LOG_TARGET = console varlinkctl call --json= short /run/systemd/io.systemd.BootControl io.systemd.BootControl.SetRebootToFirmware '{"state":true}' --graceful= io.systemd.BootControl.RebootToFirmwareNotSupported
SYSTEMD_LOG_TARGET = console varlinkctl call --json= short /run/systemd/io.systemd.BootControl io.systemd.BootControl.SetRebootToFirmware '{"state":false}' --graceful= io.systemd.BootControl.RebootToFirmwareNotSupported
2024-02-12 19:30:31 +03:00
}
2023-12-05 17:18:17 +03:00
run_testcases