Embedded Linux From Scratch Riscv
Embedded Linux From Scratch Riscv
- Kernel, drivers and embedded Linux - Development, consulting, training and support - https://bootlin.com 1/67
Michael Opdenacker
- Kernel, drivers and embedded Linux - Development, consulting, training and support - https://bootlin.com 2/67
About this presentation
- Kernel, drivers and embedded Linux - Development, consulting, training and support - https://bootlin.com 3/67
Embedded Linux from scratch in 50 minutes (on RISC-V)
Introduction
- Kernel, drivers and embedded Linux - Development, consulting, training and support - https://bootlin.com 4/67
What I like in embedded Linux
- Kernel, drivers and embedded Linux - Development, consulting, training and support - https://bootlin.com 5/67
Goals
Show you the most important aspects of embedded Linux development work
▶ Building a cross-compiling toolchain
▶ Creating a disk image
▶ Booting a using a bootloader
▶ Loading and starting the Linux kernel
▶ Building a root filesystem populated with basic utilities
▶ Configuring the way the system starts
▶ Setting up networking and controlling the system via a web interface
▶ Do this on QEMU and on real hardware!
- Kernel, drivers and embedded Linux - Development, consulting, training and support - https://bootlin.com 6/67
Things to build today
- Kernel, drivers and embedded Linux - Development, consulting, training and support - https://bootlin.com 7/67
Embedded Linux from scratch in 50 minutes (on RISC-V)
Cross-compiling toolchain
- Kernel, drivers and embedded Linux - Development, consulting, training and support - https://bootlin.com 8/67
What’s a cross-compiling toolchain?
- Kernel, drivers and embedded Linux - Development, consulting, training and support - https://bootlin.com 9/67
Why generate your own cross-compiling toolchain?
- Kernel, drivers and embedded Linux - Development, consulting, training and support - https://bootlin.com 10/67
Generating a RISC-V musl toolchain with Buildroot
- Kernel, drivers and embedded Linux - Development, consulting, training and support - https://bootlin.com 11/67
Embedded Linux from scratch in 50 minutes (on RISC-V)
- Kernel, drivers and embedded Linux - Development, consulting, training and support - https://bootlin.com 12/67
RISC-V: a new open-source ISA
See https://en.wikipedia.org/wiki/RISC-V
- Kernel, drivers and embedded Linux - Development, consulting, training and support - https://bootlin.com 13/67
RISC-V boards supported by Linux
- Kernel, drivers and embedded Linux - Development, consulting, training and support - https://bootlin.com 14/67
Beagleboard.org RISC-V boards
BeagleV-Ahead
BeagleV-Fire
https://www.beagleboard.org/boards/beaglev-ahead
https://www.beagleboard.org/boards/beaglev-fire Alibaba T-Head TH1520 SoC, 150 USD.
Microchip Polarfire MPFS025T SoC FPGA, 150 USD.
- Kernel, drivers and embedded Linux - Development, consulting, training and support - https://bootlin.com 15/67
Other community friendly RISC-V boards
https://wiki.sipeed.com/hardware/en/lichee/th1520/lpi4a/1_intro.html
- Kernel, drivers and embedded Linux - Development, consulting, training and support - https://bootlin.com 16/67
Inexpensive Milk-V boards
https://milkv.io/duo-s
Sophgo SG2000 C906@1GHz + C906@700MHz, 1xCortex-A53 @ 1GHz
https://milkv.io/duo 512 MB RAM, 10 USD
Milk-V Duo:
Cvitech CV1800B C906@1GHz + C906@700MHz CPU Products targeting camera applications
64 MB RAM, 5 USD
Caution: 1 core for Linux, 1 core for RTOS
Preliminary support in upstream kernel
Milk-V Duo 256M:
Sophgo SG2002 C906@1GHz + C906@700MHz, 1xCortex-A53 @ 1GHz Thanks to Thomas Bonnefille for the
256 MB RAM, 8 USD recommendation!
- Kernel, drivers and embedded Linux - Development, consulting, training and support - https://bootlin.com 17/67
Embedded Linux from scratch in 50 minutes (on RISC-V)
- Kernel, drivers and embedded Linux - Development, consulting, training and support - https://bootlin.com 18/67
Testing the toolchain
▶ Run source riscv64-env.sh, take a hello.c file and test your new compiler:
We are compiling statically so far to avoid having to deal with shared libraries.
▶ Test your executable with QEMU in user mode:
$ qemu-riscv64 hello
Hello world!
- Kernel, drivers and embedded Linux - Development, consulting, training and support - https://bootlin.com 19/67
Embedded Linux from scratch in 50 minutes (on RISC-V)
Hardware emulator
- Kernel, drivers and embedded Linux - Development, consulting, training and support - https://bootlin.com 20/67
Finding which machines are emulated by QEMU
- Kernel, drivers and embedded Linux - Development, consulting, training and support - https://bootlin.com 21/67
Embedded Linux from scratch in 50 minutes (on RISC-V)
- Kernel, drivers and embedded Linux - Development, consulting, training and support - https://bootlin.com 22/67
RISC-V privilege modes
- Kernel, drivers and embedded Linux - Development, consulting, training and support - https://bootlin.com 23/67
Embedded Linux from scratch in 50 minutes (on RISC-V)
Firmware
- Kernel, drivers and embedded Linux - Development, consulting, training and support - https://bootlin.com 24/67
OpenSBI: Open Supervisor Binary Interface
- Kernel, drivers and embedded Linux - Development, consulting, training and support - https://bootlin.com 25/67
Embedded Linux from scratch in 50 minutes (on RISC-V)
U-Boot bootloader
- Kernel, drivers and embedded Linux - Development, consulting, training and support - https://bootlin.com 26/67
Environment for U-Boot cross-compiling
export CROSS_COMPILE=riscv64-linux-
▶ CROSS_COMPILE is the cross-compiler prefix, as our cross-compiler is
riscv64-linux-gcc.
- Kernel, drivers and embedded Linux - Development, consulting, training and support - https://bootlin.com 27/67
Cross-compiling U-Boot
make qemu-riscv64_smode_defconfig
▶ Now let’s compile U-Boot (-j20: 20 compile jobs in parallel)
make -j20
▶ Result: u-boot.bin (859376 bytes!).
We could make it much smaller by removing many options!
- Kernel, drivers and embedded Linux - Development, consulting, training and support - https://bootlin.com 28/67
Starting U-Boot in QEMU
qemu-system-riscv64 -m 2G \
-nographic \
-machine virt \
-smp 8 \
-kernel u-boot/u-boot.bin
▶ -m: amount of RAM in the emulated machine
▶ -smp: number of CPUs in the emulated
machine
Exit QEMU with [Ctrl][a] followed by [x]
- Kernel, drivers and embedded Linux - Development, consulting, training and support - https://bootlin.com 29/67
Embedded Linux from scratch in 50 minutes (on RISC-V)
Linux kernel
- Kernel, drivers and embedded Linux - Development, consulting, training and support - https://bootlin.com 30/67
Environment for kernel cross-compiling
export CROSS_COMPILE=riscv64-linux-
export ARCH=riscv
▶ ARCH is the name of the subdirectory in arch/ corresponding to the target
architecture.
- Kernel, drivers and embedded Linux - Development, consulting, training and support - https://bootlin.com 31/67
Kernel configuration
make menuconfig
- Kernel, drivers and embedded Linux - Development, consulting, training and support - https://bootlin.com 32/67
Compiling the kernel
make -j 20
At the end, you have these files:
vmlinux: raw kernel in ELF format (not bootable, for debugging)
arch/riscv/boot/Image: uncompressed bootable kernel
arch/riscv/boot/Image.gz: compressed kernel
- Kernel, drivers and embedded Linux - Development, consulting, training and support - https://bootlin.com 33/67
Embedded Linux from scratch in 50 minutes (on RISC-V)
- Kernel, drivers and embedded Linux - Development, consulting, training and support - https://bootlin.com 34/67
Booting the Linux kernel directly
qemu-system-riscv64 -m 2G \
-nographic \
-machine virt \
-smp 8 \
-kernel linux/arch/riscv/boot/Image \
-append "console=ttyS0" \
However, what we want to demonstrate is the normal booting process:
OpenSBI →U-Boot →Linux →Userspace
- Kernel, drivers and embedded Linux - Development, consulting, training and support - https://bootlin.com 35/67
Booting the Linux kernel from U-Boot
▶ We want to show how to set the U-Boot environment to load the Linux kernel
and to specify the Linux kernel command line
▶ For this purpose, we will need some storage space to store the U-Boot
environment, load the kernel binary, and also to contain the filesystem that Linux
will boot on.
▶ Therefore, let’s create a disk image to give some storage space for QEMU
- Kernel, drivers and embedded Linux - Development, consulting, training and support - https://bootlin.com 36/67
Disk image creation (1)
cfdisk disk.img
• A first 64 MB primary partition (type
W95 FAT32 (LBA)), marked as bootable
• A second partition with remaining space
(default type: Linux) https://asciinema.org/a/656814
- Kernel, drivers and embedded Linux - Development, consulting, training and support - https://bootlin.com 37/67
Disk image creation (2)
ls -la /dev/loop31*
brw-rw---- 1 root disk 7, 2 Jan 14 10:50 /dev/loop31
brw-rw---- 1 root disk 259, 11 Jan 14 10:50 /dev/loop31p1
brw-rw---- 1 root disk 259, 12 Jan 14 10:50 /dev/loop31p2
▶ We can now format the partitions:
- Kernel, drivers and embedded Linux - Development, consulting, training and support - https://bootlin.com 38/67
Copying the Linux image to the FAT partition
mkdir /mnt/boot
▶ Let’s mount it:
- Kernel, drivers and embedded Linux - Development, consulting, training and support - https://bootlin.com 39/67
Recompiling U-Boot for environment support
make menuconfig
• CONFIG_ENV_IS_IN_FAT=y
• CONFIG_ENV_FAT_INTERFACE="virtio"
• CONFIG_ENV_FAT_DEVICE_AND_PART="0:1"
▶ Then recompile U-Boot
https://asciinema.org/a/656816
make -j20
- Kernel, drivers and embedded Linux - Development, consulting, training and support - https://bootlin.com 40/67
Run U-Boot with an environment
- Kernel, drivers and embedded Linux - Development, consulting, training and support - https://bootlin.com 41/67
Embedded Linux from scratch in 50 minutes (on RISC-V)
- Kernel, drivers and embedded Linux - Development, consulting, training and support - https://bootlin.com 42/67
Requirements for booting Linux
- Kernel, drivers and embedded Linux - Development, consulting, training and support - https://bootlin.com 43/67
Linux kernel command line
▶ root=/dev/vda2
Device for Linux to mount as root filesystem
▶ console=ttyS0
Device (here first serial line) to send Linux booting messages to
▶ earlycon=sbi
Allows to see messages before the console driver is initialized (Early Console).
▶ rw
Allows to mount the root filesystem in read-write mode.
- Kernel, drivers and embedded Linux - Development, consulting, training and support - https://bootlin.com 44/67
Booting Linux
▶ Here’s the command to boot the Linux Image file:
setenv bootcmd 'fatload virtio 0:1 84000000 Image; booti 0x84000000 - ${fdtcontroladdr}'
saveenv
▶ And boot our system (boot runs bootcmd):
boot
- Kernel, drivers and embedded Linux - Development, consulting, training and support - https://bootlin.com 45/67
Booting Linux... almost there
- Kernel, drivers and embedded Linux - Development, consulting, training and support - https://bootlin.com 46/67
Embedded Linux from scratch in 50 minutes (on RISC-V)
- Kernel, drivers and embedded Linux - Development, consulting, training and support - https://bootlin.com 47/67
BusyBox - Most Linux commands in one binary
[, [[, acpid, add-shell, addgroup, adduser, adjtimex, arch, arp, arping, ash, awk, base64, basename, bc, beep, blkdiscard, blkid,
blockdev, bootchartd, brctl, bunzip2, bzcat, bzip2, cal, cat, chat, chattr, chgrp, chmod, chown, chpasswd, chpst, chroot, chrt,
chvt, cksum, clear, cmp, comm, conspy, cp, cpio, crond, crontab, cryptpw, cttyhack, cut, date, dc, dd, deallocvt, delgroup,
deluser, depmod, devmem, df, dhcprelay, diff, dirname, dmesg, dnsd, dnsdomainname, dos2unix, dpkg, dpkg-deb, du, dumpkmap,
dumpleases, echo, ed, egrep, eject, env, envdir, envuidgid, ether-wake, expand, expr, factor, fakeidentd, fallocate, false,
fatattr, fbset, fbsplash, fdflush, fdformat, fdisk, fgconsole, fgrep, find, findfs, flock, fold, free, freeramdisk, fsck,
fsck.minix, fsfreeze, fstrim, fsync, ftpd, ftpget, ftpput, fuser, getopt, getty, grep, groups, gunzip, gzip, halt, hd, hdparm,
head, hexdump, hexedit, hostid, hostname, httpd, hush, hwclock, i2cdetect, i2cdump, i2cget, i2cset, i2ctransfer, id, ifconfig,
ifdown, ifenslave, ifplugd, ifup, inetd, init, insmod, install, ionice, iostat, ip, ipaddr, ipcalc, ipcrm, ipcs, iplink, ipneigh,
iproute, iprule, iptunnel, kbd_mode, kill, killall, killall5, klogd, last, less, link, linux32, linux64, linuxrc, ln, loadfont,
loadkmap, logger, login, logname, logread, losetup, lpd, lpq, lpr, ls, lsattr, lsmod, lsof, lspci, lsscsi, lsusb, lzcat, lzma,
lzop, makedevs, makemime, man, md5sum, mdev, mesg, microcom, mim, mkdir, mkdosfs, mke2fs, mkfifo, mkfs.ext2, mkfs.minix, mkfs.vfat,
mknod, mkpasswd, mkswap, mktemp, modinfo, modprobe, more, mount, mountpoint, mpstat, mt, mv, nameif, nanddump, nandwrite,
nbd-client, nc, netstat, nice, nl, nmeter, nohup, nologin, nproc, nsenter, nslookup, ntpd, nuke, od, openvt, partprobe, passwd,
paste, patch, pgrep, pidof, ping, ping6, pipe_progress, pivot_root, pkill, pmap, popmaildir, poweroff, powertop, printenv, printf,
ps, pscan, pstree, pwd, pwdx, raidautorun, rdate, rdev, readahead, readlink, readprofile, realpath, reboot, reformime,
remove-shell, renice, reset, resize, resume, rev, rm, rmdir, rmmod, route, rpm, rpm2cpio, rtcwake, run-init, run-parts, runlevel,
runsv, runsvdir, rx, script, scriptreplay, sed, sendmail, seq, setarch, setconsole, setfattr, setfont, setkeycodes, setlogcons,
setpriv, setserial, setsid, setuidgid, sh, sha1sum, sha256sum, sha3sum, sha512sum, showkey, shred, shuf, slattach, sleep, smemcap,
softlimit, sort, split, ssl_client, start-stop-daemon, stat, strings, stty, su, sulogin, sum, sv, svc, svlogd, svok, swapoff,
swapon, switch_root, sync, sysctl, syslogd, tac, tail, tar, taskset, tc, tcpsvd, tee, telnet, telnetd, test, tftp, tftpd, time,
timeout, top, touch, tr, traceroute, traceroute6, true, truncate, ts, tty, ttysize, tunctl, ubiattach, ubidetach, ubimkvol,
ubirename, ubirmvol, ubirsvol, ubiupdatevol, udhcpc, udhcpc6, udhcpd, udpsvd, uevent, umount, uname, unexpand, uniq, unix2dos,
unlink, unlzma, unshare, unxz, unzip, uptime, users, usleep, uudecode, uuencode, vconfig, vi, vlock, volname, w, wall, watch,
watchdog, wc, wget, which, who, whoami, whois, xargs, xxd, xz, xzcat, yes, zcat, zcip
▶ Compiling: make -j 20
Resulting size: only 460,840 bytes! (could be
300,000 with fewer features)
Funny to see that we’re using a 64 bit system
to run such small programs!
▶ Installing in _install/: make install
▶ See the created directory structure and the
symbolic links to /bin/busybox
▶ Installing to the root filesystem:
- Kernel, drivers and embedded Linux - Development, consulting, training and support - https://bootlin.com 50/67
Completing the root filesystem (1)
We also need to create a dev directory for device files. The kernel will automatically mount the
devtmpfs filesystem there (as CONFIG_DEVTMPFS_MOUNT=y)
- Kernel, drivers and embedded Linux - Development, consulting, training and support - https://bootlin.com 51/67
Completing the root filesystem (2)
# ps
PID USER VSZ STAT COMMAND
ps: can't open '/proc': No such file or directory
We need to create /proc and /sys so that we can mount the proc and sysfs virtual
filesystems on the target, which are needed by many system commands. We can now
run the commands on the target system:
mkdir /proc
mkdir /sys
mount -t proc nodev /proc
mount -t sysfs nodev /sys
- Kernel, drivers and embedded Linux - Development, consulting, training and support - https://bootlin.com 52/67
Completing the root filesystem (3)
#!/bin/sh
mount -t proc nodev /proc
mount -t sysfs nodev /sys
- Kernel, drivers and embedded Linux - Development, consulting, training and support - https://bootlin.com 53/67
Common mistakes
▶ Don’t forget to make the rcS script executable. Linux won’t allow to execute it
otherwise.
▶ Do not forget #!/bin/sh at the beginning of shell scripts! Without the leading #!
characters, the Linux kernel has no way to know it is a shell script and will try to
execute it as a binary file!
▶ Don’t forget to specify the execution of a shell in /etc/inittab or at the end of
/etc/init.d/rcS. Otherwise, execution will just stop without letting you type
new commands!
- Kernel, drivers and embedded Linux - Development, consulting, training and support - https://bootlin.com 54/67
Add support for networking (1)
- Kernel, drivers and embedded Linux - Development, consulting, training and support - https://bootlin.com 55/67
Add support for networking (2)
ifconfig -a
ifconfig eth0 192.168.2.100
▶ On the host machine:
ifconfig -a
sudo ifconfig tap2 192.168.2.1
ping 192.168.2.100
- Kernel, drivers and embedded Linux - Development, consulting, training and support - https://bootlin.com 56/67
Simple CGI script
#!/bin/sh
echo "Content-type: text/html"
echo
echo "<html>"
echo "<meta http-equiv=\"refresh\" content=\"1\">"
echo "<header></header><body>"
echo "<h1>Uptime information</h1>"
echo "Your embedded device has been running for:<pre><font color=Blue>"
echo `uptime`
echo "</font></pre>"
echo "</body></html>"
- Kernel, drivers and embedded Linux - Development, consulting, training and support - https://bootlin.com 57/67
Start a web server
/usr/sbin/httpd -h /www
▶ On the host machine, open in your browser:
http://192.168.2.100/cgi-bin/uptime
- Kernel, drivers and embedded Linux - Development, consulting, training and support - https://bootlin.com 58/67
Demo: booting Linux on Milk-V Duo S board
- Kernel, drivers and embedded Linux - Development, consulting, training and support - https://bootlin.com 59/67
Connecting the Milk-V Duo S board
- Kernel, drivers and embedded Linux - Development, consulting, training and support - https://bootlin.com 60/67
SD card for the Milk-V Duo S board
cp arch/riscv/boot/Image /mnt/boot/
▶ Also copy a DTB from a very similar board:
cp arch/riscv/boot/dts/sophgo/cv1812h-huashan-pi.dtb /mnt/boot/
- Kernel, drivers and embedded Linux - Development, consulting, training and support - https://bootlin.com 61/67
Boot the Milk-V Duo S board
▶ Insert the micro-SD card, power the board, and in the U-Boot
prompt, type:
- Kernel, drivers and embedded Linux - Development, consulting, training and support - https://bootlin.com 62/67
Initramfs for RISC-V (1)
cd ~/riscv/rootfs
ln -s sbin/init .
▶ You also need to mount the devtmpfs filesystem manually by adding this line to
etc/init.d/rcS:
- Kernel, drivers and embedded Linux - Development, consulting, training and support - https://bootlin.com 63/67
Initramfs for RISC-V (2)
Image file on the boot partition. Please press Enter to activate this console.
~ #
- Kernel, drivers and embedded Linux - Development, consulting, training and support - https://bootlin.com 64/67
A few things to remember
- Kernel, drivers and embedded Linux - Development, consulting, training and support - https://bootlin.com 65/67
Going further and thanks
अब आप गु� ह�
▶ Drew Fustini’s unmatched presentation about Linux on
RISC-V: https://tinyurl.com/elc2023-bof
▶ Bootlin’s training materials and conference
presentations (Creative Commons CC-BY-SA licence):
https://bootlin.com/docs/
▶ Thanks to Drew Fustini for sharing his personal advice.
▶ Thanks to YOU for attending this talk!
- Kernel, drivers and embedded Linux - Development, consulting, training and support - https://bootlin.com 66/67
Questions? Suggestions? Comments?
Michael Opdenacker
michael.opdenacker@bootlin.com
- Kernel, drivers and embedded Linux - Development, consulting, training and support - https://bootlin.com 67/67