|
10 | 10 | //! - More information about protocols can be found [here](https://edk2-docs.gitbook.io/edk-ii-uefi-driver-writer-s-guide/3_foundation/36_protocols_and_handles)
|
11 | 11 |
|
12 | 12 | use r_efi::efi::{self, Guid};
|
| 13 | +use r_efi::protocols::{device_path, device_path_to_text}; |
13 | 14 |
|
| 15 | +use crate::alloc::Layout; |
| 16 | +use crate::ffi::OsString; |
14 | 17 | use crate::mem::{size_of, MaybeUninit};
|
15 | 18 | use crate::os::uefi;
|
| 19 | +use crate::os::uefi::ffi::OsStringExt; |
16 | 20 | use crate::ptr::NonNull;
|
| 21 | +use crate::slice; |
| 22 | +use crate::sys_common::wstr::WStrUnits; |
17 | 23 | use crate::{
|
18 | 24 | io::{self, const_io_error},
|
19 | 25 | os::uefi::env::boot_services,
|
@@ -142,7 +148,50 @@ pub(crate) unsafe fn close_event(evt: NonNull<crate::ffi::c_void>) -> io::Result
|
142 | 148 |
|
143 | 149 | /// Get the Protocol for current system handle.
|
144 | 150 | /// Note: Some protocols need to be manually freed. It is the callers responsibility to do so.
|
145 |
| -pub(crate) fn image_handle_protocol<T>(protocol_guid: Guid) -> Option<NonNull<T>> { |
146 |
| - let system_handle = uefi::env::try_image_handle()?; |
147 |
| - open_protocol(system_handle, protocol_guid).ok() |
| 151 | +pub(crate) fn image_handle_protocol<T>(protocol_guid: Guid) -> io::Result<NonNull<T>> { |
| 152 | + let system_handle = uefi::env::try_image_handle().ok_or(io::const_io_error!( |
| 153 | + io::ErrorKind::NotFound, |
| 154 | + "Protocol not found in Image handle" |
| 155 | + ))?; |
| 156 | + open_protocol(system_handle, protocol_guid) |
| 157 | +} |
| 158 | + |
| 159 | +pub(crate) fn device_path_to_text(path: *mut device_path::Protocol) -> io::Result<OsString> { |
| 160 | + let device_path_to_text_handles = locate_handles(device_path_to_text::PROTOCOL_GUID)?; |
| 161 | + for handle in device_path_to_text_handles { |
| 162 | + let Ok(protocol) = open_protocol::<device_path_to_text::Protocol>( |
| 163 | + handle, |
| 164 | + device_path_to_text::PROTOCOL_GUID, |
| 165 | + ) else { |
| 166 | + continue; |
| 167 | + }; |
| 168 | + |
| 169 | + let path_ptr: *mut r_efi::efi::Char16 = unsafe { |
| 170 | + ((*protocol.as_ptr()).convert_device_path_to_text)( |
| 171 | + path, |
| 172 | + r_efi::efi::Boolean::FALSE, |
| 173 | + r_efi::efi::Boolean::FALSE, |
| 174 | + ) |
| 175 | + }; |
| 176 | + |
| 177 | + // SAFETY: Error only occurs if path is NULL. Thus no need to dealloc path_ptr |
| 178 | + let path_len = unsafe { |
| 179 | + WStrUnits::new(path_ptr) |
| 180 | + .ok_or(io::const_io_error!(io::ErrorKind::InvalidData, "Invalid path"))? |
| 181 | + .count() |
| 182 | + }; |
| 183 | + |
| 184 | + let path = OsString::from_wide(unsafe { slice::from_raw_parts(path_ptr.cast(), path_len) }); |
| 185 | + |
| 186 | + unsafe { |
| 187 | + // UEFI Spec says all allocations are 8 byte aligned |
| 188 | + crate::alloc::dealloc( |
| 189 | + path_ptr.cast(), |
| 190 | + Layout::from_size_align_unchecked(path_len * size_of::<u16>(), 8), |
| 191 | + ); |
| 192 | + } |
| 193 | + return Ok(path); |
| 194 | + } |
| 195 | + |
| 196 | + Err(io::const_io_error!(io::ErrorKind::NotFound, "No device path to text protocol found")) |
148 | 197 | }
|
0 commit comments