|
4 | 4 |
|
5 | 5 | use crate::data_types::PhysicalAddress;
|
6 | 6 | use crate::mem::memory_map::{MemoryMapBackingMemory, MemoryMapKey, MemoryMapMeta, MemoryMapOwned};
|
| 7 | +use crate::polyfill::maybe_uninit_slice_assume_init_ref; |
7 | 8 | use crate::proto::device_path::DevicePath;
|
8 | 9 | use crate::proto::{Protocol, ProtocolPointer};
|
9 | 10 | use crate::table::Revision;
|
10 | 11 | use crate::util::opt_nonnull_to_ptr;
|
11 | 12 | use core::ffi::c_void;
|
| 13 | +use core::mem::MaybeUninit; |
12 | 14 | use core::ops::{Deref, DerefMut};
|
13 | 15 | use core::ptr::{self, NonNull};
|
14 | 16 | use core::sync::atomic::{AtomicPtr, Ordering};
|
@@ -667,6 +669,47 @@ pub fn locate_device_path<P: ProtocolPointer + ?Sized>(
|
667 | 669 | }
|
668 | 670 | }
|
669 | 671 |
|
| 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 | + |
670 | 713 | /// Returns an array of handles that support the requested protocol in a
|
671 | 714 | /// pool-allocated buffer.
|
672 | 715 | ///
|
|
0 commit comments