From 5df24d18b6cdb8abcede6b658cf066360a219c12 Mon Sep 17 00:00:00 2001 From: Ayush Singh Date: Mon, 27 Mar 2023 19:53:53 +0530 Subject: [PATCH] Add support for building `std::os::uefi` docs Signed-off-by: Ayush Singh --- library/std/src/os/mod.rs | 1 + library/std/src/os/uefi/env.rs | 32 +++++++++++-------- library/std/src/os/uefi/mod.rs | 1 + library/std/src/sys/uefi/alloc.rs | 15 +++------ library/std/src/sys/uefi/helpers.rs | 11 ++++--- library/std/src/sys/uefi/mod.rs | 1 + .../src/platform-support/unknown-uefi.md | 11 +++---- 7 files changed, 38 insertions(+), 34 deletions(-) diff --git a/library/std/src/os/mod.rs b/library/std/src/os/mod.rs index 11ad21515fde..d1a735038992 100644 --- a/library/std/src/os/mod.rs +++ b/library/std/src/os/mod.rs @@ -143,6 +143,7 @@ pub mod solid; #[path = "ios/mod.rs"] pub(crate) mod tvos; #[cfg(target_os = "uefi")] +#[cfg(any(target_os = "uefi", doc))] pub mod uefi; #[cfg(target_os = "vita")] pub mod vita; diff --git a/library/std/src/os/uefi/env.rs b/library/std/src/os/uefi/env.rs index e62441596f3a..41dc7ccdb6ad 100644 --- a/library/std/src/os/uefi/env.rs +++ b/library/std/src/os/uefi/env.rs @@ -32,41 +32,45 @@ pub unsafe fn init_globals(handle: NonNull, system_table: NonNull NonNull { try_system_table().unwrap() } /// Get the ImageHandle Pointer. +/// /// Note: This function panics if the System Table or Image Handle is not initialized pub fn image_handle() -> NonNull { try_image_handle().unwrap() } +/// Get the BootServices Pointer. +/// This function also checks if `ExitBootServices` has already been called. +pub fn boot_services() -> Option> { + if BOOT_SERVICES_FLAG.get() { + let system_table: NonNull = try_system_table()?.cast(); + let boot_services = unsafe { (*system_table.as_ptr()).boot_services }; + NonNull::new(boot_services).map(|x| x.cast()) + } else { + None + } +} + /// Get the SystemTable Pointer. /// This function is mostly intended for places where panic is not an option -pub(crate) fn try_system_table() -> Option> { +pub(crate) fn try_system_table() -> Option> { GLOBALS.get().map(|x| x.0) } /// Get the SystemHandle Pointer. /// This function is mostly intended for places where panic is not an option -pub(crate) fn try_image_handle() -> Option> { +pub(crate) fn try_image_handle() -> Option> { GLOBALS.get().map(|x| x.1) } -/// Get the BootServices Pointer. -/// This function also checks if `ExitBootServices` has already been called. -pub(crate) fn boot_services() -> Option> { - if BOOT_SERVICES_FLAG.get() { - let system_table: NonNull = try_system_table()?.cast(); - let boot_services = unsafe { (*system_table.as_ptr()).boot_services }; - NonNull::new(boot_services) - } else { - None - } -} - pub(crate) fn enable_boot_services() { BOOT_SERVICES_FLAG.set(true); } diff --git a/library/std/src/os/uefi/mod.rs b/library/std/src/os/uefi/mod.rs index fc0468f25fc8..8ef05eee1f4e 100644 --- a/library/std/src/os/uefi/mod.rs +++ b/library/std/src/os/uefi/mod.rs @@ -1,6 +1,7 @@ //! Platform-specific extensions to `std` for UEFI. #![unstable(feature = "uefi_std", issue = "100499")] +#![doc(cfg(target_os = "uefi"))] pub mod env; #[path = "../windows/ffi.rs"] diff --git a/library/std/src/sys/uefi/alloc.rs b/library/std/src/sys/uefi/alloc.rs index d6eb371033ce..789e3cbd81ad 100644 --- a/library/std/src/sys/uefi/alloc.rs +++ b/library/std/src/sys/uefi/alloc.rs @@ -1,7 +1,7 @@ //! Global Allocator for UEFI. //! Uses [r-efi-alloc](https://crates.io/crates/r-efi-alloc) -use crate::alloc::{handle_alloc_error, GlobalAlloc, Layout, System}; +use crate::alloc::{GlobalAlloc, Layout, System}; const MEMORY_TYPE: u32 = r_efi::efi::LOADER_DATA; @@ -13,11 +13,8 @@ unsafe impl GlobalAlloc for System { return crate::ptr::null_mut(); } - let system_table = match crate::os::uefi::env::try_system_table() { - None => return crate::ptr::null_mut(), - Some(x) => x.as_ptr() as *mut _, - }; - + // If boot services is valid then SystemTable is not null. + let system_table = crate::os::uefi::env::system_table().as_ptr().cast(); // The caller must ensure non-0 layout unsafe { r_efi_alloc::raw::alloc(system_table, layout, MEMORY_TYPE) } } @@ -28,10 +25,8 @@ unsafe impl GlobalAlloc for System { return; } - let system_table = match crate::os::uefi::env::try_system_table() { - None => handle_alloc_error(layout), - Some(x) => x.as_ptr() as *mut _, - }; + // If boot services is valid then SystemTable is not null. + let system_table = crate::os::uefi::env::system_table().as_ptr().cast(); // The caller must ensure non-0 layout unsafe { r_efi_alloc::raw::dealloc(system_table, ptr, layout) } } diff --git a/library/std/src/sys/uefi/helpers.rs b/library/std/src/sys/uefi/helpers.rs index 28a823942268..2108484a40c3 100644 --- a/library/std/src/sys/uefi/helpers.rs +++ b/library/std/src/sys/uefi/helpers.rs @@ -46,7 +46,7 @@ pub(crate) fn locate_handles(mut guid: Guid) -> io::Result( handle: NonNull, mut protocol_guid: Guid, ) -> io::Result> { - let boot_services = boot_services().ok_or(BOOT_SERVICES_UNAVAILABLE)?; + let boot_services: NonNull = + boot_services().ok_or(BOOT_SERVICES_UNAVAILABLE)?.cast(); let system_handle = uefi::env::image_handle(); let mut protocol: MaybeUninit<*mut T> = MaybeUninit::uninit(); @@ -279,7 +280,8 @@ pub(crate) fn create_event( handler: Option, context: *mut crate::ffi::c_void, ) -> io::Result> { - let boot_services = boot_services().ok_or(BOOT_SERVICES_UNAVAILABLE)?; + let boot_services: NonNull = + boot_services().ok_or(BOOT_SERVICES_UNAVAILABLE)?.cast(); let mut exit_boot_service_event: r_efi::efi::Event = crate::ptr::null_mut(); let r = unsafe { let create_event = (*boot_services.as_ptr()).create_event; @@ -294,7 +296,8 @@ pub(crate) fn create_event( } pub(crate) fn close_event(evt: NonNull) -> io::Result<()> { - let boot_services = boot_services().ok_or(BOOT_SERVICES_UNAVAILABLE)?; + let boot_services: NonNull = + boot_services().ok_or(BOOT_SERVICES_UNAVAILABLE)?.cast(); let r = unsafe { let close_event = (*boot_services.as_ptr()).close_event; (close_event)(evt.as_ptr()) diff --git a/library/std/src/sys/uefi/mod.rs b/library/std/src/sys/uefi/mod.rs index fa33b681a19d..6fd2c5f21cb4 100644 --- a/library/std/src/sys/uefi/mod.rs +++ b/library/std/src/sys/uefi/mod.rs @@ -129,6 +129,7 @@ pub fn abort_internal() -> ! { if let (Some(boot_services), Some(handle)) = (uefi::env::boot_services(), uefi::env::try_image_handle()) { + let boot_services: NonNull = boot_services.cast(); let _ = unsafe { ((*boot_services.as_ptr()).exit)( handle.as_ptr(), diff --git a/src/doc/rustc/src/platform-support/unknown-uefi.md b/src/doc/rustc/src/platform-support/unknown-uefi.md index 1a4cbc9f092f..e2c09d67beda 100644 --- a/src/doc/rustc/src/platform-support/unknown-uefi.md +++ b/src/doc/rustc/src/platform-support/unknown-uefi.md @@ -251,12 +251,6 @@ Then just build the project using the following command: cargo build --target x86_64-unknown-uefi -Zbuild-std=std,panic_abort ``` -### Std Requirements -The current std has a few basic requirements to function: -1. Memory Allocation Services (`EFI_BOOT_SERVICES.AllocatePool()` and `EFI_BOOT_SERVICES.FreePool()`) are available. This should be true in in the Driver Execution Environment or later. -If the above requirement is satisfied, the Rust code will reach `main`. -Now we will discuss what the different modules of std use in UEFI. - ### Implemented features #### alloc - Implemented using `EFI_BOOT_SERVICES.AllocatePool()` and `EFI_BOOT_SERVICES.FreePool()`. @@ -302,3 +296,8 @@ pub fn main() { assert!(!r.is_error()) } ``` + +### BootServices +The current implementation of std make `BootServices` unavailable once `ExitBootServices` is called. Refer to [Runtime Drivers](https://edk2-docs.gitbook.io/edk-ii-uefi-driver-writer-s-guide/7_driver_entry_point/711_runtime_drivers) for more information regarding how to handle switching from using physical addresses to using virtual addresses. + +Note: It should be noted that it is upto the user to drop all allocated memory before `ExitBootServices` is called.