\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}

\newcommand{\codehack}[1]{{\usebeamercolor[fg]{code} {\tt #1}}}

\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{Getting started with RAUC}
\authors{Kamel Bouhara}
\email{kamel.bouhara@bootlin.com}
\slidesurl{https://bootlin.com/pub/conferences/2021/lee/bouhara-rauc}
\institute{Bootlin}
\conference{Live Embedded Event, June 3rd 2021}

\begin{document}

\addtocontents{toc}{\protect\setcounter{tocdepth}{-1}}
\section{Getting started with RAUC}
\addtocontents{toc}{\protect\setcounter{tocdepth}{2}}

\begin{frame}{Kamel Bouhara}
  \begin{itemize}
  \item Embedded Linux engineer at Bootlin
    \begin{itemize}
    \item Embedded Linux {\bf expertise}
    \item Bootloader, Linux kernel, Yocto Project, Buildroot
    \item Complete Linux BSP development
    \item Strong open-source focus: upstreaming and contributions
    \end{itemize}
  \item Significant experience in board bring up with NXP SoCs
  \item Small contributions to Yocto Project, Buildroot and Linux
  \item Living in {\bf Lyon}, France
  \end{itemize}
\end{frame}

\begin{frame}{About this talk}
  \begin{itemize}
  \item Brief introduction to RAUC
  \item Explore RAUC integration with Yocto/Buildroot, U-Boot/Barebox
  \item Share some insights and field experience
  \item Give some important keys to be ready to start with RAUC
  \end{itemize}
\end{frame}

\begin{frame}{What is RAUC ?}
\hspace{10cm}\includegraphics[width=2.5cm]{RAUC_Logo_300dpi.png}
 \begin{itemize}
 \item RAUC is an update system mechanism
 \item Developed by Pengutronix (Barebox, PTXDist)
 \item Licensed under LGPL-2.1
 \item \url{https://rauc.io/}
 \end{itemize}
\end{frame}

\begin{frame}{Non exhaustive list of RAUC features}
  \begin{itemize}
    \item Fail-safe and atomic
    \begin{itemize}
      \item Using symmetric or asymmetric update (redundant A/B scheme, rescue system)
      \item Update result is either valid or invalid (interrupt, corrupted bundle, device not compatible)
    \end{itemize}
   \item Security
   \begin{itemize}
     \item Using OpenSSL x.509 certificates
     \item Using an Hardware Secure Module with PKCS11 keys
   \end{itemize}
   \item Flexible and customizable update with bundle handlers
 \end{itemize}
\end{frame}

\begin{frame}{What's a RAUC bundle artifact ?}
  \begin{center}
    \includegraphics[height=0.8\textheight]{bundle.pdf}
  \end{center}
\end{frame}

\subsection{RAUC and Build systems}

\begin{frame}{Yocto integration}
  \begin{itemize}
  \item {\em meta-rauc} layer
    \begin{itemize}
      \item Mainly provide a generic {\em class} for bundle generation
      \item A fragment file \code{rauc.cfg} for the kernel squashfs support
      \item A basic example of bundle recipe \code{core-bundle-minimal.bb}
      \item The rauc package provide support for both sysVinit and systemd
      \item A script to generate development certificate with openssl
      \item Some useful packages: dt-utils, casync, rauc-hawkbit ...
      \item \url{https://github.com/rauc/meta-rauc}
     \end{itemize}
  \end{itemize}
\end{frame}

\begin{frame}[fragile]{Yocto integration}
  \begin{itemize}
  \item Add the \code{meta-rauc} layer to your \code{bblayers.conf}:
    \begin{block}{}
      \begin{minted}{console}
$ git clone https://github.com/rauc/meta-rauc.git
$ bitbake-layers add-layer meta-rauc
      \end{minted}
    \end{block}
  \item Create a recipe \code{rauc\_\%.bbappend} to install your own rauc configuration:
    \begin{block}{}
     \begin{minted}{c}
FILESEXTRAPATHS_prepend := "\${THISDIR}/files:"
SRC_URI_append := " file://system.conf"
      \end{minted}
    \end{block}
  \end{itemize}
\end{frame}

\begin{frame}[fragile]{Yocto integration}
  \begin{itemize}
    %% Why do we talk about initramfs here ?
    \item Setup a minimal rauc configuration through packageconfig:
    \begin{block}{}
	    \begin{minted}[fontsize=\small]{c}
PACKAGECONFIG_remove_pn-rauc = "service"
PACKAGECONFIG_remove_pn-rauc = "network"
PACKAGECONFIG_remove_pn-rauc = "gpt"
    \end{minted}
    \end{block}
    \item See {\em rauc.inc} for the exhaustive list of packageconfig
  \end{itemize}
\end{frame}

\begin{frame}[fragile]{A bundle recipe}
  \begin{itemize}
  \item Create your bundle recipe \code{demoboard-bundle.bb}
 \begin{block}{}
  \begin{minted}[fontsize=\small]{c}
inherit bundle

RAUC_BUNDLE_COMPATIBLE ?= "Demo Board"
RAUC_BUNDLE_SLOTS ?= "rootfs"
RAUC_SLOT_rootfs ?= "core-image-minimal"
RAUC_IMAGE_FSTYPE = "ubifs"

RAUC_KEY_FILE = "\${YOCTOROOT}/meta-demoboard/keys/dev.key.pem"
RAUC_CERT_FILE = "\${YOCTOROOT}/meta-demoboard/keys/dev.cert.pem"
  \end{minted}
  \end{block}
  \end{itemize}
  \begin{description}
  \item[RAUC\_BUNDLE\_COMPATIBLE] the target compatible
  \item[RAUC\_BUNDLE\_SLOTS] list of partitions to update
  \item[RAUC\_IMAGE\_FSTYPE] root filesystem (ubifs, squashfs, ext4, vfat, raw) %(eg. for NOR/NAND storage)
  \end{description}
\end{frame}

\begin{frame}[fragile]{Building and Using}
  \begin{itemize}
  \item Add the \code{rauc} package to your image
    \begin{block}{}
    \begin{minted}{c}
IMAGE_INSTALL_append = "rauc"
    \end{minted}
    \end{block}
  \item Generate your bundle image
    \begin{block}{}
    \begin{minted}{console}
$ bitbake demoboard-bundle
    \end{minted}
    \end{block}
  \item On the target, install the generated {\em *.raucb} using \code{rauc install} command
  \item Run \code{rauc status mark-good} to validate the boot on the new slot (shall be done by an initscript or systemd service)
  \end{itemize}
\end{frame}

\begin{frame}[fragile]{Using RAUC with Buildroot}
  \begin{itemize}
  \item Select \code{BR2_PACKAGE_RAUC=y}
  \item Options enabled as dependencies:
    \begin{block}{}
    \begin{minted}[fontsize=\small]{c}
select BR2_PACKAGE_SQUASHFS # run-time dependency
select BR2_PACKAGE_UBOOT_TOOLS if BR2_TARGET_UBOOT
select BR2_PACKAGE_UBOOT_TOOLS_FWPRINTENV if BR2_TARGET_UBOOT
    \end{minted}
    \end{block}
  \item To deploy rauc files on target use \code{BR2_ROOTFS_OVERLAY}
  \end{itemize}
    \begin{block}{}
    \begin{minted}{shell}
board/.../demoboard/rootfs-overlay/
└── etc
    ├── rauc
    │   ├── dev.cert.pem
    │   ├── dev.key.pem
    │   └── system.conf
    \end{minted}
    \end{block}
\end{frame}

\begin{frame}[fragile]{Using RAUC with Buildroot}
  \begin{itemize}
  \item Generate the bundle with a post image script using \code{BR2_ROOTFS_POST_IMAGE_SCRIPT}
  \end{itemize}
  \begin{block}{}
  \begin{minted}[fontsize=\scriptsize]{shell}
#!/bin/bash
...
cat >> ${BINARIES_DIR}/temp-dir/manifest.raucm << EOF
[update]
compatible=demo-board
version=${VERSION}
[image.rootfs]
filename=rootfs.ext4
EOF

${HOST_DIR}/bin/rauc --cert ${BOARD_DIR}/dev.cert.pem \
                        --key ${BOARD_DIR}/dev.key.pem \
                        bundle ${BINARIES_DIR}/temp-dir/ \
                        ${BINARIES_DIR}/bundle.raucb
  \end{minted}
  \end{block}
\end{frame}

\subsection{RAUC and Bootloaders}

\begin{frame}[fragile]{Barebox and RAUC: Pre-requisites}
Hardware pre-requisite:
  \begin{itemize}
  \item A non-volatile memory with \textasciitilde{}200 KBytes of dedicate space (not updated with Barebox)
  \end{itemize}

Software pre-requisite:
  \begin{itemize}
  \item Install {\bf dt-utils} on your filesystem from: \url{https://git.pengutronix.de/cgit/tools/dt-utils}
  \item If using EEPROM backend make sure you have the following kernel patch (nvem core) : \url{https://lkml.org/lkml/2020/4/6/445}
  \end{itemize}
\end{frame}


\begin{frame}[fragile]{Barebox and RAUC: In brief}
  \begin{itemize}
  \item Enable bootchooser and barebox state support:
    \begin{block}{}
    \begin{minted}[fontsize=\small]{c}
CONFIG_STATE_DRV=y
CONFIG_STATE=y
CONFIG_BOOTCHOOSER=y
CONFIG_CMD_STATE=y
CONFIG_CMD_BOOTCHOOSER=y
    \end{minted}
    \end{block}
  \item The {\bf Bootchooser} is the algorithm implemented in Barebox to provide a mean to work with abstract boot targets.
  \item The {\bf State} allows storing the set of variables required by RAUC
  \end{itemize}
\end{frame}

\begin{frame}[fragile]{Updating with Barebox}
 Example of A/B update scenario setup:
    \begin{block}{}
    \begin{minted}[fontsize=\scriptsize]{shell}
$ tree arch/arm/boards/demoboard/env/nv/ |grep boot
├── bootchooser.disable_on_zero_attempts
├── bootchooser.reset_attempts
├── bootchooser.reset_priorities
├── bootchooser.retry
├── bootchooser.state_prefix
├── bootchooser.system0.boot
├── bootchooser.system0.default_attempts
├── bootchooser.system0.default_priority
├── bootchooser.system1.boot
├── bootchooser.system1.default_attempts
├── bootchooser.system1.default_priority
├── bootchooser.targets
├── boot.default
...
    \end{minted}
    \end{block}
  \begin{itemize}
  \item Double check barebox dts and {\em state.prefix} above !
  \end{itemize}
\end{frame}

%  \item Require a bit of diving into barebox bootchooser and state framework documentation
%  \item Don't forget to fix bootchooser \code{global.bootchooser.state_prefix} variable or your update scenario will no work (boot status will not be stored persistently).
%  \item Make sure you have a backend device to store the state variables and that it will not be overwritten by software.
%  \item Both YP and BR provide the dt-utils package to interface with barebox state framework

\begin{frame}[fragile]{U-Boot and RAUC: Pre-requisites}
Hardware pre-requisites:
  \begin{itemize}
  \item A non-volatile memory with \textasciitilde{}200 KBytes of dedicate space (not updated with u-boot)
  \end{itemize}
Software pre-requisites:
  \begin{itemize}
  \item Install U-boot {\em fw-utils} on your filesystem, define u-boot environment offset in {\em /etc/fw\_env.config}
  \item Use \code{CONFIG_ENV_IS_IN_*} and/or \code{CONFIG_SYS_REDUNDAND_ENVIRONMENT=y} when updating u-boot % select a different storage place for the environment
  \end{itemize}
\end{frame}


\begin{frame}[fragile]{Updating with U-Boot}
  \begin{itemize}
  \item Example of boot script: \url{https://github.com/rauc/rauc/blob/master/contrib/uboot.sh}
  \item Mainly based on three variables:
    \begin{description}
    \item[BOOT\_ORDER] Which slot to boot first
    \item[BOOT\_*\_LEFT] Counters for boot attempts on A/B slots
    \end{description}
  \item On target, load and run the boot script:
  \begin{block}{}
	  \begin{minted}[fontsize=\scriptsize]{c}
setenv loadscript "fatload mmc ${mmcdev}:${mmcpart} ${loadaddr} ${script};"
run loadscript;
source ${loadaddr}:${script};
  \end{minted}
  \end{block}
  \end{itemize}
\end{frame}
%\item No need for specific device tree to hold boot status
%\item Requires to delevop your own u-boot script which can be difficult depending on the update scenario
%\item Fail-safe update needs u-boot environment to be stored in a specific partition, using \code{CONFIG\_SYS\_REDUNDAND\_ENVIRONMENT} may also be a solution
%\item Complexe scenario may also require changes in RAUC bootchooser code

\subsection{Basic update scenarios}

\begin{frame}[fragile]{Update with a rescue system or asymmetric update}
  \tiny
  \begin{block}{}
  \begin{minted}{c}
[system]
compatible=demo-board
bootloader=barebox

[keyring]
path=/etc/rauc/dev.cert.pem

[slot.rescue.0]
device=/dev/ubi0_0
type=raw
bootname=system0
readonly=true

[slot.rootfs.1]
device=/dev/ubi0_2
type=ubifs
bootname=system1
  \end{minted}
  \end{block}
  \normalsize
  \begin{itemize}
  \item Good solution for devices with minimal storage resource
  \item No fallback possible, require to define a backup plan when update failed
  \item Several reboots required to achieve the update
  \end{itemize}
\end{frame}

\begin{frame}[fragile]{Example of rauc usage from initramfs}
  % RAUC is executed from a small rescue system running on RAM
  \tiny
  \begin{block}{}
  \begin{minted}{c}
#!/bin/sh

PATH=/sbin:/bin:/usr/sbin:/usr/bin
USB=/mnt

# Sync clock on RTC
hwclock -s
# Attach ubi rootfs volume
ubiattach /dev/ubi_ctrl -m 2

...

# Install the new system image
rauc install "\${USB}/demoboard-bundle-demo-board.raucb"

# Change the active boot slot and reboot on the main system
rauc status mark-active rootfs.1

reboot -f

exit 0
  \end{minted}
  \end{block}
  \normalsize
  \begin{itemize}
  \item Make sure the system clock is correctly setup (use RTC/{\em hwclock -s} or NTP)
  \end{itemize}
  \tiny
    \begin{block}{}
    \begin{minted}{c}
  LastError: signature verification failed: Verify error:self signed
   certificate
   Installing `/media/demoboard-bundle-demo-board.raucb` failed
    \end{minted}
    \end{block}
\end{frame}

\begin{frame}[fragile]{Redundant A/B system update}
  \tiny
  \begin{block}{}
  \begin{minted}{c}
...
[slot.rootfs.0]
device=/dev/mmcblk1p1
type=ext4
bootname=A

[slot.rootfs.1]
device=/dev/mmcblk1p2
type=ext4
bootname=B

[slot.bootfs.0]
device=/dev/mmcblk1p3
type=ext4
parent=rootfs.0

[slot.bootfs.1]
device=/dev/mmcblk1p4
type=ext4
parent=rootfs.1
  \end{minted}
  \end{block}
  \normalsize
  \begin{itemize}
  \item Good solution for devices with large size storage
  \item Use the {\em parent} entry to bind all slots together in a single bundle update
  \item Depending on the application it can be a complex scenario, use post-install script handlers wisely
  \end{itemize}
\end{frame}

\subsection{Conclusion}

%before you get started with RAUC integration
\begin{frame}{What you need to know}
  \begin{itemize}
  \item Both Yocto or Buildroot fully support RAUC
  \item Well integrated in Barebox (developed by the same Pengutronix folks)
  \item With Barebox you don't need to directly deal with environment variables %to update your boot status (stored in a barebox device tree and available with dt-utils)
  \item U-Boot is good enough for a simple redundant A/B scenario
  \item More complex scenario need modification in rauc {\em bootchooser} code (\code{uboot_get_state}/\code{uboot_set_state})
  \item Make sure your device is well sized for your update strategy and application requirements  %but make sure to define your needs soon enough in your project (storage available, network bandwith, application interface with d-bus)
  \item New RAUC version 1.5 supporting the verity format for verified boot
  %\item There is also a good support for PTXDist integration
  \end{itemize}
\end{frame}

\questionslide

\end{document}
