Skip to content

Commit 939e11e

Browse files
committed
Improve std::uefi::env APIs
1. Can now only initialize Global variales once. 2. Panics if `image_handle` or `system_table` is called before initializing them 3. Special case for `abort_internal()` which can be called before the initialization of Globals. Signed-off-by: Ayush Singh <ayushsingh1325@gmail.com>
1 parent a9c1bb8 commit 939e11e

File tree

6 files changed

+39
-39
lines changed

6 files changed

+39
-39
lines changed

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

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,11 @@
33
use crate::ffi::c_void;
44
use crate::ptr::NonNull;
55
use crate::sync::atomic::{AtomicPtr, Ordering};
6+
use crate::sync::Once;
67

78
static GLOBAL_SYSTEM_TABLE: AtomicPtr<c_void> = AtomicPtr::new(crate::ptr::null_mut());
89
static GLOBAL_IMAGE_HANDLE: AtomicPtr<c_void> = AtomicPtr::new(crate::ptr::null_mut());
10+
pub(crate) static GLOBALS: Once = Once::new();
911

1012
/// Initializes the global System Table and Image Handle pointers.
1113
///
@@ -22,18 +24,22 @@ static GLOBAL_IMAGE_HANDLE: AtomicPtr<c_void> = AtomicPtr::new(crate::ptr::null_
2224
/// This function must not be called more than once.
2325
#[unstable(feature = "uefi_std", issue = "100499")]
2426
pub unsafe fn init_globals(handle: NonNull<c_void>, system_table: NonNull<c_void>) {
25-
GLOBAL_SYSTEM_TABLE.store(system_table.as_ptr(), Ordering::Release);
26-
GLOBAL_IMAGE_HANDLE.store(handle.as_ptr(), Ordering::Release);
27+
GLOBALS.call_once(|| {
28+
GLOBAL_SYSTEM_TABLE.store(system_table.as_ptr(), Ordering::Release);
29+
GLOBAL_IMAGE_HANDLE.store(handle.as_ptr(), Ordering::Release);
30+
})
2731
}
2832

2933
/// Get the SystemTable Pointer.
3034
#[unstable(feature = "uefi_std", issue = "100499")]
31-
pub fn system_table() -> Option<NonNull<c_void>> {
32-
NonNull::new(GLOBAL_SYSTEM_TABLE.load(Ordering::Acquire))
35+
pub fn system_table() -> NonNull<c_void> {
36+
assert!(GLOBALS.is_completed());
37+
unsafe { NonNull::new_unchecked(GLOBAL_SYSTEM_TABLE.load(Ordering::Acquire)) }
3338
}
3439

3540
/// Get the SystemHandle Pointer.
3641
#[unstable(feature = "uefi_std", issue = "100499")]
37-
pub fn image_handle() -> Option<NonNull<c_void>> {
38-
NonNull::new(GLOBAL_IMAGE_HANDLE.load(Ordering::Acquire))
42+
pub fn image_handle() -> NonNull<c_void> {
43+
assert!(GLOBALS.is_completed());
44+
unsafe { NonNull::new_unchecked(GLOBAL_IMAGE_HANDLE.load(Ordering::Acquire)) }
3945
}

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

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -12,15 +12,11 @@ pub(crate) const BOOT_SERVICES_ERROR: io::Error =
1212
const_io_error!(io::ErrorKind::Other, "failed to acquire boot services",);
1313
pub(crate) const RUNTIME_SERVICES_ERROR: io::Error =
1414
const_io_error!(io::ErrorKind::Other, "failed to acquire runtime services",);
15-
pub(crate) const SYSTEM_TABLE_ERROR: io::Error =
16-
const_io_error!(io::ErrorKind::Other, "failed to acquire system table",);
17-
pub(crate) const IMAGE_HANDLE_ERROR: io::Error =
18-
const_io_error!(io::ErrorKind::Other, "failed to acquire system handle",);
1915

2016
/// Get the Protocol for current system handle.
2117
/// Note: Some protocols need to be manually freed. It is the callers responsibility to do so.
2218
pub(crate) fn get_current_handle_protocol<T>(protocol_guid: Guid) -> Option<NonNull<T>> {
23-
let system_handle = uefi::env::image_handle()?;
19+
let system_handle = uefi::env::image_handle();
2420
open_protocol(system_handle, protocol_guid).ok()
2521
}
2622

@@ -240,7 +236,7 @@ pub(crate) fn open_protocol<T>(
240236
mut protocol_guid: Guid,
241237
) -> io::Result<NonNull<T>> {
242238
let boot_services = get_boot_services().ok_or(BOOT_SERVICES_ERROR)?;
243-
let system_handle = uefi::env::image_handle().ok_or(IMAGE_HANDLE_ERROR)?;
239+
let system_handle = uefi::env::image_handle();
244240
let mut protocol: MaybeUninit<*mut T> = MaybeUninit::uninit();
245241

246242
let r = unsafe {
@@ -469,14 +465,14 @@ where
469465

470466
/// Get the BootServices Pointer.
471467
pub(crate) fn get_boot_services() -> Option<NonNull<r_efi::efi::BootServices>> {
472-
let system_table: NonNull<r_efi::efi::SystemTable> = uefi::env::system_table()?.cast();
468+
let system_table: NonNull<r_efi::efi::SystemTable> = uefi::env::system_table().cast();
473469
let boot_services = unsafe { (*system_table.as_ptr()).boot_services };
474470
NonNull::new(boot_services)
475471
}
476472

477473
/// Get the RuntimeServices Pointer.
478474
pub(crate) fn get_runtime_services() -> Option<NonNull<r_efi::efi::RuntimeServices>> {
479-
let system_table: NonNull<r_efi::efi::SystemTable> = uefi::env::system_table()?.cast();
475+
let system_table: NonNull<r_efi::efi::SystemTable> = uefi::env::system_table().cast();
480476
let runtime_services = unsafe { (*system_table.as_ptr()).runtime_services };
481477
NonNull::new(runtime_services)
482478
}

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

Lines changed: 14 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -78,21 +78,22 @@ pub fn decode_error_kind(code: i32) -> crate::io::ErrorKind {
7878
}
7979

8080
pub fn abort_internal() -> ! {
81-
// First try to use EFI_BOOT_SERVICES.Exit()
82-
if let (Some(boot_services), Some(handle)) =
83-
(common::get_boot_services(), uefi::env::image_handle())
84-
{
85-
let _ = unsafe {
86-
((*boot_services.as_ptr()).exit)(
87-
handle.as_ptr(),
88-
r_efi::efi::Status::ABORTED,
89-
0,
90-
crate::ptr::null_mut(),
91-
)
92-
};
81+
if uefi::env::GLOBALS.is_completed() {
82+
let handle = uefi::env::image_handle();
83+
// First try to use EFI_BOOT_SERVICES.Exit()
84+
if let Some(boot_services) = common::get_boot_services() {
85+
let _ = unsafe {
86+
((*boot_services.as_ptr()).exit)(
87+
handle.as_ptr(),
88+
r_efi::efi::Status::ABORTED,
89+
0,
90+
crate::ptr::null_mut(),
91+
)
92+
};
93+
}
9394
}
9495

95-
// In case SystemTable and SystemHandle cannot be reached, use `core::intrinsics::abort`
96+
// In case SystemTable and ImageHandle cannot be reached, use `core::intrinsics::abort`
9697
core::intrinsics::abort();
9798
}
9899

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

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -182,12 +182,12 @@ pub fn exit(code: i32) -> ! {
182182
Err(_) => r_efi::efi::Status::ABORTED,
183183
};
184184

185+
let handle = uefi::env::image_handle().cast();
185186
// First try to use EFI_BOOT_SERVICES.Exit()
186-
if let (Some(boot_services), Some(handle)) =
187-
(common::get_boot_services(), uefi::env::image_handle())
188-
{
189-
let _ =
190-
unsafe { ((*boot_services.as_ptr()).exit)(handle.as_ptr(), code, 0, [0].as_mut_ptr()) };
187+
if let Some(boot_services) = common::get_boot_services() {
188+
let _ = unsafe {
189+
((*boot_services.as_ptr()).exit)(handle.as_ptr(), code, 0, crate::ptr::null_mut())
190+
};
191191
}
192192

193193
// If exit is not possible, the call abort

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -310,7 +310,7 @@ mod uefi_command {
310310
impl Command {
311311
pub(crate) fn load_image(p: &OsStr) -> io::Result<Self> {
312312
let boot_services = common::get_boot_services().ok_or(common::BOOT_SERVICES_ERROR)?;
313-
let system_handle = uefi::env::image_handle().ok_or(common::IMAGE_HANDLE_ERROR)?;
313+
let system_handle = uefi::env::image_handle();
314314
let mut path = super::super::path::device_path_from_os_str(p)?;
315315
let mut child_handle: MaybeUninit<r_efi::efi::Handle> = MaybeUninit::uninit();
316316
let r = unsafe {

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

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -84,8 +84,7 @@ impl io::Read for Stdin {
8484
return pipe::AnonPipe::new(None, None, pipe_protocol).read(buf);
8585
}
8686
}
87-
let global_system_table =
88-
uefi::env::system_table().ok_or(common::SYSTEM_TABLE_ERROR)?.cast();
87+
let global_system_table = uefi::env::system_table().cast();
8988
let con_in = get_con_in(global_system_table)?;
9089
let con_out = get_con_out(global_system_table)?;
9190
let wait_for_event = get_wait_for_event()?;
@@ -138,8 +137,7 @@ impl io::Write for Stdout {
138137
}
139138
}
140139

141-
let global_system_table =
142-
uefi::env::system_table().ok_or(common::SYSTEM_TABLE_ERROR)?.cast();
140+
let global_system_table = uefi::env::system_table().cast();
143141
let con_out = get_con_out(global_system_table)?;
144142
unsafe { simple_text_output_write(con_out.as_ptr(), buf) }
145143
}
@@ -169,8 +167,7 @@ impl io::Write for Stderr {
169167
return pipe::AnonPipe::new(None, None, pipe_protocol).write(buf);
170168
}
171169
}
172-
let global_system_table =
173-
uefi::env::system_table().ok_or(common::SYSTEM_TABLE_ERROR)?.cast();
170+
let global_system_table = uefi::env::system_table().cast();
174171
let std_err = get_std_err(global_system_table)?;
175172
unsafe { simple_text_output_write(std_err.as_ptr(), buf) }
176173
}

0 commit comments

Comments
 (0)