Raspberry Pi3 + Ubuntu 18.04 server (arm64) + USB Boot

Raspberry Pi3に外部USBデバイスで起動するARM64版Ubuntu 18.04環境を構築した際の記録．主に[ARM/RaspberryPi - Ubuntu Wiki](https://wiki.ubuntu.com/ARM/RaspberryPi)を参考に作業した．


## 準備するもの

* Raspberry Pi3 Model B（USB Bootモードをオンにしたもの．参考：[Raspberry Pi3 USBデバイスからブートする方法 | ある計算機屋さんの手帳](http://my-web-site.iobb.net/~yuki/2017-09/raspberry-pi/usb-boot/)）
* Ubuntuインストール用イメージ（[ubuntu-18.04-server-arm64.iso](http://cdimage.ubuntu.com/ubuntu/releases/bionic/release/ubuntu-18.04-server-arm64.iso)）を焼いたUSBメモリ（以後「インストール用USBメディア」と呼ぶ）
* インストール時の起動用microSDカード
* システムをインストールするUSBデバイス（USB接続の128GB SSDを利用）
* 作業用Linuxマシン



## 起動用microSDカードの作成
### Linuxでの作業

microSDカードをパーティションテーブルmsdos (MBR)，ファイルシステムfat16またはfat32でフォーマットする（カード全体でも先頭の一部分でもOK）．

適当な場所にマウント：

```shell
$ sudo mount /dev/XXX1 /mnt
```

GPUファームウェアとブートローダをダウンロード，展開してコピー：

```shell
$ wget https://github.com/raspberrypi/firmware/archive/master.zip
$ unzip master.zip
$ sudo cp -r firmware-master/boot/* /mnt
```

ここで展開したファイルは後で使うのでまだ消さない．

U-bootをコンパイルしてコピー：

```shell
$ sudo apt install git make gcc gcc-aarch64-linux-gnu bison flex
$ git clone --depth 1 git://git.denx.de/u-boot.git
$ cd u-boot
$ make rpi_3_defconfig
$ make CROSS_COMPILE=aarch64-linux-gnu-
$ cd ..
$ sudo cp u-boot/u-boot.bin /mnt/kernel8.img
```

ここでコンパイルしたファイルは後で使うのでまだ消さない．

デバイスツリーblobをコピー：

```shell
$ wget http://ports.ubuntu.com/dists/bionic/main/installer-arm64/current/images/device-tree/bcm2837-rpi-3-b.dtb
$ sudo mkdir -p /mnt/dtb/broadcom/
$ sudo cp bcm2837-rpi-3-b.dtb /mnt/dtb/broadcom/
```

アンマウント：

```shell
$ sudo umount /mnt
```


## インストール
### Pi3での作業

起動用microSDカードとインストール用USBメディアをPi3に差して起動する．

起動が始まってからシステムをインストールするUSBデバイスを繋ぐ．

GRUBメニューが現れたら`Install Ubuntu Server`が選ばれた状態で`e`でエディットモードに入る．

linuxで始まる行の末尾のあたり（---の直前）に`partman-partitioning/default_label=msdos`と追記（カーソルが表示されないがカーソルキーでインサートポイントが動くので手探りで適切な場所を探す）して`Ctrl-x`でブート．インストーラが起動する．

言語，キーボード，ネットワーク，アカウントなどの設定は適当に．以下では日本語を選択したものとして説明する．

ディスクのパーティショニングのダイアログが現れたら，`手動`を選択．システムをインストールするUSBデバイスを確認し，以下の手順でパーティションを作成する：
1. 該当デバイス（おそらく大抵の場合`sdb`）自体を選択し`Enter`．`新しい空のパーティションテーブルを作成`．
2. 該当デバイスすぐ下の空き領域を選択し`Enter`．`新しいパーティションの作成`→`64MB`〜`128MB`程度を指定→`基本パーティション`→`先頭`→利用方法を`EFIシステムパーティション`に変更，起動フラグがオンになっているのを確認して`パーティションのセットアップを終了`．
3. 該当デバイスの残りの空き領域を選択し`Enter`．`新しいパーティションの作成`→`max`→`論理パーティション`→マウントポイント`/`，ファイルシステム`ext4`になっていることを確認して`パーティションのセットアップを終了`．
4. `パーティショニングの終了とディスクへの変更の書き込み`を選択．

`ハードディスクへのGRUBブートローダのインストール`に失敗するので，`続ける`で一度インストールプロセスから抜けて，`ブートローダなしで続ける`を選択し，インストールを続行．

インストールが終了し，再起動がかかったら一旦電源オフ．インストール用USBメディアとシステムをインストールしたUSBデバイスをPi3から外す．



## EFIパーティションのフラグを変更
### Linuxでの作業

システムをインストールしたUSBデバイスをLinuxに繋いで，先頭パーティションの`esp`フラグを外す．デバイスのパーティションテーブルが`msdos`になっていることを確認．



## GRUBのインストール
### Pi3での作業

起動用microSDカードとシステムをインストールしたUSBデバイスをPi3に差して起動する．GRUBのプロンプトが表示されるので以下を実行（デバイスの番号が違っていたら適宜読み替えてください）：

```
grub> ls
（パーティションのリストが返る．おそらく(hd0,msdos5)がUSBデバイスのルートパーティション）
grub> set root=(hd0,msdos5)
grub> linux /boot/vmlinuz root=/dev/sda5
grub> initrd /boot/initrd.img
grub> boot
```

（`initrd /boot/initrd.img`のところでエラーが出た．もう一度この行を繰り返しても同様だった．そこで，USBデバイスをMBR/FAT32で一度まっさらにフォーマットして，再度システムのインストールからやり直したら成功した．原因は不明）

システムが起動したらログインして以下を実行：

```shell
$ sudo grub-install --no-nvram
$ sudo update-grub
$ sudo shutdown -h now
```

電源を切って，起動用microSDカードを外す．



## ファームウェア他のコピー
### Linuxでの作業

システムをインストールしたUSBデバイスのブート領域にGPUファームウェア，ブートローダ，U-bootをコピー（上で起動用microSDに行ったのと同じ作業）：

```shell
$ sudo mount /dev/XXX1 /mnt
$ sudo cp -r firmware-master/boot/* /mnt
$ sudo cp u-boot/u-boot.bin /mnt/kernel8.img
$ sudo umount /mnt
```



## システム起動
### Pi3での作業

システムをインストールしたUSBデバイスだけをPi3に接続して電源オン．うまく起動すれば成功．
あとはデスクトップ環境をインストールするなり，LAMPサーバにするなりよしなにどうぞ．



## 起動後の話

最初に`sudo apt upgrade`した際に

```
Couldn't find DTB bcm2710-rpi-3-b.dtb ...
```

というエラーが発生し，`upgrade`が完了しなかった．`/etc/flash-kernel/dtbs/`に`bcm2710-rpi-3-b.dtb`が見当たらない，という意味に読めたので

```shell
$ wget https://github.com/raspberrypi/firmware/blob/master/boot/bcm2710-rpi-3-b.dtb
$ sudo cp bcm2710-rpi-3-b.dtb /etc/flash-kernel/dtbs/
```

を実行．
改めて`upgrade`すると，今度は

```
mv: cannot move ...
```

とエラー．

```shell
$ sudo mkdir /boot/firmware
```

して`upgrade`するとエラーが消えた．
（このような対処で適切なのかどうか不明．よくわかっていません）

（2019.7.2追記．他のモデルのRaspberryPiの場合は https://github.com/raspberrypi/firmware/blob/master/boot/ から適切なdtbファイルを取得して使ってください）



## お世話になったサイト

* [ARM/RaspberryPi - Ubuntu Wiki](https://wiki.ubuntu.com/ARM/RaspberryPi)
* [Raspberry Pi 3でarm64版Ubuntu 18.04 Bionicインストーラーを起動](http://denor.daa.jp/raspberry-pi-3でarm64版ubuntu-18-04-bionicインストーラーを起動)
* [Raspberry Pi3 USBデバイスからブートする方法 | ある計算機屋さんの手帳](http://my-web-site.iobb.net/~yuki/2017-09/raspberry-pi/usb-boot/)