Skip to content

Commit 23a8525

Browse files
boot: Add freestanding find_handles
1 parent 6b49c6f commit 23a8525

File tree

1 file changed

+44
-0
lines changed

1 file changed

+44
-0
lines changed

uefi/src/boot.rs

+44
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,9 @@ use core::{mem, slice};
1818
use uefi::{table, Char16, Error, Event, Guid, Handle, Result, Status, StatusExt};
1919
use uefi_raw::table::boot::InterfaceType;
2020

21+
#[cfg(feature = "alloc")]
22+
use {alloc::vec::Vec, uefi::ResultExt};
23+
2124
#[cfg(doc)]
2225
use {
2326
crate::proto::device_path::LoadedImageDevicePath, crate::proto::loaded_image::LoadedImage,
@@ -741,6 +744,47 @@ pub fn locate_handle_buffer(search_ty: SearchType) -> Result<HandleBuffer> {
741744
})
742745
}
743746

747+
/// Returns all the handles implementing a certain protocol.
748+
///
749+
/// # Errors
750+
///
751+
/// * [`Status::NOT_FOUND`]: no matching handles.
752+
#[cfg(feature = "alloc")]
753+
pub fn find_handles<P: ProtocolPointer + ?Sized>() -> Result<Vec<Handle>> {
754+
// Search by protocol.
755+
let search_type = SearchType::from_proto::<P>();
756+
757+
// Determine how much we need to allocate.
758+
let num_handles = match locate_handle(search_type, &mut []) {
759+
Err(err) => {
760+
if err.status() == Status::BUFFER_TOO_SMALL {
761+
err.data().expect("error data is missing")
762+
} else {
763+
return Err(err.to_err_without_payload());
764+
}
765+
}
766+
// This should never happen: if no handles match the search then a
767+
// `NOT_FOUND` error should be returned.
768+
Ok(_) => panic!("locate_handle should not return success with empty buffer"),
769+
};
770+
771+
// Allocate a large enough buffer without pointless initialization.
772+
let mut handles = Vec::with_capacity(num_handles);
773+
774+
// Perform the search.
775+
let num_handles = locate_handle(search_type, handles.spare_capacity_mut())
776+
.discard_errdata()?
777+
.len();
778+
779+
// Mark the returned number of elements as initialized.
780+
unsafe {
781+
handles.set_len(num_handles);
782+
}
783+
784+
// Emit output, with warnings
785+
Ok(handles)
786+
}
787+
744788
/// Find an arbitrary handle that supports a particular [`Protocol`]. Returns
745789
/// [`NOT_FOUND`] if no handles support the protocol.
746790
///

0 commit comments

Comments
 (0)