Saturday, April 15, 2023

Automatically set Linux as first boot option

Having two operating systems (Linux and Windows 10) I get annoying problem - WIndows 10 keep settings itself first boot option instead of what I wanted. After selecting Linux manually at UEFI boot menu I want it to set itself first again. Following script and systemd service file allows to check boot order in UEFI and set Linux as first boot

 

Script named "BootFirst" and located in "/etc/systemd/system/scripts":

 #!/bin/bash

#Name=${1:-shell}
Name="${1}"
Result=0

if [[ -z "$Name" ]] # if empty
then
    Name="Linux"
fi

readarray -t BootInfo < <(efibootmgr)
BootOrder=$(printf -- '%s\n' "${BootInfo[@]}" | grep -P "^BootOrder: " | perl -pe 's/^BootOrder:\s+(.*)$/\1/')
IFS=',' read -ra BootOrder <<< "$BootOrder"

FirstBootNumber=${BootOrder[0]}
SelectedBootNumber="$(printf -- '%s\n' "${BootInfo[@]}" | grep -im1 $Name | perl -p -e 's/^Boot(\d{4}).*$/\1/g')"
if [[ -n "$SelectedBootNumber" ]] && [[ -n "$FirstBootNumber" ]] # if found
then
    if [[ ! $SelectedBootNumber = $FirstBootNumber ]]; then
        First=$(printf -- '%s\n' "${BootOrder[@]}" | grep -nm1 "$FirstBootNumber" | cut -f1 -d":")
        ((First--))
        Selected=$(printf -- '%s\n' "${BootOrder[@]}" | grep -nm1 "$SelectedBootNumber" | cut -f1 -d":")
        ((Selected--))
        Tmp="${BootOrder[First]}"
        BootOrder[First]="${BootOrder[Selected]}"
        BootOrder[Selected]="$Tmp"
        efibootmgr -o "$(printf -- '%s,' "${BootOrder[@]}"| perl -pe 's/^(.*),$/\1/')"
        Result=$?
        if (( Result == 0 ))
        then
            echo "Have set new boot order"
        fi
    else
        echo "Boot order is correct"
    fi
else
    echo "Error: found no entries that match '$Name'"
    exit 1
fi
if (( Result != 0 ))
then
    echo "Failed: exiting with nothing"
fi


Systemd service file named "boot-order.service":

[Unit]
Description=Set Linux as the first boot option
#After=

[Service]
Type=oneshot
ExecStart=/etc/systemd/system/scripts/BootFirst

[Install]
WantedBy=multi-user.target

After making this files run:

systemctl daemon-reload

systemctl enable boot-order.service