Fedora aims to provide a kernel with as many configuration options enabled as possible. Sometimes users may want to change those options for testing or for a feature Fedora doesn’t support. This is a brief guide to how kernel configurations are generated and how to best make changes for a custom kernel.

Finding the configuration files

Fedora generates kernel configurations using a hierarchy of files. Kernel options common to all architectures and configurations are listed in individual files under baseconfig. Subdirectories under baseconfig can override the settings as needed for architectures. As an example:

$ find baseconfig -name CONFIG_SPI
baseconfig/x86/CONFIG_SPI
baseconfig/CONFIG_SPI
baseconfig/arm/CONFIG_SPI
$ cat baseconfig/CONFIG_SPI
# CONFIG_SPI is not set
$ cat baseconfig/x86/CONFIG_SPI
CONFIG_SPI=y
$ cat baseconfig/arm/CONFIG_SPI
CONFIG_SPI=y

As shown above, CONFIG_SPI is initially turned off for all architectures but x86 and arm enable it.

The directory debugconfig contains options that get enabled in kernel debug builds. The file config_generation lists the order in which directories are combined and overridden to make configs. After you change a setting in one of the individual files, you must run the script build_configs.sh to combine the individual files into configuration files. These exist in kernel-$flavor.config.

When rebuilding a custom kernel, the easiest way to change kernel configuration options is to put them in kernel-local. This file is merged automatically when building the kernel for all configuration options. You can set options to be disabled (# CONFIG_FOO is not set), enabled (CONFIG_FOO=y), or modular (CONFIG_FOO=M) in kernel-local.

Catching and fixing errors in your configuration files

The Fedora kernel build process does some basic checks on configuration files to help catch errors. By default, the Fedora kernel requires that all kernel options are  explicitly set. One common error happens when enabling one kernel option exposes another option that needs to be set. This produces errors related to .newoptions, as an example:

+ Arch=x86_64
+ grep -E '^CONFIG_'
+ make ARCH=x86_64 listnewconfig
+ '[' -s .newoptions ']'
+ cat .newoptions
CONFIG_R8188EU
+ exit 1
error: Bad exit status from /var/tmp/rpm-tmp.6BXufs (%prep)

RPM build errors:
 Bad exit status from /var/tmp/rpm-tmp.6BXufs (%prep)

To fix this error, explicitly set the options (CONFIG_R8188EU in this case) in kernel-local as well.

Another common mistake is setting an option incorrectly. The kernel Kconfig dependency checker silently changes configuration options that are not what it expects. This commonly happens when one option selects another option, or has a dependency that isn’t satisfied. Fedora attempts a basic sanity check that the options specified in tree match what the kernel configuration engine expects. This may produce errors related to mismatches:

+ ./check_configs.awk configs/kernel-4.13.0-i686-PAE.config temp-kernel-4.13.0-i686-PAE.config
+ '[' -s .mismatches ']'
+ echo 'Error: Mismatches found in configuration files'
Error: Mismatches found in configuration files
+ cat .mismatches
Found CONFIG_I2C_DESIGNWARE_CORE=y  after generation, had CONFIG_I2C_DESIGNWARE_CORE=m in Fedora tree
+ exit 1

In this example, the Fedora configuration specified CONFIG_I2C_DESIGNWARE_CORE=m, but the kernel configuration engine set it to CONFIG_I2C_DESIGNWARE_CORE=y. The kernel configuration engine is ultimately what gets used, so the solution is either to change the option to what the kernel expects (CONFIG_I2C_DESIGNWARE_CORE=y in this case) or to further investigate what is causing the unexpected configuration setting.

Once the kernel configuration options are set to your liking, you can follow standard kernel build procedures to build your custom kernel.