Minimalist Initramfs and Initrd =============================== .. include:: header.rst .. contents:: Contents Overview -------- (For more information, read /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 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!