#!/bin/fish function error -d "prints an error and exits" -a error echo $error 1>&2 exit 1 end function check_deps -d "checks if all dependencies are available" set -l dependencies \ "jq" \ "rg" \ "sed" \ "snapper" \ for dep in $dependencies which $dep >/dev/null 2>/dev/null if test $status != "0" error "missing depenency: $dep" end end which "efibootmgr" >/dev/null 2>/dev/null if test $status != "0" -a $CFG_EFI = "yes" set -g CFG_EFI "no" echo "CFG_EFI overwriten to \"no\": 'efibootmgr' not available" end which "sbsign" >/dev/null 2>/dev/null if test $status != "0" -a $CFG_EFI = "yes" set -g CFG_SECUREBOOT "no" echo "CFG_SECUREBOOT overwriten to \"no\": 'sbsign' not available" end end function find_tasks -d "finds out what the program needs to do" set -ge TASK_UKI for id in (snapper -c $CFG_SNAPSHOT_CONFIG --jsonout ls | jq ".$CFG_SNAPSHOT_CONFIG [] | .number") if test "$id" = "0" continue end if test -f "$CFG_UKI_DIR/arch-linux-$id.efi" continue end set -ga TASK_UKI $id end end function create_uki -d "creates a new uki" -a variant id switch $variant case "rolling" set bd "$CFG_BUILD_DIR/current" case "fallback" set bd "$CFG_BUILD_DIR/current" set fallback "-fallback" case "snapshot" set bd "$CFG_BUILD_DIR/$id" set snid "-$id" set prefix "$CFG_SNAPSHOT_PATH/$id/snapshot" case "*" error "unknown uki variant: $variant" end # create initrd set amd "$prefix/boot/amd-ucode.img" set intel "$prefix/boot/intel-ucode.img" set initrd "$bd/initramfs-linux$fallback.img" if test -f $amd cat $amd >> $initrd end if test -f $intel cat $intel >> $initrd end cat "$prefix/boot/initramfs-linux$fallback.img" >> $initrd # create uki objcopy \ --add-section .osrel="$bd/os-release$fallback" --change-section-vma .osrel=0x20000 \ --add-section .cmdline="$bd/kernel-cmd$fallback" --change-section-vma .cmdline=0x30000 \ --add-section .splash="$prefix/usr/share/systemd/bootctl/splash-arch.bmp" --change-section-vma .splash=0x40000 \ --add-section .linux="$prefix/boot/vmlinuz-linux" --change-section-vma .linux=0x2000000 \ --add-section .initrd="$initrd" --change-section-vma .initrd=0x3000000 \ "$prefix/usr/lib/systemd/boot/efi/linuxx64.efi.stub" "$bd/arch-linux$fallback$snid.efi.unsigned" # sign if test "$CFG_SECUREBOOT" = "yes" sbsign --key $CFG_SECUREBOOT_KEY \ --cert $CFG_SECUREBOOT_CERT \ --output "$bd/arch-linux$fallback$snid.efi" \ "$bd/arch-linux$fallback$snid.efi.unsigned" else # otherwise move unsigned efi to location mv "$bd/arch-linux$fallback$snid.efi.unsigned" "$bd/arch-linux$fallback$snid.efi" end end function create_snapshot_uki -d "creates an uki for a snapshot" -a id # create build directory set bd "$CFG_BUILD_DIR/$id" if test -f $bd error "build dir for snapshot $id is a file" else if test -d $bd rm -rf "$bd/*" else mkdir -p $bd end # prepare files sed "s/BUILD_ID=.*/BUILD_ID=\"snapshot $id\"/;s/PRETTY_NAME=\"\(.*\)\"/PRETTY_NAME=\"\1 (Snapshot $id)\"/" <"$CFG_SNAPSHOT_PATH/$id/snapshot/usr/lib/os-release" >"$bd/os-release" sed "s/SNAPSHOT/$CFG_SNAPSHOT_SUBVOL\/$id\/snapshot/" <"$CFG_SNAPSHOT_PATH/$id/snapshot/etc/snap-pac-uki/kernel-cmd" >"$bd/kernel-cmd" # create uki create_uki snapshot $id end function create_current_uki -d "creates an uki for the current system" # create build directory set bd "$CFG_BUILD_DIR/current" if test -f $bd error "build dir for snapshot $id is a file" else if test -d $bd rm -rf "$bd/*" else mkdir -p $bd end # create default cp "/usr/lib/os-release" "$bd/os-release" sed "s/SNAPSHOT/$CFG_DEFAULT_SUBVOL/" <"/etc/snap-pac-uki/kernel-cmd" >"$bd/kernel-cmd" create_uki rolling # create fallbac sed "s/BUILD_ID=.*/BUILD_ID=fallback/;s/PRETTY_NAME=\"\(.*\)\"/PRETTY_NAME=\"\1 (Fallback)\"/" <"/usr/lib/os-release" >"$bd/os-release-fallback" sed "s/SNAPSHOT/$CFG_DEFAULT_SUBVOL/" <"/etc/snap-pac-uki/kernel-cmd-fallback" >"$bd/kernel-cmd-fallback" create_uki fallback end function add_efi_entry -d "adds an efi boot entry for a snapshot uki" -a id efibootmgr -q -C -d $CFG_EFI_DEV -p $CFG_EFI_PART \ -l "$CFG_EFI_PATH\arch-linux-$id.efi" \ -L "Arch Linux (Snapshot $id)" end function main # prepare for execution source "/etc/snap-pac-uki/config.fish" config check_deps switch $argv[1] case "snapshots" find_tasks for id in $TASK_UKI echo "==> found snapshot without uki: $id" create_snapshot_uki $id echo " -> created uki for snapshot $id" cp "$CFG_BUILD_DIR/$id/arch-linux-$id.efi" "$CFG_UKI_DIR" echo " -> copied uki for snapshot $id into uki directory" if test "$CFG_EFI" = "yes" add_efi_entry $id echo " -> created efi boot entry for uki of snapshot $id" end end case "current" echo "==> creating current ukis" create_current_uki echo " -> created ukis" cp "$CFG_BUILD_DIR/current/arch-linux.efi" "$CFG_UKI_DIR" cp "$CFG_BUILD_DIR/current/arch-linux-fallback.efi" "$CFG_UKI_DIR" echo " -> copied ukis into uki directory" case "clean" echo "==> cleaning ukis" set ids (snapper -c $CFG_SNAPSHOT_CONFIG --jsonout ls | jq ".$CFG_SNAPSHOT_CONFIG [] | .number") for uki in (ls "$CFG_UKI_DIR" | rg "[0-9]" | sed "s/arch-linux-\([0-9]*\).efi/\1/") if not contains "$uki" $ids echo " -> cleaning uki and boot entry for removed snapshot $uki" rm "$CFG_UKI_DIR/arch-linux-$uki.efi" if test "$CFG_EFI" = "yes" efibootmgr -q -b (efibootmgr -v | rg "arch-linux-$uki.efi" | sed "s/\*//;s/Boot0*\(.*\) Arch .*/\1/") -B end end end case "*" error "unknown command" end end main $argv