ラズパイ3B とラズパイ3B+ が止まったままで、何かに使えないかと思いつつ、 ディスクアクセスが遅いので、 SD カードを read-only で使う用途はどうかと思っています。 そこで、実機で試す前に Raspberry Pi OS を qemu で動かして read-only の挙動を確認することにしました。

動作確認バージョン

  • qemu 9.2.2
  • Raspberry Pi OS (64-bit)
    • Raspberry Pi OS Lite
    • Release date: November 19th 2024
    • Kernel version: 6.6
    • Debian version: 12 (bookworm)
    • Size: 438MB

ダウンロード

「Raspberry Pi OS」で検索して、 https://www.raspberrypi.com/software/ から「See all download options」と辿って https://www.raspberrypi.com/software/operating-systems/ に一覧があったので、そこから 64-bit の Raspberry Pi OS Lite をダウンロードしました。

カーネルなどを取り出し

Linux 上では頑張ってループバックマウントして取り出す方法もありますが、 macOS でも使える方法として、 p7zip でディスクイメージファイルをアーカイブファイルとして扱って取り出しました。

unxz 2024-11-19-raspios-bookworm-arm64-lite.img.xz
7z l 2024-11-19-raspios-bookworm-arm64-lite.img
7z x 2024-11-19-raspios-bookworm-arm64-lite.img 0.fat
7z l 0.fat
7z x 0.fat bcm2710-rpi-3-b.dtb cmdline.txt config.txt kernel8.img initramfs8

パーティションが 0.fat1.img というファイルとして見えるので、 起動に使われる 0.fat の方を取り出して、 さらにその中からカーネルなどを取り出しました。

ディスクの拡張

qemu-img create -b 2024-11-19-raspios-bookworm-arm64-lite.img -F raw -f qcow2 diff.qcow2 8G で差分ディスクを作成しても良かったのですが、 p7zip でのファイル取り出しが難しくなるので、 コピーしてリサイズすることにしました。

cp 2024-11-19-raspios-bookworm-arm64-lite.img disk.img
qemu-img resize disk.img 8G

リサイズ後は 8G の SDHC カードに書き込んだ状態に相当すると思います。

初回起動

cmdline.txt の内容を確認すると init=firstboot になっていて、 初回起動用の特別処理がありそうとわかります。

% cat cmdline.txt
console=serial0,115200 console=tty1 root=PARTUUID=8a438930-02 rootfstype=ext4 fsck.repair=yes rootwait quiet init=/usr/lib/raspberrypi-sys-mods/firstboot

cmdline.txt の内容を使って初回起動します。

PARTUUID は変化に合わせて指定するのは大変なのと、 qemu の引数でデバイスは固定なので、 root=/dev/mmcblk0p2 に書き換えて使います。

その他のオプションは、 Raspberry Pi OS 64-bit を qemu 7.2.0 で動作させる | hiroの長い長い冒険日記qemu のオプションについて などを参考にしています。

qemu-system-aarch64 -m 1024 -M raspi3b -kernel kernel8.img -initrd initramfs8 -dtb bcm2710-rpi-3-b.dtb -drive file=disk.img,format=raw -append "console=serial0,115200 console=tty1 root=/dev/mmcblk0p2 rootfstype=ext4 fsck.repair=yes rootwait quiet init=/usr/lib/raspberrypi-sys-mods/firstboot" -serial stdio -no-reboot -device usb-kbd -device usb-tablet -device usb-net,netdev=net0 -netdev user,id=net0,hostfwd=tcp::2222-:22

パーティションのリサイズと SSH ホスト鍵の自動生成などが実行されていました。

通常の起動

初回起動前と同様にファイルを取り出すと、 PARTUUID が変化して、 quietinit= の指定が削除されていました。

% cat cmdline.txt
console=serial0,115200 console=tty1 root=PARTUUID=071b9753-02 rootfstype=ext4 fsck.repair=yes rootwait

初回起動と同様に root= の指定は変更しています。

コンソールのサイズを変更するために bcm2708_fb.fbwidth=1280 bcm2708_fb.fbheight=768 を追加しました。

qemu-system-aarch64 -m 1024 -M raspi3b -kernel kernel8.img -initrd initramfs8 -dtb bcm2710-rpi-3-b.dtb -drive file=disk.img,format=raw -append "console=serial0,115200 console=tty1 root=/dev/mmcblk0p2 rootfstype=ext4 fsck.repair=yes rootwait bcm2708_fb.fbwidth=1280 bcm2708_fb.fbheight=768" -serial stdio -no-reboot -device usb-kbd -device usb-tablet -device usb-net,netdev=net0 -netdev user,id=net0,hostfwd=tcp::2222-:22

-no-reboot を指定しているので、 自動で再起動するときに終了します。

2回目の起動

通常起動の初回(全体の2回目の起動)は、 キーボードの設定とユーザーの作成がありました。 昔の Raspbian で最初から作成されていた pi ユーザーは存在しないようです。

ssh 接続

sudo raspi-config3 Interface OptionsI1 SSH で有効にすると ssh -p 2222 ${作成したユーザー}@localhostssh -p 2222 -l ${作成したユーザー} localhost で接続できるようになります。

read only 化

sudo raspi-config4 Performance OptionsP2 Overlay File System で overlay file system を Yes にすると overlayroot パッケージが追加インストールされて initramfs (/boot/firmwareinitramfs8initramfs_2712) が更新されて、 cmdline.txt の先頭に overlayroot=tmpfs が追加されていました。

initramfs8 が更新されているので、 p7zip で取り出して、 それに合わせて qemu-system-aarch64 -m 1024 -M raspi3b -kernel kernel8.img -initrd initramfs8 -dtb bcm2710-rpi-3-b.dtb -drive file=disk.img,format=raw -append "overlayroot=tmpfs console=serial0,115200 console=tty1 root=/dev/mmcblk0p2 rootfstype=ext4 fsck.repair=yes rootwait bcm2708_fb.fbwidth=1280 bcm2708_fb.fbheight=768" -serial stdio -no-reboot -device usb-kbd -device usb-tablet -device usb-net,netdev=net0 -netdev user,id=net0,hostfwd=tcp::2222-:22 のように overlayroot=tmpfs を追加して起動して、 df などで確認すると /overlayroot になっていました。

boot partition の write-protected を Yes にすると、 /etc/fstab/boot/firmware の行の defaultsdefaults,ro に変わっていました。

/ の overlay 化と boot partition の write-protected は独立して設定できましたが、 overlay を Yes にして起動している状態だと、 /etc/fstab の書き換えが再起動時に反映できないので、 boot partition の write-protected は変更できませんでした。 そのため、一気に両方有効にした状態から戻すには、 overlay を No にして再起動した後、 boot partition の write-protected を No にする必要がありました。

まとめ

qemuraspi3b の動作確認ができました。

そして overlayroot などの read-only にする仕組みも確認できました。

overlayrootでUbuntuを一時的に読み込み専用にする によると overlayroot はもっと色々な機能があるようなので、 変更は USB マスストレージに保存するようにして SD カードは読み込み専用のまま書き込み内容も保存する、ということもできそうです。

Disqus Comments

Kazuhiro NISHIYAMA

Ruby のコミッターとかやってます。 フルスタックエンジニア(って何?)かもしれません。 About znzに主なアカウントをまとめました。

znz znz


Published