Feb 10, 2024 by Thibault Debatty | 308 views
A regular Linux user will probably never have to compile it's own Linux kernel. But doing so is actually a great way to discover the features and working of the Linux kernel. So in this blog post we will guide you to compile a small kernel, create a minimal root filesystem that fits into memory, and finally create a micro-Linux system based on Busybox...
Typically, the Linux kernel only has a few built-in drivers. Additional drivers are compiled as modules that must be separately loaded in memory. Some of these modules may be required to mount the root filesystem. Hence the Linux boot process typically has 2 step :
The initramfs is a compressed (gz) cpio archive. Cpio is an archive format similar to tar, but is much more simple and requires only little code in the kernel . There is an older but similar mechanism called the initial RAM disk or initrd, that uses a full disk image as inital firlesystem. Still now, some bootloaders, and qemu (as we will see below) use the parameter
-initrd to load the initramfs.
In this blog post, we compile a small Linux kernel, and we will create a minimal initramfs archive that contains the basic Linux command line tools. This allows to create a minimal system running directly from memory.
To build the kernel and test with qemu, you will need a few tools and libraries:
sudo apt install -y build-essential libncurses-dev libelf-dev libssl-dev
And, to test with qemu:
sudo apt install qemu-system-x86
So, the first step consists in downloading, configuring and building the kernel....
Download and extract the kernel sources. For this blog post we will use the current longterm kernel version (6.6.16):
tar -xvf linux-6.6.16.tar.xz
The Linux kernel has a lot of features and configuration options. It can be quite challenging to find the correct options required to build a bootable kernel. Luckily there are different possibilities to create a sound starting point:
cp /boot/config-$(uname -r) .config
In this blog post, we will test the kernel using
qemu, so we can start with a simple default kernel:
Then, we can add or remove features using
This will open a ncurses menu that allows to select kernel features.
As a bare minimum, make sure the following options are enabled:
When done, save your kernel configuration and exit.
Hint: you can hit
/ to search for a given feature.
You can now compile your kernel with
make -j 8 bzImage
-j 8 tells make to run 8 jobs in parallel.
After a few minutes, the build process should end with
Kernel: arch/x86/boot/bzImage is ready. Let's copy the kernel to the root of our project:
cp arch/x86_64/boot/bzImage ../
BusyBox is a single binary that provides most common Unix/Linux utilities. It was specifically created for embedded systems with very limited resources. The single binary takes roughly 2,5MB and implements a simplified version of almost 300 common Unix commands. It is thus perfect for creating micro systems.
tar -xvzf 1_36_0.tar.gz
Again, we will use the menu configuration:
This time, make sure to enable
Settings ---> Build static binary (no shared libs)
After saving, we can compile:
make -j 8
busybox binary and links will be installed in
We can now create the structure of the root filesystem:
mkdir -p initramfs/bin initramfs/sbin initramfs/etc initramfs/proc initramfs/sys initramfs/dev initramfs/usr/bin initramfs/usr/sbin
Copy the busybox binary and links:
cp -a busybox-1_36_0/_install/* ./initramfs
Create the init script initramfs/init with the following content:
mount -t devtmpfs devtmpfs /dev
mount -t proc none /proc
mount -t sysfs none /sys
Welcome to Micro Linux!
Boot took $(cut -d' ' -f1 /proc/uptime) seconds
Make the init script executable:
chmod +x initramfs/init
And finally, create the compressed initramfs archive:
find . -print0 | cpio --null -ov --format=newc | gzip -9 > ../initramfs.cpio.gz
We can now test the micro system with qemu:
qemu-system-x86_64 -kernel bzImage \
-initrd initramfs.cpio.gz -nographic \
You can stop qemu by hitting
ctrl + a and then
Once this is working, you can continue by testing other features and modify the init script...
This blog post is licensed under CC BY-SA 4.0