diff --git a/uefi-test-runner/src/proto/mod.rs b/uefi-test-runner/src/proto/mod.rs index 6348aac73..0c900d84c 100644 --- a/uefi-test-runner/src/proto/mod.rs +++ b/uefi-test-runner/src/proto/mod.rs @@ -1,6 +1,7 @@ +use uefi::boot::{self, OpenProtocolParams}; use uefi::prelude::*; use uefi::proto::loaded_image::LoadedImage; -use uefi::{boot, proto, Identify}; +use uefi::{proto, Identify}; pub fn test(st: &mut SystemTable) { info!("Testing various protocols"); @@ -11,6 +12,7 @@ pub fn test(st: &mut SystemTable) { find_protocol(bt); test_protocols_per_handle(bt); test_protocols_per_handle_freestanding(); + test_test_protocol_freestanding(); debug::test(bt); device_path::test(bt); @@ -63,6 +65,15 @@ fn test_protocols_per_handle_freestanding() { assert!(pph.iter().any(|guid| **guid == LoadedImage::GUID)); } +fn test_test_protocol_freestanding() { + assert!(boot::test_protocol::(OpenProtocolParams { + handle: boot::image_handle(), + agent: boot::image_handle(), + controller: None, + }) + .unwrap()); +} + mod console; mod debug; mod device_path; diff --git a/uefi/src/boot.rs b/uefi/src/boot.rs index b0e93a74d..e86edcb87 100644 --- a/uefi/src/boot.rs +++ b/uefi/src/boot.rs @@ -11,7 +11,7 @@ use core::ops::{Deref, DerefMut}; use core::ptr::{self, NonNull}; use core::sync::atomic::{AtomicPtr, Ordering}; use core::{mem, slice}; -use uefi::{table, Char16, Event, Guid, Handle, Result, Status, StatusExt}; +use uefi::{table, Char16, Error, Event, Guid, Handle, Result, Status, StatusExt}; use uefi_raw::table::boot::InterfaceType; #[cfg(doc)] @@ -612,6 +612,38 @@ pub fn open_protocol_exclusive( } } +/// Tests whether a handle supports a protocol. +/// +/// Returns `Ok(true)` if the handle supports the protocol, `Ok(false)` if not. +/// +/// # Errors +/// +/// * [`Status::INVALID_PARAMETER`]: one of the handles in `params` is invalid. +pub fn test_protocol(params: OpenProtocolParams) -> Result { + const TEST_PROTOCOL: u32 = 0x04; + + let bt = boot_services_raw_panicking(); + let bt = unsafe { bt.as_ref() }; + + let mut interface = ptr::null_mut(); + let status = unsafe { + (bt.open_protocol)( + params.handle.as_ptr(), + &P::GUID, + &mut interface, + params.agent.as_ptr(), + Handle::opt_to_ptr(params.controller), + TEST_PROTOCOL, + ) + }; + + match status { + Status::SUCCESS => Ok(true), + Status::UNSUPPORTED => Ok(false), + _ => Err(Error::from(status)), + } +} + /// Loads a UEFI image into memory and return a [`Handle`] to the image. /// /// There are two ways to load the image: by copying raw image data