Boot i.MX to Initial RAM disk (initrd)

Document created by Marouene Boubakri Employee on Dec 27, 2018Last modified by Marouene Boubakri Employee on Jan 8, 2019
Version 6Show Document
  • View in full screen mode

initrd (initial ramdisk) is a memory-based file system (optionally compressed) designed to allow Linux startup process to occur in 2 phases.
First the kernel boots with the set of compiled-in drivers than visits the initrd file system in the memory to make preparations prior
to the real root file system.
To go more in details, when using initrd, the system typically boots as follows:

(1) U-boot loads the kernel and initial ram disk image into memory.
(2) The kernel image is booted passing in the memory address of the initrd image.
(3) The kernel converts initrd into a "normal" RAM disk available in a special block device (/dev/ram) and frees the memory used by initrd.
(4) The kernel executes /linuxrc as its first process
(5) The kernel assumes that the real root file system has been mounted and executes /sbin/init to perform the normal user-space boot sequence.
(6) The initrd file system is removed.


The following guide aims to give a summary on how to set up an Initial RAM disk and boot an i.MX to it.


1) Install cross compilers on host machine


- For ARM 32bit toolchain:

$ sudo apt-get install gcc-arm-linux-gnueabihf g++-arm-linux-gnueabihf


- For ARM 64bit toolchain:

$ sudo apt-get install gcc-aarch64-linux-gnu g++-aarch64-linux-gnu


2) Download and compile a shell


We will need a minimal shell in our initrd. BusyBox combines many common UNIX utilities into a single small executable which makes it a perfect option to full fill our requirement.


- Create a workspace 

$ cd ~
$ mkdir workspace && cd workspace && export WORKSAPCE=$PWD


- Download Busybox

$ wget
$ tar xf busybox-snapshot.tar.bz2
$ cd busybox
$ sudo apt-get install libncurses-dev libncursesw5-dev


- We need to statically link Busybox. Configuration of busybox is very similar to the configuration method of Linux kernel. From the top configuration menu select Build static binary option:

$ export CROSS_COMPILE="aarch64-linux-gnu-"
$ make ARCH=arm64 CROSS_COMPILE="$CROSS_COMPILE" menuconfig
Settings --->
[*] Build static binary (no shared libs)


- Compile Busybox

$ make ARCH=arm64 CROSS_COMPILE="$CROSS_COMPILE" -j$(nproc)


- The result is a busybox binary file available in busybox directory.

$ file busybox
busybox: ELF 64-bit LSB executable, ARM aarch64, version 1 (SYSV), statically linked, for GNU/Linux 3.7.0, BuildID[sha1]=e4da78cc97638039c1eb8663ea7029fa5a10a29d, stripped



3) Kernel support


The next step is to enable the Kernel to support initrd and RAM block devices.


- Clone the kernel sources from the repository

$  git clone git://


- Find branch/commit of kernel revision that you want to compile :


- Point to proper revision

$ cd linux-imx
$ git checkout -b imx_4.14.78_1.0.0_ga origin/imx_4.14.78_1.0.0_ga


- Clean your work area if needed

$ make ARCH=arm CROSS_COMPILE=aarch64-linux-gnu- mrproper


- Configure the kernel for the default i.MX installation


$ make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- defconfig


- Configure kernel options

$ make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- menuconfig


- From the top kernel configuration menu, select:

General setup --->
[*] Initial RAM filesystem and RAM disk (initramfs/initrd) support
() Initramfs source file(s)
Device Drivers --->
[*] Block devices --->
<*> RAM block device support
(16) Default number of RAM disks
(32768) Default RAM disk size (kbytes)


- Compile the Kernel 

$ make ARCH=arm64 CROSS_COMPILE="aarch64-linux-gnu-" -j$(nproc)


Copy arch/arm64/boot/Image to FAT32 partition of sdcard


4) Create the Initrd image 


-  Move to workspace directory

$ mkdir initrd
$ cd initrd
$ rm -f ramdisk.img
$ rm -f ramdisk.img.gz
$ rm -f uInitrd


- Define RAM disk constants

$ export RDSIZE=8000
$ export BLKSIZE=1024


- Create an empty ramdisk image

$ dd if=/dev/zero of=ramdisk.img bs=$BLKSIZE count=$RDSIZE


Make it an ext2 mountable file system

$ mke2fs -F -m 0 -b $BLKSIZE ramdisk.img $RDSIZE


Mount it so that we can populate

$ mkdir /mnt/initrd
$ mount ramdisk.img /mnt/initrd -t ext2 -o loop=/dev/loop0


- Create the basic structure of the root file system

$ cd /mnt/initrd
$ sudo mkdir bin sys dev proc mnt


Grab Busybox.

$ sudo cp "$WORKSPACE/busybox/busybox" /mnt/initrd/bin/


-  Equate sbin with bin

$ pushd /mnt/initrd
$ ln -s bin sbin
$ popd


Create the init file

$ sudo bash -c 'cat >> /mnt/initrd/init << EOF
#!/bin/busybox sh
/bin/busybox --install /bin
echo "Initrd is active"
mount -t proc /proc /proc
mount -t sysfs none /sys
mdev -s
/bin/ash --login


Make it executable

$ sudo chmod +x /mnt/initrd/init



$ cd $WORKSPACE/initrd
$ sudo umount /mnt/initrd


Create compressed ramdisk image

$ gzip -9 ramdisk.img


The result is ramdisk.img.gz file.


Install U-boot tools to get mkimage if you don't have it.

$ sudo apt-get install u-boot-tools


Create an uInitrd for u-boot

$ mkimage -A arm64 -T ramdisk -C gzip -d ramdisk.img.gz uInitrd


Copy uInitrd to FAT32 partition of sdcard


5) Prepare U-boot/Kernel for boot to Initrd


Insert the SD-Card into the target and boot it. During U-boot start press a key to get into U-boot shell.

u-boot=> setenv bootinitrd "run loadfdt;run loadimage;fatload mmc
${mmcdev}:$mmcpart $initrd_addr uInitrd;setenv bootargs
console=${console},${baudrate} root=/dev/ram0 rw init=/init;booti $loadaddr
$initrd_addr $fdt_addr"
u-boot=> setenv bootcmd "run bootinitrd"
u-boot=> saveenv
u-boot=> boot


init Instruct the kernel to tun specified binary instead of /sbin/init as init process.

root Specifies the device to be used as Root filesystem.

/dev/ram0: RAM disk mounted as root.

The rw option tells the kernel to mount the root filesystem read/write.


6) Boot to initrd


- Reboot the board or In U-boot shell run

# boot


Busybox shell

/ # id
2 people found this helpful