Building an own Layer in Yocto

When wanting to build on top of an existing BSP or your own distro, it is necessary to create an own Yocto meta-layer.

Technical requirements:

  • Yocto 3.1 (Dunfell) LTS

  • Linux-based host system with at least 60GB available Disk space

  • A microSD reader and card

  • A RaspberryPi 4 and its power supply (5V 3A USB-C)

  • An Ethernet cable and port, thus also a WiFi router

  • Another device with Bluetooth

Building your own distro

The first step that has to be done is cloning the Yocto git repo and checking out to the dunfell branch:

git clone -b dunfell https://git.yoctoproject.org/poky/

In this case, we are using the Poky Build Tool and Metadata.

Also, we need the meta-layers for rpi4 development and the openembedded meta- layer, version dunfell:

git clone -b dunfell git://git.openembedded.org/meta-openembedded
git clone -b dunfell git://git.yoctoproject.org/meta-raspberrypi

After that is done, we need to source tje oe-init-build-env to create our own build environment:

source poky/oe-init-build-env build-rpi

Some packages are still needed for these operations. Yocto will inform you thusly. In my case they were:

  • lz4

  • chrpath

After this, we are now in the build directory called build_rpi. Now it is to add the layers:

bitbake-layers add-layer ../meta-openembedded/meta-oe
bitbake-layers add-layer ../meta-openembedded/meta-python
bitbake-layers add-layer ../meta-openembedded/meta-networking
bitbake-layers add-layer ../meta-openembedded/meta-multimedia
bitbake-layers add-layer ../meta-raspberrypi

Then Verify everything worked:

bitbake-layers show-layers

To setup the correct machine, we need to set the MACHINE” variable to our build target, the raspberrypi4 with 64-bit. Therefore we edit the conf/local.conf file in the build-rpi directory we are currently in to contain the line

MACHINE = "raspberrypi4-64"

to override the default value (being assigned with the “??” operator).

Since we also want the openssh server running, we can add the feature ssh-server-openssh to the EXTRA_IMAGE_FEATURES list:

EXTRA_IMAGE_FEATURES ?= "debug-tweaks ssh-server-openssh"

If we only wanted to have an rpi image, that supports ssh, we could build the image now and be done, but since we want our own stuff to be happening, the journey continues down the road. The build command would be:

bitbake rpi-test-image

This command calls BitBake to build the image described by the recipes stored in the previously added meta-raspberrypi layer at meta-raspberrypi/recipes-core/images/rpi-test-image.bb.

Setting up the new Distro Layer

This is actually a fairly easy process, since Yocto has plenty of functionality built in to create layers. Here, we are using for example purposes the layer meta-tsg. This name just has to aligne with the distro that is being deployed, in this example the distro is called “TSG”:

bitbake-layers create-layer ../meta-tsg
bitbake-layers add-layer ../meta-tsg

Now, there is a meta-tsg folder next to you build-rpi directory, filled with all the (yet unconfigured) files, that belong into a meta-layer. To create the distro, we need a distro/ directory unter conf/:

mkdir ../meta-tsg/conf/distro

and populate a file called ${DISTRO}.conf, in this case tsg.conf:

cat <<EOF > ../meta-tsg/conf/distro/tsg.conf
DISTRO_NAME = "TSG (TSG Embedded Linux Distro)"
DISTRO_VERSION = "0.1"
EOF

alternatively, this config file can be extended by DISTRO_FEATURES: Add software support for these features. DISTRO_EXTRA_RDEPENDS: Add these packages to all images. DISTRO_EXTRA_RRECOMMENDS: Add these packages if they exist. TCLIBC: Select this version of the C standard library.

Now it is time to populate the conf/distro directory. This can be achieved by just looking up how e.g. Poky did it and repeat the pattern. For starting, copying the poky/meta/conf/distro/defaultsetup.conf file should be a fair beginning. Breaking the distro configuration file up into multiple ones, there is the conf/distro/include directory, for include files (.inc).

Adding Recipes

Since creating an own distro has a specific purpose (most of the time), this purpose has to be fulfilled. Adding recipes to the layer and populating it further, one will probably get thinking about whether there is a way to recycle recipes that already exist and adding own functionality. This can be achieved by using append files (.bbappend). The file name shall be the same as the source file, but with the .bbappend suffix instead of .bb. BBAppend files are read by BitBake, as if they were part of the original file.

Adding a Package Manager

The package manager is one of the things that makes a Linux distro a Linux distro. Yocto has builtin compatibility to rpm, ipk, dnf and opkg. The package format determines, which package manager is going to be used. To set a package format, the conf/distro/tsg.conf file will be used again:

PACKAGE_CLASSES ?= "package_ipk"

But before building just now, the conf/local.conf file has to be edited to remove the old package format that is currently set:

#PACKAGE_CLASSES ?= "package_rpm"

then add package-management to the list of EXTRA_IMAGE_FEATURES:

EXTRA_IMAGE_FEATURES ?= "debug-tweaks ssh-server-openssh package-management"

and lastly set the DISTRO variable in conf/local.conf to tsg:

DISTRO = "tsg"

After everything is set, we can build the image:

bitbake rpi-test-image

Where is my Image?

Everything valuable to the user that the system outputs, is being deployed in tmp-glibc/deploy/. From there, under images/ there will be the image archive:

ls tmp-glibc/deploy/images/raspberrypi4-64/rpi-test-image*wic.bz2

Commissioning

The image can be flashed onto a microSD card via the dd command. First, plugin the microSD card into the microSD card reader, find out which device it is (lsblk) and flash the image with:

sudo dd if=${PATH_TO_IMAGE} of=${DEVICE_FILE} bs=4M conv=fsync

for example, if the image is at tmp-glibc/deploy/images/raspberrypi4-64/rpi-test-image.wic.bz2, the device is /dev/sda, the command would be:

sudo dd \
    if=tmp-glibc/deploy/images/raspberrypi4-64/rpi-test-image.wic.bz2 \
    of=/dev/sda \
    bs=4M \
    conv=fsync

Note

Be very careful when using the dd command, since it can damage and even destroy your drive, if the wrong device file is selected! To avoid stuff like this, it is also commonly practiced to use tools, such as the rpi-imager or etcher, to get rid of command line flashing.

source: Mastering Embedded Linux Programming - Third Edition By Frank Vasquez, Chris Simmonds