Skip to content

Commit 8226547

Browse files
committed
Add Minimal Std implementation for UEFI
Implemented modules: 1. alloc 2. os_str 3. env 4. math Tracking Issue: rust-lang#100499 API Change Proposal: rust-lang/libs-team#87 This was originally part of rust-lang#100316. Since that PR was becoming too unwieldy and cluttered, and with suggestion from @dvdhrm, I have extracted a minimal std implementation to this PR. Signed-off-by: Ayush Singh <[email protected]>
1 parent 9d5224f commit 8226547

File tree

16 files changed

+587
-3
lines changed

16 files changed

+587
-3
lines changed

panic_abort/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ pub unsafe fn __rust_start_panic(_payload: &mut dyn PanicPayload) -> u32 {
4545
} else if #[cfg(any(target_os = "hermit",
4646
all(target_vendor = "fortanix", target_env = "sgx"),
4747
target_os = "xous"
48+
target_os = "uefi",
4849
))] {
4950
unsafe fn abort() -> ! {
5051
// call std::sys::abort_internal

std/Cargo.toml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,10 @@ hermit-abi = { version = "0.3.2", features = ['rustc-dep-of-std'], public = true
4848
[target.'cfg(target_os = "wasi")'.dependencies]
4949
wasi = { version = "0.11.0", features = ['rustc-dep-of-std'], default-features = false }
5050

51+
[target.'cfg(target_os = "uefi")'.dependencies]
52+
r-efi = { version = "4.1.0", features = ['rustc-dep-of-std', 'efiapi']}
53+
r-efi-alloc = { version = "1.0.0", features = ['rustc-dep-of-std']}
54+
5155
[features]
5256
backtrace = [
5357
"gimli-symbolize",

std/build.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ fn main() {
3939
|| target.contains("nto")
4040
|| target.contains("xous")
4141
|| target.contains("hurd")
42+
|| target.contains("uefi")
4243
// See src/bootstrap/synthetic_targets.rs
4344
|| env::var("RUSTC_BOOTSTRAP_SYNTHETIC_TARGET").is_ok()
4445
{
@@ -51,7 +52,7 @@ fn main() {
5152
// - mipsel-sony-psp
5253
// - nvptx64-nvidia-cuda
5354
// - arch=avr
54-
// - uefi (x86_64-unknown-uefi, i686-unknown-uefi)
55+
// - tvos (aarch64-apple-tvos, x86_64-apple-tvos)
5556
// - JSON targets
5657
// - Any new targets that have not been explicitly added above.
5758
println!("cargo:rustc-cfg=feature=\"restricted-std\"");

std/src/lib.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -263,7 +263,6 @@
263263
#![cfg_attr(target_os = "xous", feature(slice_ptr_len))]
264264
//
265265
// Language features:
266-
// tidy-alphabetical-start
267266
#![feature(alloc_error_handler)]
268267
#![feature(allocator_internals)]
269268
#![feature(allow_internal_unsafe)]

std/src/os/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,8 @@ pub mod solid;
142142
#[cfg(target_os = "tvos")]
143143
#[path = "ios/mod.rs"]
144144
pub(crate) mod tvos;
145+
#[cfg(target_os = "uefi")]
146+
pub mod uefi;
145147
#[cfg(target_os = "vita")]
146148
pub mod vita;
147149
#[cfg(target_os = "vxworks")]

std/src/os/uefi/env.rs

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
//! UEFI-specific extensions to the primitives in `std::env` module
2+
3+
use crate::ffi::c_void;
4+
use crate::ptr::NonNull;
5+
use crate::sync::atomic::{AtomicPtr, Ordering};
6+
use crate::sync::OnceLock;
7+
8+
// Position 0 = SystemTable
9+
// Position 1 = ImageHandle
10+
static GLOBALS: OnceLock<(AtomicPtr<c_void>, AtomicPtr<c_void>)> = OnceLock::new();
11+
12+
/// Initializes the global System Table and Image Handle pointers.
13+
///
14+
/// The standard library requires access to the UEFI System Table and the Application Image Handle
15+
/// to operate. Those are provided to UEFI Applications via their application entry point. By
16+
/// calling `init_globals()`, those pointers are retained by the standard library for future use.
17+
/// The pointers are never exposed to any entity outside of this application and it is guaranteed
18+
/// that, once the application exited, these pointers are never dereferenced again.
19+
///
20+
/// Callers are required to ensure the pointers are valid for the entire lifetime of this
21+
/// application. In particular, UEFI Boot Services must not be exited while an application with the
22+
/// standard library is loaded.
23+
///
24+
/// This function must not be called more than once.
25+
#[unstable(feature = "uefi_std", issue = "100499")]
26+
pub unsafe fn init_globals(handle: NonNull<c_void>, system_table: NonNull<c_void>) {
27+
GLOBALS.set((AtomicPtr::new(system_table.as_ptr()), AtomicPtr::new(handle.as_ptr()))).unwrap()
28+
}
29+
30+
/// Get the SystemTable Pointer.
31+
/// Note: This function panics if the System Table and Image Handle is Not initialized
32+
#[unstable(feature = "uefi_std", issue = "100499")]
33+
pub fn system_table() -> NonNull<c_void> {
34+
try_system_table().unwrap()
35+
}
36+
37+
/// Get the SystemHandle Pointer.
38+
/// Note: This function panics if the System Table and Image Handle is Not initialized
39+
#[unstable(feature = "uefi_std", issue = "100499")]
40+
pub fn image_handle() -> NonNull<c_void> {
41+
try_image_handle().unwrap()
42+
}
43+
44+
/// Get the SystemTable Pointer.
45+
/// This function is mostly intended for places where panic is not an option
46+
pub(crate) fn try_system_table() -> Option<NonNull<crate::ffi::c_void>> {
47+
NonNull::new(GLOBALS.get()?.0.load(Ordering::Acquire))
48+
}
49+
50+
/// Get the SystemHandle Pointer.
51+
/// This function is mostly intended for places where panic is not an option
52+
pub(crate) fn try_image_handle() -> Option<NonNull<crate::ffi::c_void>> {
53+
NonNull::new(GLOBALS.get()?.1.load(Ordering::Acquire))
54+
}

std/src/os/uefi/mod.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
//! Platform-specific extensions to `std` for UEFI.
2+
3+
#![unstable(feature = "uefi_std", issue = "100499")]
4+
5+
pub mod env;
6+
#[path = "../windows/ffi.rs"]
7+
pub mod ffi;

std/src/sys/common/thread_local/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
// "static" is for single-threaded platforms where a global static is sufficient.
77

88
cfg_if::cfg_if! {
9-
if #[cfg(all(target_family = "wasm", not(target_feature = "atomics")))] {
9+
if #[cfg(any(all(target_family = "wasm", not(target_feature = "atomics")), target_os = "uefi"))] {
1010
#[doc(hidden)]
1111
mod static_local;
1212
#[doc(hidden)]

std/src/sys/mod.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,9 @@ cfg_if::cfg_if! {
4747
} else if #[cfg(target_os = "xous")] {
4848
mod xous;
4949
pub use self::xous::*;
50+
} else if #[cfg(target_os = "uefi")] {
51+
mod uefi;
52+
pub use self::uefi::*;
5053
} else if #[cfg(all(target_vendor = "fortanix", target_env = "sgx"))] {
5154
mod sgx;
5255
pub use self::sgx::*;

std/src/sys/uefi/alloc.rs

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
//! Global Allocator for UEFI.
2+
//! Uses [r-efi-alloc](https://crates.io/crates/r-efi-alloc)
3+
4+
use crate::alloc::{handle_alloc_error, GlobalAlloc, Layout, System};
5+
6+
const MEMORY_TYPE: u32 = r_efi::efi::LOADER_DATA;
7+
8+
#[stable(feature = "alloc_system_type", since = "1.28.0")]
9+
unsafe impl GlobalAlloc for System {
10+
unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
11+
let system_table = match crate::os::uefi::env::try_system_table() {
12+
None => return crate::ptr::null_mut(),
13+
Some(x) => x.as_ptr() as *mut _,
14+
};
15+
16+
if layout.size() > 0 {
17+
unsafe { r_efi_alloc::raw::alloc(system_table, layout, MEMORY_TYPE) }
18+
} else {
19+
layout.dangling().as_ptr()
20+
}
21+
}
22+
23+
unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) {
24+
let system_table = match crate::os::uefi::env::try_system_table() {
25+
None => handle_alloc_error(layout),
26+
Some(x) => x.as_ptr() as *mut _,
27+
};
28+
if layout.size() > 0 {
29+
unsafe { r_efi_alloc::raw::dealloc(system_table, ptr, layout) }
30+
}
31+
}
32+
}

0 commit comments

Comments
 (0)