[[PageOutline]] = 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 [wiki:buildroot buildroot] for an example of using a small ~1.5MiB buildroot rootfs attached to a kernel. Note that the Linux kernel 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. The init application must be executable and statically linked or it will move on to the next item in the search path. The word 'initramfs' and 'initrd' can be used interchangeably here. see also: - https://docs.kernel.org/admin-guide/initrd.html == 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. To support this you need the following kernel config: * CONFIG_INITRAMFS_SOURCE="" (No source defined!) * CONFIG_INITRAMFS_COMPRESSION_GZIP=y (optional) - or some other compression algorithm * CONFIG_DEVTMPFS=y (optional) - to get devtmpfs support and provide a dynamic /dev 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 : hello.c #include #include int main(int argc, char *argv[]) { printf("Hello world!\n"); sleep(999999999); } EOF # cross compile it static so it has no runtime dependencies ${CROSS_COMPILE}gcc -static hello.c -o hello }}} 1. create an initramfs template and use the Linux gen_initramfs.sh script to create the cpio. Note that you need to run this relative to the linux directory {{{#!bash # create list of files 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 # generate a cpio from it ./usr/gen_initramfs.sh initramfs | gzip -9 > cpio }}} Note that we use gzip compression here (which is completely unnecessary for such a small cpio) so your kernel must have CONFIG_INITRAMFS_COMPRESSION_GZIP=y Take a look at the Linux [https://github.com/torvalds/linux/blob/master/usr/gen_initramfs.sh gen_initramfs.sh] script to see how it works for more info === Creating from scratch using a script and pre-built static busybox You can create an initramfs from scratch fairly easy using a prebuilt status busybox as your base {{{#!bash # specify a location for our rootfs ROOTFS=./rootfs # create rootfs dir mkdir -p $ROOTFS for i in bin dev etc lib mnt proc sbin sys tmp var; do \ mkdir $ROOTFS/$i; done # download a prebuilt static aarch64 binary of busybox and make it executable wget http://mirror.archlinuxarm.org/aarch64/extra/busybox-1.36.1-1-aarch64.pkg.tar.xz tar xvf busybox*.tar.xz usr/bin/busybox mv usr/bin/busybox $ROOTFS/bin # busybox takes the role of a large list of standard linux tools so anything we want or need here that it provides can by symlinked; note we use 'mount' below ln -sf busybox $ROOTFS/bin/mount # create a /init that mounts basic pseudo filesystems then executes a shell cat <<\EOF > $ROOTFS/init #!/bin/busybox sh mount -t devtmpfs devtmpfs /dev mount -t proc proc /proc mount -t sysfs sysfs /sys mount -t tmpfs tmpfs /tmp echo "Hello busybox!" sh EOF chmod +x $ROOTFS/init # create a compressed cpio archive (cd $ROOTFS; find . | cpio -ov --format=newc) | gzip -9 > cpio }}} Note that we use gzip compression here (which is completely unnecessary for such a small cpio) so your kernel must have CONFIG_INITRAMFS_COMPRESSION_GZIP=y === buildroot For a more complete and easy to build root filesystem take a look at [wiki:buildroot buildroot]. Example: {{{#!bash # clone buildroot git clone http://github.com/buildroot/buildroot.git cd buildroot # create the most basic ARM64 rootfs with a gzip cpio filesystem cat << EOF > configs/minimal_arm64_ramdisk_defconfig # arm64 arch BR2_aarch64=y # filesystem options BR2_TARGET_ROOTFS_CPIO=y BR2_TARGET_ROOTFS_CPIO_GZIP=y EOF # build it make minimal_arm64_ramdisk_defconfig make ls -l output/images/rootfs.cpio.gz }}} While the above creates a full features Linux if you want to add your own bootstraping script in front you can simply override /sbin/init or add your own /init (as its looked for first) to the buildroot output/target directory and rebuild the image: {{{#!bash # add a simple /init script cat <output/target/init #!/bin/busybox sh mount -t devtmpfs devtmpfs /dev mount -t proc proc /proc mount -t sysfs sysfs /sys mount -t tmpfs tmpfs /tmp echo "Hello buildroot!" sh EOF chmod +x output/target/init # build again to regenerate the rootfs make ls -l output/images/rootfs.cpio.gz }}} == rebuilding or modifying an initramfs You can modify an external initramfs fairly easily with the {{{cpio}}} tool. You merely need to uncompress it (if compressed) and use the extract parameter. You will want to do this as root in order to preserve file ownership of root files. Example: 1. extract files from an existing gzipped cpio: {{{#!bash # uncompress it (if compressed) and use {{{cpio -i}}} to extract it: # -i extract # -d create directories # -m preserve mtime # -v verbose mkdir rootfs_mod (cd rootfs_mod; gzip -cd ../cpio | sudo cpio -idmv) }}} 2. modify it; for example overwrite or create your own /init: {{{#!bash cat <rootfs_mod/init #!/bin/busybox sh mount -t devtmpfs devtmpfs /dev mount -t proc proc /proc mount -t sysfs sysfs /sys mount -t tmpfs tmpfs /tmp echo "Hello world!" sh EOF chmod +x rootfs_mod/init }}} 1. re-create it {{{#!bash (cd rootfs_mod; find . | cpio -ov --format=newc) | gzip -9 > cpio }}}