Browse Source

Merge pull request #1367 from linux-surface/kernel-watchdog-v3

Another kernel-watchdog update for btrfs
Dorian Stoll 1 năm trước cách đây
mục cha
commit
3187d8c8db

+ 87 - 0
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())

+ 1 - 1
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

+ 0 - 23
pkg/fedora/kernel-surface/files/linux-surface-default-watchdog.sh

@@ -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}"

+ 2 - 2
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