From 9626dfb4e1123d75c3efd1bc8cd085e2130bea76 Mon Sep 17 00:00:00 2001 From: Philipp Schuster Date: Sun, 6 Apr 2025 19:56:20 +0200 Subject: [PATCH 1/2] uefi/doc: improve documentation of exit_boot_services TL;DR: Document why exit_boot_services needs to do more than just call the UEFI function. Exiting UEFI boot services requires a non-trivial sequence of steps, including safe retrieval and finalization of the memory map. To clarify why our exit_boot_services function is more than a thin wrapper, the documentation has been updated accordingly. This complexity is also reflected in the Linux source code [0]. In fact, the sequence of steps uefi-rs uses is inspired by the Linux source code. [0] https://github.com/torvalds/linux/blob/e544a0743/drivers/firmware/efi/libstub/efi-stub-helper.c#L375 --- uefi/src/boot.rs | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/uefi/src/boot.rs b/uefi/src/boot.rs index 4c44bef55..1f0f7b283 100644 --- a/uefi/src/boot.rs +++ b/uefi/src/boot.rs @@ -1258,17 +1258,23 @@ unsafe fn get_memory_map_and_exit_boot_services(buf: &mut [u8]) -> Result Date: Sun, 6 Apr 2025 20:08:25 +0200 Subject: [PATCH 2/2] uefi: change signature of exit_boot_services People probably want to use 99% of the time LOADER_DATA here. Therefore, we indicate in our function signature, that people should use the default (`None`) if they are unsure what to do here. LOADER_DATA is also what Linux uses [0]. [0] https://elixir.bootlin.com/linux/v6.13.7/source/drivers/firmware/efi/libstub/mem.c#L24 --- uefi-test-runner/src/main.rs | 4 ++-- uefi/CHANGELOG.md | 2 ++ uefi/src/boot.rs | 12 +++++++++++- 3 files changed, 15 insertions(+), 3 deletions(-) diff --git a/uefi-test-runner/src/main.rs b/uefi-test-runner/src/main.rs index bcbbb0f8e..2e45d8438 100644 --- a/uefi-test-runner/src/main.rs +++ b/uefi-test-runner/src/main.rs @@ -10,7 +10,7 @@ extern crate alloc; use alloc::string::ToString; use alloc::vec::Vec; -use uefi::mem::memory_map::{MemoryMap, MemoryType}; +use uefi::mem::memory_map::MemoryMap; use uefi::prelude::*; use uefi::proto::console::serial::Serial; use uefi::proto::device_path::build::{self, DevicePathBuilder}; @@ -209,7 +209,7 @@ fn shutdown() -> ! { info!("Testing complete, exiting boot services..."); // Exit boot services as a proof that it works :) - let mmap = unsafe { uefi::boot::exit_boot_services(MemoryType::LOADER_DATA) }; + let mmap = unsafe { uefi::boot::exit_boot_services(None) }; info!("Memory Map:"); for desc in mmap.entries() { diff --git a/uefi/CHANGELOG.md b/uefi/CHANGELOG.md index dfb07a075..0d059b9d9 100644 --- a/uefi/CHANGELOG.md +++ b/uefi/CHANGELOG.md @@ -16,6 +16,8 @@ `&self`. - **Breaking:** The `pxe::Mode` struct is now opaque. Use method calls to access mode data instead of direct field access. +- **Breaking:** `exit_boot_services` now consumes a `Option` which + defaults to the recommended value of `MemoryType::LOADER_DATA`. - `boot::memory_map()` will never return `Status::BUFFER_TOO_SMALL` from now on, as this is considered a hard internal error where users can't do anything about it anyway. It will panic instead. diff --git a/uefi/src/boot.rs b/uefi/src/boot.rs index 1f0f7b283..d36e59dae 100644 --- a/uefi/src/boot.rs +++ b/uefi/src/boot.rs @@ -1283,6 +1283,13 @@ unsafe fn get_memory_map_and_exit_boot_services(buf: &mut [u8]) -> Result Result MemoryMapOwned { +pub unsafe fn exit_boot_services(custom_memory_type: Option) -> MemoryMapOwned { + // LOADER_DATA is the default and also used by the Linux kernel: + // https://elixir.bootlin.com/linux/v6.13.7/source/drivers/firmware/efi/libstub/mem.c#L24 + let memory_type = custom_memory_type.unwrap_or(MemoryType::LOADER_DATA); crate::helpers::exit(); let mut buf = MemoryMapBackingMemory::new(memory_type).expect("Failed to allocate memory");