Crate r_efi[][src]

Expand description

UEFI Reference Specification Protocol Constants and Definitions

This project provides protocol constants and definitions as defined in the UEFI Reference Specification. The aim is to provide all these constants as C-ABI compatible imports to rust. Safe rust abstractions over the UEFI API are out of scope of this project. That is, the purpose is really just to extract all the bits and pieces from the specification and provide them as rust types and constants.

While we strongly recommend using safe abstractions to interact with UEFI systems, this project serves both as base to write those abstractions, but also as last resort if you have to deal with quirks and peculiarities of UEFI systems directly. Therefore, several examples are included, which show how to interact with UEFI systems from rust. These serve both as documentation for anyone interested in how the system works, but also as base for anyone implementing safe abstractions on top.

Target Configuration

Rust code can be compiled natively for UEFI systems. However, you are quite unlikely to have a rust compiler running in an UEFI environment. Therefore, you will most likely want to cross compile your rust code for UEFI systems. To do this, you need a target-configuration for UEFI systems. In case your rust compiler does not provide these, this project has several of them included. As of February 2019, upstream rust includes the following UEFI targets:

  • x86_64-unknown-uefi: A native UEFI target for x86-64 systems. Programs compiled for this target can run natively as UEFI binaries on 64bit Intel-compatible systems.

If none of these targets match your architecture, you have to create the target specification yourself. Feel free to contact the r-efi project for help.

Transpose Guidelines

The UEFI specification provides C language symbols and definitions of all its protocols and features. Those are integral parts of the specification and UEFI programming is often tightly coupled with the C language. For better compatibility to existing UEFI documentation, all the rust symbols are transposed from C following strict rules, aiming for close similarity to specification. This section gives a rationale on some of the less obvious choices and tries to describe as many of those rules as possible.

  • no enums: Rust enums do not allow random discriminant values. However, many UEFI enumerations use reserved ranges for vendor defined values. These cannot be represented with rust enums in an efficient manner. Hence, any enumerations are turned into rust constants with an accompanying type alias.

    A detailed discussion can be found in:

        commit 401a91901e860a5c0cd0f92b75dda0a72cf65322
        Author: David Rheinsberg <david.rheinsberg@gmail.com>
        Date:   Wed Apr 21 12:07:07 2021 +0200
    
            r-efi: convert enums to constants
    
  • no incomplete types: Several structures use incomplete structure types by using an unbound array as last member. While rust can easily represent those within its type-system, such structures become DSTs, hence even raw pointers to them become fat-pointers, and would thus violate the UEFI ABI.

    As a workaround, trailing unbound arrays are transposed as zero-sized arrays for now.

Examples

To write free-standing UEFI applications, you need to disable the entry-point provided by rust and instead provide your own. Most target-configurations look for a function called efi_main during linking and set it as entry point. If you use the target-configurations provided with upstream rust, they will pick the function called efi_main as entry-point.

The following example shows a minimal UEFI application, which simply returns success upon invocation. Note that you must provide your own panic-handler when running without libstd. In our case, we use a trivial implementation that simply loops forever.

#![no_main]
#![no_std]

use r_efi::efi;

#[panic_handler]
fn panic_handler(_info: &core::panic::PanicInfo) -> ! {
    loop {}
}

#[export_name = "efi_main"]
pub extern fn main(_h: efi::Handle, _st: *mut efi::SystemTable) -> efi::Status {
    efi::Status::SUCCESS
}

Modules

base

UEFI Base Environment

efi

Flat EFI Namespace

hii

Human Interface Infrastructure (HII)

protocols

UEFI Protocols

system

UEFI System Integration

vendor

UEFI Vendor Protocols

Macros

eficall

Annotate function with UEFI calling convention