diff --git a/pkg/fedora/kernel-surface/files/linux-surface-default-watchdog.py b/pkg/fedora/kernel-surface/files/linux-surface-default-watchdog.py new file mode 100755 index 000000000..6b786bb07 --- /dev/null +++ b/pkg/fedora/kernel-surface/files/linux-surface-default-watchdog.py @@ -0,0 +1,87 @@ +#!/usr/bin/env python3 + +from __future__ import annotations + +import subprocess +import sys +from pathlib import Path +from typing import Any + + +def grub2_editenv(*args: Any, **kwargs: Any) -> str: + subprocess.run(["grub2-editenv", *args], check=True, **kwargs) + + +def main() -> int: + boot: Path = Path("/boot") + mid: Path = Path("/etc/machine-id") + + if not boot.exists(): + print("ERROR: /boot directory does not exist") + return 1 + + if not mid.exists(): + print("ERROR: /etc/machine-id does not exist") + return 1 + + blsdir: Path = boot / "loader" / "entries" + + if not blsdir.exists(): + print("ERROR: /boot/loader/entries does not exist") + return 1 + + try: + grub2_editenv("--help", capture_output=True) + except: + print("ERROR: grub2-editenv is not working") + return 1 + + # Get list of surface kernels sorted by timestamp. + # + # We use creation time here because it represents when the kernel was installed. + # Modification time can be a bit wonky and seems to correspond to the build date. + kernels: list[Path] = sorted( + boot.glob("vmlinuz-*.surface.*"), + key=lambda x: x.stat().st_ctime, + reverse=True, + ) + + if len(kernels) == 0: + print("ERROR: Failed to find a surface kernel") + return 1 + + # The saved_entry property from grubenv determines what kernel is booted by default. + # Its value is the filename of the BLS entry in /boot/loader/entries minus the file extension. + # + # The BLS files are named using a combination of the machine ID and the version string + # of the kernel that is being booted. Since we have the vmlinux, we can get the version + # from its name, and the machine ID from /etc/machine-id. + # + # This allows setting the default kernel without calling grubby or having to figure out + # which path GRUB will use to boot the kernel. + + kernel: Path = kernels[0] + + machineid: str = mid.read_text().strip() + version: str = kernel.name.lstrip("vmlinuz-") + + blscfg: Path = blsdir / "{}-{}.conf".format(machineid, version) + + # Make sure the config really exists + if not blscfg.exists(): + print("ERROR: {} does not exist".format(blscfg)) + return 1 + + print("Kernel: {}".format(kernel)) + print("BLS entry: {}".format(blscfg)) + + grub2_editenv("-", "set", "saved_entry={}".format(blscfg.stem)) + + # Update timestamp for rEFInd and ensure it is marked as latest across all kernels + kernel.touch(exist_ok=True) + + return 0 + + +if __name__ == "__main__": + sys.exit(main()) diff --git a/pkg/fedora/kernel-surface/files/linux-surface-default-watchdog.service b/pkg/fedora/kernel-surface/files/linux-surface-default-watchdog.service index 2c8e6c2a4..008b00ee0 100644 --- a/pkg/fedora/kernel-surface/files/linux-surface-default-watchdog.service +++ b/pkg/fedora/kernel-surface/files/linux-surface-default-watchdog.service @@ -3,4 +3,4 @@ Description=linux-surface default kernel watchdog [Service] Type=oneshot -ExecStart=/usr/bin/linux-surface-default-watchdog.sh +ExecStart=/usr/bin/linux-surface-default-watchdog.py diff --git a/pkg/fedora/kernel-surface/files/linux-surface-default-watchdog.sh b/pkg/fedora/kernel-surface/files/linux-surface-default-watchdog.sh deleted file mode 100755 index b0a55dc68..000000000 --- a/pkg/fedora/kernel-surface/files/linux-surface-default-watchdog.sh +++ /dev/null @@ -1,23 +0,0 @@ -#!/bin/bash -set -euo pipefail - -# Get list of surface kernels with timestamp -KERNELS="$( - find /boot -maxdepth 1 -name 'vmlinuz-*.surface.*' -print0 | xargs -0 -I '{}' \ - stat -c "%W %n" {} -)" - -# Sort by timestamp -KERNELS="$(echo "${KERNELS}" | sort -n)" - -# Get latest kernel (last line) and extract the path -VMLINUX="$(echo "${KERNELS}" | tail -n1 | cut -d' ' -f2)" - -echo "${VMLINUX}" - -# update GRUB config -grubby --set-default "$(grub2-mkrelpath "${VMLINUX}")" - -# Update timestamp for rEFInd -# Ensure it's marked as latest across all kernels, not just surface ones -touch "${VMLINUX}" diff --git a/pkg/fedora/kernel-surface/patches/0004-default-kernel.patch b/pkg/fedora/kernel-surface/patches/0004-default-kernel.patch index bd0b940d5..7b273304e 100644 --- a/pkg/fedora/kernel-surface/patches/0004-default-kernel.patch +++ b/pkg/fedora/kernel-surface/patches/0004-default-kernel.patch @@ -19,7 +19,7 @@ index 43dce82a9d36..28df94e561d4 100644 +Source4100: linux-surface-default-watchdog.path +Source4101: linux-surface-default-watchdog.service -+Source4102: linux-surface-default-watchdog.sh ++Source4102: linux-surface-default-watchdog.py +Source4103: 90-linux-surface-default-watchdog.preset + ## Patches needed for building this package @@ -81,7 +81,7 @@ index 43dce82a9d36..28df94e561d4 100644 %endif +%files default-watchdog -+%{_bindir}/linux-surface-default-watchdog.sh ++%{_bindir}/linux-surface-default-watchdog.py +%{_unitdir}/linux-surface-default-watchdog.path +%{_unitdir}/linux-surface-default-watchdog.service +%{_presetdir}/90-linux-surface-default-watchdog.preset