RaspberryPi zero WをUSB-bootさせる方法 検証済
1. 目的
Raspberry Pi Zero W(初代)で、SDカード上のRaspberry Pi OSをUSBメモリへコピーし、USBメモリ上のOSから起動する。
初代Raspberry Pi Zero Wは、原則としてSDカードを完全に取り外したUSB起動には対応していない。本手順ではSDカードを起動の仲介に使用し、OS本体と通常の書き込み先をUSBメモリに移す。
2. 今回使用した環境
- 本体: Raspberry Pi Zero W Rev 1.1
- OS: Raspbian GNU/Linux 13 (trixie)
- コピー元SDカード:
/dev/mmcblk0、14.5 GiB - コピー先USBメモリ:
/dev/sda、57.3 GiB - SDカードのディスク識別子:
440dc92b - USBメモリのディスク識別子:
6b7a1234
注意: /dev/sdaなどのデバイス名とPARTUUIDは環境ごとに異なる。作業前に必ず確認すること。
3. 重要な注意事項
- USBメモリ内のデータはすべて消去される。
- コピー元とコピー先を逆にすると、起動中のSDカードを破壊する恐れがある。
- 電源はZero Wの「PWR IN」端子へ接続する。
- USBメモリはOTGアダプターなどを介して「USB」端子へ接続する。
- USB起動の確認が終わるまで、SDカードを初期化しない。
- コマンドはSSH接続したRaspberry Pi上で実行する。
4. 機種とデバイスの確認
cat /proc/device-tree/model; echo
lsblk -o NAME,SIZE,TYPE,FSTYPE,MOUNTPOINTS,MODEL
USB側の識別情報確認
sudo blkid /dev/sda1 /dev/sda2
sudo file -s /dev/sda1 /dev/sda2
今回の環境では次のように判定した。
/dev/mmcblk0: 起動中のSDカード/dev/sda: コピー先USBメモリ
続いて、OS、空き容量、パーティション情報を確認する。
cat /etc/os-release
df -h /
sudo fdisk -l /dev/mmcblk0 /dev/sda
cat /boot/firmware/cmdline.txt
cat /etc/fstab
sudo blkid /dev/mmcblk0p1 /dev/mmcblk0p2
5. 必要なツールのインストール
sudo apt update
sudo apt install -y rsync dosfstools parted
6. USBメモリのパーティション作成
警告: 以下の操作で/dev/sdaの内容はすべて消去される。実行前にデバイス名を再確認する。
sudo umount /dev/sda1 2>/dev/null || true
sudo sfdisk /dev/sda <<'EOF'
label: dos
label-id: 0x6b7a1234
unit: sectors
/dev/sda1 : start=16384, size=1048576, type=c
/dev/sda2 : start=1064960, type=83
EOF
sudo partprobe /dev/sda
sudo udevadm settle
sudo mkfs.vfat -F 32 -n bootfs /dev/sda1
sudo mkfs.ext4 -F -L rootfs /dev/sda2
label-idはUSB用の新しい値を使用する。SDカードの識別子と同じ値にしないこと。
7. USBメモリのマウント
sudo mkdir -p /mnt/usb-root /mnt/usb-boot
sudo mount /dev/sda2 /mnt/usb-root
sudo mkdir -p /mnt/usb-root/boot/firmware
sudo mount /dev/sda1 /mnt/usb-boot
マウント状態を確認する。
findmnt /mnt/usb-root
findmnt /mnt/usb-boot
8. OSと起動ファイルのコピー
ルートファイルシステムをコピーする。Zero Wでは時間がかかる場合がある。
sudo rsync -aHAXx --numeric-ids --info=progress2 / /mnt/usb-root/
起動パーティションをコピーする。
sudo rsync -rt --delete --info=progress2 \
/boot/firmware/ /mnt/usb-boot/
コピー後の容量を確認する。
sudo du -sh /mnt/usb-root /mnt/usb-boot
今回の結果は、USBルートが約2.4 GB、USB起動領域が約84 MBだった。USB起動領域が4 KB程度の場合は、起動ファイルがコピーされていない。
9. USB側の起動設定変更
USB側のPARTUUIDを確認する。
sudo blkid /dev/sda1 /dev/sda2
今回のUSB側PARTUUIDは次のとおり。
- 起動領域:
6b7a1234-01 - ルート領域:
6b7a1234-02
USBのcmdline.txtで、ルートファイルシステムをUSBへ変更する。
sudo sed -i 's/440dc92b-02/6b7a1234-02/g' \
/mnt/usb-boot/cmdline.txt
USBのfstabを変更する。
sudo sed -i 's/440dc92b-01/6b7a1234-01/g' \
/mnt/usb-root/etc/fstab
sudo sed -i 's/440dc92b-02/6b7a1234-02/g' \
/mnt/usb-root/etc/fstab
設定を確認する。
sudo cat /mnt/usb-boot/cmdline.txt
sudo cat /mnt/usb-root/etc/fstab
期待する設定は次のとおり。
cmdline.txt: root=PARTUUID=6b7a1234-02
fstab:
PARTUUID=6b7a1234-01 /boot/firmware vfat defaults 0 2
PARTUUID=6b7a1234-02 / ext4 defaults,noatime 0 1
10. SD側からUSBルートを指定
SDカード側の設定をバックアップする。
sudo cp /boot/firmware/cmdline.txt \
/boot/firmware/cmdline.txt.sd-backup
SDカード側のcmdline.txtでも、ルートファイルシステムをUSBに指定する。
sudo sed -i 's/440dc92b-02/6b7a1234-02/g' \
/boot/firmware/cmdline.txt
grep -o 'root=[^ ]*' /boot/firmware/cmdline.txt
次のように表示されることを確認する。
root=PARTUUID=6b7a1234-02
11. アンマウントと再起動
sudo sync
sudo umount /mnt/usb-boot
sudo umount /mnt/usb-root
sudo reboot
SSH接続が切れたら1~3分ほど待ち、同じIPアドレスへ再接続する。
12. USB起動の確認
findmnt /
findmnt /boot/firmware
lsblk -o NAME,SIZE,FSTYPE,PARTUUID,MOUNTPOINTS
成功時は次のようになる。
/ /dev/sda2
/boot/firmware /dev/sda1
今回の環境では、ルートOSと起動パーティションの両方がUSBメモリ上にマウントされた。
13. 安定性の確認
数回再起動し、毎回ルートが/dev/sda2になることを確認する。
sudo reboot
再接続後:
findmnt /
14. 起動できない場合の復旧
USBから起動できなくなった場合は、SDカードを別のPCなどで開き、起動パーティションにあるバックアップを元へ戻す。
cmdline.txt.sd-backup → cmdline.txt
Linux上で復旧する場合の例:
sudo cp /boot/firmware/cmdline.txt.sd-backup \
/boot/firmware/cmdline.txt
USBメモリの認識が遅い、電力不足、USBメモリとの相性などでも起動に失敗する場合がある。
15. 補足
この構成では、通常のOS書き込みはUSBメモリ側で行われるため、SDカードの消耗を抑えられる。現在のSDカードには復旧用OSも残っているので、USB起動が安定するまでは初期化しないことを推奨する。
追記!!!
Raspberry Pi Zero W USBブート作業まとめ
1. 最終的な構成
今回のRaspberry Pi Zero W Rev 1.1は、次の流れで起動しています。
電源投入
↓
SDカードのbootcode.binを読み込む
↓
USBメモリーを検出
↓
USBの起動領域 /dev/sda1 を読み込む
↓
USBのルート領域 /dev/sda2 からOSを起動
確認結果:
/ → /dev/sda2
/boot/firmware → /dev/sda1
root=PARTUUID=6b7a1234-02
つまり、OSはUSBメモリー上で動作しています。ただし、初代Zero Wでは起動補助用SDカードを抜けません。
2. 最初の状態
作業開始時はSDカードから起動していました。
/dev/mmcblk0p1 → /boot/firmware
/dev/mmcblk0p2 → /
確認コマンド:
findmnt /
findmnt /boot/firmware
lsblk -o NAME,SIZE,TYPE,FSTYPE,MOUNTPOINTS,MODEL
結果:
/ /dev/mmcblk0p2
/boot/firmware /dev/mmcblk0p1
この時点ではUSBメモリーは接続されていましたが、OSの起動元ではありませんでした。
3. デバイス名の見分け方
今回の構成:
/dev/mmcblk0 SDカード
/dev/sda USBメモリー
パーティション:
SDカード
/dev/mmcblk0p1 FAT32 起動領域
/dev/mmcblk0p2 ext4 ルート領域
USBメモリー
/dev/sda1 FAT32 起動領域
/dev/sda2 ext4 ルート領域
確認コマンド:
lsblk -o NAME,SIZE,TYPE,FSTYPE,MOUNTPOINTS,MODEL
sudo fdisk -l /dev/mmcblk0 /dev/sda
/dev/sdaという名前は固定ではありません。接続状況によって変化する可能性があるため、必ず容量やモデル名も確認します。
今回のUSBは次で識別できました。
57.3G
MODEL=Ultra
4. PARTUUIDが重要な理由
Linuxのデバイス名/dev/sdaは変化する可能性があります。そのためRaspberry Pi OSは通常、ディスク固有のPARTUUIDで起動先を指定します。
確認コマンド:
sudo blkid
今回の値:
SD boot:PARTUUID=fb23ce46-01
SD root:PARTUUID=fb23ce46-02
USB boot:PARTUUID=6b7a1234-01
USB root:PARTUUID=6b7a1234-02
末尾の意味:
-01 → 第1パーティション
-02 → 第2パーティション
SDとUSBで同じPARTUUIDが重複していないことが重要です。
5. cmdline.txtの役割
USBの起動領域にあるファイルです。
cat /boot/firmware/cmdline.txt
USB側では次の指定になっていました。
root=PARTUUID=6b7a1234-02
これは次の意味です。
OSのルートファイルシステムとして
USBメモリーの第2パーティションを使用する
注意点:
cmdline.txtは原則として1行のままにする- USBのルート領域
-02を指定する rootwaitを残す- USB認識が完了するまで待たせる
6. fstabの役割
USB側OSのマウント設定です。
cat /etc/fstab
今回の正常な設定:
PARTUUID=6b7a1234-01 /boot/firmware vfat defaults 0 2
PARTUUID=6b7a1234-02 / ext4 defaults,noatime 0 1
対応関係:
6b7a1234-01 → USBの起動領域
6b7a1234-02 → USBのルート領域
cmdline.txtだけUSBを指定しても、fstabがSDを指定したままだと、起動途中やマウント時に問題が起きます。
7. USBファイルシステムの問題
USBのext4領域を検査したところ、次の状態でした。
needs journal recovery
修復コマンド:
sudo e2fsck -f /dev/sda2
結果:
rootfs: recovering journal
rootfs: ***** FILE SYSTEM WAS MODIFIED *****
これは、USBが以前に正常にアンマウントされなかったなどの理由で、ジャーナルの回復が必要だったことを示します。
重要事項:
e2fsckは対象パーティションをアンマウントして実行する- マウント中のルートファイルシステムには実行しない
- 実行前に対象デバイスを必ず確認する
8. カーネルモジュールの確認
SD側から読み込まれるカーネルと、USB側OSのモジュールが対応しているか確認しました。
uname -r
ls -1 /mnt/usb-root/lib/modules
使用中のカーネル:
6.12.75+rpt-rpi-v6
USB側にも次が存在しました。
/lib/modules/6.12.75+rpt-rpi-v6
この版が存在しないと、USB起動後にWi-Fiなどのドライバーを読み込めない可能性があります。
9. OTP設定について
確認コマンド:
vcgencmd otp_dump | grep '^17:'
結果:
17:1020000a
作業途中でprogram_usb_boot_mode=1を使う案が出ましたが、今回の初代Zero W Rev 1.1では使用しませんでした。
program_usb_boot_mode=1
は設定していません。
今回採用したのは、SDカードのbootcode.binからUSBへ起動処理を引き継ぐ方式です。
10. SDカードを起動補助用へ変更
変更前にSD起動領域をバックアップしました。
sudo tar -C /boot/firmware \
-czpf /home/pi/sd-boot-backup-raspZW-05.tar.gz .
SDの起動ファイルをサブディレクトリへ退避:
sudo mkdir /boot/firmware/sd-full-boot-disabled
sudo find /boot/firmware -mindepth 1 -maxdepth 1 \
! -name sd-full-boot-disabled \
-exec mv -t /boot/firmware/sd-full-boot-disabled -- {} +
bootcode.binをルートへ戻します。
sudo cp \
/boot/firmware/sd-full-boot-disabled/bootcode.bin \
/boot/firmware/bootcode.bin
USB認識待ち用ファイルを作成:
sudo touch /boot/firmware/timeout
sync
SD起動領域の最終構成:
bootcode.bin
timeout
sd-full-boot-disabled/
timeoutはUSBメモリーが認識されるまでの待ち時間を延ばします。
11. USB起動後にWi-Fiへ接続できなかった原因
USB起動自体は成功していましたが、USB側OSのWi-Fi設定がありませんでした。
調査したところ:
/etc/NetworkManager/system-connections/
には接続設定がなく、Netplanファイルも0バイトでした。
/etc/netplan/90-NM-....yaml
サイズ:0バイト
つまり、SD側にはWi-Fi設定があっても、USB側OSには有効なWi-Fi設定がありませんでした。
12. Windows 11でUSBのext4を編集
Windowsはext4を通常読み書きできません。そのためWSL2を導入しました。
wsl --install -d Ubuntu
ただし、次の方法はUSBメモリーでは使用できませんでした。
wsl --mount \\.\PHYSICALDRIVE7
エラー:
0x8007000f
指定されたドライブが見つかりません
wsl --mountはUSBフラッシュメモリーを直接扱えないため、usbipd-winを使用しました。
インストール:
winget install --interactive --exact dorssel.usbipd-win
USB確認:
usbipd list
SanDiskはVIDが0781だったため、対象は次でした。
BUSID 3-2
VID:PID 0781:558a
管理者PowerShellで接続:
usbipd bind --busid 3-2
usbipd attach --wsl --busid 3-2
Ubuntu側ではUSBが次として見えました。
/dev/sde
/dev/sde1 vfat
/dev/sde2 ext4
ここでも/dev/sdeは固定ではないため、容量、ラベル、モデルで確認します。
lsblk -o NAME,SIZE,FSTYPE,LABEL,MOUNTPOINTS,MODEL
13. Wi-Fi設定の作成
USBルートをマウント:
sudo mkdir -p /mnt/raspi-root
sudo mount /dev/sde2 /mnt/raspi-root
NetworkManager設定を作成しました。
重要部分:
[connection]
type=wifi
interface-name=wlan0
autoconnect=true
[wifi]
mode=infrastructure ssid=TP-LINK_B698
[wifi-security]
key-mgmt=wpa-psk psk=Wi-Fiパスワード
[ipv4]
method=auto
[ipv6]
method=auto
保存場所:
/etc/NetworkManager/system-connections/wifi.nmconnection
権限:
sudo chmod 600 \
/mnt/raspi-root/etc/NetworkManager/system-connections/wifi.nmconnection
NetworkManager接続ファイルは、rootだけが読める600にする必要があります。
設定確認:
sudo grep -E '^(ssid|key-mgmt)=' \
/mnt/raspi-root/etc/NetworkManager/system-connections/wifi.nmconnection
sudo grep -q '^psk=.\+$' \
/mnt/raspi-root/etc/NetworkManager/system-connections/wifi.nmconnection \
&& echo "Password: configured" \
|| echo "Password: EMPTY"
確認結果:
ssid=TP-LINK_B698
key-mgmt=wpa-psk
Password: configured
14. 最終確認
USB起動後に実行:
hostname
findmnt /
findmnt /boot/firmware
lsblk -o NAME,SIZE,FSTYPE,MOUNTPOINTS,MODEL
cat /proc/cmdline
結果:
hostname:raspZW-05
/:/dev/sda2
/boot/firmware:/dev/sda1
root=PARTUUID=6b7a1234-02
これにより、USB起動成功と判断できます。
15. 今回起きた問題
- 最初はSDカードから起動していた
USBは接続されていましたが、起動元ではありませんでした。 - USBのext4にジャーナル未回復があった
e2fsckで修復しました。 - Zero Wに不適切なOTP設定を検討した
実際には書き込まず、bootcode.bin方式へ修正しました。 - USB起動後にWi-Fi接続できなかった
USB側OSのWi-Fi設定が空でした。 - Windowsの
wsl --mountでUSBを開けなかった
USBメモリー非対応のため、usbipd-winを使用しました。 - Ubuntu用コマンドをPowerShellで実行した
syncやumountはUbuntu側、usbipdはWindows PowerShell側で実行する必要があります。
16. 今後の注意事項
- SDカードは抜かない
- SDには最低限
bootcode.binが必要 - USB交換時は
PARTUUIDを再確認する cmdline.txtとfstabの両方をUSBのPARTUUIDへ合わせる- Zero Wは2.4GHz Wi-Fiのみ対応
- USBを抜く前に
syncとumountを実行する - Windowsの「フォーマットしますか」は必ずキャンセルする
/dev/sdaや/dev/sdeを決め打ちしないfdisk、mkfs、e2fsckの前には対象ディスクを再確認する