Using initrd

Learn how to add boot options and gain flexibility via an initial RAM disk.

If you’ve ever looked into recompiling your "i">Linux kernel, you’ve probably seen advice to
include critical boot drivers (for your hard disk controller and
root partition’s filesystem) in the kernel itself. Omitting
the boot drivers is likely to result in an inability to boot the
computer. The kernel loads and begins doing some checks, but then
stops because it can’t read the root filesystem.

The kernels provided by most Linux distributions, however, lack
the drivers for most disk hardware. These same distributions can
install and boot on all of this hardware, though. How is that
possible? The answer is that the kernels use an "i">initial RAM disk (initrd for
short) to hold the relevant drivers as modules. When the computer
boots, the boot loader passes the initrd to
the kernel, which loads it into RAM and treats it like a disk. The
kernel can then load modules stored in the RAM disk, keeping the
kernel size small while still providing a wide variety of
drivers.

When you compile your own kernel, it’s usually easier to
bypass the initrd and instead build the
relevant drivers into your main kernel file. Sometimes, though, you
might want to build your own initrd.
Let’s see how.

Why Use initrd?

The average desktop or server system running a custom kernel
doesn’t need initrd. However, it can
be useful in several situations:

*Most distributions use
initrd because the distributions’
designers can’t predict what hard disk controller
you’ve got.

*Using "c">initrd enables you to design a custom emergency system
or specialized boot CD-R that will run on a variety of systems.
This could be handy if you want to have an emergency system for use
in a work environment with many different system
configurations.

*If you maintain several Linux
systems, you may want to custom-build a single kernel for all of
them. Rather than tweak each system’s kernel for its specific
hardware or build kernels with multiple sets of disk drivers, you
can place the necessary drivers as modules in "c">initrd.

*In certain embedded and
specialized Linux systems, initrd may be
used as the final root filesystem. This
enables Linux to run on a read/write filesystem even when the only
permanent storage is read-only in nature.

*Even if you don’t want
to build a completely new initrd, you might
want to modify the one provided by your distribution maintainer,
say, to add a new or updated driver.

Getting to Know "c">initrd

Before delving into initrd configuration,
you should understand a bit about how it works.

When a Linux system boots, the computer reads a boot loader,
which in the case of an x86 or "i">x86-64 Linux system is likely to be the "i">Linux Loader (LILO) or the Grand Unified
Boot Loader
(GRUB). LILO and GRUB are both very simple
programs. They can read data from the hard disk using BIOS calls,
so they don’t need disk drivers such as those used by the
Linux kernel. Using BIOS calls, LILO or GRUB loads the Linux kernel
into memory and executes it. When given appropriate options, LILO
or GRUB also loads an initrd image, which is
typically stored on disk in your /boot
directory along with the kernel file. When the boot loader loads an
initrd image, it passes its address in
memory to the kernel when it starts the kernel.

Once the kernel is running, it mounts the "c">initrd image and executes the "i">/linuxrc or /init program on the
RAM disk. (Most initrd documentation refers
to /linuxrc, but some systems expect a file
called /init.) This program acts something
like the normal Linux startup program ( "i">/sbin/init), in that it controls what the kernel does
with the initrd contents. Typically,
/linuxrc or /init is
a shell script that loads the drivers necessary for accessing your
hard disk, swaps out the RAM disk filesystem for the root
filesystem on the hard disk, releases the memory used by the RAM
disk, and then continues the boot process using the hard
disk’s root filesystem. In principle, this RAM disk boot
script could do much more than this, but in practice additional
steps are usually performed by /sbin/init on
your hard disk and the programs it calls, such as SysV startup
scripts. Using on-disk programs and utilities makes for easier
system maintenance.

One problem with using initrd is that the
RAM disk image must be maintained using utilities. You can’t
just copy files in and out of a directory. In the past,
initrd image files were typically filesystem
images, holding ext2, romfs, or other
filesystems. Today, they’re more often compressed
cpio archives. As a result, the process of
creating or modifying an initrd image
involves extracting data from an existing image file, replacing and
modifying files, and creating a new archive with your new or
changed files. You can then modify your boot loader configuration
to access the new files. Chances are you’ll need to
reconfigure your kernel before you do any of these things,
though.

Configuring Your Kernel

In most cases, the whole point of using "c">initrd is to slim down your kernel. Therefore, you
should peruse your kernel options, changing drivers you normally
build into the kernel to build as modules. Typically, such options
are restricted to filesystems and hard disk drivers.

Of course, you can do the same to other drivers, such as sound
card drivers, network drivers, and frame buffer video drivers;
however, such drivers are not typically required to boot the
computer (with the exception of network drivers for network boot
configurations), so you can perform such slimming even if you
don’t use initrd.

One notable caveat exists: If you intend to create an initial
RAM disk as a disk image file (rather than as a "c">cpio archive file), you must build support for the
filesystem you use into your kernel. You could build a RAM disk
image using ext2, romfs, the Minix
filesystem, or various others. Chances are ext2 would be the most
convenient, but you can use your own judgment on this matter.
Creating a cpio archive instead of using a
conventional filesystem enables you to build all your standard
filesystems as modules.

Two options that must be present in your kernel to use an
initial RAM disk are the RAM Disk Support and Initial RAM
Filesystem and RAM Disk (initramfs/initrd) Support options, both of
which are in the “Block Devices” subsection of the
Device Drivers kernel configuration area. Be sure these options are
both built into the kernel itself!

Once you’re done configuring your kernel via "c">make xconfig, make menuconfig, or
similar tools, you can compile it in the normal way. Remember to
install your kernel modules via make
modules_install
and copy your main kernel file to
/boot.

Using initrd Preparation
Tools

The easiest way to create an initrd is to
use a preparation tool. Most distributions include a program called
mkinitrd to do this job. To use it, pass it
the name of the file in which you want to store your "c">initrd image and the kernel version number you want to
use:

# mkinitrd /boot/initrd-2.6.18.cpio.gz 2.6.18

This example creates an initrd image for
the 2.6.18 kernel. Here, the "i">.cpio.gz filename extension is used because this is what
it really is, but most distributions give it no extension or an
.img extension instead.

Although mkinitrd and similar tools (such
as yaird, "http://alioth.debian.org/projects/yaird/" class=
"story_link">http://alioth.debian.org/projects/yaird/
) are
handy, they’re inflexible. If you want to create an unusual
initrd, you’ll need to dig into the
standard file and modify it.

Preparing an initrd Image from Scratch

One way to create a custom or unusual "c">initrd is to start with a working image. You can begin
with a standard initrd image or create one
with mkinitrd. Locate the original file,
copy it to a convenient directory, and create a subdirectory to
hold the RAM disk’s extracted files. The original file is
typically called /boot/initrd-* or
/boot/initrd-*.img, where "i">* is a version number and perhaps additional
distribution-specific codes. Although many distributions do not
include a .gz extension in their
initrd filenames, these files are almost
always compressed with gzip. Thus, you
should rename the copy to include a .gz
extension. Suppose it’s called "i">initrd.img.gz. If the file is a "i">cpio archive, you can uncompress it with "i">cpio and gunzip, after changing
into the working directory for your RAM disk files:

# gunzip -c ../initrd.img.gz | cpio -iv

The result should yield a copy of the files from the
initrd image file you specified.

If you’re working from a disk image rather than a
cpio archive, you can uncompress the copy
and mount it using the loopback device, after changing into the
directory that holds the initial RAM disk image file:

# gzunip ./initrd.img.gz
# mount -o loop initrd.img ./workdir

This pair of commands makes the working files available under
the workdir subdirectory of the current
directory. One caveat about this approach is that initial RAM disk
images may contain little or no extra space for adding files. Thus,
you may need to copy these files to another subdirectory, modify
them there, and then create a cpio archive
from your changed files. Alternatively, you could create a larger
filesystem image file and copy the files there.

In either case, you can begin modifying the RAM disk’s
files. Precisely how you proceed depends on what you want to
accomplish, but some things you may want to do include:

*Replace kernel modules (files
with the .ko extension) in the RAM
disk’s lib directory with their
equivalents from your newly compiled kernel, as stored in the
/lib/modules/version directory tree, where
version is your kernel version number.

*Add kernel modules for any
drivers or filesystems you want to have available during the boot
process, perhaps including proprietary or non-standard drivers.

*Modify the "i">init or linuxrc file to perform
additional tasks. You may need to add insmod
lines to load new kernel modules, for instance. This startup script
is normally a shell script, so you can edit it with a text
editor.

*Depending on your distribution
and from where you acquired your kernel source, you may need to
rename the init file to "i">linuxrc or vice-versa. To hedge your bets, create a
symbolic link so that it may be called by either name.

*More ambitious changes may
require you to add programs to bin, add
device nodes to dev, or make more extensive
changes to the startup script. If you’re creating an
emergency boot system or other standalone boot CD-R, you may want
to disable the last few lines of a standard "c">initrd startup script, which pass control over to the
on-disk boot partition. Instead, substitute a call to "c">bash or some other shell.

One potentially frustrating aspect of preparing or modifying a
startup script is that it can be tricky to get the order in which
you load kernel modules right. You can use the "i">modinfo command on the kernel module files to spot
dependencies, which can help you figure out what needs to be loaded
first (or at all).

When you’re finished making changes, you must create a new
initial RAM disk file. If you’ve used a loopback device,
unmount and recompress it to do the trick:

# umount ./workdir
# gzip -9 initrd.img

If you want to create a cpio archive as
your initrd carrier, you can

do so with cpio and "c">gzip:

# cd workdir
# find ./ | cpio -o -H newc | gzip -9 > ../initrd.cpio.gz

In either case, you should probably copy your new "c">initrd image file to /boot,
perhaps renaming it with an appropriate version number.

Reconfiguring Your Boot Loader

At this point, you should have a new kernel in "i">/boot and a new initrd image in
the same location. Your task now is to reconfigure your boot loader
(LILO or GRUB) to use both.

If you use LILO, load the /etc/lilo.conf
file into a text editor. This file contains global options followed
by a series of stanzas, each of which
describes one kernel or non-Linux OS. Linux stanzas begin with a
line that starts with the string image=
followed by the kernel’s filename. Subsequent lines in the
stanza are usually indented and describe options.

Copy your current working stanza and modify the copy to point to
the new kernel. Locate the line in the stanza that begins
initrd= and point it to your new
initrd image file. When you’re done,
save your changes and type lilo at a root
prompt to re-install LILO.

In the case of GRUB, edit the file called "i">/boot/grub/grub.conf or "i">/boot/grub/menu.lst. Locate your current boot stanza,
copy it, and modify the copy to point to the new kernel and
initrd image. The relevant lines begin with
the strings kernel and "c">initrd, respectively. Once you’ve made the
changes, you don’t need to re-install GRUB; this boot loader
reads the configuration file from disk whenever the system
boots.

Rebooting to Use Your "c">initrd Image

At this point, you should reboot your computer to test the new
kernel and initrd configuration. If all goes
well, your computer will start normally, providing access to all
your devices. If there’s a problem, it should show up fairly
early in the boot process.

The most common problem is that the kernel can’t mount a
root filesystem (either the initial RAM disk or the hard
disk’s root filesystem). If this happens, you’ll see a
note to that effect. Read all the kernel messages on the screen;
they may provide clues about what went wrong. The usual cause is a
missing or out-of-place insmod call in the
initrd startup script.

Once your system is working, you can tweak it. You can add
drivers to your startup script to support multiple hardware
configurations, or create separate startup scripts and RAM disk
images to support these configurations. Attempting to load a driver
for a nonexistent device is normally not a problem, so you may be
able to get by with a single RAM disk image for multiple hardware
configurations. Because the kernel releases the "c">initrd memory when it switches to the hard disk root
partition, there’s no memory penalty for providing a big RAM
disk with lots of drivers.

Fatal error: Call to undefined function aa_author_bios() in /opt/apache/dms/b2b/linux-mag.com/site/www/htdocs/wp-content/themes/linuxmag/single.php on line 62