# 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: ```bash 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: ```bash 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: ```bash 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: ```bash 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: ```bash 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: ```bash 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": ```bash 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/*: ```bash mkdir ../meta-tsg/conf/distro ``` and populate a file called *${DISTRO}.conf*, in this case *tsg.conf*: ```bash cat < ../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: ```bash 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: ```bash 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: ```bash 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: ```bash 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