not your average tech/non-tech blog - since 2007

Armbian - using kernel-config

May 11, 2024 Technical Ben Zucker

About a year ago the Armbian build framework made its transition to the next generation. Tons of code have been rewritten, new features added, existing one were rewritten in Python from scratch. The main driving force behind it was Ricardo Pardini.

With this transition some build options regular users were quite familiar, KERNEL_CONFIGURE or CREATE_PATCHES for example, were deprecated and this lead to confusion and incomprehension, last but not least due to the more or less constant lack of detailed framework documentation. So users had to conjecture how things work from reading the code, forums and answers to issue reports.
This situation even forced the Armbian developers to bring back the old switches to some extend.

In today’s topic I want to break down kernel-config as the now modern way to configure your Linux kernel configuration before building.



./compile.sh BOARD=orangepione BRANCH=current kernel-config
# Save with default file name .config
cp output/config/linux-sunxi-current.config userpatches/
./compile.sh BOARD=orangepione BRANCH=current kernel




While it was pretty straight forward and convenient for causal users to create either own custom firmware packages or whole images with customized kernels using one switch only, from a developers point of view this was supposedly a horrible behavior.

I won’t go into detail asking the now obvious why question, last but not least because I am no developer myself and do not fully understand the reasons behind. Instead I will focus on the new way go to and leave the answer to an actual professional:

armbian/build has been converted into a distributed build system: instead of a single monolithic artifact (the full image), Armbian build now operates on smaller units called “artifacts”: the kernel, u-boot, firmware, rootfs, and then finally the full image.
Each of those has its version calculated beforehand based on its would-be contents, and looked up in both a local and remote cache (OCI registry), allowing users to re-use artifacts across builds and to use the best hardware available for each (kernel builds benefit from multiple cores, while rootfs benefits from fast single cores of the matching architecture).

Since the kernel .config is one of the most important components of the kernel version, having a configuration step that changes it during the build has been deprecated.

– Ricardo Pardini

One thing I like to mention here is that the new behavior makes some research prior necessary because the new way of configuring the kernel requires both the BRANCH and the BOARD argument to be provided with compile.sh. The ability to conveniently choose from a list is no longer available when using a command like kernel-config. I will cover how to do this as well.

Basically the old KERNEL_CONFIGURE switch has been broken down into two steps:

  • 1: create the modified kernel config
  • 2: build the custom config

Let’s go into detail!


1: Create the modified kernel config

If not done already prepare your build environment and checkout a fresh copy of the build framework like described in the documentation.

We need to figure two things:

  • the BOARD name of the hardware you plan to customize your kernel
  • and which kernel BRANCH or branches available are for it.

To do this we have to take a look at config/boards/ in the build directory.

In this example we go for an Orange Pi One board just like in the tl;dr comment mentioned above.
The relevant file is orangepione.conf1. This gives us the first clue:
The filename, not counting its file extension, represents the BOARD name.
So in this case it is orangepione.

The second clue we find inside this file. So let’s cat it:

# Allwinner H3 quad core 512MB RAM SoC
BOARD_NAME="Orange Pi One"

function post_config_uboot_target__extra_configs_for_orangepi_one() {
	display_alert "$BOARD" "set dram clock" "info"
	run_host_command_logged scripts/config --set-val CONFIG_DRAM_CLK "624"
	run_host_command_logged scripts/config --set-val CONFIG_DRAM_ZQ "3881979"
	run_host_command_logged scripts/config --enable CONFIG_DRAM_ODT_EN

As we can see the KERNEL_TARGET has three branches we can choose from2.
In most cases using current is a solid choice.

Our list of clues is complete.
We can now start the configuring process by executing:

./compile.sh BOARD=orangepione BRANCH=current kernel-config

Here we make our adjustment as needed and then save the modified config with its default name .config.

While the script exports the custom config file and tells us where it has been put,
the core config (shipped with the build framework to say) has been modified as well. This allows developers to create a git diff and thinks like this to commit and send a pull request.3
This however needs to be accounted for when future modifications for different scenarios are planned so the stock configuration needs to be restored beforehand.


2: Build the custom config

Now we have to decide if we want the firmware packages only or a full bootable image. Depending on our choice we execute either

./compile.sh BOARD=orangepione BRANCH=current kernel


./compile.sh BOARD=orangepione BRANCH=current


Wrapping up

The same procedure should work for U-Boot customization as well by using
uboot-config instead of kernel-config.

  1. Sometimes it can be much less trivial to find the correct BOARD name for a SBC since its actual name and BOARD might quite differ. In this case it is necessary to search for the matching name inside these files. For example we have a JetHub D1 SBC but which file represents BOARD? Use a command like this to find it:
    find config/boards/ -type f -exec grep "JetHub D1" '{}' \; -print
    This reveals the matching config file is jethubj100.conf and therefore BOARD is jethubj100↩︎

  2. While not all boards following this logic, legacy usually represents an older LTS kernel release, current, as the name implies the current LTS kernel and edge the most recent kernel, if not even a RC kernel. ↩︎

  3. This was mentioned by Ricardo Pardini while proofreading. Thank you! ↩︎