From d4a57c4f7df20cd9872e1cd5165eec8ea01e1e7d Mon Sep 17 00:00:00 2001 From: "Vineel Kovvuri[MSFT]" Date: Fri, 5 Jun 2026 15:11:45 -0700 Subject: [PATCH] Migrate to R-EFI 6.0 --- Cargo.toml | 19 +- HidPkg/UefiHidDxe/src/driver_binding.rs | 52 ++-- HidPkg/UefiHidDxe/src/hid.rs | 36 ++- HidPkg/UefiHidDxe/src/key_queue.rs | 5 +- HidPkg/UefiHidDxe/src/keyboard.rs | 272 +++++++++++------- HidPkg/UefiHidDxe/src/pointer.rs | 76 +++-- HidPkg/UefiHidDxeV2/src/boot_services.rs | 70 ++++- HidPkg/UefiHidDxeV2/src/driver_binding.rs | 8 +- HidPkg/UefiHidDxeV2/src/keyboard.rs | 73 +++-- .../src/keyboard/simple_text_in_ex.rs | 4 +- .../RustBootServicesAllocatorDxe/src/lib.rs | 36 ++- 11 files changed, 425 insertions(+), 226 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index b863b6c63d..f78bdc34c6 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -15,18 +15,17 @@ members = [ HidIo = { path = "HidPkg/Crates/HidIo" } hidparser = { version = "1" } HiiKeyboardLayout = { path = "HidPkg/Crates/HiiKeyboardLayout" } -mu_pi = { version = "6" } -mu_rust_helpers = { version = "3" } +memoffset = "0.9.0" +mockall = {version = "0.14.0"} +mu_pi = { version = "7" } +mu_rust_helpers = { version = "4" } MuTelemetryHelperLib = { path = "MsWheaPkg/Crates/MuTelemetryHelperLib" } +num-derive = { version = "0.4", default-features = false } +num-traits = { version = "0.2", default-features = false } +patina = { version = "22" } +r-efi = "^6" RustAdvancedLoggerDxe = { path = "AdvLoggerPkg/Crates/RustAdvancedLoggerDxe" } RustBootServicesAllocatorDxe = { path = "MsCorePkg/Crates/RustBootServicesAllocatorDxe" } -patina = { version = "21" } -mockall = {version = "0.14.0"} - -memoffset = "0.9.0" -num-traits = { version = "0.2", default-features = false } -num-derive = { version = "0.4", default-features = false } -r-efi = "5.0.0" rustversion = "1.0.14" -spin = "0.10.0" scroll = { version = "0.13", default-features = false, features = ["derive"] } +spin = "0.10.0" diff --git a/HidPkg/UefiHidDxe/src/driver_binding.rs b/HidPkg/UefiHidDxe/src/driver_binding.rs index 422d04e19b..a090ba453b 100644 --- a/HidPkg/UefiHidDxe/src/driver_binding.rs +++ b/HidPkg/UefiHidDxe/src/driver_binding.rs @@ -36,12 +36,16 @@ pub fn initialize_driver_binding(image_handle: efi::Handle) -> Result<(), efi::S driver_binding_handle, })); - let status = (boot_services.install_protocol_interface)( - core::ptr::addr_of_mut!(driver_binding_handle), - &driver_binding::PROTOCOL_GUID as *const efi::Guid as *mut efi::Guid, - efi::NATIVE_INTERFACE, - driver_binding_ptr as *mut c_void, - ); + // SAFETY: `boot_services` references a valid Boot Services table and the arguments below are valid + // for installing the driver binding protocol. + let status = unsafe { + (boot_services.install_protocol_interface)( + core::ptr::addr_of_mut!(driver_binding_handle), + &driver_binding::PROTOCOL_GUID as *const efi::Guid as *mut efi::Guid, + efi::NATIVE_INTERFACE, + driver_binding_ptr as *mut c_void, + ) + }; if status.is_error() { drop(unsafe { Box::from_raw(driver_binding_ptr) }); @@ -77,14 +81,18 @@ extern "efiapi" fn uefi_hid_driver_binding_supported( // Check to see if this controller is supported by attempting to open HidIo on it. let mut hid_io_ptr: *mut hid_io::protocol::Protocol = core::ptr::null_mut(); - let status = (boot_services.open_protocol)( - controller, - &hid_io::protocol::GUID as *const efi::Guid as *mut efi::Guid, - core::ptr::addr_of_mut!(hid_io_ptr) as *mut *mut c_void, - driver_binding.driver_binding_handle, - controller, - efi::OPEN_PROTOCOL_BY_DRIVER, - ); + // SAFETY: `boot_services` references a valid Boot Services table and the arguments below are valid + // for opening the HidIo protocol on `controller`. + let status = unsafe { + (boot_services.open_protocol)( + controller, + &hid_io::protocol::GUID as *const efi::Guid as *mut efi::Guid, + core::ptr::addr_of_mut!(hid_io_ptr) as *mut *mut c_void, + driver_binding.driver_binding_handle, + controller, + efi::OPEN_PROTOCOL_BY_DRIVER, + ) + }; // if HidIo could not be opened then it is either in use or not present. if status.is_error() { @@ -93,12 +101,16 @@ extern "efiapi" fn uefi_hid_driver_binding_supported( // HidIo is available, so this controller is supported. Further checking that requires actual device interaction is // done in uefi_hid_driver_binding_start. close the protocol used for the supported test and exit with success. - let status = (boot_services.close_protocol)( - controller, - &hid_io::protocol::GUID as *const efi::Guid as *mut efi::Guid, - driver_binding.driver_binding_handle, - controller, - ); + // SAFETY: `boot_services` references a valid Boot Services table and the arguments below match the + // protocol opened above. + let status = unsafe { + (boot_services.close_protocol)( + controller, + &hid_io::protocol::GUID as *const efi::Guid as *mut efi::Guid, + driver_binding.driver_binding_handle, + controller, + ) + }; if status.is_error() { debugln!(DEBUG_ERROR, "Unexpected error from CloseProtocol: {:?}", status); //message, but no further action to handle. diff --git a/HidPkg/UefiHidDxe/src/hid.rs b/HidPkg/UefiHidDxe/src/hid.rs index 21e8d46fda..a9c8995de0 100644 --- a/HidPkg/UefiHidDxe/src/hid.rs +++ b/HidPkg/UefiHidDxe/src/hid.rs @@ -33,14 +33,18 @@ pub fn initialize(controller: efi::Handle, driver_binding: &driver_binding::Prot // retrieve the HidIo instance for the given controller. let mut hid_io_ptr: *mut hid_io::protocol::Protocol = core::ptr::null_mut(); - let status = (boot_services.open_protocol)( - controller, - &hid_io::protocol::GUID as *const efi::Guid as *mut efi::Guid, - core::ptr::addr_of_mut!(hid_io_ptr) as *mut *mut c_void, - driver_binding.driver_binding_handle, - controller, - system::OPEN_PROTOCOL_BY_DRIVER, - ); + // SAFETY: `boot_services` references a valid Boot Services table and the arguments below are valid + // for opening the HidIo protocol on `controller`. + let status = unsafe { + (boot_services.open_protocol)( + controller, + &hid_io::protocol::GUID as *const efi::Guid as *mut efi::Guid, + core::ptr::addr_of_mut!(hid_io_ptr) as *mut *mut c_void, + driver_binding.driver_binding_handle, + controller, + system::OPEN_PROTOCOL_BY_DRIVER, + ) + }; if status.is_error() { debugln!(DEBUG_ERROR, "[hid::initialize] Unexpected error opening HidIo protocol: {:#?}", status); return Err(status); @@ -185,12 +189,16 @@ fn release_hid_io(controller: efi::Handle, driver_binding: &driver_binding::Prot let boot_services = unsafe { BOOT_SERVICES.as_mut().expect("BOOT_SERVICES not properly initialized") }; // release HidIo - match (boot_services.close_protocol)( - controller, - &hid_io::protocol::GUID as *const efi::Guid as *mut efi::Guid, - driver_binding.driver_binding_handle, - controller, - ) { + // SAFETY: `boot_services` references a valid Boot Services table and the arguments below match the + // HidIo protocol opened on `controller`. + match unsafe { + (boot_services.close_protocol)( + controller, + &hid_io::protocol::GUID as *const efi::Guid as *mut efi::Guid, + driver_binding.driver_binding_handle, + controller, + ) + } { efi::Status::SUCCESS => (), err => { debugln!( diff --git a/HidPkg/UefiHidDxe/src/key_queue.rs b/HidPkg/UefiHidDxe/src/key_queue.rs index fecdf18bf0..62c00a9293 100644 --- a/HidPkg/UefiHidDxe/src/key_queue.rs +++ b/HidPkg/UefiHidDxe/src/key_queue.rs @@ -219,7 +219,10 @@ impl KeyQueue { { debugln!(DEBUG_WARN, "Ctrl-Alt-Del pressed, resetting system."); if let Some(runtime_services) = unsafe { RUNTIME_SERVICES.as_mut() } { - (runtime_services.reset_system)(efi::RESET_WARM, efi::Status::SUCCESS, 0, core::ptr::null_mut()); + // SAFETY: `runtime_services` references a valid Runtime Services table. + unsafe { + (runtime_services.reset_system)(efi::RESET_WARM, efi::Status::SUCCESS, 0, core::ptr::null_mut()); + } } panic!("Reset failed."); } diff --git a/HidPkg/UefiHidDxe/src/keyboard.rs b/HidPkg/UefiHidDxe/src/keyboard.rs index b32137ad68..588e7ecae1 100644 --- a/HidPkg/UefiHidDxe/src/keyboard.rs +++ b/HidPkg/UefiHidDxe/src/keyboard.rs @@ -251,13 +251,17 @@ impl KeyboardHandler { let context = unsafe { context_ptr.as_mut().expect("freshly boxed context pointer is null") }; //create wait_for_key events. let mut wait_for_key_event: efi::Event = core::ptr::null_mut(); - let status = (boot_services.create_event)( - system::EVT_NOTIFY_WAIT, - system::TPL_NOTIFY, - Some(wait_for_key), - context_ptr as *mut c_void, - core::ptr::addr_of_mut!(wait_for_key_event), - ); + // SAFETY: `boot_services` references a valid Boot Services table; `context_ptr` and the event + // out-pointer are valid for the duration of the call. + let status = unsafe { + (boot_services.create_event)( + system::EVT_NOTIFY_WAIT, + system::TPL_NOTIFY, + Some(wait_for_key), + context_ptr as *mut c_void, + core::ptr::addr_of_mut!(wait_for_key_event), + ) + }; if status.is_error() { drop(unsafe { Box::from_raw(context_ptr) }); return Err(status); @@ -265,15 +269,20 @@ impl KeyboardHandler { context.simple_text_in.wait_for_key = wait_for_key_event; let mut wait_for_key_ex_event: efi::Event = core::ptr::null_mut(); - let status = (boot_services.create_event)( - system::EVT_NOTIFY_WAIT, - system::TPL_NOTIFY, - Some(wait_for_key), - context_ptr as *mut c_void, - core::ptr::addr_of_mut!(wait_for_key_ex_event), - ); + // SAFETY: `boot_services` references a valid Boot Services table; `context_ptr` and the event + // out-pointer are valid for the duration of the call. + let status = unsafe { + (boot_services.create_event)( + system::EVT_NOTIFY_WAIT, + system::TPL_NOTIFY, + Some(wait_for_key), + context_ptr as *mut c_void, + core::ptr::addr_of_mut!(wait_for_key_ex_event), + ) + }; if status.is_error() { - (boot_services.close_event)(wait_for_key_event); + // SAFETY: `wait_for_key_event` was created successfully above. + unsafe { (boot_services.close_event)(wait_for_key_event) }; drop(unsafe { Box::from_raw(context_ptr) }); return Err(status); } @@ -283,16 +292,23 @@ impl KeyboardHandler { //per UEFI spec 2.10 section 12.2.5. The keyboard handler interfaces may run at a higher TPL, so this event is used //to dispatch the key notifies at the required TPL level. let mut key_notify_event: efi::Event = core::ptr::null_mut(); - let status = (boot_services.create_event)( - system::EVT_NOTIFY_SIGNAL, - system::TPL_CALLBACK, - Some(process_key_notifies), - context_ptr as *mut c_void, - core::ptr::addr_of_mut!(key_notify_event), - ); + // SAFETY: `boot_services` references a valid Boot Services table; `context_ptr` and the event + // out-pointer are valid for the duration of the call. + let status = unsafe { + (boot_services.create_event)( + system::EVT_NOTIFY_SIGNAL, + system::TPL_CALLBACK, + Some(process_key_notifies), + context_ptr as *mut c_void, + core::ptr::addr_of_mut!(key_notify_event), + ) + }; if status.is_error() { - (boot_services.close_event)(wait_for_key_event); - (boot_services.close_event)(wait_for_key_ex_event); + // SAFETY: both events were created successfully above. + unsafe { + (boot_services.close_event)(wait_for_key_event); + (boot_services.close_event)(wait_for_key_ex_event); + } drop(unsafe { Box::from_raw(context_ptr) }); return Err(status); } @@ -301,12 +317,16 @@ impl KeyboardHandler { //install simple_text_in and simple_text_in_ex let mut controller = controller; let simple_text_in_ptr = raw_field!(context_ptr, KeyboardContext, simple_text_in); - let status = (boot_services.install_protocol_interface)( - core::ptr::addr_of_mut!(controller), - &protocols::simple_text_input::PROTOCOL_GUID as *const efi::Guid as *mut efi::Guid, - efi::NATIVE_INTERFACE, - simple_text_in_ptr as *mut c_void, - ); + // SAFETY: `boot_services` references a valid Boot Services table; the controller and interface + // pointers are valid for installing the Simple Text Input protocol. + let status = unsafe { + (boot_services.install_protocol_interface)( + core::ptr::addr_of_mut!(controller), + &protocols::simple_text_input::PROTOCOL_GUID as *const efi::Guid as *mut efi::Guid, + efi::NATIVE_INTERFACE, + simple_text_in_ptr as *mut c_void, + ) + }; if status.is_error() { let _ = deinitialize(context_ptr); @@ -314,12 +334,16 @@ impl KeyboardHandler { } let simple_text_in_ex_ptr = raw_field!(context_ptr, KeyboardContext, simple_text_in_ex); - let status = (boot_services.install_protocol_interface)( - core::ptr::addr_of_mut!(controller), - &protocols::simple_text_input_ex::PROTOCOL_GUID as *const efi::Guid as *mut efi::Guid, - efi::NATIVE_INTERFACE, - simple_text_in_ex_ptr as *mut c_void, - ); + // SAFETY: `boot_services` references a valid Boot Services table; the controller and interface + // pointers are valid for installing the Simple Text Input Ex protocol. + let status = unsafe { + (boot_services.install_protocol_interface)( + core::ptr::addr_of_mut!(controller), + &protocols::simple_text_input_ex::PROTOCOL_GUID as *const efi::Guid as *mut efi::Guid, + efi::NATIVE_INTERFACE, + simple_text_in_ex_ptr as *mut c_void, + ) + }; if status.is_error() { let _ = deinitialize(context_ptr); @@ -344,33 +368,44 @@ impl KeyboardHandler { let mut overall_status = efi::Status::SUCCESS; // close the wait_for_key events - let status = (boot_services.close_event)(unsafe { (*simple_text_in_ptr).wait_for_key }); + // SAFETY: `boot_services` references a valid Boot Services table; the event handles were created + // during keyboard installation. + let status = unsafe { (boot_services.close_event)((*simple_text_in_ptr).wait_for_key) }; if status.is_error() { overall_status = status; } - let status = (boot_services.close_event)(unsafe { (*simple_text_in_ex_ptr).wait_for_key_ex }); + // SAFETY: see above. + let status = unsafe { (boot_services.close_event)((*simple_text_in_ex_ptr).wait_for_key_ex) }; if status.is_error() { overall_status = status; } - let status = (boot_services.close_event)(unsafe { (*keyboard_context).handler.key_notify_event }); + // SAFETY: see above. + let status = unsafe { (boot_services.close_event)((*keyboard_context).handler.key_notify_event) }; if status.is_error() { overall_status = status; } //uninstall the protocol interfaces - let status = (boot_services.uninstall_protocol_interface)( - unsafe { (*keyboard_context).controller }, - &protocols::simple_text_input::PROTOCOL_GUID as *const efi::Guid as *mut efi::Guid, - simple_text_in_ptr as *mut c_void, - ); + // SAFETY: `boot_services` references a valid Boot Services table; the controller and interface + // pointers match the protocols installed during keyboard installation. + let status = unsafe { + (boot_services.uninstall_protocol_interface)( + (*keyboard_context).controller, + &protocols::simple_text_input::PROTOCOL_GUID as *const efi::Guid as *mut efi::Guid, + simple_text_in_ptr as *mut c_void, + ) + }; if status.is_error() { overall_status = status; } - let status = (boot_services.uninstall_protocol_interface)( - unsafe { (*keyboard_context).controller }, - &protocols::simple_text_input_ex::PROTOCOL_GUID as *const efi::Guid as *mut efi::Guid, - simple_text_in_ex_ptr as *mut c_void, - ); + // SAFETY: see above. + let status = unsafe { + (boot_services.uninstall_protocol_interface)( + (*keyboard_context).controller, + &protocols::simple_text_input_ex::PROTOCOL_GUID as *const efi::Guid as *mut efi::Guid, + simple_text_in_ex_ptr as *mut c_void, + ) + }; if status.is_error() { overall_status = status; } @@ -471,7 +506,9 @@ impl KeyboardHandler { //and if so, signal the event to trigger notify processing at the appropriate TPL. if self.key_queue.peek_notify_key().is_some() { let boot_services = unsafe { BOOT_SERVICES.as_mut().expect("bad boot services pointer") }; - (boot_services.signal_event)(self.key_notify_event); + // SAFETY: `boot_services` references a valid Boot Services table; `key_notify_event` + // was created during keyboard installation. + unsafe { (boot_services.signal_event)(self.key_notify_event) }; } //after processing all the key strokes, send updated LED state if required. @@ -579,14 +616,18 @@ pub fn attempt_to_retrieve_hid_context( let boot_services = unsafe { BOOT_SERVICES.as_mut().expect("BOOT_SERVICES not properly initialized") }; let mut simple_text_in_ptr: *mut protocols::simple_text_input::Protocol = core::ptr::null_mut(); - let status = (boot_services.open_protocol)( - controller, - &protocols::simple_text_input::PROTOCOL_GUID as *const efi::Guid as *mut efi::Guid, - core::ptr::addr_of_mut!(simple_text_in_ptr) as *mut *mut c_void, - driver_binding.driver_binding_handle, - controller, - system::OPEN_PROTOCOL_GET_PROTOCOL, - ); + // SAFETY: `boot_services` references a valid Boot Services table; the arguments below are valid for + // opening the Simple Text Input protocol on `controller`. + let status = unsafe { + (boot_services.open_protocol)( + controller, + &protocols::simple_text_input::PROTOCOL_GUID as *const efi::Guid as *mut efi::Guid, + core::ptr::addr_of_mut!(simple_text_in_ptr) as *mut *mut c_void, + driver_binding.driver_binding_handle, + controller, + system::OPEN_PROTOCOL_GET_PROTOCOL, + ) + }; match status { efi::Status::SUCCESS => { @@ -613,7 +654,7 @@ extern "efiapi" fn wait_for_key(event: efi::Event, context: *mut c_void) { // Caller should have ensured this, so just expect on failure. let boot_services = unsafe { BOOT_SERVICES.as_mut().expect("BOOT_SERVICES not properly initialized") }; - let old_tpl = (boot_services.raise_tpl)(system::TPL_NOTIFY); + let old_tpl = unsafe { (boot_services.raise_tpl)(system::TPL_NOTIFY) }; loop { if let Some(key_data) = keyboard_context.handler.key_queue.peek_key() { @@ -624,12 +665,16 @@ extern "efiapi" fn wait_for_key(event: efi::Event, context: *mut c_void) { continue; } //live non-partial key at front of queue; so signal event. - (boot_services.signal_event)(event); + // SAFETY: `boot_services` references a valid Boot Services table; `event` is the wait event + // passed to this notify callback. + unsafe { (boot_services.signal_event)(event) }; } break; } - (boot_services.restore_tpl)(old_tpl); + // SAFETY: `boot_services` references a valid Boot Services table; `old_tpl` was obtained from the + // matching `raise_tpl` above. + unsafe { (boot_services.restore_tpl)(old_tpl) }; } // Event callback function for handling registered key notifications. Iterates over the queue of keys to be notified, @@ -646,7 +691,7 @@ extern "efiapi" fn process_key_notifies(_event: efi::Event, context: *mut c_void loop { //Safety: access to the key_queue needs to be at TPL_NOTIFY to ensure mutual exclusion, but this routine runs at //TPL_CALLBACK. So raise TPL to TPL_NOTIFY for the queue pop and callback function search. - let old_tpl = (boot_services.raise_tpl)(system::TPL_NOTIFY); + let old_tpl = unsafe { (boot_services.raise_tpl)(system::TPL_NOTIFY) }; let (key, callback) = match keyboard_context.handler.key_queue.pop_notifiy_key() { Some(key) => { @@ -662,7 +707,9 @@ extern "efiapi" fn process_key_notifies(_event: efi::Event, context: *mut c_void None => (None, None), }; //restore TPL back to TPL_CALLBACK before actually invoking the callback. - (boot_services.restore_tpl)(old_tpl); + // SAFETY: `boot_services` references a valid Boot Services table; `old_tpl` was obtained from the + // matching `raise_tpl` above. + unsafe { (boot_services.restore_tpl)(old_tpl) }; //Invoke the callback, if found. //Safety: this assumes that a caller doesn't "unregister" a callback and render the pointer invalid at TPL_NOTIFY @@ -670,7 +717,8 @@ extern "efiapi" fn process_key_notifies(_event: efi::Event, context: *mut c_void //spec requirement (see UEFI spec 2.10 table 7.3). if let (Some(mut key), Some(callback)) = (key, callback) { let key_data_ptr = &mut key as *mut KeyData; - let _status = callback(key_data_ptr); + // SAFETY: see the spec requirement noted above; `key_data_ptr` points to a valid `KeyData`. + let _status = unsafe { callback(key_data_ptr) }; } else { return; } @@ -903,20 +951,26 @@ pub(crate) fn initialize_keyboard_layout(context_ptr: *mut KeyboardContext) -> R //create layout update event. let mut layout_change_event: efi::Event = core::ptr::null_mut(); - let status = (boot_services.create_event_ex)( - system::EVT_NOTIFY_SIGNAL, - system::TPL_NOTIFY, - Some(on_layout_update), - context_ptr as *mut c_void, - &protocols::hii_database::SET_KEYBOARD_LAYOUT_EVENT_GUID, - core::ptr::addr_of_mut!(layout_change_event), - ); + // SAFETY: `boot_services` references a valid Boot Services table; `context_ptr`, the GUID, and the + // event out-pointer are valid for the duration of the call. + let status = unsafe { + (boot_services.create_event_ex)( + system::EVT_NOTIFY_SIGNAL, + system::TPL_NOTIFY, + Some(on_layout_update), + context_ptr as *mut c_void, + &protocols::hii_database::SET_KEYBOARD_LAYOUT_EVENT_GUID, + core::ptr::addr_of_mut!(layout_change_event), + ) + }; if status.is_error() { Err(status)?; } //signal event to pick up any existing layout. - let status = (boot_services.signal_event)(layout_change_event); + // SAFETY: `boot_services` references a valid Boot Services table; `layout_change_event` was created + // successfully above. + let status = unsafe { (boot_services.signal_event)(layout_change_event) }; if status.is_error() { Err(status)?; } @@ -933,11 +987,15 @@ pub(crate) fn initialize_keyboard_layout(context_ptr: *mut KeyboardContext) -> R pub(crate) fn install_default_layout(boot_services: &mut system::BootServices) -> Result<(), efi::Status> { let mut hii_database_protocol_ptr: *mut protocols::hii_database::Protocol = core::ptr::null_mut(); - let status = (boot_services.locate_protocol)( - &protocols::hii_database::PROTOCOL_GUID as *const efi::Guid as *mut efi::Guid, - core::ptr::null_mut(), - core::ptr::addr_of_mut!(hii_database_protocol_ptr) as *mut *mut c_void, - ); + // SAFETY: `boot_services` references a valid Boot Services table; the GUID and out-pointer are valid + // for locating the HII Database protocol. + let status = unsafe { + (boot_services.locate_protocol)( + &protocols::hii_database::PROTOCOL_GUID as *const efi::Guid as *mut efi::Guid, + core::ptr::null_mut(), + core::ptr::addr_of_mut!(hii_database_protocol_ptr) as *mut *mut c_void, + ) + }; if status.is_error() { debugln!( @@ -952,12 +1010,16 @@ pub(crate) fn install_default_layout(boot_services: &mut system::BootServices) - unsafe { hii_database_protocol_ptr.as_mut().expect("Bad pointer returned from successful locate protocol.") }; let mut hii_handle: hii::Handle = core::ptr::null_mut(); - let status = (hii_database_protocol.new_package_list)( - hii_database_protocol_ptr, - hii_keyboard_layout::get_default_keyboard_pkg_list_buffer().as_ptr() as *const hii::PackageListHeader, - core::ptr::null_mut(), - core::ptr::addr_of_mut!(hii_handle), - ); + // SAFETY: `hii_database_protocol` is a valid pointer returned from a successful locate_protocol; the + // package list buffer and handle out-pointer are valid for the duration of the call. + let status = unsafe { + (hii_database_protocol.new_package_list)( + hii_database_protocol_ptr, + hii_keyboard_layout::get_default_keyboard_pkg_list_buffer().as_ptr() as *const hii::PackageListHeader, + core::ptr::null_mut(), + core::ptr::addr_of_mut!(hii_handle), + ) + }; if status.is_error() { debugln!( @@ -968,10 +1030,14 @@ pub(crate) fn install_default_layout(boot_services: &mut system::BootServices) - Err(status)?; } - let status = (hii_database_protocol.set_keyboard_layout)( - hii_database_protocol_ptr, - &hii_keyboard_layout::DEFAULT_KEYBOARD_LAYOUT_GUID as *const efi::Guid as *mut efi::Guid, - ); + // SAFETY: `hii_database_protocol` is a valid pointer returned from a successful locate_protocol; the + // layout GUID is valid for the duration of the call. + let status = unsafe { + (hii_database_protocol.set_keyboard_layout)( + hii_database_protocol_ptr, + &hii_keyboard_layout::DEFAULT_KEYBOARD_LAYOUT_GUID as *const efi::Guid as *mut efi::Guid, + ) + }; if status.is_error() { debugln!(DEBUG_ERROR, "keyboard::install_default_layout: Failed to set keyboard layout: {:x?}", status); @@ -991,11 +1057,15 @@ extern "efiapi" fn on_layout_update(_event: efi::Event, context: *mut c_void) { let boot_services = unsafe { BOOT_SERVICES.as_mut().expect("BOOT_SERVICES not properly initialized") }; let mut hii_database_protocol_ptr: *mut protocols::hii_database::Protocol = core::ptr::null_mut(); - let status = (boot_services.locate_protocol)( - &protocols::hii_database::PROTOCOL_GUID as *const efi::Guid as *mut efi::Guid, - core::ptr::null_mut(), - core::ptr::addr_of_mut!(hii_database_protocol_ptr) as *mut *mut c_void, - ); + // SAFETY: `boot_services` references a valid Boot Services table; the GUID and out-pointer are valid + // for locating the HII Database protocol. + let status = unsafe { + (boot_services.locate_protocol)( + &protocols::hii_database::PROTOCOL_GUID as *const efi::Guid as *mut efi::Guid, + core::ptr::null_mut(), + core::ptr::addr_of_mut!(hii_database_protocol_ptr) as *mut *mut c_void, + ) + }; if status.is_error() { //nothing to do if there is no hii protocol. @@ -1008,12 +1078,16 @@ extern "efiapi" fn on_layout_update(_event: efi::Event, context: *mut c_void) { let mut keyboard_layout_buffer = vec![0u8; 4096]; let mut layout_buffer_len: u16 = keyboard_layout_buffer.len() as u16; - let status = (hii_database_protocol.get_keyboard_layout)( - hii_database_protocol_ptr, - core::ptr::null_mut(), - &mut layout_buffer_len as *mut u16, - keyboard_layout_buffer.as_mut_ptr() as *mut protocols::hii_database::KeyboardLayout<0>, - ); + // SAFETY: `hii_database_protocol` is a valid pointer returned from a successful locate_protocol; the + // length and layout buffers are valid for the duration of the call. + let status = unsafe { + (hii_database_protocol.get_keyboard_layout)( + hii_database_protocol_ptr, + core::ptr::null_mut(), + &mut layout_buffer_len as *mut u16, + keyboard_layout_buffer.as_mut_ptr() as *mut protocols::hii_database::KeyboardLayout<0>, + ) + }; if status.is_error() { return; diff --git a/HidPkg/UefiHidDxe/src/pointer.rs b/HidPkg/UefiHidDxe/src/pointer.rs index 81ed258069..9d9f8f6a75 100644 --- a/HidPkg/UefiHidDxe/src/pointer.rs +++ b/HidPkg/UefiHidDxe/src/pointer.rs @@ -174,13 +174,17 @@ impl PointerHandler { // create event for wait_for_input. let mut wait_for_pointer_input_event: efi::Event = core::ptr::null_mut(); - let status = (boot_services.create_event)( - system::EVT_NOTIFY_WAIT, - system::TPL_NOTIFY, - Some(wait_for_pointer), - context_ptr as *mut c_void, - core::ptr::addr_of_mut!(wait_for_pointer_input_event), - ); + // SAFETY: `boot_services` references a valid Boot Services table; `context_ptr` and the event + // out-pointer are valid for the duration of the call. + let status = unsafe { + (boot_services.create_event)( + system::EVT_NOTIFY_WAIT, + system::TPL_NOTIFY, + Some(wait_for_pointer), + context_ptr as *mut c_void, + core::ptr::addr_of_mut!(wait_for_pointer_input_event), + ) + }; if status.is_error() { drop(unsafe { Box::from_raw(context_ptr) }); return Err(status); @@ -190,12 +194,16 @@ impl PointerHandler { // install the absolute_pointer protocol. let mut controller = controller; let absolute_pointer_ptr = raw_field!(context_ptr, PointerContext, absolute_pointer); - let status = (boot_services.install_protocol_interface)( - core::ptr::addr_of_mut!(controller), - &absolute_pointer::PROTOCOL_GUID as *const efi::Guid as *mut efi::Guid, - efi::NATIVE_INTERFACE, - absolute_pointer_ptr as *mut c_void, - ); + // SAFETY: `boot_services` references a valid Boot Services table; the controller and interface + // pointers are valid for installing the Absolute Pointer protocol. + let status = unsafe { + (boot_services.install_protocol_interface)( + core::ptr::addr_of_mut!(controller), + &absolute_pointer::PROTOCOL_GUID as *const efi::Guid as *mut efi::Guid, + efi::NATIVE_INTERFACE, + absolute_pointer_ptr as *mut c_void, + ) + }; if status.is_error() { let _ = deinitialize(context_ptr); @@ -353,17 +361,23 @@ impl PointerHandler { let mut overall_status = efi::Status::SUCCESS; // close the wait_for_input event - let status = (boot_services.close_event)(unsafe { (*absolute_pointer_ptr).wait_for_input }); + // SAFETY: `boot_services` references a valid Boot Services table; the event handle was created + // during pointer installation. + let status = unsafe { (boot_services.close_event)((*absolute_pointer_ptr).wait_for_input) }; if status.is_error() { overall_status = status; } // uninstall absolute pointer protocol - let status = (boot_services.uninstall_protocol_interface)( - unsafe { (*pointer_context).controller }, - &absolute_pointer::PROTOCOL_GUID as *const efi::Guid as *mut efi::Guid, - absolute_pointer_ptr as *mut c_void, - ); + // SAFETY: `boot_services` references a valid Boot Services table; the controller and interface + // pointers match the protocol installed during pointer installation. + let status = unsafe { + (boot_services.uninstall_protocol_interface)( + (*pointer_context).controller, + &absolute_pointer::PROTOCOL_GUID as *const efi::Guid as *mut efi::Guid, + absolute_pointer_ptr as *mut c_void, + ) + }; if status.is_error() { overall_status = status; } @@ -425,14 +439,18 @@ pub fn attempt_to_retrieve_hid_context( let boot_services = unsafe { BOOT_SERVICES.as_mut().expect("BOOT_SERVICES not properly initialized") }; let mut absolute_pointer_ptr: *mut absolute_pointer::Protocol = core::ptr::null_mut(); - let status = (boot_services.open_protocol)( - controller, - &absolute_pointer::PROTOCOL_GUID as *const efi::Guid as *mut efi::Guid, - core::ptr::addr_of_mut!(absolute_pointer_ptr) as *mut *mut c_void, - driver_binding.driver_binding_handle, - controller, - system::OPEN_PROTOCOL_GET_PROTOCOL, - ); + // SAFETY: `boot_services` references a valid Boot Services table; the arguments below are valid for + // opening the Absolute Pointer protocol on `controller`. + let status = unsafe { + (boot_services.open_protocol)( + controller, + &absolute_pointer::PROTOCOL_GUID as *const efi::Guid as *mut efi::Guid, + core::ptr::addr_of_mut!(absolute_pointer_ptr) as *mut *mut c_void, + driver_binding.driver_binding_handle, + controller, + system::OPEN_PROTOCOL_GET_PROTOCOL, + ) + }; match status { efi::Status::SUCCESS => { @@ -461,7 +479,9 @@ extern "efiapi" fn wait_for_pointer(event: efi::Event, context: *mut c_void) { let pointer_context = unsafe { (context as *mut PointerContext).as_mut().expect("Pointer Context is bad.") }; if pointer_context.handler.state_changed { - (boot_services.signal_event)(event); + // SAFETY: `boot_services` references a valid Boot Services table; `event` is the wait event passed + // to this notify callback. + unsafe { (boot_services.signal_event)(event) }; } } diff --git a/HidPkg/UefiHidDxeV2/src/boot_services.rs b/HidPkg/UefiHidDxeV2/src/boot_services.rs index cf54a9e01f..ded6e4e1bb 100644 --- a/HidPkg/UefiHidDxeV2/src/boot_services.rs +++ b/HidPkg/UefiHidDxeV2/src/boot_services.rs @@ -118,6 +118,11 @@ impl StandardUefiBootServices { unsafe impl Sync for StandardUefiBootServices {} unsafe impl Send for StandardUefiBootServices {} +// The methods below are a thin safe-abstraction layer over the raw UEFI Boot Services. They forward +// raw-pointer arguments directly to the corresponding UEFI service functions; validity of those +// pointers is the caller's responsibility (as documented on the trait), so the lint that asks for the +// methods to be marked `unsafe` is allowed here. +#[allow(clippy::not_unsafe_ptr_arg_deref)] impl UefiBootServices for StandardUefiBootServices { fn create_event( &self, @@ -127,7 +132,9 @@ impl UefiBootServices for StandardUefiBootServices { notify_context: *mut c_void, event: *mut efi::Event, ) -> efi::Status { - (self.boot_services().create_event)(r#type, notify_tpl, notify_function, notify_context, event) + // SAFETY: `boot_services()` returns a valid Boot Services table; the caller is responsible for + // passing valid arguments to this UEFI service. + unsafe { (self.boot_services().create_event)(r#type, notify_tpl, notify_function, notify_context, event) } } fn create_event_ex( &self, @@ -138,19 +145,37 @@ impl UefiBootServices for StandardUefiBootServices { event_group: *const efi::Guid, event: *mut efi::Event, ) -> efi::Status { - (self.boot_services().create_event_ex)(r#type, notify_tpl, notify_function, notify_context, event_group, event) + // SAFETY: `boot_services()` returns a valid Boot Services table; the caller is responsible for + // passing valid arguments to this UEFI service. + unsafe { + (self.boot_services().create_event_ex)( + r#type, + notify_tpl, + notify_function, + notify_context, + event_group, + event, + ) + } } fn close_event(&self, event: efi::Event) -> efi::Status { - (self.boot_services().close_event)(event) + // SAFETY: `boot_services()` returns a valid Boot Services table; the caller is responsible for + // passing a valid event handle. + unsafe { (self.boot_services().close_event)(event) } } fn signal_event(&self, event: efi::Event) -> efi::Status { - (self.boot_services().signal_event)(event) + // SAFETY: `boot_services()` returns a valid Boot Services table; the caller is responsible for + // passing a valid event handle. + unsafe { (self.boot_services().signal_event)(event) } } fn raise_tpl(&self, new_tpl: efi::Tpl) -> efi::Tpl { - (self.boot_services().raise_tpl)(new_tpl) + // SAFETY: `boot_services()` returns a valid Boot Services table. + unsafe { (self.boot_services().raise_tpl)(new_tpl) } } fn restore_tpl(&self, old_tpl: efi::Tpl) { - (self.boot_services().restore_tpl)(old_tpl) + // SAFETY: `boot_services()` returns a valid Boot Services table; `old_tpl` was obtained from a + // prior `raise_tpl` call. + unsafe { (self.boot_services().restore_tpl)(old_tpl) } } fn install_protocol_interface( &self, @@ -159,7 +184,9 @@ impl UefiBootServices for StandardUefiBootServices { interface_type: efi::InterfaceType, interface: *mut c_void, ) -> efi::Status { - (self.boot_services().install_protocol_interface)(handle, protocol, interface_type, interface) + // SAFETY: `boot_services()` returns a valid Boot Services table; the caller is responsible for + // passing valid arguments to this UEFI service. + unsafe { (self.boot_services().install_protocol_interface)(handle, protocol, interface_type, interface) } } fn uninstall_protocol_interface( &self, @@ -167,7 +194,9 @@ impl UefiBootServices for StandardUefiBootServices { protocol: *mut efi::Guid, interface: *mut c_void, ) -> efi::Status { - (self.boot_services().uninstall_protocol_interface)(handle, protocol, interface) + // SAFETY: `boot_services()` returns a valid Boot Services table; the caller is responsible for + // passing valid arguments to this UEFI service. + unsafe { (self.boot_services().uninstall_protocol_interface)(handle, protocol, interface) } } fn open_protocol( &self, @@ -178,7 +207,18 @@ impl UefiBootServices for StandardUefiBootServices { controller_handle: efi::Handle, attributes: u32, ) -> efi::Status { - (self.boot_services().open_protocol)(handle, protocol, interface, agent_handle, controller_handle, attributes) + // SAFETY: `boot_services()` returns a valid Boot Services table; the caller is responsible for + // passing valid arguments to this UEFI service. + unsafe { + (self.boot_services().open_protocol)( + handle, + protocol, + interface, + agent_handle, + controller_handle, + attributes, + ) + } } fn close_protocol( &self, @@ -187,7 +227,9 @@ impl UefiBootServices for StandardUefiBootServices { agent_handle: efi::Handle, controller_handle: efi::Handle, ) -> efi::Status { - (self.boot_services().close_protocol)(handle, protocol, agent_handle, controller_handle) + // SAFETY: `boot_services()` returns a valid Boot Services table; the caller is responsible for + // passing valid arguments to this UEFI service. + unsafe { (self.boot_services().close_protocol)(handle, protocol, agent_handle, controller_handle) } } fn locate_protocol( &self, @@ -195,10 +237,14 @@ impl UefiBootServices for StandardUefiBootServices { registration: *mut c_void, interface: *mut *mut c_void, ) -> efi::Status { - (self.boot_services().locate_protocol)(protocol, registration, interface) + // SAFETY: `boot_services()` returns a valid Boot Services table; the caller is responsible for + // passing valid arguments to this UEFI service. + unsafe { (self.boot_services().locate_protocol)(protocol, registration, interface) } } fn set_timer(&self, event: efi::Event, r#type: efi::TimerDelay, trigger_time: u64) -> efi::Status { - (self.boot_services().set_timer)(event, r#type, trigger_time) + // SAFETY: `boot_services()` returns a valid Boot Services table; the caller is responsible for + // passing a valid event handle. + unsafe { (self.boot_services().set_timer)(event, r#type, trigger_time) } } } diff --git a/HidPkg/UefiHidDxeV2/src/driver_binding.rs b/HidPkg/UefiHidDxeV2/src/driver_binding.rs index 38964dcea4..1fb8bef0c4 100644 --- a/HidPkg/UefiHidDxeV2/src/driver_binding.rs +++ b/HidPkg/UefiHidDxeV2/src/driver_binding.rs @@ -350,16 +350,18 @@ mod test { let this_ptr = binding_ptr as *mut protocols::driver_binding::Protocol; let controller_handle = 0x4321 as efi::Handle; + // SAFETY: `this_ptr` points to the driver binding protocol installed above, and the controller + // handle and null context are valid arguments for these test invocations. assert_eq!( - (driver_binding_ref.uefi_binding.supported)(this_ptr, controller_handle, core::ptr::null_mut()), + unsafe { (driver_binding_ref.uefi_binding.supported)(this_ptr, controller_handle, core::ptr::null_mut()) }, efi::Status::SUCCESS ); assert_eq!( - (driver_binding_ref.uefi_binding.start)(this_ptr, controller_handle, core::ptr::null_mut()), + unsafe { (driver_binding_ref.uefi_binding.start)(this_ptr, controller_handle, core::ptr::null_mut()) }, efi::Status::SUCCESS ); assert_eq!( - (driver_binding_ref.uefi_binding.stop)(this_ptr, controller_handle, 0, core::ptr::null_mut()), + unsafe { (driver_binding_ref.uefi_binding.stop)(this_ptr, controller_handle, 0, core::ptr::null_mut()) }, efi::Status::SUCCESS ); } diff --git a/HidPkg/UefiHidDxeV2/src/keyboard.rs b/HidPkg/UefiHidDxeV2/src/keyboard.rs index e7818de45a..b48ed15719 100644 --- a/HidPkg/UefiHidDxeV2/src/keyboard.rs +++ b/HidPkg/UefiHidDxeV2/src/keyboard.rs @@ -431,12 +431,16 @@ impl KeyboardHidHandler { }; let mut hii_handle: hii::Handle = ptr::null_mut(); - let status = (hii_database_protocol.new_package_list)( - hii_database_protocol_ptr, - hii_keyboard_layout::get_default_keyboard_pkg_list_buffer().as_ptr() as *const hii::PackageListHeader, - ptr::null_mut(), - ptr::addr_of_mut!(hii_handle), - ); + // SAFETY: `hii_database_protocol_ptr` points to a valid HII Database Protocol obtained from a + // successful `locate_protocol` call, and the keyboard package list buffer is valid. + let status = unsafe { + (hii_database_protocol.new_package_list)( + hii_database_protocol_ptr, + hii_keyboard_layout::get_default_keyboard_pkg_list_buffer().as_ptr() as *const hii::PackageListHeader, + ptr::null_mut(), + ptr::addr_of_mut!(hii_handle), + ) + }; if status.is_error() { debugln!( @@ -447,10 +451,14 @@ impl KeyboardHidHandler { Err(status)?; } - let status = (hii_database_protocol.set_keyboard_layout)( - hii_database_protocol_ptr, - &hii_keyboard_layout::DEFAULT_KEYBOARD_LAYOUT_GUID as *const efi::Guid as *mut efi::Guid, - ); + // SAFETY: `hii_database_protocol_ptr` points to a valid HII Database Protocol obtained from a + // successful `locate_protocol` call. + let status = unsafe { + (hii_database_protocol.set_keyboard_layout)( + hii_database_protocol_ptr, + &hii_keyboard_layout::DEFAULT_KEYBOARD_LAYOUT_GUID as *const efi::Guid as *mut efi::Guid, + ) + }; if status.is_error() { debugln!(DEBUG_ERROR, "keyboard::install_default_layout: Failed to set keyboard layout: {:x?}", status); Err(status)?; @@ -658,7 +666,10 @@ extern "efiapi" fn reset_notification_function(key_data: *mut protocols::simple_ //DEL scan code received with shift state indicating CTRL-ALT also pressed. debugln!(DEBUG_WARN, "Ctrl-Alt-Del pressed, resetting system."); if let Some(runtime_services) = unsafe { RUNTIME_SERVICES.load(Ordering::SeqCst).as_ref() } { - (runtime_services.reset_system)(efi::RESET_COLD, efi::Status::SUCCESS, 0, core::ptr::null_mut()); + // SAFETY: `runtime_services` is a valid Runtime Services table loaded from the global pointer. + unsafe { + (runtime_services.reset_system)(efi::RESET_COLD, efi::Status::SUCCESS, 0, core::ptr::null_mut()); + } } panic!("Reset failed."); } @@ -897,12 +908,16 @@ extern "efiapi" fn on_layout_update(_event: efi::Event, context: *mut c_void) { // retrieve keyboard layout size let mut layout_buffer_len: u16 = 0; - match (hii_database_protocol.get_keyboard_layout)( - hii_database_protocol_ptr, - ptr::null_mut(), - &mut layout_buffer_len as *mut u16, - ptr::null_mut(), - ) { + // SAFETY: `hii_database_protocol_ptr` points to a valid HII Database Protocol obtained from a + // successful `locate_protocol` call; `layout_buffer_len` is a valid local. + match unsafe { + (hii_database_protocol.get_keyboard_layout)( + hii_database_protocol_ptr, + ptr::null_mut(), + &mut layout_buffer_len as *mut u16, + ptr::null_mut(), + ) + } { efi::Status::NOT_FOUND => break 'layout_processing, status if status != efi::Status::BUFFER_TOO_SMALL => { debugln!( @@ -917,12 +932,16 @@ extern "efiapi" fn on_layout_update(_event: efi::Event, context: *mut c_void) { } let mut keyboard_layout_buffer = vec![0u8; layout_buffer_len as usize]; - let status = (hii_database_protocol.get_keyboard_layout)( - hii_database_protocol_ptr, - ptr::null_mut(), - &mut layout_buffer_len as *mut u16, - keyboard_layout_buffer.as_mut_ptr() as *mut protocols::hii_database::KeyboardLayout<0>, - ); + // SAFETY: `hii_database_protocol_ptr` points to a valid HII Database Protocol obtained from a + // successful `locate_protocol` call; `keyboard_layout_buffer` is sized per the prior length query. + let status = unsafe { + (hii_database_protocol.get_keyboard_layout)( + hii_database_protocol_ptr, + ptr::null_mut(), + &mut layout_buffer_len as *mut u16, + keyboard_layout_buffer.as_mut_ptr() as *mut protocols::hii_database::KeyboardLayout<0>, + ) + }; if status.is_error() { debugln!(DEBUG_ERROR, "Unexpected return from get_keyboard_layout: {:x?}", status); @@ -1559,11 +1578,11 @@ mod test { assert_eq!(OrdKeyData(key_data), OrdKeyData(callback_key_data.unwrap())); assert!(callbacks.contains( &(mock_key_notify_callback - as extern "efiapi" fn(*mut protocols::simple_text_input_ex::KeyData) -> efi::Status) + as unsafe extern "efiapi" fn(*mut protocols::simple_text_input_ex::KeyData) -> efi::Status) )); assert!(callbacks.contains( &(mock_key_notify_callback2 - as extern "efiapi" fn(*mut protocols::simple_text_input_ex::KeyData) -> efi::Status) + as unsafe extern "efiapi" fn(*mut protocols::simple_text_input_ex::KeyData) -> efi::Status) )); let (callback_key_data, callbacks) = keyboard_handler.pending_callbacks(); @@ -1586,7 +1605,9 @@ mod test { char if char == 'a' as u16 || char == 'c' as u16 => { assert!(callbacks.contains( &(mock_key_notify_callback - as extern "efiapi" fn(*mut protocols::simple_text_input_ex::KeyData) -> efi::Status) + as unsafe extern "efiapi" fn( + *mut protocols::simple_text_input_ex::KeyData, + ) -> efi::Status) )); } _ => panic!("unexpected pending callback key"), diff --git a/HidPkg/UefiHidDxeV2/src/keyboard/simple_text_in_ex.rs b/HidPkg/UefiHidDxeV2/src/keyboard/simple_text_in_ex.rs index 95d5de1c05..1edb067026 100644 --- a/HidPkg/UefiHidDxeV2/src/keyboard/simple_text_in_ex.rs +++ b/HidPkg/UefiHidDxeV2/src/keyboard/simple_text_in_ex.rs @@ -418,7 +418,9 @@ impl SimpleTextInExFfi { if let Some(mut pending_key) = pending_key { let key_ptr = &mut pending_key as *mut protocols::simple_text_input_ex::KeyData; for callback in pending_callbacks { - let _ = callback(key_ptr); + // SAFETY: `callback` is a valid key notification function registered through the + // Simple Text Input Ex protocol, and `key_ptr` points to a valid `KeyData` on the stack. + let _ = unsafe { callback(key_ptr) }; } } else { // no pending notifies to process diff --git a/MsCorePkg/Crates/RustBootServicesAllocatorDxe/src/lib.rs b/MsCorePkg/Crates/RustBootServicesAllocatorDxe/src/lib.rs index 7f175459a7..30fd0c4ca7 100644 --- a/MsCorePkg/Crates/RustBootServicesAllocatorDxe/src/lib.rs +++ b/MsCorePkg/Crates/RustBootServicesAllocatorDxe/src/lib.rs @@ -68,11 +68,12 @@ impl BootServicesAllocator { 0..=8 => { //allocate the pointer directly since UEFI pool allocations are 8-byte aligned already. let mut ptr: *mut c_void = core::ptr::null_mut(); - match (boot_services.allocate_pool)( - efi::BOOT_SERVICES_DATA, - layout.size(), - core::ptr::addr_of_mut!(ptr), - ) { + // SAFETY: `allocate_pool` is a valid boot services function pointer (the caller guarantees + // `boot_services` references a valid Boot Services table). `ptr` is a valid, properly aligned + // local that lives for the duration of the call and is only read on SUCCESS. + match unsafe { + (boot_services.allocate_pool)(efi::BOOT_SERVICES_DATA, layout.size(), core::ptr::addr_of_mut!(ptr)) + } { efi::Status::SUCCESS => ptr as *mut u8, _ => core::ptr::null_mut(), } @@ -87,11 +88,16 @@ impl BootServicesAllocator { let expanded_size = expanded_layout.size() + expanded_layout.align(); let mut orig_ptr: *mut c_void = core::ptr::null_mut(); - let final_ptr = match (boot_services.allocate_pool)( - efi::BOOT_SERVICES_DATA, - expanded_size, - core::ptr::addr_of_mut!(orig_ptr), - ) { + // SAFETY: `allocate_pool` is a valid boot services function pointer (the caller guarantees + // `boot_services` references a valid Boot Services table). `orig_ptr` is a valid, properly + // aligned local that lives for the duration of the call and is only read on SUCCESS. + let final_ptr = match unsafe { + (boot_services.allocate_pool)( + efi::BOOT_SERVICES_DATA, + expanded_size, + core::ptr::addr_of_mut!(orig_ptr), + ) + } { efi::Status::SUCCESS => orig_ptr as *mut u8, _ => return core::ptr::null_mut(), }; @@ -121,7 +127,10 @@ impl BootServicesAllocator { match layout.align() { 0..=8 => { //pointer was allocated directly, so free it directly. - let _ = (boot_services.free_pool)(ptr as *mut c_void); + // SAFETY: `free_pool` is a valid boot services function pointer (the caller guarantees + // `boot_services` references a valid Boot Services table). `ptr` was returned by a prior + // `allocate_pool` call for an allocation with alignment <= 8, so it is the original pointer. + let _ = unsafe { (boot_services.free_pool)(ptr as *mut c_void) }; } _ => { //pointer was potentially adjusted for alignment. Recover tracking structure to retrieve the original @@ -134,7 +143,10 @@ impl BootServicesAllocator { ptr.add(tracking_offset).cast::().as_mut().expect("tracking pointer is invalid") }; debug_assert_eq!(tracker.signature, ALLOC_TRACKER_SIG); - let _ = (boot_services.free_pool)(tracker.orig_ptr); + // SAFETY: `free_pool` is a valid boot services function pointer (the caller guarantees + // `boot_services` references a valid Boot Services table). `tracker.orig_ptr` is the original + // pointer returned by `allocate_pool`, recovered from the tracking structure. + let _ = unsafe { (boot_services.free_pool)(tracker.orig_ptr) }; } } }