about summary refs log tree commit diff
path: root/src
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
parent44bd31c2163c944dbf061f52418900b11e1b707c (diff)
parent984ecefed8a12fc31200f5307f07acd7ce6b18c9 (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.rs6
-rw-r--r--src/doc/rustc/src/platform-support/unknown-uefi.md77
-rw-r--r--src/tools/tidy/src/deps.rs3
-rw-r--r--src/tools/tidy/src/pal.rs1
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) {