はじめに
久々にベアメタル熱が上がってきた。 メガマニュアルには下記のような記述があり、baremetalのビルドができそう。
TCLIBC Specifies the GNU standard C library (libc) variant to use during the build process. You can select “glibc”, “musl”, “newlib”, or “baremetal”.
OpenEmbedded-Coreにはbaremetal-helloworldというレシピが存在する。 この大本となるリポジトリには下記のようにビルド手順が示されており、上記の機能を使用しているようだ。
$ echo "MACHINE = \"qemuarm64\"" >> ./conf/local.conf $ echo "TCLIBC = \"baremetal\"" >> ./conf/local.conf
このビルド手順はScarthgap以前(具体的にはdunfell or kirkstoneの時代)のものなので、今回はwrynose環境でビルドしてみる。
環境構築
作業ディレクトリ
~/yocto/wrynoseを作業ディレクトリとする。
$ mkdir -p ~/yocto/wrynose $ cd ~/yocto/wrynose
bitbakeリポジトリの取得
bitbake-setupを実行するためにbitbakeのリポジトリを取得する。
$ git clone https://git.openembedded.org/bitbake -b yocto-6.0
作業環境を構築する
bitbake-setup initを実行して作業環境(=セットアップ)を作成する。
top-dir-nameを「yocto-builds」に変更する。
setup-dir-nameを「poky-wrynose-baremetal」に設定する。
$ ./bitbake/bin/bitbake-setup \
--setting default top-dir-name "yocto-builds" \
init --non-interactive poky-wrynose poky distro/poky machine/qemuarm \
--setup-dir-name poky-wrynose-baremetal
BitBake環境を設定する
init-build-envを実行する。
$ source yocto-builds/poky-wrynose-baremetal/build/init-build-env
local.confの修正
conf/local.confに以下の内容を記述する。
TCLIBC = "baremetal"
ビルド
$ bitbake baremetal-helloworld
動作確認
世界に挨拶した。
$ runqemu nographic nonetwork runqemu - INFO - Running bitbake -e ... runqemu - INFO - Continuing with the following parameters: KERNEL: [/home/mickey/yocto/wrynose/yocto-builds/poky-wrynose-baremetal/build/tmp/deploy/images/qemuarm/baremetal-helloworld-image-qemuarm.bin] MACHINE: [qemuarm] FSTYPE: [bin] ROOTFS: [/home/mickey/yocto/wrynose/yocto-builds/poky-wrynose-baremetal/build/tmp/deploy/images/qemuarm/baremetal-helloworld-image-qemuarm.bin] Disabled. Changes on rootfs will be kept after QEMU shutdown. CONFFILE: [/home/mickey/yocto/wrynose/yocto-builds/poky-wrynose-baremetal/build/tmp/deploy/images/qemuarm/baremetal-helloworld-image-qemuarm-20260801075737.qemuboot.conf] runqemu - INFO - Running /home/mickey/yocto/wrynose/yocto-builds/poky-wrynose-baremetal/build/tmp/work/x86_64-linux/qemu-helper-native/1.0/recipe-sysroot-native/usr/bin/qemu-system-arm -nic none -object rng-random,filename=/dev/urandom,id=rng0 -device virtio-rng-pci,rng=rng0 -drive id=disk0,file=/home/mickey/yocto/wrynose/yocto-builds/poky-wrynose-baremetal/build/tmp/deploy/images/qemuarm/baremetal-helloworld-image-qemuarm.bin,if=none,format=raw -device virtio-blk-device,drive=disk0 -device qemu-xhci -device usb-tablet -device usb-kbd -nographic -machine virt,highmem=off -cpu cortex-a15 -smp 4 -m 256 -serial mon:stdio -serial null -nographic -device virtio-gpu-pci -kernel /home/mickey/yocto/wrynose/yocto-builds/poky-wrynose-baremetal/build/tmp/deploy/images/qemuarm/baremetal-helloworld-image-qemuarm.bin -append 'root=/dev/vda rw mem=256M console=ttyAMA0 console=hvc0 swiotlb=0 ' runqemu - INFO - Host uptime: 603285.94 Hello OpenEmbedded on ARM!
レシピ
このレシピはOpenEmbedded-Coreで提供しているQEMU関連のマシン全てに対応している。
実際にレシピを読むとわかるが、マシンでのオーバーライドがたくさん記述されている。
baremetal-helloworld_git.bb
今回はqemuarmのマシンを設定しているので関連する部分だけ抜粋する
... (snip) ... 7 SRCREV = "db2bf750eaef7fc0832e13ada8291343bbcc3afe" 8 PV = "0.1+git" 9 10 SRC_URI = "git://github.com/ahcbb6/baremetal-helloqemu.git;protocol=https;branch=master" 11 UPSTREAM_CHECK_COMMITS = "1" 12 13 # The following variables should be set to accomodate each application 14 BAREMETAL_BINNAME ?= "hello_baremetal_${MACHINE}" 15 IMAGE_LINK_NAME ?= "baremetal-helloworld-image-${MACHINE}" 16 IMAGE_NAME_SUFFIX ?= "" 17 18 # Baremetal-Image creates the proper wiring, assumes the output is provided in 19 # binary and ELF format, installed on ${base_libdir}/firmware/ , we want a 20 # package to be created since we might have some way of updating the baremetal 21 # firmware from Linux 22 inherit baremetal-image ... (snip) ... 27 # These parameters are app specific for this example 28 # This will be translated automatically to the architecture and 29 # machine that QEMU uses on OE, e.g. -machine virt -cpu cortex-a57 30 # but the examples can also be run on other architectures/machines 31 # such as vexpress-a15 by overriding the setting on the machine.conf 32 COMPATIBLE_MACHINE = "qemuarmv5|qemuarm|qemuarm64|qemuriscv64|qemuriscv32|qemux86|qemux86-64" 33 ... (snip) ... 36 BAREMETAL_QEMUARCH:qemuarm = "arm" ... (snip) ... 43 EXTRA_OEMAKE:append = " QEMUARCH=${BAREMETAL_QEMUARCH} V=1" ... (snip) ... 50 # Install binaries on the proper location for baremetal-image to fetch and deploy 51 do_install(){ 52 install -d ${D}/${base_libdir}/firmware 53 install -m 755 ${B}/build/hello_baremetal_${BAREMETAL_QEMUARCH}.bin ${D}/${base_libdir}/firmware/${BAREMETAL_BINNAME}.bin 54 install -m 755 ${B}/build/hello_baremetal_${BAREMETAL_QEMUARCH}.elf ${D}/${base_libdir}/firmware/${BAREMETAL_BINNAME}.elf 55 } 56 57 FILES:${PN} += " \ 58 ${base_libdir}/firmware/${BAREMETAL_BINNAME}.bin \ 59 ${base_libdir}/firmware/${BAREMETAL_BINNAME}.elf \ 60 " ... (snip) ...
重要なポイントにはしっかりとコメントが記述されている。
最も重要なポイントとしては下記。
- 13〜16行目の変数の定義
- 22行目のbaremetal-imageクラスの継承
残りの部分はお約束の部分かアップストリームのソースコードの作りに依存する部分となる。
ただし、baremetal-imageクラスではbinとelfのバイナリが出力されるのを期待している。
baremetal-imageクラス
実装の詳細は省くが、やっていることは下記。
- binとelfをDEPLOY_DIR_IMAGEにコピー
- binを使ってrunqemuできるようにパラメータを調整
- imageクラスのタスク構成に準拠するように各種調整(image.bbclassの継承はしていない)
ベアメタルをやっていく上では1の機能が一番重要。 LinuxのカーネルやルートFSを作らずに、OpenEmbedded-Coreの仕掛けの上でbinとelfをDEPLOY_DIR_IMAGEに出力してくれるのは助かる。
まとめ
baremetal-imageクラスを使えばYocto Project環境でもベアメタルができることがわかった。 ツールチェーンを自前で用意しなくても良いのはかなり楽。 bitbakeでベアメタルのbinとelfが出力されるようになるのは私としてはありがたい。
本来の目的であるベアメタル熱のためにbaremetal-helloworldの実際のプログラムについては今後触れる。


