Add USB autoboot feature to PureBoot Basic

USB autoboot automatically boots to a USB flash drive if one is present
during boot.  This is intended for headless deployments as a method to
recover the installed operating system from USB without needing to
attach a display and keyboard.

USB autoboot can be controlled in config.user and the config GUI.

Signed-off-by: Jonathon Hall <jonathon.hall@puri.sm>
This commit is contained in:
Jonathon Hall 2022-11-09 15:03:53 -05:00
parent b0e0a91c97
commit 206d59dc71
No known key found for this signature in database
GPG Key ID: 1E9C3CA91AE25114
3 changed files with 90 additions and 10 deletions

View File

@ -32,6 +32,7 @@ while true; do
# check current Restricted Boot Mode
RESTRICTED_BOOT="$(load_config_value CONFIG_RESTRICTED_BOOT)"
BASIC_NO_AUTOMATIC_DEFAULT="$(load_config_value CONFIG_BASIC_NO_AUTOMATIC_DEFAULT)"
BASIC_USB_AUTOBOOT="$(load_config_value CONFIG_BASIC_USB_AUTOBOOT)"
dynamic_config_options=()
@ -39,6 +40,7 @@ while true; do
dynamic_config_options+=( \
'P' " $(get_config_display_action "$BASIC_MODE") PureBoot Basic Mode" \
'A' " $(get_inverted_config_display_action "$BASIC_NO_AUTOMATIC_DEFAULT") automatic default boot" \
'U' " $(get_config_display_action "$BASIC_USB_AUTOBOOT") USB automatic boot" \
)
else
dynamic_config_options+=( \
@ -362,6 +364,32 @@ while true; do
fi
fi
;;
"U" )
if [ "$BASIC_USB_AUTOBOOT" = "n" ]; then
if (whiptail --title 'Enable USB automatic boot?' \
--yesno "During boot, an attached bootable USB disk will be booted
\nby default instead of the installed operating system.
\n\nDo you want to proceed?" 0 80) then
set_config /etc/config.user "CONFIG_BASIC_USB_AUTOBOOT" "y"
combine_configs
whiptail --title 'Config change successful' \
--msgbox "USB automatic boot enabled;\nsave the config change and reboot for it to go into effect." 0 80
fi
else
if (whiptail --title 'Disable USB automatic boot?' \
--yesno "USB disks will no longer be booted by default.
\n\nDo you want to proceed?" 0 80) then
set_config /etc/config.user "CONFIG_BASIC_USB_AUTOBOOT" "n"
combine_configs
whiptail --title 'Config change successful' \
--msgbox "USB automatic boot disabled;\nsave the config change and reboot for it to go into effect." 0 80
fi
fi
;;
esac
done

View File

@ -64,20 +64,11 @@ mount_boot()
prompt_auto_default_boot()
{
TRACE "Under /bin/gui-init:prompt_auto_default_boot"
# save IFS before changing, restore after read
IFS_DEF=$IFS
IFS=''
first_pass=false
echo -e "\n\n"
read -t $CONFIG_AUTO_BOOT_TIMEOUT -s -n 1 -p "Automatic boot in $CONFIG_AUTO_BOOT_TIMEOUT seconds unless interrupted by keypress... "
if [[ $? -ne 0 ]]; then
IFS=$IFS_DEF
if pause_automatic_boot; then
echo -e "\n\nAttempting default boot...\n\n"
attempt_default_boot
fi
IFS=$IFS_DEF
}
show_main_menu()
@ -194,6 +185,14 @@ attempt_default_boot()
# gui-init-basic start
TRACE "Under /bin/gui-init, start"
# USB automatic boot (if configured) occurs before mounting /boot, this should
# work even if no OS is installed
if [ "$CONFIG_BASIC_USB_AUTOBOOT" = "y" ] && usb-autoboot.sh; then
# USB autoboot was offered and interrupted. Don't offer the default boot,
# go to the menu.
skip_to_menu=true
fi
if ! detect_boot_device ; then
# can't determine /boot device or no OS installed,
# so fall back to interactive selection

53
initrd/bin/usb-autoboot.sh Executable file
View File

@ -0,0 +1,53 @@
#!/bin/bash
set -o pipefail
. /etc/functions
. /etc/gui_functions
# Automatically boot to a bootable USB medium if present. This is for
# unattended boot; there is no UI.
# There are three possible results:
# * Automatic boot occurs - script does not return (kexec happens)
# * User interrupted automatic boot - script returns 0. Skip normal boot and go
# to the boot menu (don't prompt for two automatic boots).
# * No automatic boot was attempted - script returns nonzero. Continue with
# normal automatic boot.
# These may die for failure, nonzero exit is correct (USB boot wasn't possible)
enable_usb
enable_usb_storage
mkdir -p /media
parse_boot_options()
{
BOOTDIR="$1"
for i in $(find "$BOOTDIR" -name '*.cfg'); do
kexec-parse-boot "$BOOTDIR" "$i"
done
}
# Look for any bootable USB medium.
list_usb_storage >/tmp/usb-autoboot-usb-storage
while read -u 4 -r USB_BLOCK_DEVICE; do
mount "$USB_BLOCK_DEVICE" /media || continue
USB_DEFAULT_BOOT="$(parse_boot_options /media | head -1)"
if [ -n "$USB_DEFAULT_BOOT" ]; then
# Boot automatically, unless the user interrupts.
echo -e "\n\n"
echo "Found bootable USB: $(echo "$USB_DEFAULT_BOOT" | cut -d '|' -f 1)"
if ! pause_automatic_boot; then
# User interrupted, go to boot menu
umount /media
exit 0
fi
echo -e "\n\nBooting from USB...\n\n"
kexec-boot -b /media -e "$USB_DEFAULT_BOOT"
# If kexec-boot returned, the boot obviously did not occur,
# return nonzero below so the normal OS boot will continue.
fi
umount /media
done 4</tmp/usb-autoboot-usb-storage
# No bootable USB medium found
exit 1