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. 今回起きた問題

  1. 最初はSDカードから起動していた
    USBは接続されていましたが、起動元ではありませんでした。
  2. USBのext4にジャーナル未回復があった
    e2fsckで修復しました。
  3. Zero Wに不適切なOTP設定を検討した
    実際には書き込まず、bootcode.bin方式へ修正しました。
  4. USB起動後にWi-Fi接続できなかった
    USB側OSのWi-Fi設定が空でした。
  5. Windowsのwsl --mountでUSBを開けなかった
    USBメモリー非対応のため、usbipd-winを使用しました。
  6. Ubuntu用コマンドをPowerShellで実行した
    syncumountはUbuntu側、usbipdはWindows PowerShell側で実行する必要があります。

16. 今後の注意事項

  • SDカードは抜かない
  • SDには最低限bootcode.binが必要
  • USB交換時はPARTUUIDを再確認する
  • cmdline.txtfstabの両方をUSBのPARTUUIDへ合わせる
  • Zero Wは2.4GHz Wi-Fiのみ対応
  • USBを抜く前にsyncumountを実行する
  • Windowsの「フォーマットしますか」は必ずキャンセルする
  • /dev/sda/dev/sdeを決め打ちしない
  • fdiskmkfse2fsckの前には対象ディスクを再確認する

zero

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です