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/doc/rustc | |
| parent | 44bd31c2163c944dbf061f52418900b11e1b707c (diff) | |
| parent | 984ecefed8a12fc31200f5307f07acd7ce6b18c9 (diff) | |
| download | rust-c7224e3c954ce54853364c950608c1f0ed47ea85.tar.gz rust-c7224e3c954ce54853364c950608c1f0ed47ea85.zip | |
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/doc/rustc')
| -rw-r--r-- | src/doc/rustc/src/platform-support/unknown-uefi.md | 77 |
1 files changed, 75 insertions, 2 deletions
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. |
