Changes between Version 2 and Version 3 of linux/initramfs


Ignore:
Timestamp:
02/24/2024 12:02:33 AM (3 months ago)
Author:
Tim Harvey
Comment:

added additional examples

Legend:

Unmodified
Added
Removed
Modified
  • linux/initramfs

    v2 v3  
    1 = initramfs =
     1[[PageOutline]]
     2
     3= initramfs
    24The 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.
    35
    46Using 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.
    57
    6 To build a kernel with an initramfs configure the following kernel items:
    7  * CONFIG_INITRAMFS_SOURCE="/path/to/rootfs.cpio"
     8Note 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.
     9
     10see also:
     11 - https://docs.kernel.org/admin-guide/initrd.html
     12
     13== external initramfs
     14This 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.
     15
     16To support this you need the following kernel config:
     17 * CONFIG_INITRAMFS_SOURCE="" (No source defined!)
    818 * CONFIG_INITRAMFS_COMPRESSION_GZIP=y (optional) - or some other compression algorithm
    919 * CONFIG_DEVTMPFS=y (optional) - to get devtmpfs support and provide a dynamic /dev
    10 
    11 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.
    12 
    13 == external initramfs ==
    14 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.
    1520
    1621Note 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).
     
    2227Many 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.
    2328
    24 == internal initramfs ==
     29Example booting with an initramfs:
     30 - Venice: IMX8MM GW7300-00:
     31{{{#!bash
     32tftpboot $fdt_addr_r venice/imx8mm-venice-gw73xx-0x && \
     33tftpboot $kernel_addr_r venice/Image && \
     34tftpboot $ramdisk_addr_r venice/cpio && \
     35booti $kernel_addr_r $ramdisk_addr_r:$filesize $fdt_addr_r
     36}}}
     37
     38Note that the ramdisk was loaded last so that $filesize represents it's size as compared to the other two objects loaded
     39
     40== internal initramfs
    2541An 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.
    2642
    2743Note 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.
    2844
    29 == Building an initramfs ==
    30 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:
     45To build a kernel with an initramfs configure the following kernel items:
     46 * CONFIG_INITRAMFS_SOURCE="/path/to/rootfs.cpio"
     47 * CONFIG_INITRAMFS_COMPRESSION_GZIP=y (optional) - or some other compression algorithm
     48 * CONFIG_DEVTMPFS=y (optional) - to get devtmpfs support and provide a dynamic /dev
     49
     50
     51== Building an initramfs
     52There are several ways to create an initramfs
     53
     54=== Using an initramfs_list config file
     55Here 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 using an initramfs_list conifg file and the Linux kernels {{{gen_initramfs_list.sh}}} script. This assumes you have a CROSS_COMPILE environment setup and a built linux kernel:
     56 1. cd to your built Linux directory (where the gen_initramfs.sh script needs to run from as it uses some built objects):
     57{{{#!bash
     58cd venice/bsp
     59. ./setup-environment # setup your cross toolchain
     60cd linux
     61}}}
     62 1. create a simple application that is statically linked such that it has no dependencies:
    3163{{{#!bash
    3264cat << EOF > hello.c
     
    4072}
    4173EOF
     74# cross compile it static so it has no runtime dependencies
    4275${CROSS_COMPILE}gcc -static hello.c -o hello
     76}}}
     77 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
     78{{{#!bash
     79# create list of files
    4380cat << EOF > initramfs
    4481dir /dev 755 0 0
     
    5188file /init hello 755 0 0
    5289EOF
     90# generate a cpio from it
     91./usr/gen_initramfs.sh initramfs | gzip -9 > cpio
    5392}}}
    5493
    55 kernel args:
    56  * CONFIG_INITRAMFS_SOURCE="initramfs"
    57  * CONFIG_INITRAMFS_ROOT_UID=0
    58  * CONFIG_INITRAMFS_ROOT_GID=0
    59  * CONFIG_INITRAMFS_COMPRESSION_GZIP=y
    60  * CONFIG_INITRAMFS_COMPRESSION=".gz"
     94Note 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
    6195
    62 For a more complete root filesystem take a look at [wiki:buildroot buildroot]
     96Take 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
     97
     98=== Creating from scratch using a script and pre-built static busybox
     99You can create an initramfs from scratch fairly easy using a prebuilt status busybox as your base
     100{{{#!bash
     101# specify a location for our rootfs
     102ROOTFS=./rootfs
     103# create rootfs dir
     104mkdir -p $ROOTFS
     105for i in bin dev etc lib mnt proc sbin sys tmp var; do \
     106  mkdir $ROOTFS/$i;
     107done
     108# download a prebuilt static aarch64 binary of busybox and make it executable
     109wget http://mirror.archlinuxarm.org/aarch64/extra/busybox-1.36.1-1-aarch64.pkg.tar.xz
     110tar xvf busybox*.tar.xz usr/bin/busybox
     111mv usr/bin/busybox $ROOTFS/bin
     112# 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
     113ln -sf busybox $ROOTFS/bin/mount
     114# create a /init that mounts basic pseudo filesystems then executes a shell
     115cat <<\EOF > $ROOTFS/init
     116#!/bin/busybox sh
     117mount -t devtmpfs  devtmpfs  /dev
     118mount -t proc      proc      /proc
     119mount -t sysfs     sysfs     /sys
     120mount -t tmpfs     tmpfs     /tmp
     121
     122echo "Hello busybox!"
     123sh
     124EOF
     125chmod +x $ROOTFS/init
     126# create a compressed cpio archive
     127(cd $ROOTFS; find . | cpio -ov --format=newc) | gzip -9 > cpio
     128}}}
     129
     130Note 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
     131
     132=== buildroot
     133For a more complete and easy to build root filesystem take a look at [wiki:buildroot buildroot].
     134
     135Example:
     136{{{#!bash
     137# clone buildroot
     138git clone  http://github.com/buildroot/buildroot.git
     139cd buildroot
     140# create the most basic ARM64 rootfs with a gzip cpio filesystem
     141cat << EOF > configs/minimal_arm64_ramdisk_defconfig
     142# arm64 arch
     143BR2_aarch64=y
     144# filesystem options
     145BR2_TARGET_ROOTFS_CPIO=y
     146BR2_TARGET_ROOTFS_CPIO_GZIP=y
     147EOF
     148# build it
     149make minimal_arm64_ramdisk_defconfig
     150make
     151ls -l output/images/rootfs.cpio.gz
     152}}}
     153
     154While 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:
     155{{{#!bash
     156# add a simple /init script
     157cat <<EOF >output/target/init
     158#!/bin/busybox sh
     159mount -t devtmpfs  devtmpfs  /dev
     160mount -t proc      proc      /proc
     161mount -t sysfs     sysfs     /sys
     162mount -t tmpfs     tmpfs     /tmp
     163
     164echo "Hello buildroot!"
     165sh
     166EOF
     167chmod +x output/target/init
     168# build again to regenerate the rootfs
     169make
     170ls -l output/images/rootfs.cpio.gz
     171}}}