while USB booting works, it is a bit fragile, because one needs to be careful
not to overwrite that boot drive (especially when testing system
installations). So, I developed a workaround: setting a BootNext EFI variable
(selecting the alternative boot option for just the next startup) and
rebooting. Unfortunately, Grub itself does not have a function to set EFI
variables (it can only read them), but building Linux + minimal initrd with
relevant tools is rather easy. By the way, if I were starting Linux anyway, I
could simply kexec the target kernel from the NVMe disk using Linux’s drivers,
but I wanted the actual startup to remain closer to the “normal” startup,
including respecting the relevant Grub configuration.
There was one final problem to solve. When installing Qubes OS, it will set
itself as the default boot target. This means that all of the above boot
options will be overridden by the installer. To solve this issue, I passed a
kickstart file to the installer that restores the original boot order at the
very last step (%post script).
To summarize, I now had:
A way to load Grub2 on each test system (either via PXE or via iPXE loaded
from a USB stick)
A way to conveniently control which OS Grub2 will start
A way to load a local kernel even if Grub2 does not see the disk