User Tools

Site Tools


This is an old revision of the document!

Cross-compile a default Linux kernel

Now that you have a toolchain in place let's start by cross-compiling the Linux kernel with the default configuration. First clone the riscv-linux repository…

git clone --depth=1 <linux sources dir>

Then configure it with the default configuration. That includes virtio support so that you can use this kernel with QEMU later on.

cd <linux sources dir>
ARCH=riscv CROSS_COMPILE=riscv64-unknown-linux-gnu- make defconfig

And finally build the kernel…

ARCH=riscv CROSS_COMPILE=riscv64-unknown-linux-gnu- make

You should now have the kernel image as vmlinux, you may verify its compiled for RISC-V using the file command

vmlinux: ELF 64-bit LSB executable, UCB RISC-V, version 1 (SYSV), statically linked, BuildID[sha1]=..., not stripped

Cross-compile the Berkeley Boot Loader

In order to boot the kernel you just build you'll need a bootloader that supports the RISC-V Linux boot protocol and Supervisor Binary Interface (SBI). The Berkeley Boot Loader or BBL will do the trick.

git clone --depth=1 <bbl sources dir>
cd <bbl sources dir>
mkdir build
cd build
../configure --enable-logo --host=riscv64-unknown-linux-gnu

If you want you can also link the kernel and the bootloader together to create a simple binary for systems/emulators that can't distinguish between them (they just expect to run a binary). To do that you may pass the –with-payload argument to the configure script, pointing to the kernel image.

../configure --enable-logo --host=riscv64-unknown-linux-gnu \
             --with-payload=<linux sources dir>/vmlinux

Prepare a simple initramfs for testing

In order to test the kernel and the various kernel modules from the process above, you need to create a simple rootfs. Let's start by creating a directory and populating it with a typical directory layout…

mkdir -p <rootfs dir>/{bin,sbin,dev,proc,sys,etc,var/run,/lib/firmware,mnt}

…and install the kernel modules in there.

INSTALL_MOD_PATH=<rootfs dir> ARCH=riscv make modules_install

Cross-compile busybox

Busybox is a set of common UNIX tools and services combined together on a single program, that can also be statically compiled to provide a system-in-a-box, without any external dependencies. Since it's a whole suite of tools, its configuration process is similar to that of the kernel. You may use make menuconfig and work your way through, use make defconfig to get a full-featured build or you may grab busybox-config.gz and use that instead. Remember to edit the configuration and properly set CONFIG_PREFIX to <rootfs dir>.

git clone -b 1_29_stable --depth=1 git:// <busybox sources dir>
cd <busybox sources dir>
zcat busybox-config.gz | sed s#"../../rootfs"#<rootfs dir>#g > .config
ARCH=riscv make
make install

Add an init script and an inittab

This will install BusyBox on the rootfs directory and create the symbolic links to the BusyBox binary. All that remains now is to let Linux use BusyBox as the init program, to do that you need to add a symbolic link from <rootfs dir>/init to the BusyBox binary, create an init script and an inittab. To save time here is an example of an init script


# Mount /dev, /proc and /sys
mount -t devtmpfs none /dev
mount -t proc -o nodev,noexec,nosuid proc /proc
mount -t sysfs -o nodev,noexec,nosuid sysfs /sys

# Initialize networking
ip link set lo up
ip addr add dev lo
ip route add dev lo

ip link show eth0 | grep eth0 &> /dev/null
if [[ $? == 0 ]]; then
        ip link set eth0 up

echo -e "\t\tWelcome to RISC-V !"
echo "$(uname -s -v -r -p -m)"

exec setsid cttyhack /bin/bash

And an example of an inittab that assumes you've put the above init script on <rootfs dir>/sbin/initscript

::shutdown:/bin/umount -a -r > /dev/null

BusyBox expects to find the above inittab file on /etc/inittab so put it on <rootfs dir>/etc/inittab and you are done. Finally make the symbolic link for <rootfs dir>/init

cd <rootfs dir>
ln -s ./bin/busybox ./init

Create the initramfs image

Since <rootfs dir> is now populated and ready, lets make an initramfs image out of it. Initramfs images are cpio images, compressed with one of the kernel-supported compression algorithms, of them xz is probably the most efficient so that's what we'll be using here.

cd <rootfs dir>
find . find . -print0 | cpio --null -ov --format=newc > /tmp/initramfs.cpio
cd /tmp/
xz -e -T0 --check=crc32 --lzma2=dict=32MiB initramfs.cpio
mv initramfs.cpio.xz initramfs.img

Copy the initramfs.img file from /tmp to anywhere you want, you may now test your Bootloader + Linux kernel + initramfs setup with an emulator.

developers/env_buildtest.1540889145.txt.gz · Last modified: 2018/10/30 10:45 by mick