Stable RustでUEFIバイナリを作成する
はじめに
Rustにはx86_64-unknown-uefi
というターゲットが存在しますが,このターゲットに対するcore
ライブラリなどの標準ライブラリは提供されていないため,cargo
の-Z build-std=core
などのオプションを用いて自分でこれらのライブラリをコンパイルする必要があります.-Z
オプションの使用はNightlyバージョンのツールチェーンを必要としますが,この記事ではNightly Rustの使用を回避して,Stable RustでUEFIバイナリを作成します.
リポジトリ
解説
基本的にRustのx86_64-unknown-uefi
ターゲットの設定ファイルを参考にします.
また,x86_64-unknown-uefi
ターゲットが導入されたPRの各議論についても参考にしてください.
Windowsターゲットのインストール
PE32+バイナリを作成するため,Windowsターゲットをインストールします.
rustup target add x86_64-pc-windows-gnu
.cargo/config.toml
[build] target = "x86_64-pc-windows-gnu" [target.x86_64-pc-windows-gnu] rustflags = [ "-C", "link-args=/entry:efi_main /subsystem:efi_application", "-C", "no-redzone=y", "-C", "linker=lld-link", ]
/entry:efi_main
は厳密には必要ありませんが,Rustのx86_64-unknown-uefi
ターゲットがこのように指定しているため,これに倣っています.また,これらのオプションを使用するため,linker=lld-link
を指定し,リンカとしてlld-link
を使用します.Ubuntuでは以下のようにしてインストールします.
sudo apt-get install lld sudo ln -s /usr/bin/lld /usr/bin/lld-link
src/main.rs
#![no_std] #![no_main] #[no_mangle] fn efi_main(h: uefi::Handle, mut st: bootx64::SystemTable) -> ! { // 中略 }
#![no_main]
と#[no_mangle]
を使用することで,efi_main
を擬似的にエントリーポイントとします.
ビルド方法
cargo build
を実行すると,target/x86_64-pc-windows-gnu/debug
*1にbootx64.exe
というバイナリが生成されます.これをbootx64.efi
に改名することで実際にブートローダーとして使用することができます.
おまけ:ライブラリについて
UEFIに関するクレートとしてuefi
クレートが存在しますが,このクレートはNightlyの機能を使用しているため,Stable Rustではビルドできません.
Stable RustでビルドできるUEFIに関するクレートとしてr-efi
クレートが存在します.このクレートはUEFIの規格に載っている各関数や定義をなるべくそのままRustのコードとして定義しているクレートです.このクレートを直に使用することは意図されておらず,何らかのラッパを記述することが推奨されています.