Minimalist Initramfs and Initrd
===============================

.. include:: header.rst

.. contents:: Contents

Overview
--------

(For more information, read
<linux>/Documentation/filesystems/ramfs-rootfs-initramfs.txt)

This tutorial explains how to create the simplest possible initramfs
and initrd which contain only two files:

- /dev/console

     Required so that you can see characters on the screen

- init

     An executable program that Linux launches after booting

Ususally, an initramfs or initrd is a lot more complicated than this.
This tutorial hopes to enlighten you on how simple things can be though.

Initramfs and initrd both provide essentially the same feature: they
provide an initial root filesystem.  For embedded systems, that alone
might be enough: as soon as you've loaded initramfs or initrd, you're
golden.  One thing to be aware of is that initramfs and initrd-based
filesystems are *volatile*: any changes you make to the filesystem will
be lost on reboot.

Initramfs is a feature that was added in the 2.6 kernel.  It provides
two major innovations, compared to initrd:

- It makes the kernel boot process more efficient.  This should be
  especially attractive for embedded systems.  Initramfs is *not* based
  on an underlying filesystem.  An initrd must be based on a filesystem
  such as ext2, but initramfs bypasses this layer of indirection.
  Initramfs makes it possible for the files just magically live inside
  of Linux's virtual memory subsystem without any underlying filesystem.

- It has the potential ability to move more features out of Linux
  (Kernel Space) and into User Space.  One of the highly touted features
  is more flexibility in discovering and mounting the root filesystem.
  You can read more about this online.

Primary Differences Between Creating an Initramfs versus Initrd
---------------------------------------------------------------

  ==========        ================    ================================
  Image type        Location of init    Tool used to build the image
  ==========        ================    ================================
  initramfs         /init               cpio -H newc -o
  initrd            /sbin/init          mkcramfs, genext2fs (and others)
  ==========        ================    ================================

Create "myinit" (Required for Initramfs and Initrd)
---------------------------------------------------

Create a file called "myinit.c"::

    /* myinit.c
     * Build instructions:
     * ${CROSS_COMPILE}gcc -static init.c -o init
     * */

    #include <stdio.h>

    int
    main ()
    {
        printf ("\n");
        printf ("Hello world from %s!\n", __FILE__);
        while (1) { }
        return 0;
    }

Then build "myinit.c" (note: myinit will later be renamed to simply
"init")::

    ${CROSS_COMPILE}gcc -static myinit.c -o myinit

Initramfs
---------

#. Kernel configuration: Unless you use a bootloader (like U-Boot),
   you'll have to explicitly configure the kernel for initramfs by setting
   "Initramfs source file(s)"::

    General setup --->
      [*] Initial RAM filesystem and RAM disk (initramfs/initrd) suppor
      (initramfs.cpio) Initramfs source file(s)

#. Then create the initramfs CPIO archive (for the curious, "newc" means:
   "The new (SVR4) portable format, which supports file systems having more
   than 65536 i-nodes." - the cpio info page)::

    # 0. Create a directory to hold files for initramfs:
    mkdir initramfs

    # 1. Copy the "myinit" program (compiled above) into the
    #    initramfs directory (and rename it to "init"):
    cp myinit initramfs/init

    # 2. Create the CPIO archive:
    cd initramfs
    fakeroot # this is pure magic (it allows us to pretend to be root)
    mkdir -p dev
    mknod dev/console c 5 1
    chown root init
    find . | cpio -H newc -o > ../initramfs.cpio # <-- this is the actual initramfs
    exit # leave the fakeroot shell
    cd ..
    cat initramfs.cpio | gzip > initramfs.igz # <-- this step is optional


#. Finally, you have to rebuild the kernel again::

    # 0. Copy the CPIO archive to your kernel build directory:
    cp initramfs.cpio .

    # 1. Build Linux:
    nice make -j 4 simpleImage.virtex405-mine

#. And here's the output::

    ...
    [1266814140.810056] TCP cubic registered
    [1266814140.816605] RPC: Registered udp transport module.
    [1266814140.820684] RPC: Registered tcp transport module.
    [1266814140.835432] registered taskstats version 1
    [1266814140.839284] drivers/rtc/hctosys.c: unable to open rtc device (rtc0)
    [1266814140.845710] Freeing unused kernel memory: 48o
    Hello world from myinit.c!

Initrd
------

#. Kernel configuration: Make sure that initramfs is disabled by clearing
   the "Initramfs source file(s)" field in menuconfig::

    General setup --->
      [*] Initial RAM filesystem and RAM disk (initramfs/initrd) suppor
      () Initramfs source file(s)

#. Then create the initrd disk image::

    # 0. Create a directory to hold files for initramfs:
    mkdir initrd
    mkdir initrd/sbin

    # 1. Copy the "myinit" program (compiled above) into the
    #    initrd directory (and rename it to "init"):
    cp myinit initrd/sbin/init

    # 2. Create the compressed disk image:
    cd initrd
    fakeroot # this is pure magic (it allows us to pretend to be root)
    mkdir -p dev
    mknod dev/console c 5 1
    chown -R root sbin
    genext2fs -d . -b 1024 ../initrd.image
    exit # leave the fakeroot shell
    cd ..
    cat initrd.image | gzip > initrd.image.gz

#. Finally, you have to rebuild the kernel again.  *However!*  This
   time is different, instead of "simpleImage...." you will have to make
   "simpleImage.initrd..."::

    # 0. Copy the disk image and rename it to "ramdisk.image.gz":
    cp initrd.image.gz arch/powerpc/boot/ramdisk.image.gz

    # 1. Build Linux (notice the "initrd" in make's target):
    nice make -j 4 simpleImage.initrd.virtex405-mine

    # WARNING: this generates a new .elf file:
    #          "simpleImage.initrd.virtex405-mine.elf"
    #          versus
    #          "simpleImage.virtex405-mine.elf"
    #          You will have to take this into account when downloading
    #          via XMD.

#. This is the output produced on the console::

    ...
    [1266824126.533268] TCP cubic registered
    [1266824126.540140] RPC: Registered udp transport module.
    [1266824126.544300] RPC: Registered tcp transport module.
    [1266824126.558718] registered taskstats version 1
    [1266824126.562566] drivers/rtc/hctosys.c: unable to open rtc device (rtc0)
    [1266824126.569462] RAMDISK: Compressed image found at block 0
    [1266824126.929554] VFS: Mounted root (ext2 filesystem) readonly.
    [1266824126.934786] Freeing unused kernel memory: 156k init

    Hello world from myinit.c!

