]> git.ipfire.org Git - thirdparty/systemd.git/blame - test/units/testsuite-74.bootctl.sh
TEST-74-AUX-UTILS: Support running on UEFI systems
[thirdparty/systemd.git] / test / units / testsuite-74.bootctl.sh
CommitLineData
ee07fff0
YW
1#!/usr/bin/env bash
2# SPDX-License-Identifier: LGPL-2.1-or-later
3set -eux
4set -o pipefail
5
6if systemd-detect-virt --quiet --container; then
7 echo "running on container, skipping."
8 exit 0
9fi
10
11if ! command -v bootctl >/dev/null; then
12 echo "bootctl not found, skipping."
13 exit 0
14fi
15
26fff16b
FB
16if [[ ! -d /usr/lib/systemd/boot/efi ]]; then
17 echo "sd-boot is not installed, skipping."
18 exit 0
19fi
20
ee07fff0
YW
21# shellcheck source=test/units/util.sh
22. "$(dirname "$0")"/util.sh
23
24# shellcheck source=test/units/test-control.sh
25. "$(dirname "$0")"/test-control.sh
26
27basic_tests() {
28 bootctl "$@" --help
29 bootctl "$@" --version
30
31 bootctl "$@" install --make-entry-directory=yes
32 bootctl "$@" remove --make-entry-directory=yes
33
34 bootctl "$@" install --all-architectures
35 bootctl "$@" remove --all-architectures
36
37 bootctl "$@" install --make-entry-directory=yes --all-architectures
38 bootctl "$@" remove --make-entry-directory=yes --all-architectures
39
40 bootctl "$@" install
41 (! bootctl "$@" update)
42 bootctl "$@" update --graceful
43
44 bootctl "$@" is-installed
45 bootctl "$@" is-installed --graceful
46 bootctl "$@" random-seed
47
48 bootctl "$@"
49 bootctl "$@" status
50 bootctl "$@" status --quiet
51 bootctl "$@" list
52 bootctl "$@" list --quiet
53 bootctl "$@" list --json=short
54 bootctl "$@" list --json=pretty
55
56 bootctl "$@" remove
57 (! bootctl "$@" is-installed)
58 (! bootctl "$@" is-installed --graceful)
59}
60
61testcase_bootctl_basic() {
8c9d241c
RM
62 assert_in "$(bootctl --print-esp-path)" "^(/boot/|/efi)$"
63 assert_in "$(bootctl --print-boot-path)" "^(/boot/|/efi)$"
ee07fff0
YW
64 bootctl --print-root-device
65
66 basic_tests
67}
68
69cleanup_image() (
70 set +e
71
72 if [[ -z "${IMAGE_DIR:-}" ]]; then
73 return 0
74 fi
75
76 umount "${IMAGE_DIR}/root"
77
78 if [[ -n "${LOOPDEV:-}" ]]; then
79 losetup -d "${LOOPDEV}"
80 unset LOOPDEV
81 fi
82
83 udevadm settle
84
85 rm -rf "${IMAGE_DIR}"
86 unset IMAGE_DIR
87
88 return 0
89)
90
91testcase_bootctl_image() {
92 IMAGE_DIR="$(mktemp --directory /tmp/test-bootctl.XXXXXXXXXX)"
93 trap cleanup_image RETURN
94
95 truncate -s 256m "${IMAGE_DIR}/image"
96
97 cat >"${IMAGE_DIR}/partscript" <<EOF
98label: gpt
99type=C12A7328-F81F-11D2-BA4B-00A0C93EC93B name=esp size=64M
100type=0FC63DAF-8483-4772-8E79-3D69D8477DE4 name=root size=64M bootable
101type=BC13C2FF-59E6-4262-A352-B275FD6F7172 name=boot
102EOF
103
104 LOOPDEV="$(losetup --show -P -f "${IMAGE_DIR}/image")"
105 sfdisk "$LOOPDEV" <"${IMAGE_DIR}/partscript"
106
107 udevadm settle
108
109 mkfs.vfat -n esp "${LOOPDEV}p1"
110 mkfs.ext4 -L root "${LOOPDEV}p2"
111 mkfs.ext4 -L boot "${LOOPDEV}p3"
112
113 mkdir -p "${IMAGE_DIR}/root"
114 mount -t ext4 "${LOOPDEV}p2" "${IMAGE_DIR}/root"
115
116 mkdir -p "${IMAGE_DIR}/root/efi"
117 mkdir -p "${IMAGE_DIR}/root/boot"
118 mkdir -p "${IMAGE_DIR}/root/etc"
119 mkdir -p "${IMAGE_DIR}/root/usr/lib"
120 if [[ -f /usr/lib/os-release ]]; then
121 cp /usr/lib/os-release "${IMAGE_DIR}/root/usr/lib/."
122 ln -s ../usr/lib/os-release "${IMAGE_DIR}/root/etc/os-release"
123 else
124 cp -a /etc/os-release "${IMAGE_DIR}/root/etc/."
125 fi
126
127 umount "${IMAGE_DIR}/root"
128
129 assert_eq "$(bootctl --image "${IMAGE_DIR}/image" --print-esp-path)" "/run/systemd/mount-rootfs/efi"
130 assert_eq "$(bootctl --image "${IMAGE_DIR}/image" --print-esp-path --esp-path=/efi)" "/run/systemd/mount-rootfs/efi"
131 assert_eq "$(bootctl --image "${IMAGE_DIR}/image" --print-boot-path)" "/run/systemd/mount-rootfs/boot"
132 assert_eq "$(bootctl --image "${IMAGE_DIR}/image" --print-boot-path --boot-path=/boot)" "/run/systemd/mount-rootfs/boot"
133
134 # FIXME: This provides spurious result.
135 bootctl --image "${IMAGE_DIR}/image" --print-root-device || :
136
137 basic_tests --image "${IMAGE_DIR}/image"
138}
139
140cleanup_raid() (
141 set +e
142
143 if [[ -z "${IMAGE_DIR:-}" ]]; then
144 return 0
145 fi
146
147 systemd-umount "${IMAGE_DIR}/root/efi"
148 systemd-umount "${IMAGE_DIR}/root/boot"
149 systemd-umount "${IMAGE_DIR}/root"
150
151 mdadm --misc --stop /dev/md/raid-esp
152 mdadm --misc --stop /dev/md/raid-root
153
154 if [[ -n "${LOOPDEV1:-}" ]]; then
155 mdadm --misc --force --zero-superblock "${LOOPDEV1}p1"
156 mdadm --misc --force --zero-superblock "${LOOPDEV1}p2"
157 fi
158
159 if [[ -n "${LOOPDEV2:-}" ]]; then
160 mdadm --misc --force --zero-superblock "${LOOPDEV2}p1"
161 mdadm --misc --force --zero-superblock "${LOOPDEV2}p2"
162 fi
163
164 udevadm settle
165
166 if [[ -n "${LOOPDEV1:-}" ]]; then
167 mdadm --misc --force --zero-superblock "${LOOPDEV1}p1"
168 mdadm --misc --force --zero-superblock "${LOOPDEV1}p2"
169 losetup -d "${LOOPDEV1}"
170 unset LOOPDEV1
171 fi
172
173 if [[ -n "${LOOPDEV2:-}" ]]; then
174 mdadm --misc --force --zero-superblock "${LOOPDEV2}p1"
175 mdadm --misc --force --zero-superblock "${LOOPDEV2}p2"
176 losetup -d "${LOOPDEV2}"
177 unset LOOPDEV2
178 fi
179
180 udevadm settle
181
182 rm -rf "${IMAGE_DIR}"
183
184 return 0
185)
186
187testcase_bootctl_raid() {
188 if ! command -v mdadm >/dev/null; then
189 echo "mdadm not found, skipping."
190 return 0
191 fi
192
193 if ! command -v mkfs.btrfs >/dev/null; then
194 echo "mkfs.btrfs not found, skipping."
195 return 0
196 fi
197
198 IMAGE_DIR="$(mktemp --directory /tmp/test-bootctl.XXXXXXXXXX)"
199 trap cleanup_raid RETURN
200
201 truncate -s 256m "${IMAGE_DIR}/image1"
202 truncate -s 256m "${IMAGE_DIR}/image2"
203
204 cat >"${IMAGE_DIR}/partscript" <<EOF
205label: gpt
206type=C12A7328-F81F-11D2-BA4B-00A0C93EC93B name=esp size=64M
207type=0FC63DAF-8483-4772-8E79-3D69D8477DE4 name=root size=64M bootable
208type=BC13C2FF-59E6-4262-A352-B275FD6F7172 name=boot
209EOF
210
211 LOOPDEV1="$(losetup --show -P -f "${IMAGE_DIR}/image1")"
212 LOOPDEV2="$(losetup --show -P -f "${IMAGE_DIR}/image2")"
213 sfdisk "$LOOPDEV1" <"${IMAGE_DIR}/partscript"
214 sfdisk "$LOOPDEV2" <"${IMAGE_DIR}/partscript"
215
216 udevadm settle
217
218 echo y | mdadm --create /dev/md/raid-esp --name "raid-esp" "${LOOPDEV1}p1" "${LOOPDEV2}p1" -v -f --level=1 --raid-devices=2
219 mkfs.vfat /dev/md/raid-esp
220 echo y | mdadm --create /dev/md/raid-root --name "raid-root" "${LOOPDEV1}p2" "${LOOPDEV2}p2" -v -f --level=1 --raid-devices=2
221 mkfs.ext4 /dev/md/raid-root
222 mkfs.btrfs -f -M -d raid1 -m raid1 -L "raid-boot" "${LOOPDEV1}p3" "${LOOPDEV2}p3"
223
224 mkdir -p "${IMAGE_DIR}/root"
225 mount -t ext4 /dev/md/raid-root "${IMAGE_DIR}/root"
226 mkdir -p "${IMAGE_DIR}/root/efi"
227 mount -t vfat /dev/md/raid-esp "${IMAGE_DIR}/root/efi"
228 mkdir -p "${IMAGE_DIR}/root/boot"
229 mount -t btrfs "${LOOPDEV1}p3" "${IMAGE_DIR}/root/boot"
230
231 mkdir -p "${IMAGE_DIR}/root/etc"
232 mkdir -p "${IMAGE_DIR}/root/usr/lib"
233 if [[ -f /usr/lib/os-release ]]; then
234 cp /usr/lib/os-release "${IMAGE_DIR}/root/usr/lib/."
235 ln -s ../usr/lib/os-release "${IMAGE_DIR}/root/etc/os-release"
236 else
237 cp -a /etc/os-release "${IMAGE_DIR}/root/etc/."
238 fi
239
240 # find_esp() does not support md RAID partition.
241 (! bootctl --root "${IMAGE_DIR}/root" --print-esp-path)
242 (! bootctl --root "${IMAGE_DIR}/root" --print-esp-path --esp-path=/efi)
243
244 # If the verification is relaxed, it accepts md RAID partition.
245 assert_eq "$(SYSTEMD_RELAX_ESP_CHECKS=yes bootctl --root "${IMAGE_DIR}/root" --print-esp-path)" "${IMAGE_DIR}/root/efi"
246 assert_eq "$(SYSTEMD_RELAX_ESP_CHECKS=yes bootctl --root "${IMAGE_DIR}/root" --print-esp-path --esp-path=/efi)" "${IMAGE_DIR}/root/efi"
247
248 # find_xbootldr() does not support btrfs RAID, and bootctl tries to fall back to use ESP.
249 # (but as in the above, the ESP verification is also failed in this case).
250 (! bootctl --root "${IMAGE_DIR}/root" --print-boot-path)
251 (! bootctl --root "${IMAGE_DIR}/root" --print-boot-path --boot-path=/boot)
252
253 # If the verification for ESP is relaxed, bootctl falls back to use ESP.
254 assert_eq "$(SYSTEMD_RELAX_ESP_CHECKS=yes bootctl --root "${IMAGE_DIR}/root" --print-boot-path)" "${IMAGE_DIR}/root/efi"
255
256 # If the verification is relaxed, it accepts the xbootldr partition.
257 assert_eq "$(SYSTEMD_RELAX_XBOOTLDR_CHECKS=yes bootctl --root "${IMAGE_DIR}/root" --print-boot-path)" "${IMAGE_DIR}/root/boot"
258 assert_eq "$(SYSTEMD_RELAX_XBOOTLDR_CHECKS=yes bootctl --root "${IMAGE_DIR}/root" --print-boot-path --boot-path=/boot)" "${IMAGE_DIR}/root/boot"
259
260 # FIXME: This provides spurious result.
261 bootctl --root "${IMAGE_DIR}/root" --print-root-device || :
262
263 SYSTEMD_RELAX_ESP_CHECKS=yes SYSTEMD_RELAX_XBOOTLDR_CHECKS=yes basic_tests --root "${IMAGE_DIR}/root"
264}
265
79ec3995
LP
266testcase_bootctl_varlink() {
267 varlinkctl call --collect /run/systemd/io.systemd.BootControl io.systemd.BootControl.ListBootEntries '{}'
268
8c9d241c
RM
269 # We may have UEFI in the test environment.
270 # If we don't have UEFI then we can test whether bootctl's varlink API fails cleanly.
271 # If we do have UEFI then the rest of the clean fail tests should be skipped.
272 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
273 return 0
274 fi
275 (SYSTEMD_LOG_TARGET=console varlinkctl call --json=short /run/systemd/io.systemd.BootControl io.systemd.BootControl.SetRebootToFirmware '{"state":true}' || true) |& grep -q io.systemd.BootControl.RebootToFirmwareNotSupported
276 (SYSTEMD_LOG_TARGET=console varlinkctl call --json=short /run/systemd/io.systemd.BootControl io.systemd.BootControl.SetRebootToFirmware '{"state":false}' || true) |& grep -q io.systemd.BootControl.RebootToFirmwareNotSupported
79ec3995
LP
277}
278
ee07fff0 279run_testcases