Image of an arrow

Accélérer le démarrage précoce de Linux avec Yocto multiconfig

Avatar

scuny

Accélérer le démarrage précoce de Linux avec Yocto multiconfig

De Paul Le Guen de Kerneizon

Introduction

Dans les produits embarqués, il est souvent essentiel de gagner quelques secondes, voire quelques centaines de millisecondes, entre la mise sous tension et la disponibilité de l’application. Dans cet article, je vais présenter un workflow pratique pour mesurer, comparer et réduire de manière itérative la fenêtre de démarrage précoce d’un système Linux embarqué, en se limitant au noyau et à la partie initramFS. Nous utiliserons le projet Yocto, et en particulier la fonctionnalité multiconfig de BitBake.

 [L’introduction est en français, le reste du texte en anglais]

Setting the context

Nowadays, modern embedded system boot sequence share the same boot-up sequence:

    • The board firmware looks for any bootable device (USB key, hard drive, etc), and loads a valid Linux bootloader.
    • The Linux bootloader is configured to load a Linux kernel image, with custom arguments.
    • Finally, the Linux kernel boots and set up the rootfs.

 

For this article, I will consider a very simple Linux BSP architecture, using separated initramfs and rootfs images. This kind of layout is interesting to implement security features such as Secure Boot (rootfs authentication before load) and various others (file system check, A/B updates, etc). It applies to any kind of modern architecture (x86, ARM), excluding specific vendor boot sequence.

Our target BSP is composed of the following Yocto images:

    • lab-image-initramfs: this image contains the initramfs root file system, that will be responsible of the Linux first stage boot, including the load of the final rootfs. It is a very simple image, based on the core-image-minimal-initramfs image.
    • lab-image-rootfs: this image contains the final rootfs, packaged in a read-only file format such as ext4 or squashFS.
    • lab-image: this image packages the previous images into a single image, with an embedded Linux bootloader.

InitramFS optimization

As we saw previously, the initramfs image is loaded by the Linux bootloader. In embedded systems, I/O with devices such as disks are slow, and one of the most time consuming element is the initramfs image loading by the bootloader. So, reducing the size of this image will help to reduce it loading time, and so, the global system boot-time.

Initial measurements

We need to establish first what weight the most in the generated initramfs image. To do so, we are going to use the Bitbake buildhistory feature allowing to give some metrics about the contents of our generated image. It can be enabled by adding these lines in your distro file:

After building initramfs image, buildhistory has been generated:

We are interested in by the installed-package-sizes.txt file. It contains the size of each installed package in the initramfs image, sorted by weight:

Using an awk command we can get the total size of our initramfs image:

Here, the size of our image is about 39MiB.
To measure the boot-time on the target we highly recommend, if possible, to get the boot serial output and use the minicom timestamp feature.

 

List of Initramfs optimizations

On a first glance, we could interpret that there are not that much to optimize in our initramfs image, specially because it is already well minimized by the core-image-minimal-initramfs image. But some optimization can be implemented that can make the difference:

    • Changing the default C library from glib to musl library.
    • Changing the default initmanager from sysvinit to busybox-mdev.
    • Removing any additional unused packages.

Introducing Bitbake multiconfig feature

By default, a single Bitbake command can only build an image with a single configuration (distro, machine). Since the Langdale release of the Yocto Project, the multiconfig feature allows to easily apply different configuration within a single distro, for multiple images.
In our case, we would like to use the musl library and eudev init manager only for the lab-image-initramfs image, and not the rootfs image.

Setup a basic multiconfig

First, you need to add a new folder named “multiconfig” in the “conf” directory of your layer. In this folder, add a new file with the name of your multiconfig, in our example “mclabinitramfs”.

 

Now in your distro file (here lab.conf), add the following line:

We now have a basic multiconfig implementation, which currently does nothing.

Link the multiconfig to the initramfs

The usecase of the multiconfig here is to apply specific configuration boundared only to the lab-image-initramfs image. So we need to tell to Bitbake this dependency. To do so, add the following lines in your distro file (here lab.conf):

These lines specify two things:

    • INITRAMFS: the name of the initramfs used.
    • INITRAMFS_MULTICONFIG: tells to Bitbake that the kernel must be bundled with an initramfs image using a specific multiconfig and not the default one.
    • INITRAMFS_DEPLOY_DIR_IMAGE: the location where all the initramfs artifacts (images, etc) should be deployed.

Optimization

Use musl libray

musl is a C library for the Linux kernel. The main advantage of the musl library is that packages compiled with it are much lighter compared to packages build with glibc. However not all packages are compatible with musl library, especially for systemd, where musl support is still experimental. This is why I don’t recommend to use for all the images, in particular the rootfs image.

Back to our multiconfig, musl library can be enabled using the TCLIBC variable, set in the sources/meta-lab-distro/conf/multiconfig/mclabinitramfs.conf file:

Use a lighter init manager

By default, Bitbake uses sysvinit as the default initialization manager. It is great, but it can be easily improved by using mdev-busybox which is lighter compared to sysvinit. To use it, simply add these lines in the sources/meta-lab-distro/conf/multiconfig/mclabinitramfs.conf file:

Additional optimizations

To reduce further the size of the initramfs image, additional optimizations can be implemented, but are less applicable:

    • Use sh instead of bash as command interpreter, as sh is lighter compared to bash. Initramfs scripts are written using sh syntax, but keep in mind that you might need to convert your own script to the sh syntax if needed.
    • Kernel configuration minimization (unneeded file systems, etc)

Final results

With these optimizations, if we compute the size of the initramfs image, we get now a size of 29MiB, and so a reduction of 25%!
Now regarding the real result on target, it will also depends of the hardware used (CPU, disk type, etc). On our internal tests, on an ARM target we achieved to get 1.2s of boot-time reduction during initramfs image loading.

Laisser un commentaire

Votre adresse courriel ne sera pas publiée. Les champs obligatoires sont indiqués avec *

Ce site utilise Akismet pour réduire le pourriel. En savoir plus sur comment les données de vos commentaires sont utilisées.


Articles similaires

Image of an arrow
Object detection

Déployer un réseau de neurones artificiels convolutionnels sur un système embarqué Introduction L’essor des plateformes embarquées capables de traitement IA a profondément changé la donne : il est désormais possible de déployer des solutions intelligentes sur l’équipement lui-même, sans dépendre du cloud. C’est ce qu’on appelle l’« edge AI ». Lors d’un récent projet, nous […]

Le débogage de microcontrôleurs (MCU) a toujours été essentiel pour produire du code de haute qualité, mais la dépendance aux environnements de développement spécifiques aux fabricants et aux configurations complexes des serveurs de débogage peut parfois nuire à un flux de travail fluide. Bien que VSCode ait révolutionné la façon dont les développeurs écrivent et […]

  Permettre à l’industrie des systèmes embarqués de se conformer aux cyber-réglementations grâce à un outil de gestion des vulnérabilités innovant et open source.   Nuremberg, le 11 mars 2025 – Savoir-faire Linux, société de conseil et d’ingénierie en logiciels libres et Open Source est fière d’annoncer la sortie officielle de VulnScout.io, une solution Open Source […]

Savoir-faire Linux est ravi d’annoncer DHTNet, une nouvelle bibliothèque en C++17 issue du projet Jami, conçue pour simplifier la connectivité pair-à-pair (P2P). DHTNet permet aux développeurs d’établir des connexions P2P sécurisées entre des appareils en utilisant uniquement des clés publiques, éliminant le besoin d’une infrastructure centralisée ou d’un adressage IP direct. [L’introduction est en français, […]

Savoir-faire Linux est fière d’annoncer la sortie de la version v2.8.0 de l’extension officielle du Projet Yocto pour VS Code. Lisez l’article complet en anglais. Liens et ressources Pour en savoir plus sur cette ambitieuse extension du Projet Yocto pour VS Code : Téléchargez l’extension depuis le magasin VS Code Parcourez le code, signalez des […]