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)
Contents
(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:
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 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
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!
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!