Radxa Rock Pi 4C Plus SSD Boot Guide

Radxa Rock Pi 4C Plus SSD Boot Guide
Radxa Rock Pi 4C Plus SSD Boot Guide

The Rock Pi 4C Plus is a bit different to boot with a SSD than it’s predecessors. It does not have a SPI flash (nor can you solder one onto the board) so to use the NVMe slot for our root filesystem we need to use a SD card as the boot loader.

In this guide I’ll walk you through the process to clone a working SD card installation to your NVMe drive and then use some tricks with the drive’s UUID identifiers and essentially pass the boot process off from the SD card and have the NVMe SSD take over.

Let’s get started!

Hardware Used

Radxa Rock Pi 4C Plus - Top View
Radxa Rock Pi 4C Plus

The Rock Pi 4C Plus model always comes with 4GB of RAM. It has a hexa-core processor (6 cores) and a Mali T860MP4 GPU as well as a top-mounted M.2 slot (2230).

Links: AliExpress*, Amazon.com*, Amazon.ca*, Amazon.co.uk*, Amazon.de*, Amazon.es*, Amazon.fr*, Amazon.it*, Amazon.nl*, Amazon.pl*, Amazon.se*

Kioxia 2230 M2 NVMe Drive
Kioxia 2230 M.2 NVMe Drive

The Kioxia (Toshiba) 128GB M.2 2230 PCIe NVMe drive is much shorter than most NVMe drives (full size is 2280). It fits great with single board computers / tablets / other smaller form factors.

Links: Amazon.com*, Amazon.ca*, Amazon.co.uk*, Amazon.co.jp*, Amazon.com.au*, Amazon.de*, Amazon.es*, Amazon.fr*, Amazon.it*, Amazon.nl*, Amazon.pl*, Amazon.se*, Amazon.sg*

Geekworm Copper Heat Sink Set
Geekworm Copper Heat Sink Set

The Geekworm copper heat sink set is designed to fit many different single board computers. It uses thermal conductive adhesive which many “cheap” heat sink kits for SBCs don’t have. Eliminates hot spots and reduces throttling. Can be further enhanced by powered cooling over the heat sinks.

Links: Amazon.com*, Amazon.ca*, Amazon.co.jp*, Amazon.co.uk*, Amazon.de*, Amazon.es*, Amazon.fr*, Amazon.it*

Preparing SD Card

First you should have a completely working installation on a SD card of the OS that you would like to use. I used the official Debian desktop image for this guide (recommended) so if your partitions are different it may be your flavor of Linux and need slightly altered instructions.

If you have an already working installation you want to move to your SSD you can use this as well most likely.

You should completely update first with:

sudo apt update && sudo apt full-upgrade

Mounting SSD

Mounting your SSD in the board should look like this:

Radxa Rock Pi 4C Plus - NVMe and Heat Sinks Mounted
Radxa Rock Pi 4C Plus – NVMe and Heat Sinks Mounted

Preparing SSD

First we are going to completely remove all partitions from the drive so it’s completely blank. Your drive should typically be /dev/nvme0n1:

sudo gdisk /dev/nvme0n1

Now remove all partitions from the device. If you press “p” it will print out the partitions. You can then use “d” to delete them.

Here’s an example on mine:

rock@rockpi-4cplus:/boot$ sudo gdisk /dev/nvme0n1  
GPT fdisk (gdisk) version 1.0.6

Partition table scan:
  MBR: protective
  BSD: not present
  APM: not present
  GPT: present

Found valid GPT with protective MBR; using GPT.

Command (? for help): p
Disk /dev/nvme0n1: 250069680 sectors, 119.2 GiB
Sector size (logical/physical): 512/512 bytes
Disk identifier (GUID): E3017ECA-4571-4F62-A39F-4BA2A4323BD8
Partition table holds up to 128 entries
Main partition table begins at sector 2 and ends at sector 33
First usable sector is 34, last usable sector is 250069646
Partitions will be aligned on 64-sector boundaries
Total free space is 8350 sectors (4.1 MiB)

Number  Start (sector)    End (sector)  Size       Code  Name
   1              64            8063   3.9 MiB     0700  loader1
   2           16384           24575   4.0 MiB     0700  loader2
   3           24576           32767   4.0 MiB     0700  trust
   4           32768         1081343   512.0 MiB   EF00  boot
   5         1081344       250069646   118.7 GiB   8300  rootfs

Command (? for help): d

Keep pressing d until all the partitions are deleted. Once they are gone use the ‘w’ command to write your changes.

Cloning Installation to SSD

We’re now ready to clone your installation to the SSD. We can now copy your drive to the SSD with the following command:

cat /dev/mmcblk0 > /dev/nvme0n1

Wait for the operation to complete (there won’t be any output but you will have a cursor again and be able to type new commands). Remember that you are copying an entire drive from one to another basically with that one command.

Mine took about 30-45 minutes (although I was using a 64GB SD card and the larger SD card you use the longer it will take to copy the whole drive).

If you are having any trouble with permissions try becoming “root” first with:

sudo su

Now try running the command again and as the superuser you should not encounter any permission errors.

Change SD card’s rootfs UUID

We need to change our SD card’s UUID so that it doesn’t try to boot from that partition. We can set it to a random one with the following command:

sudo tune2fs -O metadata_csum_seed -U random /dev/mmcblk0p5

We can verify that it has changed with blkid like this:

rock@rockpi-4cplus:~$ sudo blkid 
/dev/nvme0n1p1: PARTLABEL="loader1" PARTUUID="5a15e3e6-dd19-480e-811a-7d9ba59b1963"
/dev/nvme0n1p2: PARTLABEL="loader2" PARTUUID="469f0b94-69ab-442d-aa9c-9b34c317a851"
/dev/nvme0n1p3: PARTLABEL="trust" PARTUUID="1263ff37-cd88-4bb1-952c-8dca6a25d854"
/dev/nvme0n1p4: UUID="AAAA-1111" BLOCK_SIZE="512" TYPE="vfat" PARTLABEL="boot" PARTUUID="256f45f9-30af-4374-85c9-2b8eaa1cc816"
/dev/nvme0n1p5: LABEL="rootfs" UUID="4d9b395f-fc57-41f9-8cad-54ea930a6506" BLOCK_SIZE="4096" TYPE="ext4" PARTLABEL="rootfs" PARTUUID="0cc2b5ce-8997-4920-a9fb-3a1db3303230"
/dev/mmcblk0p1: PARTLABEL="loader1" PARTUUID="5a15e3e6-dd19-480e-811a-7d9ba59b1963"
/dev/mmcblk0p2: PARTLABEL="loader2" PARTUUID="469f0b94-69ab-442d-aa9c-9b34c317a851"
/dev/mmcblk0p3: PARTLABEL="trust" PARTUUID="1263ff37-cd88-4bb1-952c-8dca6a25d854"
/dev/mmcblk0p4: LABEL_FATBOOT="boot" LABEL="boot" UUID="8138-1398" BLOCK_SIZE="512" TYPE="vfat" PARTLABEL="boot" PARTUUID="256f45f9-30af-4374-85c9-2b8eaa1cc816"
/dev/mmcblk0p5: LABEL="rootfs" UUID="101adf3b-0bbf-4891-8a20-d8d789b3a232" BLOCK_SIZE="4096" TYPE="ext4" PARTLABEL="rootfs" PARTUUID="0cc2b5ce-8997-4920-a9fb-3a1db3303230"

Notice that /dev/nvme0n1p5 and /dev/mmcblk0p5 no longer have matching UUIDs. This is exactly what we want.

Change SSD’s boot UUID

Next we are going to change the boot partition’s UUID on the SSD. This will make it so that the mounted /boot folder inside your operating system actually mounts the SD card (which is your actual boot loader in this configuration).

First make sure you have mtools with:

sudo apt install mtools -y

Now we can change the UUID with:

sudo mlabel -N aaaa1111 -i /dev/sdb1 ::

You can verify these are different using the same sudo blkid command as the previous section.

Run fsck

Before we reboot run fsck on the drive like this:

sudo fsck -yf /dev/nvme0n1p5

This will prevent you from having to run fsck on the CLI the first time you try to boot.

Reboot and Verify

Now reboot the Rock Pi 4C Plus with:

sudo reboot

With any luck you should be booted using your SSD! We can verify this with the mount command like this:

rock@rockpi-4cplus:~$ mount
/dev/nvme0n1p5 on / type ext4 (rw,relatime,data=ordered)
/dev/mmcblk0p4 on /boot type vfat (rw,relatime,fmask=0022,dmask=0022,codepage=936,iocharset=utf8,shortname=mixed,errors=remount-ro,x-systemd.automount)

Here we can see that our root partition (/) is indeed on /dev/nvme0n1p5 and not /dev/mmcblk0p5. We can also see that my /boot folder is properly mounted is /dev/mmcblk0p4 (the SD card which is serving as our boot loader). Success!

Testing Performance

You can verify the performance of your SSD on Pi Benchmarks using the following command:

sudo curl https://raw.githubusercontent.com/TheRemote/PiBenchmarks/master/Storage.sh | sudo bash

Here are the results:

     Category                  Test                      Result     
HDParm                    Disk Read                 370.59 MB/s              
HDParm                    Cached Disk Read          349.16 MB/s              
DD                        Disk Write                211 MB/s                 
FIO                       4k random read            47962 IOPS (191850 KB/s) 
FIO                       4k random write           12760 IOPS (51040 KB/s)  
IOZone                    4k read                   56308 KB/s               
IOZone                    4k write                  56392 KB/s               
IOZone                    4k random read            38025 KB/s               
IOZone                    4k random write           59999 KB/s               

                          Score: 14,003                                       

The full Rock Pi 4C Plus benchmark can be viewed here on Pi Benchmarks.


The Rock Pi 4C Plus is a bit of a pain to get to boot from the NVMe storage but it’s well worth the performance gains. If you are using a different OS than the official OS you may need to adjust some of the partitions to get this to work but you can follow the same process.

I highly recommend the little M.2 NVMe modules. They will save you money over SD cards and give you much higher performance and access to much greater storage capacities. If you want to spend more than $13 then you can get much, much higher storage capacities (but the price rises accordingly). It’s definitely worth it!

Other Resources

I’ve written a review about the Rock Pi 4C Plus here

All of my single board computer reviews are available here


Inline Feedbacks
View all comments

9 days ago

Hi, very intrigued. Do you think this is the same process with the rock4SE? Recently got one and have been trying a multitude of settups but none are quite stable.

9 days ago

I haven’t gotten an SSD yet, just looking still. Power could very much be the issue but currently just using a 128 uSD card and sometimes just won’t boot up, so have to reflash it and start over. Which is fine as I’m still learning so much about it as I try to setup my own web server and internal photo site for the family.

I thought is the SSD better with power failures or stability..as opposed to the uSD card, so anyway to just have a read only OS on the uSD and use the SSD for everything else, not sure what the best setup is. Currently trialing to have virtualmin and photoprism and possibly even plex if i’m greedy.

13 days ago

I wish I had seen this before I ordered my new hardware. I am on the RockPi 4A 1.4 – so I ended up buying the M.2 Extension board v1.6 ($10) +Heatsink ($8) plus delivery to Manila ($12) which is $30 before even ordering the M2 module. Perhaps with that small one, the 2230, which I did not know even existed – the extra heatsink would not be required and, although a little ugly, would be be ok to hang out of the 4A. I don’t know…. Also I am running DietPi – so will be very interested to see how it differs from this article. Thanks for writing it ! 🙏🏻😊

8 days ago

Am moving forward sleoly, step by step – I received the M2 extender and heatsink, and installed those 😊 Unlike your RockPi, I have an extra step to make my RockPi4A bootable (as per https://wiki.radxa.com/Rockpi4/Linux_system_runs_on_M.2_NVME_SSD ) — am currently searching for a USB-A (male) to USB-A (male) cable to do an SPI flash…. In parallel, the cat /dev/mmc > /dev/nvme step is running, as I write this… I am curious, my SD is 64gb and the SSD is 256gb. After copying the SD to the SSD – I think there will be a 64gb partition on the SSD. True ? Therefore – will need a few additional steps to reclaim the other 200gb (approx) of space ?? Maybe I have misunderstood something ? I am running DietPi — Thanks again James. Keep posting your work ! 🙏🏻👍

8 days ago

James – thanks reply ! 😊 Am making progress. Will give an update later today

4 days ago

Hi James – I need some help 😭
Just wanting to boot from the SSD – why should that be so difficult ?

1. first approach – as I have RockPi 4A v1.4 – it has an SPI Flash. I successfully flashed a “bootable bootloader” into that SPI. As per https://wiki.radxa.com/Rockpi4/dev/spi-install . Then what happens ( either with bootable SD in place or not ) is – nothing. Power-on results in hard blue light – which indicates it is “stuck in the bootloader”. What I do not know is – where is the bootloader trying to boot from ? Maybe it *IS* trying to boot from my SSD, but my SSD is not bootable.. My SSD was prepared as per article above ( using the cat command ) , ie cloned from the SD. Without a serial console – that requires some weird ass custom cable – I am not going to see any messages to explain what the (SPI) bootloader is doing and where it is hanging… So seems like a deadend for the “SPI flash method”.
2. next approach: use your article as a template. Seems simple enough. As the SPI method ends with a deadend, I can just remove that “SPI bootloader” so it always boots from the SD card. And then – using your approach – “the SD card contains a Bootloader” which points to the SSD…. But for some reason – this doesn’t work either … It just only boots from the SD card. and if the SD card is not inserted – it does not boot at all.
3. Try something else – there’s a forum entry about creating a “multi-boot SD card” … https://forum.radxa.com/t/about-multiboot/2838 Maybe there’s something there to followup. He also says ” The uboot searches for /extlinux/extlinux.conf and load kernel,dtb on first partition or partition which set bootable flag.” — maybe that information can be used to get #1 working ??? That would be the best option .

But I think I need some pointers or advice – otherwise I may never get this working.

What do you think James ? Which way would have most promise to pursue ?

4 days ago

[Thu Nov 24] root@batopi: ~$ fdisk -l
Disk /dev/mmcblk0: 59.63 GiB, 64021856256 bytes, 125042688 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: dos
Disk identifier: 0xb670ed71

Device Boot Start End Sectors Size Id Type
/dev/mmcblk0p1 32768 125042687 125009920 59.6G 83 Linux

Disk /dev/nvme0n1: 238.47 GiB, 256060514304 bytes, 500118192 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: gpt
Disk identifier: C1BC056C-BD7C-4813-885E-927C6E0F6051

[Thu Nov 24] root@batopi: ~$ lsblk
mmcblk0 179:0 0 59.6G 0 disk
└─mmcblk0p1 179:1 0 59.6G 0 part /
nvme0n1 259:0 0 238.5G 0 disk

Seems like I got no *bootable* partitions ! 🤣 At least the SD has a partition, the SSD does not. And the system *does* boot from the SD.

4 days ago

Thanks for reply 😊🙏🏻

1 day ago
Reply to  Sean

Working now 😁 – booting from NVMe. The SD is removed from the system. Seems ok 😉

— using your benchmark tool — my results: https://pibenchmarks.com/user/SeanPH/

Category Test Result
HDParm Disk Read 676.39 MB/s
HDParm Cached Disk Read 395.64 MB/s
DD Disk Write 252 MB/s
FIO 4k random read 57047 IOPS (228189 KB/s)
FIO 4k random write 21557 IOPS (86231 KB/s)
IOZone 4k read 100387 KB/s
IOZone 4k write 95103 KB/s
IOZone 4k random read 44117 KB/s
IOZone 4k random write 152130 KB/s

Score: 25950

Easier to check speed just with: hdparm -Tt --direct /dev/nvme0n1p1

Thanks again for great article ! and for your comments and replies 🙏🏻

21 hours ago

Totally agree 🙏🏻😁 ! My SD experience is some are fast and some are slow (unusable) – and never could know for sure until try to run it in one of my systems. Hopefully the NVMe drive will solve those problems. Now to arrange some backup protocols – like a spare NVMe with bootable image on standby. I fear the m2 card itself getting zapped – though such a power event that would probably fry the whole RockPi. Thanks again – I took alot of time to make sure I am getting the gen2 performance from my m2. This link helped a lot. And for the image copy of DietPi from SD to M2, this was my guide …. I am not sure – but I think the whole SPI flash was a red herring. I disabled it. Then – just removing the SD card – and it boots from the M.2 NVMe… Go figure ? Seems like I over-thought it from the beginning.

Rob Bohn
Rob Bohn
24 days ago

(Have comments been disabled? They do not display on my browser – Edge)