Skip to content

Commit 0358496

Browse files
authored
Merge pull request #1269 from nicholasbishop/bishop-handle-buf
Add `boot::locate_handle_buffer`
2 parents 112e20b + edec228 commit 0358496

File tree

3 files changed

+70
-3
lines changed

3 files changed

+70
-3
lines changed

uefi-test-runner/src/boot/mod.rs

+13-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ use uefi::proto::device_path::media::FilePath;
55
use uefi::proto::device_path::{DevicePath, LoadedImageDevicePath};
66
use uefi::table::boot::{BootServices, LoadImageSource, SearchType};
77
use uefi::table::{Boot, SystemTable};
8-
use uefi::{CString16, Identify};
8+
use uefi::{boot, CString16, Identify};
99

1010
mod memory;
1111
mod misc;
@@ -28,6 +28,12 @@ fn test_locate_handle_buffer(bt: &BootServices) {
2828
.locate_handle_buffer(SearchType::AllHandles)
2929
.expect("Failed to locate handle buffer");
3030
assert!(!handles.is_empty(), "Could not find any handles");
31+
32+
// Compare with freestanding version.
33+
assert_eq!(
34+
*handles,
35+
*boot::locate_handle_buffer(SearchType::AllHandles).unwrap()
36+
);
3137
}
3238

3339
{
@@ -39,6 +45,12 @@ fn test_locate_handle_buffer(bt: &BootServices) {
3945
!handles.is_empty(),
4046
"Could not find any OUTPUT protocol handles"
4147
);
48+
49+
// Compare with freestanding version.
50+
assert_eq!(
51+
*handles,
52+
*boot::locate_handle_buffer(SearchType::ByProtocol(&Output::GUID)).unwrap()
53+
);
4254
}
4355
}
4456

uefi/src/boot.rs

+56-1
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,16 @@
44
55
use crate::data_types::PhysicalAddress;
66
use core::ffi::c_void;
7+
use core::ops::Deref;
78
use core::ptr::{self, NonNull};
9+
use core::slice;
810
use core::sync::atomic::{AtomicPtr, Ordering};
911
use uefi::{table, Handle, Result, StatusExt};
1012

1113
#[cfg(doc)]
1214
use uefi::Status;
1315

14-
pub use uefi::table::boot::AllocateType;
16+
pub use uefi::table::boot::{AllocateType, SearchType};
1517
pub use uefi_raw::table::boot::MemoryType;
1618

1719
/// Global image handle. This is only set by [`set_image_handle`], and it is
@@ -128,3 +130,56 @@ pub unsafe fn free_pool(ptr: NonNull<u8>) -> Result {
128130

129131
unsafe { (bt.free_pool)(ptr.as_ptr()) }.to_result()
130132
}
133+
134+
/// Returns an array of handles that support the requested protocol in a
135+
/// pool-allocated buffer.
136+
///
137+
/// See [`SearchType`] for details of the available search operations.
138+
///
139+
/// # Errors
140+
///
141+
/// * [`Status::NOT_FOUND`]: no matching handles.
142+
/// * [`Status::OUT_OF_RESOURCES`]: out of memory.
143+
pub fn locate_handle_buffer(search_ty: SearchType) -> Result<HandleBuffer> {
144+
let bt = boot_services_raw_panicking();
145+
let bt = unsafe { bt.as_ref() };
146+
147+
let (ty, guid, key) = match search_ty {
148+
SearchType::AllHandles => (0, ptr::null(), ptr::null()),
149+
SearchType::ByRegisterNotify(registration) => {
150+
(1, ptr::null(), registration.0.as_ptr().cast_const())
151+
}
152+
SearchType::ByProtocol(guid) => (2, guid as *const _, ptr::null()),
153+
};
154+
155+
let mut num_handles: usize = 0;
156+
let mut buffer: *mut uefi_raw::Handle = ptr::null_mut();
157+
unsafe { (bt.locate_handle_buffer)(ty, guid, key, &mut num_handles, &mut buffer) }
158+
.to_result_with_val(|| HandleBuffer {
159+
count: num_handles,
160+
buffer: NonNull::new(buffer.cast())
161+
.expect("locate_handle_buffer must not return a null pointer"),
162+
})
163+
}
164+
165+
/// A buffer returned by [`locate_handle_buffer`] that contains an array of
166+
/// [`Handle`]s that support the requested protocol.
167+
#[derive(Debug, Eq, PartialEq)]
168+
pub struct HandleBuffer {
169+
count: usize,
170+
buffer: NonNull<Handle>,
171+
}
172+
173+
impl Drop for HandleBuffer {
174+
fn drop(&mut self) {
175+
let _ = unsafe { free_pool(self.buffer.cast::<u8>()) };
176+
}
177+
}
178+
179+
impl Deref for HandleBuffer {
180+
type Target = [Handle];
181+
182+
fn deref(&self) -> &Self::Target {
183+
unsafe { slice::from_raw_parts(self.buffer.as_ptr(), self.count) }
184+
}
185+
}

uefi/src/table/boot.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1716,4 +1716,4 @@ impl<'a> HandleBuffer<'a> {
17161716
/// with [`BootServices::locate_handle`] via [`SearchType::ByRegisterNotify`].
17171717
#[derive(Debug, Clone, Copy)]
17181718
#[repr(transparent)]
1719-
pub struct ProtocolSearchKey(NonNull<c_void>);
1719+
pub struct ProtocolSearchKey(pub(crate) NonNull<c_void>);

0 commit comments

Comments
 (0)