📘

RISC-V用ベアメタルHelloWorldをEDK2でbuildし、QEMU上で実行する

2022/07/31に公開約6,200字

更新ログ

  • 2022/Jul/31 新規エントリ

このエントリで言いたいこと

UEFIアプリケーション開発キットEDK2を使ってRISC-Vのベアメタル環境を構築し、
エミュレータQEMU上で実行できるまでの手順を残す。

環境

  • MSI Trdent 3 Arctic 10SI-049JP
    プロセッサ:Intel Core i7-10700F CPU @2.90GHz
    メモリ:16 GB DDR4-2666
  • Windows10Pro (バージョン21H2)
  • WSL2 (Ubuntu 20.04)

本論

きっかけ

最近作って学ぶコンピュータアーキテクチャ(LLVM本)を購入した。
RISC-Vの命令セットへ変換を行うLLVM backendを自作していく本だ。
一方、ゼロからのOS自作入門(OS自作本)を以前購入したまま、途中で読むのを挫折していた。
どちらも低レイヤの内容を扱っているので、せっかくだからRISC-VアーキテクチャでOS自作したら面白そう、と考えて手をつけてみた。
※本記事ではまだOS作成には着手していない。

フォルダ構成

riscv-collab
├── Build/
├── disk.img
├── mnt/
├── riscv-edk2/
├── riscv-edk2-platforms/
│    └──Platform/
│       └──ak2ume/
│          └─── RiscvVirt/ 
└── riscv-gnu-toolchain/

ビルド手順

このあたりに「master branchに統合されているSiFive社のデバイス環境をQEMUで実現してLinux Kernelをbootできるよ」と書いてあるが、実はソースコードが足りず途中で頓挫する(した)。
GitHub issue上では解決しているため、このissueに沿って環境構築する。

RISC-V対応GNU toolchainのビルド

riscv-collab/riscv-gnu-toolchain をclone
buildに必要なpackageをinstall

$ sudo apt-get install autoconf automake autotools-dev curl python3 libmpc-dev libmpfr-dev libgmp-dev gawk build-essential bison flex texinfo gperf libtool patchutils bc zlib1g-dev libexpat-dev

Newlib で install する。(bare metal開発ではlinuxは使わないはず)
install先(/opt/riscv)を環境変数PATHに加えておく。

EDK2 platformの準備

riscv-collab/riscv-edk2-platforms をclone
WORKSPACE, PACKGES_PATHをexportしておく。
Manual buildingに沿ってshell実行

$ . ./riscv-edk2/edksetup.sh

※fish shellではshell実行に失敗するため、一時的にbashに戻って実行した。
edk2 Build Target の注意点に従って環境変数 GCC5_RISCV64_PREFIX を設定する。
今回の場合は /opt/riscv/bin/riscv64-unknown-elf-
riscv-vert-gh-actions branchに切り替える。
※submodule の更新(git submodule update --recursive)もお忘れなく。
UsbUtility.c/.h でビルドエラーするので、2021/12にupstreamに当たった下記patchを当てる。

https://github.com/tianocore/edk2/commit/ae8272ef787d80950803c521a13a308651bdc62e

個人用 platform の作成

riscv-edk2-platforms 配下にQEMU用仮想デバイスplatform (Platform/Qemu/RiscvVirt) があるため、個人用にコピーする。
自分の場合、Platform/ak2ume を作成して、配下にコピー。

EDK2でUEFIアプリケーション(HelloWorld表示)をビルド

riscv-collab/riscv-edk2 をcloneする。
riscv-virt-540-mod branchにcheckoutする。
※submodule の更新(git submodule update --recursive)もお忘れなく。
HelloWorld表示アプリケーションコードが MdeModulePkg/Application/HelloWorld にすでに作成されているため、↑で作成した個人用 platorm のRiscvVirt.dscに追記する。

RiscvVirt.dsc
  MdeModulePkg/Application/HelloWorld/HelloWorld.inf

ターゲットを指定してbuild実行

$ build -a RISCV64 -p Platform/ak2ume/RiscvVirt/RiscvVirt.dsc -t GCC5

build成功すると、Buildフォルダ配下に成果物が保存される。

UEFIアプリケーション組み込みディスクイメージを作成

UEFI shellが認識できるディスクイメージを作成し、そこにHelloWorldのEFIファイルを格納する。
初回のみディスクイメージを新規作成する。
※パラメータは吟味せず、とりあえずOS自作本で実施していたコマンドそのまま。

$ mkfs.fat -n "zero OS" -s 2 -f 2 -R 32 -F 32 disk.img

一度ディスクイメージを作成したら、2回目以降はマウントしてファイルを書き換えるのみでOK。

$ sudo mount -o loop disk.img mnt/
$ sudo cp Build/RiscvVirt/DEBUG_GCC5/RISCV64/HelloWorld.efi mnt/HelloWorld.efi
$ sudo umount mnt

RISC-V対応QEMUのビルド

qemu-project/qemu をcloneし、stable-6.1 に checkout
※submodule の更新(git submodule update --recursive)もお忘れなく。
buildに必要そうなパッケージをinstall

$ sudo apt-get install libc6-dev pkg-config bridge-utils zlib1g-dev libglib2.0-dev autoconf automake libtool libsdl1.2-dev libpixman-1-dev cmake

参考 https://www.hirotakaster.com/weblog/risc-v-qemuで色々と動かす/
ビルド実行

$ ./configure --target-list=riscv64-softmmu --with-git-submodules=validate
  ※install時に git submodule の更新で怒られるので一時的に submodule 更新をdisable
$ make -j$(nproc)
$ sudo make install

pathが通っていること & バージョンを確認

$ qemu-system-riscv64 --version

QEMUで実行

$ qemu-system-riscv64 -machine virt -bios ./Build/RiscvVirt/DEBUG_GCC5/FV/RISCVVIRT.fd -device virtio-blk-device,drive=hd0 -drive file=./disk.img,format=raw,id=hd0 -m 4096 -smp cpus=2,maxcpus=2 -nographic

まずUEFI shellが起動する。

> map -r

でディスクイメージ(fs0)が見えるはず。

> fs0:

でディスクイメージ内に入り、

> HelloWorld.efi

でUEFIアプリケーションを実行できる。

QEMU画面
※文字表示がおかしいのはUEFI shellなのか、QEMUなのか、ターミナル(Alacritty)なのか、切り分け未実施。

やってみて感想

いろいろと情報が分散していて、これまでで一番苦労した「Hello World表示」でした。
それだけに、文字表示だけでも感動ものでした。これは体験した人にしか伝わらないかも。
同時に、各種プログラミング言語開発環境にチュートリアルがあることがどんなに有難いことなのか実感しました。
OS自作本の内容を今後はこの環境で進めていこうと思います。
描画関連は無理っぽいですが、USB関連とか、ファイルシステム回りの理解を深められることを期待。

まだ分からないこと

  • UEFIの仕様全般。詳細は追々理解していこう(kernel loader作ったら見なくなる気もするが。。)。

reference

以下は本論には登場しないが参考にした本(すべて技術書典で購入)

Discussion

ログインするとコメントできます