Version 2 (modified by 7 months ago) ( diff ) | ,
---|
initramfs
The initramfs is a complete set of directories that you would find on a normal root filesystem embedded into the Linux kernel. It is bundled into a single cpio archive and compressed with one of several compression algorithms. At boot time, the boot loader loads the kernel and the initramfs image into memory and starts the kerne. If a kernel has been built to include an initramfs it mounts that instead and ignores the 'root=' kernel parameter.
Using a small root filesystem via initramfs is a great way to do Linux kernel development or work with a system that does not yet have any via-able storage available. See buildroot for an example of using a small ~1.5MiB buildroot rootfs attached to a kernel.
To build a kernel with an initramfs configure the following kernel items:
- CONFIG_INITRAMFS_SOURCE="/path/to/rootfs.cpio"
- CONFIG_INITRAMFS_COMPRESSION_GZIP=y (optional) - or some other compression algorithm
- CONFIG_DEVTMPFS=y (optional) - to get devtmpfs support and provide a dynamic /dev
This will build a kernel that runs /init
, /sbin/init
, or /bin/sh
(searched in that order) as PID1 from the initramfs (if it exists). If you want to run a different executable as PID1 you can use the init=
kernel parameter.
external initramfs
This is a ramdisk image (cpio, or compressed cpio if you have enabled ramdisk compression in your kernel) that you pass to the kernel when booting. If doing this with U-Boot its the 2nd (middle) arg to bootm/booti/bootz.
Note that bootm
expects a uImage and uramdisk which have U-Boot wrappers (created with the mkimage
tool from the u-boot-tools
package) around the images. U-Boot must have CONFIG_LEGACY_IMAGE_FORMAT enabled for this. Note that arm64 does not support compressed kernel Images so you must use booti for arm64 (or bootm with a FIT image).
Note that booti
requires passing the size of the ramdisk by specifying <rdaddr>:<filesize and U-Boot must have CONFIG_SUPPORT_RAW_INITRD enabled. You can also use a uramdisk with booti as long as you have CONFIG_LEGACY_IMAGE_FORMAT enabled.
The benefit of using an external initramfs is that you do not have to rebuild the kernel to update the root filesystem.
Many Linux based Operating Systems using an initramfs as a shim to load kernel modules that are required to mount the root filesystem allowing them to use kernels that are very small and modular. Android and Ubuntu are two very popular Linux based Operating Systems that use this technique.
internal initramfs
An internal initramfs is when you embed an initramfs into the kernel via CONFIG_INITRAMFS_SOURCE
which can point to a directory path, an existing cpio.gz, or a text file with some directives.
Note that your bootloader (ie U-Boot) may have a limit on the size of a kernel. For U-Boot this is defined by CONFIG_SYS_BOOTM_LEN which you may need to increase if either the static kernel or the initramfs gets too large.
Building an initramfs
Here is a simple example of building an initramfs with a stand-alone application and some basic dev nodes as the only components in the rootfs:
cat << EOF > hello.c #include <stdio.h> #include <unistd.h> int main(int argc, char *argv[]) { printf("Hello world!\n"); sleep(999999999); } EOF ${CROSS_COMPILE}gcc -static hello.c -o hello cat << EOF > initramfs dir /dev 755 0 0 nod /dev/console 644 0 0 c 5 1 nod /dev/loop0 644 0 0 b 7 0 dir /bin 755 1000 1000 dir /proc 755 0 0 dir /sys 755 0 0 dir /mnt 755 0 0 file /init hello 755 0 0 EOF
kernel args:
- CONFIG_INITRAMFS_SOURCE="initramfs"
- CONFIG_INITRAMFS_ROOT_UID=0
- CONFIG_INITRAMFS_ROOT_GID=0
- CONFIG_INITRAMFS_COMPRESSION_GZIP=y
- CONFIG_INITRAMFS_COMPRESSION=".gz"
For a more complete root filesystem take a look at buildroot