Raspberry Pi 4 Model B で USB ブート(1)

Raspberry Pi 4 には microSD カードスロットが用意されており、ここに Linux をインストールした microSD カードを挿して運用するのがオフィシャルな使い方と思われる。
microSD は安い、消費電力が低いなどの利点はあるものの、

* 遅い（数十MB/sec）
    * SSD が 数百〜数千MB/sec オーダー、HDD でも 200MB/sec 以上なので桁違いに遅い
* 書き込み回数制限がきつめ
    * TCL なら 1,000回

といった欠点もあり、サーバーとして使うには不満を感じることは否定できない。

しかししばらく前からRaspberry Pi 4 Model B向けにベータ版として [USB マスストレージからブートできる EEPROM](https://github.com/raspberrypi/rpi-eeprom/releases/tag/v2020.09.03-138a1)が公開されており、最後にリリースされたものが最近[正式版に格上げ](https://github.com/raspberrypi/rpi-eeprom/blob/09f77ad9fa8655a28de754640e82ca67aabe6c33/firmware/release-notes.md)された。
これを利用し USB 接続の SSD や HDD で運用することができればこの不安を解消できる。
作業的な意味でも心理的な意味でもハードルが下がったので、実際にやってみることにした。

## 用意するもの

* Raspberry Pi 4 Model B
* microSD（2GB以上）
    * EEPROM を更新するための Raspberry Pi OS の必要容量が 2GB
    * USB マスストレージからブートできる EEPROM が工場出荷時にインストールされるようになったら必須でなくなるかもしれない
* USB 接続のストレージ
    * 今回は以下のものを使用したが、Linux で認識できるものなら多分なんでも
        * SATA-USB 変換器 KURO-DACHI/CLONE/U3
        * SATA HDD
* PC
    * microSD に EEPROM を更新するための Raspberry Pi OS をインストールするのに必要
    * USB マスストレージのパーティションを作成・編集するのにも使う
* Raspberry Pi 操作用のディスプレイ、キーボード
  * EEPROM 更新の際、コマンドを入力するのに使う（Raspberry Pi OS に SSH サーバーを立てられるなどの場合はなくてもいいかも）。ディスプレイ接続は Micro HDMI。

## EEPROM の更新

EEPROM の更新は Raspberry Pi OS から行う。

https://www.raspberrypi.org/downloads/raspberry-pi-os/ からイメージをダウンロードする。多分どれでも問題ないが、EEPROM の更新しかしないので、もっとも容量の少ない Raspberry Pi OS (32-bit) Lite がおすすめ（EEPROM のリカバリーイメージを使えばもっと簡単に更新が行えそうだが、現在のところ未確認。）。
イメージがダウンロードできたら Raspberry Pi Imager（以下 rpi-imager。[公式ダウンロードページ](https://www.raspberrypi.org/downloads/)からダウンロードできる）で microSD にインストールし、これで Raspberry Pi を起動する。

USB マスストレージブートに対応した EEPROM は、正式リリース前は GitHub のページからベータ版をダウンロードする必要があったようだが、現在ではパッケージマネージャー apt でアップデートを行えば自動的に更新される。
手順は以下のとおり。

* [Raspberry Pi 4 boot EEPROM - Raspberry Pi Documentation](https://www.raspberrypi.org/documentation/hardware/raspberrypi/booteeprom.md) 

```sh
$ sudo apt update
# rpi-eeprom パッケージに EEPROM が含まれているので、ここで更新される
$ sudo apt full-upgrade
$ sudo reboot

# 再起動後に EEPROM が 2020-09-03 に更新されたことを確認する
$ vcgencmd bootloader_version
Sep  3 2020 13:11:43
version c305ZZ1a6d7e532693cc7ff57fddfc8649def167 (release)
timestamp 1599135103
```

## 起動デバイス設定の変更

2020-09-03 の EEPROM からは起動デバイスとして USB マスストレージが最優先になるようだが、それ以前のものではデフォルトが microSD になっているので、この設定の確認と変更を行う。

```sh
$ sudo raspi-config
```

`3 Boot Options` → `B4 Boot Order` から `B1 USB Boot` を選択し、設定を保存。

## USB マスストレージへの Linux のインストール

Raspberry Pi OS (64bit) と Ubuntu 20.04.1 LTS (64bit) での動作を確認した。それぞれで手順が少し異なるので、個別に記載する。

### Raspberry Pi OS のインストール

#### rpi-imager を使う場合

PC に USB マスストレージを接続し、rpi-imager で Raspberry Pi OS をインストールする。
メニューからは 32bit 版しか選択できないので、以下の場所からあらかじめ 64bit 版のイメージをダウンロードしておきこれを使用する。

* https://downloads.raspberrypi.org/raspios_arm64/images/raspios_arm64-2020-08-24/

インストールが終わったら Raspberry Pi 4 に USB マスストレージを接続すれば起動できる。

#### rpi-imager を使わない場合

前述のイメージは単なるストレージのダンプなので、rpi-imager を使わず `dd` コマンドなどで代替可能。
但しコマンドの入力ミスがあると **PC のデーターを消去してしまう**恐れがあるため、各コマンドの実行内容を理解している人限定。

```sh
# /dev/sdb の部分は適宜変更
$ unzip -p 2020-08-20-raspios-buster-arm64.zip | sudo dd of=/dev/sdb bs=128M
0+57209 レコード入力
0+57209 レコード出力
3779067904 bytes (3.8 GB, 3.5 GiB) copied, 35.0279 s, 108 MB/s
```
ブートローダーの設定と `fstab` を書き換える。

```sh
# 各パーティションの PARTUUID を確認
$ blkid /dev/sdb*
/dev/sdb1: LABEL_FATBOOT="boot" LABEL="boot" UUID="54E3-79CE" TYPE="vfat" PARTUUID="ad09722e-01"
/dev/sdb2: LABEL="rootfs" UUID="c6dd3b94-a789-4d57-9080-1472f721804b" TYPE="ext4" PARTUUID="ad09722e-02"

$ mkdir boot root
$ sudo mount /dev/sdb1 boot
$ sudo mount /dev/sdb2 root

# root=PARTUUID= の値を rootfs の PARTUUID にする
$ cat boot/cmdline.txt
console=serial0,115200 console=tty1 root=PARTUUID=ad09722e-02 rootfstype=ext4 elevator=deadline fsck.repair=yes rootwait quiet init=/usr/lib/raspi-config/init_resize.sh splash plymouth.ignore-serial-consoles

# PARTUUID= の値を boot, rootfs の PARTUUID にする
$ cat root/etc/fstab
proc            /proc           proc    defaults          0       0
PARTUUID=ad09722e-01  /boot           vfat    defaults          0       2
PARTUUID=ad09722e-02  /               ext4    defaults,noatime  0       1

# 作業が終わったら後片付け
$ sudo umount boot root
$ rmdir boot root
```

#### パーティションの拡張

rpi-imager を使うかどうかにかかわらず、インストール直後のパーティションは以下の通り。

```sh
$ sudo gdisk -l /dev/sdb
:
Number  Start (sector)    End (sector)  Size       Code  Name
   1            8192          532479   256.0 MiB   0700  Microsoft basic data
   2          532480         7380991   3.3 GiB     8300  Linux filesystem
```

root の使用率は 88% という窮屈な状態なので、`parted` コマンドなどでパーティションを拡張する。

### Ubuntu 20.04.1 LTS のインストール

rpi-imager でイメージを作成するのは Raspberry Pi OS と同様。
イメージの場所は以下。

* [Install Ubuntu Server on a Raspberry Pi 2, 3 or 4 | Ubuntu](https://ubuntu.com/download/raspberry-pi)

rpi-imager を使わない方法も、パーティションを変更する必要があるのも Raspberry Pi OS のインストール時と同様。

追加で、以下の情報を参考にカーネル周りを調整する。

* [RPI4 Direct USB Boot Ubuntu 20.04 - Raspberry Pi Forums](https://www.raspberrypi.org/forums/viewtopic.php?t=278791)

```sh
$ mkdir boot
$ zcat boot/vmlinuz | sudo dd of=boot/vmlinux

$ cat boot/config.txt
 :
[pi4]
max_framebuffers=2
dtoverlay=vc4-fkms-v3d
boot_delay
kernel=vmlinux
initramfs initrd.img followkernel
 :

$ sudo umount boot
$ rmdir boot
```

これで起動は可能になる。
ただし `boot/vmlinux` 更新の際には `vmlinuz` も追随させる必要があるので、前述のフォーラムにあるように `auto_decompress_kernel` のようなスクリプトを登録しておくといいと思われる。

---

* [Raspberry Pi 4 Model B で USB ブート(1)](https://qiita.com/nowlinuxing/items/3c7f61bca6e5ef0d1c47)
* [Raspberry Pi 4 Model B で USB ブート(2) パーティション作成編](https://qiita.com/nowlinuxing/items/7af17f1272ca0c558d47)
* [Raspberry Pi 4 Model B で USB ブート(3) LVM 編](https://qiita.com/nowlinuxing/items/b57b3aa910fee9b82052)