# How to add a kernel configuration setting in the Yocto Project

**URL:** <https://hub.mender.io/t/how-to-add-a-kernel-configuration-setting-in-the-yocto-project/7723>\
**Category:** Yocto Project\
**Tags:** yocto, kernel\
**Created:** [April 15, 2025, 7:35pm UTC](https://hub.mender.io/t/how-to-add-a-kernel-configuration-setting-in-the-yocto-project/7723 "2025-04-15T19:35:24Z")\
**Posts on this page:** 1\
**Page:** 1

<div class="post-metadata">

**Author:** ![TheYoctoJester](https://yyz2.discourse-cdn.com/flex036/user_avatar/hub.mender.io/theyoctojester/32/1444_2.png) [@TheYoctoJester](https://hub.mender.io/u/TheYoctoJester)\
**Post date:** [April 15, 2025, 7:35pm UTC](https://hub.mender.io/t/how-to-add-a-kernel-configuration-setting-in-the-yocto-project/7723/1 "2025-04-15T19:35:24Z")

</div>

This is Part 3 of a series on using an I2C-bus connected EEPROM with the BeagleBone Black and Yocto. The other parts are:

- Part 1: [Connecting an AT24-style EEPROM to a BeagleBone Black](https://hub.mender.io/t/connecting-an-at24-style-eeprom-to-a-beaglebone-black/7741)
- Part 2: [Create a (Linux kernel) patch in Yocto](https://hub.mender.io/t/create-a-linux-kernel-patch-in-yocto/7732)

* * *

## Introduction

In many cases you need to enable a particular feature in the Linux kernel which is not active by default, such as a specialized device driver. A very common scenario are peripherals on an interface such as SPI or I2C that are present on custom baseboards.

This tutorial provides a walkthrough to add a configuration item to the kernel config and package the result up properly in a Yocto build.

It uses I2C-bus connected AT24-style EEPROMs as an example.

 ![LF_17_02_Yocto-Badge-Update_Participant_Final](https://canada1.discourse-cdn.com/flex036/uploads/mender/original/1X/758c60e0e8309c4dc2519392b78668e7396c15bd.png)

## Version notes

This tutorial uses **scarthgap** as the primary target, which is the current LTS release by the Yocto Project. You can find more infomation on releases [here](https://wiki.yoctoproject.org/wiki/Releases). Supported releases for following the tutorial are:

| Yocto Project | Tutorial applies | Maintenance |
| --- | --- | --- |
| walnascar (5.0) | :test_works: | :test_works: development |
| styhead (5.0) | :test_works: | :test_works: current stable |
| scarthgap (5.0) | :test_works: | :test_works: LTS |
| nanbield (4.3) | :test_works: | :test_works: EOL |
| mickledore (4.2) | :test_works: | :test_fails: EOL |
| langdale (4.1) | :test_works: | :test_fails: EOL |
| kirkstone (4.0) | :test_works: | :test_works: LTS |

**Please note:** a failure in the “tutorial applies” column indicates that the instructions do not work without modification. Depending on the combination of release and host Linux distribution, installing other python versions or dependencies might provide a functional state.

## Step 0: prepare a meta layer

We will need a meta layer to place our resulting recipe and files in. The rest of this tutorial assumes such a layer is prepared and added to the build already. We will use the name `meta-dawg`, and presume that the layer is present at the directory one level up from the `build` directory.

Example layout, top level:

```bash
.
├── build
├── meta-dawg
└── poky

```

Also, we expect the shell to be initialized for the build, and the current working directory to be `build`.

If this does not reflect your setup, please change the paths and name accordingly.

## Step 1: configure the Linux kernel

We need the kernel configuration baseline to add our customizations on top. There’s no need to do a full kernel build which might be time consuming, just invoking the `kernel_configme` task is enough:

```bash
bitbake -c kernel_configme virtual/kernel

```

With this configuration as it is provided by the current build setup, we start the `menuconfig` tool so we can interactively modify the kernel config as desired.

```bash
bitbake -c menuconfig virtual/kernel

```

Now we need to find the driver we want to add. In our case, it is the driver for “24C”-style EEPROMs. How do we find out which one it is? Kconfig has a search function.  
Type the `/` character. Then enter the (sub)string “at24”. Bingo! Here it is.

 ![Screenshot 2025-04-15 at 09.24.30](https://canada1.discourse-cdn.com/flex036/uploads/mender/original/2X/e/e1141c9fdec0971e3fdca7e5594a878b5283407f.png)

The important part now is to remember the location. Suprisingly - and also confusingly - it is at `Device Drivers -> Misc devices -> EEPROM -> I2C EEPROMs / RAMs / ROMs ...`.

Close the search results view by pressing `Enter` on the auto-selected `Exit` button. Then head to the location you just memorized by using the up/down arrows and Enter keys. Once you have arrived at the destination item, you can use the spacebar to trigger the `Select` function. By pressing it multiple times, it will cycle through these three variants for the selected functionality.

- `< >`: disabled and will not be compiled.
- `<M>`: enabled and compiled as a loadable module.
- `<*>`: enabled and compiled as a built-in module.

Unless the part you are working on is essential for booting the machine - which in our case, it isn’t - going for `M` is a sensible choice. Having as much as possible factored out into runtime loadable modules means that the kernel gets smaller and has less initializations to go through at boot time, which results in a shortened start up time.

Once you are finished with adjusting, save the kernel configuration by moving with the arrow keys to the `Save` item, select and confirm the `.config` destination with ´Enter`. Then close the configuration tool using the `Exit` item.

## Step 2: extract the configuration fragment

Yocto has a very powerful mechanism to extend a more generic kernel configuration with smaller additions, which it calls “fragments”. This allows for easier maintenance as it is not required to always re-configure the kernel and manage the resulting full configuration upon a new kernel release, but only keep the few modified additional lines under version control.

Extract the fragment which corresponds to our newly enabled driver:

```bash
bitbake -c diffconfig virtual/kernel

```

This command creates a configuration fragment based on our modifications, and tells us where to find it:

```bash
# example output
Config fragment has been dumped into:
 /home/mender/builds/bbb/build/tmp/work/beaglebone_yocto-poky-linux-gnueabi/linux-yocto/6.6.21+git/fragment.cfg

```

We can verify if the fragment reflects our intended change by looking at the file, like

```bash
cat /home/mender/builds/bbb/build/tmp/work/beaglebone_yocto-poky-linux-gnueabi/linux-yocto/6.6.21+git/fragment.cfg

```

and yes, it is exactly our wanted EEPROM driver:

```bash
CONFIG_EEPROM_AT24=m

```

## Step 3: create a recipe

The canonical organization for such recipes to extend the kernel configureion in Yocto is `$LAYER/recipes-kernel/linux/$RECIPE.bbapend`. We want to append to the kernel recipe which is already active, so lets look again at the path at which the configuration fragment was placed. It refers to version `6.6.21+git`, and one directory up it tells us the recipes name: `linux-yocto`.

So lets create the directory structure:

```bash
mkdir -p ../meta-dawg/recipes-kernel/linux

```

The best practice to place additional files is a directory next to the recipe in question, named like the `BPN` (short for Base Package Name) of the recipe. Create that one too:

```bash
mkdir -p ../meta-dawg/recipes-kernel/linux/linux-yocto

```

So lets move the configuration fragment into place and choose a somewhat meaningful name:

```bash
mv tmp/work/beaglebone_yocto-poky-linux-gnueabi/linux-yocto/6.6.21+git/fragment.cfg ../meta-dawg/recipes-kernel/linux/linux-yocto/at24.cfg

```

The last thing we need to glue everything together finally is the recipe itself. As we’re sticking to the canonical best practices, it is surprisingly short and simple.

```bash
cat << 'EOF' > ../meta-dawg/recipes-kernel/linux/linux-yocto_%.bbappend
FILESEXTRAPATHS:prepend := "${THISDIR}/${BPN}:"
SRC_URI += "file://at24.cfg"
EOF

```

Note that we named the recipe `linux-yocto_%.bbappend`which uses the `%` version wildcard. This means it will apply to all versions of the recipe being built.

In a production setting you might want to tie this to a specific version or `COMPATIBLE_MACHINE`.

Thats it, we’re done! Lets do some checks:

```bash
bitbake-layers show-appends | grep linux-yocto

```

includes a line with `meta-dawg/recipes-kernel/linux/linux-yocto_%.bbappend`, so our `.bbappend` is functional.

```bash
bitbake -c kernel_configcheck -f virtual/kernel

```

runs the kernel configuration as during a Yocto build, and checks if all expected `CONFIG_*` items are set in the resulting config file

And finally:

```bash
grep AT24 $(bitbake-getvar --value -r virtual/kernel B)/.config

```

This uses the `bitbake-getvar` tool to get the kernels build directory, and as the default filename is `.config`, we can just grep it for our desired item.

## Step 4 (only if required): add kernel module to image

If you are using a very minimal image recipe, then kernel modules might not be included by default. A general catch-all strategy is to add

```bash
IMAGE_INSTALL:append = " kernel-modules "

```

to your image, or as a quick workaround for testing, you can also drop it into `local.conf`.

In cases where you are more concerned with storage, you can add specific kernel modules only to your build. To get a list of the available ones, build the kernel first and then inspect the package list:

```bash
bitbake virtual/kernel
oe-pkgdata-util list-pkgs | grep kernel-module

```

This prints the list of all kernel modules which are available as separate packages. It is dependent on the actual kernel configuration, as only modules that are built are packaged accordingly.

If you take a closer look, you can spot our module:

```bash
kernel-module-at24-6.6.21-yocto-standard

```

So instead installing all modules, we can only pull in the one we just configured:

```bash
IMAGE_INSTALL:append = " kernel-module-at24 "

```

## Conclusion

That’s it! Build and run your new kernel and enjoy your customization!

We’ve chosen a relatively simple and contained driver here which does not provoke conflicts, and in most embedded situation will not have additional dependencies: the only thing it really needs is support for the I2C bus, and that is usually enabled.

More in depth documentation can be found in the [Yocto Project Linux Kernel Development Manual](https://docs.yoctoproject.org/kernel-dev/index.html)

* * *

_If this tutorial was useful to you, please press like, or leave a thank you note to the contributor who put valuable time into this and made it available to you. It will be much appreciated!_
