Monday 19 December 2016

How to Compile Linux Kernel from Source to Build Custom Kernel

Linux kernel is the life force of all Linux family of operating systems including Ubuntu, CentOS, and Fedora.

For most part, you don’t need to compile the kernel, as it is installed by default when you install the OS. Also, when there is a critical update done to the kernel, you can use yum, or apt-get to update the kernel on your Linux system.

However you might encounter certain situation, where you may have to compile kernel from source. The following are few situation where you may have to compile Kernel on your Linux system.
  • To enable experimental features that are not part of the default kernel.
  • To enable support for a new hardware that is not currently supported by the default kernel.
  • To debug the kernel
  • Or, just to learn how kernel works, you might want to explore the kernel source code, and compile it on your own.
In this tutorial, we’ll explain how to compile Linux kernel from source.
Also, please note that if you just want to compile a driver, you don’t need to compile the kernel. You need only the linux-headers package of the kernel.

1. Download the Latest Stable Kernel

The first step is to download the latest stable kernel from kernel.org.
# cd /usr/src/

# wget https://www.kernel.org/pub/linux/kernel/v3.x/linux-3.9.3.tar.xz

2. Untar the Kernel Source

The second step is to untar the kernel source file for compilation.
# tar -xvJf linux-3.9.3.tar.xz

3. Configure the Kernel

The kernel contains nearly 3000 configuration options. To make the kernel used by most people on most hardware, the Linux distro like Ubuntu, Fedora, Debian, RedHat, CentOS, etc, will generally include support for most common hardware. You can take any one of configuration from the distro, and on top of that you can add your own configuration, or you can configure the kernel from scratch, or you can use the default config provided by the kernel.# cd linux-3.9.3
# make menuconfig
The make menuconfig, will launch a text-based user interface with default configuration options as shown in the figure. You should have installed “libncurses and libncurses-devel” packages for this command to work.

We will use the default config provided by the kernel. So select “Save” and save the config in the file name “.config”.
The following is a sample of the “.config” file:
CONFIG_MMU=y
CONFIG_NEED_DMA_MAP_STATE=y
CONFIG_NEED_SG_DMA_LENGTH=y
CONFIG_GENERIC_ISA_DMA=y
CONFIG_GENERIC_BUG=y
CONFIG_GENERIC_HWEIGHT=y

4. Compile the Linux Kernel

Compile the main kernel:
# make
Compile the kernel modules:
# make modules
Install the kernel modules:
# make modules_install
At this point, you should see a directory named /lib/modules/3.9.3/ in your system.

5. Install the New Kernel

Install the new kernel on the system:
# make install
The make install command will create the following files in the /boot directory.
  • vmlinuz-3.9.3 – The actual kernel
  • System.map-3.9.3 – The symbols exported by the kernel
  • initrd.img-3.9.3 – initrd image is temporary root file system used during boot process
  • config-3.9.3 – The kernel configuration file
The command “make install” will also update the grub.cfg by default. So we don’t need to manually edit the grub.cfg file.

6. Boot Linux to the new Kernel

To use the new kernel that you just compiled, reboot the system.
# reboot
Since, in grub.cfg, the new kernel is added as default boot, the system will boot from the new kernel. Just in case if you have problems with the new kernel, you can select the old kernel from the grub menu during boot and you can use your system as usual.
Once the system is up, use uname command to verify that the new version of Linux kernel is installed.
$ uname -r
3.9.3

ARMKernelCrossCompile

The following instructions show how to properly download, tweak and cross compile an Ubuntu ARM kernel from an x86 Ubuntu host.

Vanilla Ubuntu armhf omap4 kernel compilation

First install the necessary tools for source code management and compilation:
sudo apt-get install fakeroot build-essential kexec-tools kernel-wedge gcc-arm-linux-gnueabihf
sudo apt-get install gcc-arm-linux-gnueabihf libncurses5 libncurses5-dev libelf-dev 
sudo apt-get install asciidoc binutils-dev
sudo apt-get build-dep linux
Then download the code, switch to the omap4 branch and kick a build:
git clone git://kernel.ubuntu.com/ubuntu/ubuntu-precise.git

cd ubuntu-precise
git checkout -b ti-omap4 origin/ti-omap4

export $(dpkg-architecture -aarmhf); export CROSS_COMPILE=arm-linux-gnueabihf-
fakeroot debian/rules clean
fakeroot debian/rules binary-omap4
At the end of the process you will have an header and an image .deb in the upper level directory:
ls ../*.deb
linux-headers-3.2.0-1410-omap4_3.2.0-1410.13_armhf.deb  linux-image-3.2.0-1410-omap4_3.2.0-1410.13_armhf.deb

Config modify an Ubuntu omap4 kernel

Pretty much as above, but between the 'fdr clean' and 'fdr binary-omap4' you issue:
fakeroot debian/rules editconfigs
where 'fdr' stands for 'fakeroot debian/rules'.
Choose the architecture you want to do modifications (armhf in our case):
dh_testdir;
/bin/bash -e debian/scripts/misc/kernelconfig editconfigs
Do you want to edit config: armel/config.flavour.omap4? [Y/n]n
Running splitconfig.pl for armel

Reading config's ...
  processing config.common.armel ... done.
  processing config.flavour.omap4 ... done.

Merging lists ... 
   processing config.common.armel ... done.
   processing config.flavour.omap4 ... done.

Creating common config ... done.

Creating stub configs ...
  processing config.common.armel ... done.
  processing config.flavour.omap4 ... done.
Do you want to edit config: armhf/config.flavour.omap4? [Y/n] Y
do the config changes, save and 'fdr binary-omap4' to start a compilation of the new kernel.

FAQ

1) What's the difference between armel and armhf? And which should i pick?
Armhf requires a cpu with an FPU unit, while armel doesn't strictly enforce it. As a rule of thumb, remember that from Precise onward Ubuntu uses armhf, while Oneiric and previous were armel based.
To create a package for armel, you need the armel toolchain (gcc-arm-linux-gnueabi) and an armel environment:
sudo apt-get install gcc-arm-linux-gnueabi

export $(dpkg-architecture -aarmel); export CROSS_COMPILE=arm-linux-gnueabi-
the rest is identical to the armhf case.
2) How do i mark my custom kernel to distinguish it form the stock one?
It's possible to a add a suffix to kernel name modifying the changelog file. So, in our example, _before_ the 'fdr clean', open debian.ti-omap4/changelog, look for the first line and change it from:
linux-ti-omap4 (3.2.0-1410.13) precise; urgency=low
to
linux-ti-omap4 (3.2.0-1410.13~mycustomkernel) precise; urgency=low
This way the resulting .deb packages will have the custom "~mycustomkernel" suffix in their names. Remember, only letters and numbers are allowed.
3) Ok, but what about my Beagle/XM? How do i compile a kernel for an omap3 board?
Omap3 support is fully present in mainline, so stay in the master branch (do not switch to ti-omap4) and:
fakeroot debian/rules binary-omap
4) So far all the examples were Precise based, what about the other releases?
Feel free to pick the release you prefer from http://kernel.ubuntu.com/git (see http://wiki.ubuntu.com/Kernel/Dev/KernelGitGuide for more info).
5) After export $(dpkg-architecture -aarmhf) i get a warning, what's that?
Yes, it's something like dpkg-architecture: warning: Specified GNU system type arm-linux-gnueabi does not match gcc system type i686-linux-gnu and it's harmless. Forget about it.
6) How do i compile a vanilla/upstream arm kernel that works with an Ubuntu userspace?
i assume your cwd is a checkout of Linus git tree and we are compiling an armhf kernel for an omap3 board.
a) make ARCH=arm omap2plus_defconfig
b) edit .config and modify the following options:
CONFIG_DEVTMPFS=y
CONFIG_DEVTMPFS_MOUNT=y
CONFIG_EXT4_FS=y
CONFIG_EXT4_FS_XATTR=y
Since 3.5 EHCI is broken for omap3 and was disabled upstream, to enable it again:
CONFIG_USB_EHCI_HCD=y
CONFIG_MFD_OMAP_USB_HOST=y
CONFIG_USB_EHCI_TT_NEWSCHED=y
CONFIG_USB_EHCI_HCD_OMAP=y
CONFIG_TWL4030_USB=y
c) make ARCH=arm CROSS_COMPILE=/usr/bin/arm-linux-gnueabihf- uImage
d) copy arch/arm/boot/uImage to the sd card first partition overwriting ubuntu stock uImage
e) insert the sd card, and reboot