Skip to content

Add a minimal UEFI application template #268

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .github/workflows/rust.yml
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,12 @@ jobs:
components: rust-src
# TODO: cache Rust binaries

- name: Build template
uses: actions-rs/cargo@v1
with:
command: build
args: --target x86_64-unknown-uefi --manifest-path template/Cargo.toml

- name: Build
run: ./build.py build
working-directory: ./uefi-test-runner
Expand Down
36 changes: 15 additions & 21 deletions BUILDING.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,30 +5,25 @@ UEFI applications are simple COFF (Windows) executables, with the special
[Rust supports building UEFI applications](https://github.com/rust-lang/rust/pull/56769)
though the `x86_64-unknown-uefi` target.

## Steps
## Template

The following steps allow you to build a simple UEFI app.
The [template](template) subdirectory contains a minimal example of a UEFI
application. Copy it to a new directory to get started.

- Create a new `#![no_std]` binary, add `#![no_main]` to use a custom entry point,
and make sure you have an entry point function which matches the one below:
```rust
#![feature(abi_efiapi)]
use uefi::prelude::*;
- [template/.cargo/config](template/.cargo/config) file sets some `build-std` options.
- [template/Cargo.toml](template/Cargo.toml) shows the necessary
dependencies. Note that when creating your project the
[`uefi`](https://crates.io/crates/uefi) and
[`uefi-services`](https://crates.io/crates/uefi-services) dependencies should
be changed to the latest releases on [crates.io](https://crates.io).
- [template/src/main.rs](template/src/main.rs) has a minimal entry point that
initializes services and exits successfully.

extern crate rlibc;

#[entry]
fn main(handle: Handle, mut system_table: SystemTable<Boot>) -> Status;
```
Note that Rust EFI target requires the entry function to be exported with an `efi_main` symbol,
the `#[entry]` macro takes care of that, so the function name is irrelevant.

You will also want to add a dependency to the [`rlibc`](https://docs.rs/rlibc/) crate and
explicitly link it with `extern crate rlibc;` line to avoid linking errors.
## Building and running

- Build using a `nightly` version of the compiler and activate the
[`build-std`](https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#build-std)
Cargo feature: `cargo build -Z build-std --target x86_64-unknown-uefi`.
Cargo feature: `cargo +nightly build -Z build-std --target x86_64-unknown-uefi`.

- The `target` directory will contain a `x86_64-unknown-uefi` subdirectory,
where you will find the `uefi_app.efi` file - a normal UEFI executable.
Expand All @@ -40,6 +35,5 @@ The following steps allow you to build a simple UEFI app.

- To run this in QEMU:
- You will need a recent version of QEMU as well as OVMF to provide UEFI support
- Check the `build.py` script for an idea of what arguments to pass to QEMU

You can use the `uefi-test-runner` directory as sample code for building a simple UEFI app.
- Check the [`build.py`](uefi-test-runner/build.py) script for an idea of
what arguments to pass to QEMU
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ uefi-macros = "0.3.2"

[workspace]
members = [
"template",
"uefi-macros",
"uefi-services",
"uefi-test-runner",
Expand Down
2 changes: 2 additions & 0 deletions template/.cargo/config
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
[unstable]
build-std = ["core", "compiler_builtins", "alloc"]
12 changes: 12 additions & 0 deletions template/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
[package]
name = "uefi_app"
version = "0.1.0"
edition = "2018"

[dependencies]
rlibc = "1.0.0"

# In a real application, change these to point to the latest release
# on crates.io.
uefi = { path = "..", features = ["exts"] }
uefi-services = { path = "../uefi-services" }
15 changes: 15 additions & 0 deletions template/src/main.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
#![no_main]
#![no_std]
#![feature(abi_efiapi)]

extern crate rlibc;

use uefi::prelude::*;
use uefi::ResultExt;

#[entry]
fn main(_handle: Handle, mut system_table: SystemTable<Boot>) -> Status {
uefi_services::init(&mut system_table).unwrap_success();

Status::SUCCESS
}