Installing Ubuntu Server on the StarFive VisionFive 2

Installing Ubuntu Server on the StarFive VisionFive 2

A Step-by-Step guide to installing Ubuntu on RISC-V

In the evolving landscape of computer architectures, bringing familiar operating systems to new platforms presents a unique set of challenges. A recent endeavour of mine involved installing Ubuntu Server on the StarFive VisionFive 2 RISC-V board.

Unlike the straightforward installation process we're accustomed to with more mainstream architectures, this task required delving into the nuances of UEFI bootloader configurations and intricately managing the board's boot process.

This blog post is a deep dive into that journey, aiming to demystify the steps needed to achieve a stable and functional Ubuntu setup on this emerging architecture.

📋 Prerequisites

⚠️ Before you begin, your VisionFive 2 board will need to be running the latest firmware. For a guide on how to do this, check out my previous blog post ⚠️

Hardware you will need:

  • A MicroSD card (8GB+)

  • NVME SSD (installed on the underside of the VisionFive 2 board)

  • USB to UART dongle


✅ Board Setup

Flash the installer to the MicroSD card using Etcher and insert it into the MicroSD slot of the board.

Set the DIP switches to set the Boot Mode to Flash

  • RGPIO_1 -> 0

  • RGPIO_0 -> 0

Finally, set up the UART to USB connection. I have been using the Raspberry Pi Debug Probe which works great. Connect the UART leads to the board as follows:

  • Pin 6 -> GND

  • Pin 8 -> RX

  • Pin 10 -> TX

StarFive VisionFive2 Board With UART Connected

Next, you need to connect to the serial terminal. If you are using macOS for example, the serial device will show with a prefix of tty.usbmodem, so you can search for it with the command:

ls /dev | grep tty.usb

Then initialise a connection to it using picocom:

sudo picocom -b 115200 /dev/tty.usbmodem2112402

Now we are ready to install Ubuntu!

👢Booting the Ubuntu Installer

To successfully boot the installer on the StarFive VisionFive 2 board, we must first identify the appropriate MicroSD Card and manually load essential files using U-Boot commands. Unlike more conventional systems where this process might be automated, the Ubuntu Installer for this specific RISC-V architecture requires direct intervention through the serial console. This step is crucial for initiating the installation process.

Firstly, power on the VisionFive board and interrupt the boot process when we see the following:

Hit any key to stop autoboot:  2

We start by listing all available memory cards with mmc list to see what options we have:

StarFive # mmc list
sdio0@16010000: 0
sdio1016020000: 1

In this case, we can see two devices listed; however, only one will be the MicroSD card with the installer on it. We can use the part list command to probe the device for partitions, and from there, determine which device and partition we need.

Let's examine the first device:

StarFive # part list mmc 0
Card did not respond to voltage select! : -110

Any time you see Card did not respond to voltage select! : -110, this generally means the device does not exist, or is not valid. So in this case we need to inspect the device with ID 1:

StarFive # part list mmc 1

Partition Map for MMC device 1  --   Partition Type: EFI

Part    Start LBA    End LBA        Name
    Type GUID
    Partition GUID
  1    0x0000a000    0x0003efff    "EFI System"
    attrs:    0x0000000000000000
    type:    c12a7328-f81f-11d2-ba4b-00a0c93ec93b
    type:    system
    guid:    df2030ee-9281-40ba-8e38-027c9f37917e
  2    0x0003f000    0x0063efff    "Live Media"
    attrs:    0x0000000000000004
    type:    0fc63daf-8483-4772-8e79-3d69d8477de4
    type:    linux
    guid:    4b987a45-c7ad-4804-9048-717d7d37d6b0
  3    0x00000022    0x00000821    "loader1"
    attrs:    0x0000000000000000
    type:    5b193300-fc78-40cd-8002-e86c45580b47
    guid:    ad54bbfb-4527-4681-8f6e-fa7ef471109f
  4    0x00000822    0x00002821    "loader2"
    attrs:    0x0000000000000000
    type:    2e54b353-1271-4842-806f-e436d6af6985
    guid:    3a71d22e-655d-46a6-99db-66c67ea264a1
  5    0x0063f000    0x0e81f7ff    ""
    attrs:    0x0000000000000000
    type:    0fc63daf-8483-4772-8e79-3d69d8477de4
    type:    linux
    guid:    84bc9b76-b57e-4fa4-9367-cef404541690

We are looking for the EFI System partition, which in this case is partition number 1 of device 1

Next, we load a crucial hardware configuration file called the Device Tree Blob (DTB) from the the EFI Partition of the MicroSD Card (mmc 1:1) into the system's memory using the load command as below:

load mmc 1:1 $fdt_addr_r dtb/starfive/jh7110-starfive-visionfive-2-v1.3b.dtb

Following that, we also load the RISC-V Linux kernel, located in an EFI file, into memory using the load command:

load mmc 1:1 $kernel_addr_r EFI/boot/bootriscv64.efi

You will know the load command has run successfully if you see a message in the format of 12345 bytes read in 10 ms.

Finally, we initiate the boot process with the bootefi command:

bootefi $kernel_addr_r $fdt_addr_r

This uses the loaded kernel and hardware configuration file to start up the installer. This sequence of commands essentially prepares the system and directs it to boot up from the specified files located on the memory card.

If successful, after a few seconds you should be greeted with the GRUB bootloader screen:

GRUB Bootloader

Hit enter, or wait 30s, to proceed to the installer.

⚙️ Running Through the Installer

The installer can take a few minutes to run through the boot process and can, at times, appear to hang, but just let it run and it will eventually show you the following screen:

Ubuntu Installer via Serial

From this menu, you can continue working with the installer via the serial console in either rich or basic mode. However, personally I found it easier, and more reliable, to use the SSH method. If you choose this method, you will be provided instructions on how to access the installer over SSH:

Ubuntu Installer SSH Config

Once you SSH in, you will see the standard Ubuntu Server installer program:

Ubuntu Installer

The rest of the installer is the same as any other system, so work through it and configure the installation to your needs. Be sure to install Ubuntu on the NVME drive when prompted for the disk configuration - this will likely be the default option.

Once installed, let the device reboot automatically and move on to the final stage of configuring Ubuntu on the StarFive 2 board.

🥾Booting Ubuntu on NVME

Once the board reboots, you will likely be greeted with error messages in the serial console and Ubuntu will not boot automatically from the NVME drive:

Retrieving file: /extlinux/extlinux.conf
Can't set block device
Error reading config file

Don't panic, this is normal! In most systems, the Ubuntu installer will automatically configure UEFI variables to tell the bootloader how to boot into GRUB, however, U-Boot does not allow operating systems to configure these directly. So, we will have to do this manually.

Once the board has hit the error, it should drop you into the U-Boot prompt. From here you can run commands to boot Ubuntu manually:

pci enum
nvme scan
efidebug boot add -b 0001 'Ubuntu' nvme 0:1 /EFI/ubuntu/grubriscv64.efi
efidebug boot order 0001
bootefi bootmgr

We first enumerate the PCI devices on the board with pci enum, then we use nvme scan to identify and prepare any connected NVMe drives for use, allowing the system to recognize and interact with them.

Next, we need to add a UEFI boot entry with efidebug boot add. In this case, we are setting boot entry 1 and pointing it to the NVME drive with nvme 0:1 and finally pointing it to the EFI executable /EFI/ubuntu/grubriscv64.efi.

We then set the boot order with efidebug boot order and then use bootefi bootmgr to boot the system using the UEFI boot manager. This will attempt to boot from the boot entries in the order they are set in the UEFI configuration, starting with the entry you specified (0001 in this case).

🔄 Getting Ubuntu to Boot Automatically from NVME

This above commands will boot Ubuntu fine every time, but this will not "stick" and the next time you boot the board you will face the same error and the OS will not load automatically. So just how do we achieve automatic boots?

Once again, we need to drop into the U-Boot console. This time we can set some UEFI environment variables to store the commands and run them automatically each time the board is booted:

env default -f -a
setenv bootcmd_nvme0 "pci enum; nvme scan; efidebug boot add -b 0001 'Ubuntu' nvme 0:1 /EFI/ubuntu/grubriscv64.efi; efidebug boot order 0001; bootefi bootmgr"
setenv bootcmd 'run bootcmd_nvme0'

First, we clear any existing variables to ensure a clean slate. Afterwards, we bundle the chain of commands into the bootcmd_nvme0 variable for use later.

Then we point the bootcmd variable to run our custom boot command. The bootcmd variable defines the series of commands that U-Boot will automatically execute during the boot process. Essentially, it's the default action that U-Boot will take unless interrupted or directed otherwise.

Finally, save the variables and you are good to go!

Ubuntu Console on StarFive VisionFive 2 RISC-V Board

The support for this board and RISC-V is still early for Ubuntu and certain things, such as HDMI output, may not be functional at the time of writing this. I suggest accessing the device through the serial console first, enabling SSH and going from there.

🤔 Conclusion

In summary, installing and running Ubuntu on the StarFive VisionFive 2 board is a journey through the intricacies of U-Boot/UEFI, highlighting the adaptability required when working with emerging architectures.

By manually configuring the UEFI boot process, we can successfully navigate these hurdles and get our favourite distros up and running. This process not only underscores the importance of a solid foundational understanding of system boot mechanisms but also opens the door to the vast potential of RISC-V boards in the world of Linux computing.

Have you ventured into installing operating systems on unconventional architectures like RISC-V? Do you have experiences, insights, or questions about running Ubuntu on the StarFive VisionFive 2 or similar boards? I’d love to hear about your journey and any challenges or triumphs you’ve encountered along the way. Feel free to share in the comments below or reach out to me on Mastodon!