### Run UEFI-RS Example Source: https://github.com/rust-osdev/uefi-rs/blob/main/uefi-test-runner/examples/README.md Use this command to manually run an example. Replace 'name_of_example' with the actual example name. ```bash cargo xtask run --example name_of_example ``` -------------------------------- ### Install QEMU and OVMF on Debian/Ubuntu Source: https://github.com/rust-osdev/uefi-rs/blob/main/book/src/tutorial/vm.md Installs QEMU and OVMF packages using apt-get. Ensure you have sudo privileges. ```sh sudo apt-get install qemu ovmf ``` -------------------------------- ### Open LoadedImage and DevicePathToText Protocols in Rust Source: https://github.com/rust-osdev/uefi-rs/blob/main/book/src/how_to/protocols.md This example demonstrates opening the LoadedImage protocol to get information about the current executable and the DevicePathToText protocol to retrieve its file system path. Ensure necessary imports are present. ```rust use uefi::prelude::*; use uefi::proto::device_path::text::{DevicePath, TextDisplay}; use uefi::proto::loaded_image::LoadedImage; #[entry] fn main(image_handle: Handle) { let mut boot_services = uefi_services::init().expect_success("Failed to initialize UEFI services"); // Open the LoadedImage protocol let loaded_image = boot_services .open_protocol_exclusive(image_handle) .expect_success("Failed to open LoadedImage protocol"); // Open the DevicePathToText protocol let device_path_to_text = boot_services .open_protocol_exclusive(loaded_image.device_handle()) .expect_success("Failed to open DevicePathToText protocol"); // Convert the device path to text let text_display = TextDisplay::new(device_path_to_text); let path = text_display.display(loaded_image.file_path()).expect_success("Failed to display device path"); println!("[ INFO]: example.rs@058: Image path: {}", path.to_str().expect("Failed to convert path to string")); } ``` -------------------------------- ### Install QEMU and OVMF on Fedora Source: https://github.com/rust-osdev/uefi-rs/blob/main/book/src/tutorial/vm.md Installs QEMU and OVMF packages using dnf. Requires sudo privileges. ```sh sudo dnf install qemu-kvm edk2-ovmf ``` -------------------------------- ### Load and Start UEFI Images Source: https://context7.com/rust-osdev/uefi-rs/llms.txt Loads a UEFI image from a file system buffer and then starts its execution. The loaded image can be optionally unloaded afterward. ```rust use uefi::prelude::*; use uefi::boot::{self, LoadImageSource}; use uefi::proto::BootPolicy; fn load_and_start_image() -> uefi::Result<()> { let sfs = boot::get_image_file_system(boot::image_handle())?; let mut fs = uefi::fs::FileSystem::new(sfs); // Read the image from disk let image_data = fs.read(cstr16!("\\EFI\\BOOT\\mydriver.efi"))?; // Load the image from buffer let image_handle = boot::load_image( boot::image_handle(), LoadImageSource::FromBuffer { buffer: &image_data, file_path: None, }, )?; // Start the loaded image boot::start_image(image_handle)?; // Unload if needed boot::unload_image(image_handle)?; Ok(()) } ``` -------------------------------- ### UEFI Application Log Output Source: https://github.com/rust-osdev/uefi-rs/blob/main/book/src/tutorial/vm.md Example log message expected from a running UEFI application after booting in QEMU. This indicates successful execution. ```text [ INFO]: src/main.rs@011: Hello world! ``` -------------------------------- ### Manage Time and Variables with UEFI Runtime Services Source: https://context7.com/rust-osdev/uefi-rs/llms.txt Demonstrates how to get the current system time, read and check for the existence of UEFI variables, list all variables, and set a new variable. Requires the 'alloc' feature for listing variables. ```rust use uefi::prelude::*; use uefi::runtime::{self, VariableAttributes, VariableVendor, VariableKey}; use uefi::CStr16; fn time_and_variables() -> uefi::Result<()> { // Get current time let time = runtime::get_time()?; uefi::println!( "Current time: {}-{:02}-{:02} {:02}:{:02}:{:02}", time.year(), time.month(), time.day(), time.hour(), time.minute(), time.second() ); // Read a UEFI variable let mut buf = [0u8; 256]; match runtime::get_variable( cstr16!("BootOrder"), &VariableVendor::GLOBAL_VARIABLE, &mut buf, ) { Ok((data, attrs)) => { uefi::println!("BootOrder variable: {} bytes, attrs: {:?}", data.len(), attrs); } Err(e) => uefi::println!("Could not read BootOrder: {:?}", e.status()), } // Check if variable exists if runtime::variable_exists(cstr16!("SecureBoot"), &VariableVendor::GLOBAL_VARIABLE)? { uefi::println!("SecureBoot variable exists"); } // List all variables (requires alloc feature) for key in runtime::variable_keys() { if let Ok(key) = key { uefi::println!("Variable: {}", key); } } // Set a variable runtime::set_variable( cstr16!("MyAppConfig"), &VariableVendor::GLOBAL_VARIABLE, VariableAttributes::BOOTSERVICE_ACCESS | VariableAttributes::RUNTIME_ACCESS, &[0x01, 0x02, 0x03], )?; Ok(()) } ``` -------------------------------- ### UEFI Rust Entry Point with std Source: https://github.com/rust-osdev/uefi-rs/blob/main/book/src/how_to/rust-std.md Example of a UEFI executable using Rust's standard library. Requires a nightly toolchain and the `uefi_std` feature. The `#[entry]` macro from the `uefi` crate defines the entry point. ```rust #![feature(abi_x86_interrupt)] #![no_std] #![no_main] use uefi::prelude::*; #[entry] fn main(image: Handle) -> ! { let mut boot_services = uefi_services::init(image).expect_success(()); let _stdout = boot_services.stdout(); // ... your code here ... // Halt the system panic!(); } ``` -------------------------------- ### Define Protocol GUID Constant Source: https://github.com/rust-osdev/uefi-rs/blob/main/uefi-raw/api_guidelines.md Protocols must have an associated `GUID` constant. This example shows how to define it for `RngProtocol`. ```rust impl RngProtocol { pub const GUID: Guid = guid!("3152bca5-eade-433d-862e-c01cdc291f44"); } ``` -------------------------------- ### Define Custom UEFI Protocol Source: https://context7.com/rust-osdev/uefi-rs/llms.txt Shows how to define a custom UEFI protocol using the `unsafe_protocol` macro, including its structure and a method for retrieving data. The protocol requires a unique GUID. ```rust use uefi::{Identify, guid}; use uefi::proto::unsafe_protocol; #[unsafe_protocol("12345678-9abc-def0-1234-56789abcdef0")] #[repr(C)] struct MyCustomProtocol { revision: u64, get_data: unsafe extern "efiapi" fn(*const Self, *mut u8, *mut usize) -> uefi::Status, } impl MyCustomProtocol { fn get_data(&self, buffer: &mut [u8]) -> uefi::Result { let mut size = buffer.len(); unsafe { (self.get_data)(self, buffer.as_mut_ptr(), &mut size) }.to_result_with_val(|| size) } } // The protocol can now be opened like any other: // boot::open_protocol_exclusive::(handle)? ``` -------------------------------- ### Define a new UEFI protocol Source: https://github.com/rust-osdev/uefi-rs/blob/main/CONTRIBUTING.md Example of defining a new UEFI protocol in Rust. Ensure `#[repr(C)]` is used for correct memory layout and `#[unsafe_protocol]` for the GUID. The protocol struct contains function pointers for its methods. ```rust /// Protocol which does something. #[repr(C)] #[unsafe_protocol("abcdefgh-1234-5678-9012-123456789abc")] pub struct NewProtocol { some_entry_point: extern "efiapi" fn( this: *const NewProtocol, some_parameter: SomeType, some_other_parameter: SomeOtherType, ) -> Status, some_other_entry_point: extern "efiapi" fn( this: *mut NewProtocol, another_parameter: AnotherType, ) -> SomeOtherResult, // ... } ``` -------------------------------- ### Handle UCS-2 Strings in UEFI Rust Source: https://context7.com/rust-osdev/uefi-rs/llms.txt Demonstrates creating and converting UCS-2 strings using `CStr16` for borrowed strings and `CString16` for owned strings. Includes examples of compile-time literals, runtime conversion, and printing to the console. ```rust use uefi::prelude::*; use uefi::{CStr16, CString16}; fn string_handling() { // Compile-time string literal let path: &CStr16 = cstr16!("\\EFI\\BOOT\\bootx64.efi"); // Runtime string conversion let filename = "config.txt"; let cstring: CString16 = CString16::try_from(filename) .expect("Invalid character in string"); // Use as CStr16 reference let cstr: &CStr16 = cstring.as_ref(); // Print to console uefi::println!("Path: {}", path); // Convert to Rust string (requires string contains valid characters) let rust_string = path.to_string(); } ``` -------------------------------- ### UEFI Graphics Output Protocol (GOP) Operations Source: https://context7.com/rust-osdev/uefi-rs/llms.txt Interacts with the Graphics Output Protocol to get display mode information, fill the screen with color, and draw rectangles. Requires `uefi::proto::console::gop::GraphicsOutput` and `uefi::boot::get_handle_for_protocol`. ```rust use uefi::prelude::*; use uefi::boot; use uefi::proto::console::gop::{GraphicsOutput, BltOp, BltPixel, BltRegion}; fn draw_graphics() -> uefi::Result<()> { let handle = boot::get_handle_for_protocol::()?; let mut gop = boot::open_protocol_exclusive::(handle)?; // Get current mode info let mode_info = gop.current_mode_info(); let (width, height) = mode_info.resolution(); uefi::println!("Resolution: {}x{}", width, height); // List available modes for mode in gop.modes() { let info = mode.info(); uefi::println!("Mode {}: {}x{}", mode.index(), info.resolution().0, info.resolution().1); } // Fill screen with blue color let blue = BltPixel::new(0, 0, 255); gop.blt(BltOp::VideoFill { color: blue, dest: (0, 0), dims: (width, height), })?; // Draw a red rectangle let red = BltPixel::new(255, 0, 0); gop.blt(BltOp::VideoFill { color: red, dest: (100, 100), dims: (200, 150), })?; Ok(()) } ``` -------------------------------- ### Get and Print UEFI Memory Map Source: https://context7.com/rust-osdev/uefi-rs/llms.txt Retrieves the UEFI memory map and prints details about each memory region. Requires `uefi::boot::memory_map` and `uefi::boot::MemoryType`. ```rust use uefi::prelude::*; use uefi::boot::{self, MemoryType}; use uefi::mem::memory_map::MemoryMap; fn print_memory_map() -> uefi::Result<()> { let memory_map = boot::memory_map(MemoryType::LOADER_DATA)?; uefi::println!("Memory map entries:"); for desc in memory_map.entries() { uefi::println!( " {:?}: {:#x} - {:#x} ({} pages)", desc.ty, desc.phys_start, desc.phys_start + desc.page_count * 4096, desc.page_count ); } Ok(()) } ``` -------------------------------- ### Full Sierpiński Triangle Example Source: https://github.com/rust-osdev/uefi-rs/blob/main/book/src/how_to/drawing.md This is the complete Rust code for drawing a Sierpiński triangle on the screen using the chaos game method within a UEFI environment. It requires the graphics output protocol. ```rust use alloc::vec; use uefi::proto::console::gop::{BltPixel, GraphicsOutput}; use uefi::proto::media::fs::SimpleFileSystem; use uefi::table::{boot_services::BootServices, runtime_services::RuntimeServices}; use uefi::Csm; const WIDTH: usize = 800; const HEIGHT: usize = 600; #[repr(C)] struct BltPixel { blue: u8, green: u8, red: u8, reserved: u8, } impl BltPixel { fn new(red: u8, green: u8, blue: u8, reserved: u8) -> Self { BltPixel { blue, green, red, reserved } } } struct Buffer { pixels: Vec, width: usize, height: usize, } impl Buffer { fn new(width: usize, height: usize) -> Self { Buffer { pixels: vec![BltPixel::new(0, 0, 0, 0); width * height], width, height, } } fn pixel(&mut self, x: usize, y: usize) -> &mut BltPixel { &mut self.pixels[y * self.width + x] } fn blit(&self, gop: &GraphicsOutput) { gop.blit( uefi::proto::console::gop::BltOp::BufferToVideo { src: self.pixels.iter().map(|p| *p).collect(), dest: 0, count: self.pixels.len(), }, None, None, ) .expect("Failed to blit buffer to screen"); } } #[repr(C)] struct Point { x: usize, y: usize, } impl Point { fn new(x: usize, y: usize) -> Self { Point { x, y } } } fn main(st: BootServices, mut rt: RuntimeServices, csm: Csm) { let mut gop = GraphicsOutput::new(st.locate_protocol().unwrap()).unwrap(); let mut buffer = Buffer::new(WIDTH, HEIGHT); let mut p1 = Point::new(WIDTH / 2, 0); let mut p2 = Point::new(0, HEIGHT); let mut p3 = Point::new(WIDTH, HEIGHT); let mut current = Point::new(WIDTH / 2, HEIGHT / 2); for _ in 0..100000 { let choice = (rand::random::() % 3) as usize; match choice { 0 => { current.x = (current.x + p1.x) / 2; current.y = (current.y + p1.y) / 2; } 1 => { current.x = (current.x + p2.x) / 2; current.y = (current.y + p2.y) / 2; } 2 => { current.x = (current.x + p3.x) / 2; current.y = (current.y + p3.y) / 2; } _ => unreachable!(), } if current.x < WIDTH && current.y < HEIGHT { buffer.pixel(current.x, current.y).red = 255; buffer.pixel(current.x, current.y).green = 255; buffer.pixel(current.x, current.y).blue = 255; } } buffer.blit(&gop); } fn get_fs<'a>(st: &'a BootServices) -> &'a SimpleFileSystem { st.locate_protocol().unwrap() } ``` -------------------------------- ### Serve UEFI Book Locally Source: https://github.com/rust-osdev/uefi-rs/blob/main/book/README.md Use this command to launch a local development server for the UEFI Book. The server automatically updates as you make changes to the markdown sources. Open http://localhost:3000 in your web browser to view the book. ```console mdbook serve book/ ``` -------------------------------- ### Set up UEFI System Partition (ESP) Source: https://github.com/rust-osdev/uefi-rs/blob/main/book/src/tutorial/vm.md Creates the necessary directory structure for the UEFI System Partition and copies the compiled UEFI application into it. The application must be named 'bootx64.efi' for automatic booting. ```sh mkdir -p esp/efi/boot cp target/x86_64-unknown-uefi/debug/my-uefi-app.efi esp/efi/boot/bootx64.efi ``` -------------------------------- ### UEFI File System Operations Source: https://context7.com/rust-osdev/uefi-rs/llms.txt Demonstrates reading, writing, creating directories, checking existence, and listing directory contents using `uefi::fs::FileSystem`. Requires `uefi::boot::get_image_file_system` and `uefi::CString16`. ```rust use uefi::prelude::*; use uefi::boot; use uefi::fs::{FileSystem, Path, PathBuf}; use uefi::CString16; use alloc::vec::Vec; fn file_operations() -> uefi::Result<()> { // Get the file system from the boot device let sfs = boot::get_image_file_system(boot::image_handle())?; let mut fs = FileSystem::new(sfs); // Read a file let content: Vec = fs.read(cstr16!("\\EFI\\BOOT\\config.txt")) .expect("Failed to read file"); // Read file as string let text = fs.read_to_string(cstr16!("\\EFI\\BOOT\\config.txt")) .expect("Failed to read file as string"); uefi::println!("Config content: {}", text); // Write a file fs.write(cstr16!("\\EFI\\BOOT\\output.txt"), b"Hello, UEFI!") .expect("Failed to write file"); // Create directories fs.create_dir_all(cstr16!("\\EFI\\MyApp\\data")) .expect("Failed to create directories"); // Check if file exists if fs.try_exists(cstr16!("\\EFI\\BOOT\\bootx64.efi"))? { uefi::println!("Boot file exists"); } // List directory contents for entry in fs.read_dir(cstr16!("\\EFI\\BOOT"))? { if let Ok(info) = entry { uefi::println!(" {}", info.file_name()); } } Ok(()) } ``` -------------------------------- ### Initialize UEFI Services and Logging Source: https://github.com/rust-osdev/uefi-rs/blob/main/book/src/tutorial/app.md Initializes the UEFI services and logging system for the application. Requires the `image` handle. ```rust let mut boot_services = uefi_services::init(image).expect_success(()); ``` -------------------------------- ### Launch QEMU VM with UEFI Firmware Source: https://github.com/rust-osdev/uefi-rs/blob/main/book/src/tutorial/vm.md Launches a QEMU virtual machine with KVM acceleration, using OVMF for UEFI firmware and a FAT filesystem for the system partition. The `esp` directory is mounted as a read-write drive. ```sh qemu-system-x86_64 -enable-kvm \ -drive if=pflash,format=raw,readonly=on,file=OVMF_CODE.fd \ -drive if=pflash,format=raw,readonly=on,file=OVMF_VARS.fd \ -drive format=raw,file=fat:rw:esp ``` -------------------------------- ### Prepare USB Drive for UEFI Boot (Linux) Source: https://github.com/rust-osdev/uefi-rs/blob/main/book/src/tutorial/hardware.md Use these commands on Linux to partition, format, and copy your EFI executable to a USB drive for booting. Ensure you replace placeholders with your actual disk and executable paths. Warning: these operations are destructive. ```sh # Create the GPT, create a 9MB partition starting at 1MB, and set the # partition type to EFI System. sgdisk \ --clear \ --new=1:1M:10M \ --typecode=1:C12A7328-F81F-11D2-BA4B-00A0C93EC93B \ /path/to/disk # Format the partition as FAT. mkfs.fat /path/to/disk_partition # Mount the partition. mkdir esp mount /path/to/disk_partition esp # Create the boot directory. mkdir esp/EFI/BOOT # Copy in the boot executable. cp /path/to/your-executable.efi esp/EFI/BOOT/BOOTX64.EFI ``` -------------------------------- ### Create and Use Timer Events Source: https://context7.com/rust-osdev/uefi-rs/llms.txt Demonstrates creating a timer event, setting it to trigger after a relative time, waiting for it to fire, and then closing the event. Also shows a simple delay using `boot::stall`. ```rust use uefi::prelude::*; use uefi::boot::{self, EventType, TimerTrigger, Tpl}; use core::time::Duration; fn use_events_and_timers() -> uefi::Result<()> { // Create a timer event let timer_event = unsafe { boot::create_event( EventType::TIMER, Tpl::CALLBACK, None, // No callback None, // No context )? }; // Set timer to fire after 2 seconds (in 100ns units) boot::set_timer(&timer_event, TimerTrigger::Relative(20_000_000))?; // Wait for the event let mut events = [timer_event]; let index = boot::wait_for_event(&mut events)?; uefi::println!("Event {} fired", index); // Simple delay using stall boot::stall(Duration::from_secs(1)); // Close the event when done boot::close_event(events[0])?; Ok(()) } ``` -------------------------------- ### Add UEFI and Logging Dependencies Source: https://github.com/rust-osdev/uefi-rs/blob/main/book/src/tutorial/app.md Add the `log` and `uefi` crates with specific features to your project's dependencies. ```sh cargo add log cargo add uefi --features logger,panic_handler ``` -------------------------------- ### Minimal UEFI Application Entry Point Source: https://context7.com/rust-osdev/uefi-rs/llms.txt Defines the entry point for a UEFI application using the `#[entry]` macro. Initializes helpers for logging, panic handling, and the global allocator. ```rust #![no_main] #![no_std] use uefi::prelude::*; #[entry] fn main() -> Status { // Initialize helpers (logger, panic handler, allocator) uefi::helpers::init().unwrap(); // Your UEFI application logic here uefi::println!("Hello from UEFI!"); Status::SUCCESS } ``` -------------------------------- ### Test and Run Project Locally Source: https://github.com/rust-osdev/uefi-rs/blob/main/PUBLISHING.md Verify the project's integrity by running tests and the main application locally before proceeding with a release. This ensures that the current state is stable. ```bash cargo xtask test && cargo xtask run ``` -------------------------------- ### Minimal UEFI Application Code Source: https://github.com/rust-osdev/uefi-rs/blob/main/book/src/tutorial/app.md The complete source code for a basic 'Hello, world!' UEFI application in Rust. ```rust #![no_main] #![no_std] use uefi::prelude::*; #[entry] fn main(image: Handle) -> Status { // Initialize the UEFI application let mut boot_services = uefi_services::init(image).expect_success(()); // Log a message using the log crate log::info!("Hello world!"); // Stall for 10 seconds to allow viewing the output boot_services.stall(10_000_000); // Indicate successful completion Status::SUCCESS } ``` -------------------------------- ### UEFI Application Entry Point Source: https://github.com/rust-osdev/uefi-rs/blob/main/book/src/tutorial/app.md The main function for a UEFI application, marked with `#[entry]`, takes no arguments, and returns a `Status` code. ```rust #[entry] fn main(image: Handle) -> Status { ``` -------------------------------- ### Run tests with cargo xtask Source: https://github.com/rust-osdev/uefi-rs/blob/main/CONTRIBUTING.md Execute the test harness to verify changes. This command opens a QEMU window to run the tests. ```shell cargo xtask run ``` -------------------------------- ### UEFI Memory Allocation (Pages and Pool) Source: https://context7.com/rust-osdev/uefi-rs/llms.txt Demonstrates memory allocation using `allocate_pages` for page-aligned memory and `allocate_pool` for pool-aligned memory. Both methods require explicit freeing of the allocated memory using `free_pages` and `free_pool` respectively. ```rust use uefi::prelude::*; use uefi::boot::{self, AllocateType, MemoryType}; use core::ptr::NonNull; fn allocate_memory() -> uefi::Result<()> { // Allocate 4 pages (16KB) of loader data let pages: NonNull = boot::allocate_pages( AllocateType::AnyPages, MemoryType::LOADER_DATA, 4, // number of pages )?; // Use the allocated memory unsafe { let slice = core::slice::from_raw_parts_mut(pages.as_ptr(), 4 * 4096); slice.fill(0); } // Free pages when done unsafe { boot::free_pages(pages, 4)? }; // Pool allocation (8-byte aligned) let pool: NonNull = boot::allocate_pool( MemoryType::LOADER_DATA, 1024, // size in bytes )?; // Free pool when done unsafe { boot::free_pool(pool)? }; Ok(()) } ``` -------------------------------- ### Create and Navigate to UEFI App Directory Source: https://github.com/rust-osdev/uefi-rs/blob/main/book/src/tutorial/app.md Use cargo to create a new Rust project for a UEFI application and change into its directory. ```sh cargo new my-uefi-app cd my-uefi-app ``` -------------------------------- ### UEFI Application Use Declarations Source: https://github.com/rust-osdev/uefi-rs/blob/main/book/src/tutorial/app.md Imports commonly used macros, modules, and types from the `uefi::prelude` module for UEFI application development. ```rust use uefi::prelude::*; ``` -------------------------------- ### Migrate to Freestanding Functions in UEFI Source: https://github.com/rust-osdev/uefi-rs/blob/main/docs/funcs_migration.md Compares the old struct-based API for finding loaded image handles with the new freestanding function API. The new API simplifies calls by using a global system table pointer, requiring only updated imports and direct function calls. ```rust use uefi::table::boot::{BootServices, HandleBuffer}; fn find_loaded_image_handles(bt: &BootServices) -> Result { bt.locate_handle_buffer(SearchType::from_proto::()) } ``` ```rust use uefi::boot::{self, HandleBuffer}; fn find_loaded_image_handles() -> Result { boot::locate_handle_buffer(SearchType::from_proto::()) } ``` -------------------------------- ### UEFI Application Cargo.toml Configuration Source: https://github.com/rust-osdev/uefi-rs/blob/main/book/src/tutorial/app.md The resulting Cargo.toml file should include the log and uefi dependencies with the specified features. ```toml [dependencies] log = "0.4" # Check crates.io for the latest version. uefi = { version = "", features = [ "panic_handler", "logger" ] } ``` -------------------------------- ### Run Clippy static analysis Source: https://github.com/rust-osdev/uefi-rs/blob/main/CONTRIBUTING.md Ensure code quality by running Clippy's static analysis. Contributions are expected to pass this check. ```shell cargo xtask clippy ``` -------------------------------- ### List Block Devices with BlockIO Protocol Source: https://context7.com/rust-osdev/uefi-rs/llms.txt Enumerates all handles supporting the `BlockIO` protocol using `find_handles`. It then opens each protocol exclusively to retrieve and print media information like size and block size. ```rust use uefi::prelude::*; use uefi::boot; use uefi::proto::media::block::BlockIO; use alloc::vec::Vec; fn list_block_devices() -> uefi::Result<()> { // Find all handles supporting BlockIO protocol let handles: Vec = boot::find_handles::()?; uefi::println!("Found {} block devices", handles.len()); for (i, handle) in handles.iter().enumerate() { let block_io = boot::open_protocol_exclusive::(*handle)?; let media = block_io.media(); uefi::println!( "Device {}: {} bytes, block size {}", i, media.last_block() * media.block_size() as u64, media.block_size() ); } Ok(()) } ``` -------------------------------- ### Open DevicePathToText Protocol in UEFI Rust Source: https://github.com/rust-osdev/uefi-rs/blob/main/book/src/how_to/protocols.md This snippet shows how to open the DevicePathToText protocol. It first locates a suitable handle using `locate_handle_buffer` and then opens the protocol exclusively on that handle. ```rust let device_path_handle = boot_services.locate_handle_buffer::()?.first().ok_or(Status::NotFound)?; let device_path_to_text = boot_services.open_protocol_exclusive(*device_path_handle)?; ``` -------------------------------- ### Configure UEFI Driver Subsystem in build.rs Source: https://github.com/rust-osdev/uefi-rs/blob/main/book/src/how_to/building_drivers.md Set the UEFI subsystem to `efi_runtime_driver` when the target is a UEFI system. This is done within the `build.rs` script. ```rust // In build.rs fn main() { let target = std::env::var("TARGET").unwrap(); if target.ends_with("-unknown-uefi") { println!("cargo::rustc-link-arg=/subsystem:efi_runtime_driver"); } } ``` -------------------------------- ### Execute Release with cargo-release Source: https://github.com/rust-osdev/uefi-rs/blob/main/PUBLISHING.md Execute the release process for a specific crate, including bumping versions, creating tags, and publishing to crates.io. Use this after a successful dry run. ```bash cargo release -p uefi-raw 0.4.0 --execute ``` -------------------------------- ### Specify UEFI Targets in rust-toolchain.toml Source: https://github.com/rust-osdev/uefi-rs/blob/main/book/src/tutorial/building.md Add this TOML file to your project root to define the UEFI targets for your Rust toolchain. This ensures the correct targets are available for building. ```toml [toolchain] targets = ["aarch64-unknown-uefi", "i686-unknown-uefi", "x86_64-unknown-uefi"] ``` -------------------------------- ### Format code with rustfmt Source: https://github.com/rust-osdev/uefi-rs/blob/main/CONTRIBUTING.md Apply the standard Rust code style to the entire package using `rustfmt`. This command formats all files in the repository. ```shell cargo fmt --all ``` -------------------------------- ### Open LoadedImage Protocol in UEFI Rust Source: https://github.com/rust-osdev/uefi-rs/blob/main/book/src/how_to/protocols.md This code snippet demonstrates how to open the LoadedImage protocol exclusively for a given handle. Ensure you have the correct handle for the currently running image. ```rust let loaded_image = boot_services.open_protocol_exclusive(boot::image_handle()?) .map_err(|(err, _)| err)?; ``` -------------------------------- ### Copy OVMF Firmware Files Source: https://github.com/rust-osdev/uefi-rs/blob/main/book/src/tutorial/vm.md Copies the OVMF firmware code and variable storage files to the project directory. These are required for QEMU to emulate UEFI. ```sh cp /usr/share/OVMF/OVMF_CODE.fd . cp /usr/share/OVMF/OVMF_VARS.fd . ``` -------------------------------- ### Return Success Status Source: https://github.com/rust-osdev/uefi-rs/blob/main/book/src/tutorial/app.md Indicates that the UEFI application completed successfully by returning `Status::SUCCESS`. ```rust Status::SUCCESS ``` -------------------------------- ### Build UEFI Application with Cargo Source: https://github.com/rust-osdev/uefi-rs/blob/main/book/src/tutorial/building.md Use this Cargo command to compile your Rust project for the specified UEFI target. The output will be an EFI executable file. ```sh cargo build --target x86_64-unknown-uefi ``` -------------------------------- ### Print Loaded Image Path in UEFI Rust Source: https://github.com/rust-osdev/uefi-rs/blob/main/book/src/how_to/protocols.md This function retrieves and prints the path of the currently loaded UEFI image. It requires opening the LoadedImage protocol and then the DevicePathToText protocol to convert the path to a human-readable string. ```rust fn print_image_path( boot_services: &BootServices, loaded_image: &LoadedImage, ) -> Result<()> { let device_path_to_text = boot_services .locate_handle_buffer::()? // Find handles that support DevicePathToText .into_iter() .next() .ok_or(Status::NotFound)?; let device_path_to_text = boot_services.open_protocol_exclusive(device_path_to_text)?; let device_path = loaded_image.device_handle()?; let device_path = boot_services.open_protocol_exclusive(device_path)?; let path_text = device_path_to_text.convert_device_path_to_text(device_path, None, None)?; println!("Image path: {}", path_text.to_string()?); Ok(()) } ``` -------------------------------- ### UEFI Application Boilerplate Attributes Source: https://github.com/rust-osdev/uefi-rs/blob/main/book/src/tutorial/app.md Essential attributes for Rust UEFI applications: `no_main` to disable the standard entry point and `no_std` to exclude the standard library. ```rust #![no_main] #![no_std] ``` -------------------------------- ### Convert Device Path to Text in UEFI Rust Source: https://github.com/rust-osdev/uefi-rs/blob/main/book/src/how_to/protocols.md This code converts a UEFI device path to a human-readable text format using the DevicePathToText protocol. It requires both the DevicePathToText protocol and the device handle to be open. ```rust let path_text = device_path_to_text.convert_device_path_to_text(device_path, None, None)?; ``` -------------------------------- ### Log Message and Stall Execution Source: https://github.com/rust-osdev/uefi-rs/blob/main/book/src/tutorial/app.md Outputs a log message using the `log` crate and pauses the system for 10 seconds using `stall`. ```rust log::info!("Hello world!"); // Stall for 10 seconds to allow viewing the output boot_services.stall(10_000_000); ``` -------------------------------- ### Update Lock File and Build Source: https://github.com/rust-osdev/uefi-rs/blob/main/PUBLISHING.md Update the project's lock file after a release or dependency change. This ensures that all dependencies are consistent and up-to-date. ```bash cargo xtask build ``` -------------------------------- ### Perform System Cold Reset in UEFI Rust Source: https://context7.com/rust-osdev/uefi-rs/llms.txt Initiates a cold reset of the system, which involves a full power cycle. This function uses the `uefi::runtime::reset` function with `ResetType::COLD`. ```rust use uefi::prelude::*; use uefi::runtime::{self, ResetType}; fn system_reset() -> ! { // Cold reset (full power cycle) runtime::reset(ResetType::COLD, Status::SUCCESS, None); } ``` -------------------------------- ### Implement safe access to protocol functions Source: https://github.com/rust-osdev/uefi-rs/blob/main/CONTRIBUTING.md Provides a safe Rust interface for calling the underlying UEFI protocol functions. This implementation handles the unsafe calls to the C-style function pointers. ```rust impl NewProtocol { /// This function does something. pub fn do_something(&self, a: SomeType, b: SomeOtherType) -> Result { // Call the wrapped function let status = unsafe { (self.some_entry_point)(self, a, b) }; // `Status` provides a helper function for converting to `Result` status.into() } } ``` -------------------------------- ### Push Tags to Remote Source: https://github.com/rust-osdev/uefi-rs/blob/main/PUBLISHING.md Push all local git tags to the remote repository. This is crucial for ensuring that release tags are available to others and for CI/CD pipelines. ```bash git push --tags ``` -------------------------------- ### Shut Down System in UEFI Rust Source: https://context7.com/rust-osdev/uefi-rs/llms.txt Powers off the system. This function uses the `uefi::runtime::reset` function with `ResetType::SHUTDOWN`. ```rust use uefi::prelude::*; use uefi::runtime::{self, ResetType}; fn shutdown() -> ! { // Power off the system runtime::reset(ResetType::SHUTDOWN, Status::SUCCESS, None); } ``` -------------------------------- ### Dry Run Release with cargo-release Source: https://github.com/rust-osdev/uefi-rs/blob/main/PUBLISHING.md Perform a dry run of the release process for a specific crate to preview changes without executing them. This command checks versioning and changelog updates. ```bash cargo release -p uefi-raw 0.4.0 ``` -------------------------------- ### Exit UEFI Boot Services Source: https://context7.com/rust-osdev/uefi-rs/llms.txt Safely exit boot services to transition to an operating system kernel. This invalidates all boot service protocols and retrieves the final memory map. The caller must ensure no references to boot services remain. ```rust use uefi::prelude::*; use uefi::boot::{self, MemoryType}; use uefi::mem::memory_map::MemoryMapOwned; fn exit_to_kernel() -> ! { // SAFETY: Caller must ensure no references to boot services remain let memory_map: MemoryMapOwned = unsafe { boot::exit_boot_services(Some(MemoryType::LOADER_DATA)) }; // Boot services are now unavailable // Only runtime services and configuration tables can be used // Pass memory map to kernel... // Jump to kernel entry point... loop {} // Never returns } ``` -------------------------------- ### Buffer Abstraction for Graphics Output Source: https://github.com/rust-osdev/uefi-rs/blob/main/book/src/how_to/drawing.md This code defines a Buffer type for managing pixel data, storing pixels in a Vec of BltPixels. It includes a pixel method for individual pixel manipulation, suitable for simpler graphics tasks. ```rust pub struct Buffer { pub pixels: Vec, pub width: usize, pub height: usize, } impl Buffer { pub fn new(width: usize, height: usize) -> Self { Buffer { pixels: vec![BltPixel::new(0, 0, 0, 0); width * height], width, height, } } pub fn pixel(&mut self, x: usize, y: usize) -> &mut BltPixel { &mut self.pixels[y * self.width + x] } pub fn blit(&self, gop: &GraphicsOutput) { gop.blt( BltOp::BufferToVideo { src: self.pixels.iter().map(|p| *p).collect(), dest: 0, count: self.pixels.len(), }, None, None, ) .expect("Failed to blit buffer to screen"); } } ```