Boot RaspberryPi OS on an NVME larger than 2TB
RaspberryPi OS boots from an EFI partition. On other hardware, an EFI partition is used with UEFI which demands that your disk is GPT-partitioned or a hybrid GPT with MBR. However, the RaspberryPi imager and the installer you get when pressing Shift at boot uses MBR. MBR is a way to partition a disk that we used in the 1980s and that made sense back then, but it has the unfortunate limitation that it cannot use disks larger than 2 TB. So when I bought my 4 TB NVME to use with my Raspberry Pi 5, I was unpleasantly surprised that after installing RaspberryPi OS light, I could only see a 2 TB disk.
There are various solutions floating around the internet to get around this problem, but most of them are unnecessarily complex. The RaspberryPi 5 can boot from a disk partitioned with a GPT partition table just fine. The problem is just to get the right partitions with the right data onto the disk since the installer insists on using 1980s technology which means that you cannot use it on large disks. In the early 80s, a large hard drive had 40 MB capacity, so 2TB seemed like science fiction. Who would need all that space when Macintosh System Software, a few programs like MacWrite and MacDraw and a dozen files could fit on a 800kB diskette? (The Double Density 3.5 inch floppy disks that gave 720kB space on MS-DOS delivered 800kB on a Mac.)
In addition to your NVME, you will also need a USB stick and an SD card. If you use a case like my Argon Neo, installing the NVME and SD-card demands a bit of disassembly. The reason we need two other devices is that we need to clone one of them to the NVME and to do that we need to boot from the other. Here is what you need to do to your NVME working:
- Insert the SD-card and the NVME in your case or hat or whatever you use and insert an ethernet cable connected to your router.
- Boot your RaspberryPi while repeatedly pressing down the shift key until you get to the Raspberry Pi screen that downloads the installer.
- Install RaspberryPi OS (light) on the SD card.
- Boot from the SD card. If the boot order is set to boot from NVME first, you may have to press Space when booting to get to the boot order screen first. Since RaspberryPi OS reboots once as part of the isntallation, you may have to go through the boot order screen twice, so be ready to press space again after the first boot. After the second boot, the SD card has got RaspberryPi OS and the root partition (/) has been expanded.
- Insert your USB stick into one of the blue USB3 ports.
- Boot your Raspberry Pi again and repeatedly press down shift until you get to the screen that downloads the installer.
- Install RaspberryPi OS on your USB-stick.
- When the Pi reboots, press space repeatedly to get to the boot order screen and select USB and boot.
- Be ready to press space repeatedly again since the Pi reboots once as part of the installation process and choose USB again to boot the USB stick and let it expand the root partition.
- When you have booted into the USB stick for the second time after the root partition has been expanded, open a terminal (or use the TTY if you used RPi light).
- Write sudo fdisk /dev/nvme0n1 to partition the NVME with fdisk.
- Press g to make a new GPT partition table. You may have to confirm that you want to remove an MS-DOS (MBR) partition table already there.
- Press n to make a new partition.
- Choose the default as the first sector by pressing return.
- Write +512M to make the size of the partition half a Gigabyte.
- Press t to change a partition.
- Choose the default 1 as the partition you want to change.
- Set its type to 1 (EFI System).
- Make a new partition with n.
- Accept the defaults since it will use the rest of the disk.
- Press w to write your changes to the disk.
- Write dd if=/dev/mmcblk0p1 of=/dev/nvme0n1p1 && sync and press return. This will clone the first partition, the EFI partiont, of the SD card onto the first partition of the NVME.
- Write dd if=/dev/mmcblk0p2 of=/dev/nvme0n1p2 && sync and press return. This will clone the second partition, the root partition, of the SD card onto the second partition of the NVME.
- Write sudo mount /dev/nvme0n1p1 /mnt to mount the EFI partition of the NVME to /mnt on your running system (from the USB stick).
- Write lsblk -f to get the UUID of the root partition of the NVME (/dev/nvme0n1p2).
- Open the file /mnt/cmdline.txt with sudo in a text editor. (I prefer to combine step 25 up to and including 33 since Emacs has a built in terminal multiplexer and tiling window manager, and it is easier to copy the UUID from one window in Emacs to another window than to try to remember a UUID from lsblk -f from before I opened Emacs. I also use tramp inside Emacs to open the files with sudo instead of opening emacs with sudo. If you use another text editor in a TTY, then you probably have to write the UUID down after running lsblk -f since your text editor will hide the output from that command when you launch it to edit the file, unless you use GNU screen or tmux.)
- Change where it says root=PARTUUID=somenumber to root=UUID= and write or paste the UUID from lsblk -f for /dev/nvme0n1p2.
- Save the file and exit the text editor if you use a TTY editor without a built in terminal multiplexer.
- Write sudo umount /mnt and press return to unmount the first partition.
- Write sudo mount /dev/nvme0n1p2 /mnt to mount the root partition from the NVME to /mnt on your running system (the USB stick). If it tells you the disk is busy, wait for it. It means that the disk is still writing even if it has tld the OS it has finished. If you fail to wait, then you cannot boot.
- Write lsblk -f again and note down the UUID of both /dev/nvme0n1p1 (the EFI partition) and /dev/nvme0n1p2 if you did not already note it down. (Or use a terminal multiplexer or Emacs to copy it over when you need it.)
- Open the file /mnt/etc/fstab in a text editor with sudo.
- Replace the part of the line that says PARTUUID=somenumber on the line where it says /boot/firmware with UUID= and write or paste the UUID number for /dev/nvme0n1p1 (the EFI partition).
- Do the same with line where it says /, but use the UUID for /dev/nvme0n1p2 (the root partition).
- Save the file and exit your text editor.
- Wait for a while to allow time for the nvme to write out the change. Turn off the RaspberryPi.
- Remove the SD card and the USB stick.
- Reboot the Raspberry Pi. It should now boot from the NVME. If the boot order is set to boot USB or SD Card first, you may have to press space when booting to boot from the NVME. In such a case, you should write sudo raspi-config in a terminal and go to Advanced Options, choose A4 Boot order, and choose B2 NVME/USB Boot … and then press OK and finish and reboot. It should now boot from the NVME. If something went wrong and you end up in an emergency shell, then reboot, insert the USB and SD card again, press space and try again.
I now have a 4TB NVME that boots my RaspberryPi 5. I also tried booting from SD card and using the NVME only as storage for a while, but it was slow and annoying, so it is really worth spending some time to get the Pi booting from the NVME. Hopefully, the RaspberryPi devs will change the imager and installer so they use the GPT partition scheme in the future. There is no reason to use MBR in the 21st century.