uefi: Add process · model-checking/verify-rust-std@e6eeb4e (original) (raw)
`@@ -12,7 +12,7 @@
`
12
12
`use r_efi::efi::{self, Guid};
`
13
13
`use r_efi::protocols::{device_path, device_path_to_text};
`
14
14
``
15
``
`-
use crate::ffi::OsString;
`
``
15
`+
use crate::ffi::{OsString, OsStr};
`
16
16
`use crate::io::{self, const_io_error};
`
17
17
`use crate::mem::{size_of, MaybeUninit};
`
18
18
`use crate::os::uefi::{self, env::boot_services, ffi::OsStringExt};
`
`@@ -221,3 +221,73 @@ pub(crate) fn runtime_services() -> Option<NonNull<r_efi::efi::RuntimeServices>>
`
221
221
`let runtime_services = unsafe { (*system_table.as_ptr()).runtime_services };
`
222
222
`NonNull::new(runtime_services)
`
223
223
`}
`
``
224
+
``
225
`+
pub(crate) struct DevicePath(NonNull<r_efi::protocols::device_path::Protocol>);
`
``
226
+
``
227
`+
impl DevicePath {
`
``
228
`+
pub(crate) fn from_text(p: &OsStr) -> io::Result {
`
``
229
`+
fn inner(
`
``
230
`+
p: &OsStr,
`
``
231
`+
protocol: NonNull<r_efi::protocols::device_path_from_text::Protocol>,
`
``
232
`+
) -> io::Result {
`
``
233
`+
let path_vec = p.encode_wide().chain(Some(0)).collect::<Vec>();
`
``
234
`+
let path =
`
``
235
`+
unsafe { ((*protocol.as_ptr()).convert_text_to_device_path)(path_vec.as_ptr()) };
`
``
236
+
``
237
`+
NonNull::new(path).map(DevicePath).ok_or_else(|| {
`
``
238
`+
const_io_error!(io::ErrorKind::InvalidFilename, "Invalid Device Path")
`
``
239
`+
})
`
``
240
`+
}
`
``
241
+
``
242
`+
static LAST_VALID_HANDLE: AtomicPtrcrate::ffi::c_void =
`
``
243
`+
AtomicPtr::new(crate::ptr::null_mut());
`
``
244
+
``
245
`+
if let Some(handle) = NonNull::new(LAST_VALID_HANDLE.load(Ordering::Acquire)) {
`
``
246
`+
if let Ok(protocol) = open_protocol::<r_efi::protocols::device_path_from_text::Protocol>(
`
``
247
`+
handle,
`
``
248
`+
r_efi::protocols::device_path_from_text::PROTOCOL_GUID,
`
``
249
`+
) {
`
``
250
`+
return inner(p, protocol);
`
``
251
`+
}
`
``
252
`+
}
`
``
253
+
``
254
`+
let handles = locate_handles(r_efi::protocols::device_path_from_text::PROTOCOL_GUID)?;
`
``
255
`+
for handle in handles {
`
``
256
`+
if let Ok(protocol) = open_protocol::<r_efi::protocols::device_path_from_text::Protocol>(
`
``
257
`+
handle,
`
``
258
`+
r_efi::protocols::device_path_from_text::PROTOCOL_GUID,
`
``
259
`+
) {
`
``
260
`+
LAST_VALID_HANDLE.store(handle.as_ptr(), Ordering::Release);
`
``
261
`+
return inner(p, protocol);
`
``
262
`+
}
`
``
263
`+
}
`
``
264
+
``
265
`+
io::Result::Err(const_io_error!(
`
``
266
`+
io::ErrorKind::NotFound,
`
``
267
`+
"DevicePathFromText Protocol not found"
`
``
268
`+
))
`
``
269
`+
}
`
``
270
`+
}
`
``
271
+
``
272
`+
impl AsRef<r_efi::protocols::device_path::Protocol> for DevicePath {
`
``
273
`+
fn as_ref(&self) -> &r_efi::protocols::device_path::Protocol {
`
``
274
`+
unsafe { self.0.as_ref() }
`
``
275
`+
}
`
``
276
`+
}
`
``
277
+
``
278
`+
impl AsMut<r_efi::protocols::device_path::Protocol> for DevicePath {
`
``
279
`+
fn as_mut(&mut self) -> &mut r_efi::protocols::device_path::Protocol {
`
``
280
`+
unsafe { self.0.as_mut() }
`
``
281
`+
}
`
``
282
`+
}
`
``
283
+
``
284
`+
impl Drop for DevicePath {
`
``
285
`+
fn drop(&mut self) {
`
``
286
`+
if let Some(bt) = boot_services() {
`
``
287
`+
let bt: NonNull<r_efi::efi::BootServices> = bt.cast();
`
``
288
`+
unsafe {
`
``
289
`+
((*bt.as_ptr()).free_pool)(self.0.as_ptr() as *mut crate::ffi::c_void);
`
``
290
`+
}
`
``
291
`+
}
`
``
292
`+
}
`
``
293
`+
}
`