diff options
-rw-r--r-- | src/shared/find-esp.c | 82 | ||||
-rwxr-xr-x | test/TEST-24-CRYPTSETUP/test.sh | 6 | ||||
-rwxr-xr-x | test/TEST-64-UDEV-STORAGE/test.sh | 4 | ||||
-rwxr-xr-x | test/TEST-74-AUX-UTILS/test.sh | 6 | ||||
-rw-r--r-- | test/test-functions | 46 | ||||
-rwxr-xr-x | test/units/testsuite-64.sh | 4 | ||||
-rwxr-xr-x | test/units/testsuite-74.bootctl.sh | 261 |
7 files changed, 358 insertions, 51 deletions
diff --git a/src/shared/find-esp.c b/src/shared/find-esp.c index 9b8c7f73bc..bbfd3b175f 100644 --- a/src/shared/find-esp.c +++ b/src/shared/find-esp.c @@ -27,9 +27,29 @@ typedef enum VerifyESPFlags { VERIFY_ESP_SEARCHING = 1 << 0, /* Downgrade various "not found" logs to debug level */ VERIFY_ESP_UNPRIVILEGED_MODE = 1 << 1, /* Call into udev rather than blkid */ - VERIFY_ESP_RELAX_CHECKS = 1 << 2, /* Do not validate ESP partition */ + VERIFY_ESP_SKIP_FSTYPE_CHECK = 1 << 2, /* Skip filesystem check */ + VERIFY_ESP_SKIP_DEVICE_CHECK = 1 << 3, /* Skip device node check */ } VerifyESPFlags; +static VerifyESPFlags verify_esp_flags_init(int unprivileged_mode, const char *env_name_for_relaxing) { + VerifyESPFlags flags = 0; + + assert(env_name_for_relaxing); + + if (unprivileged_mode < 0) + unprivileged_mode = geteuid() != 0; + if (unprivileged_mode) + flags |= VERIFY_ESP_UNPRIVILEGED_MODE; + + if (getenv_bool(env_name_for_relaxing) > 0) + flags |= VERIFY_ESP_SKIP_FSTYPE_CHECK | VERIFY_ESP_SKIP_DEVICE_CHECK; + + if (detect_container() > 0) + flags |= VERIFY_ESP_SKIP_DEVICE_CHECK; + + return flags; +} + static int verify_esp_blkid( dev_t devid, VerifyESPFlags flags, @@ -326,8 +346,8 @@ static int verify_esp( dev_t *ret_devid, VerifyESPFlags flags) { - bool relax_checks, searching = FLAGS_SET(flags, VERIFY_ESP_SEARCHING), - unprivileged_mode = FLAGS_SET(flags, VERIFY_ESP_UNPRIVILEGED_MODE); + bool searching = FLAGS_SET(flags, VERIFY_ESP_SEARCHING), + unprivileged_mode = FLAGS_SET(flags, VERIFY_ESP_UNPRIVILEGED_MODE); _cleanup_free_ char *p = NULL; _cleanup_close_ int pfd = -EBADF; dev_t devid = 0; @@ -343,10 +363,6 @@ static int verify_esp( * -EACESS → if 'unprivileged_mode' is set, and we have trouble accessing the thing */ - relax_checks = - getenv_bool("SYSTEMD_RELAX_ESP_CHECKS") > 0 || - FLAGS_SET(flags, VERIFY_ESP_RELAX_CHECKS); - /* Non-root user can only check the status, so if an error occurred in the following, it does not cause any * issues. Let's also, silence the error messages. */ @@ -356,7 +372,7 @@ static int verify_esp( (unprivileged_mode && ERRNO_IS_PRIVILEGE(r)) ? LOG_DEBUG : LOG_ERR, r, "Failed to open parent directory of \"%s\": %m", path); - if (!relax_checks) { + if (!FLAGS_SET(flags, VERIFY_ESP_SKIP_FSTYPE_CHECK)) { _cleanup_free_ char *f = NULL; struct statfs sfs; @@ -383,19 +399,20 @@ static int verify_esp( "File system \"%s\" is not a FAT EFI System Partition (ESP) file system.", p); } - relax_checks = - relax_checks || - detect_container() > 0; - - r = verify_fsroot_dir(pfd, p, flags, relax_checks ? NULL : &devid); + r = verify_fsroot_dir(pfd, p, flags, FLAGS_SET(flags, VERIFY_ESP_SKIP_DEVICE_CHECK) ? NULL : &devid); if (r < 0) return r; /* In a container we don't have access to block devices, skip this part of the verification, we trust * the container manager set everything up correctly on its own. */ - if (relax_checks) + if (FLAGS_SET(flags, VERIFY_ESP_SKIP_DEVICE_CHECK)) goto finish; + if (devnum_is_zero(devid)) + return log_full_errno(searching ? LOG_DEBUG : LOG_ERR, + SYNTHETIC_ERRNO(searching ? EADDRNOTAVAIL : ENODEV), + "Could not determine backing block device of directory \"%s\" (btrfs RAID?).", p); + /* If we are unprivileged we ask udev for the metadata about the partition. If we are privileged we * use blkid instead. Why? Because this code is called from 'bootctl' which is pretty much an * emergency recovery tool that should also work when udev isn't up (i.e. from the emergency shell), @@ -454,15 +471,7 @@ int find_esp_and_warn_at( assert(rfd >= 0 || rfd == AT_FDCWD); - if (unprivileged_mode < 0) - unprivileged_mode = geteuid() != 0; - flags = unprivileged_mode > 0 ? VERIFY_ESP_UNPRIVILEGED_MODE : 0; - - r = dir_fd_is_root_or_cwd(rfd); - if (r < 0) - return log_error_errno(r, "Failed to check if directory file descriptor is root: %m"); - if (r == 0) - flags |= VERIFY_ESP_RELAX_CHECKS; + flags = verify_esp_flags_init(unprivileged_mode, "SYSTEMD_RELAX_ESP_CHECKS"); if (path) return verify_esp(rfd, path, ret_path, ret_part, ret_pstart, ret_psize, ret_uuid, ret_devid, flags); @@ -742,8 +751,7 @@ static int verify_xbootldr( _cleanup_free_ char *p = NULL; _cleanup_close_ int pfd = -EBADF; bool searching = FLAGS_SET(flags, VERIFY_ESP_SEARCHING), - unprivileged_mode = FLAGS_SET(flags, VERIFY_ESP_UNPRIVILEGED_MODE), - relax_checks; + unprivileged_mode = FLAGS_SET(flags, VERIFY_ESP_UNPRIVILEGED_MODE); dev_t devid = 0; int r; @@ -756,17 +764,22 @@ static int verify_xbootldr( (unprivileged_mode && ERRNO_IS_PRIVILEGE(r)) ? LOG_DEBUG : LOG_ERR, r, "Failed to open parent directory of \"%s\": %m", path); - relax_checks = - getenv_bool("SYSTEMD_RELAX_XBOOTLDR_CHECKS") > 0 || - detect_container() > 0; - - r = verify_fsroot_dir(pfd, p, flags, relax_checks ? NULL : &devid); + r = verify_fsroot_dir(pfd, p, flags, FLAGS_SET(flags, VERIFY_ESP_SKIP_DEVICE_CHECK) ? NULL : &devid); if (r < 0) return r; - if (relax_checks) + if (FLAGS_SET(flags, VERIFY_ESP_SKIP_DEVICE_CHECK)) goto finish; + if (devnum_is_zero(devid)) + return log_full_errno(searching ? LOG_DEBUG : LOG_ERR, + SYNTHETIC_ERRNO(searching ? EADDRNOTAVAIL : ENODEV), + "Could not determine backing block device of directory \"%s\" (btrfs RAID?).%s", + p, + searching ? "" : + "\nHint: set $SYSTEMD_RELAX_XBOOTLDR_CHECKS=yes environment variable " + "to bypass this and further verifications for the directory."); + if (unprivileged_mode) r = verify_xbootldr_udev(devid, flags, ret_uuid); else @@ -800,17 +813,14 @@ int find_xbootldr_and_warn_at( sd_id128_t *ret_uuid, dev_t *ret_devid) { - VerifyESPFlags flags = 0; + VerifyESPFlags flags; int r; /* Similar to find_esp_and_warn(), but finds the XBOOTLDR partition. Returns the same errors. */ assert(rfd >= 0 || rfd == AT_FDCWD); - if (unprivileged_mode < 0) - unprivileged_mode = geteuid() != 0; - if (unprivileged_mode) - flags |= VERIFY_ESP_UNPRIVILEGED_MODE; + flags = verify_esp_flags_init(unprivileged_mode, "SYSTEMD_RELAX_XBOOTLDR_CHECKS"); if (path) return verify_xbootldr(rfd, path, flags, ret_path, ret_uuid, ret_devid); diff --git a/test/TEST-24-CRYPTSETUP/test.sh b/test/TEST-24-CRYPTSETUP/test.sh index d0ec63d870..eace3f23c0 100755 --- a/test/TEST-24-CRYPTSETUP/test.sh +++ b/test/TEST-24-CRYPTSETUP/test.sh @@ -27,7 +27,7 @@ check_result_qemu() { mount_initdir - cryptsetup luksOpen "${LOOPDEV:?}p2" "${DM_NAME:?}" <"$TESTDIR/keyfile" + cryptsetup luksOpen "${LOOPDEV:?}p4" "${DM_NAME:?}" <"$TESTDIR/keyfile" mount "/dev/mapper/$DM_NAME" "$initdir/var" check_result_common "${initdir:?}" && ret=0 || ret=$? @@ -43,8 +43,8 @@ test_create_image() { create_empty_image_rootdir echo -n test >"${TESTDIR:?}/keyfile" - cryptsetup -q luksFormat --uuid="$PART_UUID" --pbkdf pbkdf2 --pbkdf-force-iterations 1000 "${LOOPDEV:?}p2" "$TESTDIR/keyfile" - cryptsetup luksOpen "${LOOPDEV}p2" "${DM_NAME:?}" <"$TESTDIR/keyfile" + cryptsetup -q luksFormat --uuid="$PART_UUID" --pbkdf pbkdf2 --pbkdf-force-iterations 1000 "${LOOPDEV:?}p4" "$TESTDIR/keyfile" + cryptsetup luksOpen "${LOOPDEV}p4" "${DM_NAME:?}" <"$TESTDIR/keyfile" mkfs.ext4 -L var "/dev/mapper/$DM_NAME" mkdir -p "${initdir:?}/var" mount "/dev/mapper/$DM_NAME" "$initdir/var" diff --git a/test/TEST-64-UDEV-STORAGE/test.sh b/test/TEST-64-UDEV-STORAGE/test.sh index d41a4f00f9..b9e7bdf18a 100755 --- a/test/TEST-64-UDEV-STORAGE/test.sh +++ b/test/TEST-64-UDEV-STORAGE/test.sh @@ -24,7 +24,7 @@ _host_has_feature() {( case "${1:?}" in btrfs) - modprobe -nv btrfs && command -v mkfs.btrfs && command -v btrfs || return $? + host_has_btrfs ;; iscsi) # Client/initiator (Open-iSCSI) @@ -36,7 +36,7 @@ _host_has_feature() {( command -v lvm || return $? ;; mdadm) - command -v mdadm || return $? + host_has_mdadm ;; multipath) command -v multipath && command -v multipathd || return $? diff --git a/test/TEST-74-AUX-UTILS/test.sh b/test/TEST-74-AUX-UTILS/test.sh index f033ec469f..7940600612 100755 --- a/test/TEST-74-AUX-UTILS/test.sh +++ b/test/TEST-74-AUX-UTILS/test.sh @@ -16,6 +16,12 @@ test_append_files() { # the QEMU test, as nspawn refuses the invalid machine ID with -EUCLEAN printf "556f48e837bc4424a710fa2e2c9d3e3c\ne3d\n" >"$workspace/etc/machine-id" fi + + if host_has_btrfs && host_has_mdadm; then + install_btrfs + install_mdadm + generate_module_dependencies + fi } do_test "$@" diff --git a/test/test-functions b/test/test-functions index f887346b34..5af7b8cd91 100644 --- a/test/test-functions +++ b/test/test-functions @@ -1198,6 +1198,11 @@ install_lvm() { mkdir -p "${initdir:?}/etc/lvm" } +host_has_btrfs() ( + set -e + modprobe -nv btrfs && command -v mkfs.btrfs && command -v btrfs || return $? +) + install_btrfs() { instmods btrfs # Not all utilities provided by btrfs-progs are listed here; extend the list @@ -1265,6 +1270,11 @@ install_iscsi() { fi } +host_has_mdadm() ( + set -e + command -v mdadm || return $? +) + install_mdadm() { local unit local mdadm_units=( @@ -1278,6 +1288,7 @@ install_mdadm() { system-shutdown/mdadm.shutdown ) + instmods "=md" image_install mdadm mdmon inst_rules 01-md-raid-creating.rules 63-md-raid-arrays.rules 64-md-raid-assembly.rules 69-md-clustered-confirm-device.rules # Fedora/CentOS/RHEL ships this rule file @@ -1286,6 +1297,10 @@ install_mdadm() { for unit in "${mdadm_units[@]}"; do image_install "${ROOTLIBDIR:?}/$unit" done + + # Disable the mdmonitor service, since it fails if there's no valid email address + # configured in /etc/mdadm.conf, which just unnecessarily pollutes the logs + "${SYSTEMCTL:?}" mask --root "${initdir:?}" mdmonitor.service || : } install_compiled_systemd() { @@ -1597,6 +1612,9 @@ create_empty_image() { # Partition sizes are in MiBs local root_size=768 local data_size=100 + local esp_size=128 + local boot_size=128 + local total= if ! get_bool "$NO_BUILD"; then if meson configure "${BUILD_DIR:?}" | grep 'static-lib\|standalone-binaries' | awk '{ print $2 }' | grep -q 'true'; then root_size=$((root_size + 200)) @@ -1619,28 +1637,44 @@ create_empty_image() { data_size=$((data_size + IMAGE_ADDITIONAL_DATA_SIZE)) fi - echo "Setting up ${IMAGE_PUBLIC:?} (${root_size} MB)" + total=$((root_size + data_size + esp_size + boot_size)) + + echo "Setting up ${IMAGE_PUBLIC:?} (${total} MB)" rm -f "${IMAGE_PRIVATE:?}" "$IMAGE_PUBLIC" # Create the blank file to use as a root filesystem - truncate -s "${root_size}M" "$IMAGE_PUBLIC" + truncate -s "${total}M" "$IMAGE_PUBLIC" LOOPDEV="$(losetup --show -P -f "$IMAGE_PUBLIC")" [[ -b "$LOOPDEV" ]] || return 1 # Create two partitions - a root one and a data one (utilized by some tests) sfdisk "$LOOPDEV" <<EOF label: gpt -type=0FC63DAF-8483-4772-8E79-3D69D8477DE4 name=root size=$((root_size - data_size))M bootable +type=C12A7328-F81F-11D2-BA4B-00A0C93EC93B name=esp size=${esp_size}M +type=0FC63DAF-8483-4772-8E79-3D69D8477DE4 name=root size=${root_size}M bootable +type=BC13C2FF-59E6-4262-A352-B275FD6F7172 name=boot size=${boot_size}M type=0FC63DAF-8483-4772-8E79-3D69D8477DE4 name=data EOF udevadm settle + if ! mkfs -t vfat "${LOOPDEV}p1"; then + dfatal "Failed to mkfs -t vfat ${LOOPDEV}p1" + exit 1 + fi + local label=(-L systemd_boot) # mkfs.reiserfs doesn't know -L. so, use --label instead [[ "$FSTYPE" == "reiserfs" ]] && label=(--label systemd_boot) - if ! mkfs -t "${FSTYPE}" "${label[@]}" "${LOOPDEV}p1" -q; then - dfatal "Failed to mkfs -t ${FSTYPE}" + if ! mkfs -t "${FSTYPE}" "${label[@]}" "${LOOPDEV}p2" -q; then + dfatal "Failed to mkfs -t ${FSTYPE} ${label[*]} ${LOOPDEV}p2 -q" + exit 1 + fi + + local label=(-L xbootldr) + [[ "$FSTYPE" == "reiserfs" ]] && label=(--label xbootldr) + if ! mkfs -t "${FSTYPE}" "${label[@]}" "${LOOPDEV}p3" -q; then + dfatal "Failed to mkfs -t ${FSTYPE} ${label[*]} ${LOOPDEV}p3 -q" exit 1 fi } @@ -1656,7 +1690,7 @@ mount_initdir() { if ! mountpoint -q "${initdir:?}"; then mkdir -p "$initdir" - mount "${LOOPDEV}p1" "$initdir" + mount "${LOOPDEV}p2" "$initdir" TEST_SETUP_CLEANUP_ROOTDIR=1 fi } diff --git a/test/units/testsuite-64.sh b/test/units/testsuite-64.sh index 0e598cc6b3..81edb0ab7a 100755 --- a/test/units/testsuite-64.sh +++ b/test/units/testsuite-64.sh @@ -1159,10 +1159,6 @@ testcase_mdadm_lvm() { helper_check_device_units } -# Disable the mdmonitor service, since it fails if there's no valid email address -# configured in /etc/mdadm.conf, which just unnecessarily pollutes the logs -systemctl list-unit-files mdmonitor.service >/dev/null && systemctl mask --runtime mdmonitor.service - udevadm settle udevadm control --log-level debug lsblk -a diff --git a/test/units/testsuite-74.bootctl.sh b/test/units/testsuite-74.bootctl.sh new file mode 100755 index 0000000000..61373b506e --- /dev/null +++ b/test/units/testsuite-74.bootctl.sh @@ -0,0 +1,261 @@ +#!/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 + +# 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() { + assert_eq "$(bootctl --print-esp-path)" "/efi" + assert_eq "$(bootctl --print-boot-path)" "/boot" + 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" +} + +run_testcases |