back-arrow Go back to Linux on Xilinx FPGA Tutorials

Minimalist Initramfs and Initrd

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:

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:

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

  1. 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)
    
  2. 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
    
  3. 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
    
  4. 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

  1. 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)
    
  2. 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
    
  3. 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.
    
  4. 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!