Recently, I got my hands on a StarFive VisionFive Single Board Computer thanks to the RISC-V Developer Boards program. For a quick start, StarFive provides an image based on Fedora 33 that can be flashed to a microSD card. This boots without problems and gives you a working environment in a couple of minutes. However, with the installation based on Fedora 33 and apparently no recent updates available, this doesn’t feel like a future-proof setup. So I started looking for an alternative distribution, and one active port for the RISC-V architecture is provided by Debian.
There already exist a couple of instructions how to create a bootable Debian system image for the VisionFive.
This includes a guide on the forum by Houge Langley and recently also a page on the Debian Wiki.
At least the latter did not yet exist when I received my board, so I started experimenting based on the guide by Houge and the generic instructions for the RISC-V port of Debian.
My goal was to simplify as much as possible, and ideally not create partitions just so that the boot configuration in
uEnv.txt ends up on the third partition.
This can be achieved by having a careful look at the U-Boot configuration for the JH7100 SoC and realizing that there is a second place this file can be stored:
Before looking for
/boot/uEnv.txt on the third partition (must be formatted as
fatload looks for the
uEnv.txt in the root of the first FAT partition1.
A secondary goal was to avoid copying binary files from the Fedora image, in particular
Instead, I use the
bootefi command to let U-Boot give control to the Linux kernel directly.
In the remainder of this post, I’m going to give instructions how to create a bootable Debian system image. I will skip over most of the details, please consult the mentioned guides and wiki pages for more information.
Building the Linux Kernel
The heart of the system image is a Linux kernel that supports the board’s hardware.
Sadly, it’s not (yet) possible to use Debian’s kernel image for this or even boot the latest mainline version.
Instead, StarFive and in particular Emil Renner Berthing maintain a fork at https://github.com/starfive-tech/linux with the necessary changes.
To build a bootstable installation, you need to (cross-)compile the kernel sources.
This is explained in the repository’s
README and eventually boils down to the following two commands:
One word of caution: The default branch in the repository is based on mainline kernel versions. It should be thought of as “a collection of patches that will hopefully mature enough to be submitted upstream eventually”. As such, it is rebased regularly, which comes with the caveat of running Linux release candidates.
Preparing the System Image
I find it convenient to prepare the system image in a file, instead of directly on a microSD card:
900 MB might sound little, but is enough to bootstrap a minimal Debian system.
Next, create two partitions with
fdisk debian-visionfive.img or another tool of your choice.
The first partition will be the
/boot partition and 128 MB should be plenty (one kernel is around 20 MB).
The second partition will the root of the system image, and should take the rest of available space.
Upon flashing, you should obviously enlarge the root filesystem to fill the rest of the microSD card.
Now set up a loop device:
--partscan option to
losetup is necessary to scan the partition table and make the
loop0p2 devices appear.
Finally create the filesystems, and mount them:
Please note that the
/boot partition must be formatted as FAT, or U-Boot won’t find the
In principle, the root partition could be any filesystem, assuming the kernel built in the previous step has a driver for it.
However, I didn’t test this and I think
ext4 is a good default choice for a Single Board Computer.
At this point, we need to (cross-)bootstrap the Debian system.
This step requires static
qemu-user to emulate RISC-V programs on x862.
For Debian, the necessary packages are listed under the section “Creating a riscv64 chroot”.
On Arch Linux, the official
qemu-user package has dynamically linked binaries but there is the AUR package
Before finally running
deboostrap, I recommend setting up the keyring:
(On Debian, you can skip this step and instead install the
Now bootstrap the system:
This might take a while…
deboostrap has finished, there are couple of steps required to make the image work well out-of-the-box.
chroot into it to install at least an NTP client and set the
root user’s password:
You can also create other users and install the OpenSSH server, but it’s also possible to do this directly on the device once booted.
Next, configure DHCP on the Ethernet interface (assuming you want this) and delete the
resolv.conf from the host environment:
Now set the hostname and make sure
/boot is mounted automatically:
Afterwards, go the Linux build directory from the beginning and copy the kernel image as well as the device tree file:
Now put the
uEnv.txt in place to boot this kernel:
The command originally said
booti 0xa0000000 - 0xa8000000, which hands off control to the Linux kernel without EFI.
bootefiuses the kernel’s EFI Boot Stub and seems to work equally well, so I guess it should be preferred.
Finally, unmount and detach the system image that you just created:
debian-visionfive.img to a microSD card and enlarge the root filesystem.
Then plug the microSD card into your VisionFive and boot.
loadbootenvvariable expands to
fatload mmc 0 0xa0000000 uEnv.txtwhen substituting the other variables. According to the documentation of
fatload, the second parameter is
partis omitted, it “defaults to 0 (whole device)” with no mention what happens if the device actually has a partition table. Neither is there a clear statement what happens if the
filenameparameter is a relative path. However, given that the setup I’m going to describe works, I assume that the command works the way I wrote above. ↩
Unless you already have a RISC-V computer for your main development work… ↩
You do not need to agree with my opinions expressed in this blog post, and I'm fine with different views on certain topics. However, if there is a technical fault please send me a message so that I can correct it!