|
| 1 | +# Combining Rust `std` with `uefi` |
| 2 | + |
| 3 | +## TL;DR |
| 4 | + |
| 5 | +In Mid-2024, we recommend to stick to our normal guide. Use this document as |
| 6 | +guide and outlook for the future of UEFI and Rust. |
| 7 | + |
| 8 | +## About |
| 9 | + |
| 10 | +In the `uefi` crate, we provide tooling to create a `no_std` + `no_main` |
| 11 | +binary, i.e., an UEFI image, in a convenient way. However, there is also the |
| 12 | +option to create a "standard" binary with Rust. The result is the same, but the |
| 13 | +build process and the overall programming is much more similar to regular |
| 14 | +Rust binaries written for Operating Systems, such as Linux, Windows, or macOS. |
| 15 | + |
| 16 | +## Standard binary vs `no_std` binary |
| 17 | + |
| 18 | +A Rust standard binary is a binary that uses the Rust standard library. This |
| 19 | +means that the Rust standard library (_`std` implementation_) is implemented for |
| 20 | +the given platform. A `no_std` (strictly speaking, `no_std` + `no_main`) on the |
| 21 | +other hand can only use the `core` library, but not `std`. Thus, you need to |
| 22 | +write more functionality on your own or use libraries, such as the `uefi` crate. |
| 23 | + |
| 24 | +## About `std` for `uefi` |
| 25 | + |
| 26 | +Using `std` is always the recommended and standard way. However, the `std` |
| 27 | +implementation is not feature-complete and work in progress |
| 28 | +(Mid-2024, Rust stable 1.80), and will also be it in the coming months and |
| 29 | +probably years. Over time, you will need less and less specific features of |
| 30 | +`uefi` and can utilize standard and well-known OS-independent APIs in `std` |
| 31 | +instead. Just as you would to in the typical Linux application, for example. |
| 32 | + |
| 33 | +The `uefi` crate is suited to extend the functionality of these "standard |
| 34 | +binaries". |
| 35 | + |
| 36 | +## Code Example |
| 37 | + |
| 38 | +Please refer to [`<repo>/uefi-std-example`](/uefi-std-example/README.md) to |
| 39 | +see a specific example. The relevant `main.rs` looks as follows: |
| 40 | + |
| 41 | +```rust |
| 42 | +// Note: In Rust 1.82.0-nightly and before, the `uefi_std` feature is |
| 43 | +// required for accessing `std::os::uefi::env::*`. The other default |
| 44 | +// functionality doesn't need a nightly toolchain (with Rust 1.80 and later), |
| 45 | +// but with that limited functionality you - currently - also can't integrate |
| 46 | +// the `uefi` crate. |
| 47 | +#![feature(uefi_std)] |
| 48 | + |
| 49 | +use std::os::uefi as uefi_std; |
| 50 | +use uefi::runtime::ResetType; |
| 51 | +use uefi::{Handle, Status}; |
| 52 | + |
| 53 | +/// Performs the necessary setup code for the `uefi` crate. |
| 54 | +fn setup_uefi_crate() { |
| 55 | + let st = uefi_std::env::system_table(); |
| 56 | + let ih = uefi_std::env::image_handle(); |
| 57 | + |
| 58 | + // Mandatory setup code for `uefi` crate. |
| 59 | + unsafe { |
| 60 | + uefi::table::set_system_table(st.as_ptr().cast()); |
| 61 | + |
| 62 | + let ih = Handle::from_ptr(ih.as_ptr().cast()).unwrap(); |
| 63 | + uefi::boot::set_image_handle(ih); |
| 64 | + } |
| 65 | +} |
| 66 | + |
| 67 | +fn main() { |
| 68 | + println!("Hello World from uefi_std"); |
| 69 | + setup_uefi_crate(); |
| 70 | + println!("UEFI-Version is {}", uefi::system::uefi_revision()); |
| 71 | + uefi::runtime::reset(ResetType::SHUTDOWN, Status::SUCCESS, None); |
| 72 | +} |
| 73 | +``` |
0 commit comments