@@ -13,11 +13,8 @@ unsafe impl GlobalAlloc for System {
|
||||
Some(x) => x.as_ptr() as *mut _,
|
||||
};
|
||||
|
||||
if layout.size() > 0 {
|
||||
unsafe { r_efi_alloc::raw::alloc(system_table, layout, MEMORY_TYPE) }
|
||||
} else {
|
||||
layout.dangling().as_ptr()
|
||||
}
|
||||
// The caller must ensure non-0 layout
|
||||
unsafe { r_efi_alloc::raw::alloc(system_table, layout, MEMORY_TYPE) }
|
||||
}
|
||||
|
||||
unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) {
|
||||
@@ -25,8 +22,7 @@ unsafe impl GlobalAlloc for System {
|
||||
None => handle_alloc_error(layout),
|
||||
Some(x) => x.as_ptr() as *mut _,
|
||||
};
|
||||
if layout.size() > 0 {
|
||||
unsafe { r_efi_alloc::raw::dealloc(system_table, ptr, layout) }
|
||||
}
|
||||
// The caller must ensure non-0 layout
|
||||
unsafe { r_efi_alloc::raw::dealloc(system_table, ptr, layout) }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,16 +1,25 @@
|
||||
//! Contains most of the shared UEFI specific stuff. Some of this might be moved to `std::os::uefi`
|
||||
//! if needed but no point in adding extra public API when there is not Std support for UEFI in the
|
||||
//! first place
|
||||
//!
|
||||
//! Some Nomenclature
|
||||
//! * Protocol:
|
||||
//! - Protocols serve to enable communication between separately built modules, including drivers.
|
||||
//! - Every protocol has a GUID associated with it. The GUID serves as the name for the protocol.
|
||||
//! - Protocols are produced and consumed.
|
||||
//! - 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)
|
||||
|
||||
use r_efi::efi::Guid;
|
||||
|
||||
use crate::io::{self, const_io_error};
|
||||
use crate::mem::MaybeUninit;
|
||||
use crate::mem::{size_of, MaybeUninit};
|
||||
use crate::os::uefi;
|
||||
use crate::ptr::NonNull;
|
||||
|
||||
// Locate handles with a particular protocol GUID
|
||||
/// Locate Handles with a particular Protocol GUID
|
||||
/// Implemented using `EFI_BOOT_SERVICES.LocateHandles()`
|
||||
///
|
||||
/// Returns an array of [Handles](r_efi::efi::Handle) that support a specified protocol.
|
||||
pub(crate) fn locate_handles(mut guid: Guid) -> io::Result<Vec<NonNull<crate::ffi::c_void>>> {
|
||||
fn inner(
|
||||
guid: &mut Guid,
|
||||
@@ -34,6 +43,8 @@ pub(crate) fn locate_handles(mut guid: Guid) -> io::Result<Vec<NonNull<crate::ff
|
||||
let boot_services = boot_services();
|
||||
let mut buf_len = 0usize;
|
||||
|
||||
// This should always fail since the size of buffer is 0. This call should update the buf_len
|
||||
// variable with the required buffer length
|
||||
match inner(&mut guid, boot_services, &mut buf_len, crate::ptr::null_mut()) {
|
||||
Ok(()) => unreachable!(),
|
||||
Err(e) => match e.kind() {
|
||||
@@ -44,21 +55,23 @@ pub(crate) fn locate_handles(mut guid: Guid) -> io::Result<Vec<NonNull<crate::ff
|
||||
|
||||
// The returned buf_len is in bytes
|
||||
let mut buf: Vec<r_efi::efi::Handle> =
|
||||
Vec::with_capacity(buf_len / crate::mem::size_of::<r_efi::efi::Handle>());
|
||||
Vec::with_capacity(buf_len / size_of::<r_efi::efi::Handle>());
|
||||
match inner(&mut guid, boot_services, &mut buf_len, buf.as_mut_ptr()) {
|
||||
Ok(()) => {
|
||||
// SAFETY: This is safe because the call will succeed only if buf_len >= required
|
||||
// length. Also, on success, the `buf_len` is updated with the size of bufferv (in
|
||||
// bytes) written
|
||||
unsafe { buf.set_len(buf_len / crate::mem::size_of::<r_efi::efi::Handle>()) };
|
||||
Ok(buf.iter().filter_map(|x| NonNull::new(*x)).collect())
|
||||
// This is safe because the call will succeed only if buf_len >= required length.
|
||||
// Also, on success, the `buf_len` is updated with the size of bufferv (in bytes) written
|
||||
unsafe { buf.set_len(buf_len / size_of::<r_efi::efi::Handle>()) };
|
||||
Ok(buf.into_iter().filter_map(|x| NonNull::new(x)).collect())
|
||||
}
|
||||
Err(e) => Err(e),
|
||||
}
|
||||
}
|
||||
|
||||
/// Open Protocol on a handle
|
||||
/// Implemented using `EFI_BOOT_SERVICES.OpenProtocol()`
|
||||
/// Open Protocol on a handle.
|
||||
/// Internally just a call to `EFI_BOOT_SERVICES.OpenProtocol()`.
|
||||
///
|
||||
/// Queries a handle to determine if it supports a specified protocol. If the protocol is
|
||||
/// supported by the handle, it opens the protocol on behalf of the calling agent.
|
||||
pub(crate) fn open_protocol<T>(
|
||||
handle: NonNull<crate::ffi::c_void>,
|
||||
mut protocol_guid: Guid,
|
||||
@@ -256,9 +269,7 @@ pub(crate) fn status_to_io_error(s: r_efi::efi::Status) -> io::Error {
|
||||
|
||||
/// Get the BootServices Pointer.
|
||||
pub(crate) fn boot_services() -> NonNull<r_efi::efi::BootServices> {
|
||||
let system_table: NonNull<r_efi::efi::SystemTable> = uefi::env::system_table().cast();
|
||||
let boot_services = unsafe { (*system_table.as_ptr()).boot_services };
|
||||
NonNull::new(boot_services).unwrap()
|
||||
try_boot_services().unwrap()
|
||||
}
|
||||
/// Get the BootServices Pointer.
|
||||
/// This function is mostly intended for places where panic is not an option
|
||||
@@ -47,7 +47,7 @@ pub mod thread_local_key;
|
||||
#[path = "../unsupported/time.rs"]
|
||||
pub mod time;
|
||||
|
||||
pub(crate) mod common;
|
||||
pub(crate) mod helpers;
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests;
|
||||
@@ -60,18 +60,20 @@ pub mod memchr {
|
||||
pub use core::slice::memchr::{memchr, memrchr};
|
||||
}
|
||||
|
||||
// SAFETY: must be called only once during runtime initialization.
|
||||
// SAFETY: argc must be 2.
|
||||
// SAFETY: argv must be &[Handle, *mut SystemTable].
|
||||
pub unsafe fn init(argc: isize, argv: *const *const u8, _sigpipe: u8) {
|
||||
/// # SAFETY
|
||||
/// - must be called only once during runtime initialization.
|
||||
/// - argc must be 2.
|
||||
/// - argv must be &[Handle, *mut SystemTable].
|
||||
pub(crate) unsafe fn init(argc: isize, argv: *const *const u8, _sigpipe: u8) {
|
||||
assert_eq!(argc, 2);
|
||||
let image_handle = unsafe { NonNull::new(*argv as *mut crate::ffi::c_void).unwrap() };
|
||||
let system_table = unsafe { NonNull::new(*argv.add(1) as *mut crate::ffi::c_void).unwrap() };
|
||||
unsafe { crate::os::uefi::env::init_globals(image_handle, system_table) };
|
||||
}
|
||||
|
||||
// SAFETY: must be called only once during runtime cleanup.
|
||||
// NOTE: this is not guaranteed to run, for example when the program aborts.
|
||||
/// # SAFETY
|
||||
/// this is not guaranteed to run, for example when the program aborts.
|
||||
/// - must be called only once during runtime cleanup.
|
||||
pub unsafe fn cleanup() {}
|
||||
|
||||
#[inline]
|
||||
@@ -89,7 +91,7 @@ pub fn decode_error_kind(code: i32) -> crate::io::ErrorKind {
|
||||
use r_efi::efi::Status;
|
||||
|
||||
if let Ok(code) = usize::try_from(code) {
|
||||
common::status_to_io_error(Status::from_usize(code)).kind()
|
||||
helpers::status_to_io_error(Status::from_usize(code)).kind()
|
||||
} else {
|
||||
ErrorKind::Uncategorized
|
||||
}
|
||||
@@ -97,7 +99,7 @@ pub fn decode_error_kind(code: i32) -> crate::io::ErrorKind {
|
||||
|
||||
pub fn abort_internal() -> ! {
|
||||
if let (Some(boot_services), Some(handle)) =
|
||||
(common::try_boot_services(), uefi::env::try_image_handle())
|
||||
(helpers::try_boot_services(), uefi::env::try_image_handle())
|
||||
{
|
||||
let _ = unsafe {
|
||||
((*boot_services.as_ptr()).exit)(
|
||||
@@ -130,9 +132,9 @@ fn get_random() -> Option<(u64, u64)> {
|
||||
use r_efi::protocols::rng;
|
||||
|
||||
let mut buf = [0u8; 16];
|
||||
let handles = common::locate_handles(rng::PROTOCOL_GUID).ok()?;
|
||||
let handles = helpers::locate_handles(rng::PROTOCOL_GUID).ok()?;
|
||||
for handle in handles {
|
||||
if let Ok(protocol) = common::open_protocol::<rng::Protocol>(handle, rng::PROTOCOL_GUID) {
|
||||
if let Ok(protocol) = helpers::open_protocol::<rng::Protocol>(handle, rng::PROTOCOL_GUID) {
|
||||
let r = unsafe {
|
||||
((*protocol.as_ptr()).get_rng)(
|
||||
protocol.as_ptr(),
|
||||
|
||||
Reference in New Issue
Block a user