みつきんのメモ

組み込みエンジニアです。Interface誌で「Yocto Projectではじめる 組み込みLinux開発入門」連載中

Yocto QEMUのストレージを拡張する(デバイス追加/wic)

はじめに

MACHINE="qemuarm64"などでイメージを作成すると、実機を用意しなくてもYoctoProjectを試せるので便利。 ただ、複数のパーティションを使用したり、ストレージを追加したい場合にぱっとやり方がわからない。 手順を調査したのでメモ。

今回は、ディスクイメージファイルを作成しqemuにデバイスを追加する方法とwicを使用してパーティションを追加する方法を記す。

環境構築

ソース取得

$ git clone git://git.yoctoproject.org/poky.git -b kirkstone

環境変数設定

source poky/oe-init-build-env

local.conf

下記の内容をconf/local.confに追加

MACHINE = "qemuarm64"

ビルド

$ bitbake core-image-minimal

qemuの起動

下記のコマンドでqemuを起動できる。

nographicを指定することで、端末の中で起動することができる。VMの出力はシリアルコンソールとして扱われる。 qemu上の文字列などをコピペしたいときなどは便利。

$ runqemu nographic

実際にqemuを起動するにはデバイス構成や、使用するカーネルなど様々な設定をコマンドラインで渡す必要がある。

bitbakeでqemuのイメージを作成するとbuild/tmp/deploy/images/qemuarm64/core-image-minimal-qemuarm64.qemuboot.confというファイルが一緒に生成される。

runqemuで特にオプションが指定されない場合は、このファイルにかかれている情報がqemuに渡されるようになっている。

qemuboot.confの中身

core-image-minimal-qemuarm64.qemuboot.confの内容を見てみる。

[config_bsp]
deploy_dir_image = .
image_link_name = core-image-minimal-qemuarm64
image_name = core-image-minimal-qemuarm64-20230811074446
kernel_imagetype = Image
machine = qemuarm64
qb_cmdline_ip_slirp = ip=dhcp
qb_cmdline_ip_tap = ip=192.168.7.@CLIENT@::192.168.7.@GATEWAY@:255.255.255.0::eth0:off:8.8.8.8
qb_cpu = -cpu cortex-a57
qb_cpu_kvm = -cpu host -machine gic-version=3
qb_default_fstype = ext4
qb_default_kernel = ${@bb.utils.contains("INITRAMFS_IMAGE_BUNDLE", "1", "Image-${INITRAMFS_LINK_NAME}.bin", "Image", d)}
qb_drive_type = /dev/sd
qb_graphics = -device virtio-gpu-pci
qb_machine = -machine virt
qb_mem = -m 256
qb_network_device = -device virtio-net-pci,netdev=net0,mac=@MAC@
qb_opt_append = -device qemu-xhci -device usb-tablet -device usb-kbd -echr 0x14
qb_rng = -object rng-random,filename=/dev/urandom,id=rng0 -device virtio-rng-pci,rng=rng0
qb_rootfs_extra_opt = 
qb_rootfs_opt = -drive id=disk0,file=@ROOTFS@,if=none,format=raw -device virtio-blk-pci,drive=disk0
qb_serial_opt = -device virtio-serial-pci -chardev null,id=virtcon -device virtconsole,chardev=virtcon
qb_smp = -smp 4
qb_system_name = qemu-system-aarch64
qb_tap_opt = -netdev tap,id=net0,ifname=@TAP@,script=no,downscript=no
qb_tcpserial_opt = -device virtio-serial-pci -chardev socket,id=virtcon,port=@PORT@,host=127.0.0.1 -device virtconsole,chardev=virtcon
serial_consoles = 115200;ttyAMA0 115200;hvc0
staging_bindir_native = ../../../work/x86_64-linux/qemu-helper-native/1.0-r1/recipe-sysroot-native/usr/bin
staging_dir_host = ../../../work/qemuarm64-poky-linux/core-image-minimal/1.0-r0/recipe-sysroot
staging_dir_native = ../../../work/qemuarm64-poky-linux/core-image-minimal/1.0-r0/recipe-sysroot-native
tune_arch = aarch64
uninative_loader = ../../../sysroots-uninative/x86_64-linux/lib/ld-linux-x86-64.so.2

メインとなるストレージを指定しているのは以下の部分

qb_rootfs_opt = -drive id=disk0,file=@ROOTFS@,if=none,format=raw -device virtio-blk-pci,drive=disk0

ディスクドライブの指定方法はこれを参考にすれば良さそう。

ストレージの追加を試みる

ディスクイメージファイルの作成

下記のコマンドを実行し、${DEPLOY_DIR_IMAGE}の変数が指す場所にディスクイメージとなるファイルを作成する。

$ pushd ./tmp/deploy/images/qemuarm64/
$ fallocate -l 1G disk.img

qemuboot.confの直接編集

core-image-base-qemuarm64.qemuboot.confの内容を修正しディスクを追加する。 ディスク指定は汎用的なオプション追加のためのqb_opt_appendで行う。

qb_opt_append = -drive id=disk1,file=@DEPLOY_DIR_IMAGE@/disk.img,if=none,format=raw -device virtio-blk-pci,drive=disk1

runqemuではqb_opt_appendを処理する際に「@DEPLOY_DIR_IMAGE@」を見つけると、 bitbakeで参照される${DEPLOY_DIR_IMAGE}が指すディレクトリのパスに置き換えるようになっている。

qemuを起動し、/dev/vdbが認識されていればストレージの追加は成功となる。

$ runqemu nographic
root@qemuarm64:~# ls /dev/vd*
/dev/vda  /dev/vdb

ただし、ストレージデバイスが追加されただけなので、ファイルシステムの作成(mkfs)やマウントなどは手動で行う必要がある。

また、この方法では次回bitbake実行時にこの内容は破棄されてしまう。

local.confでの設定

ディスクイメージファイルを作成した状態でlocal.confに下記の内容を記載する。

QB_OPT_APPEND:append = " -drive id=disk1,file=@DEPLOY_DIR_IMAGE@/disk.img,if=none,format=raw -device virtio-blk-pci,drive=disk1"

これでbitbakeをするたびに追加したストレージが認識しなくなることは避けられる。

qemuでwicを使用する

ストレージを追加する方法では、以下のことを自分で行う必要がある。

これは意外と面倒な作業となる。

ディスクイメージを追加することにこだわらずにパーティションを追加するだけであればwicを使用する方法もある。 この場合、qemu上で/dev/vdbは存在しないが、/dev/vdaがパーティション分割された状態で認識されるようになる。

作業用レイヤの作成

下記のコマンドで作業用レイヤを作成する。

$ bitbake-layers create-layer ./meta-wic-work
$ bitbake-layers add-layer ./meta-wic-work

wksファイルの作成

下記のコマンドでwksの格納場所を作成する。

$ mkdir ./meta-wic-work/wic

meta-wic-work/wic/qemu-wic.wksを下記の内容で作成する。

part / --source rootfs --ondisk vda --fstype=ext4 --label platform --align 1024
part /opt --fstype=ext4 --ondisk vda --label opt --fixed-size=1G

bbclassファイルの作成

qemuqemu-wic.wksを参照し、wicイメージを出力するための設定と、ルートFS上に/optディレクトリを作成する、qemu-wic.bbclassを作成する。

下記のコマンドでbbclassの格納場所を作成する。

$ mkdir ./meta-wic-work/classes

meta-wic-work/classes/qemu-wic.bbclassを下記の内容で作成する。

ROOTFS_POSTPROCESS_COMMAND += "create_opt_dir;"

QB_FSINFO = "wic:no-kernel-in-fs"
QB_KERNEL_ROOT = "/dev/vda1"
QB_DEFAULT_FSTYPE = "wic"
WKS_FILE = "qemu-wic.wks"
IMAGE_FSTYPES += "wic"

create_opt_dir() {
    mkdir ${IMAGE_ROOTFS}/opt
}

local.confの修正

local.confに下記の内容を追加する。

INHERIT += "qemu-wic"

また、QB_OPT_APPEND:appendの行は不要なので削除する。

イメージのビルド及び動作確認

下記コマンドでイメージをビルドしなおす。

$ bitbake core-image-minimal -c cleansstate
$ bitbake core-image-minimal

動作確認

$ runqemu nographic

qemu上で下記を実行し/dev/vda2/optとしてマウントされていることを確認する。

root@qemuarm64:~# mount
/dev/root on / type ext4 (rw,relatime)
devtmpfs on /dev type devtmpfs (rw,relatime,size=116500k,nr_inodes=29125,mode=755)
proc on /proc type proc (rw,relatime)
sysfs on /sys type sysfs (rw,relatime)
debugfs on /sys/kernel/debug type debugfs (rw,relatime)
tmpfs on /run type tmpfs (rw,nosuid,nodev,mode=755)
tmpfs on /var/volatile type tmpfs (rw,relatime)
/dev/vda2 on /opt type ext4 (rw,relatime)
devpts on /dev/pts type devpts (rw,relatime,gid=5,mode=620,ptmxmode=000)

ついでにqemu上の/etc/fstabの内容も確認する。

root@qemuarm64:~# cat /etc/fstab 
# stock fstab - you probably want to override this with a machine specific one

/dev/root            /                    auto       defaults              1  1
proc                 /proc                proc       defaults              0  0
devpts               /dev/pts             devpts     mode=0620,ptmxmode=0666,gid=5      0  0
tmpfs                /run                 tmpfs      mode=0755,nodev,nosuid,strictatime 0  0
tmpfs                /var/volatile        tmpfs      defaults              0  0

# uncomment this if your device has a SD/MMC/Transflash slot
#/dev/mmcblk0p1       /media/card          auto       defaults,sync,noauto  0  0

/dev/vda2   /opt    ext4    defaults    0   0

まとめ

今回は、下記の2つの方法でqemuのストレージを拡張する方法を調べた。

どうしてもディスクデバイスを増やしたい理由がなければwicを使用してパーティションを追加する方法が手軽。 さりげにbbclassの作成方法にも軽く触れておいたので参考になれば。