あっきぃ日誌

鉄道ブログのような技術系ブログのようななにか

Raspberry Pi Compute Module 4でUSBマスストレージブートを有効化する

Raspberry Pi Advent Calendar 2020の13日目です。つぼさんご結婚おめでとうございます!式が終わって一息みたいなことを言っていたので、今なら書く余裕出ましたか?!とつついたところ参加登録してもらえました。新婚のひとに対してやることじゃない感がありちょっと反省しています。

adventar.org

今日はPCIeデバイスの続き……をするためにCM4でUSBマスストレージブート(以下USB MSDブート)を有効化しようとしたら、これだけで1記事書ける感じになったのでそのはなしです。

CM4のUSB MSDブートサポート

CM4の出荷時のBoot EEPROMバージョンは2020-10-02リリースのものになっています。が、これはcriticalにもstableにも置かれておらず、なんやねんという感じがしました。さておき、この2020-10-02リリースのものでは実はUSB MSDブートができません。

Pi4のUSB MSDブートはVL805がある前提で作られているらしく、それがないCM4ではUSBからのブートができないようです。ちなみにIOボードのUSB2.0ポートはSoCから出たUSB2.0ポートをUSB2514ハブチップで増やしていて、USB-Ax2と、ピンヘッダ(ピンアサインはわからんけど多分データシートにあるはず)で提供されています。

そんなわけで、CM4のUSB MSDブートサポートは2020-11-24リリースのbetaのイメージで提供され始めたので、USBを使いたければアップデートせよ、ということのようです。

rpi-eeprom/release-notes.md at master · raspberrypi/rpi-eeprom · GitHub

rpi-eeprom-updateは使えない

いつものようにCM4でRaspberry Pi OSを起動してrpi-eeprom-updateコマンドでアップデートを……とおもったらなんか怒られました。

pi@raspberrypi:~ $ sudo rpi-eeprom-update 
BCM2711 detected
rpi-eeprom-update is not enabled by default on CM4

CM4ではrpi-eeprom-updateが使えないらしく、母艦を用意して母艦上に用意したrpibootコマンドを使ってイメージを流し込む必要があるとのこと。

やり方は以下のドキュメントに記載されていました。というわけで手順を読みながら進めていくことにします。

www.raspberrypi.org

アップデートのためのファイルを準備する

母艦には手元に転がっていたPi4を使うことにして、MicroSDカードをCM4からPi4に移して起動し、作業開始します。

まずはイメージの用意。最新は2020-11-24の次にリリースされた2020-12-11(これもbeta)になるので、これを使います。このバージョンではconfig.txtで[pi400]と[cm4]セクションが使えるようになったので、config.txtの設定をPi400とCM4とその他とで使い分けたいことがあれば有用な変更です。最新のパッケージに2020-12-11版イメージが含まれているのでaptでインストールします。

pi@raspberrypi:~ $ sudo apt update;sudo apt install rpi-eeprom

次にrpibootの用意。これもaptで入るっぽかったのですが、パッケージ版のコマンドで書き込んだら変な出力が出て怖かったので、手順に従ってソースからコンパイルします。

pi@raspberrypi:~ $ git clone --depth=1 https://github.com/raspberrypi/usbboot
pi@raspberrypi:~ $ cd usbboot
pi@raspberrypi:~/usbboot $ sudo apt install -y libusb-1.0-0-dev
pi@raspberrypi:~/usbboot $ make -j 4

次はイメージの準備をします。clone下リポジトリの中にrecoveryディレクトリがあり、古いイメージが鎮座しているので、適当にどかします。

pi@raspberrypi:~/usbboot $ cd recovery
pi@raspberrypi:~/usbboot/recovery $ mkdir original
pi@raspberrypi:~/usbboot/recovery $ mv pieeprom.* original/

かわりに2020-12-11版イメージをコピーしたいのですが、ブート順を変更する必要があるため、rpi-eeprom-configコマンドで設定を書き換えたイメージを生成する必要があります。だるいね。やり方は以前Pi4のPXEブートをやったときと同様です。

(pieeprom-2020-12-11.binの設定をhoge.confに書き出し)
pi@raspberrypi:~/usbboot/recovery $ rpi-eeprom-config /lib/firmware/raspberrypi/bootloader/beta/pieeprom-2020-12-11.bin -o hoge.conf
(hoge.confの設定を編集)
pi@raspberrypi:~/usbboot/recovery $ vi hoge.conf

[all]
BOOT_UART=0
WAKE_ON_GPIO=1
POWER_OFF_ON_HALT=0
BOOT_ORDER=0xf51   ←この行を追記

(pieeprom-2020-12-11.binにhoge.confの設定を投入したものをpieeprom.binに書き出し)
pi@raspberrypi:~/usbboot/recovery $ rpi-eeprom-config -c hoge.conf -o pieeprom.bin /lib/firmware/raspberrypi/bootloader/beta/pieeprom-2020-12-11.bin

BOOT_ORDERの値については、リリースノートにもあるとおり"5"がUSB2.0ポート版USB USDブートとなります。この5の値はPi4とPi400のUSB-Cポートでも有効のようです。使いみちは……🤔?

続けて、pieeprom.binのsha256チェックサムを記述したpieeprom.sigファイルを作成します。別のドキュメント(どれか忘れた)にはpieeprom.sigの内容は将来的に変更される可能性があるとか書かれていたので、この記事を遠い未来に読んでいる方は、先述のドキュメントを参照してください。ただ、記事公開からそれほど経っていない時点で読んでいる方は以下を見てください。公式ドキュメントのawkのパラメーターが間違っていて$2になっていました。$2にしたらファイル名が書かれるやろがい。

pi@raspberrypi:~/usbboot/recovery $ sha256sum pieeprom.bin | awk '{print $1}' > pieeprom.sig

ここまででファイルの準備は完了です。

物理的な準備

イメージを書き込むための準備をします。

イメージを書き込むには、IOボードのJ2ジャンパの「Fit jumper to disable eMMC Boot」と書かれた部分をショートさせる必要があります。ジャンパピンを使うか、メス-メスのヘッダーピン用ケーブルでつなぐかすると良いでしょう。

f:id:Akkiesoft:20201212221406j:plain

データ転送には、IOボードのUSB Slave(MicroUSBポート)と母艦をつなぎます。つまりMicroUSBケーブルが必要です。こんなかんじ。IOボードの電源はまだ入れません。

f:id:Akkiesoft:20201212221848j:plain

書き込み!

準備完了。母艦側でrpibootコマンドを実行して、待機状態にします。

pi@raspberrypi:~/usbboot/recovery $ sudo ../rpiboot -d .
Waiting for BCM2835/6/7/2711...

待機状態になったらIOボードの電源ケーブルを差し込みます。

f:id:Akkiesoft:20201212222137j:plain

すると、こんな感じでメッセージが流れます。「Second stage boot server done」と出てコマンドが終われば成功です。またIOボード側は緑ランプが高速で点滅していれば書き込み完了の状態です。

Waiting for BCM2835/6/7/2711...
Loading: /home/pi/recovery/bootcode4.bin
Sending bootcode.bin
Successful read 4 bytes 
Waiting for BCM2835/6/7/2711...
Loading: /home/pi/recovery/bootcode4.bin
Second stage boot server
Loading: /home/pi/recovery/config.txt
File read: config.txt
Loading: /home/pi/recovery/pieeprom.bin
Loading: /home/pi/recovery/pieeprom.bin
Loading: /home/pi/recovery/pieeprom.sig
File read: pieeprom.sig
Loading: /home/pi/recovery/pieeprom.bin
File read: pieeprom.bin
Second stage boot server done

IOボードの電源ケーブルを抜いて、ジャンパを取り外します。この辞典でCM4のSDカードブートができるか確認しておくと良いでしょう。

USB MSDブートする

あとはUSBデバイスをIOボードに挿して起動します、うまく起動したら成功です。

f:id:Akkiesoft:20201212222339j:plain

まとめ

CM4でUSB MSDブートをするための手順を紹介しました。

USB2.0なのになぜCM4でUSB MSDブートする必要があるのかと思われるかもしれませんが、Pi 4のUSB3.0ポートでSSDを使って高速にUSB MSDブート&読み書きできる環境で生成した結果をCM4上で利用したかったので、CM4でせっせとUSB MSDブートを有効化していたのでした。

具体的には、USB SSDを使ってLinuxカーネルコンパイルをやっていました。10GbEを利用するにはドライバー以外にカーネルのオプション周りもいじらないといけないのかと思い、カーネル全体をコンパイルしたりしていた次第です。ちなみに、正確な時間は測っておらず放置した時間からの推測ですが、Pi4とSSDだと1時間半くらいでコンパイルできていたんじゃないかと思います。つよいね。