Raspbian/Raspberry PI OS with initrd

Posted on January 25, 2021 with tags , , . 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!