Build yourself a Linux
This started out as a personal project to build a very small Linux based operating system that has very few moving parts but is still very complete and useful. Along the way of figuring out how to get the damn thing to boot and making it do something useful I learned quite a lot. Too much time has been spent reading very old and hard to find documentation. Or when there was none, the source code of how other people were doing it. So I thought, why not share what I have learned.
This git repo contains a Makefile and scripts that automate everything that will be explained in this document. But it doesn't necessarily do everything in the same order as it's explained. You can also use that as reference if you'd like.
The Linux Kernel
The kernel is the core component of our operating system. It manages the processes and talks to the hardware on our behalf. You can retrieve a copy of the source code easily from kernel.org. There are multiple versions to choose from, choosing one is usually a tradeoff between stability and wanting newer features. If you look at the Releases tab, you can see how long each version will be supported and keeps receiving updates. So you can usually just apply the update or use the updated version without changing anything else or having something break.
So just pick a version and download the tar.xz file and extract it with
tar -xf linux-version.tar.xz. To build the kernel we obviously need a compiler and some build tools. Installing
build-essential on Ubuntu (or
base-devel on Arch Linux) will almost give you everything you need. You'll also need to install
bc for some reason.
The next step is configuring your build, inside the untarred directory you do
make defconfig. This will generate a default config for your current cpu architecture and put it in
.config. You can edit it directly with a text editor but it's much better to do it with an interface by doing
make nconfig (this needs
libncurses5-dev on Ubuntu) because it also deals with dependencies of enabled features. Here you can enable/disable features and device drivers with the spacebar.
* means that it will be compiled in your kernel image.
M means it will be compiled inside a separate kernel module. This is a part of the kernel that will be put in a separate file and can be loaded in or out dynamically in the kernel when they are required. The default config will do just fine for basic stuff like running in a virtual machine. But in our case, we don't really want to deal with kernel modules so we'll just do this:
sed "s/=m/=y/" -i .config. And we're done, so we can simply do
make to build our kernel. Don't forget to add
N the number of cores because this might take a while. When it's done, it should tell you where your finished kernel is placed. This is usually
arch/x86/boot/bzImage in the linux source directory for Intel computers.
Other useful/interesting ways to configure the kernel are:
make localmodconfigwill look at the modules that are currently loaded in the running kernel and change the config so that only those are enabled as module. Useful for when you only want to build the things you need without having to figure out what that is. So you can install something like Ubuntu on the machine first, copy the config to your build machine, usually located in /boot, Arch Linux has it in gzipped at /proc/config.gz). Do
lsmod > /tmp/lsmodfile, transfer this file to you build machine and run
LSMOD=lsmodfile make localmodconfigthere after you created
.config. And you end up with a kernel that is perfectly tailored to your machine. But this has a huge disadvantage, your kernel only supports what you were using at the time. If you insert a usb drive it might not work because you weren't using the kernel module for fat32 support at the time.
make localyesconfigis the same as above but everything gets compiled in the kernel instead as a kernel module.
make allmodconfiggenerates a new config where all options are enabled and as much as possible as module.
make allyesconfigis same as above but with everything compiled in the kernel.
make randconfiggenerates a random config...
You can check out
make help for more info.
All these tools you know and love like
rm and so on are commonly referred to as the 'coreutils'. Busybox has that and a lot more, like utilities from
util-linux so we can do stuff like
mount and even a complete init system. Basically, it contains most tools you expect to be present on a Linux system, except they are a slightly simplified version of the regular ones.