Skip to content

Commit 2345867

Browse files
committed
Improve handling of Globals
Builds upon 4032d3a2378da875dfeb1522101d2e87033ae5c0. Use the non-panic version in places where panic should be avoided. Signed-off-by: Ayush Singh <ayushsingh1325@gmail.com>
1 parent 67329ff commit 2345867

File tree

9 files changed

+91
-88
lines changed

9 files changed

+91
-88
lines changed

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

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -31,15 +31,29 @@ pub unsafe fn init_globals(handle: NonNull<c_void>, system_table: NonNull<c_void
3131
}
3232

3333
/// Get the SystemTable Pointer.
34+
/// Note: This function panics if the System Table and Image Handle is Not initialized
3435
#[unstable(feature = "uefi_std", issue = "100499")]
3536
pub fn system_table() -> NonNull<c_void> {
36-
assert!(GLOBALS.is_completed());
37-
unsafe { NonNull::new_unchecked(GLOBAL_SYSTEM_TABLE.load(Ordering::Acquire)) }
37+
try_system_table().unwrap()
38+
}
39+
40+
/// Get the SystemTable Pointer.
41+
/// This function is mostly intended for places where panic is not an option
42+
#[unstable(feature = "uefi_std", issue = "100499")]
43+
pub fn try_system_table() -> Option<NonNull<c_void>> {
44+
NonNull::new(GLOBAL_SYSTEM_TABLE.load(Ordering::Acquire))
3845
}
3946

4047
/// Get the SystemHandle Pointer.
48+
/// Note: This function panics if the System Table and Image Handle is Not initialized
4149
#[unstable(feature = "uefi_std", issue = "100499")]
4250
pub fn image_handle() -> NonNull<c_void> {
43-
assert!(GLOBALS.is_completed());
44-
unsafe { NonNull::new_unchecked(GLOBAL_IMAGE_HANDLE.load(Ordering::Acquire)) }
51+
try_image_handle().unwrap()
52+
}
53+
54+
/// Get the SystemHandle Pointer.
55+
/// This function is mostly intended for places where panic is not an option
56+
#[unstable(feature = "uefi_std", issue = "100499")]
57+
pub fn try_image_handle() -> Option<NonNull<c_void>> {
58+
NonNull::new(GLOBAL_IMAGE_HANDLE.load(Ordering::Acquire))
4559
}

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ unsafe impl GlobalAlloc for System {
1818

1919
// Return NULL pointer if boot_services pointer cannot be obtained. The only time this
2020
// should happen is if SystemTable has not been initialized
21-
let boot_services = match common::get_boot_services() {
21+
let boot_services = match common::try_boot_services() {
2222
Some(x) => x,
2323
None => return ptr::null_mut(),
2424
};
@@ -38,7 +38,7 @@ unsafe impl GlobalAlloc for System {
3838
}
3939

4040
unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) {
41-
let boot_services = match common::get_boot_services() {
41+
let boot_services = match common::try_boot_services() {
4242
Some(x) => x,
4343
None => return,
4444
};

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

Lines changed: 19 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,6 @@ use crate::os::uefi;
88
use crate::os::uefi::ffi::{OsStrExt, OsStringExt};
99
use crate::ptr::NonNull;
1010

11-
pub(crate) const BOOT_SERVICES_ERROR: io::Error =
12-
const_io_error!(io::ErrorKind::Other, "failed to acquire boot services",);
13-
pub(crate) const RUNTIME_SERVICES_ERROR: io::Error =
14-
const_io_error!(io::ErrorKind::Other, "failed to acquire runtime services",);
15-
1611
/// Get the Protocol for current system handle.
1712
/// Note: Some protocols need to be manually freed. It is the callers responsibility to do so.
1813
pub(crate) fn get_current_handle_protocol<T>(protocol_guid: Guid) -> Option<NonNull<T>> {
@@ -42,7 +37,7 @@ impl Event {
4237
notify_function: Option<EventNotify>,
4338
notify_context: Option<NonNull<crate::ffi::c_void>>,
4439
) -> io::Result<Self> {
45-
let boot_services = get_boot_services().ok_or(BOOT_SERVICES_ERROR)?;
40+
let boot_services = boot_services();
4641

4742
let mut event: r_efi::efi::Event = crate::ptr::null_mut();
4843
let notify_context = match notify_context {
@@ -69,7 +64,7 @@ impl Event {
6964
}
7065

7166
pub(crate) fn wait(&self) -> io::Result<()> {
72-
let boot_services = get_boot_services().ok_or(BOOT_SERVICES_ERROR)?;
67+
let boot_services = boot_services();
7368

7469
let mut index = 0usize;
7570
let r = unsafe {
@@ -91,10 +86,9 @@ impl Event {
9186

9287
impl Drop for Event {
9388
fn drop(&mut self) {
94-
if let Some(boot_services) = get_boot_services() {
95-
// Always returns EFI_SUCCESS
96-
let _ = unsafe { ((*boot_services.as_ptr()).close_event)(self.inner.as_ptr()) };
97-
}
89+
let boot_services = boot_services();
90+
// Always returns EFI_SUCCESS
91+
let _ = unsafe { ((*boot_services.as_ptr()).close_event)(self.inner.as_ptr()) };
9892
}
9993
}
10094

@@ -203,7 +197,7 @@ pub(crate) fn locate_handles(mut guid: Guid) -> io::Result<Vec<NonNull<crate::ff
203197
if r.is_error() { Err(status_to_io_error(r)) } else { Ok(()) }
204198
}
205199

206-
let boot_services = get_boot_services().ok_or(BOOT_SERVICES_ERROR)?;
200+
let boot_services = boot_services();
207201
let mut buf_len = 0usize;
208202

209203
match inner(&mut guid, boot_services, &mut buf_len, crate::ptr::null_mut()) {
@@ -235,7 +229,7 @@ pub(crate) fn open_protocol<T>(
235229
handle: NonNull<crate::ffi::c_void>,
236230
mut protocol_guid: Guid,
237231
) -> io::Result<NonNull<T>> {
238-
let boot_services = get_boot_services().ok_or(BOOT_SERVICES_ERROR)?;
232+
let boot_services = boot_services();
239233
let system_handle = uefi::env::image_handle();
240234
let mut protocol: MaybeUninit<*mut T> = MaybeUninit::uninit();
241235

@@ -376,7 +370,7 @@ pub(crate) fn install_protocol<T>(
376370
mut guid: r_efi::efi::Guid,
377371
interface: &mut T,
378372
) -> io::Result<()> {
379-
let boot_services = get_boot_services().ok_or(BOOT_SERVICES_ERROR)?;
373+
let boot_services = boot_services();
380374
let r = unsafe {
381375
((*boot_services.as_ptr()).install_protocol_interface)(
382376
handle,
@@ -393,7 +387,7 @@ pub(crate) fn uninstall_protocol<T>(
393387
mut guid: r_efi::efi::Guid,
394388
interface: &mut T,
395389
) -> io::Result<()> {
396-
let boot_services = get_boot_services().ok_or(BOOT_SERVICES_ERROR)?;
390+
let boot_services = boot_services();
397391
let r = unsafe {
398392
((*boot_services.as_ptr()).uninstall_protocol_interface)(
399393
handle,
@@ -464,17 +458,24 @@ where
464458
}
465459

466460
/// Get the BootServices Pointer.
467-
pub(crate) fn get_boot_services() -> Option<NonNull<r_efi::efi::BootServices>> {
461+
pub(crate) fn boot_services() -> NonNull<r_efi::efi::BootServices> {
468462
let system_table: NonNull<r_efi::efi::SystemTable> = uefi::env::system_table().cast();
469463
let boot_services = unsafe { (*system_table.as_ptr()).boot_services };
464+
NonNull::new(boot_services).unwrap()
465+
}
466+
/// Get the BootServices Pointer.
467+
/// This function is mostly intended for places where panic is not an option
468+
pub(crate) fn try_boot_services() -> Option<NonNull<r_efi::efi::BootServices>> {
469+
let system_table: NonNull<r_efi::efi::SystemTable> = uefi::env::try_system_table()?.cast();
470+
let boot_services = unsafe { (*system_table.as_ptr()).boot_services };
470471
NonNull::new(boot_services)
471472
}
472473

473474
/// Get the RuntimeServices Pointer.
474-
pub(crate) fn get_runtime_services() -> Option<NonNull<r_efi::efi::RuntimeServices>> {
475+
pub(crate) fn runtime_services() -> NonNull<r_efi::efi::RuntimeServices> {
475476
let system_table: NonNull<r_efi::efi::SystemTable> = uefi::env::system_table().cast();
476477
let runtime_services = unsafe { (*system_table.as_ptr()).runtime_services };
477-
NonNull::new(runtime_services)
478+
NonNull::new(runtime_services).unwrap()
478479
}
479480

480481
// Create UCS-2 Vector from OsStr

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

Lines changed: 18 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -79,19 +79,17 @@ pub fn decode_error_kind(code: i32) -> crate::io::ErrorKind {
7979
}
8080

8181
pub fn abort_internal() -> ! {
82-
if uefi::env::GLOBALS.is_completed() {
83-
let handle = uefi::env::image_handle();
84-
// First try to use EFI_BOOT_SERVICES.Exit()
85-
if let Some(boot_services) = common::get_boot_services() {
86-
let _ = unsafe {
87-
((*boot_services.as_ptr()).exit)(
88-
handle.as_ptr(),
89-
r_efi::efi::Status::ABORTED,
90-
0,
91-
crate::ptr::null_mut(),
92-
)
93-
};
94-
}
82+
if let (Some(boot_services), Some(handle)) =
83+
(common::try_boot_services(), uefi::env::try_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+
};
9593
}
9694

9795
// In case SystemTable and ImageHandle cannot be reached, use `core::intrinsics::abort`
@@ -146,16 +144,14 @@ pub unsafe extern "efiapi" fn efi_main(
146144
handle: r_efi::efi::Handle,
147145
st: *mut r_efi::efi::SystemTable,
148146
) -> r_efi::efi::Status {
149-
// Null SystemTable and ImageHandle is an ABI violoation
150-
assert!(!st.is_null());
151-
assert!(!handle.is_null());
152-
153-
let system_table = unsafe { NonNull::new_unchecked(st) };
154-
let image_handle = unsafe { NonNull::new_unchecked(handle) };
147+
let system_table = NonNull::new(st).unwrap();
148+
let image_handle = NonNull::new(handle).unwrap();
155149
unsafe { uefi::env::init_globals(image_handle, system_table.cast()) };
156150

157-
match unsafe { main(0, crate::ptr::null()) } {
158-
0 => r_efi::efi::Status::SUCCESS,
159-
_ => r_efi::efi::Status::ABORTED, // Or some other status code
151+
let res = unsafe { main(0, crate::ptr::null()) };
152+
153+
match usize::try_from(res) {
154+
Ok(x) => r_efi::efi::Status::from_usize(x),
155+
Err(_) => r_efi::efi::Status::ABORTED,
160156
}
161157
}

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

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

185-
let handle = uefi::env::image_handle().cast();
186185
// First try to use EFI_BOOT_SERVICES.Exit()
187-
if let Some(boot_services) = common::get_boot_services() {
186+
if let (Some(handle), Some(boot_services)) =
187+
(uefi::env::try_image_handle(), common::try_boot_services())
188+
{
188189
let _ = unsafe {
189190
((*boot_services.as_ptr()).exit)(handle.as_ptr(), code, 0, crate::ptr::null_mut())
190191
};
@@ -304,8 +305,7 @@ pub(crate) mod uefi_vars {
304305
data_size: usize,
305306
data: *mut crate::ffi::c_void,
306307
) -> io::Result<()> {
307-
let runtime_services =
308-
common::get_runtime_services().ok_or(common::RUNTIME_SERVICES_ERROR)?;
308+
let runtime_services = common::runtime_services();
309309
let r = unsafe {
310310
((*runtime_services.as_ptr()).set_variable)(
311311
variable_name,
@@ -324,8 +324,7 @@ pub(crate) mod uefi_vars {
324324
data_size: &mut usize,
325325
data: *mut crate::ffi::c_void,
326326
) -> io::Result<()> {
327-
let runtime_services =
328-
common::get_runtime_services().ok_or(common::RUNTIME_SERVICES_ERROR)?;
327+
let runtime_services = common::runtime_services();
329328
let r = unsafe {
330329
((*runtime_services.as_ptr()).get_variable)(
331330
key,
@@ -343,8 +342,7 @@ pub(crate) mod uefi_vars {
343342
variable_name: *mut u16,
344343
vendor_guid: *mut r_efi::efi::Guid,
345344
) -> io::Result<()> {
346-
let runtime_services =
347-
common::get_runtime_services().ok_or(common::RUNTIME_SERVICES_ERROR)?;
345+
let runtime_services = common::runtime_services();
348346
let r = unsafe {
349347
((*runtime_services.as_ptr()).get_next_variable_name)(
350348
variable_name_size,

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

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -309,7 +309,7 @@ mod uefi_command {
309309

310310
impl Command {
311311
pub(crate) fn load_image(p: &OsStr) -> io::Result<Self> {
312-
let boot_services = common::get_boot_services().ok_or(common::BOOT_SERVICES_ERROR)?;
312+
let boot_services = common::boot_services();
313313
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();
@@ -337,7 +337,7 @@ mod uefi_command {
337337
}
338338

339339
pub(crate) fn start_image(&self) -> io::Result<r_efi::efi::Status> {
340-
let boot_services = common::get_boot_services().ok_or(common::BOOT_SERVICES_ERROR)?;
340+
let boot_services = common::boot_services();
341341
let mut exit_data_size: MaybeUninit<usize> = MaybeUninit::uninit();
342342
let mut exit_data: MaybeUninit<*mut u16> = MaybeUninit::uninit();
343343
let r = unsafe {
@@ -373,10 +373,9 @@ mod uefi_command {
373373
impl Drop for Command {
374374
// Unload Image
375375
fn drop(&mut self) {
376-
if let Some(boot_services) = common::get_boot_services() {
377-
self.command_protocol = None;
378-
let _ = unsafe { ((*boot_services.as_ptr()).unload_image)(self.handle.as_ptr()) };
379-
}
376+
let boot_services = common::boot_services();
377+
self.command_protocol = None;
378+
let _ = unsafe { ((*boot_services.as_ptr()).unload_image)(self.handle.as_ptr()) };
380379
}
381380
}
382381
}

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

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,12 @@ impl Stderr {
159159

160160
impl io::Write for Stderr {
161161
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
162+
// Since wrtiting to stderr might be tried due to a panic caused by unintialized GLOBALS,
163+
// this check ensures we do not cause an inifinte panic loop.
164+
if !uefi::env::GLOBALS.is_completed() {
165+
return Err(io::const_io_error!(io::ErrorKind::Other, "Globals not intialized"));
166+
}
167+
162168
if let Some(command_protocol) = common::get_current_handle_protocol::<
163169
uefi_command_protocol::Protocol,
164170
>(uefi_command_protocol::PROTOCOL_GUID)
@@ -249,7 +255,7 @@ fn get_con_in(
249255

250256
#[inline]
251257
fn get_wait_for_event() -> io::Result<BootWaitForEvent> {
252-
let boot_services = common::get_boot_services().ok_or(common::BOOT_SERVICES_ERROR)?;
258+
let boot_services = common::boot_services();
253259
Ok(unsafe { (*boot_services.as_ptr()).wait_for_event })
254260
}
255261

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

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -24,11 +24,8 @@ impl Thread {
2424
}
2525

2626
pub fn sleep(dur: Duration) {
27-
if let Some(boot_services) = common::get_boot_services() {
28-
let _ = unsafe { ((*boot_services.as_ptr()).stall)(dur.as_micros() as usize) };
29-
} else {
30-
panic!("Boot services needed for sleep")
31-
}
27+
let boot_services = common::boot_services();
28+
let _ = unsafe { ((*boot_services.as_ptr()).stall)(dur.as_micros() as usize) };
3229
}
3330

3431
pub fn join(self) {

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

Lines changed: 14 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -50,18 +50,14 @@ impl Instant {
5050
if let Some(ns) = get_timestamp() {
5151
return Instant(Duration::from_nanos(ns));
5252
}
53+
let runtime_services = common::runtime_services();
5354

54-
if let Some(runtime_services) = common::get_runtime_services() {
55-
// Finally just use `EFI_RUNTIME_SERVICES.GetTime()`
56-
let mut t = r_efi::efi::Time::default();
57-
let r =
58-
unsafe { ((*runtime_services.as_ptr()).get_time)(&mut t, crate::ptr::null_mut()) };
55+
// Finally just use `EFI_RUNTIME_SERVICES.GetTime()`
56+
let mut t = r_efi::efi::Time::default();
57+
let r = unsafe { ((*runtime_services.as_ptr()).get_time)(&mut t, crate::ptr::null_mut()) };
5958

60-
if r.is_error() {
61-
panic!("time not implemented on this platform")
62-
} else {
63-
return Instant(uefi_time_to_duration(t));
64-
}
59+
if !r.is_error() {
60+
return Instant(uefi_time_to_duration(t));
6561
}
6662

6763
// Panic if nothing works
@@ -87,19 +83,15 @@ impl Instant {
8783
// Using Unix representation of Time.
8884
impl SystemTime {
8985
pub fn now() -> SystemTime {
90-
if let Some(runtime_services) = common::get_runtime_services() {
91-
let mut t = r_efi::efi::Time::default();
92-
let r =
93-
unsafe { ((*runtime_services.as_ptr()).get_time)(&mut t, crate::ptr::null_mut()) };
94-
95-
if r.is_error() {
96-
panic!("time not implemented on this platform")
97-
} else {
98-
SystemTime::from(t)
99-
}
100-
} else {
101-
panic!("Runtime Services are needed for Time to work")
86+
let runtime_services = common::runtime_services();
87+
let mut t = r_efi::efi::Time::default();
88+
let r = unsafe { ((*runtime_services.as_ptr()).get_time)(&mut t, crate::ptr::null_mut()) };
89+
90+
if !r.is_error() {
91+
return SystemTime::from(t);
10292
}
93+
94+
panic!("Failed to create SystemTime")
10395
}
10496

10597
#[inline]

0 commit comments

Comments
 (0)