📘 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.
Kconfig files in kernel 6.x
Kernel Version
Practical Steps
Topics Covered in This Lecture
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
menuand themenuconfigkeyword
📸 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.
| 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 | ||||||
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.
| 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.* |
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 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
| 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.
| 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.
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
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:
1. init/Kconfigconfig EP_MY_DRIVER |
→ user selects Y |
2. .configCONFIG_EP_MY_DRIVER=y |
→ make generates |
3. autoconf.h#define CONFIG_EP_MY_DRIVER 1 |
→ Makefile expands |
4. Makefileobj-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 | 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. |
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
boolfor built-in-only options,tristatefor anything that can be a loadable module - Adding an option requires: edit the right Kconfig file, add the
configblock, update the Makefile withobj-$(CONFIG_YOUR_OPTION) - The flow is: Kconfig →
.config→autoconf.h→ Makefile → compiled object → kernel image - Prefer
depends onoverselectfor expressing dependencies —selectcan cause circular dependency errors - Use
menuconfig+if/endifto 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.
