raspberry pi 4 でubuntu20.04をusbブートするの巻

はじめに

ラズベリーパイ4はUSB3.0が追加され、ここに外部ストレージを追加するとmicrosdより高耐久で高速な環境にする事ができます。

ちなみに、どんなに高速なmicrosdを用意しても、ラズパイのカードリーダーが30MB/sほどの性能しか無いのでお察しです。

(良い品質のmicrosdを使えばランダム性能は上がる)

用意するもの

イメージの書き込み

rasbianをmicrosdに、ubuntuをusbに書き込みます。

ちなみに、OSの選択で書き込みOSを選択できますが、ダウンロードしながら書き込むのでとても遅いです。

事前にイメージをダウンロードしてから書き込むことを推奨します。

microsdに書き込み

画像のように行えば書き込むことができます。

書き込み完了後、SSHを利用できるようにするために、「ssh」という空のファイルを作成しておきます。

bootが見つからない場合は、sdを抜き差しすると見えます。

USBに書き込み

同様にしてubuntuをusbに書き込みます。

raspberry pi の起動

rasberry pi にmicrosdと電源、LANケーブルを接続し、起動します。

ユーザー名はpi、パスワードはraspberryです。

入れると以下のようになります。

PS C:\Users\pcuser> ssh pi@192.168.1.172
The authenticity of host '192.168.1.172 (192.168.1.172)' can't be established.
ECDSA key fingerprint is SHA256:i26a1np9/e+3u7l1hIJdVGVQXII79iuM6TxYpbY1wPs.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added '192.168.1.172' (ECDSA) to the list of known hosts.
pi@192.168.1.172's password:
Linux raspberrypi 5.4.51-v7l+ #1333 SMP Mon Aug 10 16:51:40 BST 2020 armv7l
The programs included with the Debian GNU/Linux system are free software;
the exact distribution terms for each program are described in the
individual files in /usr/share/doc/*/copyright.
Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent
permitted by applicable law.
SSH is enabled and the default password for the 'pi' user has not been changed.
This is a security risk - please login as the 'pi' user and type 'passwd' to set a new password.
Wi-Fi is currently blocked by rfkill.
Use raspi-config to set the country before use.
pi@raspberrypi:~ $

eepromの確認

以下のコマンドを実行することで、ラズパイのeepromのバージョンを確認できます。

pi@raspberrypi:~ $ vcgencmd bootloader_version
Mar 19 2020 14:27:25
version 940f978d13e45be9baef77f3f4a13b76a832f7b4 (release)
timestamp 1584628045

色々更新

とりあえず以下のコマンドを実行し、システムを更新します。

sudo apt update
sudo apt upgrade -y
sudo reboot

再起動後にeepromのバージョンを確認すると、更新されている事がわかります。

pi@raspberrypi:~ $ vcgencmd bootloader_version
Sep  3 2020 13:11:43
version c305221a6d7e532693cc7ff57fddfc8649def167 (release)
timestamp 1599135103

ブートオーダーの設定

ラズパイはeepromに記載された手順に従ってプログラムをロードします。

つまり、通常のPCのようにどこからどの順番で読み込みを試みるかという、起動順序があります。

以下のコマンドで現在の設定状態がわかります。

pi@raspberrypi:~ $ vcgencmd bootloader_config
[all]
BOOT_UART=0
WAKE_ON_GPIO=1
POWER_OFF_ON_HALT=0
DHCP_TIMEOUT=45000
DHCP_REQ_TIMEOUT=4000
TFTP_FILE_TIMEOUT=30000
TFTP_IP=
TFTP_PREFIX=0
BOOT_ORDER=0x1
SD_BOOT_MAX_RETRIES=3
NET_BOOT_MAX_RETRIES=5
[none]
FREEZE_VERSION=0

BOOT_ORDER がブート順序になります。ここには以下のような意味があります。

  • 0x0 – NONE (stop with error pattern)
  • 0x1 – SD CARD
  • 0x2 – NETWORK
  • 0x3 – USB device boot – Reserved – Compute Module only.
  • 0x4 – USB mass storage boot (since 2020-09-03)
  • 0xf – RESTART (loop) – start again with the first boot order field. (since 2020-09-03)

BOOT_ORDER=0xf41

であれば、「USBで起動し、できなければSDで起動する。両方失敗したら、最初から繰り返す」

という意味になります。

詳しい解説はこちらを御覧ください

で、現在はsdカードからしか起動しません。

この設定を手動で書き換えてもよいのですが、aptによる更新で上書きされる恐れがあるのでデフォルトの方を変更します。

以下のように「critical」を「stable」に書き換えます。これでaptはstableをインストールするようになります。

pi@raspberrypi:~ $ cat /etc/default/rpi-eeprom-update
FIRMWARE_RELEASE_STATUS="critical"
pi@raspberrypi:~ $ cat /etc/default/rpi-eeprom-update
FIRMWARE_RELEASE_STATUS="stable"

あとはstableを書き込みます。

バイナリの日付は最新のものを選んでください。

pi@raspberrypi:~ $ sudo rpi-eeprom-update -d -f /lib/firmware/raspberrypi/bootloader/stable/pieeprom-2020-09-03.bin
BCM2711 detected
VL805 firmware in bootloader EEPROM
*** INSTALLING /lib/firmware/raspberrypi/bootloader/stable/pieeprom-2020-09-03.bin  ***
BOOTFS /boot
EEPROM update pending. Please reboot to apply the update.

再起動するとUSBブートが有効になります。

pi@raspberrypi:~ $ vcgencmd bootloader_config
[all]
BOOT_UART=0
WAKE_ON_GPIO=1
POWER_OFF_ON_HALT=0
DHCP_TIMEOUT=45000
DHCP_REQ_TIMEOUT=4000
TFTP_FILE_TIMEOUT=30000
ENABLE_SELF_UPDATE=1
DISABLE_HDMI=0
BOOT_ORDER=0xf41

ubuntuの設定

これでubuntuのUSBを指して終了!!

と言いたいところですが、ubuntuのカーネルは圧縮されているため、このままだとラズパイは認識できません。

なので、

  • 初期ramイメージの圧縮解除
  • 起動イメージの場所の変更
  • aptでの更新時に初期ramの圧縮解除

の設定を行わないといけません。

この処理は将来的に、ubuntuか、ラズパイで対応されるとは思うので、最新の情報を確認してください

ubuntuの書き込んだUSBをラズパイに接続します。

次にbootパーテーションをマウントします。

pi@raspberrypi:~ $ mkdir  boot
pi@raspberrypi:~ $ ls
boot
pi@raspberrypi:~ $ sudo mount -o uid=pi,gid=pi /dev/sda1 boot/
pi@raspberrypi:~ $ ls boot/
 bcm2710-rpi-2-b.dtb        bootcode.bin   fixup.dat         start4cd.elf  'System Volume Information'
 bcm2710-rpi-3-b.dtb        boot.scr       fixup_db.dat      start4db.elf   uboot_rpi_3.bin
 bcm2710-rpi-3-b-plus.dtb   cmdline.txt    fixup_x.dat       start4.elf     uboot_rpi_4.bin
 bcm2710-rpi-cm3.dtb        config.txt     initrd.img        start4x.elf    usercfg.txt
 bcm2711-rpi-4-b.dtb        fixup4cd.dat   meta-data         start_cd.elf   user-data
 bcm2837-rpi-3-a-plus.dtb   fixup4.dat     network-config    start_db.elf   vmlinuz
 bcm2837-rpi-3-b.dtb        fixup4db.dat   overlay_map.dtb   start.elf
 bcm2837-rpi-3-b-plus.dtb   fixup4x.dat    overlays          start_x.elf
 bcm2837-rpi-cm3-io3.dtb    fixup_cd.dat   README            syscfg.txt

vmlinuzを解凍します

pi@raspberrypi:~ $ cd boot/
pi@raspberrypi:~/boot $ zcat vmlinuz > vmlinux

config.txtを以下のように変更します。

[pi4]
max_framebuffers=2
dtoverlay=vc4-fkms-v3d
boot_delay
kernel=vmlinux
initramfs initrd.img followkernel
[pi2]
kernel=uboot_rpi_2.bin
[pi3]
kernel=uboot_rpi_3.bin
[all]
arm_64bit=1
device_tree_address=0x03000000
# The following settings are "defaults" expected to be overridden by the
# included configuration. The only reason they are included is, again, to
# support old firmwares which don't understand the "include" command.
enable_uart=1
cmdline=cmdline.txt
include syscfg.txt
include usercfg.txt

新しく「auto_decompress_kernel」を作成します

cat  auto_decompress_kernel
#!/bin/bash -e
#Set Variables
BTPATH=/boot/firmware
CKPATH=$BTPATH/vmlinuz
DKPATH=$BTPATH/vmlinux
#Check if compression needs to be done.
if [ -e $BTPATH/check.md5 ]; then
	if md5sum --status --ignore-missing -c $BTPATH/check.md5; then
	echo -e "\e[32mFiles have not changed, Decompression not needed\e[0m"
	exit 0
	else echo -e "\e[31mHash failed, kernel will be compressed\e[0m"
	fi
fi
#Backup the old decompressed kernel
mv $DKPATH $DKPATH.bak
if [ ! $? == 0 ]; then
	echo -e "\e[31mDECOMPRESSED KERNEL BACKUP FAILED!\e[0m"
	exit 1
else 	echo -e "\e[32mDecompressed kernel backup was successful\e[0m"
fi
#Decompress the new kernel
echo "Decompressing kernel: "$CKPATH".............."
zcat $CKPATH > $DKPATH
if [ ! $? == 0 ]; then
	echo -e "\e[31mKERNEL FAILED TO DECOMPRESS!\e[0m"
	exit 1
else
	echo -e "\e[32mKernel Decompressed Succesfully\e[0m"
fi
#Hash the new kernel for checking
md5sum $CKPATH $DKPATH > $BTPATH/check.md5
if [ ! $? == 0 ]; then
	echo -e "\e[31mMD5 GENERATION FAILED!\e[0m"
	else echo -e "\e[32mMD5 generated Succesfully\e[0m"
fi
#Exit
exit 0
chmod +x auto_decompress_kernel

bootをアンマウントします。

pi@raspberrypi:~ $ cd
pi@raspberrypi:~ $ sudo umount boot

システムパーテーションをマウントします。

pi@raspberrypi:~ $ mkdir root
pi@raspberrypi:~ $ sudo mount  /dev/sda2 root/

apt時に自動で解答するために「999_decompress_rpi_kernel」を追加します。

pi@raspberrypi:~ $ cd root/etc/apt/apt.conf.d/
pi@raspberrypi:~ $ cat <<EOF | sudo tee 999_decompress_rpi_kernel
DPkg::Post-Invoke {"/bin/bash /boot/firmware/auto_decompress_kernel"; };
EOF
sudo chmod +x 999_decompress_rpi_kernel

これでubuntuの設定が終わりました。

ubuntuで起動

上記の状態でmicrosdを抜いて再起動するとusbのubuntuで起動します。

IPアドレスが変わる場合があるので注意

ユーザー名はubuntu、パスワードはubuntuです。

最初はパスワードの変更になります。

PS C:\Users\pcuser> ssh ubuntu@192.168.1.173
ubuntu@192.168.1.173's password:
You are required to change your password immediately (administrator enforced)
Welcome to Ubuntu 20.04.1 LTS (GNU/Linux 5.4.0-1015-raspi aarch64)
 * Documentation:  https://help.ubuntu.com
 * Management:     https://landscape.canonical.com
 * Support:        https://ubuntu.com/advantage
  System information as of Sat Oct 24 07:38:51 UTC 2020
  System load:  3.77              Temperature:           44.8 C
  Usage of /:   27.9% of 6.79GB   Processes:             155
  Memory usage: 4%                Users logged in:       0
  Swap usage:   0%                IPv4 address for eth0: 192.168.1.173
 * Introducing autonomous high availability clustering for MicroK8s
   production environments! Super simple clustering, hardened Kubernetes,
   with automatic data store operations. A zero-ops HA K8s for anywhere.
     https://microk8s.io/high-availability
0 updates can be installed immediately.
0 of these updates are security updates.
The list of available updates is more than a week old.
To check for new updatesYou are required to change your password immediately (administrator enforced)
Welcome to Ubuntu 20.04.1 LTS (GNU/Linux 5.4.0-1015-raspi aarch64)
 * Documentation:  https://help.ubuntu.com
 * Management:     https://landscape.canonical.com
 * Support:        https://ubuntu.com/advantage
  System information as of Sat Oct 24 07:38:51 UTC 2020
  System load:  3.77              Temperature:           44.8 C
  Usage of /:   27.9% of 6.79GB   Processes:             155
  Memory usage: 4%                Users logged in:       0
  Swap usage:   0%                IPv4 address for eth0: 192.168.1.173
 * Introducing autonomous high availability clustering for MicroK8s
   production environments! Super simple clustering, hardened Kubernetes,
   with automatic data store operations. A zero-ops HA K8s for anywhere.
     https://microk8s.io/high-availability
0 updates can be installed immediately.
0 of these updates are security updates.
The list of available updates is more than a week old.
To check for new updates run: sudo apt update
WARNING: Your password has expired.
You must change your password now and login again!
Changing password for ubuntu.
Current password:
New password:
Retype new password:
passwd: password updated successfully
Connection to 192.168.1.173 closed.

これでubuntuをusbでブートすることができました。

ubuntu@ubuntu:~$ df -h
Filesystem      Size  Used Avail Use% Mounted on
udev            3.7G     0  3.7G   0% /dev
tmpfs           782M  4.0M  778M   1% /run
/dev/sda2       6.8G  2.0G  4.6G  30% /
tmpfs           3.9G     0  3.9G   0% /dev/shm
tmpfs           5.0M     0  5.0M   0% /run/lock
tmpfs           3.9G     0  3.9G   0% /sys/fs/cgroup
/dev/sda1       253M   84M  169M  34% /boot/firmware
/dev/loop0       26M   26M     0 100% /snap/snapd/8543
/dev/loop1       49M   49M     0 100% /snap/core18/1883
/dev/loop2       64M   64M     0 100% /snap/lxd/16103
tmpfs           782M     0  782M   0% /run/user/1000
ubuntu@ubuntu:~$ sudo fdisk /dev/sda -l
Disk /dev/sda: 7.22 GiB, 7743995904 bytes, 15124992 sectors
Disk model: PicoDriveL3
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: dos
Disk identifier: 0xab86aefd

aptで更新しても、最後に初期ramの解凍処理が行われるので起動しなくなることはなくなります。