uefi-rs: safe Rust abstractions for writing UEFI firmware applications
Rusty wrapper for the Unified Extensible Firmware Interface (UEFI). This crate makes it easy to develop Rust software that leverages safe, convenient, and performant abstractions for UEFI functionality.
At a glance
- What is it?
- uefi-rs is a Rust wrapper around the Unified Extensible Firmware Interface, built to give firmware developers safe, convenient and performant abstractions instead of raw C tables and manual pointer arithmetic. It is a workspace of five crates, tested by booting real UEFI binaries in QEMU against OVMF, and it is the base layer under community projects like a Ratatui terminal for firmware.
- Who is it for?
- uefi-rs suits a systems programmer writing a UEFI application in Rust, because it removes the C-style table walks and manual lifetime management that the UEFI specification is full of, and because the test runner boots a real UEFI binary so the tests exercise the actual firmware environment.
- Can I use it commercially?
- Yes. Apache-2.0 is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 4 days ago.
- What is it written in?
- Mainly Rust, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.
Star history
- rust-osdev/uefi-rs1,670 ★ · +3
| Repository | 2026-10-16 | 2026-10-23 |
|---|---|---|
| rust-osdev/uefi-rs | 1.7k | 1.7k |
3 Stars in the last 7 days, measured from the daily GitHub snapshot. Compare with other projects
Editorial analysis
Why UEFI is a bad fit for safe Rust
The README states the goal in one sentence. This crate makes it easy to develop Rust software that leverages safe, convenient, and performant abstractions for UEFI functionality.
The word safe is doing the heavy lifting, because UEFI is a specification written for C. It is a table-driven interface: the firmware hands you a pointer to a system table, you look up a protocol GUID in it, you get a pointer to an interface structure, and every call is a function pointer invoked through a pointer to a pointer. The types are raw, the lifetimes are unconstrained, and the compiler will not stop you from passing the wrong structure to the wrong protocol.
Rust's answer to that is a layer of abstractions where the unsafe parts are small and confined, so that the ordinary case is checked. The uefi crate is that layer, and the project makes the distinction explicit by splitting the work across crates.
The workspace holds seven members: template, uefi, uefi-macros, uefi-raw, uefi-std-example, uefi-test-runner and xtask. The main contribution is the uefi crate, the high-level wrapper around various low-level UEFI APIs. uefi-raw holds raw ABI-compatible types that closely match the definitions in the UEFI Specification, and the README says they are suitable for implementing UEFI firmware or creating interfaces to it. uefi-macros provides helper macros used by uefi.
The workspace metadata lists the categories as embedded, no-std and api-bindings, the edition is 2024, and the rust-version is 1.91. The licence is MIT OR Apache-2.0, and the README states it as licensed under either of the Apache License, Version 2.0 or the MIT license at your option, with LICENSE-APACHE and LICENSE-MIT in the repository root.
The crate split tells you which layer to reach for
Choosing the right crate is the first decision a new user makes, and the four descriptions in the README are precise enough to decide on.
The uefi crate is the high-level wrapper and the one most people want. It is where the safe abstractions live.
The uefi-raw crate is the raw layer. Raw ABI-compatible types that closely match the definitions in the UEFI Specification, suitable for implementing UEFI firmware or creating interfaces to it. That is a different job from writing an application. If you are writing firmware that implements the specification rather than an application that calls into it, uefi-raw is what you want, and uefi on top of it.
uefi-macros holds the helper macros used by uefi, which is the proc-macro crate.
uefi-std-example is an example UEFI app but as a Rust standard binary, and the distinction is instructive. A Rust standard binary cannot run in UEFI, because UEFI is not an operating system with a process model and a dynamic loader. The example exists to show what the same logic looks like when compiled for the host, and it is the reason the test suite can run unit tests and doctests on the host.
uefi-test-runner is a UEFI application that runs the integration tests, and the README says the uefi-test-runner directory contains a sample UEFI app which exercises most of the library's functionality.
The template crate is the scaffolding for a new UEFI project.
The workspace also patches itself into crates.io with a [patch.crates-io] section, so the local uefi, uefi-macros and uefi-raw are used rather than the published ones during development.
cargo xtask, and running a UEFI binary in QEMU
Building and testing goes through one command. Use the cargo xtask command to build and test the crate.
The available commands are build, clippy, doc, run and test.
build builds all the UEFI packages, with a --release flag and a --target flag taking {x86_64,ia32,aarch64} to choose the target UEFI architecture. clippy runs clippy on all the packages, with the same target flag and a --warnings-as-errors option. doc builds the docs for the UEFI packages, with --open to open them in a browser and --warnings-as-errors. test runs unit tests and doctests on the host.
The interesting one is run, which builds uefi-test-runner and runs it in QEMU. Its options are more than a flag list, and each one reflects a real environment problem. There is --ci to disable some tests that don't work in the CI environment, and --disable-kvm to disable hardware accelerated virtualization support in QEMU, which the README says is especially useful if you want to run the tests under WSL on Windows. There is --example <NAME> to run an example instead of the main binary, and --headless to run QEMU without a GUI, which is what a CI runner needs. And there are --ovmf-code <PATH> and --ovmf-vars <PATH> for the OVMF firmware files.
That last pair deserves a note. OVMF is the Open Virtual Machine Firmware, an open source UEFI implementation. A UEFI application cannot be tested without a UEFI firmware to run it on, and the firmware comes as a code file and a variables file. Pointing the test runner at your own OVMF build means your tests run against the firmware your users will actually have, rather than against a default.
The screenshot in the README is of a UEFI application running in QEMU on UEFI firmware that leverages the Rust library, which is the whole loop in one image.
The dependency set, and what no-std costs
The workspace dependency list is short and every entry is a no-std one, which is the constraint that shapes everything else.
[workspace.dependencies]
bitflags = "2.0.0"
log = { version = "0.4.5", default-features = false }
jiff = { version = "0.2", default-features = false }
ptr_meta = { version = "0.3.0", default-features = false, features = ["derive"] }
qemu-exit = { version = "4.0.0" }
time = { version = "0.3", default-features = false }
uguid = "2.2.1"The default-features = false on log, jiff, ptr_meta and time is the interesting part. A firmware application runs before any operating system exists, so there is no filesystem, no network stack, no standard library runtime and no threads. A dependency that turns on its default features will often pull in std, and the build will fail with a confusing error about the target not supporting it. Turning the features off is what makes those crates usable at all.
ptr_meta with the derive feature is the pointer metadata support, which is how the crate validates that a pointer actually points at a structure of the right type and length before it dereferences it. That is one of the places where the safety claim is actually enforced rather than merely asserted.
uguid is the UEFI GUID type, since the specification identifies every protocol and every file system by GUID and a safe wrapper needs a real GUID type rather than a byte array.
qemu-exit is a different kind of dependency, and an unusual one to see in a library: it is the mechanism by which the test runner tells QEMU to exit when the tests are done. A UEFI application has no way to return an exit code to a shell, so it writes to a special I/O port that QEMU is watching. The library therefore depends on the test environment, which is a small coupling worth knowing about if you are using uefi for something other than testing.
The xtask crate is given opt-level = 3 in the dev profile, with a comment explaining that this enables optimization for xtask itself, not for its dependencies, because it speeds up OVMF prebuilt decompression without much increase in compilation time.
Community projects on top of the crate
The showcases section lists selected projects from the community, with an invitation to raise a pull request and add yours.
ratatuefi provides a Ratatui backend for the UEFI environment using uefi. Ratatui is the Rust terminal user interface library, so this is a terminal emulator that runs inside the firmware, before the operating system starts.
efimux is an EFI application for booting other EFI applications, written with ratatuefi and therefore also uefi. That is a firmware-level multiplexer, the kind of thing a boot menu or a chainloader would be.
uefirc is a graphical UEFI IRC client to connect to an IRC server, chat, and read messages, all from the comfort of your motherboard's pre-boot environment.
Read together, these three tell you what the library is for. It is not for writing a full firmware volume with a boot manager and a driver stack, it is for writing applications that run inside somebody's existing firmware, on real hardware, before an OS exists. That is a narrow and unusual niche, and it is the niche where safe Rust genuinely pays off, because a bug in a pre-boot application is a machine that does not boot.
The authors of those projects are also the test case for the library's public API. A graphical IRC client in a firmware environment exercises graphics, networking, input and the console, which is considerably more of the API surface than a test runner needs.
For community discussion, the README points to a Zulip instance at rust-osdev.zulipchat.com, and the issue tracker is the place for bugs and questions.
Editorial conclusion
uefi-rs suits a systems programmer writing a UEFI application in Rust, because it removes the C-style table walks and manual lifetime management that the UEFI specification is full of, and because the test runner boots a real UEFI binary so the tests exercise the actual firmware environment. It is the wrong tool if you need to implement a full firmware volume rather than an application, and it is the wrong choice if you are writing in C, since the raw ABI crate is there for interoperability rather than as an alternative to a C toolchain. Before you start, read the UEFI book linked from the homepage, and set up the xtask workflow, since cargo xtask run is what actually exercises the library in QEMU rather than only on the host.
Frequently asked questions
What is uefi-rs and what does it do?
It is a Rust wrapper around the Unified Extensible Firmware Interface, providing safe, convenient and performant abstractions so that Rust software can be written for the UEFI environment without handling the raw C-style tables and pointers by hand.
What is the difference between the uefi and uefi-raw crates?
The uefi crate is the high-level wrapper with the safe abstractions and is the main contribution. The uefi-raw crate holds raw ABI-compatible types that closely match the UEFI Specification and are suitable for implementing UEFI firmware or creating interfaces to it.
How do I build and test uefi-rs?
Use cargo xtask. The commands are build, clippy, doc, run and test, and the run command builds uefi-test-runner and runs it in QEMU, with options for --headless, --ci, --disable-kvm and paths to the OVMF code and vars files.
What licence is uefi-rs released under?
MIT OR Apache-2.0, at your option, with LICENSE-APACHE and LICENSE-MIT in the repository root and the workspace package section declaring license = "MIT OR Apache-2.0".
What are the community projects built on uefi-rs?
The README lists ratatuefi, a Ratatui terminal backend for the UEFI environment, efimux, an EFI application for booting other EFI applications, and uefirc, a graphical UEFI IRC client.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/rust-osdev-uefi-rs)Star history chart for your README
[](https://hysenlabs.com/projects/rust-osdev-uefi-rs)Was this useful?