Skip to content
Yocto: The initramf...
 
Notifications
Clear all

Yocto: The initramfs-framework

1 Posts
1 Users
0 Reactions
27 Views
David Truan
(@david)
Member
Joined: 4 months ago
Posts: 10
Topic starter  

Introduction

When building embedded Linux systems with Yocto, there are situations where you need to run some code very early in the boot process, before the root filesystem is even mounted. This is exactly what the initramfs (initial RAM filesystem) is for: a temporary root filesystem loaded into memory by the bootloader, used to prepare the environment for the real root mount. Examples can be decrypting a partition, mounting a special device and so on.

Yocto provides a useful framework to build and integrate an initramfs image directly into your distribution. In this post, we'll cover:

  • How the initramfs framework works in Yocto
  • How to set it up in your layer
  • How to add a hook with a custom init script

Let's get into it.

 

Setup

The initramfs support in Yocto is built around a dedicated image recipe, typically based on core-image-minimal-initramfs, and a set of packagegroup recipes that bundle the necessary tools.

Enabling the initramfs image

In your local.conf or distro configuration, add the following:

INITRAMFS_IMAGE = "core-image-minimal-initramfs"
INITRAMFS_IMAGE_BUNDLE = "1"

INITRAMFS_IMAGE tells Yocto which image recipe to use as the initramfs. Setting INITRAMFS_IMAGE_BUNDLE to "1" instructs the kernel build to bundle the initramfs cpio archive directly into the kernel image, so the bootloader only needs to load a single binary.

The initramfs image recipe

The default core-image-minimal-initramfs recipe lives in meta/recipes-core/images/. It inherits core-image and pulls in a minimal package group:

PACKAGE_INSTALL = "\
    initramfs-framework \
    base-passwd \
    ${VIRTUAL-RUNTIME_base-utils} \
"

The key package here is initramfs-framework, which provides the modular init infrastructure we'll hook into.

The initramfs-framework package

initramfs-framework is a shell-based, modular init system designed specifically for Yocto initramfs images. It lives in meta/recipes-core/initrdscripts/ and provides:

  • A main /init script that sources modules in order
  • A set of built-in modules (e.g. udev, rootfs, nfsrootfs, ...)
  • A clean hook mechanism to add your own modules

Modules are shell scripts placed in /init.d/ inside the initramfs, named with a numeric prefix to control execution order (e.g. 00-debug, 10-overlayroot).

 

Adding a Hook with a Custom Init Script

Now the interesting part. Say you need to run a custom script early in boot — for instance, to configure a network interface, check hardware, or set up an overlay. Here is how to do it cleanly using the initramfs-framework hook system.

1. Write the module script

Create a shell script following the initramfs-framework module convention. Each module must define two functions:

  • <module>_enabled: Determine if your module should run. Returning 0 means your module should run, returning 1 means it is deactivated.
  • <module>_run: Your custom module logic
 
#!/bin/sh
# modules/80-myhook

myhook_enabled() {
    return 0
}

myhook_run() {
    msg "Running my custom initramfs hook..."

    # Your logic here — e.g. load a kernel module, set up a mount, etc.
    modprobe mydriver

    msg "Custom hook done."
}

The msg helper is provided by initramfs-framework and writes to the console. It also offers some other logging wrappers such as fatal and warn.

2. Create a bbappend or new recipe

The cleanest way to integrate this into Yocto is to create a recipe in your custom layer that installs the module into the initramfs image.

Create a recipe file, e.g. recipes-core/initrdscripts/initramfs-myhook_1.0.bb:

SUMMARY = "Custom initramfs hook for my project"
LICENSE = "MIT"
LIC_FILES_CHKSUM = "file://${COMMON_LICENSE_DIR}/MIT;md5=0835ade698e0bcf8506ecda2f7b4f302"

SRC_URI = "file://80-myhook"

S = "${WORKDIR}"

do_install() {
    install -d ${D}/init.d
    install -m 0755 ${WORKDIR}/80-myhook ${D}/init.d/80-myhook
}

FILES:${PN} = "/init.d/80-myhook"

Place your 80-myhook script under recipes-core/initrdscripts/files/80-myhook.

3. Add the package to your initramfs image

Either create a core-image-minimal-initramfs.bbappend in your layer, or create a custom initramfs image recipe. With the bbappend approach:

# recipes-core/images/core-image-minimal-initramfs.bbappend

PACKAGE_INSTALL:append = " initramfs-myhook"

And just like that, the minimal-initramfs is extended with your init script. A custom recipe would allow more customization on core-image-minimal-initramfs, but for this use case, extending the existing recipe is enough.

4. Build

Trigger the build as usual:

bitbake core-image-minimal-initramfs

 

Conclusion

The initramfs-framework in Yocto provides a solid, modular foundation for early boot customization. Rather than hacking a monolithic init script, you can slot in well-isolated modules that are easy to maintain and test independently. The pattern is always the same: write a module script, package it in a recipe, add it to the initramfs image and Yocto takes care of the rest.

This approach scales well as your project grows: need to add an overlayfs setup? A hardware self-test? An early network configuration? Each one becomes its own module with a clear numeric priority, living cleanly in your layer. It also bases itself on a well tested, actively maintained base.


This topic was modified 2 weeks ago by David Truan

   
Quote
Share: