hhl/content/news/to-initramfs-or-not-to-initramfs.md
Nathan Fisher 7fe7ec9c68 Added post
2021-03-25 09:14:27 -04:00

58 lines
3.5 KiB
Markdown

+++
title = "To Initramfs or Not to Initramfs"
date = 2021-03-23
[taxonomies]
tags = ["Boot", "Initramfs", "Cross Compile"]
+++
Once upon a time booting Linux was simpler. Well, everything was simpler to be
honest. But the bootloader, after initializing a few key things, basically just
passed control over to the kernel, which was expected to have capability built in
to mount the root filesystem without having to load any further modules.
<!-- more -->
This can actually still be done. It is a matter of compiling your own kernel with
support for your specific hardware. Unfortunately, if one wishes to compile a
kernel for distribution this can lead to a rather kitchen sink configuration in
order to include support for every possible sane hardware configuration. This in
turn leads to a larger kernel image.
The solution employed by most distributions is the use of an initramfs, which is
basically a minimal root filesystem which is loaded into memory, which then loads
whatever modules are required to bootstrap your system, mounts the real root and
then calls the *switch_root* binary to move into the real root and run init. The
initramfs is generally a compressed cpio archive on disk, and will usually
include at minimum a statically compiled busybox executable, an init script and
some kernel modules.
Often, however, it is desirable to also start udev while still in the initramfs
so that we can do things like specify the root disk by uuid in /etc/fstab, as
the kernel only makes the device nodes /dev/sdx, and udev then creates the links
in /dev/disk/by-uuid. However, udev also pulls in libkmod from the kmod package
and libblkid from util-linux. So we end up with those libraries plus glibc in
the initrd. It's at this point that the 'minimal' description begins to be a
stretch. I did attempt to compile udev statically. However, kmod stright refuses
to be compiled statically with it's current build system so that was a show
stopper right off the bat. Is there a technical reason? Well I haven't dug too
deaply yet but I suspect the functionality to build a static library was just
never implemented due to static linking being frowned upon my most conventional
thinking these days.
Right now I'm toying with a compromise approach, and compiling all of the needed
libraries and programs against musl libc. Overall this shrinks the size from
around 20M uncompressed (on my Arch installation) to around 10M. I'm basing the
init script off of the one used by Artix Linux ,which is a fork of Arch without
systemd. I think this is a nice gain, as it's half the amount of data for the
kernel to decompress and musl linked binaries do actually run a little faster.
I have a separate project which is not yet online to build a range of cross
compilers which is suitable for building against musl on every arch that
HitchHiker supports. However, at the moment I have not automated the building of
kmod, libblkid, eudev and busybox, or the creation of an initrd. Even when I do,
I don't think that code will ship with the default source tree, as I would like
to encourage users to build a kernel for their machine and run without an
initramfs. I will most likely ship the default install tarballs with an initramfs
however, just to make booting a little bit more generic and support a wider range
of hardware. If and when I have the initrd creation a little more automated I'll
post it online as a separate project. I'll probably also make the toolchains
available in binary form as compressed tarballs at that time.