diff --git a/uefi-test-runner/src/boot/memory.rs b/uefi-test-runner/src/boot/memory.rs index 826a0a54f..2856bdaa1 100644 --- a/uefi-test-runner/src/boot/memory.rs +++ b/uefi-test-runner/src/boot/memory.rs @@ -1,23 +1,20 @@ use alloc::vec::Vec; -use uefi::boot; -use uefi::mem::memory_map::{MemoryMap, MemoryMapMut, MemoryMapOwned, MemoryType}; -use uefi::table::boot::{AllocateType, BootServices}; +use uefi::boot::{self, AllocateType}; +use uefi::mem::memory_map::{MemoryMap, MemoryMapMut, MemoryType}; -pub fn test(bt: &BootServices) { +pub fn test() { info!("Testing memory functions"); - test_allocate_pages_freestanding(); - test_allocate_pool_freestanding(); + test_allocate_pages(); + test_allocate_pool(); - allocate_pages(bt); vec_alloc(); alloc_alignment(); - memory_map(bt); - memory_map_freestanding(); + test_memory_map(); } -fn test_allocate_pages_freestanding() { +fn test_allocate_pages() { let num_pages = 1; let ptr = boot::allocate_pages(AllocateType::AnyPages, MemoryType::LOADER_DATA, num_pages).unwrap(); @@ -34,7 +31,7 @@ fn test_allocate_pages_freestanding() { unsafe { boot::free_pages(ptr, num_pages) }.unwrap(); } -fn test_allocate_pool_freestanding() { +fn test_allocate_pool() { let ptr = boot::allocate_pool(MemoryType::LOADER_DATA, 10).unwrap(); // Verify the allocation can be written to. @@ -46,28 +43,6 @@ fn test_allocate_pool_freestanding() { unsafe { boot::free_pool(ptr) }.unwrap(); } -fn allocate_pages(bt: &BootServices) { - info!("Allocating some pages of memory"); - - let ty = AllocateType::AnyPages; - let mem_ty = MemoryType::LOADER_DATA; - let pgs = bt - .allocate_pages(ty, mem_ty, 1) - .expect("Failed to allocate a page of memory"); - - assert_eq!(pgs % 4096, 0, "Page pointer is not page-aligned"); - - // Reinterpret the page as an array of bytes - let buf = unsafe { &mut *(pgs as *mut [u8; 4096]) }; - - // If these don't fail then we properly allocated some memory. - buf[0] = 0xF0; - buf[4095] = 0x23; - - // Clean up to avoid memory leaks. - unsafe { bt.free_pages(pgs, 1) }.unwrap(); -} - // Simple test to ensure our custom allocator works with the `alloc` crate. fn vec_alloc() { info!("Allocating a vector through the `alloc` crate"); @@ -94,7 +69,12 @@ fn alloc_alignment() { assert_eq!(value.as_ptr() as usize % 0x100, 0, "Wrong alignment"); } -fn check_memory_map(mut memory_map: MemoryMapOwned) { +fn test_memory_map() { + info!("Testing memory map functions"); + + let mut memory_map = + boot::memory_map(MemoryType::LOADER_DATA).expect("Failed to retrieve UEFI memory map"); + memory_map.sort(); // Collect the descriptors into a vector @@ -125,22 +105,3 @@ fn check_memory_map(mut memory_map: MemoryMapOwned) { let page_count = first_desc.page_count; assert!(page_count != 0, "Memory map entry has size zero"); } - -fn memory_map(bt: &BootServices) { - info!("Testing memory map functions"); - - let memory_map = bt - .memory_map(MemoryType::LOADER_DATA) - .expect("Failed to retrieve UEFI memory map"); - - check_memory_map(memory_map); -} - -fn memory_map_freestanding() { - info!("Testing memory map functions (freestanding)"); - - let memory_map = - boot::memory_map(MemoryType::LOADER_DATA).expect("Failed to retrieve UEFI memory map"); - - check_memory_map(memory_map); -} diff --git a/uefi-test-runner/src/boot/misc.rs b/uefi-test-runner/src/boot/misc.rs index 7fab703f5..f006f18ff 100644 --- a/uefi-test-runner/src/boot/misc.rs +++ b/uefi-test-runner/src/boot/misc.rs @@ -1,37 +1,29 @@ use core::ffi::c_void; +use core::mem; use core::ptr::{self, NonNull}; -use core::mem; +use uefi::boot::{ + EventType, OpenProtocolAttributes, OpenProtocolParams, SearchType, TimerTrigger, Tpl, +}; use uefi::mem::memory_map::MemoryType; use uefi::proto::unsafe_protocol; -use uefi::table::boot::{ - BootServices, EventType, OpenProtocolAttributes, OpenProtocolParams, SearchType, TimerTrigger, - Tpl, -}; -use uefi::table::{Boot, SystemTable}; -use uefi::{boot, guid, system, Event, Guid, Identify, Status}; +use uefi::{boot, guid, system, Event, Guid, Identify}; -pub fn test(st: &SystemTable) { - let bt = st.boot_services(); +pub fn test() { test_tpl(); info!("Testing timer..."); - test_timer(bt); + test_timer(); info!("Testing events..."); - test_check_event_freestanding(); - test_timer_freestanding(); - test_event_callback(bt); - test_callback_with_ctx(bt); + test_check_event(); + test_callback_with_ctx(); info!("Testing watchdog..."); - test_watchdog(bt); + test_watchdog(); info!("Testing protocol handler services..."); - test_register_protocol_notify(bt); - test_register_protocol_notify_freestanding(); - test_protocol_interface_management(); - test_install_protocol_interface(bt); - test_reinstall_protocol_interface(bt); - test_uninstall_protocol_interface(bt); - test_install_configuration_table(st); - test_install_configuration_table_freestanding(); + test_register_protocol_notify(); + test_install_protocol_interface(); + test_reinstall_protocol_interface(); + test_uninstall_protocol_interface(); + test_install_configuration_table(); } fn test_tpl() { @@ -40,7 +32,7 @@ fn test_tpl() { let _guard = unsafe { boot::raise_tpl(Tpl::NOTIFY) }; } -fn test_check_event_freestanding() { +fn test_check_event() { extern "efiapi" fn callback(_event: Event, _ctx: Option>) { info!("Callback triggered by check_event"); } @@ -56,7 +48,7 @@ fn test_check_event_freestanding() { boot::close_event(event).unwrap(); } -fn test_timer_freestanding() { +fn test_timer() { let timer_event = unsafe { boot::create_event_ex(EventType::TIMER, Tpl::CALLBACK, None, None, None) } .unwrap(); @@ -67,28 +59,7 @@ fn test_timer_freestanding() { boot::close_event(timer_event).unwrap(); } -fn test_timer(bt: &BootServices) { - let timer_event = unsafe { bt.create_event(EventType::TIMER, Tpl::APPLICATION, None, None) } - .expect("Failed to create TIMER event"); - let mut events = unsafe { [timer_event.unsafe_clone()] }; - bt.set_timer(&timer_event, TimerTrigger::Relative(5_0 /*00 ns */)) - .expect("Failed to set timer"); - bt.wait_for_event(&mut events) - .expect("Wait for event failed"); -} - -fn test_event_callback(bt: &BootServices) { - extern "efiapi" fn callback(_event: Event, _ctx: Option>) { - info!("Inside the event callback"); - } - - let event = - unsafe { bt.create_event(EventType::NOTIFY_WAIT, Tpl::CALLBACK, Some(callback), None) } - .expect("Failed to create custom event"); - bt.check_event(event).expect("Failed to check event"); -} - -fn test_callback_with_ctx(bt: &BootServices) { +fn test_callback_with_ctx() { let mut data = 123u32; extern "efiapi" fn callback(_event: Event, ctx: Option>) { @@ -105,7 +76,7 @@ fn test_callback_with_ctx(bt: &BootServices) { let ctx = NonNull::new(ctx.cast::()).unwrap(); let event = unsafe { - bt.create_event( + boot::create_event( EventType::NOTIFY_WAIT, Tpl::CALLBACK, Some(callback), @@ -114,21 +85,17 @@ fn test_callback_with_ctx(bt: &BootServices) { .expect("Failed to create event with context") }; - bt.check_event(event).expect("Failed to check event"); + boot::check_event(event).expect("Failed to check event"); // Check that `data` was updated inside the event callback. assert_eq!(data, 456); } -fn test_watchdog(bt: &BootServices) { +fn test_watchdog() { // There's no way to check the watchdog timer value, so just test setting it. // Disable the UEFI watchdog timer. - bt.set_watchdog_timer(0, 0x10000, None) - .expect("Could not set watchdog timer"); - - // Set the timer with the freestanding function. - boot::set_watchdog_timer(240, 0x10000, None).expect("Could not set watchdog timer"); + boot::set_watchdog_timer(0, 0x10000, None).expect("Could not set watchdog timer"); } /// Dummy protocol for tests @@ -137,29 +104,9 @@ struct TestProtocol { data: u32, } -unsafe extern "efiapi" fn _test_notify(_event: Event, _context: Option>) { - info!("Protocol was (re)installed and this function notified.") -} - -fn test_register_protocol_notify(bt: &BootServices) { - let protocol = &TestProtocol::GUID; - let event = unsafe { - bt.create_event( - EventType::NOTIFY_SIGNAL, - Tpl::NOTIFY, - Some(_test_notify), - None, - ) - .expect("Failed to create an event") - }; - - bt.register_protocol_notify(protocol, event) - .expect("Failed to register protocol notify fn"); -} - -fn test_register_protocol_notify_freestanding() { +fn test_register_protocol_notify() { unsafe extern "efiapi" fn callback(_event: Event, _context: Option>) { - info!("in callback for test_register_protocol_notify_freestanding") + info!("in callback for test_register_protocol_notify") } let protocol = &TestProtocol::GUID; @@ -171,79 +118,34 @@ fn test_register_protocol_notify_freestanding() { .expect("Failed to register protocol notify fn"); } -fn test_protocol_interface_management() { - let mut interface = TestProtocol { data: 123 }; - let interface_ptr: *mut _ = &mut interface; - - // Install the protocol. - let handle = unsafe { - boot::install_protocol_interface(None, &TestProtocol::GUID, interface_ptr.cast()) - } - .unwrap(); - - // Verify the handle was installed. - assert_eq!( - &*boot::locate_handle_buffer(SearchType::from_proto::()).unwrap(), - [handle] - ); - - // Re-install the protocol. - unsafe { - boot::reinstall_protocol_interface( - handle, - &TestProtocol::GUID, - interface_ptr.cast(), - interface_ptr.cast(), - ) - } - .unwrap(); - - // Uninstall the protocol. - unsafe { - boot::uninstall_protocol_interface(handle, &TestProtocol::GUID, interface_ptr.cast()) - } - .unwrap(); - - // Verify the protocol was uninstalled. - assert_eq!( - boot::locate_handle_buffer(SearchType::from_proto::()) - .unwrap_err() - .status(), - Status::NOT_FOUND - ); -} - -fn test_install_protocol_interface(bt: &BootServices) { +fn test_install_protocol_interface() { info!("Installing TestProtocol"); - let alloc: *mut TestProtocol = bt - .allocate_pool( - MemoryType::BOOT_SERVICES_DATA, - mem::size_of::(), - ) - .unwrap() - .cast() - .as_ptr(); + let alloc: *mut TestProtocol = boot::allocate_pool( + MemoryType::BOOT_SERVICES_DATA, + mem::size_of::(), + ) + .unwrap() + .cast() + .as_ptr(); unsafe { alloc.write(TestProtocol { data: 123 }) }; let _ = unsafe { - bt.install_protocol_interface(None, &TestProtocol::GUID, alloc.cast()) + boot::install_protocol_interface(None, &TestProtocol::GUID, alloc.cast()) .expect("Failed to install protocol interface") }; - let _ = bt - .locate_handle_buffer(SearchType::from_proto::()) + let _ = boot::locate_handle_buffer(SearchType::from_proto::()) .expect("Failed to find protocol after it was installed"); } -fn test_reinstall_protocol_interface(bt: &BootServices) { +fn test_reinstall_protocol_interface() { info!("Reinstalling TestProtocol"); - let handle = bt - .locate_handle_buffer(SearchType::from_proto::()) + let handle = boot::locate_handle_buffer(SearchType::from_proto::()) .expect("Failed to find protocol to uninstall")[0]; unsafe { - let _ = bt.reinstall_protocol_interface( + let _ = boot::reinstall_protocol_interface( handle, &TestProtocol::GUID, ptr::null_mut(), @@ -252,11 +154,10 @@ fn test_reinstall_protocol_interface(bt: &BootServices) { } } -fn test_uninstall_protocol_interface(bt: &BootServices) { +fn test_uninstall_protocol_interface() { info!("Uninstalling TestProtocol"); - let handle = bt - .locate_handle_buffer(SearchType::from_proto::()) + let handle = boot::locate_handle_buffer(SearchType::from_proto::()) .expect("Failed to find protocol to uninstall")[0]; unsafe { @@ -267,7 +168,7 @@ fn test_uninstall_protocol_interface(bt: &BootServices) { let mut sp = boot::open_protocol::( OpenProtocolParams { handle, - agent: bt.image_handle(), + agent: boot::image_handle(), controller: None, }, OpenProtocolAttributes::GetProtocol, @@ -277,14 +178,14 @@ fn test_uninstall_protocol_interface(bt: &BootServices) { &mut *sp }; - bt.uninstall_protocol_interface(handle, &TestProtocol::GUID, interface_ptr.cast()) + boot::uninstall_protocol_interface(handle, &TestProtocol::GUID, interface_ptr.cast()) .expect("Failed to uninstall protocol interface"); - bt.free_pool(interface_ptr.cast()).unwrap(); + boot::free_pool(NonNull::new(interface_ptr.cast()).unwrap()).unwrap(); } } -fn test_install_configuration_table_freestanding() { +fn test_install_configuration_table() { // Get the current number of entries. let count = system::with_config_table(|t| t.len()); @@ -312,29 +213,3 @@ fn test_install_configuration_table_freestanding() { boot::install_configuration_table(&ID, ptr::null()).unwrap(); } } - -fn test_install_configuration_table(st: &SystemTable) { - let config = st - .boot_services() - .allocate_pool(MemoryType::ACPI_RECLAIM, 1) - .expect("Failed to allocate config table") - .as_ptr(); - unsafe { config.write(42) }; - - let count = st.config_table().len(); - const ID: Guid = guid!("3bdb3089-5662-42df-840e-3922ed6467c9"); - - unsafe { - st.boot_services() - .install_configuration_table(&ID, config.cast()) - .expect("Failed to install configuration table"); - } - - assert_eq!(count + 1, st.config_table().len()); - let config_entry = st - .config_table() - .iter() - .find(|ct| ct.guid == ID) - .expect("Failed to find test config table"); - assert_eq!(unsafe { *(config_entry.address as *const u8) }, 42); -} diff --git a/uefi-test-runner/src/boot/mod.rs b/uefi-test-runner/src/boot/mod.rs index ae5b78f0e..26a04581d 100644 --- a/uefi-test-runner/src/boot/mod.rs +++ b/uefi-test-runner/src/boot/mod.rs @@ -1,58 +1,42 @@ use alloc::string::ToString; +use uefi::boot::{LoadImageSource, SearchType}; use uefi::fs::FileSystem; use uefi::proto::console::text::Output; use uefi::proto::device_path::media::FilePath; use uefi::proto::device_path::{DevicePath, LoadedImageDevicePath}; use uefi::proto::BootPolicy; -use uefi::table::boot::{BootServices, LoadImageSource, SearchType}; -use uefi::table::{Boot, SystemTable}; use uefi::{boot, CString16, Identify}; mod memory; mod misc; -pub fn test(st: &SystemTable) { - let bt = st.boot_services(); +pub fn test() { info!("Testing boot services"); - memory::test(bt); - misc::test(st); - test_locate_handles(bt); + memory::test(); + misc::test(); + test_locate_handles(); test_load_image(); } -fn test_locate_handles(bt: &BootServices) { +fn test_locate_handles() { info!("Testing the `locate_handle_buffer`/`find_handles` functions"); { // search all handles - let handles = bt - .locate_handle_buffer(SearchType::AllHandles) + let handles = boot::locate_handle_buffer(SearchType::AllHandles) .expect("Failed to locate handle buffer"); assert!(!handles.is_empty(), "Could not find any handles"); - - // Compare with freestanding version. - assert_eq!( - *handles, - *boot::locate_handle_buffer(SearchType::AllHandles).unwrap() - ); } { // search by protocol - let handles = bt - .locate_handle_buffer(SearchType::ByProtocol(&Output::GUID)) + let handles = boot::locate_handle_buffer(SearchType::ByProtocol(&Output::GUID)) .expect("Failed to locate handle buffer"); assert!( !handles.is_empty(), "Could not find any OUTPUT protocol handles" ); - // Compare with freestanding version. - assert_eq!( - *handles, - *boot::locate_handle_buffer(SearchType::ByProtocol(&Output::GUID)).unwrap() - ); - // Compare with `boot::find_handles`. This implicitly tests // `boot::locate_handle` as well. let handles_vec = boot::find_handles::().unwrap(); diff --git a/uefi-test-runner/src/main.rs b/uefi-test-runner/src/main.rs index d6dec41f5..43c7a3d21 100644 --- a/uefi-test-runner/src/main.rs +++ b/uefi-test-runner/src/main.rs @@ -1,8 +1,5 @@ #![no_std] #![no_main] -// TODO: temporarily allow deprecated code so that we can continue to test -// SystemTable/BootServices. -#![allow(deprecated)] #[macro_use] extern crate log; @@ -24,16 +21,10 @@ mod proto; mod runtime; #[entry] -fn efi_main(image: Handle, mut st: SystemTable) -> Status { +fn efi_main() -> Status { // Initialize utilities (logging, memory allocation...) uefi::helpers::init().expect("Failed to initialize utilities"); - // unit tests here - - let firmware_vendor = st.firmware_vendor(); - info!("Firmware Vendor: {}", firmware_vendor); - assert_eq!(firmware_vendor.to_string(), "EDK II"); - // Test print! and println! macros. let (print, println) = ("print!", "println!"); // necessary for clippy to ignore print!("Testing {} macro with formatting: {:#010b} ", print, 155u8); @@ -43,18 +34,16 @@ fn efi_main(image: Handle, mut st: SystemTable) -> Status { ); // Reset the console before running all the other tests. - st.stdout().reset(false).expect("Failed to reset stdout"); - - // Ensure the tests are run on a version of UEFI we support. - check_revision(st.uefi_revision()); + system::with_stdout(|stdout| stdout.reset(false).expect("Failed to reset stdout")); // Check the `uefi::system` module. - check_system(&st); + check_system(); // Try retrieving a handle to the file system the image was booted from. - uefi::boot::get_image_file_system(image).expect("Failed to retrieve boot file system"); + uefi::boot::get_image_file_system(uefi::boot::image_handle()) + .expect("Failed to retrieve boot file system"); - boot::test(&st); + boot::test(); // Test all the supported protocols. proto::test(); @@ -65,7 +54,7 @@ fn efi_main(image: Handle, mut st: SystemTable) -> Status { runtime::test(); - shutdown(st); + shutdown(); } fn check_revision(rev: uefi::table::Revision) { @@ -82,13 +71,13 @@ fn check_revision(rev: uefi::table::Revision) { ); } -fn check_system(st: &SystemTable) { +fn check_system() { + info!("Firmware Vendor: {}", system::firmware_vendor()); + info!("Firmware Revision: {}", system::firmware_revision()); + assert_eq!(system::firmware_vendor(), cstr16!("EDK II")); check_revision(system::uefi_revision()); - assert_eq!(system::firmware_revision(), st.firmware_revision()); - system::with_config_table(|t| assert_eq!(t, st.config_table())); - system::with_stdout(|stdout| { stdout .output_string(cstr16!("test system::with_stdout\n")) @@ -201,9 +190,9 @@ fn send_request_to_host(request: HostRequest) { } } -fn shutdown(mut st: SystemTable) -> ! { +fn shutdown() -> ! { // Get our text output back. - st.stdout().reset(false).unwrap(); + system::with_stdout(|stdout| stdout.reset(false).unwrap()); // Tell the host that tests are done. We are about to exit boot // services, so we can't easily communicate with the host any later