Boot Pi from USB disk


Update 2019-11-17
Current versions of Raspberry Pi 4 do not support USB boot.

Tinkering with Raspberry Pi over Christmas, this note details setting Pi up to boot from USB disk.
A variant of these instructions

Some intructions (including the above) advise modifying /boot/config.txt to enable USB boot by adding program_usb_boot_mode=1
My experience is that this is not necessary, at least with recent Pi 3B+ which seems to have USB boot enabled by default.
Plus, the usb_boot_mode config directive does not seem to appear in the documentation for config.txt

# Value of 3020000a would indicate this Pi OS is capable of USB boot
root@pib:~# vcgencmd otp_dump | grep 17:
17:3020000a

Plug your USB drive in and get it’s disk device name, sda in this case:

root@pib:~# lsblk
NAME        MAJ:MIN RM   SIZE RO TYPE MOUNTPOINT
sda           8:0    0 111.8G  0 disk
mmcblk0     179:0    0  14.4G  0 disk
├─mmcblk0p1 179:1    0  43.9M  0 part /boot
└─mmcblk0p2 179:2    0  14.4G  0 part /

Run parted to configure the disk with 100M partition for boot and remainder of disk as ext4.
Note: if you are reusing an old disk then you might need to delete existing partitions (using rm) first.

root@pib:~# parted /dev/sda
GNU Parted 3.2
Using /dev/sda
Welcome to GNU Parted! Type 'help' to view a list of commands.
(parted) print
Model: Intenso SSD (scsi)
Disk /dev/sda: 120GB
Sector size (logical/physical): 512B/512B
Partition Table: msdos
Disk Flags:

Number  Start  End  Size  Type  File system  Flags

(parted) mktable msdos
Warning: The existing disk label on /dev/sda will be destroyed and all data on this disk will be lost. Do you want to continue?
Yes/No? yes
(parted) mkpart primary fat32 0% 100M
(parted) mkpart primary ext4 100M 100%
(parted) print
Model: Intenso SSD (scsi)
Disk /dev/sda: 120GB
Sector size (logical/physical): 512B/512B
Partition Table: msdos
Disk Flags:

Number  Start   End     Size    Type     File system  Flags
 1      1049kB  99.6MB  98.6MB  primary  fat32        lba
 2      99.6MB  120GB   120GB   primary  ext4         lba

(parted) quit
Information: You may need to update /etc/fstab.

Run lsblk to check new disk configuration, sda now displays two partitions.

root@pib:~# lsblk
NAME        MAJ:MIN RM   SIZE RO TYPE MOUNTPOINT
sda           8:0    0 111.8G  0 disk
├─sda1        8:1    0    94M  0 part
└─sda2        8:2    0 111.7G  0 part
mmcblk0     179:0    0  14.4G  0 disk
├─mmcblk0p1 179:1    0  43.9M  0 part /boot
└─mmcblk0p2 179:2    0  14.4G  0 part /

Format the new disk partitions, boot as vfat and the remainder as ext4.

root@pib:~# mkfs.vfat -n BOOT -F 32 /dev/sda1
mkfs.fat 4.1 (2017-01-24)

root@pib:~# mkfs.ext4 /dev/sda2
mke2fs 1.43.4 (31-Jan-2017)
Creating filesystem with 29280768 4k blocks and 7323648 inodes
Filesystem UUID: 6be6a0dc-de1a-4f93-9ca6-b192fb5b6df6
Superblock backups stored on blocks:
	32768, 98304, 163840, 229376, 294912, 819200, 884736, 1605632, 2654208,
	4096000, 7962624, 11239424, 20480000, 23887872

Allocating group tables: done
Writing inode tables: done
Creating journal (131072 blocks): done
Writing superblocks and filesystem accounting information: done

Mount the new disk partitions and install rsync (it may already be present):

root@pib:~# mkdir /mnt/target
root@pib:~# mount /dev/sda2 /mnt/target/
root@pib:~# mkdir /mnt/target/boot
root@pib:~# mount /dev/sda1 /mnt/target/boot/
root@pib:~# apt-get install rsync
Reading package lists... Done
Building dependency tree
Reading state information... Done
rsync is already the newest version (3.1.2-1+deb9u1).
0 upgraded, 0 newly installed, 0 to remove and 0 not upgraded.

Copy SD card to USB disk:

root@pib:~# rsync -ax --progress / /boot /mnt/target
sending incremental file list
./
bin/
bin/bash
        912,712 100%   69.93MB/s    0:00:00 (xfr#1, ir-chk=1520/1542)
... snipped ...

Refresh SSH server keys

root@pib:~# cd /mnt/target
root@pib:/mnt/target# mount --bind /dev dev
root@pib:/mnt/target# mount --bind /sys sys
root@pib:/mnt/target# mount --bind /proc proc
root@pib:/mnt/target# chroot /mnt/target
root@pib:/# rm /etc/ssh/ssh_host*
root@pib:/# dpkg-reconfigure openssh-server
Creating SSH2 RSA key; this may take some time ...
2048 SHA256:NDd/YHP7+k5nsS6fLNFbbEXCBUgXvs1+lFQcM5hy7BY root@pib.local.bits (RSA)
Creating SSH2 ECDSA key; this may take some time ...
256 SHA256:sD3yIMHAqjdVmfVCeTjjhk6uBaX4OOv//AX5wD9xeRA root@pib.local.bits (ECDSA)
Creating SSH2 ED25519 key; this may take some time ...
256 SHA256:Oc9q/MY3YQ3048PzsqPCGdysBVpwaWyUTaep1CnDifo root@pib.local.bits (ED25519)
Running in chroot, ignoring request.
root@pib:/# exit
exit
root@pib:/mnt/target# umount dev
root@pib:/mnt/target# umount sys
root@pib:/mnt/target# umount proc

Run blkid to get UUID’s of new partions (this is variation on instructions given in above link)

root@pib:/mnt/target# blkid -o export
...snipped...

DEVNAME=/dev/sda1
LABEL=BOOT
UUID=ACC2-B94D
TYPE=vfat
PARTUUID=590ea081-01

DEVNAME=/dev/sda2
UUID=6be6a0dc-de1a-4f93-9ca6-b192fb5b6df6
TYPE=ext4
PARTUUID=590ea081-02

Update partition UUID’s (e.g. PARTUUID) in cmdline.txt and fstab
Note: Edit the ones on USB disk, not the originals on SD card :-)

root@pib:/mnt/target# cat /mnt/target/boot/cmdline.txt
dwc_otg.lpm_enable=0 console=serial0,115200 console=tty1 root=PARTUUID=cab20800-02 rootfstype=ext4 elevator=deadline fsck.repair=yes rootwait

root@pib:/mnt/target# vi /mnt/target/boot/cmdline.txt

root@pib:/mnt/target# cat /mnt/target/boot/cmdline.txt
dwc_otg.lpm_enable=0 console=serial0,115200 console=tty1 root=PARTUUID=590ea081-02 rootfstype=ext4 elevator=deadline fsck.repair=yes rootwait

root@pib:/mnt/target# cat /mnt/target/etc/fstab
proc            /proc           proc    defaults          0       0
PARTUUID=cab20800-01  /boot           vfat    defaults          0       2
PARTUUID=cab20800-02  /               ext4    defaults,noatime  0       1
# a swapfile is not a swap partition, no line here
#   use  dphys-swapfile swap[on|off]  for that

root@pib:/mnt/target# vi /mnt/target/etc/fstab

root@pib:/mnt/target# cat /mnt/target/etc/fstab
proc            /proc           proc    defaults          0       0
PARTUUID=590ea081-01  /boot           vfat    defaults          0       2
PARTUUID=590ea081-02  /               ext4    defaults,noatime  0       1
# a swapfile is not a swap partition, no line here
#   use  dphys-swapfile swap[on|off]  for that

Unmount USB disk and power off Pi

root@pib:/mnt/target# cd
root@pib:~# umount /mnt/target/boot
root@pib:~# umount /mnt/target
root@pib:~# poweroff

Remove power from Pi before removing SD card …
Once SD card removed, power up Pi and it should boot from USB disk

Comment on this article using form below. Requires email login only for authentication. HTML forbidden, Markdown only.