OpenBSD 7.1 (7.4) on PINE64 RockPro64

This is a small write-up about installing OpenBSD 7.1 on a PINE64 RockPro64 SBC.

Update 2023-12-30 - OpenBSD 7.4 u-boot

There is a small but important regression with OpenBSD u-boot-aarch64 package started in 7.3 or maybe even before: it doesn’t boot the RockPro64 board at all. I had to reinstall stuff recently and only old package from 7.1 (u-boot-aarch64-2021.10p3) seemed to work, while u-boot-aarch64-2021.10p8 did not. So everything written below stands true with (replacing 7.1 to 7.4) except u-boot files; ‘modern’ dtb is okay as well.

Preamble

RockPro64 is a beefy single-board computer made by a company that brought us awesome devices like Pinebook Pro (laptop), Pinecil (soldering iron), PineTime (smartwatch) and of course PinePhone. The board utilizes the same hexa-core processor as Pinebook Pro - Rockchip RK3399, and 4 gigabytes of LPDDR4 RAM.

One of the distinct features of that computer is a PCI-express X4 socket. Unfortunately I wasn’t able to use any video card there even with “stock” GNU/Linux - particular PCIe implementations don’t work with memory mappings required for GPUs to work1. The slot is often being used for a network cards and SATA controllers - there is even an official case for RP64 with 3.5" hard drives spots inside, quite handy for a homemade NAS or something of sorts.

I am using a different case that doubles as a heat sink for the RK3399 as it runs relatively hot under heavy load especially.

pic

Prerequisites

Storage choice

Since I’ve obtained the board I’ve ran OpenBSD on a microsd card there and while it has its perks if used as a disposable/read-only storage it is usually not a good choice to run an operating system from, especially because FFS (OpenBSD default FS) is not particularly optimized for that kind of flash storage.

Apart from microsd as boot/main drive the board supports eMMC chips up to 128gb, in my opinion this is a far better option for using with any SBC long-term (except SSD/HDD obviously).

There is no difference in the installation procedure between those variants though.

Brief boot sequence theory

Unlike x86_64 ARM ecosystem does not have unified boot routine - hardware and especially memory initialization process is vastly different between CPUs, unlike old BIOS or modern UEFI. Das U-Boot is the most successful attempt to fix that and nowadays even UEFI is a viable option for some arm64 devices (notably Raspberry Pi 4/400).

Unfortunately that means that it is necessary to use a specific u-boot builds for each different board out there. Fortunately for us OpenBSD already has prebuilt images to write onto storage to successfully boot on RockPro64; having mainline support is awesome in general.

I’ll try to not dive deep into RK3399 process since I’m no expert; essentially the internal CPU boot ROM will execute the code from eMMC/microsd at the 32768 bytes offset ( 64 sectors of 512 bytes)2. At this point though the RAM is not fully initialized and only small amount is available to the CPU so the whole bootloader cannot be fit there; it inits “main” DDR memory and chainloads the next piece of puzzle at the offset of 16384 sectors.

Once U-Boot is fully chainloaded it fires off proper OpenBSD bootloader.

The process described goes only for eMMC/MicroSD boot, not SPI flash - I avoid using that because the “u-boot flavor” there would be hardwired for certain OS, so if you flash u-boot made for Linux you won’t be able to boot other OS.

Required downloads as of OpenBSD v7.1

If you have any OpenBSD installation you can get the bootloader binaries from u-boot-aarch64 and dtb binary packages. Otherwise just download their tarballs from here: https://ftp.openbsd.org/pub/OpenBSD/7.1/packages/aarch64/

Obviously we wouldn’t be able to install anything without an install image itself - the usual place to grab it is from the official website: https://ftp.openbsd.org/pub/OpenBSD/7.1/arm64/install71.img

Preparing the boot media

In examples below I’ll be using sd5 as target disk and OpenBSD as a host system.

First we dump the install image onto the drive - microsd or eMMC connected via adapter:

dd if=install71.img of=/dev/rsd5c bs=1024M

Next thing is to dump both parts of bootloader:

dd if=/usr/local/share/u-boot/rockpro64-rk3399/idbloader.img of=/dev/rsd5c bs=512 seek=64
dd if=/usr/local/share/u-boot/rockpro64-rk3399/u-boot.itb of=/dev/rsd5c bs=512 seek=16384

(Be sure to provide valid paths in case you’re not on OpenBSD and unpacked u-boot tarball somewhere else.)

DTB is an acronym for the “Device Tree Binary”. It is a blob that has a board hardware description for operating system to use - SPI/flash storage, memory mappings and so on. We have that prebuilt from a package mentioned above - all is need to unpack specific files needed to the boot partition.

Install image contains a FAT32 partition that we have to mount and copy files onto:

mount /dev/sd5i /mnt
mkdir -p /mnt/dtb/rockchip
cp /usr/local/share/dtb/arm64/rockchip/rk3399-rockpro64* /mnt/dtb/rockchip/
umount /mnt

Hooking up the serial console

Default install media OpenBSD kernel cannot use the GPU on the RockPro64 so it is necessary to be able to interact with the installer, that’s where serial console comes into play. We need 3 wires connected from USB UART to the board:

UART GND -> BOARD PIN 6 (GND)
UART RXD -> BOARD PIN 8 (TXD)
UART TXD -> BOARD PIN 10 (RXD)

Using serial adapter is trivial using many tools (screen, minicom, picocom, cu), I’ll be using cu since it is default and preinstalled OpenBSD program:

cu -l cuaU0 -s 115200

You can check dmesg in your OS after plugging in the adapter to get the name of the device (cuaU0, ttyUSB0 or something else). pic

OS installation tips

General installation procedure is the same boring OpenBSD stuff that just always works anyway.

Notable detail is that when the installer suggests wiping whole storage to write down a whole new partition table - don’t let it, we have precious code at offsets 64 and 16384 and definitely don’t want to lose that. So in the fdisk question it is needed to only edit the 4th partition (OpenBSD one) and extend its boundaries to the end of the storage. Don’t touch the default “begin” sector though, only move the last one so partition takes the majority of disk.

Reusing an existing partition is the last tricky thing; disklabel-ing it can be done as usual with automatic partitioning.

Some older guides3 suggested copying DTB files over to the fat32 boot partition all over again after the installation is finishes; I found this redundant because after-install scripts copied those files onto sd0i without my assist just fine.

This is a full dmesg of an installed system:

OpenBSD 7.1 (GENERIC.MP) #3: Sun May 15 09:18:22 MDT 2022
    root@syspatch-71-arm64.openbsd.org:/usr/src/sys/arch/arm64/compile/GENERIC.MP
real mem  = 4038729728 (3851MB)
avail mem = 3839430656 (3661MB)
random: good seed from bootblocks
mainbus0 at root: Pine64 RockPro64 v2.1
psci0 at mainbus0: PSCI 1.1, SMCCC 1.2
cpu0 at mainbus0 mpidr 0: ARM Cortex-A53 r0p4
cpu0: 32KB 64b/line 2-way L1 VIPT I-cache, 32KB 64b/line 4-way L1 D-cache
cpu0: 512KB 64b/line 16-way L2 cache
cpu0: CRC32,SHA2,SHA1,AES+PMULL,ASID16
cpu1 at mainbus0 mpidr 1: ARM Cortex-A53 r0p4
cpu1: 32KB 64b/line 2-way L1 VIPT I-cache, 32KB 64b/line 4-way L1 D-cache
cpu1: 512KB 64b/line 16-way L2 cache
cpu1: CRC32,SHA2,SHA1,AES+PMULL,ASID16
cpu2 at mainbus0 mpidr 2: ARM Cortex-A53 r0p4
cpu2: 32KB 64b/line 2-way L1 VIPT I-cache, 32KB 64b/line 4-way L1 D-cache
cpu2: 512KB 64b/line 16-way L2 cache
cpu2: CRC32,SHA2,SHA1,AES+PMULL,ASID16
cpu3 at mainbus0 mpidr 3: ARM Cortex-A53 r0p4
cpu3: 32KB 64b/line 2-way L1 VIPT I-cache, 32KB 64b/line 4-way L1 D-cache
cpu3: 512KB 64b/line 16-way L2 cache
cpu3: CRC32,SHA2,SHA1,AES+PMULL,ASID16
cpu4 at mainbus0 mpidr 100: ARM Cortex-A72 r0p2
cpu4: 48KB 64b/line 3-way L1 PIPT I-cache, 32KB 64b/line 2-way L1 D-cache
cpu4: 1024KB 64b/line 16-way L2 cache
cpu4: CRC32,SHA2,SHA1,AES+PMULL,ASID16
cpu5 at mainbus0 mpidr 101: ARM Cortex-A72 r0p2
cpu5: 48KB 64b/line 3-way L1 PIPT I-cache, 32KB 64b/line 2-way L1 D-cache
cpu5: 1024KB 64b/line 16-way L2 cache
cpu5: CRC32,SHA2,SHA1,AES+PMULL,ASID16
efi0 at mainbus0: UEFI 2.8
efi0: Das U-Boot rev 0x20211000
apm0 at mainbus0
agintc0 at mainbus0 sec shift 3:3 nirq 288 nredist 6 ipi: 0, 1: "interrupt-controller"
agintcmsi0 at agintc0
syscon0 at mainbus0: "qos"
syscon1 at mainbus0: "qos"
syscon2 at mainbus0: "qos"
syscon3 at mainbus0: "qos"
syscon4 at mainbus0: "qos"
syscon5 at mainbus0: "qos"
syscon6 at mainbus0: "qos"
syscon7 at mainbus0: "qos"
syscon8 at mainbus0: "qos"
syscon9 at mainbus0: "qos"
syscon10 at mainbus0: "qos"
syscon11 at mainbus0: "qos"
syscon12 at mainbus0: "qos"
syscon13 at mainbus0: "qos"
syscon14 at mainbus0: "qos"
syscon15 at mainbus0: "qos"
syscon16 at mainbus0: "qos"
syscon17 at mainbus0: "qos"
syscon18 at mainbus0: "qos"
syscon19 at mainbus0: "qos"
syscon20 at mainbus0: "qos"
syscon21 at mainbus0: "qos"
syscon22 at mainbus0: "qos"
syscon23 at mainbus0: "qos"
syscon24 at mainbus0: "qos"
syscon25 at mainbus0: "power-management"
"power-controller" at syscon25 not configured
syscon26 at mainbus0: "syscon"
"io-domains" at syscon26 not configured
rkclock0 at mainbus0
rkclock1 at mainbus0
syscon27 at mainbus0: "syscon"
"io-domains" at syscon27 not configured
"usb2phy" at syscon27 not configured
"usb2phy" at syscon27 not configured
rkemmcphy0 at syscon27
"pcie-phy" at syscon27 not configured
rktcphy0 at mainbus0
rktcphy1 at mainbus0
rkpinctrl0 at mainbus0: "pinctrl"
rkgpio0 at rkpinctrl0
rkgpio1 at rkpinctrl0
rkgpio2 at rkpinctrl0
rkgpio3 at rkpinctrl0
rkgpio4 at rkpinctrl0
pwmreg0 at mainbus0
rkdrm0 at mainbus0
drm0 at rkdrm0
"pmu_a53" at mainbus0 not configured
"pmu_a72" at mainbus0 not configured
agtimer0 at mainbus0: 24000 kHz
"xin24m" at mainbus0 not configured
rkpcie0 at mainbus0
rkpcie0: link training timeout
dwge0 at mainbus0: rev 0x35, address 3e:16:08:b2:57:d5
rgephy0 at dwge0 phy 0: RTL8169S/8110S/8211 PHY, rev. 6
dwmmc0 at mainbus0: 50 MHz base clock
sdmmc0 at dwmmc0: 4-bit, sd high-speed, dma
dwmmc1 at mainbus0: 50 MHz base clock
sdmmc1 at dwmmc1: 4-bit, sd high-speed, dma
sdhc0 at mainbus0
sdhc0: SDHC 3.0, 200 MHz base clock
sdmmc2 at sdhc0: 8-bit, sd high-speed, mmc high-speed, dma
ehci0 at mainbus0
usb0 at ehci0: USB revision 2.0
uhub0 at usb0 configuration 1 interface 0 "Generic EHCI root hub" rev 2.00/1.00 addr 1
ohci0 at mainbus0: version 1.0
ehci1 at mainbus0
usb1 at ehci1: USB revision 2.0
uhub1 at usb1 configuration 1 interface 0 "Generic EHCI root hub" rev 2.00/1.00 addr 1
ohci1 at mainbus0: version 1.0
rkdwusb0 at mainbus0: "usb"
xhci0 at rkdwusb0, xHCI 1.10
usb2 at xhci0: USB revision 3.0
uhub2 at usb2 configuration 1 interface 0 "Generic xHCI root hub" rev 3.00/1.00 addr 1
rkdwusb1 at mainbus0: "usb"
xhci1 at rkdwusb1, xHCI 1.10
usb3 at xhci1: USB revision 3.0
uhub3 at usb3 configuration 1 interface 0 "Generic xHCI root hub" rev 3.00/1.00 addr 1
"saradc" at mainbus0 not configured
rkiic0 at mainbus0
iic0 at rkiic0
escodec0 at iic0 addr 0x11
rkiic1 at mainbus0
iic1 at rkiic1
com0 at mainbus0: dw16550, 64 byte fifo
com1 at mainbus0: dw16550, 64 byte fifo
com1: console
"spi" at mainbus0 not configured
rktemp0 at mainbus0
rkrng0 at mainbus0
rkiic2 at mainbus0
iic2 at rkiic2
rkpmic0 at iic2 addr 0x1b: RK808
fanpwr0 at iic2 addr 0x40: SYR827, 1.00 VDC
fanpwr1 at iic2 addr 0x41: SYR828, 1.00 VDC
rkiic3 at mainbus0
iic3 at rkiic3
fusbtc0 at iic3 addr 0x22
rkpwm0 at mainbus0
rkpwm1 at mainbus0
rkpwm2 at mainbus0
"video-codec" at mainbus0 not configured
"iommu" at mainbus0 not configured
"video-codec" at mainbus0 not configured
"iommu" at mainbus0 not configured
"rga" at mainbus0 not configured
"efuse" at mainbus0 not configured
"dma-controller" at mainbus0 not configured
"dma-controller" at mainbus0 not configured
"watchdog" at mainbus0 not configured
"rktimer" at mainbus0 not configured
rkiis0 at mainbus0
rkiis1 at mainbus0
rkiis2 at mainbus0
rkvop0 at mainbus0: RK3399 VOPL
"iommu" at mainbus0 not configured
rkvop1 at mainbus0: RK3399 VOPB
"iommu" at mainbus0 not configured
"iommu" at mainbus0 not configured
"iommu" at mainbus0 not configured
simpleaudio0 at mainbus0
rkdwhdmi0 at mainbus0: HDMI TX
rkdwhdmi0: version 2.11a, phytype 0xf3
"gpu" at mainbus0 not configured
"opp-table0" at mainbus0 not configured
"opp-table1" at mainbus0 not configured
"opp-table2" at mainbus0 not configured
"external-gmac-clock" at mainbus0 not configured
gpiokeys0 at mainbus0: "GPIO Key Power"
"ir-receiver" at mainbus0 not configured
gpioleds0 at mainbus0: "work", "diy"
pwmfan0 at mainbus0: no cooling levels
"sdio-pwrseq" at mainbus0 not configured
graphaudio0 at mainbus0
graphaudio1 at mainbus0
"spdif-dit" at mainbus0 not configured
"vcc12v-dcin" at mainbus0 not configured
"vcc1v8-s3" at mainbus0 not configured
"vcc3v0-sd" at mainbus0 not configured
"vcc3v3-pcie-regulator" at mainbus0 not configured
"vcc3v3-sys" at mainbus0 not configured
"vcc5v0-host-regulator" at mainbus0 not configured
"vcc5v0-typec-regulator" at mainbus0 not configured
"vcc5v0-sys" at mainbus0 not configured
"vcc5v0-usb" at mainbus0 not configured
"framebuffer" at mainbus0 not configured
usb4 at ohci0: USB revision 1.0
uhub4 at usb4 configuration 1 interface 0 "Generic OHCI root hub" rev 1.00/1.00 addr 1
usb5 at ohci1: USB revision 1.0
uhub5 at usb5 configuration 1 interface 0 "Generic OHCI root hub" rev 1.00/1.00 addr 1
audio0 at graphaudio0
sdmmc0: can't enable card
scsibus0 at sdmmc2: 2 targets, initiator 0
sd0 at scsibus0 targ 1 lun 0:  removable
sd0: 118000MB, 512 bytes/sector, 241664000 sectors
uhidev0 at uhub4 port 1 configuration 1 interface 0 "HAILUCK CO.,LTD USB KEYBOARD" rev 1.10/1.00 addr 2
uhidev0: iclass 3/1
ukbd0 at uhidev0: 8 variable keys, 6 key codes
wskbd0 at ukbd0 mux 1
uhidev1 at uhub4 port 1 configuration 1 interface 1 "HAILUCK CO.,LTD USB KEYBOARD" rev 1.10/1.00 addr 2
uhidev1: iclass 3/0, 9 report ids
ums0 at uhidev1 reportid 1: 5 buttons, Z and W dir
wsmouse0 at ums0 mux 0
uhid0 at uhidev1 reportid 2: input=1, output=0, feature=0
ucc0 at uhidev1 reportid 3: 24 usages, 13 keys, enum
wskbd1 at ucc0 mux 1
uhid1 at uhidev1 reportid 5: input=0, output=0, feature=5
uhid2 at uhidev1 reportid 6: input=0, output=0, feature=255
uhid3 at uhidev1 reportid 9: input=1, output=0, feature=0
uhidev2 at uhub5 port 1 configuration 1 interface 0 "Hoksi Technology DURGOD Taurus K320" rev 2.00/1.04 addr 2
uhidev2: iclass 3/1
ukbd1 at uhidev2: 8 variable keys, 6 key codes
wskbd2 at ukbd1 mux 1
uhidev3 at uhub5 port 1 configuration 1 interface 1 "Hoksi Technology DURGOD Taurus K320" rev 2.00/1.04 addr 2
uhidev3: iclass 3/1, 4 report ids
uhid4 at uhidev3 reportid 1: input=1, output=0, feature=0
ucc1 at uhidev3 reportid 2: 573 usages, 18 keys, array
wskbd3 at ucc1 mux 1
ukbd2 at uhidev3 reportid 3: 104 variable keys, 0 key codes
wskbd4 at ukbd2 mux 1
ums1 at uhidev3 reportid 4: 5 buttons, Z and W dir
wsmouse1 at ums1 mux 0
uhidev4 at uhub5 port 1 configuration 1 interface 2 "Hoksi Technology DURGOD Taurus K320" rev 2.00/1.04 addr 2
uhidev4: iclass 3/0
uhid5 at uhidev4: input=64, output=64, feature=64
vscsi0 at root
scsibus1 at vscsi0: 256 targets
softraid0 at root
scsibus2 at softraid0: 256 targets
root on sd0a (eec5a595eb8339a3.a) swap on sd0b dump on sd0b
WARNING: bad clock chip time
WARNING: CHECK AND RESET THE DATE!
rkvop0: using CRTC 0 for RK3399 VOPL
rkvop1: using CRTC 1 for RK3399 VOPB
rkdrm0: 1920x1080, 32bpp
wsdisplay0 at rkdrm0 mux 1
wskbd0: connecting to wsdisplay0
wskbd1: connecting to wsdisplay0
wskbd2: connecting to wsdisplay0
wskbd3: connecting to wsdisplay0
wskbd4: connecting to wsdisplay0
wsdisplay0: screen 0-5 added (std, vt100 emulation)