OpenWrt uses a layered, fragment-based approach to Linux kernel configuration. Rather than maintaining a single monolithic .config file, configuration is split across several files that are merged at build time.
How Kernel Config Is Assembled
The build system merges kernel config fragments in the following order:
target/linux/generic/config-<version> # shared base config
target/linux/<target>/config-<version> # target-specific config
target/linux/<target>/<subtarget>/config-<version> # subtarget config (if present)
These fragments are combined using scripts/kconfig.pl to produce the final .config that is passed to the Linux build system.
Kernel Config Targets
| Make Target | Description |
|---|
make kernel_menuconfig | Open the kernel’s interactive ncurses configurator |
make kernel_nconfig | Open the kernel’s nconfig (alternative ncurses) configurator |
make kernel_xconfig | Open the kernel’s Qt-based xconfig configurator |
make kernel_oldconfig | Update config to a newer kernel version non-interactively |
After running kernel_menuconfig, diff the resulting config against the existing fragment to extract only your changes. The modified config is saved in the kernel build directory at build_dir/target-*/linux-*/linux-*/.config.
All kernel options follow the standard Linux Kconfig format:
# Enabled options
CONFIG_NET=y
CONFIG_INET=y
CONFIG_PACKET=y
# Built as loadable module
CONFIG_USB_SERIAL=m
# Explicitly disabled
# CONFIG_VIRTUALIZATION is not set
# String/integer options
CONFIG_DEFAULT_HOSTNAME="OpenWrt"
CONFIG_LOG_BUF_SHIFT=14
In config fragment files you only need to include lines that differ from the upstream kernel defaults. The build system merges and resolves conflicts automatically.
Built-in vs. Loadable Modules
Kernel features can be compiled in three ways:
| Setting | Meaning |
|---|
CONFIG_FOO=y | Built into the kernel image (always present) |
CONFIG_FOO=m | Built as a loadable kernel module (.ko file) |
# CONFIG_FOO is not set | Disabled entirely |
kmod Packages
OpenWrt wraps loadable kernel modules into installable kmod-* packages. When a module is built as =m, the build system packages the resulting .ko file and its dependencies into an IPK that can be installed with opkg.
Example: kmod-usb-serial installs usb-serial.ko and its dependencies into the firmware or as an installable package.
The naming convention is:
kmod-<subsystem> # e.g. kmod-usb-core
kmod-<driver> # e.g. kmod-ath9k
kmod-<feature> # e.g. kmod-nf-conntrack
Kernel module packages are defined in target/linux/<target>/modules.mk and target/linux/generic/modules.mk.
Adding a Kernel Module Package
To expose a kernel module as an installable package, add it to the appropriate modules.mk:
# target/linux/generic/modules.mk (example)
define KernelPackage/my-driver
SUBMENU:=Other
TITLE:=My hardware driver
DEPENDS:=@TARGET_mytarget
KCONFIG:=CONFIG_MY_DRIVER
FILES:=$(LINUX_DIR)/drivers/misc/my-driver.ko
AUTOLOAD:=$(call AutoLoad,80,my-driver)
endef
$(eval $(call KernelPackage,my-driver))
The KCONFIG variable references the kernel Kconfig symbol. AUTOLOAD controls whether the module is loaded automatically at boot via /etc/modules.d/.
Target Config Fragment Example
This is an excerpt from target/linux/ath79/config-6.12:
CONFIG_ATH79=y
CONFIG_MIPS_ELF_APPENDED_DTB=y
CONFIG_MIPS_CMDLINE_FROM_DTB=y
CONFIG_ATH79_MACH_GENERIC=y
# CONFIG_MIPS_MT_SMP is not set
CONFIG_HZ_250=y
Only options specific to the ATH79 SoC family need to appear here; generic network and filesystem options are inherited from generic/config-<version>.
Viewing the Effective Config
After configuring, you can inspect the final merged kernel config:
# Build the kernel config without compiling
make target/linux/prepare
# The merged .config is at:
build_dir/target-*/linux-*/linux-*/.config