Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Patina in the UEFI Rust Ecosystem

This section provides an overview of the most likely options you will encounter when first considering writing UEFI firmware in Rust. The ecosystem is still in its early stages, but there are already a number of projects that have been active for years.

  • r-efi
    • UEFI Reference Specification Protocol Constants and Definitions. A pure transpose of the UEFI specification into Rust. This provides the raw definitions from the specification, without any extended helpers or Rustification. It serves as baseline to implement any more elaborate Rust UEFI layers.
  • uefi-rs
    • Safe and easy-to-use wrapper for building UEFI apps. An elaborate library providing safe abstractions for UEFI protocols and features. It implements allocators and provides an execution environment to UEFI applications written in Rust.

Though not a project, you can also write UEFI code using uefi std support tracked by the official Rust language. Additionally, more information about the *-unknown-uefi target is a great place to understand information that applies to all UEFI Rust projects building against that target.

It is important to understand that Patina is fundamentally different from these projects.

AspectPatinauefi-rsr-efiuefi std
Abstraction levelHigh-level firmware frameworkHigh-level safe abstractionsLow-level raw bindingsStandard library port
Target use caseFull firmware implementation ground up in Pure RustUEFI applications & driversSimple spec type bindings reused in other implementationsUEFI applications
SafetySafe Rust APIsSafe Rust APIsUnsafe raw FFISafe Rust APIs
Opinionated designYesModerateNoNo

Because of the "raw" nature of r-efi, it is used in many other places including Patina and uefi-rs. uefi-rs and Rust std support provide a path to write UEFI applications (and to some extent, DXE drivers) in Rust using safe and ergonomic interfaces. They are both compatible with an underlying core written in C (such as Tianocore EDK II) or Rust (such as Patina) since UEFI Specification defined interfaces like the Boot Services table serve as a common abstraction.

UEFI Apps and Core Abstraction

Patina, implements the entire core environment in Rust with a design that supports porting drivers to Pure Rust over time while providing backward compatibility with Platform Initialization (PI) Specification dispatch. Therefore, while Patina provides an SDK that can be used for general-purpose UEFI development, its main focus is to write the entire execution environment in Rust as opposed to a wrapper around services that ultimately are implemented in C. Due to this, Patina has an audience ranging from core developers to application developers.

Rust Firmware Layers and Developers

By writing the core in Rust, Patina provides a unique opportunity to leverage Rust's safety and other language features up and down the entire DXE build for a given platform. A key goal of Patina is to leverage this by porting more DXE drivers to Patina components over time that use idiomatic Rust interfaces while maintaining backward compatibility with the remaining DXE drivers.

In particular, a call to action for the ecosystem is to port those existing drivers to Patina components. Because there are hundreds of DXE drivers in a typical platform today, Patina components are likely to depend on functionality in some code that is not ported yet and we lose some of the benefits of Rust's safety when we have to call back into C code.

Patina Components and C Drivers

When a C DXE driver installs a protocol that Patina-based code must consume, the Rust compiler cannot verify the struct’s function pointers behave safely. We are forced to trust the layout and the implementation.

A Patina Service call, by contrast, is fully accounted for at compile time. Aliasing, lifetimes, and ownership all checked end-to-end. Read Getting Started with Components for more information.