Raspbian/Raspberry PI OS with initrd
Posted on January 25, 2021 with tags tech, debian, raspberrypi. See the previous or next posts.
Can't wait for plain Debian on Raspberry PI!
Background
While Raspbian, ahem, Raspberry PI OS is mostly Debian, the biggest difference is the kernel, both in terms of code and packaging.
The packaging is weird since it needs to deal with the fact that
there’s no bootloader per se, the firmware parses /boot/config.txt
and depending on the setting of 64bit and/or kernel
line, it loads a
specific file. Normally, one of kernel7.img
, kernel7l.img
or
kernel8.img
. While this configuration file supports an initrd, it
doesn’t have a clean way to associate an initrd with a kernel, but
rather you have to (like for the actual kernel) settle on a hard-coded
initrd name.
Due to this, the normal way of using an initrd doesn’t work, and one has to do two things:
- enable building initrd’s at all
- settle on the naming for the initrd
- ensure the initrd is updated correctly
There are quite a few of forum threads about this, but there’s no official support for this. The best link I found was this Stack Exchange post, which goes most of the way, but fails at the third point above.
My trivial solution
Instead of naming tricks the above post suggests, I settled on having a fixed name. It risks boot failure when the kernel architecture will change, which could be worked around with hard-coded kernel too, but I haven’t done that yet.
First, enable initrd creation/update in
/etc/default/raspberrypi-kernel
, like the post says. Uncomment
INITRD=yes
, but not the RPI_INITRD
. This will enable creating/updating
the initrd when the kernel package is installed and/or other packages
trigger it via hooks.
Second, naming: choose an initrd name. I have simply this in my config.txt
:
initramfs initrd.img followkernel
So the value is fully hard-coded, and the actual work is done in the next part.
Last, add an initramfs
-hook in (e.g.)
/etc/initramfs/post-update.d/rpi-initrd
. Note that, by default
(unless other packages have created it), the /etc/initramfs
directory doesn’t exist. It’s not the confusingly-named
/etc/initramfs-tools/
directory, which is related to building the
initrd, but rather to doing things with the (already built)
initrd. This directory is briefly explain in the Debian
kernel-handbook
guide.
This is my contents:
#!/bin/bash
ABI="$1"
INITRD="$2"
BOOTDIR="$(dirname "$INITRD")"
# Note: the match below _must_ be synced with the boot kernel
if [[ "$ABI" == *-v8+ ]]; then
echo "Building v8l+ image, updating top initrd"
cp -p "$INITRD" "$BOOTDIR/initrd.img"
fi
This script seems to me much simpler, so in principle less chance of
bugs, than all the renaming and editing config.txt
I saw in that
stack exchange post. As far as I know, all one needs to care about is
to sync the ABI passed to this hook with the kernel one is running,
and since there is only one kernel version installed at a time on
Raspbian (as there’s no versioning in the kernel names), this should
work correctly.
With this hook, the update also works correctly when packages trigger initrd updates, not only when new kernels are installed.
Note that the cp
there is needed since the book partition is FAT, so
no symbolic links/hard links allowed.
Happy initrd’ing!