#!/usr/bin/env bash # Pretty name for firmware interface biosname="Firmware Configuration" # Check if systemd-boot is available bootctl is-installed &> /dev/null && sdboot=1 # Check if rebooting to the firmware interface is supported [[ "$(bootctl reboot-to-firmware)" == "supported" ]] && fwboot=1 selectentry() { # Usage: selectentry <prompt> local sel PS3 COLUMNS PS3="$2 " COLUMNS=1 # Print title to stderr printf "\n%s\n\n" "$1" >&2 # Populate entry list array # If we're in EFI mode if [[ -v efimode ]]; then # This one is fun # mapfile splits stdin on \n to an array # The sed regex looks for an asterisk in the 8th position (0 indexed), # which marks an efi boot entry as "active", so those are the only ones # we care to add to the list. # It *seems* like one could put mapfile at the end of the pipeline, but # each command gets run in a subshell, so the array is lost. (ref: SC2031) mapfile -t entrylist < <(efibootmgr | sed -n '/.\{8\}\*/p') # Add firmware interface entry if supported [[ -v fwboot ]] && entrylist+=("$biosname") # If we're in systemd-boot mode elif [[ ! -v efimode ]]; then # Put all systemd-boot loder entry confs into an array mapfile -t entrylist < <(systemctl --boot-loader-entry=help) # Only add the firmware interface to the list if booting to it is supported [[ -v fwboot ]] && entrylist+=("$biosname") fi # Get user selection select sel in "${entrylist[@]}"; do break done # If in efi mode and the user did not select the firmware config menu item, # then drop everything except for the BOOTNUM (character 4-8) [[ -v efimode && "$sel" != "$biosname" ]] && sel="${sel:4:4}" # Print result to stdout printf "%s" "$sel" } # Parse command line options while getopts ":en" opt; do case $opt in e) efimode=1 ;; n) noreboot=1 ;; \?) echo "E: Invalid option: -$OPTARG" >&2 exit 1 ;; esac done # If -e wasn't set, and systemd-boot isn't installed, fail over to efimode anyways if [[ ! -v efimode && ! -v sdboot ]]; then echo "W: systemd-boot not installed. Choosing EFI boot entries instead..." efimode=1 fi # If we're in EFI mode if [[ -v efimode ]]; then title="Pick EFI boot entry" # If we're in systemd-boot mode elif [[ ! -v efimode ]]; then title="Pick systemd-boot entry config" else echo "E: idk how you got here..." exit 1 fi # Specialize prompt for reboot mode if [[ -v noreboot ]]; then prompt="Entry for next boot:" elif [[ ! -v noreboot ]]; then prompt="Entry to boot IMMEDIATELY:" else echo "E: idk how you got here either..." exit 1 fi # Prompt for the user's choice choice="$(selectentry "$title" "$prompt")" # A special case to boot into firmware interface if [[ "$choice" == "$biosname" ]]; then sudo bootctl reboot-to-firmware true # For all other entry selections elif [[ "$choice" != "$biosname" ]]; then # If we're in EFI mode if [[ -v efimode ]]; then # Set bootnext in nvram sudo efibootmgr -q --bootnext "$choice" # If we're in systemd-boot mode elif [[ ! -v efimode ]]; then # Set default boot entry only for next boot sudo bootctl set-oneshot "$choice" # Add an option to speed past the boot menu, since we've already # chosen the desired entry. rebootopts+=("--boot-loader-menu=1") else echo "E: you DEFINITELY don't belong here..." exit 1 fi else echo "E: must you insist on breaking my things?" exit 1 fi # Reboot if necessary [[ ! -v noreboot ]] && sudo systemctl reboot "${rebootopts[@]}"