pve-kernel-meta/bin/pve-efiboot-tool
Fabian Grünbichler 27d9325195 efiboot refresh: check --hook parameter
against list of default hook scripts.

Signed-off-by: Fabian Grünbichler <f.gruenbichler@proxmox.com>
2019-08-05 13:26:08 +02:00

404 lines
8.5 KiB
Bash
Executable File

#!/bin/sh
set -e
. /usr/share/pve-kernel-helper/scripts/functions
_add_entry_to_list_file() {
file="$1"
entry="$2"
if [ -e "$file" ]; then
cp "$file" "$file.new"
fi
echo "$entry" >> "$file.new"
sort -uo "$file.new" "$file.new"
mv "$file.new" "$file"
}
_remove_entry_from_list_file() {
file="$1"
entry="$2"
# guard against removing whole file by accident!
if [ -z "$entry" ]; then
echo "cannot remove empty entry from '$file'."
return
fi
if [ -e "$file" ]; then
grep -vFx "$entry" "$file" > "$file.new" || true
mv "$file.new" "$file"
else
echo "'$file' does not exist.."
fi
}
_get_partition_info() {
if [ ! -e "$1" ]; then
warn "E: '$1' does not exist!"
exit 1
fi
bdev=$(realpath "$1")
if [ ! -b "$bdev" ]; then
warn "E: '$bdev' is not a block device!"
exit 1
fi
bdev_info=$( \
lsblk \
--bytes \
--pairs \
-o 'UUID,SIZE,FSTYPE,PARTTYPE,PKNAME,MOUNTPOINT' \
"$bdev" \
)
if [ -z "$bdev_info" ]; then
warn "E: unable to get information about block device '$1'!"
exit 1
fi
count=$(echo "$bdev_info" | grep -c '^')
if [ "$count" -ne '1' ]; then
echo "$bdev_info"
warn "E: block device '$1' has children!"
exit 1
fi
echo "$bdev_info"
eval "$bdev_info"
if [ -z "$PKNAME" ]; then
warn "E: cannot determine parent device of '$1' - please provide a partition, not a full disk."
exit 1
fi
if [ -n "$SIZE" ] && [ "$SIZE" -lt 268435456 ]; then
warn "E: '$1' is too small (<256M)."
exit 1
fi
if [ -n "$MOUNTPOINT" ]; then
warn "E: '$1' is mounted on '$MOUNTPOINT' - exiting."
exit 1
fi
}
format() {
part="$1"
force="$2"
_get_partition_info "$part"
if [ -n "$FSTYPE" ]; then
if [ -z "$force" ] || [ "$force" != '--force' ]; then
warn "E: '$part' contains a filesystem ('$FSTYPE') - exiting (use --force to override)"
exit 1
fi
fi
part_basename=$(basename "$part")
if [ -z "$part_basename" ]; then
warn "E: unable to determine basename of '$part'"
exit 1
fi
part_num=$(cat /sys/block/"$PKNAME"/"$part_basename"/partition)
if [ -z "$part_num" ]; then
warn "E: unable to determine partition number of '$part'"
exit 1
fi
if [ -z "$PARTTYPE" ] || [ "$PARTTYPE" != "$ESPTYPE" ]; then
echo "Setting partition type of '$part' to '$ESPTYPE'.."
sgdisk "-t$part_num:$ESPTYPE" "/dev/$PKNAME"
echo "Calling 'udevadm settle'.."
udevadm settle --timeout=5
fi
echo "Formatting '$part' as vfat.."
mkfs.vfat -F 32 "$part"
echo "Done."
exit 0
}
init() {
part="$1"
_get_partition_info "$part"
if [ -z "$PARTTYPE" ] || [ "$PARTTYPE" != "$ESPTYPE" ]; then
warn "E: '$part' has wrong partition type (!= $ESPTYPE)."
exit 1
fi
if [ -z "$FSTYPE" ] || [ "$FSTYPE" != 'vfat' ]; then
warn "E: '$part' has wrong filesystem (!= vfat)."
exit 1
fi
if [ -z "$UUID" ]; then
warn "E: '$part' has no UUID set, required for mounting."
exit 1
fi
esp_mp="/var/tmp/espmounts/$UUID"
mkdir -p "$esp_mp"
echo "Mounting '$part' on '$esp_mp'."
mount -t vfat "$part" "$esp_mp"
echo "Installing systemd-boot.."
mkdir -p "$esp_mp/$PMX_ESP_DIR"
bootctl --path "$esp_mp" install
echo "Configuring systemd-boot.."
echo "timeout 3" > "$esp_mp/$PMX_LOADER_CONF.tmp"
echo "default proxmox-*" >> "$esp_mp/$PMX_LOADER_CONF.tmp"
mv "$esp_mp/$PMX_LOADER_CONF.tmp" "$esp_mp/$PMX_LOADER_CONF"
echo "Unmounting '$part'."
umount "$part"
echo "Adding '$part' to list of synced ESPs.."
_add_entry_to_list_file "$ESP_LIST" "$UUID"
echo "Refreshing kernels and initrds.."
refresh
}
_clean_impl() {
if [ ! -e "/dev/disk/by-uuid/" ]; then
warn 'E: /dev/disk/by-uuid does not exist, aborting!'
exit 1
fi
echo -n "Checking whether ESP '$curr_uuid' exists.. "
if [ -e "/dev/disk/by-uuid/$curr_uuid" ]; then
echo "Found!"
else
echo "Not found!"
if [ -z "$dry_run" ] || [ "$dry_run" != '--dry-run' ]; then
_remove_entry_from_list_file "$ESP_LIST" "$curr_uuid"
fi
fi
}
clean() {
dry_run="$1"
rm -f "$ESP_LIST".tmp
loop_esp_list _clean_impl
if [ "$?" -eq 2 ]; then
warn "E: $ESP_LIST does not exist."
exit 1
fi
if [ -e "$ESP_LIST".tmp ]; then
mv "$ESP_LIST".tmp "$ESP_LIST"
fi
}
refresh() {
hook=$1
hookscripts='pve-auto-removal zz-pve-efiboot'
if [ -n "$hook" ]; then
if echo "$hookscripts" | grep -sqE "(^|[[:space:]]+)$hook([[:space:]]+|$)"; then
hookscripts="$hook"
else
warn "E: '$hook' is not a valid hook script name.";
exit 1;
fi
fi
for script in $hookscripts; do
scriptpath="/etc/kernel/postinst.d/$script"
if [ -f "$scriptpath" ] && [ -x "$scriptpath" ]; then
echo "Running hook script '$script'.."
$scriptpath
else
warn "Hook script '$script' not found or not executable, skipping."
fi
done
}
add_kernel() {
ver="$1"
if [ -z "$ver" ]; then
warn "E: <kernel-version> is mandatory"
warn ""
exit 1
fi
if [ ! -e "/boot/vmlinuz-$ver" ]; then
warn "E: no kernel image found in /boot for '$ver', not adding."
exit 1
fi
_add_entry_to_list_file "$MANUAL_KERNEL_LIST" "$ver"
echo "Added kernel '$ver' to manual kernel list. Use the 'refresh' command to update the ESPs."
}
remove_kernel() {
ver="$1"
if [ -z "$ver" ]; then
warn "E: <kernel-version> is mandatory"
warn ""
exit 1
fi
if grep -sqFx "$ver" "$MANUAL_KERNEL_LIST"; then
_remove_entry_from_list_file "$MANUAL_KERNEL_LIST" "$ver"
echo "Removed kernel '$ver' from manual kernel list. Use the 'refresh' command to update the ESPs."
else
echo "Kernel '$ver' not found in manual kernel list."
fi
}
list_kernels() {
boot_kernels="$(boot_kernel_list)"
if [ -e "$MANUAL_KERNEL_LIST" ]; then
manual_kernels="$(echo "$boot_kernels" | grep -Fx -f "$MANUAL_KERNEL_LIST" || true)"
boot_kernels="$(echo "$boot_kernels" | grep -Fxv -f "$MANUAL_KERNEL_LIST" || true)"
fi
if [ -z "$manual_kernels" ]; then
manual_kernels="None."
fi
echo "Manually selected kernels:"
echo "$manual_kernels"
echo ""
echo "Automatically selected kernels:"
echo "$boot_kernels"
}
usage() {
warn "USAGE: $0 <commands> [ARGS]"
warn ""
warn " $0 format <partition> [--force]"
warn " $0 init <partition>"
warn " $0 clean [--dry-run]"
warn " $0 refresh [--hook <name>]"
warn " $0 kernel <add|remove> <kernel-version>"
warn " $0 kernel list"
warn " $0 help"
}
help() {
echo "USAGE: $0 format <partition> [--force]"
echo ""
echo " format <partition> as EFI system partition. Use --force to format even if <partition> is currently in use."
echo ""
echo "USAGE: $0 init <partition>"
echo ""
echo " initialize EFI system partition at <partition> for automatic synchronization of pve-kernels and their associated initrds."
echo ""
echo "USAGE: $0 clean [--dry-run]"
echo ""
echo " remove no longer existing EFI system partition UUIDs from $ESP_LIST. Use --dry-run to only print outdated entries instead of removing them."
echo ""
echo "USAGE: $0 refresh [--hook <name>]"
echo ""
echo " refresh all configured EFI system partitions. Use --hook to only run the specified hook, omit to run all."
echo ""
echo "USAGE: $0 kernel <add|remove> <kernel-version>"
echo ""
echo " add/remove pve-kernel with ABI <kernel-version> to list of synced kernels, in addition to automatically selected ones."
echo " NOTE: you need to manually run 'refresh' once you're finished with adding/removing kernels from the list"
echo ""
echo "USAGE: $0 kernel list"
echo ""
echo " list kernel versions currently selected for inclusion on ESPs."
echo ""
}
if [ -z "$1" ]; then
usage
exit 0
fi
case "$1" in
'format')
shift
if [ -z "$1" ]; then
warn "E: <partition> is mandatory."
warn ""
usage
exit 1
fi
format "$@"
exit 0
;;
'init')
reexec_in_mountns "$@"
shift
if [ -z "$1" ]; then
warn "E: <partition> is mandatory."
warn ""
usage
exit 1
fi
init "$@"
exit 0
;;
'clean')
shift
clean "$@"
exit 0
;;
'refresh')
shift
if [ "$#" -eq 0 ]; then
refresh
elif [ "$#" -eq 2 ] && [ "$1" = "--hook" ]; then
refresh "$2"
else
usage
exit 1
fi
exit 0
;;
'kernel'|'kernels')
shift
if [ -z "$1" ]; then
warn "E: subcommand is mandatory for 'kernel'."
warn ""
usage
exit 1
fi
cmd="$1"
case "$cmd" in
'add')
add_kernel "$2"
exit 0
;;
'remove')
remove_kernel "$2"
exit 0
;;
'list')
list_kernels
exit 0
;;
*)
warn "E: invalid 'kernel' subcommand '$cmd'."
warn ""
usage
exit 1
;;
esac
;;
'help')
shift
help
exit 0
;;
*)
warn "Invalid/unknown command '$1'."
warn ""
usage
exit 1
;;
esac
exit 1