備忘録やめた

備忘録として使用していたけどやめた.このブログに載せてあるコードのライセンスは別途記載がない限りWTFPL OR NYSLです.

Stable RustでUEFIバイナリを作成する

はじめに

Rustにはx86_64-unknown-uefiというターゲットが存在しますが,このターゲットに対するcoreライブラリなどの標準ライブラリは提供されていないため,cargo-Z build-std=coreなどのオプションを用いて自分でこれらのライブラリをコンパイルする必要があります.-Zオプションの使用はNightlyバージョンのツールチェーンを必要としますが,この記事ではNightly Rustの使用を回避して,Stable RustでUEFIバイナリを作成します.

リポジトリ

github.com

解説

基本的にRustのx86_64-unknown-uefiターゲットの設定ファイルを参考にします.

github.com

github.com

また,x86_64-unknown-uefiターゲットが導入されたPRの各議論についても参考にしてください.

github.com

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*1bootx64.exeというバイナリが生成されます.これをbootx64.efiに改名することで実際にブートローダーとして使用することができます.

おまけ:ライブラリについて

UEFIに関するクレートとしてuefiクレートが存在しますが,このクレートはNightlyの機能を使用しているため,Stable Rustではビルドできません.

Stable RustでビルドできるUEFIに関するクレートとしてr-efiクレートが存在します.このクレートはUEFIの規格に載っている各関数や定義をなるべくそのままRustのコードとして定義しているクレートです.このクレートを直に使用することは意図されておらず,何らかのラッパを記述することが推奨されています

*1:提示したリポジトリの場合,ワークスペースの関係で../にtargetディレクトリが生成されます