Skip to content

Commit e290398

Browse files
committed
uefi: process: Fixes from PR
- Update system table crc32 - Fix unsound use of Box - Free exit data - Code improvements - Introduce OwnedTable - Update r-efi to latest version - Use extended_varargs_abi_support for install_multiple_protocol_interfaces and uninstall_multiple_protocol_interfaces - Fix comments - Stub out args implementation Signed-off-by: Ayush Singh <[email protected]>
1 parent 56e2a57 commit e290398

File tree

4 files changed

+232
-152
lines changed

4 files changed

+232
-152
lines changed

library/std/Cargo.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ hermit-abi = { version = "0.4.0", features = ['rustc-dep-of-std'], public = true
5656
wasi = { version = "0.11.0", features = ['rustc-dep-of-std'], default-features = false }
5757

5858
[target.'cfg(target_os = "uefi")'.dependencies]
59-
r-efi = { version = "4.2.0", features = ['rustc-dep-of-std'] }
59+
r-efi = { version = "4.5.0", features = ['rustc-dep-of-std'] }
6060
r-efi-alloc = { version = "1.0.0", features = ['rustc-dep-of-std'] }
6161

6262
[features]

library/std/src/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -293,6 +293,7 @@
293293
#![feature(doc_masked)]
294294
#![feature(doc_notable_trait)]
295295
#![feature(dropck_eyepatch)]
296+
#![feature(extended_varargs_abi_support)]
296297
#![feature(f128)]
297298
#![feature(f16)]
298299
#![feature(if_let_guard)]

library/std/src/sys/pal/uefi/helpers.rs

+92-39
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,12 @@ use crate::slice;
2121
use crate::sync::atomic::{AtomicPtr, Ordering};
2222
use crate::sys_common::wstr::WStrUnits;
2323

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+
2430
const BOOT_SERVICES_UNAVAILABLE: io::Error =
2531
const_io_error!(io::ErrorKind::Other, "Boot Services are no longer available");
2632

@@ -231,6 +237,13 @@ impl DevicePath {
231237
protocol: NonNull<r_efi::protocols::device_path_from_text::Protocol>,
232238
) -> io::Result<DevicePath> {
233239
let path_vec = p.encode_wide().chain(Some(0)).collect::<Vec<u16>>();
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+
234247
let path =
235248
unsafe { ((*protocol.as_ptr()).convert_text_to_device_path)(path_vec.as_ptr()) };
236249

@@ -267,17 +280,9 @@ impl DevicePath {
267280
"DevicePathFromText Protocol not found"
268281
))
269282
}
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-
}
277283

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() }
284+
pub(crate) fn as_ptr(&self) -> *mut r_efi::protocols::device_path::Protocol {
285+
self.0.as_ptr()
281286
}
282287
}
283288

@@ -292,74 +297,122 @@ impl Drop for DevicePath {
292297
}
293298
}
294299

295-
pub(crate) struct Protocol<T> {
300+
pub(crate) struct OwnedProtocol<T> {
296301
guid: r_efi::efi::Guid,
297302
handle: NonNull<crate::ffi::c_void>,
298-
protocol: Box<T>,
303+
protocol: *mut T,
299304
}
300305

301-
impl<T> Protocol<T> {
302-
const fn new(
303-
guid: r_efi::efi::Guid,
304-
handle: NonNull<crate::ffi::c_void>,
305-
protocol: Box<T>,
306-
) -> Self {
307-
Self { guid, handle, protocol }
308-
}
309-
310-
pub(crate) fn create(protocol: T, mut guid: r_efi::efi::Guid) -> io::Result<Self> {
311-
let boot_services: NonNull<r_efi::efi::BootServices> =
306+
impl<T> OwnedProtocol<T> {
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<Self> {
309+
let bt: NonNull<r_efi::efi::BootServices> =
312310
boot_services().ok_or(BOOT_SERVICES_UNAVAILABLE)?.cast();
313-
let mut protocol = Box::new(protocol);
311+
let protocol: *mut T = Box::into_raw(Box::new(protocol));
314312
let mut handle: r_efi::efi::Handle = crate::ptr::null_mut();
315313

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+
316318
let r = unsafe {
317-
((*boot_services.as_ptr()).install_protocol_interface)(
319+
func(
318320
&mut handle,
319-
&mut guid,
320-
r_efi::efi::NATIVE_INTERFACE,
321-
protocol.as_mut() as *mut T as *mut crate::ffi::c_void,
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,
322324
)
323325
};
324326

325327
if r.is_error() {
328+
drop(unsafe { Box::from_raw(protocol) });
326329
return Err(crate::io::Error::from_raw_os_error(r.as_usize()));
327330
};
328331

329332
let handle = NonNull::new(handle)
330333
.ok_or(io::const_io_error!(io::ErrorKind::Uncategorized, "found null handle"))?;
331334

332-
Ok(Self::new(guid, handle, protocol))
335+
Ok(Self { guid, handle, protocol })
333336
}
334337

335338
pub(crate) fn handle(&self) -> NonNull<crate::ffi::c_void> {
336339
self.handle
337340
}
338341
}
339342

340-
impl<T> Drop for Protocol<T> {
343+
impl<T> Drop for OwnedProtocol<T> {
341344
fn drop(&mut self) {
345+
// Do not deallocate a runtime protocol
342346
if let Some(bt) = boot_services() {
343347
let bt: NonNull<r_efi::efi::BootServices> = bt.cast();
344-
unsafe {
345-
((*bt.as_ptr()).uninstall_protocol_interface)(
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(
346354
self.handle.as_ptr(),
347-
&mut self.guid,
348-
self.protocol.as_mut() as *mut T as *mut crate::ffi::c_void,
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,
349358
)
350359
};
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+
}
351365
}
352366
}
353367
}
354368

355-
impl<T> AsRef<T> for Protocol<T> {
369+
impl<T> AsRef<T> for OwnedProtocol<T> {
356370
fn as_ref(&self) -> &T {
357-
&self.protocol
371+
unsafe { self.protocol.as_ref().unwrap() }
372+
}
373+
}
374+
375+
pub(crate) struct OwnedTable<T> {
376+
layout: crate::alloc::Layout,
377+
ptr: *mut T,
378+
}
379+
380+
impl<T> OwnedTable<T> {
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
358394
}
359395
}
360396

361-
impl<T> AsMut<T> for Protocol<T> {
362-
fn as_mut(&mut self) -> &mut T {
363-
&mut self.protocol
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<T> Drop for OwnedTable<T> {
415+
fn drop(&mut self) {
416+
unsafe { crate::alloc::dealloc(self.ptr as *mut u8, self.layout) };
364417
}
365418
}

0 commit comments

Comments
 (0)