Raspberry PiにArch Linux ARMをLVMでインストールする
環境構築記録です。Raspberry Piでは普通はRaspberry Pi OSを使うところですが、筆者はほかの環境ではArch Linuxを使っているので、管理コスト低減のためにArch Linux ARMを使うことにしました。また、 /var/log
のボリュームを分けたいので、柔軟性を持たせられるようにLVMで構成します。
使っているRaspberry PiはRaspberry Pi 4 Model Bです。
パーティショニングとファイルコピー
まず一旦LVMを使わずに普通にインストールします。この過程を経ずにやる方法がないかなといろいろ試したのですが、LVMを使うには後で出てくるようにinitramfsにフックを入れてやる必要があり、そのためには実機で操作しないと難しいと思います(もしかしたら何かしら術があるかもしれませんが)。
で、作業としては適当なマシンの上でISOイメージをダウンロードしてmicroSDに焼くだけ……と言いたいところですが、Arch Linux ARMのイメージは .iso
ではなく .tar.gz
なのでファイルシステムを作ってコピーしてあげる感じです。Raspberry Pi 4 | Arch Linux ARMに書いてある通りにやればいいです。Armv7とAarch64がありますが当然Aarch64を選びます。
注意事項として、Raspberry PiをmicroSDカードから起動するには、MBRでフォーマットされていて、先頭のbootパーティションはFAT32である必要があります。何も考えずに手癖でGPTとかext4とかでやると嵌まります(嵌まりました)。それと、後の手順でrootパーティションを dd
することになるので小さめにしておくとよいです。rootパーティションは第2パーティションでなければならないので注意してください。
以下、bootパーティションを /mnt/boot
に、ルートを /mnt/root
にマウントしているとします。
Device Treeの修正
これでとりあえず起動するはずなのですが、私の手元ではブートの途中で以下のエラーが無限に繰り返される状態になってしまいました。
mmc1: error -22 whilst initialising SD card
mmc1: unrecognised SCR structure version 4
手順通りにインストールしただけなので、明らかに配布されているイメージの時点で問題があるということです。超絶探し回って試行錯誤しまくった結果、U-boot compilation on CM4 - Raspberry Pi Forumsと[SOLVED] Slackware aarch64 installer, C0 stepping RPi4 & Samsung EVO SD cardsに書かれていることを /mnt/boot/dtbs/broadcom/bcm2711-rpi-4-b.dtb
に対してやると治りました(step by stepの手順は後者のページに詳しいです)。どうやらdevice treeの問題だったようです。device treeが何かという説明は私には手に負えないですが、Raspberry Piのハードウェアの仕様とbootパーティション内に置かれているファイルの記述とが整合しない状態になっていたということだと思います。
initramfs
さて、上でも少し触れましたが、LVM に Arch Linux をインストールする - ArchWikiに書かれている通り、LinuxをLVM構成でインストールした場合、initramfsにlvm2フックを追加する必要があります。
母艦で mkinitcpio
にオプションを付けてinitramfsを作れないかと試したのですが上手くいかなかったので、実機で作業します。ちなみに別のmicroSDカードで起動して作成したinitramfsをまっさらなイメージに持ち込んでみるというのも試したのですが、これも上手くいきませんでした( lvm2
パッケージをインストールする際に pacman -Syu
でシステムのフルアップデートをしたのでkernelもアップデートされて不整合が起きた……とかだと思っています)。
手順は上に貼ったArch Wikiの通りです。新しいinitramfsで起動するかどうかを一度試しておきましょう。 /boot
をマウントしておくのを忘れずに(一敗)。
LVMパーティションの作成
LVMパーティションを作成して、 dd
コマンドなどでrootパーティションをここにコピーしてあげます。LVMまわりの操作はLVM に Arch Linux をインストールする - ArchWikiやLVM - ArchWikiを参照してください。LVMパーティション内を切り刻むのは後にして、とりあえず論理ボリュームを1個だけ作成しましょう。コピーの段取りはなんでもよいですが、筆者は
- 第2パーティションにrootがある
- 第4パーティションを作成
dd if=/dev/mmcblk0p2 of=/dev/mmcblk0p4 bs=128K status=progress
- もとの第2パーティションを爆破して、LVMな第2パーティションを新たに作成
dd if=/dev/mmcblk0p4 of=/dev/vga/root bs=128K status=progress
としました。最終的なLVMパーティションが第2パーティションになるのを諦めてもいいですし、パーティション番号を付け替えてあげてもいいです。この段階では起動しないので、次に進んでください。
カーネルパラメタの更新
rootパーティションの場所が変わったので、カーネルパラメタでrootがどこにあるのか教えてやる必要があります。前提として、Raspberry Pi 4 Model BのブートシークエンスはRaspi4B+ Boot Sequence の再整理とBoot LoaderのUART出力 - 備忘録などに詳しいです(Raspberry Pi 3以前とは異なっているので注意)。それで、 start4.elf
が config.txt
に従ってカーネルを読み込んで起動するわけですが、Arch Linux ARMのイメージでは以下のようになっています。
config.txt
でkernel
は設定されていない(ので、config.txt - Raspberry Pi Documentationにあるように、デフォルト値であるkernel7.img
→kernel8.img
が順に試される)。kernel8.img
が存在するが、これはLinuxカーネルではなくU-Bootである。- U-BootがU-Bootスクリプト
boot.scr
に従ってLinuxカーネルを読み込む。LinuxカーネルはImage
というファイルで、U-Bootスクリプトでこれが指定されている。
U-Bootを噛ませないブートシークエンスの場合はカーネルパラメタは cmdline.txt
で指定しますが、このブートシークエンスではLinuxカーネルを起動するのは start4.elf
ではなくU-Bootなので、カーネルパラメタもU-Bootスクリプトで指定します。具体的には
$ sudo pacman -S uboot-tools
$ sudo -i
# cd /mnt/boot
# vi boot.txt
# ./mkscr
と叩きます。 boot.txt
の setenv bootargs
で始まる行がカーネルパラメタです。元はroot=PARTUUID=${uuid}
となっているところを、 root=/dev/vga/root
などと変えます(LVMのボリュームグループ名と論理ボリューム名は自分の作ったものを入れてください)。
ここまで来たら起動するはずなので、microSDカードをRaspberry Piにさして電源を入れましょう。
パーティションレイアウトの修正
後は仕上げです。論理ボリュームを切り刻んで /etc/fstab
をいい感じにしてください。