diff options
Diffstat (limited to 'library/std/src')
| -rw-r--r-- | library/std/src/lib.rs | 1 | ||||
| -rw-r--r-- | library/std/src/os/mod.rs | 2 | ||||
| -rw-r--r-- | library/std/src/os/uefi/env.rs | 54 | ||||
| -rw-r--r-- | library/std/src/os/uefi/mod.rs | 7 | ||||
| -rw-r--r-- | library/std/src/sys/common/thread_local/mod.rs | 2 | ||||
| -rw-r--r-- | library/std/src/sys/mod.rs | 3 | ||||
| -rw-r--r-- | library/std/src/sys/uefi/alloc.rs | 32 | ||||
| -rw-r--r-- | library/std/src/sys/uefi/common.rs | 269 | ||||
| -rw-r--r-- | library/std/src/sys/uefi/env.rs | 9 | ||||
| -rw-r--r-- | library/std/src/sys/uefi/mod.rs | 155 | ||||
| -rw-r--r-- | library/std/src/sys/uefi/path.rs | 25 | ||||
| -rw-r--r-- | library/std/src/sys/uefi/tests.rs | 21 | ||||
| -rw-r--r-- | library/std/src/sys_common/mod.rs | 2 |
13 files changed, 580 insertions, 2 deletions
diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs index 5e3249655b8..b572347019c 100644 --- a/library/std/src/lib.rs +++ b/library/std/src/lib.rs @@ -263,7 +263,6 @@ #![cfg_attr(target_os = "xous", feature(slice_ptr_len))] // // Language features: -// tidy-alphabetical-start #![feature(alloc_error_handler)] #![feature(allocator_internals)] #![feature(allow_internal_unsafe)] diff --git a/library/std/src/os/mod.rs b/library/std/src/os/mod.rs index 24d16e64c86..11ad21515fd 100644 --- a/library/std/src/os/mod.rs +++ b/library/std/src/os/mod.rs @@ -142,6 +142,8 @@ pub mod solid; #[cfg(target_os = "tvos")] #[path = "ios/mod.rs"] pub(crate) mod tvos; +#[cfg(target_os = "uefi")] +pub mod uefi; #[cfg(target_os = "vita")] pub mod vita; #[cfg(target_os = "vxworks")] diff --git a/library/std/src/os/uefi/env.rs b/library/std/src/os/uefi/env.rs new file mode 100644 index 00000000000..479ff5f6975 --- /dev/null +++ b/library/std/src/os/uefi/env.rs @@ -0,0 +1,54 @@ +//! UEFI-specific extensions to the primitives in `std::env` module + +use crate::ffi::c_void; +use crate::ptr::NonNull; +use crate::sync::atomic::{AtomicPtr, Ordering}; +use crate::sync::OnceLock; + +// Position 0 = SystemTable +// Position 1 = ImageHandle +static GLOBALS: OnceLock<(AtomicPtr<c_void>, AtomicPtr<c_void>)> = OnceLock::new(); + +/// Initializes the global System Table and Image Handle pointers. +/// +/// The standard library requires access to the UEFI System Table and the Application Image Handle +/// to operate. Those are provided to UEFI Applications via their application entry point. By +/// calling `init_globals()`, those pointers are retained by the standard library for future use. +/// The pointers are never exposed to any entity outside of this application and it is guaranteed +/// that, once the application exited, these pointers are never dereferenced again. +/// +/// Callers are required to ensure the pointers are valid for the entire lifetime of this +/// application. In particular, UEFI Boot Services must not be exited while an application with the +/// standard library is loaded. +/// +/// This function must not be called more than once. +#[unstable(feature = "uefi_std", issue = "100499")] +pub unsafe fn init_globals(handle: NonNull<c_void>, system_table: NonNull<c_void>) { + GLOBALS.set((AtomicPtr::new(system_table.as_ptr()), AtomicPtr::new(handle.as_ptr()))).unwrap() +} + +/// Get the SystemTable Pointer. +/// Note: This function panics if the System Table and Image Handle is Not initialized +#[unstable(feature = "uefi_std", issue = "100499")] +pub fn system_table() -> NonNull<c_void> { + try_system_table().unwrap() +} + +/// Get the SystemHandle Pointer. +/// Note: This function panics if the System Table and Image Handle is Not initialized +#[unstable(feature = "uefi_std", issue = "100499")] +pub fn image_handle() -> NonNull<c_void> { + try_image_handle().unwrap() +} + +/// Get the SystemTable Pointer. +/// This function is mostly intended for places where panic is not an option +pub(crate) fn try_system_table() -> Option<NonNull<crate::ffi::c_void>> { + NonNull::new(GLOBALS.get()?.0.load(Ordering::Acquire)) +} + +/// Get the SystemHandle Pointer. +/// This function is mostly intended for places where panic is not an option +pub(crate) fn try_image_handle() -> Option<NonNull<crate::ffi::c_void>> { + NonNull::new(GLOBALS.get()?.1.load(Ordering::Acquire)) +} diff --git a/library/std/src/os/uefi/mod.rs b/library/std/src/os/uefi/mod.rs new file mode 100644 index 00000000000..fc0468f25fc --- /dev/null +++ b/library/std/src/os/uefi/mod.rs @@ -0,0 +1,7 @@ +//! Platform-specific extensions to `std` for UEFI. + +#![unstable(feature = "uefi_std", issue = "100499")] + +pub mod env; +#[path = "../windows/ffi.rs"] +pub mod ffi; diff --git a/library/std/src/sys/common/thread_local/mod.rs b/library/std/src/sys/common/thread_local/mod.rs index 975509bd412..8b2c839f837 100644 --- a/library/std/src/sys/common/thread_local/mod.rs +++ b/library/std/src/sys/common/thread_local/mod.rs @@ -6,7 +6,7 @@ // "static" is for single-threaded platforms where a global static is sufficient. cfg_if::cfg_if! { - if #[cfg(all(target_family = "wasm", not(target_feature = "atomics")))] { + if #[cfg(any(all(target_family = "wasm", not(target_feature = "atomics")), target_os = "uefi"))] { #[doc(hidden)] mod static_local; #[doc(hidden)] diff --git a/library/std/src/sys/mod.rs b/library/std/src/sys/mod.rs index 457eb782ccc..a03501e6a13 100644 --- a/library/std/src/sys/mod.rs +++ b/library/std/src/sys/mod.rs @@ -47,6 +47,9 @@ cfg_if::cfg_if! { } else if #[cfg(target_os = "xous")] { mod xous; pub use self::xous::*; + } else if #[cfg(target_os = "uefi")] { + mod uefi; + pub use self::uefi::*; } else if #[cfg(all(target_vendor = "fortanix", target_env = "sgx"))] { mod sgx; pub use self::sgx::*; diff --git a/library/std/src/sys/uefi/alloc.rs b/library/std/src/sys/uefi/alloc.rs new file mode 100644 index 00000000000..6a14ee76e92 --- /dev/null +++ b/library/std/src/sys/uefi/alloc.rs @@ -0,0 +1,32 @@ +//! Global Allocator for UEFI. +//! Uses [r-efi-alloc](https://crates.io/crates/r-efi-alloc) + +use crate::alloc::{handle_alloc_error, GlobalAlloc, Layout, System}; + +const MEMORY_TYPE: u32 = r_efi::efi::LOADER_DATA; + +#[stable(feature = "alloc_system_type", since = "1.28.0")] +unsafe impl GlobalAlloc for System { + unsafe fn alloc(&self, layout: Layout) -> *mut u8 { + let system_table = match crate::os::uefi::env::try_system_table() { + None => return crate::ptr::null_mut(), + 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() + } + } + + unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) { + let system_table = match crate::os::uefi::env::try_system_table() { + 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) } + } + } +} diff --git a/library/std/src/sys/uefi/common.rs b/library/std/src/sys/uefi/common.rs new file mode 100644 index 00000000000..6316a74d367 --- /dev/null +++ b/library/std/src/sys/uefi/common.rs @@ -0,0 +1,269 @@ +//! 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 + +use r_efi::efi::Guid; + +use crate::io::{self, const_io_error}; +use crate::mem::MaybeUninit; +use crate::os::uefi; +use crate::ptr::NonNull; + +// Locate handles with a particular protocol GUID +/// Implemented using `EFI_BOOT_SERVICES.LocateHandles()` +pub(crate) fn locate_handles(mut guid: Guid) -> io::Result<Vec<NonNull<crate::ffi::c_void>>> { + fn inner( + guid: &mut Guid, + boot_services: NonNull<r_efi::efi::BootServices>, + buf_size: &mut usize, + buf: *mut r_efi::efi::Handle, + ) -> io::Result<()> { + let r = unsafe { + ((*boot_services.as_ptr()).locate_handle)( + r_efi::efi::BY_PROTOCOL, + guid, + crate::ptr::null_mut(), + buf_size, + buf, + ) + }; + + if r.is_error() { Err(status_to_io_error(r)) } else { Ok(()) } + } + + let boot_services = boot_services(); + let mut buf_len = 0usize; + + match inner(&mut guid, boot_services, &mut buf_len, crate::ptr::null_mut()) { + Ok(()) => unreachable!(), + Err(e) => match e.kind() { + io::ErrorKind::FileTooLarge => {} + _ => return Err(e), + }, + } + + // 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>()); + 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()) + } + Err(e) => Err(e), + } +} + +/// Open Protocol on a handle +/// Implemented using `EFI_BOOT_SERVICES.OpenProtocol()` +pub(crate) fn open_protocol<T>( + handle: NonNull<crate::ffi::c_void>, + mut protocol_guid: Guid, +) -> io::Result<NonNull<T>> { + let boot_services = boot_services(); + let system_handle = uefi::env::image_handle(); + let mut protocol: MaybeUninit<*mut T> = MaybeUninit::uninit(); + + let r = unsafe { + ((*boot_services.as_ptr()).open_protocol)( + handle.as_ptr(), + &mut protocol_guid, + protocol.as_mut_ptr().cast(), + system_handle.as_ptr(), + crate::ptr::null_mut(), + r_efi::system::OPEN_PROTOCOL_GET_PROTOCOL, + ) + }; + + if r.is_error() { + Err(status_to_io_error(r)) + } else { + NonNull::new(unsafe { protocol.assume_init() }) + .ok_or(const_io_error!(io::ErrorKind::Other, "null protocol")) + } +} + +pub(crate) fn status_to_io_error(s: r_efi::efi::Status) -> io::Error { + use io::ErrorKind; + use r_efi::efi::Status; + + // Keep the List in Alphabetical Order + // The Messages are taken from UEFI Specification Appendix D - Status Codes + match s { + Status::ABORTED => { + const_io_error!(ErrorKind::ConnectionAborted, "The operation was aborted.") + } + Status::ACCESS_DENIED => { + const_io_error!(ErrorKind::PermissionDenied, "Access was denied.") + } + Status::ALREADY_STARTED => { + const_io_error!(ErrorKind::Other, "The protocol has already been started.") + } + Status::BAD_BUFFER_SIZE => { + const_io_error!( + ErrorKind::InvalidData, + "The buffer was not the proper size for the request." + ) + } + Status::BUFFER_TOO_SMALL => { + const_io_error!( + ErrorKind::FileTooLarge, + "The buffer is not large enough to hold the requested data. The required buffer size is returned in the appropriate parameter when this error occurs." + ) + } + Status::COMPROMISED_DATA => { + const_io_error!( + ErrorKind::Other, + "The security status of the data is unknown or compromised and the data must be updated or replaced to restore a valid security status." + ) + } + Status::CONNECTION_FIN => { + const_io_error!( + ErrorKind::Other, + "The receiving operation fails because the communication peer has closed the connection and there is no more data in the receive buffer of the instance." + ) + } + Status::CONNECTION_REFUSED => { + const_io_error!( + ErrorKind::ConnectionRefused, + "The receiving or transmission operation fails because this connection is refused." + ) + } + Status::CONNECTION_RESET => { + const_io_error!( + ErrorKind::ConnectionReset, + "The connect fails because the connection is reset either by instance itself or the communication peer." + ) + } + Status::CRC_ERROR => const_io_error!(ErrorKind::Other, "A CRC error was detected."), + Status::DEVICE_ERROR => const_io_error!( + ErrorKind::Other, + "The physical device reported an error while attempting the operation." + ), + Status::END_OF_FILE => { + const_io_error!(ErrorKind::UnexpectedEof, "The end of the file was reached.") + } + Status::END_OF_MEDIA => { + const_io_error!(ErrorKind::Other, "Beginning or end of media was reached") + } + Status::HOST_UNREACHABLE => { + const_io_error!(ErrorKind::HostUnreachable, "The remote host is not reachable.") + } + Status::HTTP_ERROR => { + const_io_error!(ErrorKind::Other, "A HTTP error occurred during the network operation.") + } + Status::ICMP_ERROR => { + const_io_error!( + ErrorKind::Other, + "An ICMP error occurred during the network operation." + ) + } + Status::INCOMPATIBLE_VERSION => { + const_io_error!( + ErrorKind::Other, + "The function encountered an internal version that was incompatible with a version requested by the caller." + ) + } + Status::INVALID_LANGUAGE => { + const_io_error!(ErrorKind::InvalidData, "The language specified was invalid.") + } + Status::INVALID_PARAMETER => { + const_io_error!(ErrorKind::InvalidInput, "A parameter was incorrect.") + } + Status::IP_ADDRESS_CONFLICT => { + const_io_error!(ErrorKind::AddrInUse, "There is an address conflict address allocation") + } + Status::LOAD_ERROR => { + const_io_error!(ErrorKind::Other, "The image failed to load.") + } + Status::MEDIA_CHANGED => { + const_io_error!( + ErrorKind::Other, + "The medium in the device has changed since the last access." + ) + } + Status::NETWORK_UNREACHABLE => { + const_io_error!( + ErrorKind::NetworkUnreachable, + "The network containing the remote host is not reachable." + ) + } + Status::NO_MAPPING => { + const_io_error!(ErrorKind::Other, "A mapping to a device does not exist.") + } + Status::NO_MEDIA => { + const_io_error!( + ErrorKind::Other, + "The device does not contain any medium to perform the operation." + ) + } + Status::NO_RESPONSE => { + const_io_error!( + ErrorKind::HostUnreachable, + "The server was not found or did not respond to the request." + ) + } + Status::NOT_FOUND => const_io_error!(ErrorKind::NotFound, "The item was not found."), + Status::NOT_READY => { + const_io_error!(ErrorKind::ResourceBusy, "There is no data pending upon return.") + } + Status::NOT_STARTED => { + const_io_error!(ErrorKind::Other, "The protocol has not been started.") + } + Status::OUT_OF_RESOURCES => { + const_io_error!(ErrorKind::OutOfMemory, "A resource has run out.") + } + Status::PROTOCOL_ERROR => { + const_io_error!( + ErrorKind::Other, + "A protocol error occurred during the network operation." + ) + } + Status::PROTOCOL_UNREACHABLE => { + const_io_error!(ErrorKind::Other, "An ICMP protocol unreachable error is received.") + } + Status::SECURITY_VIOLATION => { + const_io_error!( + ErrorKind::PermissionDenied, + "The function was not performed due to a security violation." + ) + } + Status::TFTP_ERROR => { + const_io_error!(ErrorKind::Other, "A TFTP error occurred during the network operation.") + } + Status::TIMEOUT => const_io_error!(ErrorKind::TimedOut, "The timeout time expired."), + Status::UNSUPPORTED => { + const_io_error!(ErrorKind::Unsupported, "The operation is not supported.") + } + Status::VOLUME_FULL => { + const_io_error!(ErrorKind::StorageFull, "There is no more space on the file system.") + } + Status::VOLUME_CORRUPTED => { + const_io_error!( + ErrorKind::Other, + "An inconstancy was detected on the file system causing the operating to fail." + ) + } + Status::WRITE_PROTECTED => { + const_io_error!(ErrorKind::ReadOnlyFilesystem, "The device cannot be written to.") + } + _ => io::Error::new(ErrorKind::Uncategorized, format!("Status: {}", s.as_usize())), + } +} + +/// 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() +} +/// Get the BootServices Pointer. +/// This function is mostly intended for places where panic is not an option +pub(crate) fn try_boot_services() -> Option<NonNull<r_efi::efi::BootServices>> { + let system_table: NonNull<r_efi::efi::SystemTable> = uefi::env::try_system_table()?.cast(); + let boot_services = unsafe { (*system_table.as_ptr()).boot_services }; + NonNull::new(boot_services) +} diff --git a/library/std/src/sys/uefi/env.rs b/library/std/src/sys/uefi/env.rs new file mode 100644 index 00000000000..c106d5fed3e --- /dev/null +++ b/library/std/src/sys/uefi/env.rs @@ -0,0 +1,9 @@ +pub mod os { + pub const FAMILY: &str = ""; + pub const OS: &str = "uefi"; + pub const DLL_PREFIX: &str = ""; + pub const DLL_SUFFIX: &str = ""; + pub const DLL_EXTENSION: &str = ""; + pub const EXE_SUFFIX: &str = ".efi"; + pub const EXE_EXTENSION: &str = "efi"; +} diff --git a/library/std/src/sys/uefi/mod.rs b/library/std/src/sys/uefi/mod.rs new file mode 100644 index 00000000000..193d4ecc16f --- /dev/null +++ b/library/std/src/sys/uefi/mod.rs @@ -0,0 +1,155 @@ +//! Platform-specific extensions to `std` for UEFI platforms. +//! +//! Provides access to platform-level information on UEFI platforms, and +//! exposes UEFI-specific functions that would otherwise be inappropriate as +//! part of the core `std` library. +//! +//! It exposes more ways to deal with platform-specific strings ([`OsStr`], +//! [`OsString`]), allows to set permissions more granularly, extract low-level +//! file descriptors from files and sockets, and has platform-specific helpers +//! for spawning processes. +//! +//! [`OsStr`]: crate::ffi::OsStr +//! [`OsString`]: crate::ffi::OsString + +#![deny(unsafe_op_in_unsafe_fn)] +pub mod alloc; +#[path = "../unsupported/args.rs"] +pub mod args; +#[path = "../unix/cmath.rs"] +pub mod cmath; +pub mod env; +#[path = "../unsupported/fs.rs"] +pub mod fs; +#[path = "../unsupported/io.rs"] +pub mod io; +#[path = "../unsupported/locks/mod.rs"] +pub mod locks; +#[path = "../unsupported/net.rs"] +pub mod net; +#[path = "../unsupported/once.rs"] +pub mod once; +#[path = "../unsupported/os.rs"] +pub mod os; +#[path = "../windows/os_str.rs"] +pub mod os_str; +pub mod path; +#[path = "../unsupported/pipe.rs"] +pub mod pipe; +#[path = "../unsupported/process.rs"] +pub mod process; +#[path = "../unsupported/stdio.rs"] +pub mod stdio; +#[path = "../unsupported/thread.rs"] +pub mod thread; +#[path = "../unsupported/thread_local_key.rs"] +pub mod thread_local_key; +#[path = "../unsupported/time.rs"] +pub mod time; + +pub(crate) mod common; + +#[cfg(test)] +mod tests; + +use crate::io as std_io; +use crate::os::uefi; +use crate::ptr::NonNull; + +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) { + 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. +pub unsafe fn cleanup() {} + +#[inline] +pub const fn unsupported<T>() -> std_io::Result<T> { + Err(unsupported_err()) +} + +#[inline] +pub const fn unsupported_err() -> std_io::Error { + std_io::const_io_error!(std_io::ErrorKind::Unsupported, "operation not supported on UEFI",) +} + +pub fn decode_error_kind(code: i32) -> crate::io::ErrorKind { + use 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() + } else { + ErrorKind::Uncategorized + } +} + +pub fn abort_internal() -> ! { + if let (Some(boot_services), Some(handle)) = + (common::try_boot_services(), uefi::env::try_image_handle()) + { + let _ = unsafe { + ((*boot_services.as_ptr()).exit)( + handle.as_ptr(), + r_efi::efi::Status::ABORTED, + 0, + crate::ptr::null_mut(), + ) + }; + } + + // In case SystemTable and ImageHandle cannot be reached, use `core::intrinsics::abort` + core::intrinsics::abort(); +} + +// This function is needed by the panic runtime. The symbol is named in +// pre-link args for the target specification, so keep that in sync. +#[cfg(not(test))] +#[no_mangle] +pub extern "C" fn __rust_abort() { + abort_internal(); +} + +#[inline] +pub fn hashmap_random_keys() -> (u64, u64) { + get_random().unwrap() +} + +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()?; + for handle in handles { + if let Ok(protocol) = common::open_protocol::<rng::Protocol>(handle, rng::PROTOCOL_GUID) { + let r = unsafe { + ((*protocol.as_ptr()).get_rng)( + protocol.as_ptr(), + crate::ptr::null_mut(), + buf.len(), + buf.as_mut_ptr(), + ) + }; + if r.is_error() { + continue; + } else { + return Some(( + u64::from_le_bytes(buf[..8].try_into().ok()?), + u64::from_le_bytes(buf[8..].try_into().ok()?), + )); + } + } + } + None +} diff --git a/library/std/src/sys/uefi/path.rs b/library/std/src/sys/uefi/path.rs new file mode 100644 index 00000000000..106682eee56 --- /dev/null +++ b/library/std/src/sys/uefi/path.rs @@ -0,0 +1,25 @@ +use super::unsupported; +use crate::ffi::OsStr; +use crate::io; +use crate::path::{Path, PathBuf, Prefix}; + +pub const MAIN_SEP_STR: &str = "\\"; +pub const MAIN_SEP: char = '\\'; + +#[inline] +pub fn is_sep_byte(b: u8) -> bool { + b == b'\\' +} + +#[inline] +pub fn is_verbatim_sep(b: u8) -> bool { + b == b'\\' +} + +pub fn parse_prefix(_p: &OsStr) -> Option<Prefix<'_>> { + None +} + +pub(crate) fn absolute(_path: &Path) -> io::Result<PathBuf> { + unsupported() +} diff --git a/library/std/src/sys/uefi/tests.rs b/library/std/src/sys/uefi/tests.rs new file mode 100644 index 00000000000..8806eda3ac0 --- /dev/null +++ b/library/std/src/sys/uefi/tests.rs @@ -0,0 +1,21 @@ +use super::alloc::*; + +#[test] +fn align() { + // UEFI ABI specifies that allocation alignment minimum is always 8. So this can be + // statically verified. + assert_eq!(POOL_ALIGNMENT, 8); + + // Loop over allocation-request sizes from 0-256 and alignments from 1-128, and verify + // that in case of overalignment there is at least space for one additional pointer to + // store in the allocation. + for i in 0..256 { + for j in &[1, 2, 4, 8, 16, 32, 64, 128] { + if *j <= 8 { + assert_eq!(align_size(i, *j), i); + } else { + assert!(align_size(i, *j) > i + std::mem::size_of::<*mut ()>()); + } + } + } +} diff --git a/library/std/src/sys_common/mod.rs b/library/std/src/sys_common/mod.rs index f7d82175063..d65d68337d8 100644 --- a/library/std/src/sys_common/mod.rs +++ b/library/std/src/sys_common/mod.rs @@ -44,6 +44,8 @@ cfg_if::cfg_if! { cfg_if::cfg_if! { if #[cfg(any(target_os = "l4re", + target_os = "hermit", + target_os = "uefi", feature = "restricted-std", all(target_family = "wasm", not(target_os = "emscripten")), target_os = "xous", |
