diff --git a/uefi-test-runner/src/boot/misc.rs b/uefi-test-runner/src/boot/misc.rs index 87a4d206b..39bc86571 100644 --- a/uefi-test-runner/src/boot/misc.rs +++ b/uefi-test-runner/src/boot/misc.rs @@ -9,7 +9,7 @@ use uefi::table::boot::{ Tpl, }; use uefi::table::{Boot, SystemTable}; -use uefi::{boot, guid, Event, Guid, Identify, Status}; +use uefi::{boot, guid, system, Event, Guid, Identify, Status}; pub fn test(st: &SystemTable) { let bt = st.boot_services(); @@ -30,6 +30,7 @@ pub fn test(st: &SystemTable) { test_reinstall_protocol_interface(bt); test_uninstall_protocol_interface(bt); test_install_configuration_table(st); + test_install_configuration_table_freestanding(); } fn test_tpl() { @@ -262,6 +263,35 @@ fn test_uninstall_protocol_interface(bt: &BootServices) { } } +fn test_install_configuration_table_freestanding() { + // Get the current number of entries. + let count = system::with_config_table(|t| t.len()); + + // Create the entry data. + let config = boot::allocate_pool(MemoryType::RUNTIME_SERVICES_DATA, 1) + .unwrap() + .as_ptr(); + unsafe { config.write(42) }; + + // Install the table. + const ID: Guid = guid!("4bec53c4-5fc1-48a1-ab12-df214907d29f"); + unsafe { + boot::install_configuration_table(&ID, config.cast()).unwrap(); + } + + // Verify the installation. + assert_eq!(count + 1, system::with_config_table(|t| t.len())); + system::with_config_table(|t| { + let config_entry = t.iter().find(|ct| ct.guid == ID).unwrap(); + assert_eq!(unsafe { *(config_entry.address as *const u8) }, 42); + }); + + // Uninstall the table. + unsafe { + boot::install_configuration_table(&ID, ptr::null()).unwrap(); + } +} + fn test_install_configuration_table(st: &SystemTable) { let config = st .boot_services() diff --git a/uefi/src/boot.rs b/uefi/src/boot.rs index d86d635a3..5666411c2 100644 --- a/uefi/src/boot.rs +++ b/uefi/src/boot.rs @@ -724,6 +724,32 @@ pub unsafe fn exit( ) } +/// Adds, updates, or removes a configuration table entry +/// from the EFI System Table. +/// +/// # Safety +/// +/// When installing or updating a configuration table, the data pointed to by +/// `table_ptr` must be a pool allocation of type +/// [`RUNTIME_SERVICES_DATA`]. Once this table has been installed, the caller +/// should not modify or free the data. +/// +/// [`RUNTIME_SERVICES_DATA`]: MemoryType::RUNTIME_SERVICES_DATA +/// +/// # Errors +/// +/// * [`Status::NOT_FOUND`]: tried to delete a nonexistent entry. +/// * [`Status::OUT_OF_RESOURCES`]: out of memory. +pub unsafe fn install_configuration_table( + guid_entry: &'static Guid, + table_ptr: *const c_void, +) -> Result { + let bt = boot_services_raw_panicking(); + let bt = unsafe { bt.as_ref() }; + + (bt.install_configuration_table)(guid_entry, table_ptr).to_result() +} + /// Stalls execution for the given number of microseconds. pub fn stall(microseconds: usize) { let bt = boot_services_raw_panicking();