Custom Debian Kernel

- 3 mins read

Working with embedded systems often requires customizing the operating system as per the specific requirements of the project. This includes customizing the root filesystem, the kernel, the disk image etc.

The first step towards the customisation of the linux kernel is to be able to compile the kernel. Once the debian kernel compilation steps are figured out, we can proceed with the customisation steps. In this article we explain the steps to compile the debian kernel from source inside a docker container.

The debian kernel is configured to generate images for a wide variety of architechures and for each architechure there can be multiple featureset and flavours. For example for the amd64 architechure, we will compile the none featureset and the cloud-amd64 flavour.

Booting a debian bookworm docker

To compile a debian kernel from source we start with the creation of a debian bookworm environment.

Disable kernel debug symbol packages to reduce build time: export DEB_BUILD_PROFILES='pkg.linux.nokerneldbg pkg.linux.nokerneldbginfo'

Several build profiles are understood and supported:

  • stage1: Needed when bootstrapping an architecture. A stage1 build produces only the linux-libc-dev package and has no host build-dependencies.

  • nodoc: Exclude most documentation

  • noudeb: Exclude installer udeb packages

  • pkg.linux.notools: Exclude userland tool packages (linux-kbuild-<version>, linux-perf, etc.)

  • pkg.linux.mintools: Build minimal set of userland tool packages (linux-kbuild-<version>, linux-bootwrapper-<abiname> on powerpc/ppc64)

  • pkg.linux.nokernel: Exclude kernel image and header packages

  • pkg.linux.nokerneldbg: Exclude kernel debug packages

  • pkg.linux.nokerneldbginfo: Build kernel without debug symbols (also disables BTF)

  • pkg.linux.nosource: Exclude source binary package (linux-source-<version>)

  • cross: Needed when cross-building.

  • nopython: Disable Python bindings. This currently disables building the linux-perf-<version> package, as the perf program embeds Python.

  • pkg.linux.nometa: Exclude most meta-packages. The linux-compiler-* and linux-headers--all packages can still be built.

  • pkg.linux.quick: Perform a limited build that should provide good coverage yet be quick enough for use in CI.

Inside the debian docker we setup a linux directory into which the sources will be downloaded by apt. For this we give apt the required permissions:

    mkdir linux
    chown -Rv _apt:root linux
    chown -Rv _apt:root /var/cache/apt/archives/partial/
    chmod -Rv 700 /var/cache/apt/arch

After this we download the source files:

    cd linux
    apt update
    apt source linux

This downloads and extracts the linux sources in a directory linux-6.1.124. Next we trigger build for amd64 architechure, featureset none and flavour cloud-amd64.

    cd linux-6.1.124
    fakeroot make -f debian/rules.gen binary-arch_amd64_node_cloud-amd64 -j3

This created the following files:

drwxr-xr-x 28 root root 4.0K Feb 26 04:44 linux-6.1.124
-rw-r--r--  1 root root 1.2M Feb 26 05:27 linux-headers-6.1.0-30-cloud-amd64_6.1.124-1_amd64.deb
-rw-r--r--  1 root root  22M Feb 26 05:27 linux-image-6.1.0-30-cloud-amd64-unsigned_6.1.124-1_amd64.deb

localmodconfig

"make localmodconfig" Create a config based on current config and loaded modules (lsmod). Disables any module option that is not needed for the loadedmodules.

To create a localmodconfig for another machine, store the lsmod of that machine into a file and pass it in as a LSMOD parameter.

               target$ lsmod > /tmp/mylsmod
               target$ scp /tmp/mylsmod host:/tmp

               host$ make LSMOD=/tmp/mylsmod localmodconfig

The above also works when cross compiling.

 "make localyesconfig" Similar to localmodconfig, except it will convert
                       all module options to built in (=y) options.