NetBSD Advent Calendar 2020 5日目の記事です。
今日はNetBSD-9.0で追加された、mount_qemufwcfg(8)コマンドの紹介をしようと思います。
NetBSD-9.0のリリースアナウンス(Announcing NetBSD 9.0 (Feb 14, 2020))を見ると、"support for the QEMU firmware configuration device"という一文があります。これに対応する機能が今日紹介するmount_qemufwcfg(8)のようです。
Improvements for using NetBSD as a guest OS, with support for the QEMU firmware configuration device, ...
mount_qemufwcfgとQEMU fw configuration file
QEMUにはQEMU fw_cfg(QEMU firmware configuration)という、ゲストOS側に対してBootの順番やACPIやSMBIOSテーブル、仮想マシンに割り振るUUID、SMPやNUMA情報といったデータをホストOS側から提供するためのインタフェースが提供されています。
NetBSD-9.0で追加された、mount_qemufwcfg(8)は、このQEMU fw_cfgデータを仮想ファイルシステム経由でmountして参照可能にするコマンドになります。
ホストOS側でのqemu起動オプション
さっそく順を追って試してみましょう。mount_qemufwcfg(8)はゲストOS側のNetBSDで実行するため、まずはホストOS側でqemuを起動します。起動時に -fw_cfg name=<NAME>,file=<FILE>
のような形で必要なデータをゲストOS側に渡します。
name=...
で指定した内容がゲストOS側での参照パスになります。 opt/...
から始まるパスがユーザ用に予約されているため(※)、この例では opt/com.mycompany/blob
というパスを指定しています。
※ QEMU fw cfgでは以下のように記載されています。
Names that begin with "opt/" are reserved for users.
そして file=...
には参照させるファイルを指定します。この例では"Hello,World."というテキストが書かれたファイルを渡しています。
$ echo 'Hello,World.' > my_blob.bin
$ qemu-system-x86_64 \
-m 512M \
-boot order=c \
-net nic \
-net user,hostfwd=tcp::2222-:22 \
-fw_cfg name=opt/com.mycompany/blob,file=./my_blob.bin \
-snapshot \
-hdd nbsd.img
mount_qemucfgを使用する
必要な準備
ゲストOSが起動したらmount_qemufwcfg(8)を試してみたいところですが、いくつか準備が必要です。
/usr/src/sbin/mount_qemufwcfg/fwcfg.cのソースコードを見ると、 /dev/qemufwcfg
を参照するようです。
#define _PATH_FWCFG "/dev/qemufwcfg"
ゲストOS側のNetBSDでデバイスノードを作成するため、 mknod -l
で qemufwcfg
のmajorデバイス番号を確認します。
$ mknod -l | grep qemufwcfg
qemufwcfg character major 342
mknod qemufwcfg c 342 0
で qemufwcfg
のデバイスノードを作成します。
$ cd /dev
$ sudo mknod qemufwcfg c 342 0
$ ls -l /dev/qemufwcfg
crw-r--r-- 1 root wheel 342, 0 Dec 4 10:21 /dev/qemufwcfg
mount_qemufwcfg(8)でfw_cfgデータを参照する
これでmount_qemufwcfg(8)を使用してfw_cfgデータをマウントできます。この例では /mnt
をマウントポイントにしています。
$ sudo mount_qemufwcfg /mnt
どうやらPUFFS(NetBSDのユーザランド上でファイルシステムを実現する機能)を利用しているようですね。
PUFFSについては、過去のNetBSD Advent Calendarにて紹介していますので併せてご参照ください。
$ df -h
Filesystem Size Used Avail %Cap Mounted on
...
/dev/puffs 0B 0B 0B 100% /mnt
マウントしたディレクトリ以下では色々なデータが参照できる状態になっています。今回は -fw_cfg
オプションで渡した /mnt/opt/com.mycompany/blob
を見てみます。
$ find /mnt -type f | xargs file
/mnt/bios-geometry: empty
/mnt/bootorder: empty
/mnt/etc/acpi/rsdp: data
/mnt/etc/acpi/tables: data
/mnt/etc/boot-fail-wait: ISO-8859 text, with no line terminators
/mnt/etc/e820: data
/mnt/etc/smbios/smbios-anchor: data
/mnt/etc/smbios/smbios-tables: SVr2 curses screen image, big-endian
/mnt/etc/system-states: lif file
/mnt/etc/table-loader: data
/mnt/etc/tpm/log: empty
/mnt/genroms/kvmvapic.bin: BIOS (ia32) ROM Ext. (18*512)
/mnt/opt/com.mycompany/blob: UTF-8 Unicode text
ファイルの中身を見てみると、ホストOS側で指定したファイルが参照できています!
ただし、ゲストOS起動後にホストOS側がファイルの中身を変更してもゲストOS側のファイルには変更が反映されず、どうやらゲストOS起動時点ででのファイルの中身が常に参照されるという挙動になっています。
$ cat /mnt/opt/com.mycompany/blob
Hello,World.
まとめ
NetBSD 9.0で追加されたmount_qemufwcfg(8)コマンドを試してみました。ホストOS側からファイルを渡すことができるため、ゲストOS起動時にssh鍵やクレデンシャル情報等を渡すといった柔軟な応用ができそうです。