Skip to content

Latest commit

 

History

History
322 lines (217 loc) · 15.8 KB

File metadata and controls

322 lines (217 loc) · 15.8 KB

Linux system image build scripts for RK3576 based boards

The scripts in this repository produce disk images for Rockchip RK3576 based boards, ready to be flashed to an SD card or uploaded to internal storage via a USB connection and Maskrom mode.

You don't necessarily have to build images yourself. Most commits include a small green checkmark in the GitHub interface next to the commit message (or a red cross if we are less lucky), which links to a page in our Buildbot web interface with full build logs and links to pre-built images for all relevant boards, which our automated build system produces whenever something updates either in this repository or in one of its dependencies. Building from source is only necessary if you want to modify the system.


Repos structure

This repo contains build scripts only. The full system is assembled from several components:

Repository Description
flipperone-linux-build-scripts Build scripts that assemble complete disk images for RK3576-based boards (this repo)
flipper-linux-kernel Linux kernel patches and configuration for Flipper One RK3576-based boards
flipperone-mcu-firmware Firmware for the low-power RP2350 MCU

The build scripts pull the kernel and other components automatically — you don't need to clone other repos manually unless you want to modify them.

What's in this repo

Build scripts (run them in order):

Script What it does
build-uboot.sh Clones U-Boot and TF-A (or uses Rockchip's binary BL31), builds the bootloader and SPL loader for each target board
build-kernel-mainline.sh Clones flipper-linux-kernel, merges config fragments from configs/linux/, builds arm64 kernel .deb packages and DTBs
build-kernel-bsp.sh Clones Rockchip's BSP kernel (develop-6.1), fetches vendor DTS files, applies patches from patches/bsp/, builds arm64 kernel packages
build-images.sh Assembles complete GPT disk images for all boards you've built bootloaders for; calls build-rootfs-img.sh to build the root filesystem if it doesn't exist yet
build-rootfs-img.sh Runs debos on debian-rk3576-img.yaml to install the kernel into a partitioned image, then zeekstd-compresses it
build-ospack.sh Runs mmdebstrap via debos (debian-rk3576-ospack.yaml) to build the Debian root filesystem tarball

Other directories:

  • configs/ — kernel config fragments merged on top of the base config (minconfig-mainline for mainline, linux-bsp/ for the BSP kernel)
  • overlays/ — files copied into the root filesystem: systemd units, NetworkManager config, Broadcom Wi-Fi/BT firmware, KDE Plasma settings, SDDM autologin, U-Boot menu config
  • vendor-dts/ — Luckfox Omni3576 DTS/DTSI files and BSP device tree overlay sources (.dtso) for the EVB evaluation board and shared peripherals
  • patches/bsp/ — kernel patches applied to the BSP tree (TypeC, panfrost DTS, audio card)
  • rk_unpacker/ — standalone Python tool to extract partition images from Rockchip update.img files
  • prebuilt/, src/, out/ — build outputs and source clones; all gitignored

Automated builds

Every push to this repository (and to the tracked branches of its dependencies) triggers a full build on Buildbot. The resulting images land at dl-linux-images.flipp.dev/full-img/ and are updated automatically.

Supported boards

Board Target name Notes

Flipper One Prototype
flipper-one Our current Flipper One prototype
sige5 Same hardware sold under two names. Has DisplayPort on USB-C. Recommended for development.
rock-4d No DisplayPort on USB-C. Entering Maskrom requires a USB-A to USB-A cable.
nanopi-m5
omni3576
roc-pc The only RK3576 board supported by unmodified upstream U-Boot (as of mid-2025).
Rockchip RK3576 EVB1 evb Official Rockchip evaluation board. Not available for sale.

How to build image manually

The scripts are designed to run on Debian 13 (trixie). Other distributions may work but you'll need to find the equivalent packages yourself.

Quick start with Docker or Podman

Use the included Dockerfile to avoid installing anything on the host:

# Clone the repo
git clone https://github.com/flipperdevices/flipperone-linux-build-scripts
cd flipperone-linux-build-scripts

# Build the container image (one-time; typically 20–30 min depending on network and CPU)
docker build -t flipperone-linux-build-scripts .

# Run a full build — images appear in out/images/
mkdir -p out
docker run --privileged --rm -v "$(pwd)/out:/artifacts" \
    flipperone-linux-build-scripts

Replace docker with podman if that's what you have. --privileged is required because debos and mmdebstrap use loop devices and mount namespaces.

Quick start with VS Code Dev Container

  1. Install VS Code and the Dev Containers extension
  2. Clone this repository and open it in VS Code
  3. Press F1 and select "Dev Containers: Reopen in Container"
  4. Wait for the container to build (first time only)
  5. Run build scripts from the integrated terminal

Building on a bare Debian 13 host

For the bootloader:

sudo dpkg --add-architecture arm64
sudo apt update
sudo apt install git build-essential crossbuild-essential-arm64 bison flex \
    python3-dev python3-libfdt python3-setuptools swig libssl-dev gnutls-dev \
    python3-pyelftools device-tree-compiler

For the kernel:

sudo dpkg --add-architecture arm64
sudo apt update
sudo apt install git build-essential crossbuild-essential-arm64 bc bison flex \
    imagemagick libssl-dev libdw-dev libelf-dev debhelper libssl-dev:arm64 rsync

For assembling disk images — debos, bmaptool, and zeekstd all need to be installed from source:

sudo apt install golang pipx pigz cargo parted fdisk mmdebstrap \
    systemd-resolved systemd-container qemu-user-binfmt \
    libglib2.0-dev libostree-dev fakemachine

# debos
go install -v github.com/go-debos/debos/cmd/debos@latest
sudo install -m 755 ~/go/bin/debos /usr/local/bin

# zeekstd (requires Rust; v0.4.5+ needs Rust 1.91 — stick to v0.4.4-cli for now)
cargo install --git https://github.com/rorosen/zeekstd.git --tag v0.4.4-cli zeekstd_cli
sudo install -m 755 ~/.cargo/bin/zeekstd /usr/local/bin/

# bmaptool (Flipper fork)
sudo pipx install --global git+https://github.com/flipperdevices/bmaptool.git@flipper-devel

For flashing images to boards over USB:

sudo apt install rockusb

Building the bootloader

To fetch and build U-Boot with open-source TF-A:

./build-uboot.sh

The default source is the Flipper fork of U-Boot (flipperdevices/u-boot, branch rk3576), which has defconfigs for all supported boards. Note that as of mid-2025, only the Firefly ROC-RK3576-PC (roc-pc) is supported by vanilla upstream U-Boot; all other boards require either the Flipper fork or a board-specific tree.

To build for a specific board instead of all boards:

BOARD=sige5 ./build-uboot.sh

If you need a different U-Boot source tree (e.g., a newer upstream tree for a specific board):

BOARD=sige5 UBOOT_GIT="https://source.denx.de/u-boot/contributors/kwiboo/u-boot.git" UBOOT_BRANCH="rk3576" ./build-uboot.sh
BOARD=omni3576 KEEP_SRC=yes ./build-uboot.sh
BOARD=nanopi-m5 KEEP_SRC=yes ./build-uboot.sh
BOARD=rock-4d KEEP_SRC=yes ./build-uboot.sh

KEEP_SRC=yes reuses the already-cloned source tree; KEEP_SRC=update pulls the latest commits without a full re-clone.

To use Rockchip's binary BL31 instead of open-source TF-A:

USE_BL31=vendor BOARD=sige5 UBOOT_GIT="https://source.denx.de/u-boot/contributors/kwiboo/u-boot.git" UBOOT_BRANCH="rk3576" ./build-uboot.sh
USE_BL31=vendor BOARD=omni3576 KEEP_SRC=yes ./build-uboot.sh
USE_BL31=vendor BOARD=nanopi-m5 KEEP_SRC=yes ./build-uboot.sh
USE_BL31=vendor BOARD=rock-4d KEEP_SRC=yes ./build-uboot.sh

Outputs go to prebuilt/u-boot/<board>/u-boot-rockchip.bin, rk3576_loader_v*.bin, and rk3576_loader_fspi1_v*.bin per board, plus USB loader variants.

Building the kernel

Mainline kernel

./build-kernel-mainline.sh

To rebuild without re-downloading:

KEEP_SRC=yes ./build-kernel-mainline.sh

To incrementally pull new commits without a full fresh clone:

KEEP_SRC=update ./build-kernel-mainline.sh

To build from a different tree:

LINUX_GIT=https://gitlab.collabora.com/hardware-enablement/rockchip-3588/linux.git \
    LINUX_BRANCH=rockchip-devel ./build-kernel-mainline.sh

BSP kernel

./build-kernel-bsp.sh

The same KEEP_SRC variants work here too.

Assembling disk images

Once you have bootloader outputs in prebuilt/u-boot/ and kernel outputs in prebuilt/linux/, run:

./build-images.sh

This produces compressed images for each board whose bootloader is present. The kernel and root filesystem are shared; only the bootloader partition differs per board. Output files: out/debian-<sector-size>-<board>-<timestamp>.img.gz with a matching .bmap file, for both 512-byte and 4096-byte sector variants. When run inside the container, images go to out/images/ instead (the container sets IMG_OUT=/artifacts/images).

Don't run the mainline and BSP kernel scripts in parallel against the same output directory — both write to the same prebuilt/linux/ path and the final packaging step will fail. Run one, then the other (or set separate LINUX_OUT paths).

Note that as of mid-2025, upstream U-Boot doesn't have a driver for the Rockchip UFS controller, so boards with UFS cannot boot from it.

Writing the image to SD/eMMC

Flashing to an SD card

To produce a bootable SD card with your newly built Debian image, connect it to your host computer (e.g. through a card reader).

If you have a built-in SD card slot, you may use that, and the card will likely show up as /dev/mmcblkX (where X is the number identifying the respective SD/MMC controller, likely 0 if you only have one).

If you are using a USB card reader, the card will likely show up as /dev/sdX (where X is a lowercase letter). In this latter case you need to be triple careful, because any SATA or SCSI storage devices will also share the same naming scheme, and if you have important data on any other /dev/sdX device (such as your main system disk being called something like /dev/sda) you might end up inadvertently overwriting it if you pick the wrong one in the below commands, losing all your data. Please be careful.

sudo bmaptool copy out/debian-512-<your_board>-*.img.gz /dev/sdX

Flashing to eMMC using a USB cable and Maskrom

Rockchip devices include a special built-in mode called Maskrom, which allows flashing the board over a USB connection even if the board contains no bootloader or it is corrupted.

This mode is activated by holding down a MASKROM button when the power supply gets connected.

  • Instructions for Radxa Rock 4D: Connect a USB A to A cable (or Type C to USB A, depending on your host computer's available USB ports) to the top USB 3.0 blue port, hold the MASKROM button and apply power to the board as usual via its Type C DC IN. Note that eMMC modules cannot be used together with the onboard SPI flash, as they share pins internally
  • Instructions for ArmSoM Sige5: Connect a USB A to Type C cable (or Type C to Type C, depending on your host computer's available USB ports) to the Type C OTG port (marked TYPEC on the board), hold the MASKROM button and apply power to the board as usual via its Type C DC IN

You should then see something like this in lsusb command output:

Bus 002 Device 011: ID 2207:350e Fuzhou Rockchip Electronics Company

Your device is now ready for programming over the Rockusb protocol.

# Boot the board in USB upload mode
sudo rockusb download-boot prebuilt/u-boot/<your_board>/rk3576_loader_v*.bin

sudo rockusb write-bmap out/debian-512-<your_board>-*.img.gz

Container builds place bootloaders in out/u-boot/<board>/ and disk images in out/images/ instead.

Flashing Radxa Rock 4D eMMC

Switch Radxa 4D into Maskrom mode, then:

rockusb list
rockusb download-boot prebuilt/u-boot/rock-4d/rk3576_loader_v*.bin
rockusb write-bmap out/debian-512-rock-4d-*.img.gz
rockusb reset-device

How to contribute

Branch model

The default branch is dev. Branch off it, then open a PR back to dev:

git checkout dev && git pull
git checkout -b your-feature-name
# make changes, then:
git push origin your-feature-name

Don't push directly to dev.

CI

Every PR and every push to dev triggers a full build on Buildbot — all boards, both kernels. The green checkmark on a commit means they all passed. If your PR makes the build go red, it won't merge.

To test locally before pushing:

docker build -t flipperone-linux-build-scripts .
mkdir -p out
docker run --privileged --rm -v "$(pwd)/out:/artifacts" flipperone-linux-build-scripts

Adding kernel config options

Drop a config fragment file in configs/linux/ (mainline) or configs/linux-bsp/ (BSP). Every file in those directories gets merged in. One file per logical feature.

Modifying the root filesystem

Files go in overlays/, mirroring the target filesystem: overlays/configs//etc/, overlays/usr//usr/, etc. Firmware blobs go in overlays/firmware/. For system packages, edit debian-rk3576-ospack.yaml.

Adding a new board

  1. U-Boot: If the board needs a custom U-Boot tree, note the UBOOT_GIT/UBOOT_BRANCH/BOARD values in the PR description. If it uses the Rockchip binary BL31, note USE_BL31=vendor.
  2. Device tree (mainline kernel): If a DTS is already upstream, nothing extra is needed. If not, add the source to the appropriate location and document it.
  3. Device tree (BSP kernel): Vendor DTS files go in vendor-dts/ (see vendor-dts/omni3576/ for the layout). Device tree overlays go in vendor-dts/bsp/ as .dtso files.
  4. Kernel config: Board-specific options go as a fragment in configs/linux/ or configs/linux-bsp/.
  5. Open a PR with a description of the board and how you tested that the image boots.