# This script is called by ./xen-dom0.nix to create the Xen boot entries.
# shellcheck shell=bash
# Handle input argument and exit if the flag is invalid. See virtualisation.xen.efi.bootBuilderVerbosity below.
[[$# -ne 1]]&&echo -e "\e[1;31merror:\e[0m xenBootBuilder must be called with exactly one verbosity argument. See the \e[1;34mvirtualisation.xen.efi.bootBuilderVerbosity\e[0m option."&&exit1
"debug")echo -e "\e[1;34mxenBootBuilder:\e[0m called with the '$1' flag";;
*)
echo -e "\e[1;31merror:\e[0m xenBootBuilder was called with an invalid argument. See the \e[1;34mvirtualisation.xen.efi.bootBuilderVerbosity\e[0m option."
exit2
;;
esac
# Get the current Xen generations and store them in an array. This will be used
# for displaying the diff later, if xenBootBuilder was called with `info`.
# We also delete the current Xen entries here, as they'll be rebuilt later if
# the corresponding NixOS generation still exists.
mapfile -t preGenerations < <(find "$efiMountPoint"/loader/entries -type f -name 'xen-*.conf'| sort -V | sed 's_/loader/entries/nixos_/loader/entries/xen_g;s_^.*/xen_xen_g;s_.conf$__g')
if["$1"="debug"];then
if((${#preGenerations[@]}== 0));then
echo -e "\e[1;34mxenBootBuilder:\e[0m no previous Xen entries."
else
echo -e "\e[1;34mxenBootBuilder:\e[0m deleting the following stale xen entries:"&&for debugGen in "${preGenerations[@]}";doecho" - $debugGen";done
# We do nothing if the Bootspec for the current $gen does not contain the Xen
# extension, which is added as a configuration attribute below.
if grep -sq '"org.xenproject.bootspec.v1"'"$bootspecFile";then
["$1"="debug"]&&echo -e " \e[1;32msuccess:\e[0m found Xen entries in $gen."
# TODO: Support DeviceTree booting. Xen has some special handling for DeviceTree
# attributes, which will need to be translated in a boot script similar to this
# one. Having a DeviceTree entry is rare, and it is not always required for a
# successful boot, so we don't fail here, only warn with `debug`.
if grep -sq '"devicetree"'"$bootspecFile";then
echo -e "\n\e[1;33mwarning:\e[0m $gen has a \e[1;34morg.nixos.systemd-boot.devicetree\e[0m Bootspec entry. Xen currently does not support DeviceTree, so this value will be ignored in the Xen boot entries, which may cause them to \e[1;31mfail to boot\e[0m."
else
["$1"="debug"]&&echo -e "\e[1;34mxenBootBuilder:\e[0m no DeviceTree entries found in $gen."
fi
# Prepare required attributes for `xen.cfg/xen.conf`. It inherits the name of
# the corresponding nixos generation, substituting `nixos` with `xen`:
# Sometimes, garbage collection weirdness causes a generation to still exist in
# the loader entries, but its Bootspec file was deleted. We consider such a
# generation to be invalid, but we don't write extra code to handle this
# situation, as supressing grep's error messages above is quite enough, and the
# error message below is still technically correct, as no Xen can be found in
# something that does not exist.
else
["$1"="debug"]&&echo -e " \e[1;33mwarning:\e[0m \e[1;31mno Xen found\e[0m in $gen."
fi
done
# Counterpart to the preGenerations array above. We use it to diff the
# generations created/deleted when callled with the `info` argument.
mapfile -t postGenerations < <(find "$efiMountPoint"/loader/entries -type f -name 'xen-*.conf'| sort -V | sed 's_/loader/entries/nixos_/loader/entries/xen_g;s_^.*/xen_xen_g;s_.conf$__g')
# In the event the script does nothing, guide the user to debug, as it'll only
# ever run when Xen is enabled, and it makes no sense to enable Xen and not have
# any hypervisor boot entries.
if((${#postGenerations[@]}== 0));then
case"$1" in
"default"|"info")echo"none found."&&echo -e "If you believe this is an error, set the \e[1;34mvirtualisation.xen.efi.bootBuilderVerbosity\e[0m option to \e[1;34m\"debug\"\e[0m and rebuild to print debug logs.";;
"debug")echo -e "\e[1;34mxenBootBuilder:\e[0m wrote \e[1;31mno generations\e[0m. Most likely, there were no generations with a valid \e[1;34morg.xenproject.bootspec.v1\e[0m entry.";;
esac
# If the script is successful, change the default boot, say "done.", write a
# diff, or print the total files written, depending on the argument this script
# was called with. We use some dumb dependencies here, like `diff` or `bat` for
# colourisation, but they're only included with the `info` argument.
#
# It's also fine to change the default here, as this runs after the
# `systemd-boot-builder.py` script, which overwrites the file, and this script
# does not run after an user disables the Xen module.
else
sed --in-place 's/^default nixos-/default xen-/g'"$efiMountPoint"/loader/loader.conf
case"$1" in
"default"|"info")echo"done.";;
"debug")echo -e "\e[1;34mxenBootBuilder:\e[0m \e[1;32msuccessfully wrote\e[0m the following generations:"&&for debugGen in "${postGenerations[@]}";doecho" - $debugGen";done;;