Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

hooks: remove: Switch to PreTransaction #18

Merged
merged 3 commits into from
Jan 11, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 2 additions & 10 deletions booster-um
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,8 @@ main() {
;;
-p)
# This argument is used in libalpm remove hook
# Remove UKI files and other leftovers for removed kernels
_post_transaction_remove || exit 0
# Remove orphaned EFI entries
_remove_orphaned_efi_entries
;;
-C)
# Cleanup
Expand All @@ -65,17 +65,9 @@ main() {
# The initramfs will be generated by the booster hook script
# UKI file will not be signed if it already exists in the sbctl database
shift
always_sign=0
_generate_fallback_initramfs "$1" "$2"
_generate_uki "$1" "$2"
;;
-U)
# It will always regenerate initramfs
# This argument is used in libalpm hook
# Regenerate UKI files for all installed kernels
always_sign=0
_regenerate_all
;;
*)
echo -e "${R}==>${NC} Unknown parameter ${R}$arg${NC} passed." >&2
show_help && exit 1
Expand Down
11 changes: 11 additions & 0 deletions libalpm/hooks/60-booster-um-remove.hook
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
[Trigger]
Type = Path
Operation = Remove
Target = usr/bin/booster-um
Target = usr/lib/modules/*/vmlinuz

[Action]
Description = Removing UKI files...
When = PreTransaction
Exec = /usr/share/libalpm/scripts/booster-um-remove
NeedsTargets
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ Operation = Remove
Target = usr/lib/modules/*/vmlinuz

[Action]
Description = Removing UKI leftovers...
Description = Removing orphaned EFI entries...
When = PostTransaction
Exec = /usr/bin/booster-um -p
NeedsTargets
NeedsTargets
5 changes: 4 additions & 1 deletion libalpm/scripts/booster-um-install
Original file line number Diff line number Diff line change
Expand Up @@ -39,9 +39,12 @@ if [ "${sign_all}" -eq "1" ]; then
exit
fi

# Sbctl hook should sign the UKI file if it already exists in database
export ALWAYS_SIGN=1

# Generate UKI files for all kernels
if [ "${all}" -eq "1" ]; then
booster-um -U
booster-um -G
exit
fi

Expand Down
28 changes: 28 additions & 0 deletions libalpm/scripts/booster-um-remove
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
#!/usr/bin/env bash

set -e

kernels=()

while read -r line; do
case "$line" in
usr/bin/booster-um)
booster-um -R
exit
;;
usr/lib/modules/*/vmlinuz)
kernels+=("/${line%/vmlinuz}")
;;
esac
done

for kernel in "${kernels[@]}"; do
if ! pacman -Qqo -- "${kernel}/pkgbase" > /dev/null 2>&1; then
# if pkgbase does not belong to any package then skip this kernel
continue
fi
read -r pkgbase < "${kernel}/pkgbase"

# Remove the UKI file
export REMOVE_EFI=1; booster-um -r "$pkgbase"
done
32 changes: 16 additions & 16 deletions scripts/config
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,10 @@
set -e

# Disable sbsign by default
declare -g sbsign=0
declare -g SBSIGN=1

# A value of 0 means that the booster-um config is valid
declare -g config_valid=0
declare -g CONFIG_VALID=0

# Array with initramfs configs
declare -A initramfs_config
Expand All @@ -17,13 +17,13 @@ declare -g BOOSTER_CONFIG=/etc/booster.yaml

# Checks if booster-um.yaml config is valid
_check_config() {
[[ ! -e $CONFIG ]] && config_valid=$((1-$?)) && return
[[ ! -e $CONFIG ]] && CONFIG_VALID=$((1-$?)) && return

if [[ ! -s $CONFIG ]]; then
config_valid=1
CONFIG_VALID=1
else
config_valid=$(yq --exit-status "$CONFIG" &>/dev/null; echo "$?")
if [[ $config_valid -ne 0 ]]; then
CONFIG_VALID=$(yq --exit-status "$CONFIG" &>/dev/null; echo "$?")
if [[ $CONFIG_VALID -ne 0 ]]; then
echo -e "${R}==>${NC} ${Y}$CONFIG${NC} config ${R}is not valid${NC}. ${Y}Default${NC} settings are used."
fi
fi
Expand All @@ -32,53 +32,53 @@ _check_config() {
}

_set_signing_tool() {
[[ $config_valid -eq 1 ]] && return
if _command_exists sbsign && yq '.sbsign == true' "$CONFIG" | grep -Fqwx -- 'true'; then sbsign=1; fi
[[ $CONFIG_VALID -eq 1 ]] && return
if _command_exists sbsign && yq '.sbsign == true' "$CONFIG" | grep -Fqwx -- 'true'; then SBSIGN=0; fi
}

# Checks if the creation of universal images is enabled
_is_universal() {
[[ $config_valid -eq 1 ]] && return 1
[[ $CONFIG_VALID -eq 1 ]] && return 1
yq '.universal == true' "$BOOSTER_CONFIG" | grep -Fqwx -- 'true'
}

# Checks if the booster-um should always generate a fallback UKI
_should_generate_fallback() {
[[ $config_valid -eq 1 ]] && return 1
[[ $CONFIG_VALID -eq 1 ]] && return 1
if yq '.generate_fallback == true' "$CONFIG" | grep -Fqwx -- 'true' && ! _is_universal; then return; fi
false
}

# Checks if the booster-um should always sign generated UKI
_should_sign_uki() {
[[ $config_valid -eq 1 ]] && return
[[ $CONFIG_VALID -eq 1 ]] && return
if ! yq '.sign_uki == false' "$CONFIG" | grep -Fqwx -- 'true'; then return; fi
false
}

# Checks if the booster-um should remove leftovers (vmlinuz and initramfs)
_should_remove_leftovers() {
[[ $config_valid -eq 1 ]] && return
[[ $CONFIG_VALID -eq 1 ]] && return
if ! yq '.remove_leftovers == false' "$CONFIG" | grep -Fqwx -- 'true'; then return; fi
false
}

# Checks if the booster-um should create EFI entry
_should_create_efi_entry() {
[[ $config_valid -eq 1 ]] && return 1
[[ $CONFIG_VALID -eq 1 ]] && return 1
if yq '.efistub == true' "$CONFIG" | grep -Fqwx -- 'true'; then return; fi
false
}

# Checks if the booster-um should create EFI entry
_should_preserve_boot_order() {
[[ $config_valid -eq 1 ]] && return
[[ $CONFIG_VALID -eq 1 ]] && return
if ! yq '.efistub_config.preserve_boot_order == false' "$CONFIG" | grep -Fqwx -- 'true'; then return; fi
false
}

_cmdline_per_kernel() {
[[ $config_valid -eq 1 ]] && return 1
[[ $CONFIG_VALID -eq 1 ]] && return 1
if yq '.cmdline_per_kernel == true' "$CONFIG" | grep -Fqwx -- 'true'; then return; fi
false
}
Expand Down Expand Up @@ -118,7 +118,7 @@ _get_splash_path() {
local default_splash=/usr/share/systemd/bootctl/splash-arch.bmp

# If the config file doesn't exist or is not valid, use the default arch linux splash
if [[ $config_valid -eq 1 ]] && _is_bmp "$default_splash"; then
if [[ $CONFIG_VALID -eq 1 ]] && _is_bmp "$default_splash"; then
echo "$default_splash" && return
fi

Expand Down
74 changes: 69 additions & 5 deletions scripts/efistub
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@ declare -g ESP
# EFI dir path of the directory where the UKI files are located. Example: esp/EFI/Linux
declare -g EFI_DIR

# ESP partition UUID
declare -g ESP_PARTUUID

# EFI System Partition mount point. Examples: /boot, /efi, /boot/efi
declare -g ESP_MOUNT

Expand Down Expand Up @@ -44,6 +47,8 @@ _set_efi_path() {
ESP="$(findmnt --real -nreo source "${ESP_MOUNT}")"
fi

ESP_PARTUUID="$(partx -g -o UUID "${ESP}")"

# Trigger any potential automounts
stat -- /boot /efi "$EFI_DIR" &>/dev/null || :
}
Expand All @@ -52,8 +57,7 @@ _set_efi_path() {
_efi_entry_exists() {
local loader_path esp_partuuid
loader_path="$1"
esp_partuuid="$(partx -g -o UUID "${ESP}")"
efibootmgr | grep -w "$esp_partuuid" | grep -Fwq -e "${loader_path}" -e "${loader_path^^}"
efibootmgr | grep -w "$ESP_PARTUUID" | grep -Fwq -e "${loader_path}" -e "${loader_path^^}"
}

# Extracts the pkgbase from known UKI file path
Expand All @@ -68,7 +72,7 @@ _get_pkgbase_from_path() {
}

# Formats the efi path to be readable by efibootmgr
_get_formatted_efi_path() {
_get_loader_path() {
local efi
efi="$1"

Expand All @@ -79,6 +83,25 @@ _get_formatted_efi_path() {
echo "$efi_path"
}

# Checks if loader file exists
_loader_file_exists() {
local loader_path uki_name uki_path
loader_path="$1"

# Remove string prefix, before last \ char
# \EFI\LINUX\ARCH-LINUX.EFI -> ARCH-LINUX.EFI
uki_name="${loader_path##*\\}"

# Lowercase name
uki_name="${uki_name,,}"

# Set the UKI file path
uki_path="${EFI_DIR}/${uki_name}"

# Check if the UKI file exists
[[ -f $uki_path ]]
}

# Returns the EFI entry label
_get_label() {
local pkgbase="$1"
Expand Down Expand Up @@ -115,7 +138,7 @@ _create_efi_entry() {
uki="$1"

# Set loader path with backslashes
loader_path="$(_get_formatted_efi_path "$uki")"
loader_path="$(_get_loader_path "$uki")"

# Return if the entry exists
if _efi_entry_exists "$loader_path"; then return; fi
Expand Down Expand Up @@ -160,7 +183,7 @@ _remove_efi_entry() {
uki="$1"

# Set loader path with backslashes
loader_path="$(_get_formatted_efi_path "$uki")"
loader_path="$(_get_loader_path "$uki")"

# Find all known labels
readarray -t labels < <(efibootmgr | \
Expand All @@ -181,3 +204,44 @@ _remove_efi_entry() {
efibootmgr -b "$boot_num" -B > /dev/null
done
}

# Removes orphaned EFI entries
_remove_orphaned_efi_entries() {
# Return if efibootmgr doesn't exist
if ! _command_exists efibootmgr; then exit; fi

local search="${EFI_DIR#$ESP_MOUNT}/arch-"
search="${search//\//\\}"

# Get all uniqe loader paths
readarray -t loader_paths < <(efibootmgr | \
grep -w "$ESP_PARTUUID" | grep -Fi "$search" | \
sed 's/.*(\(.*\))/\1/' | uniq -u)

for loader_path in "${loader_paths[@]}"; do
if ! _loader_file_exists "$loader_path"; then
# Get the boot number
readarray -t boot_nums < <(efibootmgr | \
grep -Fw "$loader_path" | \
awk '{ print $1 }' | \
sed -r 's/0+([0-9]+)/\1/g;s/Boot//;s/\*//')

# Get the labels
readarray -t labels < <(efibootmgr | \
grep -Fw "$loader_path" | \
sed 's/.*\*[[:blank:]]\(.*\)[[:blank:]]\(.*\)/\1/')

for label in "${labels[@]}"; do
echo -e "${Y} ->${NC} Removing EFI entry ${Y}${label}${NC}..."
done

# Remove the EFI entries
for boot_num in "${boot_nums[@]}"; do
efibootmgr -b "$boot_num" -B > /dev/null
done
fi
done

# One shot function, just exit
exit
}
6 changes: 3 additions & 3 deletions scripts/generate
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ _generate_uki() {
local uki_path="${EFI_DIR}/arch-${pkgbase}"

local -a sign_args=()
if [[ $sbsign -eq 1 ]] && _should_sign_uki; then
if [[ $SBSIGN -eq 0 ]] && _should_sign_uki; then
local pcr_banks="$(_get_sbsign_property pcr_banks)"
local pcr_private_key="$(_get_sbsign_property pcr_private_key)"
local pcr_public_key="$(_get_sbsign_property pcr_public_key)"
Expand Down Expand Up @@ -92,7 +92,7 @@ _generate_uki() {
done

# Remove the leftovers (vmlinuz, booster initramfs and other files)
_remove_leftovers "$pkgbase" 1
_remove_leftovers "$pkgbase"
}

# Generates UKI file for specified kernel package name
Expand Down Expand Up @@ -157,7 +157,7 @@ _generate_initramfs() {
# Generate initramfs
if ! booster build --force --kernel-version "$uname" "$initramfs"; then
echo -e "${R}==>${NC} Unable to generate initramfs for ${R}${pkgbase}${NC}..."
_remove_leftovers "$pkgbase" 1
_remove_leftovers "$pkgbase"
return 1
fi

Expand Down
Loading