diff options
author | d10n | 2022-02-09 11:46:23 -0500 |
---|---|---|
committer | d10n | 2022-02-09 18:17:45 -0500 |
commit | 1b97fb4256a9449452ba86da7f5d14824c62acb6 (patch) | |
tree | 4fb91cc4a5866d2a413a77e85e8ad146cfa94e7d | |
download | aur-1b97fb4256a9449452ba86da7f5d14824c62acb6.tar.gz |
Create repository
-rw-r--r-- | .SRCINFO | 17 | ||||
-rw-r--r-- | .gitignore | 6 | ||||
-rw-r--r-- | 90-unified-kernel-image-uefi-ucode.hook | 11 | ||||
-rw-r--r-- | PKGBUILD | 24 | ||||
-rw-r--r-- | README.md | 32 | ||||
-rw-r--r-- | unified-kernel-image-backup.service | 14 | ||||
-rw-r--r-- | unified-kernel-image-backup.sh | 122 | ||||
-rw-r--r-- | unified-kernel-image-hooks.install | 11 |
8 files changed, 237 insertions, 0 deletions
diff --git a/.SRCINFO b/.SRCINFO new file mode 100644 index 000000000000..8c7c51e9b75b --- /dev/null +++ b/.SRCINFO @@ -0,0 +1,17 @@ +pkgbase = unified-kernel-image-hooks + pkgdesc = Unified kernel image UEFI hooks: save the currently-booted efi image as a backup entry + pkgver = 1.0.0 + pkgrel = 1 + url = https://github.com/d10n/arch-unified-kernel-image-hooks + install = unified-kernel-image-hooks.install + arch = x86_64 + license = GPL + depends = binutils + source = 90-unified-kernel-image-uefi-ucode.hook + source = unified-kernel-image-backup.service + source = unified-kernel-image-backup.sh + sha256sums = 6aa273c83faf1d15664bb2c39950ffdab0c540f5ace5dd58e531f9a9de515c54 + sha256sums = c90ff05c0fb9629f09b1ab7bd672ff2a88dc6a3e6a474ac1c6d82096431c477b + sha256sums = 1d68aad096c55357e574291fe93c2c2be6bcd3e493edd4ea15da0c12ce0f0f38 + +pkgname = unified-kernel-image-hooks diff --git a/.gitignore b/.gitignore new file mode 100644 index 000000000000..7d5c9c83be0b --- /dev/null +++ b/.gitignore @@ -0,0 +1,6 @@ +pkg/ +src/ +*.tar.zst +*.tar.xz +*.tar.gz + diff --git a/90-unified-kernel-image-uefi-ucode.hook b/90-unified-kernel-image-uefi-ucode.hook new file mode 100644 index 000000000000..c7c77189e05a --- /dev/null +++ b/90-unified-kernel-image-uefi-ucode.hook @@ -0,0 +1,11 @@ +[Trigger] +Operation = Install +Operation = Upgrade +Type = Path +Target = boot/*-ucode.img + +[Action] +Description = Updating linux initcpios for microcode in unified uefi... +When = PostTransaction +Exec = /usr/share/libalpm/scripts/mkinitcpio-install +NeedsTargets diff --git a/PKGBUILD b/PKGBUILD new file mode 100644 index 000000000000..6c13efe07188 --- /dev/null +++ b/PKGBUILD @@ -0,0 +1,24 @@ +# Maintainer: d10n <david at bitinvert dot com> +pkgname=unified-kernel-image-hooks +pkgver=1.0.0 +pkgrel=1 +pkgdesc="Unified kernel image UEFI hooks: save the currently-booted efi image as a backup entry" +arch=(x86_64) +url="https://github.com/d10n/arch-unified-kernel-image-hooks" +license=('GPL') +depends=(binutils) +source=( + 90-unified-kernel-image-uefi-ucode.hook + unified-kernel-image-backup.service + unified-kernel-image-backup.sh + ) +install=unified-kernel-image-hooks.install +sha256sums=('6aa273c83faf1d15664bb2c39950ffdab0c540f5ace5dd58e531f9a9de515c54' + 'c90ff05c0fb9629f09b1ab7bd672ff2a88dc6a3e6a474ac1c6d82096431c477b' + '1d68aad096c55357e574291fe93c2c2be6bcd3e493edd4ea15da0c12ce0f0f38') + +package() { + install -m755 -D unified-kernel-image-backup.sh "$pkgdir/usr/libexec/unified-kernel-image-hooks/unified-kernel-image-backup.sh" + install -m644 -D unified-kernel-image-backup.service "$pkgdir/usr/lib/systemd/system/unified-kernel-image-backup.service" + install -m644 -D 90-unified-kernel-image-uefi-ucode.hook "$pkgdir/usr/share/libalpm/hooks/90-unified-kernel-image-uefi-ucode.hook" +} diff --git a/README.md b/README.md new file mode 100644 index 000000000000..01e4ca618ccb --- /dev/null +++ b/README.md @@ -0,0 +1,32 @@ +# arch-unified-kernel-image-hooks + +* Save a backup copy of the currently-booted unified kernel image UEFI entry +* Update the unified kernel image when the microcode gets updated + +## Notes + +* Ensure that your EFI System Partition has enough available space to save an extra copy of each unified kernel image that you boot into. +* The tool only works on local disks, which is probably what you have. Network EFI images are not backed up. +* The tool currently supports images generated by mkinitcpio. Pull requests for other initramfs generators welcome. + +## Setup + +1. [Configure Unified Kernel Image creation](https://wiki.archlinux.org/title/Unified_kernel_image) +2. Install the package. (`unified-kernel-image-hooks`) +3. `systemctl enable unified-kernel-image-backup.service` +4. Add the UEFI boot entry. + Examples (change --disk, --part, and --loader as necessary): + ``` + efibootmgr -v --create --disk /dev/sda --part 1 --label 'Arch Linux (last booted kernel)' --loader '\EFI\ARCH\linux-x64-last.efi' + ``` + ``` + efibootmgr -v --create --disk /dev/nvme0n1 --part 1 --label 'Arch Linux (last booted kernel)' --loader '\EFI\ARCH\linux-x64-last.efi' + ``` +5. To create the first backup entry, either reboot, or run: + ``` + /usr/libexec/unified-kernel-image-hooks/unified-kernel-image-backup.sh + ``` + +## License + +GPL2 diff --git a/unified-kernel-image-backup.service b/unified-kernel-image-backup.service new file mode 100644 index 000000000000..b2d18927534c --- /dev/null +++ b/unified-kernel-image-backup.service @@ -0,0 +1,14 @@ +[Unit] +Description=Save a backup of the currently-booted unified kernel image +DefaultDependencies=no +Requires=boot-complete.target +After=local-fs.target boot-complete.target +Conflicts=shutdown.target +Before=shutdown.target + +[Service] +Type=oneshot +ExecStart=/usr/libexec/unified-kernel-image-hooks/unified-kernel-image-backup.sh + +[Install] +WantedBy=basic.target diff --git a/unified-kernel-image-backup.sh b/unified-kernel-image-backup.sh new file mode 100644 index 000000000000..1cbcb2e7495d --- /dev/null +++ b/unified-kernel-image-backup.sh @@ -0,0 +1,122 @@ +#!/bin/sh + +set -eu + +# unified-kernel-image-backup.sh +# Saves a backup copy of the currently-booted unified kernel image +# Depends on binutils + +# Limitations: +# * The EFI partition must be mounted +# * The EFI loader image must not have a ")" character in its path/name +# * The EFI partition must have enough space to make the backup copy + +# Output: +# * <image-name>-last.efi +# * <image-name>-last.txt + +# Setup: +# efibootmgr -v --create --disk /dev/sda --part 1 --label 'Arch Linux (last booted kernel)' --loader '\EFI\ARCH\linux-x64-last.efi' +# -or- +# efibootmgr -v --create --disk /dev/nvme0n1 --part 1 --label 'Arch Linux (last booted kernel)' --loader '\EFI\ARCH\linux-x64-last.efi' + +# 1. Find the currently-booted efi image +# 2. Determine if it is an Arch unified kernel image +# 3. Determine if it is already saved +# 4. Save a copy of the currently-booted image + + +# Example efibootmgr output: +#BootCurrent: 0002 +#Timeout: 1 seconds +#BootOrder: 0002,0000,0001,0004,0003 +#Boot0000* Arch Linux Grub HD(1,GPT,00000000-0000-4000-0000-000000000000,0x1000,0x1ff800)/File(\EFI\ARCH\grubx64.efi) +#Boot0001* Linux Recovery HD(1,GPT,00000000-0000-4000-0000-000000000000,0x1000,0x1ff800)/File(\EFI\LinuxRecovery\grubx64.efi) +#Boot0002* Arch Linux HD(1,GPT,00000000-0000-4000-0000-000000000000,0x1000,0x1ff800)/File(\EFI\ARCH\linux-x64.efi) +#Boot0003* Arch Linux (last booted kernel) HD(1,GPT,00000000-0000-4000-0000-000000000000,0x1000,0x1ff800)/File(\EFI\ARCH\linux-x64-last.efi) +#Boot0004* Windows Boot Manager HD(1,GPT,22222222-2222-4222-2222-222222222222,0x800,0x32000)/File(\EFI\MICROSOFT\BOOT\BOOTMGFW.EFI)WINDOWS.........x...B.C.D.O.B.J.E.C.T.=.{.9.d.e.a.8.6.2.c.-.5.c.d.d.-.4.e.7.0.-.a.c.c.1.-.f.3.2.b.3.4.4.d.4.7.9.5.}.................... +#Boot0010 Setup FvFile(33333333-3333-4333-3333-333333333333) +#Boot0011 Boot Menu FvFile(55555555-5555-4555-5555-555555555555) + +# @see: UEFI Spec, version 2.9, 10.6.1.6 Text Device Node Reference + +# Assuming efibootmgr output is stable +efibootmgr -v | + awk ' + # Identify the current boot entry + /^BootCurrent:/ { bc = $2 } + + # Get partition and file path information from the current boot entry + $1 ~ "^Boot" bc { + # The tab character separates the entry id/name from the device path. + # There may be tabs in the device path, so use sub() instead of $2 and FS="\t" + sub("^[^\t]*\t", ""); + print $0; + + # UEFI only supports GPT, so this pattern should be safe enough + guid_idx = match($0, "GPT,........-....-....-....-............"); + if (!guid_idx) { exit 1; } + + # Extract the EFI partition GUID from the device node + guid = substr($0, guid_idx + 4, RLENGTH - 4); # 4: length of "GPT," + print guid; + + # Extract the path to the EFI image + file_idx = match($0, "\\)/File\\([^)]*"); + if (!file_idx) { exit 1; } + + # Fix path separator for Linux + gsub("\\\\", "/"); + + print substr($0, file_idx + 7, RLENGTH - 7); # 7: length of ")/File(" + } + ' | +( +IFS= read -r boot_entry_full +printf '%s\n' "Found current boot entry: $boot_entry_full" +IFS= read -r efi_partuuid +IFS= read -r efi_bin + +# findmnt -P is safe to eval. This sets the variable TARGET +eval "$(findmnt -P -o TARGET "/dev/disk/by-partuuid/$efi_partuuid")" + +case "$efi_bin" in + *-last.*) + if [ -e "${TARGET}${efi_bin%.*}.txt" ]; then + echo 'Probably booting a saved UEFI Unified Kernel Image; not saving last boot image' + exit 0 + fi + ;; +esac + +if ! objcopy -O binary --only-section .osrel "${TARGET}${efi_bin}" /dev/stdout | grep -qFx 'NAME="Arch Linux"'; then + # FIXME: does this work with the dracut-generated images? + echo 'Probably not a UEFI Unified Kernel Image; not saving last boot image' + exit 0 +fi + +efi_bin_save="${TARGET}${efi_bin%.*}-last.${efi_bin##*.}" +efi_bin_save_txt="${efi_bin_save%.*}.txt" +boot_uname_current="$(uname -r)" +if [ -e "$efi_bin_save_txt" ]; then + boot_uname_saved="$(cat "$efi_bin_save_txt")" + if [ "$boot_uname_saved" = "$boot_uname_current" ]; then + echo 'UEFI Unified Kernel Image already saved' + exit 0 + fi +fi + +# FUTURE: save multiple versions and clean up old versions with a timer/hook? +#efi_bin_save="${TARGET}${efi_bin%.*}-$(uname -r).${efi_bin##*.}" +#if [ -e "$efi_bin_save" ]; then +# exit 0; +#fi + +echo 'Saving UEFI Unified Kernel Image' +cp -av -- "${TARGET}${efi_bin}" "$efi_bin_save" +printf '%s\n' "$boot_uname_current" >"$efi_bin_save_txt" +) + +echo 'Done' + +#objcopy -O binary --only-section .osrel /boot/efi/EFI/arch/linux-x64.efi /dev/stdout diff --git a/unified-kernel-image-hooks.install b/unified-kernel-image-hooks.install new file mode 100644 index 000000000000..6895d2fb4b27 --- /dev/null +++ b/unified-kernel-image-hooks.install @@ -0,0 +1,11 @@ +## arg 1: the new package version +post_install() { + cat <<'EOF' +1. Enable the service: + systemctl enable unified-kernel-image-backup.service +2. Add the UEFI entry: + (example command; replace --disk, --part, --label, and --loader as required): + efibootmgr -v --create --disk /dev/sda --part 1 --label 'Arch Linux (last booted kernel)' --loader '\EFI\ARCH\linux-x64-last.efi' +3. Reboot to create the entry, or run /usr/libexec/unified-kernel-image-hooks/unified-kernel-image-backup.sh +EOF +} |