Skip to content

Commit 6b49c6f

Browse files
boot: Add freestanding locate_handle
This is one of the older parts of uefi-rs, so the API of the BootServices version didn't quite match our current conventions. Changed the input buffer to not be an `Option`, and changed the buffer-too-small case to be an error rather than returning `Ok(usize)`.
1 parent a7d321b commit 6b49c6f

File tree

1 file changed

+43
-0
lines changed

1 file changed

+43
-0
lines changed

uefi/src/boot.rs

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,13 @@
44
55
use crate::data_types::PhysicalAddress;
66
use crate::mem::memory_map::{MemoryMapBackingMemory, MemoryMapKey, MemoryMapMeta, MemoryMapOwned};
7+
use crate::polyfill::maybe_uninit_slice_assume_init_ref;
78
use crate::proto::device_path::DevicePath;
89
use crate::proto::{Protocol, ProtocolPointer};
910
use crate::table::Revision;
1011
use crate::util::opt_nonnull_to_ptr;
1112
use core::ffi::c_void;
13+
use core::mem::MaybeUninit;
1214
use core::ops::{Deref, DerefMut};
1315
use core::ptr::{self, NonNull};
1416
use core::sync::atomic::{AtomicPtr, Ordering};
@@ -667,6 +669,47 @@ pub fn locate_device_path<P: ProtocolPointer + ?Sized>(
667669
}
668670
}
669671

672+
/// Enumerates all handles installed on the system which match a certain query.
673+
///
674+
/// # Errors
675+
///
676+
/// * [`Status::NOT_FOUND`]: no matching handles found.
677+
/// * [`Status::BUFFER_TOO_SMALL`]: the buffer is not large enough. The required
678+
/// size (in number of handles, not bytes) will be returned in the error data.
679+
pub fn locate_handle<'buf>(
680+
search_ty: SearchType,
681+
buffer: &'buf mut [MaybeUninit<Handle>],
682+
) -> Result<&'buf [Handle], Option<usize>> {
683+
let bt = boot_services_raw_panicking();
684+
let bt = unsafe { bt.as_ref() };
685+
686+
// Obtain the needed data from the parameters.
687+
let (ty, guid, key) = match search_ty {
688+
SearchType::AllHandles => (0, ptr::null(), ptr::null()),
689+
SearchType::ByRegisterNotify(registration) => {
690+
(1, ptr::null(), registration.0.as_ptr().cast_const())
691+
}
692+
SearchType::ByProtocol(guid) => (2, guid as *const Guid, ptr::null()),
693+
};
694+
695+
let mut buffer_size = buffer.len() * mem::size_of::<Handle>();
696+
let status =
697+
unsafe { (bt.locate_handle)(ty, guid, key, &mut buffer_size, buffer.as_mut_ptr().cast()) };
698+
699+
let num_handles = buffer_size / mem::size_of::<Handle>();
700+
701+
match status {
702+
Status::SUCCESS => {
703+
let buffer = &buffer[..num_handles];
704+
// SAFETY: the entries up to `num_handles` have been initialized.
705+
let handles = unsafe { maybe_uninit_slice_assume_init_ref(buffer) };
706+
Ok(handles)
707+
}
708+
Status::BUFFER_TOO_SMALL => Err(Error::new(status, Some(num_handles))),
709+
_ => Err(Error::new(status, None)),
710+
}
711+
}
712+
670713
/// Returns an array of handles that support the requested protocol in a
671714
/// pool-allocated buffer.
672715
///

0 commit comments

Comments
 (0)