L23: The Kconfig System and Adding Your Own Menu Item



📘 Free Linux Kernel Programming Course | Chapter 2

Chapter 2 · Lecture 23

The Kconfig System and Adding Your Own Menu Item

Understand how the kernel’s entire configuration menu is assembled from Kconfig files — then add your own custom option from scratch, step by step.

1700+
Kconfig files in kernel 6.x
6.x
Kernel Version
Hands-On
Practical Steps

Topics Covered in This Lecture

Kconfig language
init/Kconfig
add custom menu item
bool vs tristate
depends on
select keyword
obj-$(CONFIG_)
autoconf.h
menuconfig keyword
free linux kernel course

🎯 What You Will Learn

  • What Kconfig files are and how they are assembled into the menuconfig UI
  • Which Kconfig file controls which section of the kernel configuration menu
  • The Kconfig language: config, bool, tristate, default, depends on, select, help
  • Step-by-step how to add your own configuration option to the Linux kernel menu
  • How your Kconfig option connects to the Makefile and C source code
  • How to group options using menu and the menuconfig keyword

📸 Suggested Image for This Section

A screenshot of make menuconfig running in terminal showing the General Setup submenu with a custom option highlighted. Alt text: “Adding a custom Kconfig option to Linux kernel menuconfig General Setup menu”

1. What Are Kconfig Files and Why Do They Exist?

When you run make menuconfig, you see a text-based interface with dozens of menus, hundreds of sub-menus, and thousands of individual options. None of this comes from a single master file. Instead, the kernel’s build system assembles the entire menu dynamically from thousands of small files called Kconfig files.

Every subsystem in the kernel — networking, USB, filesystems, security, power management — owns one or more Kconfig files that describe the options that belong to it. The Kconfig build system (called Kbuild) reads all of them starting from the root Kconfig file, follows the chain of source directives, and assembles the complete menu tree you interact with.

How Kconfig Files Are Assembled Into the menuconfig UI
Root: Kconfig (top-level)
↓ sources via “source” directives
init/Kconfig
General Setup
| drivers/Kconfig
Device Drivers
| net/Kconfig
Networking
| security/Kconfig
Security
↓ all assembled into
make menuconfig / xconfig / nconfig — the configuration UI
📌 Scale in kernel 6.x: The Linux 6.x source tree contains over 1,700 Kconfig files. Each subsystem owns its own. This modularity is what keeps the configuration system manageable despite the enormous scale of the kernel.

2. Which Kconfig File Controls Which Menu Section?

Before you can add your own option or modify an existing one, you need to know which Kconfig file to edit. The table below covers all the major sections of the menuconfig UI and the corresponding file you need to look at. This is knowledge you will use constantly as a kernel developer.

Kernel Config Menu Sections and Their Kconfig Files
Menu Section in menuconfig Kconfig File Location
Main menu / initial screen Kconfig
General setup + Module support init/Kconfig
Processor types, Bus options (arch-specific) arch/<arch>/Kconfig
Power management kernel/power/Kconfig
Firmware drivers drivers/firmware/Kconfig
Virtualization (KVM) arch/<arch>/kvm/Kconfig
Block layer + IO Schedulers block/Kconfig
Memory management mm/Kconfig
Networking support net/Kconfig, net/*/Kconfig
Device drivers drivers/Kconfig, drivers/*/Kconfig
File systems fs/Kconfig, fs/*/Kconfig
Security options security/Kconfig, security/*/Kconfig
Cryptographic API crypto/Kconfig, crypto/*/Kconfig
Library routines lib/Kconfig, lib/*/Kconfig
Kernel hacking / Debug options lib/Kconfig.debug, lib/Kconfig.*
💡 Pro Tip — Find Any Option’s Kconfig File in Seconds: Inside make menuconfig, navigate to any option and press the ? key. The help screen shows the exact Kconfig file and line that defines that option. This is the fastest lookup method — no grep needed.

3. The Kconfig Language — Core Keywords You Need

The Kconfig language is intentionally minimal. You only need a handful of keywords to write useful entries. Let us go through each one clearly.

The config Keyword

Every configuration option starts with the keyword config followed by a symbol name you choose. The build system automatically prepends CONFIG_ to your symbol name everywhere it is used — in Makefiles, in C code, and in the .config file. So config MY_DRIVER becomes CONFIG_MY_DRIVER throughout the build.

config MY_DRIVER
    bool "Enable my custom driver"
    default n
    help
      Set this to Y to include my custom driver in the kernel.
      If unsure, say N.

Type Keywords — bool vs tristate

bool vs tristate — Choosing the Right Type for Your Option
bool
Two states only: y (built in) or n (off). Use for kernel-core features that cannot be made into modules — security features, core scheduler options, debug flags.

config MY_DEBUG_FLAG
    bool "Enable debug mode"
    default n
tristate
Three states: y (built in), m (loadable module), or n (off). Use for drivers and subsystems that can reasonably be loaded and unloaded at runtime.

config MY_USB_DRIVER
    tristate "My USB driver"
    depends on USB

Other Important Kconfig Keywords

Kconfig Language — Essential Keywords Reference
Keyword What It Does Example
default Sets the value when the user has not explicitly chosen one default n
depends on Hides this option unless the named dependency is already enabled depends on USB
select Auto-enables another option when this one is set to y select CRYPTO_AES
help Text shown when user presses ? on this item in menuconfig help
Say Y to enable…
string / int / hex Types for text string, integer, or hexadecimal value options string “Default hostname”

4. Step-by-Step: Adding Your Own Option to the Kernel Menu

Let us walk through a complete real example. We will add a configuration option called CONFIG_EP_MY_DRIVER that appears inside the General Setup menu. This is the exact process you will follow for any real driver or kernel feature you develop.

The Five Steps to Add a Custom Kernel Config Option
1
Find the right Kconfig file
2
Add your entry
3
Verify in menuconfig
4
Wire up Makefile
5
Use in C code

Step 1 — Find and Back Up the Right Kconfig File

We want our option in General Setup. From the table above, that means init/Kconfig. Always back up before editing:

# From the root of your kernel source tree
$ cp init/Kconfig init/Kconfig.bak

Step 2 — Add Your Entry Inside init/Kconfig

Open init/Kconfig in your editor. Find a logical place — near the LOCALVERSION_AUTO area is a good spot used by the community. Add this block:

config EP_MY_DRIVER
    bool "EmbeddedPathashala: Enable my custom driver support"
    default n
    help
      Enable this option to include the EmbeddedPathashala custom
      driver in your kernel build.

      If unsure, say N.
Naming Convention: Always prefix your config symbols with a unique project or company identifier. Using EP_ or MYCOMPANY_ as a prefix ensures you never accidentally clash with existing kernel symbols, which start with non-prefixed names or known subsystem prefixes.

Step 3 — Run menuconfig to Verify It Appears

$ make menuconfig

Navigate to General Setup. Your new entry should appear in the list as “EmbeddedPathashala: Enable my custom driver support”. Press ? on it to confirm the help text displays correctly. Press Y to enable it and save the config.

Step 4 — Wire Up Your Makefile

The Kconfig entry alone does not compile anything. You must tell the build system what to build when the option is selected. Edit the Makefile in your driver’s directory:

# In your driver's Makefile — for example: drivers/mydriver/Makefile

# When CONFIG_EP_MY_DRIVER=y  → obj-y  → built into kernel image
# When CONFIG_EP_MY_DRIVER=m  → obj-m  → compiled as a .ko module
# When CONFIG_EP_MY_DRIVER=n  → nothing → file not compiled at all

obj-$(CONFIG_EP_MY_DRIVER) += my_driver.o

The $(CONFIG_EP_MY_DRIVER) variable is automatically substituted with y, m, or left empty by the build system, based on what the user selected.

Step 5 — Use the Config Symbol in Your C Code

The kernel build system auto-generates a header file include/generated/autoconf.h from your .config. When CONFIG_EP_MY_DRIVER=y, the macro CONFIG_EP_MY_DRIVER is defined as 1 in that header, which is automatically included everywhere in the kernel. You can use it like this:

/* my_driver.c */
#include <linux/kernel.h>

#ifdef CONFIG_EP_MY_DRIVER
static void my_feature_init(void)
{
    pr_info("EP driver: custom feature is active\n");
}
#endif
When to use #ifdef: If your entire C file is only compiled when the option is y (which is the normal case, thanks to your Makefile), you rarely need #ifdef around the whole file. It is most useful for adding optional behaviour inside a file that is always compiled, or for conditional feature blocks within a larger driver.

5. The Full Chain — From Kconfig to Compiled Code

It helps to see how a single menu selection flows all the way from the user’s keypress in menuconfig to your compiled kernel binary. Here is the complete picture:

Complete Flow: Kconfig Entry → .config → autoconf.h → Object File → Kernel Image
1. init/Kconfig
config EP_MY_DRIVER
bool "..."

user selects Y
2. .config
CONFIG_EP_MY_DRIVER=y

make generates
3. autoconf.h
#define CONFIG_EP_MY_DRIVER 1

Makefile expands
4. Makefile
obj-y += my_driver.o
5. Kernel Image
my_driver.o built in

6. Handling Dependencies — depends on vs select

Most real drivers depend on other subsystems being present. A USB driver needs the USB subsystem. A crypto driver needs the crypto layer. Kconfig gives you two tools for expressing this — and they work very differently.

depends on vs select — Behavior Comparison
depends on select

Your option is hidden from the menu entirely if the dependency is not already enabled. The user must first go and enable the dependency themselves.

config MY_USB_DRIVER
    tristate "My USB driver"
    depends on USB

If USB=n, MY_USB_DRIVER will not appear in the menu at all.

When the user enables your option, the listed symbol is automatically forced to y — without the user doing anything. The selection happens silently.

config MY_CRYPTO_DRV
    tristate "My crypto driver"
    select CRYPTO_AES

Enabling MY_CRYPTO_DRV automatically forces CRYPTO_AES=y.

⚠️ Use select with Great Caution: select overrides the user’s explicit choice for the selected symbol. This can create circular dependencies (A selects B, B selects A) that cause the Kconfig system to fail. It can also force-enable a symbol that has its own unmet dependencies, leading to confusing build errors. The kernel community’s guidance is clear: prefer depends on in almost all cases and reserve select only for well-understood, non-cyclic hard requirements.

7. Grouping Options — menu, endmenu, and menuconfig

As your driver grows you may add multiple related config options. Rather than listing them all flat in the parent menu, you can group them under a collapsible sub-menu. Kconfig gives you two approaches:


# Approach 1 — Plain sub-menu (always visible as a group)
menu "EmbeddedPathashala Driver Options"

config EP_FEATURE_A
    bool "Feature A"
    default n

config EP_FEATURE_B
    bool "Feature B"
    default n

endmenu


# Approach 2 — menuconfig (submenu only appears when top-level is enabled)
menuconfig EP_MY_SUBSYSTEM
    bool "EmbeddedPathashala Subsystem"
    default n

if EP_MY_SUBSYSTEM

config EP_FEATURE_A
    bool "Feature A (requires EP subsystem)"
    default n

config EP_FEATURE_B
    bool "Feature B (requires EP subsystem)"
    default n

endif

The menuconfig approach is the cleaner pattern used throughout the kernel. Sub-options only appear if the user has enabled the parent — so users who do not need your subsystem do not see the sub-options cluttering their menu. Study how the USB or sound subsystems use this pattern in drivers/usb/Kconfig and sound/Kconfig.

📸 Suggested Image for This Section

A side-by-side terminal screenshot showing the same menuconfig before and after adding the custom Kconfig entry — the new item visible in the General Setup submenu. Alt text: “Custom CONFIG_EP_MY_DRIVER option visible in Linux kernel menuconfig General Setup”

📋 Lecture Summary

  • The kernel’s menuconfig UI is assembled from over 1,700 individual Kconfig files — each subsystem owns its own
  • Find any option’s defining file by pressing ? on it inside menuconfig
  • Use bool for built-in-only options, tristate for anything that can be a loadable module
  • Adding an option requires: edit the right Kconfig file, add the config block, update the Makefile with obj-$(CONFIG_YOUR_OPTION)
  • The flow is: Kconfig → .configautoconf.h → Makefile → compiled object → kernel image
  • Prefer depends on over select for expressing dependencies — select can cause circular dependency errors
  • Use menuconfig + if/endif to group related options under a collapsible sub-menu

❓ Frequently Asked Questions

Do I need to modify any other file besides Kconfig and the Makefile to add a new kernel option?

For a driver in an existing directory, editing the Kconfig file and the Makefile in that directory is sufficient. If you are creating a brand new subdirectory under drivers/, you also need to add a source "drivers/mydir/Kconfig" line in the parent drivers/Kconfig and an obj-y += mydir/ or equivalent line in the parent drivers/Makefile so the build system knows to descend into your directory.

What happens to CONFIG_MY_OPTION in autoconf.h when it is set to m (module)?

When an option is set to m, the generated autoconf.h defines CONFIG_MY_OPTION_MODULE as 1 rather than CONFIG_MY_OPTION. This distinction matters for code that needs to behave differently when built as a module versus built in. In most cases you do not need to care about this because your Makefile handles the compilation difference automatically via obj-$(CONFIG_MY_OPTION).

Can a single Kconfig file define options for multiple menus?

Typically, one Kconfig file drives one menu or submenu. However, there is nothing technically preventing a Kconfig file from defining options that appear in multiple places — the Kconfig language supports this through menu structure keywords. In practice, keeping one Kconfig file per subsystem directory is a strong convention in the kernel because it makes the build system easy to understand and maintain.

How do I search for a specific CONFIG_ symbol inside make menuconfig?

Press the / key inside menuconfig to open a search box. Type the symbol name (without the CONFIG_ prefix) and the UI will show you every matching option, where it is located in the menu tree, and which Kconfig file defines it. This is the fastest way to navigate the menu when you know the symbol name you are looking for.

🎯 Interview Questions

Q1. You write a new Linux driver. What files must you create or modify to expose a new Kconfig option for it in make menuconfig?

At minimum, two things must be done. First, add a config entry in the appropriate Kconfig file for the subsystem your driver belongs to — for a character device, this would typically be near drivers/char/Kconfig. Second, update the Makefile in your driver’s directory with obj-$(CONFIG_MY_DRIVER) += my_driver.o. If your driver is in a new subdirectory, you also need to add source and obj-y += lines in the parent directory’s Kconfig and Makefile respectively so the build system descends into your directory.

Q2. What is the difference between bool and tristate in a Kconfig entry? When would you choose each one?

A bool option supports two states: y (compiled in) and n (disabled). A tristate option adds a third state: m (built as a loadable kernel module). Use bool for features that are tightly integrated with the kernel core and cannot be meaningfully unloaded at runtime — architecture options, core security features, scheduler settings. Use tristate for device drivers, file systems, and protocol implementations that can be loaded and unloaded at runtime. If in doubt for a driver, use tristate.

Q3. What is the difference between depends on and select in Kconfig? Why should select be used with caution?

depends on makes your option invisible in the menu unless the listed dependency is already enabled by the user. select silently forces the listed symbol to y when the user enables your option. The risk with select is circular dependencies — if A selects B and B selects A, the Kconfig resolver cannot find a valid configuration and produces an error. It can also force-enable symbols that have their own unmet dependencies, causing cryptic build failures. The kernel community’s strong recommendation is to use depends on in nearly all cases.

Q4. How do kernel Makefiles know whether to build a driver as built-in, a module, or skip it entirely, based on the user’s menuconfig selection?

The Makefile uses the obj-$(CONFIG_SYMBOL) pattern. The Kbuild system substitutes $(CONFIG_SYMBOL) with the value from .config. If the value is y, the line becomes obj-y += my_driver.o and the object is linked into the kernel image. If the value is m, it becomes obj-m += my_driver.o and a .ko module file is produced. If the value is n or the symbol is absent, the variable expands to nothing and the line has no effect — the file is not compiled.

Q5. How would you quickly find which Kconfig file defines a specific option you see in make menuconfig?

The fastest method is to navigate to that option in menuconfig and press the ? key. The help screen shows the exact Kconfig file path and the config symbol name. Alternatively, use the / search key inside menuconfig. From the command line, grep -r "config SYMBOL_NAME" . from the kernel source root will also find it. The ? key approach is generally fastest because it gives the file path directly without needing to parse grep results.

Q6. What is autoconf.h, how is it generated, and why do kernel C files not need to explicitly include it?

include/generated/autoconf.h is a C header file automatically generated by the Kbuild system from the .config file after every configuration change. For each option set to y, it writes #define CONFIG_SYMBOL 1. For m options, it writes #define CONFIG_SYMBOL_MODULE 1. Options set to n are simply not defined. Kernel C files do not need to explicitly include it because the Kbuild compilation flags automatically pass -include include/generated/autoconf.h (via the -include gcc flag) to every compiled translation unit, making all CONFIG_ macros automatically available everywhere.

🎉 Chapter 2 Complete!

You have now covered the full kernel configuration process — from tooling through security auditing to customizing the menu system. Chapter 3 moves into the actual kernel compilation: running the build, understanding the output, and installing your custom kernel.

Continue to Chapter 3 →
Back to Course Index

← Previous Lecture
EmbeddedPathashala · Free Linux Kernel Course · Ch.2 Lecture 23
Next Lecture→

Leave a Reply

Your email address will not be published. Required fields are marked *