|
|
@@ -0,0 +1,106 @@ |
|
|
#!/usr/bin/env python3 |
|
|
#exec tail -n +3 $0 |
|
|
# Be careful not to change |
|
|
# the 'exec tail' line above. |
|
|
|
|
|
# This script lives in /etc/grub.d/ |
|
|
|
|
|
# 2015,2022 Ralph Versteegen |
|
|
# The menuentry template was orginally generated by /etc/grub.d/10_linux |
|
|
|
|
|
import os |
|
|
import glob |
|
|
import re |
|
|
import sys |
|
|
import subprocess |
|
|
|
|
|
def tell(*args): |
|
|
print(*args, file = sys.stderr) |
|
|
|
|
|
def run(cmd): |
|
|
tell(cmd) |
|
|
ret = subprocess.check_output(cmd.split()).decode('utf-8').rstrip() |
|
|
tell(" ->", ret) |
|
|
return ret |
|
|
|
|
|
# Don't use initrd; the kernel image has it builtin and this breaks it |
|
|
# I blame the patch applied in the SlackBuild to GRUB2 which makes it look for /boot/initrd.gz... |
|
|
|
|
|
#################### bootflags |
|
|
|
|
|
# Useful kernel params: |
|
|
# rootdelay= [KNL] Delay (in seconds) to pause before attempting to |
|
|
# mount the root filesystem |
|
|
# S [KNL] Run init in single mode |
|
|
# libata.force=1.00:1.5,norst,udma4 or udma3 pio4 etc |
|
|
|
|
|
|
|
|
bootflags = "rootflags=subvol=root rootfstype=btrfs ro" |
|
|
|
|
|
#################### disks |
|
|
|
|
|
# Find HDD and SSD devices which have mounted partitions |
|
|
disks = {} |
|
|
for part in ("/mnt/btrfs_ssd", "/mnt/btrfs_pool", "/mnt/btrfs_hdd"): |
|
|
if not os.path.isdir(part): |
|
|
continue |
|
|
part_dev = run("findmnt -vfn -o SOURCE " + part) |
|
|
if part not in disks: |
|
|
# Trim the partition number, to get disk's device |
|
|
disks[part] = re.match("[^0-9]*", part_dev).group(0) |
|
|
|
|
|
tell("Found disks:", disks) |
|
|
|
|
|
#################### Entry for each disk |
|
|
|
|
|
for disk_path,disk_dev in disks.items(): |
|
|
|
|
|
# PARTUUID of the root's btrfs partition |
|
|
# PARTUUID shown by "lsblk -f -o +PARTUUID,SIZE", and by gdisk 'i' (information) as "Partition unique GUID" |
|
|
# It is stored in MBR or GPT |
|
|
root_partuuid = run("findmnt -vfn -o PARTUUID " + disk_path) |
|
|
|
|
|
# Check fstab for a /mnt/boot entry |
|
|
# It's also possible to search HDD for LABEL=boot using blkid |
|
|
#boot_dev = run("findmnt -vfn -o UUID /mnt/boot") |
|
|
|
|
|
# Check for a partition labelled "boot" |
|
|
try: |
|
|
boot_dev = run("blkid -t LABEL=boot -o device " + " ".join(glob.glob(disk_dev + "*"))) |
|
|
#if boot_dev: |
|
|
tell("Found boot partition " + boot_dev) |
|
|
|
|
|
boot_uuid = run("lsblk -n -o UUID " + boot_dev) |
|
|
#else: |
|
|
except subprocess.CalledProcessError: |
|
|
# No boot partition, using /boot |
|
|
|
|
|
# UUID aka FS UUID is stored in the FS itself |
|
|
boot_uuid = run("findmnt -vfn -o UUID " + disk_path) |
|
|
|
|
|
|
|
|
template = """ |
|
|
menuentry 'Slackware GNU/Linux {NAME}' --class gnu-linux --class gnu --class os $menuentry_id_option 'gnulinux-simple-new' {{ |
|
|
load_video |
|
|
insmod gzio |
|
|
insmod part_msdos |
|
|
insmod part_gpt |
|
|
insmod btrfs |
|
|
insmod ext2 |
|
|
echo 'Searching for boot partition...' |
|
|
search.fs_uuid {BOOTUUID} root |
|
|
echo 'Loading Linux from' $root |
|
|
linux /root/boot/{IMAGE} {BOOTFLAGS} root=PARTUUID={ROOTPARTUUID} |
|
|
}} |
|
|
""" |
|
|
|
|
|
for image_name in ("vmlinuz", "vmlinuz-backup"): |
|
|
image_path = disk_path + "/root/boot/" + image_name |
|
|
if os.path.isfile(image_path): |
|
|
name = os.readlink(image_path) + " on " + disk_path |
|
|
|
|
|
print(template.format(ROOTPARTUUID = root_partuuid, |
|
|
BOOTUUID = boot_uuid, |
|
|
BOOTFLAGS = bootflags, |
|
|
IMAGE = image_name, |
|
|
NAME = name)) |