diff options
| author | bors <bors@rust-lang.org> | 2023-09-24 09:47:30 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2023-09-24 09:47:30 +0000 |
| commit | c7224e3c954ce54853364c950608c1f0ed47ea85 (patch) | |
| tree | 266ea338b4a331fd370b880bf27102679d60451f /src | |
| parent | 44bd31c2163c944dbf061f52418900b11e1b707c (diff) | |
| parent | 984ecefed8a12fc31200f5307f07acd7ce6b18c9 (diff) | |
Auto merge of #105861 - Ayush1325:uefi-std-minimial, r=workingjubilee
Add Minimal Std implementation for UEFI # Implemented modules: 1. alloc 2. os_str 3. env 4. math # Related Links Tracking Issue: https://github.com/rust-lang/rust/issues/100499 API Change Proposal: https://github.com/rust-lang/libs-team/issues/87 # Additional Information This was originally part of https://github.com/rust-lang/rust/pull/100316. Since that PR was becoming too unwieldy and cluttered, and with suggestion from `@dvdhrm,` I have extracted a minimal std implementation to this PR. The example in `src/doc/rustc/src/platform-support/unknown-uefi.md` has been tested for `x86_64-unknown-uefi` and `i686-unknown-uefi` in OVMF. It would be great if someone more familiar with AARCH64 can help with testing for that target. Signed-off-by: Ayush Singh <ayushsingh1325@gmail.com>
Diffstat (limited to 'src')
| -rw-r--r-- | src/bootstrap/config.rs | 6 | ||||
| -rw-r--r-- | src/doc/rustc/src/platform-support/unknown-uefi.md | 77 | ||||
| -rw-r--r-- | src/tools/tidy/src/deps.rs | 3 | ||||
| -rw-r--r-- | src/tools/tidy/src/pal.rs | 1 |
4 files changed, 80 insertions, 7 deletions
diff --git a/src/bootstrap/config.rs b/src/bootstrap/config.rs index 176ef8e92db..836328f94ef 100644 --- a/src/bootstrap/config.rs +++ b/src/bootstrap/config.rs @@ -532,11 +532,7 @@ pub struct Target { impl Target { pub fn from_triple(triple: &str) -> Self { let mut target: Self = Default::default(); - if triple.contains("-none") - || triple.contains("nvptx") - || triple.contains("switch") - || triple.contains("-uefi") - { + if triple.contains("-none") || triple.contains("nvptx") || triple.contains("switch") { target.no_std = true; } target diff --git a/src/doc/rustc/src/platform-support/unknown-uefi.md b/src/doc/rustc/src/platform-support/unknown-uefi.md index 03fa284620e..68cd7fae319 100644 --- a/src/doc/rustc/src/platform-support/unknown-uefi.md +++ b/src/doc/rustc/src/platform-support/unknown-uefi.md @@ -19,8 +19,8 @@ Available targets: ## Requirements All UEFI targets can be used as `no-std` environments via cross-compilation. -Support for `std` is missing, but actively worked on. `alloc` is supported if -an allocator is provided by the user. No host tools are supported. +Support for `std` is present, but incomplete and extremely new. `alloc` is supported if +an allocator is provided by the user or if using std. No host tools are supported. The UEFI environment resembles the environment for Microsoft Windows, with some minor differences. Therefore, cross-compiling for UEFI works with the same @@ -230,3 +230,76 @@ pub extern "C" fn main(_h: efi::Handle, st: *mut efi::SystemTable) -> efi::Statu efi::Status::SUCCESS } ``` + +## Rust std for UEFI +This section contains information on how to use std on UEFI. + +### Build std +The building std part is pretty much the same as the official [docs](https://rustc-dev-guide.rust-lang.org/getting-started.html). +The linker that should be used is `rust-lld`. Here is a sample `config.toml`: +```toml +[rust] +lld = true +``` +Then just build using `x.py`: +```sh +./x.py build --target x86_64-unknown-uefi --stage 1 +``` +Alternatively, it is possible to use the `build-std` feature. However, you must use a toolchain which has the UEFI std patches. +Then just build the project using the following command: +```sh +cargo build --target x86_64-unknown-uefi -Zbuild-std=std,panic_abort +``` + +### Implemented features +#### alloc +- Implemented using `EFI_BOOT_SERVICES.AllocatePool()` and `EFI_BOOT_SERVICES.FreePool()`. +- Passes all the tests. +- Currently uses `EfiLoaderData` as the `EFI_ALLOCATE_POOL->PoolType`. +#### cmath +- Provided by compiler-builtins. +#### env +- Just some global constants. +#### locks +- The provided locks should work on all standard single-threaded UEFI implementations. +#### os_str +- While the strings in UEFI should be valid UCS-2, in practice, many implementations just do not care and use UTF-16 strings. +- Thus, the current implementation supports full UTF-16 strings. + +## Example: Hello World With std +The following code features a valid UEFI application, including stdio and `alloc` (`OsString` and `Vec`): + +This example can be compiled as binary crate via `cargo` using the toolchain +compiled from the above source (named custom): + +```sh +cargo +custom build --target x86_64-unknown-uefi +``` + +```rust,ignore (platform-specific) +#![feature(uefi_std)] + +use r_efi::{efi, protocols::simple_text_output}; +use std::{ + ffi::OsString, + os::uefi::{env, ffi::OsStrExt} +}; + +pub fn main() { + let st = env::system_table().as_ptr() as *mut efi::SystemTable; + let mut s: Vec<u16> = OsString::from("Hello World!\n").encode_wide().collect(); + s.push(0); + let r = + unsafe { + let con_out: *mut simple_text_output::Protocol = (*st).con_out; + let output_string: extern "efiapi" fn(_: *mut simple_text_output::Protocol, *mut u16) -> efi::Status = (*con_out).output_string; + output_string(con_out, s.as_ptr() as *mut efi::Char16) + }; + assert!(!r.is_error()) +} +``` + +### BootServices +The current implementation of std makes `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 up to the user to drop all allocated memory before `ExitBootServices` is called. diff --git a/src/tools/tidy/src/deps.rs b/src/tools/tidy/src/deps.rs index 843ffe2c4c3..daa9cb8d22e 100644 --- a/src/tools/tidy/src/deps.rs +++ b/src/tools/tidy/src/deps.rs @@ -18,6 +18,7 @@ const LICENSES: &[&str] = &[ "Apache-2.0/MIT", "ISC", "MIT / Apache-2.0", + "MIT OR Apache-2.0 OR LGPL-2.1-or-later", // r-efi, r-efi-alloc "MIT OR Apache-2.0 OR Zlib", // tinyvec_macros "MIT OR Apache-2.0", "MIT OR Zlib OR Apache-2.0", // miniz_oxide @@ -217,6 +218,8 @@ const PERMITTED_RUSTC_DEPENDENCIES: &[&str] = &[ "pulldown-cmark", "punycode", "quote", + "r-efi", + "r-efi-alloc", "rand", "rand_chacha", "rand_core", diff --git a/src/tools/tidy/src/pal.rs b/src/tools/tidy/src/pal.rs index 3a4d9c53d7b..5f6b63a67fd 100644 --- a/src/tools/tidy/src/pal.rs +++ b/src/tools/tidy/src/pal.rs @@ -56,6 +56,7 @@ const EXCEPTION_PATHS: &[&str] = &[ "library/std/src/path.rs", "library/std/src/sys_common", // Should only contain abstractions over platforms "library/std/src/net/test.rs", // Utility helpers for tests + "library/std/src/io/error.rs", // Repr unpacked needed for UEFI ]; pub fn check(path: &Path, bad: &mut bool) { |
