about summary refs log tree commit diff
path: root/src/doc/rustc
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2023-09-24 09:47:30 +0000
committerbors <bors@rust-lang.org>2023-09-24 09:47:30 +0000
commitc7224e3c954ce54853364c950608c1f0ed47ea85 (patch)
tree266ea338b4a331fd370b880bf27102679d60451f /src/doc/rustc
parent44bd31c2163c944dbf061f52418900b11e1b707c (diff)
parent984ecefed8a12fc31200f5307f07acd7ce6b18c9 (diff)
downloadrust-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.md77
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.