Skip to content

Commit 2b1cdf8

Browse files
committed
Rebase to master
- Update Example - Add thread_parking to sys::uefi - Fix unsafe in unsafe errors - Improve docs - Improve os/exit - Some asserts - Switch back to atomics Signed-off-by: Ayush Singh <ayushdevel1325@gmail.com>
1 parent d5a1806 commit 2b1cdf8

File tree

10 files changed

+111
-63
lines changed

10 files changed

+111
-63
lines changed

compiler/rustc_codegen_ssa/src/base.rs

+4-9
Original file line numberDiff line numberDiff line change
@@ -421,7 +421,7 @@ pub fn maybe_create_entry_wrapper<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
421421
entry_type: EntryFnType,
422422
) -> Bx::Function {
423423
// The entry function is either `int main(void)` or `int main(int argc, char **argv)`, or
424-
// `Status efi_main(Handle hd, SystemTable *st)` depending on the target.
424+
// `usize efi_main(void *handle, void *system_table)` depending on the target.
425425
let llfty = if cx.sess().target.os.contains("uefi") {
426426
cx.type_func(&[cx.type_ptr(), cx.type_ptr()], cx.type_isize())
427427
} else if cx.sess().target.main_needs_argc_argv {
@@ -508,10 +508,9 @@ fn get_argc_argv<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
508508
let param_handle = bx.get_param(0);
509509
let param_system_table = bx.get_param(1);
510510
let arg_argc = bx.const_int(cx.type_isize(), 2);
511-
let arg_argv = bx.alloca(cx.type_array(cx.type_i8p(), 2), Align::ONE);
511+
let arg_argv = bx.alloca(cx.type_array(cx.type_ptr(), 2), Align::ONE);
512512
bx.store(param_handle, arg_argv, Align::ONE);
513-
let arg_argv_el1 =
514-
bx.gep(cx.type_ptr_to(cx.type_i8()), arg_argv, &[bx.const_int(cx.type_int(), 1)]);
513+
let arg_argv_el1 = bx.gep(cx.type_ptr(), arg_argv, &[bx.const_int(cx.type_int(), 1)]);
515514
bx.store(param_system_table, arg_argv_el1, Align::ONE);
516515
(arg_argc, arg_argv)
517516
} else if cx.sess().target.main_needs_argc_argv {
@@ -566,11 +565,7 @@ pub fn allocator_kind_for_codegen(tcx: TyCtxt<'_>) -> Option<AllocatorKind> {
566565
use rustc_middle::middle::dependency_format::Linkage;
567566
list.iter().any(|&linkage| linkage == Linkage::Dynamic)
568567
});
569-
if any_dynamic_crate {
570-
None
571-
} else {
572-
tcx.allocator_kind(())
573-
}
568+
if any_dynamic_crate { None } else { tcx.allocator_kind(()) }
574569
}
575570

576571
pub fn codegen_crate<B: ExtraBackendMethods>(

library/panic_abort/src/lib.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ pub unsafe fn __rust_start_panic(_payload: &mut dyn PanicPayload) -> u32 {
4444
}
4545
} else if #[cfg(any(target_os = "hermit",
4646
all(target_vendor = "fortanix", target_env = "sgx"),
47-
target_os = "xous"
47+
target_os = "xous",
4848
target_os = "uefi",
4949
))] {
5050
unsafe fn abort() -> ! {

library/std/build.rs

-1
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,6 @@ fn main() {
5151
// - mipsel-sony-psp
5252
// - nvptx64-nvidia-cuda
5353
// - arch=avr
54-
// - tvos (aarch64-apple-tvos, x86_64-apple-tvos)
5554
// - JSON targets
5655
// - Any new targets that have not been explicitly added above.
5756
println!("cargo:rustc-cfg=feature=\"restricted-std\"");

library/std/src/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -263,6 +263,7 @@
263263
#![cfg_attr(target_os = "xous", feature(slice_ptr_len))]
264264
//
265265
// Language features:
266+
// tidy-alphabetical-start
266267
#![feature(alloc_error_handler)]
267268
#![feature(allocator_internals)]
268269
#![feature(allow_internal_unsafe)]

library/std/src/os/mod.rs

-1
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,6 @@ pub mod solid;
140140
#[cfg(target_os = "tvos")]
141141
#[path = "ios/mod.rs"]
142142
pub(crate) mod tvos;
143-
#[cfg(target_os = "uefi")]
144143
#[cfg(any(target_os = "uefi", doc))]
145144
pub mod uefi;
146145
#[cfg(target_os = "vita")]

library/std/src/os/uefi/env.rs

+33-21
Original file line numberDiff line numberDiff line change
@@ -2,33 +2,49 @@
22
33
#![unstable(feature = "uefi_std", issue = "100499")]
44

5-
use crate::{cell::Cell, ffi::c_void, ptr::NonNull};
5+
use crate::sync::atomic::{AtomicBool, AtomicPtr, Ordering};
6+
use crate::{ffi::c_void, ptr::NonNull};
67

7-
// Since UEFI is single-threaded, making the global variables thread local should be safe.
8-
thread_local! {
9-
// Flag to check if BootServices are still valid.
10-
// Start with assuming that they are not available
11-
static BOOT_SERVICES_FLAG: Cell<bool> = Cell::new(false);
12-
// Position 0 = SystemTable
13-
// Position 1 = ImageHandle
14-
static GLOBALS: Cell<Option<(NonNull<c_void>, NonNull<c_void>)>> = Cell::new(None);
15-
}
8+
static SYSTEM_TABLE: AtomicPtr<c_void> = AtomicPtr::new(crate::ptr::null_mut());
9+
static IMAGE_HANDLE: AtomicPtr<c_void> = AtomicPtr::new(crate::ptr::null_mut());
10+
// Flag to check if BootServices are still valid.
11+
// Start with assuming that they are not available
12+
static BOOT_SERVICES_FLAG: AtomicBool = AtomicBool::new(false);
1613

1714
/// Initializes the global System Table and Image Handle pointers.
1815
///
1916
/// The standard library requires access to the UEFI System Table and the Application Image Handle
2017
/// to operate. Those are provided to UEFI Applications via their application entry point. By
2118
/// calling `init_globals()`, those pointers are retained by the standard library for future use.
19+
/// Thus this function must be called before any of the standard library services are used.
20+
///
2221
/// The pointers are never exposed to any entity outside of this application and it is guaranteed
2322
/// that, once the application exited, these pointers are never dereferenced again.
2423
///
2524
/// Callers are required to ensure the pointers are valid for the entire lifetime of this
2625
/// application. In particular, UEFI Boot Services must not be exited while an application with the
2726
/// standard library is loaded.
2827
///
29-
/// This function must not be called more than once.
30-
pub unsafe fn init_globals(handle: NonNull<c_void>, system_table: NonNull<c_void>) {
31-
GLOBALS.set(Some((system_table, handle)));
28+
/// # SAFETY
29+
/// Calling this function more than once will panic
30+
pub(crate) unsafe fn init_globals(handle: NonNull<c_void>, system_table: NonNull<c_void>) {
31+
IMAGE_HANDLE
32+
.compare_exchange(
33+
crate::ptr::null_mut(),
34+
handle.as_ptr(),
35+
Ordering::Release,
36+
Ordering::Acquire,
37+
)
38+
.unwrap();
39+
SYSTEM_TABLE
40+
.compare_exchange(
41+
crate::ptr::null_mut(),
42+
system_table.as_ptr(),
43+
Ordering::Release,
44+
Ordering::Acquire,
45+
)
46+
.unwrap();
47+
BOOT_SERVICES_FLAG.store(true, Ordering::Release)
3248
}
3349

3450
/// Get the SystemTable Pointer.
@@ -50,7 +66,7 @@ pub fn image_handle() -> NonNull<c_void> {
5066
/// Get the BootServices Pointer.
5167
/// This function also checks if `ExitBootServices` has already been called.
5268
pub fn boot_services() -> Option<NonNull<c_void>> {
53-
if BOOT_SERVICES_FLAG.get() {
69+
if BOOT_SERVICES_FLAG.load(Ordering::Acquire) {
5470
let system_table: NonNull<r_efi::efi::SystemTable> = try_system_table()?.cast();
5571
let boot_services = unsafe { (*system_table.as_ptr()).boot_services };
5672
NonNull::new(boot_services).map(|x| x.cast())
@@ -62,19 +78,15 @@ pub fn boot_services() -> Option<NonNull<c_void>> {
6278
/// Get the SystemTable Pointer.
6379
/// This function is mostly intended for places where panic is not an option
6480
pub(crate) fn try_system_table() -> Option<NonNull<c_void>> {
65-
GLOBALS.get().map(|x| x.0)
81+
NonNull::new(SYSTEM_TABLE.load(Ordering::Acquire))
6682
}
6783

6884
/// Get the SystemHandle Pointer.
6985
/// This function is mostly intended for places where panicking is not an option
7086
pub(crate) fn try_image_handle() -> Option<NonNull<c_void>> {
71-
GLOBALS.get().map(|x| x.1)
72-
}
73-
74-
pub(crate) fn enable_boot_services() {
75-
BOOT_SERVICES_FLAG.set(true);
87+
NonNull::new(IMAGE_HANDLE.load(Ordering::Acquire))
7688
}
7789

7890
pub(crate) fn disable_boot_services() {
79-
BOOT_SERVICES_FLAG.set(false);
91+
BOOT_SERVICES_FLAG.store(false, Ordering::Release)
8092
}

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

+7-7
Original file line numberDiff line numberDiff line change
@@ -60,13 +60,14 @@ pub(crate) fn locate_handles(mut guid: Guid) -> io::Result<Vec<NonNull<crate::ff
6060
}
6161

6262
// The returned buf_len is in bytes
63-
let mut buf: Vec<r_efi::efi::Handle> =
64-
Vec::with_capacity(buf_len / size_of::<r_efi::efi::Handle>());
63+
assert_eq!(buf_len % size_of::<r_efi::efi::Handle>(), 0);
64+
let num_of_handles = buf_len / size_of::<r_efi::efi::Handle>();
65+
let mut buf: Vec<r_efi::efi::Handle> = Vec::with_capacity(num_of_handles);
6566
match inner(&mut guid, boot_services, &mut buf_len, buf.as_mut_ptr()) {
6667
Ok(()) => {
6768
// This is safe because the call will succeed only if buf_len >= required length.
6869
// Also, on success, the `buf_len` is updated with the size of bufferv (in bytes) written
69-
unsafe { buf.set_len(buf_len / size_of::<r_efi::efi::Handle>()) };
70+
unsafe { buf.set_len(num_of_handles) };
7071
Ok(buf.into_iter().filter_map(|x| NonNull::new(x)).collect())
7172
}
7273
Err(e) => Err(e),
@@ -114,16 +115,15 @@ pub(crate) fn create_event(
114115
) -> io::Result<NonNull<crate::ffi::c_void>> {
115116
let boot_services: NonNull<efi::BootServices> =
116117
boot_services().ok_or(BOOT_SERVICES_UNAVAILABLE)?.cast();
117-
let mut exit_boot_service_event: r_efi::efi::Event = crate::ptr::null_mut();
118+
let mut event: r_efi::efi::Event = crate::ptr::null_mut();
118119
let r = unsafe {
119120
let create_event = (*boot_services.as_ptr()).create_event;
120-
(create_event)(signal, tpl, handler, context, &mut exit_boot_service_event)
121+
(create_event)(signal, tpl, handler, context, &mut event)
121122
};
122123
if r.is_error() {
123124
Err(crate::io::Error::from_raw_os_error(r.as_usize()))
124125
} else {
125-
NonNull::new(exit_boot_service_event)
126-
.ok_or(const_io_error!(io::ErrorKind::Other, "null protocol"))
126+
NonNull::new(event).ok_or(const_io_error!(io::ErrorKind::Other, "null protocol"))
127127
}
128128
}
129129

library/std/src/sys/uefi/mod.rs

+26-10
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@
1212
//! [`OsStr`]: crate::ffi::OsStr
1313
//! [`OsString`]: crate::ffi::OsString
1414
15-
#![deny(unsafe_op_in_unsafe_fn)]
1615
pub mod alloc;
1716
#[path = "../unsupported/args.rs"]
1817
pub mod args;
@@ -43,6 +42,8 @@ pub mod stdio;
4342
pub mod thread;
4443
#[path = "../unsupported/thread_local_key.rs"]
4544
pub mod thread_local_key;
45+
#[path = "../unsupported/thread_parking.rs"]
46+
pub mod thread_parking;
4647
#[path = "../unsupported/time.rs"]
4748
pub mod time;
4849

@@ -53,18 +54,17 @@ mod tests;
5354

5455
pub type RawOsError = usize;
5556

56-
use crate::cell::Cell;
5757
use crate::io as std_io;
5858
use crate::os::uefi;
5959
use crate::ptr::NonNull;
60+
use crate::sync::atomic::{AtomicPtr, Ordering};
6061

6162
pub mod memchr {
6263
pub use core::slice::memchr::{memchr, memrchr};
6364
}
6465

65-
thread_local! {
66-
static EXIT_BOOT_SERVICE_EVENT: Cell<Option<NonNull<crate::ffi::c_void>>> = Cell::new(None);
67-
}
66+
static EXIT_BOOT_SERVICE_EVENT: AtomicPtr<crate::ffi::c_void> =
67+
AtomicPtr::new(crate::ptr::null_mut());
6868

6969
/// # SAFETY
7070
/// - must be called only once during runtime initialization.
@@ -75,8 +75,6 @@ pub(crate) unsafe fn init(argc: isize, argv: *const *const u8, _sigpipe: u8) {
7575
let image_handle = unsafe { NonNull::new(*argv as *mut crate::ffi::c_void).unwrap() };
7676
let system_table = unsafe { NonNull::new(*argv.add(1) as *mut crate::ffi::c_void).unwrap() };
7777
unsafe { uefi::env::init_globals(image_handle, system_table) };
78-
// Enable boot services once GLOBALS are initialized
79-
uefi::env::enable_boot_services();
8078

8179
// Register exit boot services handler
8280
match helpers::create_event(
@@ -86,7 +84,17 @@ pub(crate) unsafe fn init(argc: isize, argv: *const *const u8, _sigpipe: u8) {
8684
crate::ptr::null_mut(),
8785
) {
8886
Ok(x) => {
89-
EXIT_BOOT_SERVICE_EVENT.set(Some(x));
87+
if EXIT_BOOT_SERVICE_EVENT
88+
.compare_exchange(
89+
crate::ptr::null_mut(),
90+
x.as_ptr(),
91+
Ordering::Release,
92+
Ordering::Acquire,
93+
)
94+
.is_err()
95+
{
96+
abort_internal();
97+
};
9098
}
9199
Err(_) => abort_internal(),
92100
}
@@ -96,7 +104,9 @@ pub(crate) unsafe fn init(argc: isize, argv: *const *const u8, _sigpipe: u8) {
96104
/// this is not guaranteed to run, for example when the program aborts.
97105
/// - must be called only once during runtime cleanup.
98106
pub unsafe fn cleanup() {
99-
if let Some(exit_boot_service_event) = EXIT_BOOT_SERVICE_EVENT.take() {
107+
if let Some(exit_boot_service_event) =
108+
NonNull::new(EXIT_BOOT_SERVICE_EVENT.swap(crate::ptr::null_mut(), Ordering::Acquire))
109+
{
100110
let _ = unsafe { helpers::close_event(exit_boot_service_event) };
101111
}
102112
}
@@ -159,7 +169,9 @@ pub fn decode_error_kind(code: RawOsError) -> crate::io::ErrorKind {
159169
}
160170

161171
pub fn abort_internal() -> ! {
162-
if let Some(exit_boot_service_event) = EXIT_BOOT_SERVICE_EVENT.take() {
172+
if let Some(exit_boot_service_event) =
173+
NonNull::new(EXIT_BOOT_SERVICE_EVENT.load(Ordering::Acquire))
174+
{
163175
let _ = unsafe { helpers::close_event(exit_boot_service_event) };
164176
}
165177

@@ -226,3 +238,7 @@ fn get_random() -> Option<(u64, u64)> {
226238
extern "efiapi" fn exit_boot_service_handler(_e: r_efi::efi::Event, _ctx: *mut crate::ffi::c_void) {
227239
uefi::env::disable_boot_services();
228240
}
241+
242+
pub fn is_interrupted(_code: RawOsError) -> bool {
243+
false
244+
}

library/std/src/sys/uefi/os.rs

+33-9
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,16 @@ use crate::ffi::{OsStr, OsString};
44
use crate::fmt;
55
use crate::io;
66
use crate::marker::PhantomData;
7+
use crate::os::uefi;
78
use crate::path::{self, PathBuf};
9+
use crate::ptr::NonNull;
10+
use r_efi::efi::Status;
811

912
pub fn errno() -> RawOsError {
1013
0
1114
}
1215

1316
pub fn error_string(errno: RawOsError) -> String {
14-
use r_efi::efi::Status;
15-
1617
// Keep the List in Alphabetical Order
1718
// The Messages are taken from UEFI Specification Appendix D - Status Codes
1819
match r_efi::efi::Status::from_usize(errno) {
@@ -160,26 +161,36 @@ impl fmt::Display for JoinPathsError {
160161
}
161162
}
162163

163-
impl StdError for JoinPathsError {
164-
#[allow(deprecated)]
165-
fn description(&self) -> &str {
166-
"not supported on this platform yet"
167-
}
168-
}
164+
impl StdError for JoinPathsError {}
169165

170166
pub fn current_exe() -> io::Result<PathBuf> {
171167
unsupported()
172168
}
173169

174170
pub struct Env(!);
175171

172+
impl Env {
173+
// FIXME(https://github.com/rust-lang/rust/issues/114583): Remove this when <OsStr as Debug>::fmt matches <str as Debug>::fmt.
174+
pub fn str_debug(&self) -> impl fmt::Debug + '_ {
175+
let Self(inner) = self;
176+
match *inner {}
177+
}
178+
}
179+
176180
impl Iterator for Env {
177181
type Item = (OsString, OsString);
178182
fn next(&mut self) -> Option<(OsString, OsString)> {
179183
self.0
180184
}
181185
}
182186

187+
impl fmt::Debug for Env {
188+
fn fmt(&self, _: &mut fmt::Formatter<'_>) -> fmt::Result {
189+
let Self(inner) = self;
190+
match *inner {}
191+
}
192+
}
193+
183194
pub fn env() -> Env {
184195
panic!("not supported on this platform")
185196
}
@@ -204,7 +215,20 @@ pub fn home_dir() -> Option<PathBuf> {
204215
None
205216
}
206217

207-
pub fn exit(_code: i32) -> ! {
218+
pub fn exit(code: i32) -> ! {
219+
if let (Some(boot_services), Some(handle)) =
220+
(uefi::env::boot_services(), uefi::env::try_image_handle())
221+
{
222+
let boot_services: NonNull<r_efi::efi::BootServices> = boot_services.cast();
223+
let _ = unsafe {
224+
((*boot_services.as_ptr()).exit)(
225+
handle.as_ptr(),
226+
Status::from_usize(code as usize),
227+
0,
228+
crate::ptr::null_mut(),
229+
)
230+
};
231+
}
208232
crate::intrinsics::abort()
209233
}
210234

0 commit comments

Comments
 (0)