| Crates.io | efi |
| lib.rs | efi |
| version | 0.3.1 |
| created_at | 2018-03-14 06:10:16.943367+00 |
| updated_at | 2023-10-18 07:42:30.631042+00 |
| description | Ergonomic Rust bindings for writing UEFI applications |
| homepage | |
| repository | https://github.com/gurry/efi |
| max_upload_size | |
| id | 55492 |
| size | 510,495 |
A framework for writing UEFI applications in Rust. Acts like the Rust standard library on the UEFI platform with support for things like:
Vec and String via a custom allocatorprintln!, write!, format! etc.Read and Write traits and the related typesIpAddr and its supporting typesAlso offers an ergonomic API for UEFI-specific functionality such as:
It uses the efi_ffi crate to interface with the UEFI platform.
x64 architecture is supported.nightly-2023-01-12. May not compile with others. You must force this version using a rust-toolchain file (as shown in the following section)To write a UEFI application using this framework follow the below steps:
cargo new my_efi_app, where my_efi_app is the name of the applicationefi = "0.3" under [dependencies] in Cargo.tomlrust-toolchain containing the text nightly-2023-01-12 at the root of the crate. This will ensure that the crate is always built with nightly-2023-01-12.my_efi_app/src/main.rs. Comments in the code explain each part:#![no_std] // Indicates to the Rust compiler that the app does not depend on the standard library but is a 'standalone' application.
#![no_main] // Indicates that this application does not have a "main" function typically found in a Linux or Windows application (although it does have its own "main" function "efi_main" as declared below)
// Externs for efi and alloc crates (alloc crate is the one that contains definitions of String and Vec etc.)
#[macro_use] extern crate efi;
extern crate alloc;
// EFI entrypoint or main function. UEFI firmware will call this function to start the application.
// The signature and the name of this function must be exactly as below.
#[no_mangle]
pub extern "win64" fn efi_main(image_handle: efi::ffi::EFI_HANDLE, sys_table : *const efi::ffi::EFI_SYSTEM_TABLE) -> isize {
efi::init_env(image_handle, sys_table); // Call to init_env must be the first thing in efi_main. Without it things like println!() won't work
println!("Welcome to UEFI");
// Your business logic here
0
}
// A handler to respond to panics in the code. Required by the Rust compiler
#[panic_handler]
fn panic(_: &core::panic::PanicInfo) -> ! {
loop {}
}
Building the application requires the target x86_64-unknown-uefi to be installed on your machine. To install it:
my_efi_app folder in this case)rustup target add x86_64-unknown-uefiThis must be done in the root of the crate because then the target will be installed for the Rust toolchain we specified above with the root-toolchain file.
After the target is installed, build the application with the command cargo build --target x86_64-unknown-uefi. When the build completes the resulting EFI application my_efi_app.efi will be found in target\x86_64-unknown-uefi\debug\
Run the UEFI appliction in a qemu virtual machine by following the below steps:
ovmf.fd and download that binary (This is the OVMF firmware under which we will run the application)<path where qemu is installed>/qemu-system-x86_64 -pflash <path where you downloaded ovmf.fd>/ovmf.fd -hda fat:rw:<path to your uefi application crate>/target/x86_64-unknown-uefi/debugovmf.fd firmware and start the EFI shellmy_efi_app.efi and press ENTERFor a sample application see examples/sample_efi_app.rs. Build it by running cargo build --target x86_64-unknown-uefi --example sample_efi_app. The resulting binary sample_efi_app.efi will be found in target/x86_64-unknown-uefi/debug/examples.
The application performs DHCP at the start to obtain an IP address and then makes an HTTP request to a specified server. So to run it you need to follow the below steps:
<path where qemu is installed>/qemu-system-x86_64 -pflash <path where you downloaded ovmf.fd>/ovmf.fd -hda fat:rw:<path to your uefi application crate>/target/x86_64-unknown-uefi/debug/examples -net tap,ifname=<name of your TAP adapter> -net nic. With the two -net options at the end this commandline tells qemu to use the TAP adapter you installed above. Ensure that the name you specify after ifname= is that of the TAP adapter which you noted above.The application will start, perform DHCP, get an IP address, prompt you for the name of an HTTP server and then make a GET request to that server.