I am very interested in trying out OpenBSD on my machine as a desktop system.
I flashed install60.fs to a pendrive, and attempted to boot my amd64 UEFI system with it. It displays the kernel entry point information, followed by the message "ExitBootServices" and then instantly reboots the machine. Here is the code where the problem happens: http://cvsweb.openbsd.org/cgi-bin/cvsweb/src/sys/arch/amd64/stand/efiboot/efiboot.c?rev=1.14&content-type=text/x-cvsweb-markup void efi_cleanup(void) { EFI_STATUS status; efi_memprobe_internal(); /* sync the current map */ status = EFI_CALL(BS->ExitBootServices, IH, mmap_key); if (status != EFI_SUCCESS) panic("ExitBootServices"); } I spliced in some debugging code and found that the call to ExitBootServices is returning a status code of 2 (EFI_INVALID_PARAMETER), which causes the panic and reboot. Here's a description of this problem in the UEFI Specification [1] (page 221): "An EFI OS loader must ensure that it has the system's current memory map at the time it calls ExitBootServices(). This is done by passing in the current memory map's MapKey value as returned by EFI_BOOT_SERVICES.GetMemoryMap(). Care must be taken to ensure that the memory map does not change between these two calls. It is suggested that GetMemoryMap() be called immediately before calling ExitBootServices(). If MapKey value is incorrect, ExitBootServices() returns EFI_INVALID_PARAMETER and GetMemoryMap() with ExitBootServices() must be called again." I spliced in some more debugging code and found that the MapKey value (mmap_key) does indeed change during the call to ExitBootServices. That isolates the problem: ExitBootServices is changing the memory map. The simple solution seems to be to just retry calling GetMemoryMap to get the updated MapKey, and then call ExitBootServices a second time. However, I did some more research before attempting this solution on my machine. I found this quote from a Linux mailing list archive where they were discussing the same issue [2]: "ExitBootServices() can legitimately fail if any of the event handlers that are signaled by its invocation change the memory map. In that case, we need to get the memory map and exit boot services again. Only retry once so that we don't get stuck if ExitBootServices() is returning a genuine error value." This tells me that it's normal behaviour for ExitBootServices to fail in such a way, so I am more confident that this is a legitimate bug and the code needs to be prepared to call ExitBootServices a second time in case of failure. I also found some more directly relevant quotes where the same problem was being discussed in relation to FreeBSD [3]: "[the solution] Is not quite that easy -- the memory map itself is passed as module metadata to the kernel (bi_load_efi_data), so that needs to be redone as well." I did some more investigating and found that this appears to be the case in OpenBSD too: http://cvsweb.openbsd.org/cgi-bin/cvsweb/src/sys/arch/amd64/stand/libsa/exec_i386.c?rev=1.18&content-type=text/x-cvsweb-markup /* Pass memory map to the kernel */ mem_pass(); and shortly afterwards: /* * Move the loaded kernel image to the usual place after calling * ExitBootServices(). */ delta = DEFAULT_KERNEL_ADDRESS - efi_loadaddr; efi_cleanup(); It appears that the memory map is passed to the kernel before calling ExitBootServices (which changes the memory map again, leaving the kernel with an obsolete copy). I am very hesitant to attempt any self-made solutions to this problem after reading this quote, again from [3]: "... if the memory map has actually changed the kernel will now possibly corrupt firmware data (or the firmware will corrupt OS/user data)." It seems that a proper and safe solution may require rearranging a significant chunk of code to ensure that ExitBootServices is successfully called prior to passing the memory map to the kernel. At least, that's my take on it. I am not a strong coder and nowhere near experienced enough to attempt any such fixes myself, so I thought it would be best to send this in as a bug report. [1] (www.uefi.org/sites/default/files/resources/UEFI%202_5.pdf) [2] (http://www.gossamer-threads.com/lists/linux/kernel/1727968) [3] (https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=202455)
