ラズパイ4でCentOSをSSDブートすると途中で止まって起動できない時の対処法

#はじめに

**cmdline.txtの中身のroot=/dev/mmcblk0p3を/dev/sda3に書き換えてください。この記事の内容はこの説明で全てです。**

この説明でわかる方はこれで解決できると思います。以下は詳細です。

Raspberry Pi 4(以下ラズパイ)にSSDをUSB接続して、SSDにCentOSを入れてブートしようとしたら起動できずハマりました。ググった範囲では似たケースはあったものの、全く同じ症状に関する記事等はないようでした。わかってみれば大したことではなかったのですが、同じハマり方をした人の参考のために記事にします。

#環境
* Raspberry Pi 4 (Amazonで[これ](https://www.amazon.co.jp/gp/product/B08GS76DLN"Raspberry Pi 4B Server 8GB エキスパートセット")を購入しました)
* SSD: 東芝 mSATA 128 GB SSD thnsnj128gmcu (2014年秋冬モデルdynabook KIRA V63から抜いた物)
USB-mSATAアダプタ: [KingSpec MSATA SSDケース](https://www.amazon.co.jp/gp/product/B01DA1C43G) (2017年12月に購入)
* Raspberry Pi OSをmicroSDに焼いてあって、問題なく起動できる。
* 事前にRaspberry Pi OSのraspi-configでUSB起動を有効化している ([ラズパイダさんの記事](https://raspida.com/rpi4-ssd-usb-boot)を参考にさせていただきました)。
* Raspberry Pi以外のPCで、Raspberry Pi Imagerを使ってCentOSのOSイメージをSSDに焼いてある([こちらのサイト](https://denor.jp/raspberry-pi-4%E3%81%A7centos-7%E3%83%AB%E3%83%BC%E3%83%88%E3%83%91%E3%83%BC%E3%83%86%E3%82%A3%E3%82%B7%E3%83%A7%E3%83%B3%E3%82%92%E6%8B%A1%E5%BC%B5%E3%81%99%E3%82%8B%E3%81%AB%E3%81%AF)を参考にさせていただきました)。
* CentOSを焼いたSSDをラズパイにUSB接続
* CentOSのバージョンは7。8でもおそらく同じ (8をラズパイに入れた[記事](https://ptplus.jp/archives/91)があります)。

なお、SSDではなくCentOSをmicroSDに焼いて、それをラズパイに挿して起動した場合は問題なく起動するようで、成功例が複数([1](https://qiita.com/Asuka_Saito/items/c4aeeab6c9db65d8f500), [2](https://www.clara.jp/media/?p=5792), [3](https://grapho.jp/raspberrypi4/centos7-install/), [4](https://denor.jp/raspberry-pi-4%E3%81%A7centos-7%E3%83%AB%E3%83%BC%E3%83%88%E3%83%91%E3%83%BC%E3%83%86%E3%82%A3%E3%82%B7%E3%83%A7%E3%83%B3%E3%82%92%E6%8B%A1%E5%BC%B5%E3%81%99%E3%82%8B%E3%81%AB%E3%81%AF))報告されています。今回の現象は、PCから直接SSDに焼いた場合特有に起こる問題のようです。

#症状

boot時に以下のようにend Kernel panic -……とメッセージが出て止まる。(xxxは数字)

```
end Kernel panic - not syncing: VFS: Unable to mount root fs on unknown-block(xxx,xxx)
```

これは、SSDと同時にRaspberry Pi OSが入ったmicroSDを挿しっぱなしにしていた場合のみ起こりました。microSDを抜いて、SSDのみがラズパイに接続されている状態で起動しなおすと、Kernel panicは出なくなりました。しかしながら、今度は

```
vcc-sd: disabling
```

というメッセージが出て一旦止まり、数分経過した後に

```
random: crng init done
```

というメッセージが出て、それ以降はいくら待っても進まなくなりました。

#対処法
結論から言うと、SSDの1つめのパーティションにある`cmdline.txt`というファイルを編集すると起動できるようになりました。

以下手順です。

* 一旦ラズパイからSSDを外し、microSDを挿入してRaspberry Pi OSを起動する。
* SSDをつなぐ。`300 MB ボリューム`と`_/`という名前のアイコンが、以下のスクショのようにデスクトップに出現しています。
![desktop_icon.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1447545/7c841681-ae8a-195f-160a-ccab5eaf2f65.png)

* `lsblk`コマンドを実行すると、現在接続されているデバイスとマウントポイントが見えます。

```console:LXterminal
(ユーザー名)@(ホスト名):~ $ lsblk
NAME        MAJ:MIN RM   SIZE RO TYPE MOUNTPOINT
sda           8:0    0 119.2G  0 disk 
├─sda1        8:1    0   286M  0 part /media/(ユーザー名)/(UUID)
├─sda2        8:2    0   488M  0 part 
└─sda3        8:3    0 118.5G  0 part /media/(ユーザー名)/__
mmcblk0     179:0    0 119.1G  0 disk 
├─mmcblk0p1 179:1    0   256M  0 part /boot
└─mmcblk0p2 179:2    0 118.9G  0 part /
```

(ユーザー名)と(ホスト名)はデフォルトではpiとraspberrypiです。(UUID)の部分はデバイスのUULD(Universally Unique Identifier) で、環境依存です。
[`sda`は1番目のSCSI/SATA/USBに接続したHDD](https://www.infraeye.com/study/linuxz21.html) (今回はSSDですが) を意味し、配下の`sda1`, `sda2`, `sda3`がSSD内にある3つのパーティションの1つめ、2つめ、3つめにそれぞれ対応しています。また`lsblk`の実行結果の7列目の情報から、`sda1`と`sda3`が`/media/(ユーザー名)/`のディレクトリにマウントされていることが確認できます(自動的にここにマウントされるようです)。
　ちなみにmmcblk0はRaspberry Pi OSの入っているmicroSDカードのことで、`mmcblk0p1`,`mmcblk0p2`はmultimedia card block 0 partition 1または2を[意味します](https://www.raspberrypi.org/documentation/configuration/cmdline-txt.md)。

* sda1のパーティションにあるcmdline.txtを編集します。`lsblk`で確認したように、sda1は/media/(ユーザー名)/(UUID)にマウントされているので、そのディレクトリ直下にある`cmdline.txt`をNanoで開きます。

```console:LXterminal
$ sudo nano /media/(ユーザー名)/(UUID)/cmdline.txt
```

以下はNanoで開いた例。

```console:/media/(ユーザー名)/(UUID)/cmdline.txt
console=ttyAMA0,115200 console=tty1 root=/dev/mmcblk0p3 rootfstype=ext4 elevator=deadline rootwait
```

* cmdline.txtのファイル内で`root=/dev/mmcblk0p3`となっている部分を、下記のように`root=/dev/sda3`に書き換えます。
 
```console:/media/(ユーザー名)/(UUID)/cmdline.txt
console=ttyAMA0,115200 console=tty1 root=/dev/sda3 rootfstype=ext4 elevator=deadline rootwait
```

* 上書き保存します。これでRaspberry Pi OSでの作業は終わりです。Raspberry Pi OSを再起動します。

```console:LXterminal
$ sudo reboot
```

* CentOSが立ち上がるはずです。ユーザー名`root`, 初期パスワード`centos`でログインできます。

なお、cmdline.txtだけではなくfstabの書き換えもしている[記事](https://ptplus.jp/archives/91)もありましたが、今回試した限りではcmdline.txtのみ編集しただけで起動できました。ちなみにfstabの編集にはUUIDを確認する必要がありますが、コンソールで`blkid`のコマンドを実行して、確認できます (xxxxは環境依存の16進数の値)。


```console:LXterminal
$ blkid
/dev/mmcblk0p1: LABEL_FATBOOT="boot" LABEL="boot" UUID="xxxx" TYPE="vfat" PARTUUID="xxxx-01"
/dev/mmcblk0p2: LABEL="rootfs" UUID="xxxx" TYPE="ext4" PARTUUID="xxxx-02"
/dev/sda1: SEC_TYPE="msdos" UUID="xxxx" TYPE="vfat" PARTUUID="xxxx-01"
/dev/sda2: LABEL="_swap" UUID="xxxx" TYPE="swap" PARTUUID="xxxx-02"
/dev/sda3: LABEL="_/" UUID="xxxx" TYPE="ext4" PARTUUID="xxxx-03"

```


`/dev/sda1`と`/dev/sda3`のところに表示されているUUIDと、先に`lsblk`で確認した`/media/(ユーザー名)/`のディレクトリの`(UUID)`と`__`がそれぞれに対応しています。



#考察
　今回の問題は、端的にいうとmicroSDに書き込むことを前提に作られたOSイメージを、何も考えずにSSDに焼いてしまったために起きたものです。具体的には、ラズパイのブートの仕組みに起因します。ラズパイでは、ブートファイルは通常SDカードの1つ目のパーティションに保存されています。ラズパイの電源が投入されると、様々なプロセッサを起動するためにブートパーティション/フォルダからブートローダー等の様々なファイルがロードされ、その後Linuxカーネルが起動されます。

https://www.raspberrypi.org/documentation/configuration/boot_folder.md

Linuxカーネルは、起動の際に複数のパラメータから成るコマンドを受け付けます。ラズパイでは、このコマンドはブートパーティションに存在するcmdline.txtというテキストファイルで定義されます。cmdline.txtではroot (bootではなくroot) のパスが指定されています。このとき、前述の通り通常はここがmmcblk0p3となっているのに、SSDで起動する場合は実際のrootはsda3に存在するため、Linuxカーネルは存在しないパーティションを見にいってしまいます。そのため起動がうまくいかない、ということになると考えられます。

https://www.raspberrypi.org/documentation/configuration/cmdline-txt.md


上ではラズパイの公式ドキュメントを典拠として挙げましたが、それ以外にもいくつかのサイトが非常に参考になりました。(この記事を書くために公式ドキュメントを読んだら全部書いてありました)(私は公式ドキュメントを読め)

エラーメッセージの理由と、cmdline.txtを編集するべきであると気づかせてくれた記事。

https://www.webzoit.net/hp/it/internet/homepage/env/hardware/single_board_computer/raspberry_pi/boot.html


また、Raspberry Pi 4でCentOS7を外付けSSDで動かした記事がありますが、

https://qiita.com/reishisu/items/a0b12e7bcd096db2f292

この記事では詳細がとても詳しく述べられていて、とても参考になりました。この記事では一旦microSDにCentOSを書き込んだ後、SSDに自分でパーティションを切って、microSDからSSDにパーティションごとにコピーするという手順を踏まれています。この当時はおそらくこのような手順を踏まなければいけなかったのだと思われますが、2021年5月現在はもろもろの進歩 (Raspberry Pi Imagerで直接SSDに焼ける) によってより簡単にできるようになりました。この記事ではcmdline.txtの編集についても述べられています。


さらに、CentOS 8でほぼ同じことをしている記事を、解決した後になってから見つけました。

https://ptplus.jp/archives/91

僅かな手順の差 (現在のほうがRaspberry Pi  OSのバージョンが上がっていることに起因する)がありますが、結局やっていることは同じでした。しかしながら、当該記事は淡々と手順を述べているものであったため、トラブルシューティング的な位置付けで、私と同じハマり方をしている方向けに書く意義があると思い、この記事を書きました。


#まとめ
* cmdline.txtを書き換えることがポイント
* 私は公式ドキュメントをちゃんと読め

以上です。