Booting from a Hard Disk - sakaki-/gentoo-on-rpi-64bit GitHub Wiki

This is a list of instructions on how to install gentoo onto a hard disk for the Rpi4 using genpi64 as a basis. This guide assumes you've already setup genpi64 on a SD card and are able to ssh or access the console over the network.

Hardware

For the enclosure / Sata interface for this example I'm using parts from GeekWorm

  • Rpi 4 8Gb
  • 16Gb Micro SD Card
  • Geekworm Raspberry Pi X735 (allows control over the power like ATX / acts as a fan for the Pi Board)
  • Geekworm Raspberry Pi 4 NAS Dual SATA, X829 - allows the attachment of 2 x Sata disks to an Rpi4 via USB3 and provides a couple of USB3 ports as a hub
  • Geekworm X829-C1 Matching Metal Case (include power switch / case fan)
  • Geekworm DC 5V 4A Power Adapter
  • 2 x BarraCuda 2 TB Internal Hard Drive 2.5 inch

Both disks show up fine with this setup as /dev/sda /dev/sdb Note a metal case will impact the wifi range though

UAS issues

With the Rpi3 and older there was no support for UAS when connecting to a Sata hard disk over USB. With the Rpi4 UAS is supported which is good since it offers better performance but it can cause issues with some sata USB controllers that don't support UAS fully and have not yet been properly blacklisted within the kernel

This was an issue I ran into, but it took a while to show up under dmesg

  • As a fix the first step is to get the vendor / product id of the usb device that handles the drive (in my case 174c:0829)
  • Add this to the /boot/cmdline.txt (Substituting your own vendor / product id's)
  • usb-storage.quirks=174c:0829:u
  • Then do a reboot

This will largely depend on the type of USB3 to Sata bridge you are using. The speed difference isn't that much for a regular disk, but may affect an SSD more (see below)

Determining sata speed

From the looks of things smartctl doesn't have support for this usb bridge yet

smartctl -i /dev/sda

#/dev/sda: Unknown USB bridge [0x174c:0x0829 (0x100)]
#Please specify device type with the -d option.

Another approach is hdparm

hdparm -I /dev/sda | egrep "Model|speed|Transport"
# For the X829 this shows
#*    Gen1 signaling speed (1.5Gb/s)
#*    Gen2 signaling speed (3.0Gb/s)
#*    Gen3 signaling speed (6.0Gb/s)
#*    SMART Command Transport (SCT) feature set

To run some timing tests

hdparm -tT /dev/sda

# For the X829 / BarraCuda drives

# UAS enabled
#/dev/sda:
# Timing cached reads:   2132 MB in  2.00 seconds = 1067.16 MB/sec
# Timing buffered disk reads: 386 MB in  3.01 seconds = 128.33 MB/sec

# UAS disabled (to prevent issues)
#/dev/sda:
# Timing cached reads:   2112 MB in  2.00 seconds = 1056.71 MB/sec
# Timing buffered disk reads: 350 MB in  3.01 seconds = 116.16 MB/sec

Setting up Partitions

First we're going to create three new partitions on the disk.

  • Boot partition - copy of /boot/ from the sd card
  • Swap partition
  • Root partition - copy of / from the sd card

The boot partition isn't really needed at this point but it may be useful later on once USB booting via the EEPROM is supported for the Rpi4

Setup the partition table

# To reset the partition table
parted /dev/sda mklabel msdos
# Create some new partitions
parted -a optimal /dev/sda mkpart primary fat32 0% 2048MB
parted -a optimal /dev/sda mkpart primary linux-swap 2048MB 18GB
parted -a optimal /dev/sda mkpart primary ext4 18.0GB 100%

Next lets format some partitions

mkfs.vfat -F 32 -n DISKBOOT /dev/sda1
mkswap /dev/sda2
mkfs.ext4 /dev/sda3

Copying over data

Copy Boot partition

Copy over the boot partition, just in case USB booting becomes a thing

mkdir /mnt/boot
mount -t auto /dev/sda1 /mnt/boot
cp -a /boot/* /mnt/boot/
umount /mnt/boot

Copy root partition

Mount the disk ext4 root where we will be copying the root files to

mkdir /mnt/diskroot
mount -t auto /dev/sda3 /mnt/diskroot

Mount the current root to a different directory, this avoid things like /sys/ files being picked up

mkdir /mnt/oldroot
mount -t auto /dev/mmcblk0p2 /mnt/oldroot

Copy over the data

rsync -aHS --progress /mnt/oldroot/. /mnt/diskroot/.

unmount the old root

umount /mnt/oldroot

Update fstab

Next we're going to update the fstab on the disk root. Run the following to get the UUID values

blkid -p /dev/sda1
blkid -p /dev/sda2
blkid -p /dev/sda3

The output will look something like this. The part we're interested in is the PART_ENTRY_UUID value for each partition We use PART_ENTRY_UUID instead of UUID as UUID is within the filesystem so may need a initramfs to read initially such as within cmdline.txt

/dev/sda3: UUID="247e836f-7929-4702-aadd-955dfc947d8c" VERSION="1.0" BLOCK_SIZE="4096" TYPE="ext4" USAGE="filesystem" PART_ENTRY_SCHEME="dos" PART_ENTRY_UUID="ea23b7f3-03" PART_ENTRY_TYPE="0x83" PART_ENTRY_NUMBER="3" PART_ENTRY_OFFSET="35155968" PART_ENTRY_SIZE="3871873024" PART_ENTRY_DISK="8:0"

Create a directory for the boot partition on the disk

mkdir /mnt/diskroot/boot-hd

Edit the fstab file

vi /mnt/diskroot/etc/fstab

Replace the lines

PARTUUID=7a0c8bb0-01    /boot           vfat    defaults          0       2
PARTUUID=7a0c8bb0-02    /               ext4    defaults,noatime  0       1
/var/cache/swap/swap1   none            swap    sw                0       0

With the PARTUUID values taken from blkid above, as an example (note the uuid valus will be different for your setup)

PARTUUID=ea23b7f3-01    /boot-hd        vfat    defaults          0       3
PARTUUID=7a0c8bb0-01    /boot           vfat    defaults          0       2
PARTUUID=ea23b7f3-03    /               ext4    defaults,noatime  0       1
PARTUUID=ea23b7f3-02    none            swap    sw                0       0

Finally unmount the disk root

umount /mnt/diskroot

Switch boot to hard disk

Now we're going to switch the boot process across to use the root partition on the disk instead of the sd card

First lets make a backup of the cmdline.txt just in case we need to boot from the sdcard at some point in the future in an emergency. (this file can be easily edited under linux or windows via a sd card reader)

cp cmdline.txt cmdline.txt.sdcard

Next edit the cmdline.txt file and replace

root=PARTUUID=7A0C8BB0-02

With the PARTUUID of the disk above

root=PARTUUID=ea23b7f3-03

Finally make a copy of cmdline.txt so that we can swap back and forth between the hard disk and the sd card just by copying a file

cp cmdline.txt cmdline.txt.hddisk

Reboot time

If all goes to plan then on the next reboot the OS should boot from the hard disk instead of the SD Card. the boot partition on the SD card will still be needed to startup the root on the hard disk. But hopefully in the future that can be switched across to the hard disk as well once the EEPROM features move out of beta

The way the mounts are setup above /boot will point to the SD card's boot /boot-hd will point to the boot partition on the hard disk (not yet used)

so any changes should be made to /boot for the boot process