Translation(s): none


How initramfs works

The basic initramfs is the root filesystem image used for booting the kernel provided as a compressed cpio archive.

This basic initramfs image may be prepended with an uncompressed cpio archive holding the microcode data loaded very early in the boot process.

At boot time, the kernel performs the followings:

Much of the kernel initialization and bootstrap code can then be moved into this disk and run in user mode. Tasks like finding the real root disk, boot-time networking setup, handling of initrd-style ramdisks, ACPI setup, etc, will be shifted out of the kernel in this way.

An obvious advantage of this scheme is that the size of the kernel code itself can shrink. That does not free memory for a running system, since the Linux kernel already dumps initialization code when it is no longer needed. But a smaller code base for the kernel itself makes the whole thing a little easier to maintain, and that is always a good thing. But the real advantages of initramfs are:

It includes:

The kernel has currently 3 ways to mount the root filesystem:

  1. all required device and filesystem drivers compiled into the kernel, no initrd. init/main.c:init() will call prepare_namespace() to mount the final root filesystem, based on the root= option and optional init= to run some other init binary than listed at the end of init/main.c:init().
  2. some device and filesystem drivers built as modules and stored in an Initrd. The initrd must contain a binary '/linuxrc' which is supposed to load these driver modules. It is also possible to mount the final root filesystem via linuxrc and use the pivot_root syscall. The initrd is mounted and executed via prepare_namespace().

  3. using initramfs. The call to prepare_namespace() must be skipped. This means that a binary must do all the work. Said binary can be stored into initramfs either via modifying usr/gen_init_cpio.c or via the new initrd format, an cpio archive. It must be called "/init". This binary is responsible to do all the things prepare_namespace() would do.

To remain backwards compatibility, the /init binary will only run if it comes via an initramfs cpio archive. If this is not the case, init/main.c:init() will run prepare_namespace() to mount the final root and exec one of the predefined init binaries

How to inspect initramfs

The initramfs-tools-core package provides lsinitramfs to list files inside the initramfs and unmkinitramfs to extract files from the initramfs.

Alternatively, you can do the following (assuming path/to/initrd already exists as empty working directory):

The microcode cpio archive size can be independently checked by cpio -t </initrd.img >/dev/null

(This manual method somehow worked for me at one point. But this is not reliable. /usr/bin/lsinitramfs has a comment "cpio won't tell us the true size".)

Please note Debian currently use gzip as the compression method and the above method assumes so. Ubuntu seems to start using LZ4 as of March 2018. initramfs-tools in Debian supports LZ4 since Debian buster (893845).

References

See:


CategoryKernel | CategoryBootProcess