November 29, 2025

Orange Pi R1 Plus LTS (RK3328) - Sources for Debian SD card

When I began working with this board again in 2025, I went looking for a more recent Debian image to place on an SD card.
I found this: He splits the image into two pieces (that you can simply cat together). These are the boot image and the debian image. My interest here is in the boot image. It contains the partition table, chip specific code, ATF, and U-boot.
His instructions to build the boot image are:
docker build -t sd-images https://github.com/johang/sd-card-images.git
mkdir -p /tmp/sd-images
docker run --rm -v /tmp/sd-images:/artifacts sd-images build-boot raspberrypi_3b bcm2837 rpi_3_defconfig aarch64-linux-gnu
I have never had any dealings with "docker", but I suppose we can give it a try. He says the above process will leave the boot image in /tmp/sd-images.

Install Docker

I am running Fedora 42 on an x86 system. I do this:
su
dnf install docker
dnf update
The install removes some selinux files -- which is fine by me, I have selinux disabled.

I do the dnf update simply because things on my system are quite out of date. I will also end up needing to reboot. I get some weird error about Nvidia modules not building properly. I know this has something to do with me installing CUDA development tools on my machine, which have conflicts with the drivers I use to run my system. All this has nothing to do with docker, so we will try to ignore it for now. But it turns ugly. I spend an hour or so getting rid of the entire CUDA package set.

I find this nice tutorial:

Of course all tutorials seem nice at first. I run into my first problem right away:
docker run hello-world
docker: permission denied while trying to connect to the Docker daemon socket
at unix:///var/run/docker.sock
It works as root, which tells me that the docker daemon is running properly. It does go fetch the hello world thing from the "docker hub" for me. Some searching tells me that it is not the best idea to run docker as root. I edit /etc/group and add "tom" to the docker group. I have to log out and back in again for this to take effect. Docker gives me a bunch of tips and suggests trying:
docker run -it ubuntu bash
This pulls an "ubuntu:latest" image from the hub and runs it for me.

Back to SD-sources and Docker

I try the first command that is suggested:
docker build -t sd-images https://github.com/johang/sd-card-images.git
This fails. A look at the error message shows that it is trying to do something with apt-get. I don't know enough to tell if this is simply because I am running on Fedora, or whether it is trying to run things in a debian docker image -- but this is turning into much more of a tangle than I want to dive into. I peek a little more after I clone his repository and see that all this is coming from the "Dockerfile" which seems to specify a ubuntu image. As a Docker beginner, this is above my pay grade.

A different approach

cd Projects/RK3328
git clone https://github.com/johang/sd-card-images.git
cd sd-card-images
Here is the line he said would build the boot image for a rpi-3:
docker run --rm -v /tmp/sd-images:/artifacts sd-images build-boot raspberrypi_3b bcm2837 rpi_3_defconfig aarch64-linux-gnu
I squint at this and see the tail end is the command:
build-boot raspberrypi_3b bcm2837 rpi_3_defconfig aarch64-linux-gnu
In "scripts" is a shell script named "build-boot" that extracts and renames 4 arguments:
BOARD_ID = raspberrypi_3b
CHIP_ID = bcm2837
DEFCONFIG = rpi_3_defconfig
TUPLE = aarch64-linux-gnu
It then has a long case/switch on CHIP_ID. For a chip that matches "rk*" it invokes:
build-boot-rk "${BOARD_ID}" "${CHIP_ID}" "${DEFCONFIG}" "${TUPLE}"
Also, stepping back a bit. I grep for "3328" and find these lines. What are these csv files for? My guess is that he has a top level script that automates the build process for all the boards in his collection.
boards.csv:orangepi_r1_plus_lts,Orange Pi R1 Plus LTS,Xunlong,rk3328,orangepi-r1-plus-lts-rk3328_defconfig,aarch64-linux-gnu,rk3328-orangepi-r1-plus-lts
chips.csv:rk3328,RK3328,Rockchip,ARM Cortex A53,armv8,arm64
Squinting at this, I can guess the following:
BOARD_ID = orangepi_r1_plus_lts
CHIP_ID = rk3328
DEFCONFIG = orangepi-r1-plus-lts-rk3328_defconfig
TUPLE = aarch64-linux-gnu
So, I could invoke "build-boot" as:
build-boot orangepi_r1_plus_lts rk3328 orangepi-r1-plus-lts-rk3328_defconfig aarch64-linux-gnu
Poking around yet more I discover docs/_boards/orangepi_r1_plus_lts.md --
# DO NOT EDIT - Generated by rebuild-jekyll-boards
layout: board
title: Orange Pi R1 Plus LTS SD card images
description: "Minimal, pure and up-to-date vanilla Debian/Ubuntu arm64 SD card images for Orange Pi R1 Plus LTS by Xunlong, SoC: Rockchip RK3328, CPU ISA: armv8"
board_id: orangepi_r1_plus_lts
board_dtb_name: rk3328-orangepi-r1-plus-lts
board_name: Orange Pi R1 Plus LTS
board_maker_name: Xunlong
board_soc_name: Rockchip RK3328
board_cpu_name: ARM Cortex A53 (armv8)
board_cpu_arch_isa: armv8
board_cpu_arch_debian: arm64
But back in build-boot-rk, I find (more or less):
git clone --depth 1 --reference-if-able https://github.com/rockchip-linux/rkbin.git rkbin
I just do this:
cd Projects/RK3328
mkdir sources
cd sources
git clone https://github.com/rockchip-linux/rkbin.git
The webpage is here. You can ask google chrome to translate the Chinese for you. As build-boot-rk continue along, it will do these two things for the rk3328:
build-atf "${CHIP_ID}" "${TUPLE}"
export BL31="$PWD/arm-trusted-firmware/build/${CHIP_ID}/debug/bl31/bl31.elf"

build-u_boot "${DEFCONFIG}" "${TUPLE}"
The sources are:
https://github.com/ARM-software/arm-trusted-firmware.git
https://source.denx.de/u-boot/u-boot.git/
I clone these for now. I am somewhat surprised that the "official" sources for each of these is what is used -- and I am pleased.
Details of how each is built can be found in each build script.
The ATF build is like so:
cd arm-trusted-firmware
make PLAT="rk3328" DEBUG=1 bl31
Apparently PLAT is short for "platform". Maybe.

When build-boot-rk is done, it does:

# Copy U-Boot to 64 sectors from start
dd if=u-boot/u-boot-rockchip.bin of=tmp.img seek=64 conv=notrunc
Then back in build-boot, this happens:
truncate -s 32M tmp.img
pigz tmp.img
For now, I just want to peek at the ATF sources (in particular for bl31). I am not yet ready to try to do a build.
Have any comments? Questions? Drop me a line!

Tom's electronics pages / tom@mmto.org