RISC-V用ベアメタルHelloWorldをEDK2でbuildし、QEMU上で実行する
更新ログ
- 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を当てる。
個人用 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
に追記する。
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アプリケーションを実行できる。
※文字表示がおかしいのはUEFI shellなのか、QEMUなのか、ターミナル(Alacritty)なのか、切り分け未実施。
やってみて感想
いろいろと情報が分散していて、これまでで一番苦労した「Hello World表示」でした。
それだけに、文字表示だけでも感動ものでした。これは体験した人にしか伝わらないかも。
同時に、各種プログラミング言語開発環境にチュートリアルがあることがどんなに有難いことなのか実感しました。
OS自作本の内容を今後はこの環境で進めていこうと思います。
描画関連は無理っぽいですが、USB関連とか、ファイルシステム回りの理解を深められることを期待。
まだ分からないこと
- UEFIの仕様全般。詳細は追々理解していこう(kernel loader作ったら見なくなる気もするが。。)。
reference
- 作って学ぶコンピュータアーキテクチャ(LLVM本)
- ゼロからのOS自作入門(OS自作本)
- riscv-collab/riscv-gnu-toolchain
- riscv-collab/riscv-edk2-platforms
- riscv-collab/riscv-edk2
- qemu-project/qemu
以下は本論には登場しないが参考にした本(すべて技術書典で購入)
-
ほんのり詳しいUEFI BIOS
※UEFIについて日本語でざっくり解説してくれる貴重な本。ぜひ理解のお供に。 - フルスクラッチで作る!UEFIベアメタルプログラミング
- フルスクラッチで作る!UEFIベアメタルプログラミング パート2
- DragonUniversity 2020.3
- Gitのサブモジュールで困ったら読む本
Discussion