User avatar
Posts: 11
Joined: Sat Jul 17, 2021 4:26 am

HOWTO: Move the rootfs to native SATA (no usb adapter)

Mon Aug 16, 2021 3:56 pm

I'm writing this in the hopes it will be helpful to others who may want this kind of setup. All of the guides I found were for using a USB encolsure/adapter.

This guide is intended for use with a CM4 + IO board, but may be helpful for other hardware/board setups as well.

This setup was most useful for me as I am using a pcie multiplier (ASM1184e) with multiple different cards attached, including a SATA multiplier card (JMB585). I have a bunch of HDDs attached for large/cheap storage, but I wanted to add a SSD to use as my main linux filesystem (rootfs). (Currently there is no way to boot directly off of a drive attached over a pcie bridge).

The short version:
You need to ensure the SATA drivers are built-in to the kernel and not built as modules. When I was first trying to get this to work, I could see my pcie bridge was loaded in the dmesg logs before the kernel tried to load the rootfs, but the SATA drivers weren't loaded until way after. After I dug into how to change the driver load order, I realized you could just statically link them.

Ensure they look like this in your kernel .config before building:

Code: Select all

And not this:

Code: Select all

Otherwise they are loaded much too late in the boot process and the kernel can't load the rootfs from the drive.
The SATA_MV could be optional as it is specifically for Marvel based SATA controllers. So if you have some other chipset, you could ignore that.

In the menuconfig, those are located at:

Code: Select all

Device Drivers --->
    Serial ATA and Parallel ATA drivers (libata)  --->  (ensure this one is built-in)
        AHCI SATA support (ensure this one is built-in)
        Marvell SATA support (ensure this one is built-in)
This guide is not intended to cover kernel building. For reference see the raspberry pi docs: ... l#building

The longer version:

This is intended to provide a more thorough/complete guide for someone who may be completely new to doing something like this.

There are many reasons you may want to run with a setup like this. For me, it was about increased space, improved performance, and increased longevity. I am using a 250GB crucial MX500. They are cheap, well rated, have lots of nice features (including integrated power loss immunity). But there are many many options to choose from.

This guide is written from the point of view of having a brand new SSD.

1. Setting up the new drive

I will be creating a single ext4 partition, you can follow similar steps to create more than 1 if you would like to (there are certainly advantages to doing so).

Find the drive:

Code: Select all

sudo fdisk -l
Mine was at /dev/sde

Create a single partition:

Code: Select all

sudo fdisk /dev/sde
Command (m for help): n
Partition type
   p   primary (0 primary, 0 extended, 4 free)
   e   extended (container for logical partitions)
Select (default p): 

Using default response p.
Partition number (1-4, default 1): 
First sector (2048-488397167, default 2048): 
Last sector, +/-sectors or +/-size{K,M,G,T,P} (2048-488397167, default 488397167): 

Created a new partition 1 of type 'Linux' and of size 232.9 GiB.

Command (m for help): w
Now we need to format our new partitions:

Code: Select all

sudo mkfs.ext4 /dev/sde1
Optionally add a label (there are other ways to do this):

Code: Select all

sudo e2label /dev/sde1 RN1-Main
Now we need to mount this new partition so we can copy over the rootfs:

Code: Select all

sudo mkdir /media/rootFSMigration
sudo mount /dev/sde1 /media/rootFSMigration
Check that everything looks right so far:

Code: Select all

df -h
You should see your new drive listed.

Now we need to copy over the rootfs from the sdcard:

Code: Select all

sudo rsync -axv / /media/rootFSMigration
The main flag of interest is the -x. This ensures that rsync does not cross filesystem boundaries. What that means is any mounts you have will not be copied. This also prevents any of the standard linux mount points to be omitted (ex: /dev, /proc, etc...). Note that those directories will still be created on the new drive, they will just be empty. Let that command run, it will take a few minutes to copy the entire tree.

2. Now we need to configure the raspberry pi boot to use this new drive as the rootfs

Make a copy of the existing boot config:

Code: Select all

sudo cp /boot/cmdline.txt /boot/cmdline.orig.txt
We need to change the root entry to point to our new partitions. It should look something like this:

Code: Select all

You can find the PARTUUID of the new partition by looking at the output of:

Code: Select all

sudo blkid
Copy the value of the PARTUUID for your drive. For me it was listed under /dev/sde1.

Edit the /boot/cmdline.txt with your favorite editor and change root=PARTUUID=738a4d67-02 to your new PARTUUID. Then save the file.

Finally, we need to modify the fstab to mount the partition (Make sure you are modifying the fstab on the new drive and not on the sdcard).
For me it was located here:

Code: Select all

Look for the existing root entry and again change the PARTUUID to your new partition's PARTUUID:

Code: Select all

#PARTUUID=df27ccca-02  /               ext4    defaults,noatime  0       1
PARTUUID=f8dd766a-01  /               ext4    defaults,noatime  0       1
You should now be able to reboot your system.

You can verify that your new drive is being used as the rootfs with this command:

Code: Select all

findmnt -n -o SOURCE /
You should see the new drive listed. For me:

Code: Select all


Hopefully this is helpful. Please let me know if something is not clear or does not work for you.

Return to “Compute Module”