In another episode of my experimentation, I was back again tinkering with my X230. This time I tried out Buildroot.
Buildroot is a set of tools to build a tiny complete Linux system from scratch. From the tarball, you can create a bzImage with integrated initramfs that has everything you want to include (even the X server if you want to).
At the heart of Buildroot is the Linux kernel itself, the C library of choice (of which I picked musl), as well as busybox -- an all-in-one command-line utilities that includes the shell.
If you happen to be running OpenWRT on some ouf your routers, the OpenWRT is actually based on Buildroot. This is how they're able to create system small enough to fit that router ROM with only megabytes in size.
Preparation
I was building it on my Debian system I've been using in my previous articles.
For the Buildroot package, I was using the version 2022.02.6.
To ensure I got all the necessary build requirements, I ran:
$ apt install libssl-dev libelf-dev pahole
Configuration
I first configured it by running make menuconfig
. I was then presented by this menu.
These are the configurations I did:
- "Target options" menu:
- set "Target architecture" to
x86_64
- set "Target Architecture Variant" to
sandybridge
- set "Target architecture" to
- "Toolchain" menu
- set "C library" to
musl
.
- set "C library" to
- "Kernel" menu
- ticked "Linux Kernel"
- set "Kernel configuration" to "Using a custom (def)config file"
- set "Configuration file path" to
config-linux
- ticked the options for OpenSSL, libelf, and pahole
- "Target packages" menu
- set "BusyBox configuration file to use?" to
config-busybox
- set "BusyBox configuration file to use?" to
Linux kernel
To prompt the menuconfig for Linux kernel, I ran make linux-menuconfig
. But before I was able to run it, I needed the file config-linux
(the file name was determined by the buildroot makeconfig). So I created an empty file by running touch config-linux
.
After I was happy with the Linux kernel configuration, I ran make linux-update-config
to update the config-linux
file.
Busybox
Same goes with the Linux kernel, I needed the config file before I ran the menuconfig.
$ touch config-busybox
$ make busybox-menuconfig
$ make busybox-update-config
Build process
After configuring, the Buildroot was ready to build a bootable image. I ran make -j8
and waited for a bit.
I was building the whole thing on the X230 itself, with its i7-3520M. While there are much faster machines out there, this one is quite fast for this purpose. At least with this, I didn't have to wait a long time.
The resulting image is on output/images/bzImage
.
Testing
To test that it's usable, I simply booted from it using GRUB2, which I already have.
I only needed to have the bzImage
under /boot
and have it listed on the /boot/grub/grub.cfg
.
First the bzImage
was copied into the /boot
directory by running sudo cp output/images/bzImage /boot/
.
Then the grub.cfg
was updated accordingly -- I wouldn't do it manually as it would get overwritten on each update.
GRUB2 config
The clean way of doing it was thru /etc/grub.d/40_custom
. So I opened up that file (as root) and added:
menuentry 'Buildroot testing' {
set gfxmode=1280x1024
load_video
insmod gfxterm
set root='hd0,msdos1'
echo 'Loading Linux'
linux /bzImage quiet
}
This way, the custom entry would always be there on the boot menu.
Finally, to update the grub.cfg
, I ran sudo update-grub2
.
Modifications
I ended up making several attempts of adjustments in order to include the features I wanted while keeping the size down. For that, I reran the menuconfig commands, backing up the config
, config-linux
, and config-busybox
files each time (and then updating them, of course).
Running make clean
is important before rebuilding to ensure a clean build each time. Do note that the all the build stuff will get removed, including the toolchain. So if you run the clean and you wanna configure the Linux kernel, the toolchain is gonna have to be rebuilt first.
Sometimes, nuking everything by running make distclean
is necessary. Just got to ensure the configs are backed-up, especially the busybox config, which gets removed everytime this command runs.
You should also backup the dl
folder before make distclean
to save time. That way, there's no need to download the packages on each build. Just make sure to copy the folder back afterwards.
After each build process I simply copied the resulting bzImage
to /boot
without doing anything to the GRUB as it's already pointing there. Occasionally, I'd backup the old bzImage
(and its corresponding configs) when I feel like it's a good build (i.e. able to access the shell with it).
Closing
Simply running the above commands seem quite simple, but getting the configs to fit the need is definitely not for the faint of hearts. The sight of menuconfig screen can definitely be daunting, especially for the uninitiated.
I happened to have some experience configuring and building my own kernel. Even for myself, it's not always easy to get everything right.
The buildroot config itself is just a matter of what extra features to include (aside from the ones covered above, at least). The busybox config The Linux kernel config, on the other hand, can be quite tricky at times.
This is especially true for the device drivers. Missing some drivers can yield inoperable system such as not being able to use the keyboard, having blank screen. Missing some others can hinder certain functionalities that can render the system useless depending on the context (e.g. networking, ACPI, disk access, audio).
While the default configuration can be said to work, it is rarely optimal. So more often than not, you may find yourself tweaking it here and there. The difficulty level would rise when you want a minimum build, as removing certain parts always have potential in breaking the system.
With that said, I've included the config files below: