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 a sister crate efi_ffi to interface with the UEFI platform.
x64 architecture is supported. In terms of Rust this implies that the crate builds only with the target x86_64-unknown-uefi.To build the crate:
x86_64-unknown-uefi is installed. If not, install it by running the command rustup target add x86_64-unknown-ueficargo build --target x86_64-unknown-uefiTo 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.tomlmy_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 standard "main" function typically found in a Linux or Windows application (although it does have its own main function "efi_main")
// 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 it 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. Install it by running rustup target add x86_64-unknown-uefi in command shell.
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.
Rust
100.0%
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 a sister crate efi_ffi to interface with the UEFI platform.
x64 architecture is supported. In terms of Rust this implies that the crate builds only with the target x86_64-unknown-uefi.To build the crate:
x86_64-unknown-uefi is installed. If not, install it by running the command rustup target add x86_64-unknown-ueficargo build --target x86_64-unknown-uefiTo 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.tomlmy_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 standard "main" function typically found in a Linux or Windows application (although it does have its own main function "efi_main")
// 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 it 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. Install it by running rustup target add x86_64-unknown-uefi in command shell.
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.
Rust
100.0%