🍓

Apple Silicon Macでvagrantを使って32-bit Raspberry Pi OSイメージをカスタマイズする

2024/12/02に公開

この記事はUMITRON Advent Calendar 2024 2日目の記事です。

まえがき

弊社で生産しているIoTプロダクトの一部にRaspberry Piを用いています。このプロダクトを出荷する前にRaspberry PiのSDカードにRaspberry Pi OSのイメージを書き込みするのですが、当然弊社のソフトウェアや依存のインストール、必要な設定等を行う必要があります。事前にこれらのインストール・設定を行なったカスタムイメージを準備した上でそれを書き込みする、ということを行っています。弊社では開発機としてMacを用いてるのですが、案外Macを用いているとこの作業が一筋縄ではいきません。

Raspberry Pi OSイメージはパーティションが2つあり、bootパーティションがFAT32、rootパーティションがext4です。Macではネイティブでext4をマウントして書き込みすることが(無料で安全には)出来ませんし、仮に書き込みが出来たとしてもapt-get installしてソフトウェアのインストールを行うなどの複雑な操作がそのままでは出来ません。ext4はLinuxだと扱うことが出来るので、macOSの場合Linux VMを動かして、そのLinux VM上でRaspberry Pi OSイメージを扱った上で、chrootを実行することでやっと必要なソフトウェアのインストール等を行うことが出来るようになります。

これらの作業はIntel Mac時代はVirtualBox + vagrantで行っており問題なかったのですが、Apple Silicon Macに関してはVirtualBoxが長らくApple Silicon Macをサポートしておらず、同様の作業を行うことが出来ませんでした。2024年9月に待望の Apple Silicon Mac対応をしたVirtualBox 7.1がリリースされたのですが、筆者が試した限りだとまだVirtualBox + vagrantでRaspberry Pi OSを編集することはできませんでした。VirtualBox以外の選択肢としてVMware Fusionがあります。これは元々有料でしたが、2024年5月に個人利用において無料化、2024年11月には個人利用以外でも無料化されました。

そこでVMware Fusion + vagrantを試したところRaspberry Pi OSをマウントしてchrootしてカスタムイメージを作成することが出来たので、この記事で共有します。この記事では32-bit Raspberry Pi OSを対象とします。

本編

まずはVMware Fusionとvagrantをインストールします

VMware Fusionは以下から最新版をダウンロードしインストールします。ダウンロードにはユーザ登録とログインが必要になります。

vagrantは以下のリンクからarm64のインストーラをダウンロードし、インストールします。

次にVagrant VMware Utilityを以下からインストーラをダウンロードし、インストールします。

次にコマンドラインからVagrant VMware provider pluginをインストールします

vagrant plugin install vagrant-vmware-desktop

これで必要なソフトウェアのインストールが終わりました。

ここで次の作業に入る前に、今回やることとその課題、対策について説明します。今回やることは、Apple Silicon、つまりarm64のCPUで、arm64のLinux VMを動かし、32-bit Raspberry Pi OS、つまりarmv7のOSイメージをマウントし、chrootして必要な作業を行えるようにする、というものです。

調べたところarm64のLinuxはカーネルコンフィグのCONFIG_COMPATが有効になっていればarmv7の実行ファイルを通常実行できるらしいのですが、Apple Silicon Mac上で動かしたCONFIG_COMPATが有効なLinux VMではarmv7の実行ファイルが実行できませんでした。

で、archtectureの互換性のないOSイメージをchrootする場合は通常、binfmtとQEMUを使って、chroot対象OS側で実行される命令を親マシンのarchitectureの命令に自動で変換して実行します。このbinfmtの設定は binfmt-support package をインストールすると通常自動で有効になるはずなんですが、armv7は本来互換性があるからか自動で有効になりませんでした。ので、これを手動で有効にする必要があります。

ということを前提に、次にVagrantfileを作成します。

Vagrant boxにはbento/ubuntu-24.04を用います。また、必要なソフトウェアのインストールと、前述したbinfmtの設定をprovisionでやります。以下がそのVagrantfileです。

Vagrant.configure("2") do |config|
  config.vm.box = "bento/ubuntu-24.04"
  config.vm.provision "shell", inline: <<-SHELL
    apt-get update
    DEBIAN_FRONTEND=noninteractive apt-get install -y qemu-user-static binfmt-support
    # On Apple Silicon Mac, qemu-arm-static is not configured by default.
    echo ':qemu-arm:M::\\x7f\\x45\\x4c\\x46\\x01\\x01\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x02\\x00\\x28\\x00:\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\xfe\\xff\\xff\\xff:/usr/bin/qemu-arm-static:F' > /etc/binfmt.d/qemu-arm.conf
    systemctl restart systemd-binfmt
  SHELL
end

これでvagrant up, vagrant sshします。ここから先はVM内での作業になります。

vagrant up
vagrant ssh

次に以下から対象の32-bit Raspberry Pi OSをダウンロード・解凍します。今回は32-bit Raspberry Pi OS Liteを用います。

wget https://downloads.raspberrypi.com/raspios_lite_armhf/images/raspios_lite_armhf-2024-11-19/2024-11-19-raspios-bookworm-armhf-lite.img.xz
xz -d 2024-11-19-raspios-bookworm-armhf-lite.img.xz

まずこのイメージのパーティションをループバックデバイスに割り当てます。

vagrant@vagrant:~$ sudo losetup --find --show --partscan 2024-11-19-raspios-bookworm-armhf-lite.img
/dev/loop0

上記コマンドで表示されたパスが割り当てられたデバイスになります。

次にこれをmountします。/dev/loop0p2 がrootのパーティション、/dev/loop0p1 がbootパーティションになります。

mkdir -p mnt
sudo mount /dev/loop0p2 mnt
sudo mount /dev/loop0p1 mnt/boot

その他chrootした時にないと困りやすいディレクトリをmountします。

sudo mount --bind /dev mnt/dev
sudo mount --bind /sys mnt/sys
sudo mount --bind /proc mnt/proc
sudo mount --bind /dev/pts mnt/dev/pts

binfmtが発動するqemuの実行ファイルをインストールします。

sudo cp /usr/bin/qemu-arm-static mnt/usr/bin/qemu-arm-static

最後にマウントしたディレクトリを対象にchrootします

sudo chroot mnt /bin/bash

これで、たとえばapt-get update, apt-get installなど行うと、対象のイメージに任意のパッケージをインストールしたりできます。

必要な作業が終われば、Raspberry Pi OS内のbashからexitして

exit

アンマウントして、パーティションのマッピングを解除して終了です。

sudo umount mnt/dev/pts
sudo umount mnt/proc
sudo umount mnt/sys
sudo umount mnt/dev
sudo umount mnt/boot
sudo umount mnt
sudo losetup --detach /dev/loop0

vagrantではデフォルトで /vagrant にホストマシンのディレクトリがマウントされてるので、そちらに移動することでホストマシン側で取り出すことができます。

mv 2024-11-19-raspios-bookworm-armhf-lite.img /vagrant

以上です。

補足

今回chrootを行うことを目標としましたが、単純なファイルのcpなど行うだけで、お金も払っても良いのなら、有料のソフトウェアでmacOSでext4のファイルシステムの書き込みを直接行えるものがあります。

また読み込みのみ行いたい場合は以下のような無料のソフトウェアもあります。

fuse-ext2 は名前はext2ですがext4もサポートしています。また、機能としては書き込みも行えるようにするオプションが提供されていますが、READMEに以下のように書いてあるとおり、ちゃんと動く保証はないようです。

Even though write support is available, please do not mount your filesystems with write support unless you have nothing to lose.

参考


ウミトロンは、「持続可能な水産養殖を地球に実装する」というミッション実現に向けて、日々プロダクト開発・展開にチーム一丸となって邁進しています。
ウミトロンのニュースや活動状況を各種SNSで配信していますので、ぜひチェックいただき、来年も応援よろしくお願いします!
Facebook https://www.facebook.com/umitronaqtech/
X https://x.com/umitron
Instagram https://www.instagram.com/umitron.aqtech/
Linkedin https://www.linkedin.com/company/umitron

Discussion