123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687 |
- #!/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())
|