Off-topic: The importance of efficient tooling
You’re probably aware of the existence and hopes tied to the rise of the RISC-V architecture, which means we should prepare for future (yet hypothetical) RISC-V Linux-based mobile devices.
The first step in this journey being the ability to build binary packages for this architecture, we purchased a StarFive VisionFive v2 SBC with the goal to turn it into a (Debian-powered, of course!) GitLab CI runner. And that’s exactly where the tools developed to build Mobian came in really handy!
Debian on RISC-V
64-bits RISC-V (or
riscv64 in Debian terms) is not an architecture officially
supported by upstream Debian. However, the vast majority of packages are built
and available to
riscv64 devices thanks to the Debian Ports
As an unofficial port, the
riscv64 packages live in a separate archive,
providing only the
experimental suites. Those details aside,
all the usual Debian tools work in the exact same way they do on other
With this in mind, why not use the tools we’ve been developing for Mobian and create an “almost-pure” Debian image for the VisionFive v2?
The VisionFive 2 is a RISC-V SBC based on StarFive’s JH7110 SoC. This chip includes 4x SiFive U74 cores, Gigabit Ethernet, PCIe and many other interfaces.
The board itself includes a choice of 2, 4 or 8GB RAM, a now-standard 40-pin GPIO header, a microSD card slot, an eMMC socket as well as an M.2 slot for an NVMe SSD, and of course several USB ports and 2 Gigabit Ethernet ports.
OK, but… can it run Debian?
In order to run any kind of Linux system (including a Debian-based one), we need the following elements:
- a bootloader
- a kernel which includes support for this specific device
- a root filesystem containing userspace software, compiled for the device’s CPU architecture
Das U-boot Abenteuer
The first item is already present on the board, in the form of a SPI NOR flash
chip, factory-flashed with
u-boot. However, the one present on our (early
bird) board lacked support for standard “distroboot”, therefore we had to build
a more recent version from StarFive’s u-boot
repository and flash it using the documented
It required backporting an upstream
to be able to build using the compiler and
binutils from current Debian
testing. However, for some reason using the latest commit (at the time) of the
JH7110_VisionFive2_devel branch led to a non-functional binary, unable to
detect the RAM size of our board. One more
later, we could however get a working bootloader!
It wasn’t capable of using the “distroboot” due to wrong and/or missing environment variables, which were later added. Feel free to refer to our patched source tree, or simply download the binary files from our artifacts branch.
A working kernel
u-boot, StarFive provides a
repository, including all needed patches to get it running on the VisionFive 2
board… and just like
u-boot, it doesn’t build from a current Debian
This is easily solved by, once again, backporting an upstream
Once built with the usual
make bindeb-pkg command (and, of course, the proper
values for the
CROSS_COMPILE env vars), we get a
the kernel and its modules, which boots just fine. However, the default kernel
config is somewhat limited and doesn’t allow us to run
docker (remember, we
want to make this board a GitLab CI runner!). With some additional
we finally get to a point where this kernel is fully usable for our purpose.
Our patched kernel is of course also available on GitLab.
Tying it all together
Putting the architecture differences aside, this device is quite similar to the PinePhone Pro from a low-level perspective: the bootloader is directly flashed to the board’s SPI flash, and we need to create a bootable image to be written on a microSD card.
We already know how to do this on the PPP, so why not re-use this knowledge for the VisionFive 2? Not wanting to mess with Mobian’s “production” codebase, we imported this repo to gitlab.com and made the necessary changes there. As you’ll notice from the single commit needed to generate the VisionFive 2 image, the changes are very minimal, demonstrating the flexibility and power of the tools we’ve been developing over the past 3 (!) years.
Let’s walk through those changes:
build.shscript is modified to support a new
riscv64device (it could/should probably have been named
vf2, but remember this is only a quick and dirty experiment), using the
riscv64architecture and fetching its device-specific recipes from
devices/riscv64is mostly a copy from
devices/rockchipwith only a few small adjustments:
- as the kernel package is locally-built and not available from the Mobian
repository, it is copied under a subfolder and imported to the rootfs
overlayaction, then manually installed using a
- no package is installed for
phoshas we want to create a minimal system.
- as the kernel package is locally-built and not available from the Mobian repository, it is copied under a subfolder and imported to the rootfs using the
- the global
packages-base.yamlsub-recipe is modified to always include
openssh-server, which is pretty much a requirement for a headless system.
- the most important changes lie in the
- use the
debian-portsarchive when building for the
riscv64architecture; as this archive uses different GPG keys than the main Debian archive, we use the relevant key file from the host system (this requires first installing the
debian-ports-archive-keyringpackage on the host system).
debootstrapwon’t install it, we install the
debian-ports-archive-keyringpackage to the rootfs so it can be updated over time.
- we drop the
packages-$environmentsub-recipe (minimal system, remember?)
- use the
With those changes, building the image is as simple as running
./build.sh -t riscv64. It can then be flashed to a microSD and should bring
you a fully functional Debian/Mobian system on your VisionFive 2 :)
Note: we could have easily made it a “pure” Debian image, however we carry a
patched version of
u-boot-menu which simplifies the image generation process
This process can probably easily be replicated for PINE64’s
once it becomes available, as both boards use the same SoC. Likewise, this
experiment can and will be re-used as the first step towards proper
support in Mobian, hopefully in a not-so-distant future ;)
We hope this article will also highlight how building and/or using flexible and powerful tools can greatly help expanding a project’s features set, and can even be used for only remotely-related tasks. It also shows how “easy” it can be to create Debian-based images for embedded systems (as opposed to, for example, having to re-compile the whole world twice using Yocto ;) ).
Finally, we want to point out how such things can only happen in the FLOSS world:
- being able to build each package from source is what makes the Debian ports initiative possible at all
- the vendor publishing the source code to the bootloader and kernel allowed us to build those with the needed options to fulfill our needs
- anyone (with decent knowledge of Linux systems internals) can build their own image easily, adding or removing packages and tweaks as they see fit, rather than being stuck with a generic (and probably bloated) third-party image.