58 lines
3.5 KiB
Markdown
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.
|