yocto-kiss is an example of the simplest, but realistic and working,
Yocto/OpenEmbedded setup.
It aims at providing an example of how Yocto/OE can be used as the embedded Linux build system for end products without unnecessary complications.
While working for several Bootlin customers on their Yocto/OpenEmbedded setups we have seen many problems caused by unnecessary complications in their layers.
We have spent a lot of time in educating to writing clean layers, which often involved fixing problems by removing a lot of the code they had written or they had taken from existing third-party layers. In other words: making the code simple and "stupid", resulting in a more understandable, more efficient, easier to upgrade and less buggy build environment.
This repository is implementing a similar setup, aiming at being a reference for product companies in need to set up a Yocto/OpenEmbedded build environment or to clean up what they already have.
This repository is composed of:
- kas configuration files: modular configuration for different machines
meta-kiss: the layer with the (fictitious) distro configuration and common recipes for the products of a (fictitious) companymeta-kiss-ti: machine-specific layer for the dogbonedark boardmeta-kiss-st: machine-specific layer for the stompduck boardmeta-kiss-nxp: machine-specific layer for the freiheit93 boardmeta-kiss-amd: machine-specific layer for the krazymp board (scarthgap branch only)
The kas configuration files use the kas utility, which allows to easily download all the required third-party components in the correct place and enable them in the configuration. The configuration is split into modular files that can be combined to build for different machines. In this example it downloads and enables:
- the
bitbakebuild engine - the
openembedded-corerepository which contains themetalayer with all the "core" recipes - the
meta-armrepository which contains themeta-armandmeta-arm-toolchainlayers - the
meta-openembeddedrepository which contains themeta-oeandmeta-pythonlayers needed to build the FSBL of the krazymp board - the
meta-xilinxrepository which contains themeta-microblazelayer needed to build the PMUFW of the krazymp board - the
meta-kiss*layers, not downloaded as they are already part of this repository, but enabled inbuild/conf/bblayers.conf
Using kas is not mandatory to use Yocto/OpenEmbedded, but we found it simple and convenient. You can use another tool for your project if so you prefer.
The meta-kiss* layers demonstrate how a realistic layer structure for a
product company can (and, in our opinion, should) look like.
They are named after the KISS principle which "states that most systems work best if they are kept simple rather than made complicated" (source: Wikipedia).
Here we used "kiss" as the hypothetical name of a fictitious company. The
machine configurations in the meta-kiss machine layers implement fictitious
products, but except for their name they are actual development boards and
the output images can be used on these boards. In real world use cases
layers implementing company products can reasonably be called
meta-<company-name> and meta-<company-name>-<product-name>, with the
product names matching the actual product names.
The layer structure is organized as follows:
meta-kiss: the base distro layer providing:- a distro configuration (
kiss) - common recipes including kernel, U-Boot, a userspace application and an image recipe
- a distro configuration (
meta-kiss-ti,meta-kiss-st,meta-kiss-nxp,meta-kiss-amd: machine-specific layers, each providing:- a machine configuration file
- machine-specific recipe customizations (kernel defconfig, U-Boot config, etc.)
- WIC configuration for image creation
Note that the bitbake Yocto/OE build engine is powerful enough to handle
lots of machines, recipes and even multiple distros in a single layer. Thus
using a simple layer in your company is perfectly fine and encouraged.
However, when you have multiple products with significantly different
hardware architectures, splitting machine-specific content into separate
layers can improve organization and make it easier to maintain each product
independently, as demonstrated in this setup.
The meta-kiss machine-specific layers contain four machine configurations, called dogbonedark, stompduck, freiheit93 and krazymp.
The dogbonedark machine describes a fictitious product which in reality implements the BeagleBone® Black. In order to implement it we took the relevant content from the BeagleBone machine configuration found in the meta-ti-bsp layer.
We could of course have used the meta-ti-bsp layer directly, however since the hardware is very well supported by the mainline kernel and U-Boot we only needed to write (or copy and paste!) a small amount of code.
Several BSP layers provided by hardware vendors bring in extra complexity, deviation from standard coding practices and even bugs and unnecessarily complex code. In the spirit of this project, we chose to provide an example of how you can do without them in many cases.
The stompduck machine describes a fictitious product which in reality implements the STM32MP157A-DK1. For the same motivations, the minimum necessary code in this case was taken from the STM32MP1 machine configuration found in the meta-st-stm32mp layer.
In addition to the steps needed to implement the dogbonedark, for the
stompduck machine we additionally chose to boot it using
TrustedFirmware-A (TF-A).
In order to build TF-A, using the existing
recipe
from the meta-arm layer looked like a good choice given the balance between
the code quality of the meta-arm layer itself and the complexity required
for a recipe to build TF-A. So we added this layer to the kas configuration
file together with the meta-arm-toolchain layer it depends on.
The freiheit93 machine describes a fictitious product which in reality implements the FRDM i.MX93. Here the minimal necessary code was taken from meta-imx-frdm i.MX93 machine configuration and meta-freescale i.MX93 machine include. Additionally, firmware recipe was taken from meta-freescale boot firmwares.
As for the stompduck machine, we are relying on meta-arm to build the TF-A
firmware.
Here we also showcase the handling of proprietary licenses that have to be
accepted before building a component: the NXP firmwares require acceptance of
the NXP EULA, by adding NXP_EULA_v57 and NXP_EULA_v58 to the
LICENSE_FLAGS_ACCEPTED variable.
The krazymp machine describes a fictitious product which in reality implements the ZynqMP Kria KD240 Devres Starter kit. Here the minimal necessary code was taken from meta-xilinx soc-zynqmp configuration.
We use the meta-microblaze sublayer of meta-xilinx to build the appropriate
toolchain for the ZynqMP PMUFW. Similarly we need meta-python from
meta-openembedded to build the ZynqMP FSBL.
As for the stompduck machine, we are relying on meta-arm to build the TF-A
firmware.
Note: the meta-kiss-amd layer is quite complex due to the nature of how
ZynqMP devices boot. Its purpose is to demonstrate how a complex boot flow
can be implemented in a customized and straightforward way, without relying
on third-party tools too much.
Due to dependencies on meta-kiss-amd, this machine is only supported on the scarthgap branch so far.
The kas configuration files are modular: a base configuration (kas/kiss.yaml)
is combined with a machine-specific configuration to build for a specific
board. Here's how you can have a working image in a few steps:
# If you don't have kas yet (needed once only):
pip install kas
# Build for the dogbonedark board
kas build kas/kiss.yaml:kas/dogbonedark.yaml
# Or build for the stompduck board
kas build kas/kiss.yaml:kas/stompduck.yaml
# Or build for the freiheit93 board
# NXP licenses are accepted by default in kas/freiheit93.yaml but you should
# read them in meta-kiss-nxp/recipes-bsp/firmware-imx/files/ beforehand
kas build kas/kiss.yaml:kas/freiheit93.yaml
# Or build for the krazymp board
# sdtgen licenses are accepted by default in kas/freiheit93.yaml but you should
# read them beforehand
git checkout scarthgap
kas build kas/kiss.yaml:kas/krazymp.yaml
# Have dinner
# Find the output images here (replace dogbonedark with your machine):
ls -l build/tmp-glibc/deploy/images/dogbonedark/
# Flash the image (replace machine name, and use your uSD card device
# instead of XYZ!):
sudo bmaptool copy build/tmp-glibc/deploy/images/dogbonedark/kiss-image-dogbonedark.rootfs.wic /dev/XYZIf you prefer to use bitbake directly instead of kas build:
# First, use kas to checkout the required repositories:
kas checkout kas/kiss.yaml:kas/dogbonedark.yaml
# Then initialize the build environment:
. openembedded-core/oe-init-build-env
# Now you can use bitbake as usual:
bitbake kiss-image
# To switch machines, update conf/site.conf or your shell environment:
echo 'MACHINE = "stompduck"' >> conf/site.confThat's all! Have a look around the code to know about the implementation details. We wrote some explanatory comments here and there which should help you understand the reason of several choices we made.
We also added some explanations in the git commit messages when the changes being committed were possibly not obvious. Look at the git history to discover the various steps we took, for example how we created the new meta-kiss layer skeleton initially and the process we took to add and modify a kernel defconfig.
In the end we hope you like the advantages of this clean setup:
- uses Yocto wrynose and builds on modern distros without the need of a container -- which you can of course use when it makes sense to
- no manual cloning of layers: kas does it all for you
- no manual configuration, except of course for selecting a machine
- a little amount of code: organized cleanly across distro and machine-specific layers, documentation included, not including the kernel defconfigs
- and, most important, readable code -- at least we hope so!