feat: vmtest.sh: the boot loader test for every loader the ISO advertises

One VM per loader, Steam Machine (--fremont): Steamify's state as its menu sees it,
OS name untouched, loader identity, the DKMS modules for every kernel, Steamify's
loader-specific code (hdmi_remove_boot_param), a kernel update, and a reboot into
each of the two kernels. Headless by default with a log Konsole (--window shows
the VMs). Fails when an advertised loader has no test. Limine 41, systemd-boot 40,
GRUB 40 checks pass.
This commit is contained in:
theupriser committed 2026-09-29 11:23:50 +02:00
1 parent 8ea75424b0
commit ed12ecb57d
8 files changed
+271

No files matched your search

+9
View File
@@ -0,0 +1,9 @@
#!/bin/bash
# Guest side: after a reboot, the running kernel has Steamify's modules.
pass() { echo "PASS $*"; }; fail() { echo "FAIL $*"; }
k=$(uname -r)
echo "kernel: $k"; echo "cmdline: $(cut -c1-140 /proc/cmdline)"
compgen -G "/usr/lib/modules/$k/updates/dkms/steamify-fremont-poweroff.ko*" >/dev/null && pass "power-off fix built for the running kernel" || fail "no power-off fix for $k"
sudo dmesg | grep -q "steamify_fremont_poweroff" && pass "power-off fix loaded at boot" || fail "power-off fix not loaded"
lsmod | grep -q '^leds_valve' && pass "leds_valve loaded" || fail "leds_valve not loaded"
[[ -z "$(systemctl --failed --no-legend)" ]] && pass "no failed units" || { fail "failed units:"; systemctl --failed --no-legend; }
+28
View File
@@ -0,0 +1,28 @@
#!/bin/bash
# Guest side: reinstall both kernels + headers (what an update does: the
# DKMS hook rebuilds the modules, mkinitcpio and the boot loader's hook run).
pass() { echo "PASS $*"; }; fail() { echo "FAIL $*"; }
start=$(date +%s)
sudo pacman -S --noconfirm linux-cachyos linux-cachyos-lts linux-cachyos-headers linux-cachyos-lts-headers > /tmp/kernel-update.log 2>&1
rc=$?
sed 's/\x1b\[[0-9;]*m//g' /tmp/kernel-update.log | grep -E "^==> dkms|Building image|Generating grub|sdboot|limine|error" | cut -c1-140
[[ $rc -eq 0 ]] && pass "pacman kernel reinstall exit 0" || fail "pacman exit $rc"
for k in $(ls /usr/lib/modules); do
for m in cros-ec-cec leds-valve steamify-fremont-poweroff; do
compgen -G "/usr/lib/modules/$k/updates/dkms/$m.ko*" >/dev/null || fail "$m not rebuilt for $k"
done
done
[[ $(dkms status | grep -c ': installed') -eq $((3 * $(ls /usr/lib/modules | wc -w))) ]] && pass "DKMS rebuilt 3 modules for each kernel" || fail "DKMS status after the update"
# The images: /boot/initramfs-*.img (GRUB, systemd-boot); Limine keeps them per kernel
# under /boot/<machine-id>/<kernel>/initramfs (limine-mkinitcpio) and rewrites limine.conf.
if [[ "$LOADER" == limine ]]; then
# limine-entry-tool copies an image only when its content changed (same version = untouched):
# the hook ran when both images were built and limine.conf was regenerated.
n=$(sed 's/\x1b\[[0-9;]*m//g' /tmp/kernel-update.log | grep -c 'Creating zstd-compressed initcpio image')
[[ $n -ge 2 ]] && pass "Limine's hook built the initramfs for both kernels" || fail "Limine's hook built $n initramfs image(s)"
[[ $(sudo stat -c %Y /boot/limine.conf) -ge $start ]] && pass "limine.conf regenerated" || fail "limine.conf not regenerated"
else
for img in /boot/initramfs-linux-cachyos.img /boot/initramfs-linux-cachyos-lts.img; do
[[ $(sudo stat -c %Y "$img") -ge $start ]] && pass "$(basename "$img") rebuilt" || fail "$(basename "$img") not rebuilt"
done
fi
+28
View File
@@ -0,0 +1,28 @@
#!/bin/bash
# Guest side: Steamify's boot-loader-specific code, hdmi_remove_boot_param
# (older versions put drm.edid_firmware= on the kernel command line): seed
# the parameter where this loader keeps it, run the removal, and check that
# it's gone and the boot entries are rebuilt.
pass() { echo "PASS $*"; }; fail() { echo "FAIL $*"; }
sudo mountpoint -q /mnt || sudo mount -t 9p -o trans=virtio,version=9p2000.L repo /mnt
cd /mnt || exit 1
. lib/common.sh; . lib/state.sh; . lib/hdmi-refresh.sh
f="$(hdmi_boot_file)"
echo "boot file: ${f:-none}"
[[ -n "$f" ]] && pass "hdmi_boot_file finds the loader's file" || { fail "hdmi_boot_file finds nothing"; exit 0; }
p='drm.edid_firmware=DP-1:edid/steamify-test.bin'
case "$f" in
/etc/default/grub) sudo sed -i -E "s|^(GRUB_CMDLINE_LINUX_DEFAULT=\")|\1$p |" "$f" ;;
/etc/sdboot-manage.conf) if grep -q '^LINUX_OPTIONS=' "$f"; then sudo sed -i -E "s|^(LINUX_OPTIONS=\")|\1$p |" "$f"; else echo "LINUX_OPTIONS=\"$p\"" | sudo tee -a "$f" >/dev/null; fi ;;
/etc/default/limine) if grep -q '^KERNEL_CMDLINE\[default\]' "$f"; then sudo sed -i -E "s|^(KERNEL_CMDLINE\[default\]\+?=\")|\1$p |" "$f"; else echo "KERNEL_CMDLINE[default]+=\"$p\"" | sudo tee -a "$f" >/dev/null; fi ;;
esac
[[ -n "$(hdmi_cmdline_param)" ]] && pass "the seeded parameter is detected" || fail "seeded parameter not detected in $f"
hdmi_remove_boot_param > /tmp/legacy-param.log 2>&1; rc=$?
tail -3 /tmp/legacy-param.log | sed 's/\x1b\[[0-9;]*m//g' | cut -c1-120
[[ $rc -eq 0 ]] && pass "hdmi_remove_boot_param exit 0" || fail "hdmi_remove_boot_param exit $rc"
[[ -z "$(hdmi_cmdline_param)" ]] && pass "parameter removed from $f" || fail "parameter still in $f"
case "$f" in
/etc/default/grub) sudo grep -q edid /boot/grub/grub.cfg && fail "edid still in grub.cfg" || pass "no edid in grub.cfg"; [[ $(sudo grep -c '^\s*linux\s' /boot/grub/grub.cfg) -ge 1 ]] && pass "grub.cfg has linux entries" || fail "grub.cfg has no linux entries" ;;
/etc/sdboot-manage.conf) sudo sh -c 'grep -l edid /boot/loader/entries/* 2>/dev/null' | grep -q . && fail "edid still in the entries" || pass "no edid in the entries"; [[ $(sudo ls /boot/loader/entries | wc -l) -ge 1 ]] && pass "boot entries exist" || fail "no boot entries" ;;
/etc/default/limine) sudo grep -q edid /boot/limine.conf && fail "edid still in limine.conf" || pass "no edid in limine.conf"; sudo grep -q 'linux-cachyos' /boot/limine.conf && pass "limine.conf lists the kernels" || fail "limine.conf lists no kernel" ;;
esac
+15
View File
@@ -0,0 +1,15 @@
#!/bin/bash
# Guest side: Steamify's DKMS modules exist for every installed kernel.
# Prints PASS/FAIL lines (scripts/vmbootloadertest.sh counts the FAILs).
pass() { echo "PASS $*"; }; fail() { echo "FAIL $*"; }
kernels=$(ls /usr/lib/modules)
n=$(wc -w <<< "$kernels")
echo "kernels: $(tr '\n' ' ' <<< "$kernels")"
dkms status
[[ $(dkms status | grep -c ': installed') -eq $((3 * n)) ]] && pass "3 DKMS modules x $n kernels installed" || fail "dkms status is not 3 modules x $n kernels"
for k in $kernels; do
for m in cros-ec-cec leds-valve steamify-fremont-poweroff; do
compgen -G "/usr/lib/modules/$k/updates/dkms/$m.ko*" >/dev/null && pass "$m for $k" || fail "$m missing for $k"
done
done
[[ -f /etc/modules-load.d/steamify-fremont-poweroff.conf ]] && pass "modules-load.d has the power-off fix" || fail "no modules-load.d entry"
+27
View File
@@ -0,0 +1,27 @@
#!/bin/bash
# Guest side ($LOADER = limine|systemd-boot|grub): Steamify's state as its own
# menu detects it (the same *_status functions), the OS name untouched, and
# the boot loader as expected.
pass() { echo "PASS $*"; }; fail() { echo "FAIL $*"; }
sudo mountpoint -q /mnt || sudo mount -t 9p -o trans=virtio,version=9p2000.L repo /mnt
cd /mnt || exit 1
for lib in common state packages login-manager single-user steam-desktop steam-machine fremont-poweroff vram-booster hdmi-refresh cec boot-session vapor-theme steamos-extras bios desktop-shortcut wizard-shortcut steam-game update-notifier; do
# shellcheck source=/dev/null
. "lib/$lib.sh" 2>/dev/null
done
# Items this Steam Machine VM has on after `--options gaming,theme,glyphs,single,launcher,notify,cec,machine,poweroff`.
for item in gaming theme glyphs single launcher notify poweroff cec; do
if "${item}_status" 2>/dev/null; then pass "$item is on (the menu shows it ticked)"; else fail "$item is off"; fi
done
# Steamify never renames the OS (limine-snapper-sync / grub-btrfs read it).
grep -qx 'NAME="CachyOS Linux"' /etc/os-release && grep -qx 'PRETTY_NAME="CachyOS"' /etc/os-release && pass "os-release NAME and PRETTY_NAME are CachyOS's" || fail "os-release NAME/PRETTY_NAME changed"
grep -q 'with Steamify' /etc/lsb-release && fail "lsb-release still says 'with Steamify'" || pass "lsb-release name is CachyOS's"
# The boot loader is the one this VM was installed with.
case "$LOADER" in
limine) command -v limine-update >/dev/null && [[ -f /etc/default/limine ]] && pass "Limine is installed" || fail "no Limine"
grep -q '^TARGET_OS_NAME="CachyOS"' /etc/default/limine && pass "limine TARGET_OS_NAME is set" || fail "TARGET_OS_NAME missing in /etc/default/limine" ;;
systemd-boot) sudo bootctl status --no-pager 2>/dev/null | grep -q 'Product: systemd-boot' && pass "systemd-boot is the boot loader" || fail "not systemd-boot" ;;
grub) sudo bootctl status --no-pager 2>/dev/null | grep -q 'Product: GRUB' && pass "GRUB is the boot loader" || fail "not GRUB" ;;
esac
# "BIOS" menu item: rebooting into the firmware setup must be possible (never trigger it here).
sudo bootctl status --no-pager 2>/dev/null | grep -q 'Boot into FW: supported' && pass "reboot into firmware setup is supported" || fail "firmware setup reboot not supported"