を読み始めた。(読了までいけるかはわからない)
せっかくなのでRustで書いてみようということでググりながらHello Worldの出力まで。
全部作ると大変そうなのでuefi-rsを利用する方針でやります。
環境等
この記事はM1 Macでローカル環境で直接実行することを前提としている。
Docker上での構築やWin・Linuxでの動作については対象としていない。
記事時点の実装は以下。
github.com
Rustのインストールとプロジェクト作成
公式のGetting started を参考にインストール。
$ curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
ベアメタルプログラミングをする場合nightlyのコンパイラが必要なケースが多いらしいので導入
$ rustup install
ゼロからのOS自作入門をRustで でrust-srcも必要と書いてあったので用意した
$ rustup component add rust-src --toolchain nightly-aarch64-apple-darwin
適当な命名でプロジェクト作成
$ cargo new rusty-mikan-os
実装とビルド
Rust で UEFI のハローワールド - 借り初めのひみつきち を参考に実装していく。
Cargo.tomlの修正
uefiの依存を追加
[dependencies] uefi = "0.24"
.cargo/config.tomlの修正
ゼロからのOS自作入門 in Rust /ブートローダまで を参考にして以下を記述。
- ビルドのターゲットを
x86_64-unknown-uefi
に - UEFIアプリケーションを動作させる際はstdを利用できないため、必要なクレートを明示
- coreクレートに必要な
memcpy
などをcompiler-builtins-mem
から利用するように指定
[unstable] build-std = ["core", "compiler_builtins"] build-std-features = ["compiler-builtins-mem"] [build] target = "x86_64-unknown-uefi"
rust-toolchain.tomlの修正
nightlyでビルドされるように以下の記述を追加
[toolchain] channel = "nightly"
main.rsの実装
ここの実装も Rust で UEFI のハローワールド - 借り初めのひみつきち を参考にした。
#![feature(abi_efiapi)]
はこの記事を書いている時点では指定は不要になっていた。
#![no_std] #![no_main] use uefi::prelude::*; use core::panic::PanicInfo; use core::fmt::Write; #[panic_handler] fn panic(_info: &PanicInfo) -> ! { loop {} } #[entry] fn efi_main(_handle: Handle, mut st: SystemTable<Boot>) -> Status { writeln!(st.stdout(), "Hello, world!").unwrap(); loop {} // Status::SUCCESS }
以下は記述に対する覚え書き
#![no_std]
- 通常のライブラリを利用しないベアメタル環境向けという指定
#![no_main]
- 通常のmain関数から始まらないという指定
use uefi::prelude::*;
- uerf-rsの読み込み
use core::panic::PanicInfo;
- 通常はstdの中でpanicが定義されているが、
no_std
を指定しているので定義が必要 #[panic_handler]
で定義したpanic関数が呼び出される- とりあえず現時点では無限にloopするだけ
- 通常はstdの中でpanicが定義されているが、
#[entry]
no_main
を指定してるのでエントリポイントを指定している
st: SystemTable<Boot>
- UEFIが提供するサービスにアクセスするためのシステムテーブル
ビルド
ここまでの記述をしていれば、以下のコマンドでビルドできる。
$ cargo build --release
imageを作成してQEMUで動作させる
必要なものをインストール
QEMUは手元でビルドなどはせず、brewで落ちてくるものを利用した。
fatのファイルシステム作成のために dosfstools
も合わせてインストールする。
$ brew install qemu $ brew install dosfstools
また、後続の作業のために GitHub - uchan-nos/mikanos-build: Build and run scripts for MikanOS を手元に用意しておく。
devenv配下にある、OVMF_CODE.fd
と OVMF_VARS.fd
を後の工程で利用する。
imageの作成
新規のイメージを作成してfatでフォーマットする
$ qemu-img create -f raw disk.img 200M $ mkfs.fat -n 'MIKAN OS' -s 2 -f 2 -R 32 -F 32 disk.img
作成したEFIをimage内に配置する
rootに作成された /EFI/BOOT
の下に BOOTX64.EFI
というファイルがあると、起動時に認識して呼び出してくれる。
image内にディレクトリを作成して、EFIファイルを配置する。
$ hdiutil attach disk.img $ mkdir -p /Volumes/MIKAN\ OS/EFI/BOOT $ cp target/x86_64-unknown-uefi/release/rusty-mikan-os.efi /Volumes/MIKAN\ OS/EFI/BOOT/BOOTX64.EFI $ hdiutil detach /Volumes/MIKAN\ OS
作成したimageを起動する
前の工程で取得したOVMF_CODE.fd
と OVMF_VARS.fd
を指定して、作成したimageを起動する
$ qemu-system-x86_64 \ -drive if=pflash,format=raw,file=$HOME/ghq/github.com/uchan-nos/mikanos-build/devenv/OVMF_CODE.fd \ -drive if=pflash,format=raw,file=$HOME/ghq/github.com/uchan-nos/mikanos-build/devenv/OVMF_VARS.fd \ -hda disk.img
以下のような画面が出れば成功
ビルドからimageの起動までをshellにまとめる
都度実行するのも大変なので以下のファイルにまとめた
rusty-mikan-os/qemu_run.sh at d175d8d600a0255e8f6224483c5f73a6951a10ca · beatdjam/rusty-mikan-os · GitHub