Description
I've been working on getting Xen supported as a bootable payload via Limine for NixOS in this PR.
The short version is that Limine currently (and may not want to) support the EFI Boot Services Multiboot2 tag, and the EFI Boot Service is exited and memory remapped for all payloads. This prevents Xen from booting in a UEFI environment via multiboot2. Booting via the efi
protocol works fine, however requires a bunch of extra configuration explained in the above PR. It'd be great to be able to consistently use multiboot2
regardless of BIOS or UEFI to boot Xen under Limine.
With that said, here's the long version, with some more background of what I've already looked into:
As part of initial testing, I found that multiboot2
would not boot Xen under BIOS or UEFI, however I was able to use multiboot1
on BIOS systems successfully. I raised #482 which was resolved by c8cdc9e and 80912a3. I've tested and under both BIOS and UEFI the original error is resolved. However, I have only been able to successfully boot Xen under BIOS via multiboot2. The UEFI version of Limine gets further, however after several days of snooping around source code and serial consoles, I managed to catch the message ERR: Bootloader shutdown EFI x64 boot services! (via Serial console)
from the Xen kernel.
This message occurs because Xen requires, when booted under UEFI, via multiboot2, that the EFI Boot Service is left running (i.e. in Limine this happens via the efi_exit_boot_services()
call in multiboot2.c
. I've done a bunch of reading into why Xen needs this, and how it's handled in GRUB, and the short version is: It's a horrible, cursed workaround to accomodate Xen needing access to the EFI Boot Service & original memory map so it can work out the usage for certain allocated ranges in memory.
In GRUB, a special Multiboot2 tag was added to the spec to indicate that the Multiboot2 kernel requests that the EFI Boot Service is retained and not exited prior to passing control to the Kernel. There's some history here and the GRUB source code in grub-core/loader/multiboot_mbi2.c
shows a good chunk of the logic of how GRUB handles this (the keep_bs
variable is indicative that the Boot Service should be kept running in this file).
I took a very crude attempt at testing whether I could get this working by adding a config flag keep_boot_service
to the multiboot2 provider, which prevented the call to efi_exit_boot_services
. Additionally, I also (as a total hack to see how far I could get, I know this isn't the correct approach) converted the panic()
for get_raw_memmap called whilst in boot services
into a simple warning using print
. So whilst this does seem like it prevented the call to efi_exit_boot_services
when set, I think because the memory was still being remapped in multiboot2.c
Xen still couldn't see the Boot Service and failed with the same error message. So I think the unmodified memory map would need to be passed to Xen, and the EFI Boot Service kept running to support this. Ideally, it should only happen if the prior mentioned boot tag was present.
I'd previously provided these binaries as reference, so I'll link them again. These binaries should exhibit this behaviour: https://junkyard.systems/limine-nixos-test-binaries.tar.xz (I had to configure Xen to log to serial with console=com1 com1=115200,8n1
so I could catch the log message I mentioned earlier.