\documentclass[aspectratio=169,obeyspaces,spaces,hyphens,dvipsnames]{beamer}
\usepackage[utf8]{inputenc}
\usepackage{lmodern}% http://ctan.org/pkg/lm
\usepackage{minted}
\usepackage{hyperref}
\usepackage{xcolor}
\usepackage{pgfplots}
\usepackage{tikz}
\usepackage[normalem]{ulem}

\mode<presentation>
\usetheme{Bootlin}

\def\signed #1{{\leavevmode\unskip\nobreak\hfil\penalty50\hskip2em
  \hbox{}\nobreak\hfil(#1)
  \parfillskip=0pt \finalhyphendemerits=0 \endgraf}}

\newsavebox\mybox
\newenvironment{aquote}[1]
  {\savebox\mybox{#1}\begin{quotation}}
  {\signed{\usebox\mybox}\end{quotation}}

\title{Embedded Linux from scratch in 40 minutes (on RiscV)}
\authors{Michael Opdenacker}
\email{michael.opdenacker@bootlin.com}
\slidesurl{https://bootlin.com/pub/conferences/}
\institute{Bootlin}
\conference{Capitole du Libre 2019}

\begin{document}

\addtocontents{toc}{\protect\setcounter{tocdepth}{-1}}
\section{Embedded Linux from scratch in 40 minutes (on RiscV)}
\addtocontents{toc}{\protect\setcounter{tocdepth}{2}}

\begin{frame}{Michael Opdenacker}
\begin{columns}
  \column{0.7\textwidth}
  \begin{itemize}
  \item Founder and Embedded Linux engineer at Bootlin:
    \begin{itemize}
    \item Embedded Linux {\bf expertise}
    \item {\bf Development}, consulting and training
    \item Focusing {\bf only on Free and Open Source Software}
    \item Has its biggest office in Colomiers, near {\bf Toulouse}
    \end{itemize}
  \item Free Software contributor:
    \begin{itemize}
      \item Current maintainer of the Elixir Cross Referencer, making it
            easier to study the sources of big C projects like the Linux kernel.
            See \url{https://elixir.bootlin.com}
      \item Co-author of Bootlin's freely available embedded Linux and
	    kernel training materials (\url{https://bootlin.com/docs/})
      \item Former maintainer of \href{https://www.gnu.org/software/gtypist/}{GNU Typist}
    \end{itemize}
  \end{itemize}
  \column{0.3\textwidth}
    \begin{center}
    \includegraphics[width=0.5\textwidth]{graphics/logo-cc.pdf}\\
    \vspace{1.0cm}
    \includegraphics[width=\textwidth]{graphics/elixir.pdf}
    \end{center}
\end{columns}
\end{frame}

\subsection{Introduction}

\begin{frame}{What I like in embedded Linux}
\begin{itemize}
  \item Linux is perfect for operating devices with a fixed set of
        features. Unlike on the desktop, Linux is almost in every existing
        system.
  \item Embedded Linux makes Linux easy to learn: just a few programs and
        libraries are sufficient. {\bf You can understand the usefulness of each
        file in your filesystem}.
  \item The Linux kernel is standalone: no complex dependencies against
	external software. The code is in C!
  \item Linux works with just a few MB of RAM and storage
  \item There's a new version of Linux every 2-3 months.
  \item Relatively small development community. You end up meeting lots
        of familiar faces at technical conferences (like the Embedded
	Linux Conference).
  \item Lots of opportunities (and funding available) for becoming a
        contributor (Linux kernel, bootloader, build systems...).
\end{itemize}
\end{frame}

\begin{frame}{Reviving an old presentation}
\begin{columns}
  \column{0.5\textwidth}
    \begin{itemize}
      \item First shown in 2005 at the Libre Software Meeting in Dijon, France.
      \item Showing a 2.6 Linux kernel booting on a QEMU emulated ARM board.
      \item One of our most downloaded presentations at that time.
    \end{itemize}
  \column{0.5\textwidth}
    \includegraphics[width=\textwidth]{graphics/old-elfs-presentation.png}
\end{columns}
\end{frame}

\begin{frame}{Things that changed since 2005}
\begin{columns}
  \column{0.5\textwidth}
  In the embedded environment
  \begin{itemize}
     \item The Maker movement
     \item Cheap development boards (500+ EUR \textrightarrow 50-100 EUR)
     \item The rise of Open Hardware (Arduino, Beaglebone Black...)
     \item {\em RiscV}: a new open-source hardware instruction set architecture
  \end{itemize}
  \column{0.5\textwidth}
  In the Linux kernel:
  \begin{itemize}
     \item Linux 2.6.x \textrightarrow 5.x
     \item \code{tar} \textrightarrow \code{git}
     \item Linux is now everywhere, no need to convince customers to use
	   it. It's even easier and easier to convince then to fund
	   contributions to the official version.
     \item {\em devtmpfs}: automatically creates device files
     \item ARM and other architectures: devices described by the {\em Device Tree} instead of C code
  \end{itemize}
  And many more!
\end{columns}
\end{frame}

\begin{frame}{RiscV: a new open-source Instruction Set Architecture (ISA)}
  \includegraphics[height=0.1\textheight]{graphics/RISC-V-logo.pdf}\\
  \begin{itemize}
     \item Created by the University of California Berkeley, in a world dominated by proprietary ISAs (ARM, x86)
     \item Exists in 32, 64 and 128 bit variants, from microcontrollers
	   to powerful server hardware.
     \item Anyone can use and extend it to create their own SoCs
	   and CPUs.
     \item This reduces costs and promotes reuse and collaboration
     \item Implementations can be proprietary. Many hardware vendors
	   have plans to include RiscV CPUs in their hardware (examples:
	   Western Digital, Nvidia)
     \item Free implementations are being created
  \end{itemize}
  See \url{https://en.wikipedia.org/wiki/RISC-V}
\end{frame}

\begin{frame}{How to use RiscV with Linux?}
  \begin{itemize}
  \item SiFive makes a low cost {\em HiFive1} Arduino Compatible board,
        but which cannot run Linux.
  \item SiFive also makes the {\em HiFive Unleashed} board, based on
        the first Linux capable multi-core RISC-V CPU, but it cost about
	1,000 USD!
  \item Before affordable hardware is available (in the next years), you
        can get started with the QEMU emulator, which simulates a
        virtual board with {\em virtio} hardware
  \end{itemize}
  Already try it with JSLinux: \url{https://bellard.org/jslinux/}
\end{frame}

\begin{frame}{Things to build today}
\begin{itemize}
  \item Hardware emulator: QEMU (provided by the distro)
  \item Cross-compiling toolchain: {\em Buildroot}
  \item Bootloader: {\em BBL Berkeley Boot Loader}
  \item Kernel: {\em Linux 5.4-rc7}
  \item Root filesystem and application: {\em BusyBox}
\end{itemize}
That's easy to compile and assemble in less than 40 minutes!
\end{frame}

\begin{frame}
  \frametitle{Embedded Linux - host and target}
  \begin{center}
    \includegraphics[width=0.9\textwidth]{graphics/host-and-target.pdf}
  \end{center}
\end{frame}

\subsection{Cross-compiling toolchain}

\begin{frame}
  \frametitle{What's a cross-compiling toolchain?}
  \begin{center}
    \includegraphics[width=0.8\textwidth]{graphics/cross-toolchain.pdf}
  \end{center}
\end{frame}

\begin{frame}
  \frametitle{Why generate your own cross-compiling toolchain?}
  Compared to ready-made toolchains:
  \begin{itemize}
    \item You can choose your compiler version
    \item You can choose your C library (glibc, uClibc, musl)
    \item You can tweak other features
    \item You gain reproducibility: if a bug is found, just apply a fix.\\
          Don't need to get another toolchain (different bugs)
  \end{itemize}
\end{frame}

\begin{frame}
  \frametitle{Choosing the C library}
  \begin{columns}
    \column{0.7\textwidth}
    \begin{itemize}
    \item The C library is an essential component of a Linux system
      \begin{itemize}
      \item Interface between the applications and the kernel
      \item Provides the well-known standard C API to ease application
        development
      \end{itemize}
    \item Several C libraries are available:
      \begin{itemize}
      \item {\em glibc}: full featured, but rather big (2 MB of ARM)
      \item {\em uClibc}: great for embedded use, the smallest
      \item {\em musl}: great for embedded use too, more recent
      \end{itemize}
    \item The choice of the C library must be made at
      cross-compiling toolchain generation time, as the GCC compiler is
      compiled against a specific C library.
    \end{itemize}
    \column{0.3\textwidth}
    \includegraphics[width=\textwidth]{graphics/Linux_kernel_System_Call_Interface_and_uClibc.pdf}\\
    {\tiny Source: Wikipedia (\url{http://bit.ly/2zrGve2})}
  \end{columns}
\end{frame}

\begin{frame}{Generating a RISC-V musl toolchain with Buildroot}
  \begin{columns}
    \column{0.7\textwidth}
    \begin{itemize}
      \item Download Buildroot from \url{https://buildroot.org}
      \item Extract the sources (\code{tar xf})
      \item Run \code{make menuconfig}
      \item In \code{Target options} \textrightarrow \code{Target
	    Architecture}, choose \code{RISCV}
      \item In \code{Toolchain} \textrightarrow \code{C library},
	    choose \code{musl}.
      \item Save your configuration and run:\\
	    \code{make sdk}
      \item At the end, you have an toolchain archive in
            \code{output/images/riscv64-buildroot-linux-musl_sdk-buildroot.tar.gz}
      \item Extract the archive in a suitable directory, and
	    in the extracted directory, run: \code{./relocate-sdk.sh}
    \end{itemize}
    \column{0.3\textwidth}
    \includegraphics[width=\textwidth]{asciinema/281267.png}\\
    \tiny \url{https://asciinema.org/a/281267}
  \end{columns}
\end{frame}

\begin{frame}[fragile]{Testing the toolchain}
\begin{itemize}
\item Create a new \code{riscv64-env.sh} file you can source to set
    environment variables for your project:
\begin{block}{}
\scriptsize
\begin{verbatim}
export PATH=$HOME/toolchain/riscv64-buildroot-linux-musl_sdk-buildroot/bin:$PATH
\end{verbatim}
\end{block}
\item Run \code{source riscv64-env.sh}, take a \code{hello.c} file and test your new compiler:
\begin{block}{}
\scriptsize
\begin{verbatim}
$ riscv64-linux-gcc -static -o hello hello.c
$ file hello
hello: ELF 64-bit LSB executable, UCB RISC-V, version 1 (SYSV), statically linked, not stripped
\end{verbatim}
\end{block}
     We are compiling statically so far to avoid having to deal with shared
     libraries.
\item Test your executable with QEMU in user mode:
\begin{block}{}
\begin{verbatim}
$ qemu-riscv64 hello
Hello world!
\end{verbatim}
\end{block}
\end{itemize}
\end{frame}

\subsection{Hardware emulator}

\begin{frame}[fragile]{Finding which machines are emulated by QEMU}
\begin{block}{}
\small
\begin{verbatim}
$ qemu-system-riscv64 -M ?
Supported machines are:
none                 empty machine
sifive_e             RISC-V Board compatible with SiFive E SDK
sifive_u             RISC-V Board compatible with SiFive U SDK
spike_v1.10          RISC-V Spike Board (Privileged ISA v1.10) (default)
spike_v1.9.1         RISC-V Spike Board (Privileged ISA v1.9.1)
virt                 RISC-V VirtIO Board (Privileged ISA v1.10)
\end{verbatim}
\end{block}
We are going to use the \code{virt} one, emulating VirtIO peripherals
(more efficient than emulating real hardware).
\end{frame}

\subsection{Linux kernel}

\begin{frame}
  \frametitle{Kernel building overview}
  \begin{center}
    \includegraphics[height=0.8\textheight]{graphics/kernel-building-overview.pdf}
  \end{center}
\end{frame}

\begin{frame}[fragile]
  \frametitle{Environment for kernel cross-compiling}
  Let's add two environment variables for kernel cross-compiling to our
  \code{riscv64-env.sh} file:
  \begin{block}{}
  \begin{verbatim}
export CROSS_COMPILE=riscv64-linux-
export ARCH=riscv
\end{verbatim}
  \end{block}{}
  \begin{itemize}
  \item \code{CROSS_COMPILE} is the cross-compiler prefix, as our
      cross-compiler is {\bf \tt{riscv64-linux-}}\code{gcc}.
  \item \code{ARCH} is the name of the subdirectory in \kdir{arch} corresponding
      to the target architecture.
  \end{itemize}
\end{frame}

\begin{frame}[fragile]
  \frametitle{Kernel configuration}
  \begin{itemize}
  \item Lets take the default Linux kernel configuration for RISCV:
    \begin{block}{}
    \small
    \begin{verbatim}
$ make help | grep defconfig
  defconfig       - New config with default from ARCH supplied defconfig
  savedefconfig   - Save current config as ./defconfig (minimal config)
  alldefconfig    - New config with all symbols set to default
  olddefconfig    - Same as oldconfig but sets new symbols to their
  rv32_defconfig           - Build for rv32
$ make defconfig
\end{verbatim}
    \end{block}{}
  \item Note: on ARM, you have one \code{defconfig} file per SoC family.
        RISC-V SoCs are too few for the moment.
  \item We can now further customize the configuration:
    \begin{block}{}
    \begin{verbatim}
make menuconfig
\end{verbatim}
    \end{block}{}
  \end{itemize}
\end{frame}

\begin{frame}[fragile]
  \frametitle{Compiling the kernel}
    \begin{block}{}
    \begin{verbatim}
make
\end{verbatim}
    \end{block}{}
    To compile faster, run multiple {\bf j}obs in parallel:
    \begin{block}{}
    \begin{verbatim}
make -j 8
\end{verbatim}
    \end{block}{}
    To {\bf re}compile faster (7x according to some
    benchmarks), run multiple {\bf j}obs in parallel:
    \begin{block}{}
    \begin{verbatim}
make -j 8 CC="ccache riscv64-linux-gcc"
\end{verbatim}
    \end{block}{}
    At the end, you have two files:\\
    \code{vmlinux}: raw kernel in ELF format\\
    \code{arch/riscv/boot/Image.gz}: compressed kernel
\end{frame}

\subsection{Bootloader}

\begin{frame}[fragile]
  \frametitle{BBL: Berkeley Boot Loader}
  \begin{itemize}
  \item To boot the Linux kernel on the QEMU RISC-V {\em virt} machine,
	one solution is to use BBL:
  \begin{block}{}
  \scriptsize
  \begin{verbatim}
git clone https://github.com/riscv/riscv-pk.git
cd riscv-pk
mkdir build && cd build
../configure --enable-logo --host=riscv64-linux-gnu --with-payload=$HOME/git/linux/vmlinux
\end{verbatim}
  \end{block}
  \item Now, each time you recompile your kernel, run:
  \begin{block}{}
  \begin{verbatim}
make
\end{verbatim}
  \end{block}{}
  This generates the \code{bbl} file which is a binary that QEMU can run\\
  (this doesn't work with the raw \code{vmlinux} binary).
  \end{itemize}
\end{frame}

\subsection{Booting the kernel}

\begin{frame}[fragile]
  \frametitle{Booting the kernel with QEMU}
  \begin{block}{}
  \begin{verbatim}
qemu-system-riscv64 \
  -nographic \
  -machine virt \
  -m 32M \
  -kernel riscv-pk/build/bbl \
  -append "console=ttyS0" \
\end{verbatim}
  \end{block}{}
  \begin{itemize}
    \item \code{-m}: amount of RAM in the emulated machine
    \item \code{-append}: kernel command line
  \end{itemize}
  The kernel starts to boot but eventually panics. We need a \em{root filesystem}!
  \begin{block}{}
  \tiny
  \begin{verbatim}
[    0.491433] ---[ end Kernel panic - not syncing: VFS: Unable to mount root fs on unknown-block(0,0) ]---
\end{verbatim}
  \end{block}{}
\end{frame}

\subsection{Building the root filesystem}

\begin{frame}[fragile]
  \frametitle{BusyBox - Most commands in one binary - about 10 years ago}
  \begin{spacing}{0}
    \tiny
    \code{[, [[, acpid, addgroup, adduser, adjtimex, ar, arp, arping, ash, awk, basename, beep, blkid, brctl, bunzip2, bzcat, bzip2, cal, cat, catv, chat, chattr, chgrp, chmod, chown, chpasswd, chpst, chroot, chrt, chvt, cksum, clear, cmp, comm, cp, cpio, crond, crontab, cryptpw, cut, date, dc, dd, deallocvt, delgroup, deluser, depmod, devmem, df, dhcprelay, diff, dirname, dmesg, dnsd, dnsdomainname, dos2unix, dpkg, du, dumpkmap, dumpleases, echo, ed, egrep, eject, env, envdir, envuidgid, expand, expr, fakeidentd, false, fbset, fbsplash, fdflush, fdformat, fdisk, fgrep, find, findfs, flash_lock, flash_unlock, fold, free, freeramdisk, fsck, fsck.minix, fsync, ftpd, ftpget, ftpput, fuser, getopt, getty, grep, gunzip, gzip, hd, hdparm, head, hexdump, hostid, hostname, httpd, hush, hwclock, id, ifconfig, ifdown, ifenslave, ifplugd, ifup, inetd, init, inotifyd, insmod, install, ionice, ip, ipaddr, ipcalc, ipcrm, ipcs, iplink, iproute, iprule, iptunnel, kbd_mode, kill, killall, killall5, klogd, last, length, less, linux32, linux64, linuxrc, ln, loadfont, loadkmap, logger, login, logname, logread, losetup, lpd, lpq, lpr, ls, lsattr, lsmod, lzmacat, lzop, lzopcat, makemime, man, md5sum, mdev, mesg, microcom, mkdir, mkdosfs, mkfifo, mkfs.minix, mkfs.vfat, mknod, mkpasswd, mkswap, mktemp, modprobe, more, mount, mountpoint, mt, mv, nameif, nc, netstat, nice, nmeter, nohup, nslookup, od, openvt, passwd, patch, pgrep, pidof, ping, ping6, pipe_progress, pivot_root, pkill, popmaildir, printenv, printf, ps, pscan, pwd, raidautorun, rdate, rdev, readlink, readprofile, realpath, reformime, renice, reset, resize, rm, rmdir, rmmod, route, rpm, rpm2cpio, rtcwake, run-parts, runlevel, runsv, runsvdir, rx, script, scriptreplay, sed, sendmail, seq, setarch, setconsole, setfont, setkeycodes, setlogcons, setsid, setuidgid, sh, sha1sum, sha256sum, sha512sum, showkey, slattach, sleep, softlimit, sort, split, start-stop-daemon, stat, strings, stty, su, sulogin, sum, sv, svlogd, swapoff, swapon, switch_root, sync, sysctl, syslogd, tac, tail, tar, taskset, tcpsvd, tee, telnet, telnetd, test, tftp, tftpd, time, timeout, top, touch, tr, traceroute, true, tty, ttysize, udhcpc, udhcpd, udpsvd, umount, uname, uncompress, unexpand, uniq, unix2dos, unlzma, unlzop, unzip, uptime, usleep, uudecode, uuencode, vconfig, vi, vlock, volname, watch, watchdog, wc, wget, which, who, whoami, xargs, yes, zcat, zcip}
  \end{spacing}
  \vfill
  Source: run \code{/bin/busybox}
\end{frame}

\begin{frame}[fragile]
  \frametitle{BusyBox - Most commands in one binary - In 2019}
  \begin{spacing}{0}
    \tiny
    \code{[, [[, acpid, add-shell, addgroup, adduser, adjtimex, ar, arch, arp, arping, awk, base64, basename, bbconfig, bc, beep, blkdiscard, blkid, blockdev, bootchartd, brctl, bunzip2, busybox, bzcat, bzip2, cal, cat, chat, chattr, chcon, 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, 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, flash_eraseall, flash_lock, flash_unlock, flashcp, flock, fold, free, freeramdisk, fsck, fsck.minix, fsfreeze, fstrim, fsync, ftpd, ftpget, ftpput, fuser, getenforce, getopt, getsebool, getty, grep, groups, gunzip, gzip, halt, hd, hdparm, head, hexdump, hexedit, hostid, hostname, httpd, hush, hwclock, 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, load_policy, loadfont, loadkmap, logger, login, logname, logread, losetup, lpd, lpq, lpr, ls, lsattr, lsmod, lsof, lspci, lsscsi, lsusb, lzcat, lzma, lzop, lzopcat, makedevs, makemime, man, matchpathcon, md5sum, mdev, mesg, microcom, minips, mkdir, mkdosfs, mke2fs, mkfifo, mkfs.ext2, mkfs.minix, mkfs.reiser, mkfs.vfat, mknod, mkpasswd, mkswap, mktemp, modinfo, modprobe, more, mount, mountpoint, mpstat, mt, mv, nameif, nanddump, nandwrite, nbd-client, nc, netcat, 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, printenv, printf, ps, pscan, pstree, pwd, pwdx, raidautorun, rdate, rdev, readahead, readlink, readprofile, realpath, reboot, reformime, remove-shell, renice, reset, resize, restorecon, resume, rev, rfkill, rm, rmdir, rmmod, route, rpm, rpm2cpio, rtcwake, run-init, run-parts, runcon, runlevel, runsv, runsvdir, rx, script, scriptreplay, sed, selinuxenabled, sendmail, seq, sestatus, setarch, setconsole, setenforce, setfattr, setfiles, setfont, setkeycodes, setlogcons, setpriv, setsebool, 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, tune2fs, ubiattach, ubidetach, ubimkvol, ubirename, ubirmvol, ubirsvol, ubiupdatevol, udhcpc, udhcpd, udpsvd, uevent, umount, uname, uncompress, unexpand, uniq, unit, unix2dos, unlink, unlzma, unlzop, 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}
  \end{spacing}
  \vfill
\end{frame}

\begin{frame}[fragile]
  \frametitle{BusyBox - Configuring}
  \begin{columns}
  \column{0.7\textwidth}
     \begin{itemize}
        \item Create a \code{rootfs} installation directory
	\item Download the sources from \url{https://busybox.net}
        \item Run \code{make allnoconfig}\\
	      Starts with no applet selected
	\item Run \code{make menuconfig}\\
	      \begin{itemize}
	      \item In \code{Settings} \textrightarrow \code{Build
	      Options}, enable \code{Build static binary (no shared libs)}
	      \item In \code{Settings} \textrightarrow \code{Build
	      Options}, set \code{Cross compiler prefix} to \code{riscv64-linux-}
	      \item In \code{Settings} \textrightarrow
              \code{Installation Options...}, set \code{Destination path for 'make
              install'} to the path of your \code{rootfs} directory.
	      \item Then enable support for the following commands:\\
		    \code{ash}, \code{init}, \code{mount}, \code{cat},
		    \code{mkdir}, \code{echo}, \code{uptime},
		    \code{ls}, \code{vi}, \code{halt}, \code{ifconfig}, \code{httpd}
	      \end{itemize}
     \end{itemize}
  \column{0.3\textwidth}
    \includegraphics[width=\textwidth]{asciinema/281501.png}\\
    \tiny \url{https://asciinema.org/a/281501}
  \end{columns}
\end{frame}

\begin{frame}
  \frametitle{BusyBox - Installing and compiling}
  \begin{columns}
  \column{0.6\textwidth}
  \begin{itemize}
     \item Compiling: \code{make} or \code{make -j 8} (faster)\\
	   Resulting size: 251624 bytes only!
     \item Installing: \code{make install}
     \item See the created directory structure and the symbolic links
	   to \code{/bin/busybox}
  \end{itemize}
  \column{0.4\textwidth}
    \includegraphics[width=\textwidth]{graphics/busybox-tree.png}\\
  \end{columns}
\end{frame}

\begin{frame}[fragile]
  \frametitle{Creating a root filesystem image}
  \begin{itemize}
    \item Creating an empty file with a 1M size:
    \begin{block}{}
    \begin{verbatim}
dd if=/dev/zero of=rootfs.img bs=1M count=1
\end{verbatim}
    \end{block}
    \item Formating this file for the ext2 filesystem:
    \begin{block}{}
    \begin{verbatim}
mkfs.ext2 rootfs.img
\end{verbatim}
    \end{block}
  \end{itemize}
\end{frame}

\begin{frame}[fragile]
  \frametitle{Populating the root filesystem}
  \begin{itemize}
    \item Create a mount point:
    \begin{block}{}
    \begin{verbatim}
sudo mkdir /mnt/rootfs
\end{verbatim}
    \end{block}
    \item Mounting the root filesystem image:
    \begin{block}{}
    \begin{verbatim}
sudo mount -o loop rootfs.img /mnt/rootfs
\end{verbatim}
    \end{block}
    \item Filling the BusyBox file structure:
    \begin{block}{}
    \begin{verbatim}
sudo rsync -a rootfs/ /mnt/rootfs/
\end{verbatim}
    \end{block}
    \item Flushing the changes into the mounted filesystem image:
    \begin{block}{}
    \begin{verbatim}
sync
\end{verbatim}
    \end{block}
  \end{itemize}
\end{frame}

\begin{frame}[fragile]
  \frametitle{Booting Linux with the root filesystem}
  \begin{itemize}
    \item Add a disk to the emulated machine:
    \begin{block}{}
    \begin{verbatim}
qemu-system-riscv64 -nographic -machine virt -m 32M \
    -kernel riscv-pk/build/bbl \
    -append "console=ttyS0 ro root=/dev/vda" \
    -drive file=root.img,format=raw,id=hd0 \
    -device virtio-blk-device,drive=hd0 \
\end{verbatim}
    \end{block}
    \item You should see the root filesystem is mounted:
    \begin{block}{}
    \scriptsize
\begin{verbatim}
[    0.630560] EXT4-fs (vda): mounting ext2 file system using the ext4 subsystem
[    0.659433] EXT4-fs (vda): mounted filesystem without journal. Opts: (null)
[    0.663114] VFS: Mounted root (ext2 filesystem) readonly on device 254:0.
\end{verbatim}
    \end{block}
  \end{itemize}
\end{frame}

\begin{frame}[fragile]
  \frametitle{Completing and configuring the root filesystem (1)}
  \begin{itemize}
  \item Create a \code{dev} directory.\\
        The \code{devtmpfs} filesystem will automatically be mounted there
        (as \code{CONFIG_DEVTMPFS_MOUNT=y})
  \item Let's try to mount the \code{proc} and \code{sysfs} filesystems:
    \begin{block}{}
\begin{verbatim}
mount -t proc nodev /proc
mount -t sysfs nodev /sys
\end{verbatim}
    \end{block}
  \end{itemize}
\end{frame}


\begin{frame}[fragile]
  \frametitle{Completing and configuring the root filesystem (1)}
  Let's automate the mounting of \code{proc} and \code{sysfs}...
  \begin{itemize}
  \item Let's create an \code{/etc/inittab} to configure Busybox Init:
    \begin{block}{}
\begin{verbatim}
# This is run first script:
:sysinit:/etc/init.d/rcS
# Start an "askfirst" shell on the console:
:askfirst:­/bin/sh
\end{verbatim}
    \end{block}
  \item Let's create and fill \code{/etc/init.d/rcS} to automatically
    mount the virtual filesystems:
    \begin{block}{}
\begin{verbatim}
#!/bin/sh
mount -t proc nodev /proc
mount -t sysfs nodev /sys
\end{verbatim}
    \end{block}
  \end{itemize}
\end{frame}

\begin{frame}[fragile]
  \frametitle{Common mistakes}
  \begin{itemize}
    \item Don't forget to make the \code{rcS} script executable. Linux
          won't allow to execute it otherwise.
    \item Do not forget \code{#!/bin/sh} at the beginning of shell scripts!
          Without the leading \code{#!} characters, the Linux kernel has no
          way to know it is a shell script and will try to execute it as
          a binary file!
    \item Don't forget to specify the execution of a shell in
          \code{/etc/inittab} or at the end of \code{/etc/init.d/rcS}.
          Otherwise, execution will just stop without letting you type new commands!
  \end{itemize}
\end{frame}

\begin{frame}[fragile]
  \frametitle{Add support for networking (1)}
  \begin{itemize}
    \item Add a network interface to the emulated machine:
    \begin{block}{}
\begin{verbatim}
sudo qemu-system-riscv64 -nographic -machine virt -m 32M \
    -kernel riscv-pk/build/bbl \
    -append "console=ttyS0 ro root=/dev/vda" \
    -drive file=root.img,format=raw,id=hd0 \
    -device virtio-blk-device,drive=hd0 \
    -netdev tap,id=tapnet,ifname=tap2,script=no,downscript=no \
    -device virtio-net-device,netdev=tapnet \
\end{verbatim}
    \end{block}
    \item Need to be \code{root} to bring up the \code{tap2} network
          interface
  \end{itemize}
\end{frame}

\begin{frame}[fragile]
  \frametitle{Add support for networking (2)}
  \begin{itemize}
    \item On the target machine:
    \begin{block}{}
\begin{verbatim}
ifconfig -a
ifconfig eth0 192.168.2.100
\end{verbatim}
    \end{block}
    \item On the host machine:
    \begin{block}{}
\begin{verbatim}
ifconfig -a
ifconfig tap2 192.168.2.1
ping 192.168.2.100
\end{verbatim}
    \end{block}
  \end{itemize}
\end{frame}

\begin{frame}[fragile]
  \frametitle{Simple CGI script}
    \begin{block}{}
    \small
\begin{verbatim}
#!/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>"
\end{verbatim}
    \end{block}
    Store it in \code{/www/cgi-bin/uptime}
\end{frame}

\begin{frame}[fragile]
  \frametitle{Start a web server}
  \begin{itemize}
    \item On the target machine:
    \begin{block}{}
\begin{verbatim}
/usr/sbin/httpd -h /www
\end{verbatim}
    \end{block}
    \item On the host machine, open in your browser:\\
          \url{http://192.168.2.100/cgi-bin/uptime}
  \end{itemize}
\end{frame}

\begin{frame}[fragile]
  \frametitle{What to remember}
  \begin{itemize}
    \item Embedded Linux is easy. It makes it easier to get started with Linux.
    \item You just need a toolchain, a kernel and a few executables.
    \item RISC-V is a new, open Instruction Set Architecture, support it!
    \item In embedded Linux, things don't change that much over time.
          You just get more features.
  \end{itemize}
\end{frame}

\begin{frame}[fragile]
  \frametitle{Going further}
  \begin{itemize}
    \item Our "Embedded Linux system development" training materials
(500+ pages, CC-BY-SA licence): \\
    \url{https://bootlin.com/doc/training/embedded-linux/}
    \item All our training materials and conference presentations:\\
    \url{https://bootlin.com/docs/}
    \item The Embedded Linux Wiki: presentations, howtos... contribute to it!\\
    \url{https://elinux.org}
  \end{itemize}
\end{frame}

\begin{frame}[fragile]
\begin{columns}
  \column{0.5\textwidth}
   \centering
    \Huge
    Questions? Suggestions? Comments?\\
    \vspace{1.5cm}
    \huge
    Michael Opdenacker\\
    \large
    {\em \insertemail}\\
    \vspace{0.5cm}
    Slides under CC-BY-SA 3.0\\
    \scriptsize
    \url{\insertslidesurl}
  \column{0.5\textwidth}
  Check out our {\bf jobs in Toulouse}:\\
  {\footnotesize \url{https://bootlin.com/company/careers/}}\\
  \vspace{0.5cm}
  Check out Bootlin {\bf internship topics}:
  \begin{itemize}
     \item Video encoding on Allwinner VPU in the Linux kernel
     \item Linux kernel driver for the MIPI CSI-2 controller in Allwinner SoCs
     \item Improve TPM v2.0 support in U-Boot
     \item Support the SquashFS filesystem in U-Boot
     \item Implementing new features in the Elixir Cross Referencer
  \end{itemize}
  \footnotesize \url{https://bootlin.com/blog/2020-internships/}\\
  \hfill \includegraphics[width=0.2\textwidth]{graphics/penguins-at-work.png}
\end{columns}
\end{frame}

\end{document}
