Chapter 30B: Product kernel configs¶
Chapter 30 explained how kernel configuration works. Chapter 30A explained how to choose and maintain a kernel version.
This chapter is about using configuration in a product. A product rarely has only one kernel config. You usually need at least:
a development config,
a production config,
a recovery config.
They should be related, but not identical.
30B.1 Why one config is not enough¶
During bring-up, you want many debug features:
verbose logs,
debug filesystems,
extra drivers,
symbols,
tracing.
In production, you usually want less:
smaller image,
shorter boot time,
fewer attack paths,
fewer accidental interfaces.
In recovery, you want a kernel that can boot when the normal system is broken:
storage driver built in,
console built in,
initramfs support,
enough networking or USB for update,
fewer optional product features.
Trying to use one .config for all three jobs makes the file confusing.
30B.2 Use fragments¶
Do not hand-edit one huge .config forever.
Keep small config fragments in your board repository:
kernel-configs/
base.config
dev.config
prod.config
recovery.config
Example base.config:
CONFIG_ARCH_MXC=y
CONFIG_SOC_IMX6ULL=y
CONFIG_SERIAL_IMX=y
CONFIG_SERIAL_IMX_CONSOLE=y
CONFIG_MMC=y
CONFIG_MMC_SDHCI=y
CONFIG_MMC_SDHCI_ESDHC_IMX=y
CONFIG_EXT4_FS=y
CONFIG_DEVTMPFS=y
CONFIG_DEVTMPFS_MOUNT=y
Example dev.config:
CONFIG_DEBUG_KERNEL=y
CONFIG_DYNAMIC_DEBUG=y
CONFIG_DEBUG_FS=y
CONFIG_KALLSYMS=y
CONFIG_KALLSYMS_ALL=y
CONFIG_FTRACE=y
CONFIG_FUNCTION_TRACER=y
Example prod.config:
# CONFIG_DEBUG_FS is not set
# CONFIG_DYNAMIC_DEBUG is not set
CONFIG_STRICT_KERNEL_RWX=y
CONFIG_STRICT_MODULE_RWX=y
Example recovery.config:
CONFIG_BLK_DEV_INITRD=y
CONFIG_INITRAMFS_SOURCE=""
CONFIG_USB_SUPPORT=y
CONFIG_USB=y
CONFIG_USB_STORAGE=y
CONFIG_VFAT_FS=y
CONFIG_FAT_FS=y
These are examples, not a final product policy. The important idea is that each fragment has a purpose.
30B.3 Build separate output directories¶
Use one output directory per config.
$ cd ~/imx6ull/src/linux-v6.6
$ mkdir -p build-dev build-prod build-recovery
Merge the development config:
$ ./scripts/kconfig/merge_config.sh \
-O build-dev \
arch/arm/configs/imx_v6_v7_defconfig \
kernel-configs/base.config \
kernel-configs/dev.config
$ make O=build-dev olddefconfig
Merge the production config:
$ ./scripts/kconfig/merge_config.sh \
-O build-prod \
arch/arm/configs/imx_v6_v7_defconfig \
kernel-configs/base.config \
kernel-configs/prod.config
$ make O=build-prod olddefconfig
Merge the recovery config:
$ ./scripts/kconfig/merge_config.sh \
-O build-recovery \
arch/arm/configs/imx_v6_v7_defconfig \
kernel-configs/base.config \
kernel-configs/recovery.config
$ make O=build-recovery olddefconfig
Then build each one:
$ make O=build-dev -j$(nproc) zImage dtbs modules
$ make O=build-prod -j$(nproc) zImage dtbs modules
$ make O=build-recovery -j$(nproc) zImage dtbs
The O= directory keeps generated files separate. That makes it possible to compare configs and rebuild only the one you need.
30B.4 Built-in or module?¶
For embedded boot, this decision matters.
Driver |
Built-in ( |
Module ( |
|---|---|---|
UART console |
Usually yes |
No, too late for early boot logs |
MMC rootfs driver |
Yes if rootfs is on MMC |
Only if initramfs can load it |
Ethernet |
Depends on boot needs |
Fine if rootfs can load modules |
USB storage recovery |
Yes for recovery kernel |
Fine for normal product |
Optional sensor |
Usually no |
Good module candidate |
Filesystem for rootfs |
Yes |
Only if initramfs loads it first |
A simple rule:
If the kernel needs it before the real root filesystem is mounted, build it in.
30B.5 Compare configs¶
The kernel tree includes a config comparison tool:
$ ./scripts/diffconfig build-dev/.config build-prod/.config
Example output:
-DEBUG_FS y
-DYNAMIC_DEBUG y
-FTRACE y
STRICT_KERNEL_RWX y
STRICT_MODULE_RWX y
Use this before release. It catches surprises like debug features left enabled in production.
30B.6 Save a small defconfig¶
After merging and checking a config, save the minimal form:
$ make O=build-prod savedefconfig
$ cp build-prod/defconfig kernel-configs/imx6ull_product_defconfig
The full .config is generated output. It is useful for builds, but it is noisy in code review.
Commit the small defconfig or fragments. Regenerate the full .config during the build.
30B.7 Name the kernel clearly¶
Set a local version so the running board tells you what it is using.
In a config fragment:
CONFIG_LOCALVERSION="-imx6ull-prod"
Or from the command line:
$ make O=build-prod LOCALVERSION=-imx6ull-prod zImage
On the board:
# uname -a
Linux imx6ull 6.6.0-imx6ull-prod ...
This small detail helps distinguish several kernel variants in the same development environment.
30B.8 Keep bootargs different from config¶
Kernel config decides what the kernel can do.
Bootargs decide what this boot should do.
Examples:
Setting |
Usually belongs in |
|---|---|
Enable MMC driver |
Kernel config |
Select root device |
Bootargs |
Enable ext4 support |
Kernel config |
Pass |
Bootargs |
Enable initramfs support |
Kernel config |
Pass |
Bootargs |
Enable dynamic debug support |
Kernel config |
Turn on one driver’s debug messages |
Bootargs or debugfs |
Do not rebuild the kernel just to change root=/dev/mmcblk0p2. That is a bootargs job.
30B.9 A small CI matrix¶
Even a small embedded team should build more than one kernel in automation.
Example:
Build |
Config |
Must prove |
|---|---|---|
|
base + dev |
Boots, has debugfs and symbols |
|
base + prod |
Boots normal rootfs, debug features absent |
|
base + recovery |
Boots initramfs recovery menu |
|
board DTS |
Device tree still validates |
The CI does not need to run on real hardware for every commit, but hardware boot tests should happen before release.
30B.10 Release checklist¶
Before handing a kernel to manufacturing or customers:
uname -ashows the expected version string.The DTB in the boot partition matches the kernel release.
scripts/diffconfigwas checked against the previous release.Debug-only features are intentionally enabled or disabled.
Rootfs storage, console, and filesystem drivers are built in when needed.
Recovery boot was tested, not only normal boot.
The exact kernel source tag and config fragments are recorded.
30B.11 Key Notes¶
Development, production and recovery kernels share hardware needs but serve different operational roles. A diagnostic interface useful in development is not automatically a production requirement.
A base fragment captures common support, while role fragments express differences. Kconfig resolution determines the final state, so the resulting
.configmatters as well as the requested fragments.Separate
O=directories isolate generated state for each variant. They prevent one role’s configuration and artifacts from silently replacing another’s.Boot-critical drivers must be reachable before the normal rootfs mounts. Modules are viable at that stage only when an earlier environment can provide and load them.
Kernel configuration defines capability, bootargs select boot policy, and DT defines hardware resources. These interfaces need coordinated releases without being collapsed into one configuration file.
Local version strings and config diffs expose artifact identity and policy changes. They complement source revision records rather than replacing them.
A CI build checks a different boundary from normal or recovery boot tests. Manufacturing readiness includes recovery operation, not merely the existence of three successfully built images.
Part IV connects image artifacts, firmware handoff, hardware description, recovery and configuration ownership. Part V examines the user-space environment that depends on those interfaces.
Previous chapter: Chapter 30A - Kernel lifecycle
Next part: Part V - Root filesystem and user space