about summary refs log tree commit diff
path: root/library/std/src/sys/uefi
diff options
context:
space:
mode:
authorAyush Singh <ayushsingh1325@gmail.com>2023-05-21 14:26:59 +0530
committerAyush Singh <ayushdevel1325@gmail.com>2023-09-22 17:23:33 +0530
commitc7e5f3ca085c3adfd285a6d41080ff65a6299bc9 (patch)
tree116df502759aa3ddff2b95e388736ba981c3ac7e /library/std/src/sys/uefi
parent40c3dacc767a4fbf42ea5dfa686a54acf9ded5fb (diff)
downloadrust-c7e5f3ca085c3adfd285a6d41080ff65a6299bc9.tar.gz
rust-c7e5f3ca085c3adfd285a6d41080ff65a6299bc9.zip
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>
Diffstat (limited to 'library/std/src/sys/uefi')
-rw-r--r--library/std/src/sys/uefi/helpers.rs14
-rw-r--r--library/std/src/sys/uefi/mod.rs36
-rw-r--r--library/std/src/sys/uefi/os.rs42
3 files changed, 66 insertions, 26 deletions
diff --git a/library/std/src/sys/uefi/helpers.rs b/library/std/src/sys/uefi/helpers.rs
index 2e1bcb36944..126661bfc96 100644
--- a/library/std/src/sys/uefi/helpers.rs
+++ b/library/std/src/sys/uefi/helpers.rs
@@ -60,13 +60,14 @@ pub(crate) fn locate_handles(mut guid: Guid) -> io::Result<Vec<NonNull<crate::ff
     }
 
     // The returned buf_len is in bytes
-    let mut buf: Vec<r_efi::efi::Handle> =
-        Vec::with_capacity(buf_len / size_of::<r_efi::efi::Handle>());
+    assert_eq!(buf_len % size_of::<r_efi::efi::Handle>(), 0);
+    let num_of_handles = buf_len / size_of::<r_efi::efi::Handle>();
+    let mut buf: Vec<r_efi::efi::Handle> = Vec::with_capacity(num_of_handles);
     match inner(&mut guid, boot_services, &mut buf_len, buf.as_mut_ptr()) {
         Ok(()) => {
             // 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 / size_of::<r_efi::efi::Handle>()) };
+            unsafe { buf.set_len(num_of_handles) };
             Ok(buf.into_iter().filter_map(|x| NonNull::new(x)).collect())
         }
         Err(e) => Err(e),
@@ -114,16 +115,15 @@ pub(crate) fn create_event(
 ) -> io::Result<NonNull<crate::ffi::c_void>> {
     let boot_services: NonNull<efi::BootServices> =
         boot_services().ok_or(BOOT_SERVICES_UNAVAILABLE)?.cast();
-    let mut exit_boot_service_event: r_efi::efi::Event = crate::ptr::null_mut();
+    let mut event: r_efi::efi::Event = crate::ptr::null_mut();
     let r = unsafe {
         let create_event = (*boot_services.as_ptr()).create_event;
-        (create_event)(signal, tpl, handler, context, &mut exit_boot_service_event)
+        (create_event)(signal, tpl, handler, context, &mut event)
     };
     if r.is_error() {
         Err(crate::io::Error::from_raw_os_error(r.as_usize()))
     } else {
-        NonNull::new(exit_boot_service_event)
-            .ok_or(const_io_error!(io::ErrorKind::Other, "null protocol"))
+        NonNull::new(event).ok_or(const_io_error!(io::ErrorKind::Other, "null protocol"))
     }
 }
 
diff --git a/library/std/src/sys/uefi/mod.rs b/library/std/src/sys/uefi/mod.rs
index 85d00caf149..9a10395af8e 100644
--- a/library/std/src/sys/uefi/mod.rs
+++ b/library/std/src/sys/uefi/mod.rs
@@ -12,7 +12,6 @@
 //! [`OsStr`]: crate::ffi::OsStr
 //! [`OsString`]: crate::ffi::OsString
 
-#![deny(unsafe_op_in_unsafe_fn)]
 pub mod alloc;
 #[path = "../unsupported/args.rs"]
 pub mod args;
@@ -43,6 +42,8 @@ pub mod stdio;
 pub mod thread;
 #[path = "../unsupported/thread_local_key.rs"]
 pub mod thread_local_key;
+#[path = "../unsupported/thread_parking.rs"]
+pub mod thread_parking;
 #[path = "../unsupported/time.rs"]
 pub mod time;
 
@@ -53,18 +54,17 @@ mod tests;
 
 pub type RawOsError = usize;
 
-use crate::cell::Cell;
 use crate::io as std_io;
 use crate::os::uefi;
 use crate::ptr::NonNull;
+use crate::sync::atomic::{AtomicPtr, Ordering};
 
 pub mod memchr {
     pub use core::slice::memchr::{memchr, memrchr};
 }
 
-thread_local! {
-    static EXIT_BOOT_SERVICE_EVENT: Cell<Option<NonNull<crate::ffi::c_void>>> = Cell::new(None);
-}
+static EXIT_BOOT_SERVICE_EVENT: AtomicPtr<crate::ffi::c_void> =
+    AtomicPtr::new(crate::ptr::null_mut());
 
 /// # SAFETY
 /// - 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) {
     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 { uefi::env::init_globals(image_handle, system_table) };
-    // Enable boot services once GLOBALS are initialized
-    uefi::env::enable_boot_services();
 
     // Register exit boot services handler
     match helpers::create_event(
@@ -86,7 +84,17 @@ pub(crate) unsafe fn init(argc: isize, argv: *const *const u8, _sigpipe: u8) {
         crate::ptr::null_mut(),
     ) {
         Ok(x) => {
-            EXIT_BOOT_SERVICE_EVENT.set(Some(x));
+            if EXIT_BOOT_SERVICE_EVENT
+                .compare_exchange(
+                    crate::ptr::null_mut(),
+                    x.as_ptr(),
+                    Ordering::Release,
+                    Ordering::Acquire,
+                )
+                .is_err()
+            {
+                abort_internal();
+            };
         }
         Err(_) => abort_internal(),
     }
@@ -96,7 +104,9 @@ pub(crate) unsafe fn init(argc: isize, argv: *const *const u8, _sigpipe: u8) {
 /// this is not guaranteed to run, for example when the program aborts.
 /// - must be called only once during runtime cleanup.
 pub unsafe fn cleanup() {
-    if let Some(exit_boot_service_event) = EXIT_BOOT_SERVICE_EVENT.take() {
+    if let Some(exit_boot_service_event) =
+        NonNull::new(EXIT_BOOT_SERVICE_EVENT.swap(crate::ptr::null_mut(), Ordering::Acquire))
+    {
         let _ = unsafe { helpers::close_event(exit_boot_service_event) };
     }
 }
@@ -159,7 +169,9 @@ pub fn decode_error_kind(code: RawOsError) -> crate::io::ErrorKind {
 }
 
 pub fn abort_internal() -> ! {
-    if let Some(exit_boot_service_event) = EXIT_BOOT_SERVICE_EVENT.take() {
+    if let Some(exit_boot_service_event) =
+        NonNull::new(EXIT_BOOT_SERVICE_EVENT.load(Ordering::Acquire))
+    {
         let _ = unsafe { helpers::close_event(exit_boot_service_event) };
     }
 
@@ -226,3 +238,7 @@ fn get_random() -> Option<(u64, u64)> {
 extern "efiapi" fn exit_boot_service_handler(_e: r_efi::efi::Event, _ctx: *mut crate::ffi::c_void) {
     uefi::env::disable_boot_services();
 }
+
+pub fn is_interrupted(_code: RawOsError) -> bool {
+    false
+}
diff --git a/library/std/src/sys/uefi/os.rs b/library/std/src/sys/uefi/os.rs
index cd489d8f7f9..e6693db68e6 100644
--- a/library/std/src/sys/uefi/os.rs
+++ b/library/std/src/sys/uefi/os.rs
@@ -4,15 +4,16 @@ use crate::ffi::{OsStr, OsString};
 use crate::fmt;
 use crate::io;
 use crate::marker::PhantomData;
+use crate::os::uefi;
 use crate::path::{self, PathBuf};
+use crate::ptr::NonNull;
+use r_efi::efi::Status;
 
 pub fn errno() -> RawOsError {
     0
 }
 
 pub fn error_string(errno: RawOsError) -> String {
-    use r_efi::efi::Status;
-
     // Keep the List in Alphabetical Order
     // The Messages are taken from UEFI Specification Appendix D - Status Codes
     match r_efi::efi::Status::from_usize(errno) {
@@ -160,12 +161,7 @@ impl fmt::Display for JoinPathsError {
     }
 }
 
-impl StdError for JoinPathsError {
-    #[allow(deprecated)]
-    fn description(&self) -> &str {
-        "not supported on this platform yet"
-    }
-}
+impl StdError for JoinPathsError {}
 
 pub fn current_exe() -> io::Result<PathBuf> {
     unsupported()
@@ -173,6 +169,14 @@ pub fn current_exe() -> io::Result<PathBuf> {
 
 pub struct Env(!);
 
+impl Env {
+    // FIXME(https://github.com/rust-lang/rust/issues/114583): Remove this when <OsStr as Debug>::fmt matches <str as Debug>::fmt.
+    pub fn str_debug(&self) -> impl fmt::Debug + '_ {
+        let Self(inner) = self;
+        match *inner {}
+    }
+}
+
 impl Iterator for Env {
     type Item = (OsString, OsString);
     fn next(&mut self) -> Option<(OsString, OsString)> {
@@ -180,6 +184,13 @@ impl Iterator for Env {
     }
 }
 
+impl fmt::Debug for Env {
+    fn fmt(&self, _: &mut fmt::Formatter<'_>) -> fmt::Result {
+        let Self(inner) = self;
+        match *inner {}
+    }
+}
+
 pub fn env() -> Env {
     panic!("not supported on this platform")
 }
@@ -204,7 +215,20 @@ pub fn home_dir() -> Option<PathBuf> {
     None
 }
 
-pub fn exit(_code: i32) -> ! {
+pub fn exit(code: i32) -> ! {
+    if let (Some(boot_services), Some(handle)) =
+        (uefi::env::boot_services(), uefi::env::try_image_handle())
+    {
+        let boot_services: NonNull<r_efi::efi::BootServices> = boot_services.cast();
+        let _ = unsafe {
+            ((*boot_services.as_ptr()).exit)(
+                handle.as_ptr(),
+                Status::from_usize(code as usize),
+                0,
+                crate::ptr::null_mut(),
+            )
+        };
+    }
     crate::intrinsics::abort()
 }