Using kernel config fragments to remove an unwanted feature
Adding a feature to a linux-yocto
based kernel is fairly well documented. This makes sense because it is the most common thing you might want to do: “My board needs support for this sensor added to our BSP.”
Konsulko Group recently helped a customer that had exactly the opposite problem, a standard feature in linux-intel
(which includes linux-yocto.inc
and inherits the kernel-yocto
class) needed to be removed. The SoC (in the Intel™ “Bay Trail” family) and the off-the-shelf industrial PC had a problem. When USB 3.0 (xHCI) support is enabled, the default BIOS settings (xHCI Mode = Auto
) would cause the system to lock-up upon either warm reboot or shutdown. Given that these systems are deeply embedded in the field—where simply “hooking up a display, keyboard and mouse” is cost prohibitive—we needed to find an option that would not prevent OTA updates.
You might think you could apply a patch via SRC_URI
to kmeta
(yocto-kernel-cache), but this isn’t supported in the Yocto Project kernel tooling. Instead we can apply kernel config fragments that disable the problematic xHCI
feature. The trade off is that USB 3.x devices won’t be able to run at full speed, but the systems in question have no need for USB 3.0 (they are a classic IoT gateway use case).
Determining your existing kernel configuration
The first thing you want to do in this situation is determine what your (default) kernel configuration is. In our case, Konsulko and our customer are using the ‘dunfell’ (3.1.x) branch of meta-intel with MACHINE="intel-corei7-64"
. Upon building an image or the kernel (e.g. bitbake virtual/kernel
or bitbake linux-intel
), the kernel configuration can be found at the following path:
<build>tmp/work/corei7-64-intel-common-poky-linux/linux-intel/5.4.170+gitAUTOINC+98cce1c95f_36f93ff941-r0/linux-corei7-64-intel-common-standard-build/.config
Where the kernel version is 5.4.170
, the (shortened) git commit hash of the kernel cache is 98cce1c95f
and the (shortened) git commit hash of the kernel source is 36f93ff941
.
Modifying the kernel configuration with menuconfig
The documented way to modify the kernel configuration is with:
bitbake -c menuconfig linux-intel
This approach works fine, but you must remember to copy the resulting .config
to defconfig
in your recipe’s SRC_URI
.
Alternatively you can create your kernel config fragments in the kernel build directory and then add them to your kernel recipe. The fragments can be created with the help of the diffconfig
script in the kernel source tree.
Also note that you must have already run:
$ bitbake -c kernel_configme -f linux-intel
or previously built the kernel in order for the .config
to be present.
Modifying the kernel configuration with devtool
It will come as no surprise that my preferred way to modify the kernel configuration is to run:
$ devtool menuconfig linux-intel
But you will get an error:
ERROR: No recipe named 'linux-intel' in your workspace
So first we must get the kernel recipe into our workspace:
$ devtool modify linux-intel
Now we are able to run:
$ devtool menuconfig linux-intel
One benefit of this approach is that devtool
will run the required steps that need to happen before menuconfig
can be run (most notably the do_kernel_configme
task).
Determining the changes needed
Regardless of which method you used to run menuconfig
, you will now be presented with the text UI:
Since Konsulko and our customer already knew we needed to change the xHCI
enablement, we can quickly </> for Search
and then enter xHCI
.
This gives us several results, but the ones that we care about have [=y]
(built-in) next to them:
CONFIG_USB_XHCI_HCD
CONFIG_USB_XHCI_PCI
CONFIG_USB_XHCI_PLATFORM
The top level item that needs to be disabled (set to N
) is CONFIG_USB_XHCI_HCD
:
After this we can spot check the other values are also disabled (by using </> for Search
again):CONFIG_USB_XHCI_PCI
and CONFIG_USB_XHCI_PLATFORM
:
Satisfied that we have the needed change, we can save our configuration. Press the <E>
key or click on < Exit >
to exit the sub-menus until you are at the top of the stack. Press the <S>
key or click on < Save >
to save the configuration. At they prompt, press enter or click on <Yes>
.
Now, the benefit of the devtool
workflow comes into play, because we are rewarded with:
INFO: Updating config fragment <build>/workspace/sources/linux-intel/oe-local-files/devtool-fragment.cfg
The contents of this file are what you might expect:
# CONFIG_USB_XHCI_HCD is not set
Applying our configuration change
If we don’t already have one, we need a layer into which to put our changes:
$ bitbake-layers create-layer ~/Projects/meta-awesome-bsp
Add the layer to our active layers:
$ bitbake-layers add-layer ~/Projects/meta-awesome-bsp
Create a directory–following the pattern in openembedded-core–for our kernel changes:
$ mkdir -p ~/Projects/meta-awesome-bsp/recipes-kernel/linux
Finish our recipe:
$ devtool finish linux-intel ~/Projects/meta-awesome-bsp
Examine the resulting directory structure:
$ tree ~/Projects/meta-awesome-bsp
/home/<user>/Projects/meta-awesome-bsp
├── conf
│ └── layer.conf
├── COPYING.MIT
├── README
├── recipes-example
│ └── example
│ └── example_0.1.bb
└── recipes-kernel
└── linux
├── linux-intel
│ └── devtool-fragment.cfg
└── linux-intel_%.bbappend
Since this might not be the only change to the kernel we will need to make, let us give the fragment a better name:
pushd ~/Projects/meta-awesome/recipes-kernel/linux/linux-intel
mv devtool-fragment.cfg disable-xhci-hcd.cfg
And create an .scc
file to give the Yocto Project kernel tooling better hints of how to apply our change:
cat << EOF >> disable-xhci-hcd.scc
# SPDX-License-Identifier: MIT
define KFEATURE_DESCRIPTION "Disable options for xhci (USB 3.0)"
define KFEATURE_COMPATIBILITY board
kconf hardware disable-xhci-hcd.cfg
EOF
And finally make changes to our linux-intel_%.bbappend
to reflect these files:
$ cd ..
$ cat linux-intel_%.bbappend
FILESEXTRAPATHS_prepend := "${THISDIR}/${PN}:"
SRC_URI += "\
file://disable-xhci-hcd.cfg \
file://disable-xhci-hcd.scc \
"
Now—as long as our layer has high enough priority and no other recipes add kernel config fragments which conflict with our change—we should be able to build the kernel and inspect the resulting .config
:
$ popd
$ bitbake linux-intel
$ grep -R XHCI tmp/work/corei7-64-intel-common-poky-linux/linux-intel/5.4.170+gitAUTOINC+98cce1c95f_36f93ff941-r0/linux-corei7-64-intel-common-standard-build/.config
# CONFIG_USB_XHCI_HCD is not set
# CONFIG_USB_ROLES_INTEL_XHCI is not set
We should also be able to run dmesg | grep xhci
on the target and we would not expect to see any messages.
Summary
A Konsulko Group customer had a hardware problem that required us to remove a kernel feature. By using tools like devtool
, we were able to fairly easily make a change to the kernel configuration and capture those changes in a persistent way with a .cfg
fragment and a .bbappend
. This approach solved the problem and allowed OTA updates to proceed to these deeply embedded devices in the field. Please contact us to discuss how Konsulko can help you with the unique requirements of your commercial project.