Friday, October 17, 2014

Compiling and Installing the Linux Kernel

The first few times I tried to boot from a custom kernel, I faced a lot of problems and found documentation to be a spread out in different places and also somewhat incomplete depending on the specific distribution. This guide will document the steps to be followed to get a custom kernel running, focusing on Ubuntu and Debian derivatives. The steps followed however, are almost completely, distribution neutral, and hence should be applicable for whichever distro you may be using.


I will be using the kernel tree from for this post. If you have a specific version, then great! Otherwise, you can clone the kernel tree using:
$ git clone
(This requires git, but you have that installed, don't you?)


For the compilation process, we first need to create the configuration file. This file specifies the various properties of the kernel, including which modules to be compiled, which to be included in the image, and which to be loaded dynamically. You can, depending on your configuration, go for a modular or a monolithic kernel from here. You can either create one using the kernel utilities, or simply use the one that comes with your distro and which the current kernel is using.
$ ls /boot/*config*`uname -r` -a
Copy the config file to your kernel root directory and rename it to .config
$ cp /boot/*config*`uname -r` ./.config
Now, run make to verify the configuration file for the current distribution. You will see a number of new options that have been added into the new kernel. I would suggest simply going with the defaults on most of them, unless you know what you are doing.
$ make oldconfig
We are ready to start compiling. You simply need to run make. To make things go faster, we can make make spawn multiple jobs. Usually, 2 per core is a good number to go by. I also like to time how long it takes, hence my command is similar to:
$ time make -j$((`nproc`*2)) > ./.build-feedback
The output redirection will save all the build feedback into a file that you come back and read when compilation is over. Oh yes, it's gonna be awhile.


Assuming there weren't any errors during compile time, you are good to install your flashy new kernel. The installation process is simple and involves installing modules, copying files to the correct directories and updating your bootloader.

Installing modules is a one liner:
% make modules_install
Note at the end of the install process, you will see a version number. Copy it, or use the following command:
$ KVER=`ls /lib/modules -ht | head -n 1`
Now, we need to copy the kernel image to the /boot directory. You will find it under /arch corresponding to your machine architecture. For seeing your machine architecture, run:
$ uname -m
Or we can copy the correct image with this one liner:
% cp ./arch/`uname -m`/boot/bzImage /boot/vmlinuz-$KVER
Next, we need to copy the system map, which stores information regarding the built modules and their relative addresses for dynamic loading.
% cp /boot/$KVER
Next, comes the config file.
% cp .config /boot/config-$KVER
If your distro is configured to use an initramfs, which can easily be confirmed by the presence (or absence) of initrd files in /boot, then you need to generate it using:
% update-initramfs -c -k $KVER
The last step is updating GRUB, so that the new kernel can be added to the boot list.
% update-grub2


Let's boot into the new kernel now. As the new kernel should be at the top of the GRUB boot list, you should automatically be booted into it. Once you have a usable desktop, which may or may not happen, open up a terminal, or switch to a virtual terminal, and verify your install version (should match with KVER).
$ uname -r 
Congratulations! You are now using your compiled kernel.

This process can take upto 2.5 hours the first time you attempt it, with successive attempts taking upto an hour depending on your workstation. Nonetheless, it is an exciting process and your first step transitioning towards kernel development.

No comments:

Post a Comment