Rollup merge of #123196 - Ayush1325:uefi-process, r=joboet · model-checking/verify-rust-std@a077eb1 (original) (raw)
`@@ -12,15 +12,21 @@
`
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::{OsStr, OsString};
`
16
16
`use crate::io::{self, const_io_error};
`
17
17
`use crate::mem::{size_of, MaybeUninit};
`
18
``
`-
use crate::os::uefi::{self, env::boot_services, ffi::OsStringExt};
`
``
18
`+
use crate::os::uefi::{self, env::boot_services, ffi::OsStrExt, ffi::OsStringExt};
`
19
19
`use crate::ptr::NonNull;
`
20
20
`use crate::slice;
`
21
21
`use crate::sync::atomic::{AtomicPtr, Ordering};
`
22
22
`use crate::sys_common::wstr::WStrUnits;
`
23
23
``
``
24
`+
type BootInstallMultipleProtocolInterfaces =
`
``
25
`+
unsafe extern "efiapi" fn(_: *mut r_efi::efi::Handle, _: ...) -> r_efi::efi::Status;
`
``
26
+
``
27
`+
type BootUninstallMultipleProtocolInterfaces =
`
``
28
`+
unsafe extern "efiapi" fn(_: r_efi::efi::Handle, _: ...) -> r_efi::efi::Status;
`
``
29
+
24
30
`const BOOT_SERVICES_UNAVAILABLE: io::Error =
`
25
31
`const_io_error!(io::ErrorKind::Other, "Boot Services are no longer available");
`
26
32
``
`@@ -221,3 +227,192 @@ pub(crate) fn runtime_services() -> Option<NonNull<r_efi::efi::RuntimeServices>>
`
221
227
`let runtime_services = unsafe { (*system_table.as_ptr()).runtime_services };
`
222
228
`NonNull::new(runtime_services)
`
223
229
`}
`
``
230
+
``
231
`+
pub(crate) struct DevicePath(NonNull<r_efi::protocols::device_path::Protocol>);
`
``
232
+
``
233
`+
impl DevicePath {
`
``
234
`+
pub(crate) fn from_text(p: &OsStr) -> io::Result {
`
``
235
`+
fn inner(
`
``
236
`+
p: &OsStr,
`
``
237
`+
protocol: NonNull<r_efi::protocols::device_path_from_text::Protocol>,
`
``
238
`+
) -> io::Result {
`
``
239
`+
let path_vec = p.encode_wide().chain(Some(0)).collect::<Vec>();
`
``
240
`+
if path_vec[..path_vec.len() - 1].contains(&0) {
`
``
241
`+
return Err(const_io_error!(
`
``
242
`+
io::ErrorKind::InvalidInput,
`
``
243
`+
"strings passed to UEFI cannot contain NULs",
`
``
244
`+
));
`
``
245
`+
}
`
``
246
+
``
247
`+
let path =
`
``
248
`+
unsafe { ((*protocol.as_ptr()).convert_text_to_device_path)(path_vec.as_ptr()) };
`
``
249
+
``
250
`+
NonNull::new(path).map(DevicePath).ok_or_else(|| {
`
``
251
`+
const_io_error!(io::ErrorKind::InvalidFilename, "Invalid Device Path")
`
``
252
`+
})
`
``
253
`+
}
`
``
254
+
``
255
`+
static LAST_VALID_HANDLE: AtomicPtrcrate::ffi::c_void =
`
``
256
`+
AtomicPtr::new(crate::ptr::null_mut());
`
``
257
+
``
258
`+
if let Some(handle) = NonNull::new(LAST_VALID_HANDLE.load(Ordering::Acquire)) {
`
``
259
`+
if let Ok(protocol) = open_protocol::<r_efi::protocols::device_path_from_text::Protocol>(
`
``
260
`+
handle,
`
``
261
`+
r_efi::protocols::device_path_from_text::PROTOCOL_GUID,
`
``
262
`+
) {
`
``
263
`+
return inner(p, protocol);
`
``
264
`+
}
`
``
265
`+
}
`
``
266
+
``
267
`+
let handles = locate_handles(r_efi::protocols::device_path_from_text::PROTOCOL_GUID)?;
`
``
268
`+
for handle in handles {
`
``
269
`+
if let Ok(protocol) = open_protocol::<r_efi::protocols::device_path_from_text::Protocol>(
`
``
270
`+
handle,
`
``
271
`+
r_efi::protocols::device_path_from_text::PROTOCOL_GUID,
`
``
272
`+
) {
`
``
273
`+
LAST_VALID_HANDLE.store(handle.as_ptr(), Ordering::Release);
`
``
274
`+
return inner(p, protocol);
`
``
275
`+
}
`
``
276
`+
}
`
``
277
+
``
278
`+
io::Result::Err(const_io_error!(
`
``
279
`+
io::ErrorKind::NotFound,
`
``
280
`+
"DevicePathFromText Protocol not found"
`
``
281
`+
))
`
``
282
`+
}
`
``
283
+
``
284
`+
pub(crate) fn as_ptr(&self) -> *mut r_efi::protocols::device_path::Protocol {
`
``
285
`+
self.0.as_ptr()
`
``
286
`+
}
`
``
287
`+
}
`
``
288
+
``
289
`+
impl Drop for DevicePath {
`
``
290
`+
fn drop(&mut self) {
`
``
291
`+
if let Some(bt) = boot_services() {
`
``
292
`+
let bt: NonNull<r_efi::efi::BootServices> = bt.cast();
`
``
293
`+
unsafe {
`
``
294
`+
((*bt.as_ptr()).free_pool)(self.0.as_ptr() as *mut crate::ffi::c_void);
`
``
295
`+
}
`
``
296
`+
}
`
``
297
`+
}
`
``
298
`+
}
`
``
299
+
``
300
`+
pub(crate) struct OwnedProtocol {
`
``
301
`+
guid: r_efi::efi::Guid,
`
``
302
`+
handle: NonNullcrate::ffi::c_void,
`
``
303
`+
protocol: *mut T,
`
``
304
`+
}
`
``
305
+
``
306
`+
impl OwnedProtocol {
`
``
307
`+
// FIXME: Consider using unsafe trait for matching protocol with guid
`
``
308
`+
pub(crate) unsafe fn create(protocol: T, mut guid: r_efi::efi::Guid) -> io::Result {
`
``
309
`+
let bt: NonNull<r_efi::efi::BootServices> =
`
``
310
`+
boot_services().ok_or(BOOT_SERVICES_UNAVAILABLE)?.cast();
`
``
311
`+
let protocol: *mut T = Box::into_raw(Box::new(protocol));
`
``
312
`+
let mut handle: r_efi::efi::Handle = crate::ptr::null_mut();
`
``
313
+
``
314
`+
// FIXME: Move into r-efi once extended_varargs_abi_support is stablized
`
``
315
`+
let func: BootInstallMultipleProtocolInterfaces =
`
``
316
`+
unsafe { crate::mem::transmute((*bt.as_ptr()).install_multiple_protocol_interfaces) };
`
``
317
+
``
318
`+
let r = unsafe {
`
``
319
`+
func(
`
``
320
`+
&mut handle,
`
``
321
`+
&mut guid as *mut _ as *mut crate::ffi::c_void,
`
``
322
`+
protocol as *mut crate::ffi::c_void,
`
``
323
`+
crate::ptr::null_mut() as *mut crate::ffi::c_void,
`
``
324
`+
)
`
``
325
`+
};
`
``
326
+
``
327
`+
if r.is_error() {
`
``
328
`+
drop(unsafe { Box::from_raw(protocol) });
`
``
329
`+
return Err(crate::io::Error::from_raw_os_error(r.as_usize()));
`
``
330
`+
};
`
``
331
+
``
332
`+
let handle = NonNull::new(handle)
`
``
333
`+
.ok_or(io::const_io_error!(io::ErrorKind::Uncategorized, "found null handle"))?;
`
``
334
+
``
335
`+
Ok(Self { guid, handle, protocol })
`
``
336
`+
}
`
``
337
+
``
338
`+
pub(crate) fn handle(&self) -> NonNullcrate::ffi::c_void {
`
``
339
`+
self.handle
`
``
340
`+
}
`
``
341
`+
}
`
``
342
+
``
343
`+
impl Drop for OwnedProtocol {
`
``
344
`+
fn drop(&mut self) {
`
``
345
`+
// Do not deallocate a runtime protocol
`
``
346
`+
if let Some(bt) = boot_services() {
`
``
347
`+
let bt: NonNull<r_efi::efi::BootServices> = bt.cast();
`
``
348
`+
// FIXME: Move into r-efi once extended_varargs_abi_support is stablized
`
``
349
`+
let func: BootUninstallMultipleProtocolInterfaces = unsafe {
`
``
350
`+
crate::mem::transmute((*bt.as_ptr()).uninstall_multiple_protocol_interfaces)
`
``
351
`+
};
`
``
352
`+
let status = unsafe {
`
``
353
`+
func(
`
``
354
`+
self.handle.as_ptr(),
`
``
355
`+
&mut self.guid as *mut _ as *mut crate::ffi::c_void,
`
``
356
`+
self.protocol as *mut crate::ffi::c_void,
`
``
357
`+
crate::ptr::null_mut() as *mut crate::ffi::c_void,
`
``
358
`+
)
`
``
359
`+
};
`
``
360
+
``
361
`+
// Leak the protocol in case uninstall fails
`
``
362
`+
if status == r_efi::efi::Status::SUCCESS {
`
``
363
`+
let _ = unsafe { Box::from_raw(self.protocol) };
`
``
364
`+
}
`
``
365
`+
}
`
``
366
`+
}
`
``
367
`+
}
`
``
368
+
``
369
`+
impl AsRef for OwnedProtocol {
`
``
370
`+
fn as_ref(&self) -> &T {
`
``
371
`+
unsafe { self.protocol.as_ref().unwrap() }
`
``
372
`+
}
`
``
373
`+
}
`
``
374
+
``
375
`+
pub(crate) struct OwnedTable {
`
``
376
`+
layout: crate::alloc::Layout,
`
``
377
`+
ptr: *mut T,
`
``
378
`+
}
`
``
379
+
``
380
`+
impl OwnedTable {
`
``
381
`+
pub(crate) fn from_table_header(hdr: &r_efi::efi::TableHeader) -> Self {
`
``
382
`+
let header_size = hdr.header_size as usize;
`
``
383
`+
let layout = crate::alloc::Layout::from_size_align(header_size, 8).unwrap();
`
``
384
`+
let ptr = unsafe { crate::alloc::alloc(layout) as *mut T };
`
``
385
`+
Self { layout, ptr }
`
``
386
`+
}
`
``
387
+
``
388
`+
pub(crate) const fn as_ptr(&self) -> *const T {
`
``
389
`+
self.ptr
`
``
390
`+
}
`
``
391
+
``
392
`+
pub(crate) const fn as_mut_ptr(&self) -> *mut T {
`
``
393
`+
self.ptr
`
``
394
`+
}
`
``
395
`+
}
`
``
396
+
``
397
`+
impl OwnedTable<r_efi::efi::SystemTable> {
`
``
398
`+
pub(crate) fn from_table(tbl: *const r_efi::efi::SystemTable) -> Self {
`
``
399
`+
let hdr = unsafe { (*tbl).hdr };
`
``
400
+
``
401
`+
let owned_tbl = Self::from_table_header(&hdr);
`
``
402
`+
unsafe {
`
``
403
`+
crate::ptr::copy_nonoverlapping(
`
``
404
`+
tbl as *const u8,
`
``
405
`+
owned_tbl.as_mut_ptr() as *mut u8,
`
``
406
`+
hdr.header_size as usize,
`
``
407
`+
)
`
``
408
`+
};
`
``
409
+
``
410
`+
owned_tbl
`
``
411
`+
}
`
``
412
`+
}
`
``
413
+
``
414
`+
impl Drop for OwnedTable {
`
``
415
`+
fn drop(&mut self) {
`
``
416
`+
unsafe { crate::alloc::dealloc(self.ptr as *mut u8, self.layout) };
`
``
417
`+
}
`
``
418
`+
}
`