From f604e10b3e9427d78eae94b4d4007ba1ce83a6c1 Mon Sep 17 00:00:00 2001 From: Rick Peters Date: Wed, 30 Sep 2026 10:12:35 +0200 Subject: [PATCH] feat: vmbootloadertest.sh --quick [--generic]: a Steam Machine gets all its items and modules, a plain PC none --- scripts/vmbootloadertest.sh | 24 +++++++++++++++--------- share/bootloader-test/boot-check.sh | 4 ++++ share/bootloader-test/modules.sh | 10 ++++++++++ share/bootloader-test/steamify-state.sh | 10 +++++++++- 4 files changed, 38 insertions(+), 10 deletions(-) diff --git a/scripts/vmbootloadertest.sh b/scripts/vmbootloadertest.sh index 561488d..375f8ff 100755 --- a/scripts/vmbootloadertest.sh +++ b/scripts/vmbootloadertest.sh @@ -5,10 +5,11 @@ # the old drm.edid_firmware parameter), a kernel update, and a reboot into # each of the two kernels. Guest checks: share/bootloader-test/*.sh. # All loaders in one go: scripts/vmtest.sh. -# scripts/vmbootloadertest.sh [--install] [--quick] [--window] +# scripts/vmbootloadertest.sh [--install] [--quick [--generic]] [--window] # --install first install the VM (scripts/vminstall.sh, from the Steamify ISO) # --quick only what the ISO's install must get right (B1-B5: boots through its own entry, OS name, loader, # Steamify's state and modules as the install left them): no steamify.sh run, kernel update or reboots +# --generic with --quick: a plain PC, not a Steam Machine (no --fremont): its Steam Machine items must stay off # --window show the VM's window (default: headless, with a Konsole on the log when there is a desktop) # Env: VM_DIR (default ~/vms/bl-), VM_ISO (default: the newest ISO in # ../steamify-cachyos-live-iso/out/desktop), REPO (steamify-cachyos, 9p `repo`). @@ -17,23 +18,28 @@ set -uo pipefail here="$(cd "$(dirname "$0")" && pwd)" repo="$(cd "$here/.." && pwd)" loader="${1:?usage: $0 [--install]}" -install=false; window=false; quick=false +install=false; window=false; quick=false; generic=false for a in "${@:2}"; do - case "$a" in --install) install=true ;; --quick) quick=true ;; --window) window=true ;; *) echo "Unknown argument: $a" >&2; exit 2 ;; esac + case "$a" in --install) install=true ;; --quick) quick=true ;; --generic) generic=true ;; --window) window=true ;; *) echo "Unknown argument: $a" >&2; exit 2 ;; esac done # No human is needed: headless (no VM window) unless --window. On a desktop a Konsole follows the log. $window || export VM_HEADLESS=1 case "$loader" in limine|systemd-boot|grub) ;; *) echo "Unknown boot loader: $loader" >&2; exit 2 ;; esac -export VM_DIR="${VM_DIR:-$HOME/vms/bl-$loader}" +$generic && ! $quick && { echo "--generic needs --quick" >&2; exit 2; } +hw=fremont; $generic && hw=generic +suffix=""; $generic && suffix="-generic" +export VM_DIR="${VM_DIR:-$HOME/vms/bl-$loader$suffix}" +hwflags=(--fremont); $generic && hwflags=() # Own ssh port per loader, so the loaders can run side by side (vmtest.sh). -case "$loader" in limine) export VM_PORT="${VM_PORT:-2401}" ;; systemd-boot) export VM_PORT="${VM_PORT:-2402}" ;; grub) export VM_PORT="${VM_PORT:-2403}" ;; esac +off=0; $generic && off=10 +case "$loader" in limine) export VM_PORT="${VM_PORT:-$((2401 + off))}" ;; systemd-boot) export VM_PORT="${VM_PORT:-$((2402 + off))}" ;; grub) export VM_PORT="${VM_PORT:-$((2403 + off))}" ;; esac . "$here/common.sh" guest="$repo/share/bootloader-test" log="$VM_DIR.test.log" step() { printf '\n##### %s %s\n' "$(date +%T)" "$*"; } gssh() { vm_ssh -o ConnectTimeout=6 -o LogLevel=ERROR "$@"; } -gscript() { gssh env "LOADER=$loader" bash -s < "$guest/$1"; } # the guest's login shell is fish +gscript() { gssh env "LOADER=$loader" "HARDWARE=$hw" bash -s < "$guest/$1"; } # the guest's login shell is fish waitssh() { local _; for _ in $(seq 60); do gssh 'uptime -p' 2>/dev/null | grep -q '^up' && return 0; sleep 5; done; echo "FAIL no SSH"; return 1; } running() { pgrep -f "[h]ostfwd=tcp::$VM_PORT-" >/dev/null; } stop_vm() { @@ -45,7 +51,7 @@ stop_vm() { pkill -f "[h]ostfwd=tcp::$VM_PORT-"; sleep 2 } export VM_CACHE="${VM_CACHE-$HOME/vms/pkg-cache}" # 9p tag `cache`: Steamify's downloads once for every VM -start_vm() { stop_vm; cp "$repo/run.sh" "$VM_DIR/run.sh"; (cd "$VM_DIR" && VM_MEM="${VM_MEM:-4G}" REPO="${REPO:-$repo/../steamify-cachyos}" setsid nohup ./run.sh --fremont > vm.log 2>&1 &); } +start_vm() { stop_vm; cp "$repo/run.sh" "$VM_DIR/run.sh"; (cd "$VM_DIR" && VM_MEM="${VM_MEM:-4G}" REPO="${REPO:-$repo/../steamify-cachyos}" setsid nohup ./run.sh "${hwflags[@]}" > vm.log 2>&1 &); } reboot_vm() { gssh 'sudo systemctl reboot' >/dev/null 2>&1; sleep 25; waitssh; } view_start # one shared Konsole (common.sh) # The guest checks print PASS/FAIL lines; the summary at the end counts them in the log. @@ -66,11 +72,11 @@ if $install; then fi # --quick checks what the ISO's install leaves on a Steam Machine: install on a VM that reports Fremont hardware # (a generic PC rightly gets no poweroff/CEC items and no DKMS modules). - fremont=(); $quick && fremont=(--fremont) + fremont=(); $quick && ! $generic && fremont=(--fremont) VM_BOOTLOADER="$loader" "$here/vminstall.sh" --iso "$iso" "${fremont[@]}" < /dev/null || exit 1 fi -step "start $loader as a Steam Machine" +step "start $loader as a $($generic && echo plain PC || echo Steam Machine)" start_vm; waitssh || exit 1 gssh 'sudo cat /sys/class/dmi/id/product_name' 2>/dev/null diff --git a/share/bootloader-test/boot-check.sh b/share/bootloader-test/boot-check.sh index 6bc448d..f7d7f0a 100755 --- a/share/bootloader-test/boot-check.sh +++ b/share/bootloader-test/boot-check.sh @@ -3,6 +3,9 @@ pass() { echo "PASS $*"; }; fail() { echo "FAIL $*"; } k=$(uname -r) echo "kernel: $k"; echo "cmdline: $(cut -c1-140 /proc/cmdline)" +if [[ "${HARDWARE:-fremont}" == generic ]]; then + lsmod | grep -qE "^(steamify_fremont_poweroff|leds_valve)" && fail "Steam Machine modules loaded on a plain PC" || pass "no Steam Machine modules loaded (not a Steam Machine)" +else 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" # Loaded (a real Steam Machine), or tried at boot and refused with "No such device" (the VM has no AMD GPIO # controller, so the module returns -ENODEV silently). The refusal is in the journal; it only sometimes @@ -12,6 +15,7 @@ elif sudo journalctl -b -q --no-pager -u systemd-modules-load | grep -q "steamif pass "power-off fix tried at boot (No such device: no AMD GPIO controller in the VM)" else fail "power-off fix not loaded, and not tried at boot"; fi lsmod | grep -q '^leds_valve' && pass "leds_valve loaded" || fail "leds_valve not loaded" +fi [[ -z "$(systemctl --failed --no-legend)" ]] && pass "no failed units" || { fail "failed units:"; systemctl --failed --no-legend; } # B1: booted through the loader's own EFI boot entry, not the firmware's automatic disk entry (the # fallback path \EFI\BOOT\BOOTX64.EFI) and not an entry without a partition (HD(0,GPT,0000...)). diff --git a/share/bootloader-test/modules.sh b/share/bootloader-test/modules.sh index 8b807b2..b805bc5 100755 --- a/share/bootloader-test/modules.sh +++ b/share/bootloader-test/modules.sh @@ -2,6 +2,16 @@ # 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 $*"; } +# HARDWARE=generic (a plain PC): none of Steamify's Steam Machine modules belong on it. +if [[ "${HARDWARE:-fremont}" == generic ]]; then + 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 is installed for $k, but this is not a Steam Machine" || pass "no $m for $k (not a Steam Machine)" + done + done + [[ -f /etc/modules-load.d/steamify-fremont-poweroff.conf ]] && fail "modules-load.d has the power-off fix on a plain PC" || pass "no modules-load.d entry (not a Steam Machine)" + exit 0 +fi kernels=$(ls /usr/lib/modules) n=$(wc -w <<< "$kernels") echo "kernels: $(tr '\n' ' ' <<< "$kernels")" diff --git a/share/bootloader-test/steamify-state.sh b/share/bootloader-test/steamify-state.sh index 8e87d3c..ae78253 100755 --- a/share/bootloader-test/steamify-state.sh +++ b/share/bootloader-test/steamify-state.sh @@ -10,9 +10,17 @@ for lib in common state packages login-manager single-user steam-desktop steam-m . "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 +# HARDWARE=generic (a plain PC): the Steam Machine items (poweroff, cec) must stay off. +for item in gaming theme glyphs single launcher notify; do if "${item}_status" 2>/dev/null; then pass "$item is on (the menu shows it ticked)"; else fail "$item is off"; fi done +for item in poweroff cec; do + if [[ "${HARDWARE:-fremont}" == generic ]]; then + if "${item}_status" 2>/dev/null; then fail "$item is on, but this is not a Steam Machine"; else pass "$item is off (not a Steam Machine)"; fi + else + if "${item}_status" 2>/dev/null; then pass "$item is on (the menu shows it ticked)"; else fail "$item is off"; fi + 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"