scripts/win.uefi.boot.sh

302 lines
8.2 KiB
Bash
Executable File
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/bin/sh
#
# Purpose {{{
# This script will reboot on Windows system
# 1. Try to get UEFI entry number for Windows.
# 2. Define it as default only for next boot.
# 3. Reboot (default) or poweroff the system.
# …
#
# 2023-08-18
# }}}
# Flags {{{
## Exit on error {{{
set -o errexit
## }}}
## Exit on unset var {{{
### Use "${VARNAME-}" to test a var that may not have been set
set -o nounset
## }}}
## Pipeline command is treated as failed {{{
### Not available in POSIX sh https://github.com/koalaman/shellcheck/wiki/SC3040
#set -o pipefail
## }}}
## Help with debugging {{{
### Call the script by prefixing it with "TRACE=1 ./script.sh"
if [ "${TRACE-0}" -eq 1 ]; then set -o xtrace; fi
## }}}
# }}}
# Vars {{{
PROGNAME=$(basename "${0}"); readonly PROGNAME
PROGDIR=$(readlink --canonicalize-missing $(dirname "${0}")); readonly PROGDIR
ARGS="${*}"; readonly ARGS
readonly NBARGS="${#}"
[ -z "${DEBUG-}" ] && DEBUG=1
## Export DEBUG for sub-script
export DEBUG
## Default values for some vars
readonly FLAG_REBOOT_DEFAULT="0"
readonly FLAG_POWEROFF_DEFAULT="1"
readonly WINDOWS_BASE_LABEL_DEFAULT="Windows"
## Colors
readonly PURPLE='\033[1;35m'
readonly RED='\033[0;31m'
readonly RESET='\033[0m'
readonly COLOR_DEBUG="${PURPLE}"
# }}}
usage() { # {{{
cat <<- HELP
usage: $PROGNAME [-d|-h|-l|-r|-s]
Try to reboot to Windows system.
EXAMPLES:
- Reboot to Windows system
${PROGNAME}
- Define Windows for next boot but poweroff the system
${PROGNAME} --poweroff
- Search for a specific Windows label
${PROGNAME} --label "Windows Boot Manager"
OPTIONS:
-d,--debug
Enable debug messages.
-h,--help
Print this help message.
-l,--label,--windows-label
Define a different label to search for Windows UEFI entry.
(default: ${WINDOWS_BASE_LABEL_DEFAULT})
-r,--reboot
Reboot the system (default behaviour).
-s,--shutdown,--poweroff,--halt
Ask to shutdown the system.
-u,--uefi,--uefi-entry
Define the UEFI entry to use.
(default: first matching from efibootmgr + windows-label)
HELP
}
# }}}
debug_message() { # {{{
local_debug_message="${1}"
## Print message if DEBUG is enable (=0)
[ "${DEBUG}" -eq "0" ] && printf '\e[1;35m%-6b\e[m\n' "DEBUG ${PROGNAME}: ${local_debug_message}"
unset local_debug_message
return 0
}
# }}}
error_message() { # {{{
local_error_message="${1}"
local_error_code="${2}"
## Print message
printf '%b\n' "ERROR ${PROGNAME}: ${RED}${local_error_message}${RESET}" >&2
unset local_error_message
exit "${local_error_code:=66}"
}
# }}}
define_vars() { # {{{
debug_message "-- Define vars BEGIN"
# If flag_reboot wasn't defined (argument) {{{
if [ -z "${flag_reboot-}" ]; then
## Use default value
readonly flag_reboot="${FLAG_REBOOT_DEFAULT}"
fi
# }}}
# If flag_poweroff wasn't defined (argument) {{{
if [ -z "${flag_poweroff-}" ]; then
## Use default value
readonly flag_poweroff="${FLAG_POWEROFF_DEFAULT}"
fi
# }}}
# If windows_base_label wasn't defined (argument) {{{
if [ -z "${windows_base_label-}" ]; then
## Use default value
readonly windows_base_label="${WINDOWS_BASE_LABEL_DEFAULT}"
fi
# }}}
# If windows_uefi_entry wasn't defined (argument) {{{
if [ -z "${windows_uefi_entry-}" ]; then
## Try to get the first matching entry with efibootmgr + windows_base_label
debug_message "||define_vars \
Try to get Windows UEFI entry with 'efibootmgr' + windows-label (${windows_base_label})."
windows_uefi_entry=$(efibootmgr | grep --extended-regexp --max-count=1 -- ".*${windows_base_label}.*" | cut --characters=5-8)
fi
# }}}
# If windows_uefi_entry remains empty {{{
if [ -z "${windows_uefi_entry-}" ]; then
error_message "windows_uefi_entry seems empty! Verify the windows_base_label used (${windows_base_label}) and your UEFI configuration ('efibootmgr -v')." 11
elif [ -n "${windows_uefi_entry}" ]; then
debug_message "||define_vars \
The ${RED}${windows_uefi_entry}${COLOR_DEBUG} UEFI entry will be used for Windows."
else
error_message "I am not supposed to happen!" 12
fi
# }}}
debug_message "-- Define vars END"
}
# }}}
is_command_available() { # {{{
local_command_available_cmd="${1}"
debug_prefix="${2:-}"
## Return False by default
return_command_available="1"
if [ "$(command -v ${local_command_available_cmd})" ]; then
debug_message "${debug_prefix}is_command_available \
${RED}${local_command_available_cmd}${COLOR_DEBUG} seems present on this host."
return_command_available="0"
else
debug_message "${debug_prefix}is_command_available \
${RED}${local_command_available_cmd}${COLOR_DEBUG} is not available on this host."
return_command_available="1"
fi
unset local_command_available_cmd
unset debug_prefix
return "${return_command_available}"
}
# }}}
main() { # {{{
debug_message "--- MAIN BEGIN"
## If a command is missing {{{
### Exit with error message
is_command_available "efibootmgr" "| " \
|| error_message "No test_me command available. Please install efibootmgr package with your package manager." 01
## }}}
## Define all vars
define_vars
## If the expected UEFI entry doesn't exists {{{
if ! sudo efibootmgr | grep --quiet -- "Boot${windows_uefi_entry}"; then
error_message "The expected UEFI entry (${windows_uefi_entry}) doesn't seem to exist…" 21
fi
## }}}
## Define next boot entry
sudo efibootmgr --quiet --bootnext "${windows_uefi_entry}"
## If BootNext entry doesn't match {{{
if ! sudo efibootmgr | grep --quiet -- "BootNext: ${windows_uefi_entry}"; then
error_message "The expected UEFI entry (${windows_uefi_entry}) doesn't seem to be the next one (see 'sudo efibootmgr' BootNext entry)." 22
fi
## }}}
printf '%b' "Reboot/shutdown as requested to winbouse partition\\n"
[ "${flag_reboot}" -eq "0" ] && sudo systemctl reboot
[ "${flag_poweroff}" -eq "0" ] && sudo systemctl poweroff
debug_message "--- MAIN END"
}
# }}}
# Manage arguments # {{{
# This code can't be in a function due to argument management
if [ ! "${NBARGS}" -eq "0" ]; then
manage_arg="0"
## If the first argument ask for help (h|help|-h|-help|-*h|-*help) {{{
if printf -- '%s' "${1-}" | grep --quiet --extended-regexp -- "^-*h(elp)?$"; then
usage
exit 0
fi
## }}}
## If the first argument is not an option
if ! printf -- '%s' "${1}" | grep --quiet --extended-regexp -- "^-+";
then
## Print help message and exit
printf '%b\n' "${RED}Invalid option: ${1}${RESET}"
printf '%b\n' "---"
usage
exit 1
fi
# Parse all options (start with a "-") one by one
while printf -- '%s' "${1-}" | grep --quiet --extended-regexp -- "^-+"; do
case "${1}" in
-d|--debug ) ## debug
DEBUG=0
debug_message "--- Manage argument BEGIN"
;;
-h|--help ) ## help message (if it's not the first option)
usage
exit 0
;;
-l|--label|--windows-label ) ## Set windows_base_label var
## Move to the next argument
shift
## Define var
readonly windows_base_label="${1}"
;;
-r|--reboot ) ## If a reboot was requested (default behaviour)
flag_reboot="0"
flag_poweroff="1"
;;
-s|--shutdown|--poweroff|--halt ) ## If a poweroff was requested
flag_reboot="1"
flag_poweroff="0"
;;
-u|--uefi|--uefi-entry ) ## Set windows_uefi_entry var
## Move to the next argument
shift
## Define var
readonly windows_uefi_entry="${1}"
;;
* ) ## unknow option
printf '%b\n' "${RED}Invalid option: ${1}${RESET}"
printf '%b\n' "---"
usage
exit 1
;;
esac
debug_message "| ${RED}${1}${COLOR_DEBUG} option managed."
## Move to the next argument
shift
manage_arg=$((manage_arg+1))
done
debug_message "| ${RED}${manage_arg}${COLOR_DEBUG} argument(s) successfully managed."
else
debug_message "| No arguments/options to manage."
fi
debug_message "--- Manage argument END"
# }}}
main
exit 255