Skip to content

Commit 9c5732f

Browse files
Add a minimal UEFI application template (#268)
This adds a new crate under `template/` that contains a very minimal UEFI application. The instructions in `BUILDING.md` have been updated to reference the template instead of using inline code snippets. I think this makes it a bit easier to get started with a new app -- you can just copy the whole directory and make a couple changes in `Cargo.toml` to get started. `uefi-test-runner` is similar, but has a lot more stuff in it so it's harder to see exactly what is needed. Moving the code out of markdown also makes it easier to test in github actions to ensure the code stays valid.
1 parent d64590d commit 9c5732f

File tree

6 files changed

+51
-21
lines changed

6 files changed

+51
-21
lines changed

.github/workflows/rust.yml

+6
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,12 @@ jobs:
4848
components: rust-src
4949
# TODO: cache Rust binaries
5050

51+
- name: Build template
52+
uses: actions-rs/cargo@v1
53+
with:
54+
command: build
55+
args: --target x86_64-unknown-uefi --manifest-path template/Cargo.toml
56+
5157
- name: Build
5258
run: ./build.py build
5359
working-directory: ./uefi-test-runner

BUILDING.md

+15-21
Original file line numberDiff line numberDiff line change
@@ -5,30 +5,25 @@ UEFI applications are simple COFF (Windows) executables, with the special
55
[Rust supports building UEFI applications](https://github.com/rust-lang/rust/pull/56769)
66
though the `x86_64-unknown-uefi` target.
77

8-
## Steps
8+
## Template
99

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

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

18-
extern crate rlibc;
19-
20-
#[entry]
21-
fn main(handle: Handle, mut system_table: SystemTable<Boot>) -> Status;
22-
```
23-
Note that Rust EFI target requires the entry function to be exported with an `efi_main` symbol,
24-
the `#[entry]` macro takes care of that, so the function name is irrelevant.
25-
26-
You will also want to add a dependency to the [`rlibc`](https://docs.rs/rlibc/) crate and
27-
explicitly link it with `extern crate rlibc;` line to avoid linking errors.
22+
## Building and running
2823

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

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

4136
- To run this in QEMU:
4237
- You will need a recent version of QEMU as well as OVMF to provide UEFI support
43-
- Check the `build.py` script for an idea of what arguments to pass to QEMU
44-
45-
You can use the `uefi-test-runner` directory as sample code for building a simple UEFI app.
38+
- Check the [`build.py`](uefi-test-runner/build.py) script for an idea of
39+
what arguments to pass to QEMU

Cargo.toml

+1
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ uefi-macros = "0.3.2"
3838

3939
[workspace]
4040
members = [
41+
"template",
4142
"uefi-macros",
4243
"uefi-services",
4344
"uefi-test-runner",

template/.cargo/config

+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
[unstable]
2+
build-std = ["core", "compiler_builtins", "alloc"]

template/Cargo.toml

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
[package]
2+
name = "uefi_app"
3+
version = "0.1.0"
4+
edition = "2018"
5+
6+
[dependencies]
7+
rlibc = "1.0.0"
8+
9+
# In a real application, change these to point to the latest release
10+
# on crates.io.
11+
uefi = { path = "..", features = ["exts"] }
12+
uefi-services = { path = "../uefi-services" }

template/src/main.rs

+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
#![no_main]
2+
#![no_std]
3+
#![feature(abi_efiapi)]
4+
5+
extern crate rlibc;
6+
7+
use uefi::prelude::*;
8+
use uefi::ResultExt;
9+
10+
#[entry]
11+
fn main(_handle: Handle, mut system_table: SystemTable<Boot>) -> Status {
12+
uefi_services::init(&mut system_table).unwrap_success();
13+
14+
Status::SUCCESS
15+
}

0 commit comments

Comments
 (0)