The RockPRO64 is a low cost single-board computer featuring the powerful Rockchip RK3399 SoC. Although plenty of Linux rootfs images are available to install on the board, most of them are built in an opaque manner, leaving the user unable to determine whether they contain binary blobs or malware. Instead of trusting a binary image downloaded from the internet, why not learn the boot flow and build your own?
This guide was tested using the SD card slot. SPI does not need to be bypassed but this can be done by bridging GPIO pins 23 (CLK) and 25 (GND).
Connecting to the RockPRO64’s serial console will allow you to troubleshoot in case of any mistakes. A board based on the CP2104 chip was used to create this guide, and a CP2102 chip was tested and found to be incompatible with the board’s preferred baud rate of 1500000.
Abbreviated pinout for basic GPIO serial operation:
debootstrap
and other prerequisitesarm-none-eabi
and aarch64-unknown-linux-gnu
compilers are required to assemble the boot firmware. If you use an aarch64 system to follow this guide, you already have the latter. If not, packages are available on most distributions and you can use qemu-user-static to run the debootstrap command which comes later.
On Gentoo aarch64:
crossdev -P -v \
--b 2.33.1-r1 \
--g 9.3.0 \
--l 3.3.0-r1 \
--target arm-none-eabi
emerge -av sys-block/parted \
sys-fs/dosfstools \
dev-util/debootstrap \
app-crypt/debian-archive-keyring \
sys-boot/grub
Users following this guide on an architecture other than aarch64 may also have trouble getting the grub installer modules compiled. These users may be able to build grub themselves with the aarch64-unknown-linux-gnu
compiler.
Andrius Štikonas has written an excellent tutorial for building this firmware.
First, build ATF:
cd /tmp
git clone https://github.com/ARM-software/arm-trusted-firmware.git
cd arm-trusted-firmware
git reset --hard v2.3
make CROSS_COMPILE=aarch64-unknown-linux-gnu- PLAT=rk3399
Check that the bl31.elf
firmware file is ready for use by U-Boot:
export BL31=/tmp/arm-trusted-firmware/build/rk3399/release/bl31/bl31.elf
test -f ${BL31} && echo ok || echo WARNING
Then build U-Boot:
cd /tmp
git clone https://gitlab.denx.de/u-boot/u-boot.git
cd u-boot
git reset --hard v2020.07
make CROSS_COMPILE=aarch64-unknown-linux-gnu- rockpro64-rk3399_defconfig
make CROSS_COMPILE=aarch64-unknown-linux-gnu-
Carefully identify the SD card in dmesg
, or run ls /dev/sd*
before and after insertion.
export DRIVE=/dev/sdg
Erase at least the first few megabytes on the card:
dd if=/dev/zero of=${DRIVE} bs=1M count=50
On the Rockchip website we can see the expected partition layout. The detailed sequence description from sigmaris explains what the partitions are for.
Partition the drive, then create and mount the filesystems:
parted --script "${DRIVE}" \
mklabel gpt \
mkpart 1 ext2 8MiB 12MiB \
mkpart 2 fat32 12MiB 140MiB \
mkpart 3 ext2 140MiB 100% \
set 2 esp on
dd if=/tmp/u-boot/idbloader.img of=${DRIVE} seek=64
dd if=/tmp/u-boot/u-boot.itb of=${DRIVE}p1
mkfs.ext4 -L ROCKROOT ${DRIVE}p3
mkfs.vfat -F 32 -n ROCKBOOT ${DRIVE}p2
mkdir -pv /mnt/rockpro
mount -v ${DRIVE}p3 /mnt/rockpro
mkdir -pv /mnt/rockpro/boot/efi
mount -v -t vfat -oiocharset=iso8859-1 ${DRIVE}p2 /mnt/rockpro/boot/efi
If you are running through these steps on an aarch64 system:
debootstrap --arch=arm64 \
--components=main \
--variant=minbase \
--include=linux-image-arm64,systemd-sysv \
unstable \
/mnt/rockpro \
http://cdn-fastly.deb.debian.org/debian
If you are on a different architecture, add the flag --foreign
.
If a UEFI image is located on the first FAT formatted partition, U-Boot will load that. Standalone grub can be our UEFI image, we just have to configure it.
cat <<EOF > /tmp/grub.cfg
set timeout=5
set default=0
menuentry Debian {
insmod gzio
insmod part_gpt
insmod ext2
set root=hd0,gpt3
echo Loading kernel...
linux /boot/vmlinuz-5.7.0-1-arm64 root=LABEL=ROCKROOT console=ttyS2,1500000
echo Loading ramdisk...
initrd /boot/initrd.img-5.7.0-1-arm64
}
EOF
According to osdev wiki, “you have to specify what file to include at what path in the memdisk”.
mkdir -pv /mnt/rockpro/boot/efi/EFI/BOOT/
grub-mkstandalone -O arm64-efi \
-o /mnt/rockpro/boot/efi/EFI/BOOT/BOOTAA64.EFI \
"boot/grub/grub.cfg=/tmp/grub.cfg"
Include the device tree file provided by Debian:
mkdir -pv /mnt/rockpro/boot/efi/dtb/rockchip
cp -v /mnt/rockpro/usr/lib/linux-image-5.7.0-1-arm64/rockchip/rk3399-rockpro64.dtb \
/mnt/rockpro/boot/efi/dtb/rockchip
If you ran debootstrap on an aarch64 system (without the --foreign
flag as described above), you must skip this section.
If you don’t have a qemu-user-static in your distribution, this Gentoo guide has some hints for compiling your own and configuring your kernel to detect aarch64 binaries (binfmt_misc
).
chroot /mnt/rockpro /debootstrap/debootstrap --second-stage
Set a root password:
chroot /mnt/rockpro passwd root
Configure the fstab. Some kernels issue a warning if the charset is not specified.
cat <<EOF > /mnt/rockpro/etc/fstab
LABEL=ROCKROOT / ext4 noatime 0 1
LABEL=ROCKBOOT /boot/efi vfat iocharset=iso8859-1 0 2
EOF
You are ready to boot. Remove any serial cable connected to pin 10 and apply power with the barrel connector. You should see U-Boot, UEFI and finally the kernel print messages to the serial console. The tutorial is complete, but the following opinionated notes are provided as hints for further configuration.
The RockPRO64 has what most hackers would call an HDMI port, but Rockchip and Pine64 have chosen not to license some proprietary aspects of the protocol. In documentation it is referred to as “4K Digital Video Out”.
Alyssa Rosenzweig has put considerable effort into producing a free software driver for the RK3399’s GPU. At the time of writing, this driver, called Panfrost, is available in the Mesa packages for Debian unstable.
Linux 5.7 supports many USB wifi dongles. A device from TP-Link called Archer T1U was tested to work with this board. It uses the MediaTek MT7610U chipset and requires a firmware file to be located at /lib/firmware/mediatek/mt7610u.bin
. This file can be installed from the standard Linux firmware repo or the Debian firmware-linux
package.
The card will operate in a conservative mode until it learns which country’s RF rules to follow. The country can be configured in /etc/default/crda
if using crda
, or in wpa_supplicant-wlan0.conf
with country=xx
.