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のコードとして定義しているクレートです.このクレートを直に使用することは意図されておらず,何らかのラッパを記述することが推奨されています.