Rustでcoreboot payload
この記事は自作OS Advent Calendar の19日目の記事として書かれた. ここでは,corebootのpayloadをRustを使って作ってみる. corebootはファームウェアなのでOSとは異なるが,そこはご愛嬌ということで.
corebootについて
corebootとは既存のプロプライエタリなBIOSを置き換えるBIOSと そのプロジェクトのことである. corebootは大きくcoreboot本体とPayloadの2つがあり, Payloadには様々なソフトウェアを載せることができる. 今回はPayloadをRustで作ってみようということである. ここでは,Libpayloadと呼ばれるPayload向けのライブラリの関数を Rustから呼び出してみる.
Rustでのベアメタルプログラミング
Rustでのベアメタルプログラミングについてはκeenさんの記事 が詳しい.ほとんどここを参考にした.
ホストの環境はx86_64であるとする.
最初にcargo new --bin cb-ffi
とかやって新規のCargoプロジェクトを作成する.
次に以下のような内容でmain.rs
を書く.
#![feature(lang_items, asm)]
#![crate_type = "staticlib"]
#![no_std]
#[link(name = "libpayload", kind = "static")]
extern {
fn putchar(c: u32);
}
#[no_mangle]
pub extern fn main() {
loop{
unsafe { putchar(65) };
}
}
#[lang = "eh_personality"]
extern fn eh_personality() {}
#[lang = "panic_fmt"]
extern fn panic_fmt() {}
ほとんど上記の記事と同じであるが,
#[link(name = "libpayload", kind = "static")]
extern {
fn putchar(c: u32);
}
でlibpayloadのputchar
の参照を定義しており,
#[no_mangle]
pub extern fn main() {
loop{
unsafe { putchar(65) };
}
}
で上記のputcharを呼び出していることがわかる.
次に
rustc --target i686-unknown-linux-gnu --emit=obj main.rs
とかやってmain.o
を作成する.
最後に,あらかじめ作成しておいたlibpayload.a
とリンクする.
ここでは,Libpayloadのlpgcc
を用いる.Libpayloadについては
ここを参照のこと.
~/src/coreboot/payloads/libpayload/bin/lpgcc main.o libpayload.a
できたa.out
をcorebootのPayloadに指定すればできあがり.
以上,ファームウェアといいつつも, ただのベアメタルプログラミングであることがわかる. しかも一切アセンブリに触れずにできていることからも簡単であると言える.