Emulating RISC-V system with Oreboot and Barebox, using Qemu or RVVM

Date: 2025-02-07
Tags: Barebox, RISC-V, Rust, oreboot, qemu, rvvm, system
Orebeoot with RustSBI + barebox booting on Qemu emulating RISC-V

This is a short post about the installation of usage of OreBoot bootloader and Barebox on Qemu and RVVM RISC-V virtual machine and emulators.

Precompiled version are available here:

It will take about 2.8GB in your home directory, subdir ~/.rustup/toolchains for installation of needed toolchain.

First thanks to the authors oreboot and RVVM for their softwares and their help to make it running.

Requirements for building Barebox and oreBoot

For the oreboot part only, [Rustup](The Rust toolchain installer) (the Rust toolchain installer) is currently neeeded instead of Rust to have a compatible toolchain sadly, so it will ask to remmove rust package, can be reinstalled after if needed (and another rust lib will probably ask for it). So depending on your OS it will maybe ask to remove rust package due to conflicting packages. It's the case on Arch Linux. If you prefer you can use included openSBI on qemu. Still need to compile barebox

As said in introduction, it will take 2.8GB on home directory partition. A symbolic link to a director on other partition can be put as ~/.rustup if your home partition is limited.

= Arch Linux =

On Arch Linux you will need the following things for building

sudo pacman -S --needed base-devel git pkg-config rustup riscv64-linux-gnu-gcc inetutils emscripten

Note: inetutils is only needed for hostname command used in some cases for building of Barebox. emscripten is only useful if you want to build WASM version of emulators.

= Debian =

There is only rustup package on Debian, so no question:

sudo apt install build-essential git curl rustup gcc-riscv64-linux-gnu bison flex lz4 libssl-dev libcurl4-openssl-dev libsdl-dev emscripten

Note: libcurl4-openssl-dev and libsdl-dev are only mandatory for tinyemu. emscripten is only useful if you want to build WASM version of emulators.

Installing Qemu or RVVM

Qemu is available as standard package, RVVM in AUR only for ArchLinux.

= Arch Linux =

For Qemu

sudo pacman -S qemu-system-riscv

For RVVM (rvvm-git from AUR here is needed in february 2024):

yay -S rvvm-git

For TinyEMU

sudo pacman -S tinyemu

You can donwload, following these links precompiled version of RVVM-git for x86_64 and RVVM-git for aarch64 (ARM64).

= Debian =

For Qemu

sudo apt install qemu-system-riscv

For RVVM: Need to compile it by yourself:

**Warning'': --depth 1 is for downloading only last should only be used if you only want to compile it and not to patch it and help the project.

This is based on RVVM author, Lekkit, Arch Linux AUR package PKGBUILD, just added the --depth 1 for faster installation:

git clone --depth 1 https://github.com/LekKit/RVVM
cd RVVM
unset CFLAGS
unset LDFLAGS
make USE_NET=1 all lib
sudo make USE_NET=1 PREFIX=/usr install
cd ..

For TinyEMU: Need to compile it by yourself

temu_version=2019-12-21
curl -OR https://www.bellard.org/tinyemu/tinyemu-${temu_version}.tar.gz
tar xf tinyemu-${temu_version}.tar.gz
cd tinyemu-${temu_version}
make
sudo make bindir=/usr/bin install
cd ..

= WASM =

For wasm version of tinyemu, you will need to compile it in both cases:

temu_version=2019-12-21
curl -OR https://www.bellard.org/tinyemu/tinyemu-${temu_version}.tar.gz
tar xf tinyemu-${temu_version}.tar.gz
cd tinyemu-${temu_version}
sed -i 's/-s BINARYEN_TRAP_MODE=clamp//' Makefile.js
# don't do this on Debian, need to found a solution on last Arch, this doesnt work: sed -i 's/-memory-init-file 0//' Makefile.js
make -f Makefile.js
cd ..

BINARYEN_TRAP_MODE=clamp and -memory-init-file 0 are the default on recent versions of emscripten. The first one doesn't exist anymore in 3.1.6 (debian) and both in 3.1.72 (Arch Linux) for the second one

The WASM

Building Barebox

You can found last release version at https://barebox.org/download/.

First create a dire where you want to build in, place in, and define variables:

bb_version=2025.01.0
barebox=barebox-${bb_version}
prefix=`pwd`
export ARCH=riscv
export CROSS_COMPILE=/usr/bin/riscv64-linux-gnu-
export PAYLOAD="${prefix}/${barebox}/images/barebox-dt-2nd.img"
export QEMU_RISCV_MAIN=${prefix}/oreboot/src/mainboard/emulation/qemu-riscv/main

Then compile Barebox:

if [ ! -e ${barebox}.tar.bz2 ]
then
  curl -OR https://barebox.org/download/${barebox}.tar.bz2
fi
tar xf ${barebox}.tar.bz2

cd barebox-${bb_version}
make rv64i_defconfig
make -j # use -j only if you want to use the maximum of core available

Last export will be used later with oreboot

This will make some warning, like this but will build needed image images/barebox-dt-2nd.img:

/root/barebox-2025.01.0/images/Makefile:152: FORCE prerequisite is missing

Optionnaly you can tune configuration via menuconfig insteald of using the rv64i_defconfig:

make menuconfig

Or use my part tuned config file (need to remove options of some unused/incompatibles boards with emulators, they will not be used): Use my config file, tuned several parameters (will improve it with time):

curl -OR -o .config https://gblog4.popolon.org/medias/2025-02/barebox_emulator_config.txt

Don't forget after using them to redo a make of the project:

make -j

No we have a basic Bareboot image, just for testing (need to add by yourself what you want to do with it).

Building oreboot

Variables defined previously including PAYLOAD are important here:

git clone --depth 1 https://github.com/oreboot/oreboot
cd oreboot
make firsttime
cd src/mainboard/emulation/qemu-riscv/main
make run

For the last line PAYLOAD can be set betwenn make and run, instead of exporting the variable like this

export PAYLOAD=/my/path/barebox-2025.01.0/images/barebox-dt-2nd.img run

Et voilà !, some red errors are thrown, but you should have it working with qemu and have the Barebox prompt.

barebox@riscv-virtio,qemu:/ cpuinfo
RV64I barebox for S-Mode
Hart ID=0
SBI specification v2.0 detected
SBI implementation ID=0x4 "RustSBI" Version=0x400
SBI Machine VENDORID=0x0 ARCHID=0x0 MIMPID=0x0

there are some tools included in bareboot by default, you can list them by typing help:

Asciinema demo:

To restart qemu with this you can simply, after having defined prefix as this working dir:

prefix=/my/working/dir
qemu-system-riscv64 -m 1g -machine virt -nographic \
  -bios ${prefix}/oreboot/target/riscv64imac-unknown-none-elf/release/emulation-qemu-riscv.bin \
  -device loader,addr=0x80200000,file=${prefix}/barebox-2025.01.0/images/barebox-dt-2nd.img

Here:

It is also impossible to improve RISC-V CPU features support.

For exemple for respectivly system/command/static to have RISC-V vector 1.0 extension:

qemu-system-riscv64 -M virt -cpu rv64,v=true ...
qemu-riscv64 -cpu rv64,v=true "command"
qemu-riscv64-static -cpu rv64,v=true "command"

It is also possible to have a list of supported RISC-V cpus, with max model, enabling all supported extension. Exemple with Qemu 9.2.0 (ArchLinx, february 2024):

$ qemu-riscv64 -cpu help
Available CPUs:
  max
  rv64
  rv64e
  rv64i
  rva22s64
  rva22u64
  shakti-c
  sifive-e51
  sifive-u54
  thead-c906
  veyron-v1
  x-rv128

So qemu can runs with all extensions include vector one by using:

qemu-system-riscv64 -cpu max ...

You can found some example of using RISC-V Vector extension (generaly called rvv) by Bruce Hoult here or for rvv v0.8 (never had hardware implementation) by Georg Sauthoff, for rvv v0.7.1 only (used on D1 and other first hardware implementation, maid generaly by THead): by Enthusi.

RVVM

RVVM syntax is simpler rvvm <boot> -k <payload/kernel>. So:

rvvm ${prefix}/oreboot/target/riscv64imac-unknown-none-elf/release/emulation-qemu-riscv.bin \
  -k ${prefix}/barebox-2025.01.0/images/barebox-dt-2nd.img
Screenshot of Barebox on RVVM

TinyEMU

Didn't managed to have Oreboot writing on graphics display framebuffer, nor to display default serial console on TinyEmu for now. This could maybe help someone else to found a solution. If I found one, I will correct it here.

You need to create a configuration file first. Like this here:

If you don't use cat to create the file, replace ``${prefix}'' by the content of this variable.

cat >oreboot-barebox.cfg <<EOF
{
    version: 1,
    machine: "riscv64",
    memory_size: 256,
    bios: "${prefix}/oreboot/target/riscv64imac-unknown-none-elf/release/emulation-qemu-riscv.bin",
    kernel: "${prefix}/barebox-2025.01.0/images/barebox-dt-2nd.img",
    eth0: { driver: "user" },
    display0: {
        device: "simplefb",
        width: 1024,
        height: 640,
    },
    input_device: "virtio",
}
EOF

TODO TinyEmu and WASM version for RVVM/TinyEmu.

Tags: Barebox, RISC-V, Rust, oreboot, qemu, rvvm, system