UEFI Setup
Setting up a Rust UEFI development environment.
Prerequisites
Install Rust nightly and the UEFI target:
# Install nightly toolchain
rustup install nightly
# Add UEFI target
rustup target add x86_64-unknown-uefi --toolchain nightly
# Or for ARM64
rustup target add aarch64-unknown-uefi --toolchain nightly
Project Setup
Create New Project
cargo new uefi-app --edition 2021
cd uefi-app
Cargo.toml
[package]
name = "uefi-app"
version = "0.1.0"
edition = "2021"
[dependencies]
uefi = "0.32"
log = "0.4"
[profile.dev]
panic = "abort"
[profile.release]
panic = "abort"
opt-level = "z" # Optimize for size
lto = true
codegen-units = 1
strip = true
rust-toolchain.toml
Pin to nightly:
[toolchain]
channel = "nightly"
components = ["rust-src"]
targets = ["x86_64-unknown-uefi"]
.cargo/config.toml
Configure build settings:
[build]
target = "x86_64-unknown-uefi"
[unstable]
build-std = ["core", "alloc"]
build-std-features = ["compiler-builtins-mem"]
Project Structure
uefi-app/
├── .cargo/
│ └── config.toml
├── src/
│ └── main.rs
├── Cargo.toml
├── rust-toolchain.toml
└── scripts/
└── run-qemu.sh
Basic Application Template
// src/main.rs
#![no_main]
#![no_std]
use uefi::prelude::*;
#[entry]
fn main() -> Status {
uefi::helpers::init().unwrap();
log::info!("UEFI application started!");
Status::SUCCESS
}
Building
# Build the application
cargo build --release
# Output location
ls target/x86_64-unknown-uefi/release/uefi-app.efi
Installing QEMU and OVMF
Ubuntu/Debian
# Install QEMU
sudo apt install qemu-system-x86 ovmf
# OVMF firmware location
ls /usr/share/OVMF/OVMF_CODE.fd
ls /usr/share/OVMF/OVMF_VARS.fd
Fedora
sudo dnf install qemu-system-x86 edk2-ovmf
# Files in /usr/share/edk2/ovmf/
macOS
brew install qemu
# Download OVMF from https://retrage.github.io/edk2-nightly/
Windows
Download from:
- QEMU: https://www.qemu.org/download/#windows
- OVMF: https://retrage.github.io/edk2-nightly/
Running with QEMU
Basic Run Script
Create scripts/run-qemu.sh:
#!/bin/bash
set -e
# Build
cargo build --release
# Create ESP directory structure
mkdir -p esp/EFI/BOOT
cp target/x86_64-unknown-uefi/release/uefi-app.efi esp/EFI/BOOT/BOOTX64.EFI
# Run QEMU
qemu-system-x86_64 \
-nodefaults \
-machine q35 \
-bios /usr/share/OVMF/OVMF_CODE.fd \
-drive format=raw,file=fat:rw:esp \
-serial stdio \
-display none
With Graphics
qemu-system-x86_64 \
-nodefaults \
-machine q35 \
-bios /usr/share/OVMF/OVMF_CODE.fd \
-drive format=raw,file=fat:rw:esp \
-device virtio-gpu-pci \
-display gtk
With Debugging
qemu-system-x86_64 \
-nodefaults \
-machine q35 \
-bios /usr/share/OVMF/OVMF_CODE.fd \
-drive format=raw,file=fat:rw:esp \
-serial stdio \
-debugcon file:debug.log \
-global isa-debugcon.iobase=0x402 \
-s -S # GDB server on port 1234, pause at start
Using cargo-uefi
The cargo-uefi tool simplifies building and running:
# Install
cargo install cargo-uefi
# Build and run
cargo uefi run
Alternative: uefi-run
# Install
cargo install uefi-run
# Run
uefi-run target/x86_64-unknown-uefi/release/uefi-app.efi
Makefile Setup
Create a Makefile for convenience:
.PHONY: build run debug clean
TARGET = x86_64-unknown-uefi
OVMF = /usr/share/OVMF/OVMF_CODE.fd
EFI = target/$(TARGET)/release/uefi-app.efi
build:
cargo build --release
esp/EFI/BOOT/BOOTX64.EFI: $(EFI)
mkdir -p esp/EFI/BOOT
cp $(EFI) esp/EFI/BOOT/BOOTX64.EFI
run: build esp/EFI/BOOT/BOOTX64.EFI
qemu-system-x86_64 \
-nodefaults \
-machine q35 \
-bios $(OVMF) \
-drive format=raw,file=fat:rw:esp \
-serial stdio
debug: build esp/EFI/BOOT/BOOTX64.EFI
qemu-system-x86_64 \
-nodefaults \
-machine q35 \
-bios $(OVMF) \
-drive format=raw,file=fat:rw:esp \
-serial stdio \
-s -S
clean:
cargo clean
rm -rf esp
Docker Development Environment
Create Dockerfile:
FROM rust:latest
# Install QEMU and OVMF
RUN apt-get update && apt-get install -y \
qemu-system-x86 \
ovmf \
&& rm -rf /var/lib/apt/lists/*
# Install nightly and UEFI target
RUN rustup install nightly \
&& rustup target add x86_64-unknown-uefi --toolchain nightly
WORKDIR /app
And docker-compose.yml:
version: '3.8'
services:
uefi-dev:
build: .
volumes:
- .:/app
working_dir: /app
IDE Configuration
VS Code settings.json
{
"rust-analyzer.cargo.target": "x86_64-unknown-uefi",
"rust-analyzer.cargo.features": [],
"rust-analyzer.checkOnSave.allTargets": false
}
VS Code launch.json (for debugging)
{
"version": "0.2.0",
"configurations": [
{
"type": "cppdbg",
"request": "launch",
"name": "Debug UEFI",
"program": "${workspaceFolder}/target/x86_64-unknown-uefi/release/uefi-app.efi",
"miDebuggerServerAddress": "localhost:1234",
"miDebuggerPath": "gdb",
"cwd": "${workspaceFolder}",
"preLaunchTask": "qemu-debug"
}
]
}
Common Issues
| Issue | Solution |
|---|---|
| Missing target | rustup target add x86_64-unknown-uefi |
| Build errors | Use nightly: rustup override set nightly |
| OVMF not found | Install ovmf package or download |
| QEMU hangs | Check OVMF path, use -serial stdio |
Summary
| Component | Purpose |
|---|---|
uefi crate |
Safe UEFI bindings |
| Nightly Rust | Required for UEFI target |
| QEMU | VM for testing |
| OVMF | Open-source UEFI firmware |
Next Steps
Create your first UEFI application in UEFI Hello World.