Skip to content
 

Modifying initrd/initramfs files

This should be less and less necessary these days as most distributions offer command line tools to automatically create or update initrd or initramfs files. Still, once in a while you may need a level of control that those tools don't offer, so you need to manually unpack, modify and repack the initrd or initramfs file. It's not particularly complicated, but there are some steps that you need to get right.

Introduction

The purpose of initrd and initramfs (also known, generically, as "initial RAM disk") is similar: they contain a minimal root filesystem, along with some scripts. When the kernel boots, if it is instructed to use an initrd or initramfs (this is usually done with some boot loader configuration) it unpacks the file in RAM, chroot()s into it, and run some predefined scripts. Finally, the "real" root file system is mounted, the kernel switches to it and the normal init process can begin.

Why do we need an initial RAM disk in the first place? You're probably wondering this if you use to build your own kernel with the necessary modules for your hardware built-in. In that case, you almost never need an initial RAM disk.
But many distributions have to ship a binary kernel that should work on most, or even all, different combinations of hardware, storage, filesystems, etc. They can't obviously build all the possible modules into the kernel. So they ship a minimal, generic kernel, and use an initial RAM disk that contains most hardware modules and some logic to detect which modules need to be loaded to be able to continue to boot the system normally (ie from the hard drive).
This means that it's possible to boot the kernel, load some modules and run some tasks (from the RAM disk), and finally start the normal boot process (/sbin/init etc.). The initial RAM disk must contain a fully functional file system, including some essential programs and libraries. For space reasons, small footprint binaries are usually used (eg ash, busybox, or klibc). Once the initial RAM disk's job is over and the kernel has switched to the real root file system, the memory used by the RAM disk is freed.

As briefly mentioned, there are two types of initial RAM disk: initrd and initramfs. The main difference is that an initrd contain a raw filesystem image (eg ext2), while an initramfs contains a cpio archive (which, when expanded, produces a directory hierarchy). Note that there are quite a few other differences, not mentioned here. In both cases, the image file is compressed (typically with gzip) and the kernel expands and mount it.
All the recent Linux distribution that use an initial RAM disk use an initramfs image. initrd is being used less and less.

To check if the file you're interested in is an initrd or an initramfs, you can decompress it and feed it to file:

# gunzip -c /boot/initrd-2.4.19.img.gz | file -
/dev/stdin: Linux rev 1.0 ext2 filesystem data

so that file is a real initrd. Here's what you'd see with an initramfs:

# gunzip -c /boot/initrd.img-2.6.24-19-generic | file -
/dev/stdin: ASCII cpio archive (SVR4 with no CRC)

Note the "SVR4 with no CRC" format which will be useful later.

Modifying an initrd image

An initrd image is a compressed filesystem, so you just uncompress and mount it:

# mkdir temp
# gunzip -c /boot/initrd-2.4.19.img.gz > initrd.img
# mount -t ext2 -o loop initrd.img temp/
# ls -l temp
total 36
drwxr-xr-x 2 root root  1024 May 30  2005 bin
drwxr-xr-x 4 root root  5120 Jan 26  2005 dev
drwxr-xr-x 2 root root  1024 May 30  2005 etc
drwxr-xr-x 2 root root  1024 May 30  2005 gentoo
drwxr-xr-x 2 root root  2048 May 30  2005 lib
-rwxr-xr-x 1 root root  5730 May 30  2005 linuxrc
drwx------ 2 root root 12288 May 30  2005 lost+found
drwxr-xr-x 2 root root  1024 May 30  2005 mnt
drwxr-xr-x 2 root root  1024 May 30  2005 proc
drwxr-xr-x 3 root root  1024 Jan 26  2005 root
drwxr-xr-x 2 root root  1024 May 30  2005 sbin
drwxr-xr-x 2 root root  1024 May 30  2005 sys
drwxr-xr-x 2 root root  1024 May 30  2005 tmp
drwxr-xr-x 6 root root  1024 May 30  2005 usr
drwxr-xr-x 2 root root  1024 May 30  2005 var

Now it can be modified. Keep in mind that the loop filesystem won't probably have a lot of free space (if at all), so think carefully if you want to add a lot of files. (btw, this is one of the limitations that led to the more recent initramfs.)
Ater you've modified what you want, you just need to unmount the image and recompress it:

# umount temp
# gzip -9 -c initrd.img > /boot/initrd-2.4.19.img.gz-NEW

Modifying an initramfs image

As said, an initramfs image is a compressed cpio archive, although the file name may sometimes be deceiving; sometimes it still has "initrd" in its name, and also many times it does not end in .gz or other suffixes that indicate compression:

# file /boot/initrd.img-2.6.24-19-generic
/boot/initrd.img-2.6.24-19-generic: gzip compressed data, from Unix, last modified: Wed May 26 11:55:59 2010, max compression

Now cpio is an ancient (and a bit weird) archive format. When de-archiving, it needs to read the archive from standard input (GNU cpio also has a --file option to specify the file on the command line). The directory hierarchy is created in the current working directory. So:

# mkdir temp
# cd temp
# gunzip -c /boot/initrd.img-2.6.24-19-generic | cpio -i
34208 blocks
# ls -l
total 36
drwxr-xr-x  2 root root 4096 2010-05-28 14:16 bin
drwxr-xr-x  3 root root 4096 2010-05-28 14:16 conf
drwxr-xr-x  6 root root 4096 2010-05-28 14:16 etc
-rwxr-xr-x  1 root root 3355 2010-05-28 14:16 init
drwxr-xr-x  5 root root 4096 2010-05-28 14:16 lib
drwxr-xr-x  2 root root 4096 2010-05-28 14:16 modules
drwxr-xr-x  2 root root 4096 2010-05-28 14:16 sbin
drwxr-xr-x 12 root root 4096 2010-05-28 14:16 scripts
drwxr-xr-x  3 root root 4096 2010-05-28 14:16 var

Now you can finally edit and change the contents at will (no space limitations, unlike initrd). When you're done, you have to recreate the compressed cpio archive. Again, cpio is a bit weird when archiving, because it wants to read the names of the files to archive on standard input (and writes the archive on standard output). So you can do as follows:

# pwd
/root/temp
# find . | cpio -H newc -o | gzip -9 > /boot/initrd.img-2.6.24-19-generic-NEW
34207 blocks

The only catch is that the -H newc option must be specified because the cpio archive contained in the initramfs has to be in the (new) "SVR4 with no CRC" portable format, as we saw at the beginning. In case you're wondering, cpio can create archives in other formats: bin, odc, crc, tar, ustar, hpbin, hpodc are those listed in the info page for GNU cpio.
Note that the construct

find . | something

is generally considered unsafe and to be avoided in shell scripting, because files could have newlines and control characters in them that could deceive the consumer of those filenames. This is generally not the case for filenames contained in an initramfs image, so it is "safe enough" to use here.

Boot loader configuration

Regardless of whether you used an initrd or an initramfs, when the new image file is created you should edit your boot loader configuration file to instruct it to use the image you just created. This is an example with an initramfs and grub 1 (not 2):

title        Ubuntu 8.04.1, kernel 2.6.24-19-generic
    root     (hd0,0)
    kernel   /boot/vmlinuz-2.6.24-19-generic root=/dev/sda1 ro quiet splash
    initrd   /boot/initrd.img-2.6.24-19-generic-NEW

The "initrd" line now references the newly created initrd/initramfs file.

9 Comments

  1. Tasha Upchurch says:

    Thank you for the great tutorial i wonder if you might have a tutorial or be able to create one about how to modify the initramfs to connect to a nfs boot over a wpa wifi access point?

    If not please point me towards the resources i need I've been trying for a month now.

  2. stanimir says:

    Thank you! An excellent article and very useful, saved my skin.

  3. Martin says:

    Thanks! It helped saving my debian testing raid 1 virtual machine.

  4. christopher barry says:

    Waldner,
    nice article, but you stress something that is indeed incorrect: both 'newc' and 'crc' cpio formats are eqally valid.

    • waldner says:

      Thanks for the information. It's just that all the initramfs that I could check were in that "newc" format so I just assumed it was safe to recreate them in the same format.

  5. Stas Kobzar says:

    Thank you, very good article.

  6. Frank says:

    Hi,

    Very good article. I ran into something though. If I try an add a command
    like mdadm, then when the kernel runs initrd and it opens up the command
    cannot be found. Any idea on this?

    • waldner says:

      Well, the first thing that comes to mind is that the file isn't executable, or its location is not in the PATH in effect at that time. Also remember that the command needs to be able to find all the libraries it needs to run, and probably its configuration files (if any), so you have to copy these as well.