UEFI bootloader not respecting spec when calling `ExitBootServices()`
Hello, it is my first time here!
I am encountering the following issue trying to boot Redox in UEFI mode on some laptop: When calling ExitBootServices
from the UEFI system map, this function may return an InvalidParameter error. When this happens, currently, the Redox bootloader simply panics away.
However, this is not supposed to be a fatal error. See the relevant specification which is located here: https://uefi.org/specs/UEFI/2.9_A/07_Services_Boot_Services.html?highlight=exitbootservices#efi-boot-services-exitbootservices
As far as I can tell, what should happen when this error code is returned is reloading the memory map. (obtaining a new handle for it). And then calling that function again so the firmware actually relinquishes the memory allocated for boot time services.
I have only gotten the bad behavior on a laptop from 2012. Not sure how many dragons lie in the "early days of UEFI" in the consumer market...
One interesting thing is I think allocating memory via the UEFI facilities actually invalidates the memory map. (I have not double-checked that against the specification, but there's a random comment about it in some Linux code.
With the current design of the MemoryMapIter
, its construction does create a Vec, call GetMemoryMap
, then resize the vec, and then return the struct. Rust is still a bit new to me (coming from C++... But I am pretty sure truncating the Vec should reallocate an array of the exact size for the data and move it there?)
Also, I have not yet familiarized myself with where this Vec
implementation actually comes from (I see we have a crate somewhere that is a global UEFI allocator? That a thread to pull on).
So far, I have played with the code a bit, and tried (in case of error) to implement the retry behavior, with no allocations between GetMemoryMap
and ExitBootServices
once the error occurs.
The problem is that then it hangs the bootloader on that specific machine inside the 2nd call to ExitBootServices
So that was not very successful.
The next thing I may try is to attempt rewriting the memory map so it does not need to do the realoc in the first place... To see if that unstuck me.
In all cases, at the very least the error from that call should be handled gracefully (at least one retry, and not just expecting it away). I may try to propose that patch soon. So that call actually follows what is stated in the UEFI specification.