# FIT Image with initramfs as an artifact

**URL:** <https://hub.mender.io/t/fit-image-with-initramfs-as-an-artifact/2057>\
**Category:** General Discussions\
**Tags:** yocto\
**Created:** [June 17, 2020, 9:29am UTC](https://hub.mender.io/t/fit-image-with-initramfs-as-an-artifact/2057 "2020-06-17T09:29:17Z")\
**Posts on this page:** 11\
**Page:** 1

<div class="post-metadata">

**Author:** ![martin](https://avatars.discourse-cdn.com/v4/letter/m/73ab20/32.png) [@martin](https://hub.mender.io/u/martin)\
**Post date:** [June 17, 2020, 9:29am UTC](https://hub.mender.io/t/fit-image-with-initramfs-as-an-artifact/2057/1 "2020-06-17T09:29:17Z")

</div>

Hi,

I would like to create an image where the rootfs are just FIT images that contain the kernel, device tree and initramfs root filesystem that stays resident in RAM.

I came across this post

> [@Read only compressed rootfs in raw flash?](https://hub.mender.io/t/read-only-compressed-rootfs-in-raw-flash/950/11):
>
> @mirzak I am able to flash squashfs image in standalone mender. [quote=“mirzak, post:3, topic:950”]artifcat ArtifactReboot\_Enter\_50 [/quote] I renamed your mender state scripts and run once inside rootfs and with artifact. renamed to Download\_Leave\_50 and kept as part of rootfs. renamed to ArtifactInstall\_leave\_50 and integrated with release-1.mender. Both made mender exit with ERRO[0007] stderr collected while running script please see the log for details,let me know on how to fix th…

which also mentions this. I’ve taken a look through the Mender Yocto layer and I don’t think it supports it out of the box but mender-ubimg.bbclass looks like the place where it creates the image using ubifs root filesystems. Should I create my own IMAGE\_FSTYPE and create my own mender-myimg.bbclass so I can customise this to create my image?

Many Thanks,  
Martin.

---

<div class="post-metadata">

**Author:** ![drewmoseley](https://yyz2.discourse-cdn.com/flex036/user_avatar/hub.mender.io/drewmoseley/32/47_2.png) [@drewmoseley](https://hub.mender.io/u/drewmoseley)\
**Post date:** [June 17, 2020, 5:12pm UTC](https://hub.mender.io/t/fit-image-with-initramfs-as-an-artifact/2057/2 "2020-06-17T17:12:47Z")

</div>

Hi @martin that feels like the right approach to me. If the changes end up being minimal then perhaps just a bitbake variable and some strategic changes to the existing image classes could work but that may be a bit unwieldy.

---

<div class="post-metadata">

**Author:** ![martin](https://avatars.discourse-cdn.com/v4/letter/m/73ab20/32.png) [@martin](https://hub.mender.io/u/martin)\
**Post date:** [June 17, 2020, 5:54pm UTC](https://hub.mender.io/t/fit-image-with-initramfs-as-an-artifact/2057/3 "2020-06-17T17:54:23Z")

</div>

It kind of worked but I had a chicken and egg situation between the initramfs (which was the image that was being menderised) and the FIT Image that should be containing it. So it worked but as soon as I cleaned the sstate of the kernel and tried to rebuild it didn’t work.

I think I have worked out a way around this by creating a dummy image recipe that is the image that gets menderised and this dummy image depends the kernel and bootloader. So I get my FIT image and the bootloader which is all that is needed to create my custom image.

I’ll let you know how I get on.

---

<div class="post-metadata">

**Author:** ![martin](https://avatars.discourse-cdn.com/v4/letter/m/73ab20/32.png) [@martin](https://hub.mender.io/u/martin)\
**Post date:** [June 17, 2020, 8:23pm UTC](https://hub.mender.io/t/fit-image-with-initramfs-as-an-artifact/2057/4 "2020-06-17T20:23:00Z")

</div>

One problem I have is that the FIT image isn’t in ${IMGDEPLOYDIR}. The original ubimg class file had

```
cat > ${WORKDIR}/ubimg-${IMAGE_NAME}.cfg <<EOF

```

[rootfsA]  
mode=ubi  
image={IMGDEPLOYDIR}/{IMAGE\_LINK\_NAME}.ubifs  
vol\_id=0  
vol\_size=${MENDER\_CALC\_ROOTFS\_SIZE}KiB  
vol\_type=dynamic  
vol\_name=rootfsa

so for image= I could replace IMGDEPLOYDIR with DEPLOY\_DIR\_IMAGE and get the FIT image with the initramfs from there.

Is there any problem with this?

My instinct says I need to create my own mender-artifactimg.bbclass file that works with FIT images and not rootfs images. That way I should get a FIT image artifact for deploying as an update. I see when it creates the mender artifact it assumes the artifact is already in  
${IMGDEPLOYDIR}

```
mender-artifact write rootfs-image \
    -n ${MENDER_ARTIFACT_NAME} \
    $extra_args \
    $image_flag ${IMGDEPLOYDIR}/${ARTIFACTIMG_NAME}.${ARTIFACTIMG_FSTYPE} \
    ${MENDER_ARTIFACT_EXTRA_ARGS} \
    -o ${IMGDEPLOYDIR}/${IMAGE_NAME}${IMAGE_NAME_SUFFIX}.mender

```

I can’t find where this occurs, could someone point me to the file in meta-mender where this happens?

Cheers,  
Martin.

---

<div class="post-metadata">

**Author:** ![wkswain](https://avatars.discourse-cdn.com/v4/letter/w/3e96dc/32.png) [@wkswain](https://hub.mender.io/u/wkswain)\
**Post date:** [June 17, 2020, 10:42pm UTC](https://hub.mender.io/t/fit-image-with-initramfs-as-an-artifact/2057/5 "2020-06-17T22:42:39Z")

</div>

@martin  
I am running Xilinx Petalinux, and we implemented Mender on Zynq7. Our setup might be close, so I’ll do my best to explain what we did. We run a fitimage (device-tree,kernel,rootfs) in ramdisk. The fitImage is the only thing inside the mender image in EMMC aside from the uEnv, and our fpgabin. We use /data location as persistent disk partition area.

First, you have to get the fiIimage working. In our project.conf for our main image we have something like this:

KERNEL\_CLASSES = “kernel-fitimage”  
KERNEL\_IMAGETYPES = “fitImage”  
INITRAMFS\_IMAGE\_BUNDLE = “1”  
INITRAMFS\_IMAGE = “your-user-image”  
INITRAMFS\_MAXSIZE = “16777216”

Once we had that, test it by downloading it TFTP and make sure it works the way you like.

Next, I tried in many ways to get the mender image to build from the above image, but couldn’t get it to work. And I don’t think an image can depend on an image? So we created a second image recipe local-mender-image.bb. So, we have to do a 2-step build, and you have to remember to clean your local-mender-image each time, but it works. The trick is, how do you remove all the extra junk from the image. You don’t want a kernel image inside your mender image plus the fitImage!

Here’s some of the recipe so you can get an idea how we did that. Sorry if it’s not complete, I’m just hoping to point you down a path that may work.

my\_postprocess\_function() {  
rm -rf {IMAGE\_ROOTFS}/etc rm -rf {IMAGE\_ROOTFS}/var  
rm -rf {IMAGE\_ROOTFS}/usr cp {DEPLOY\_DIR\_IMAGE}/fitImage-petalinux-user-image-plnx-zynq7-plnx-zynq7 {IMAGE\_ROOTFS}/boot/ ln -sf fitImage-petalinux-user-image-plnx-zynq7-plnx-zynq7 {IMAGE\_ROOTFS}/boot/fitImage  
install -d {IMAGE\_ROOTFS}/data/mender install -d {IMAGE\_ROOTFS}/data/u-boot  
echo “/dev/mmcblk0 0x800000 0x4000” \>\> {IMAGE\_ROOTFS}/data/u-boot/fw\_env.config echo "/dev/mmcblk0 0x1000000 0x4000" \>\> {IMAGE\_ROOTFS}/data/u-boot/fw\_env.config  
}

my\_preprocess\_function() {  
rm -rf ${IMAGE\_ROOTFS}/var  
}

ROOTFS\_POSTPROCESS\_COMMAND\_append = “my\_postprocess\_function;”  
IMAGE\_PREPROCESS\_COMMAND = " my\_preprocess\_function;"

inherit image  
MACHINE\_ESSENTIAL\_EXTRA\_RDEPENDS\_remove\_petalinux-user-image = " kernel-image kernel-devicetree"  
MACHINE\_ESSENTIAL\_EXTRA\_RDEPENDS\_remove\_mender-image\_arm = " kernel-image kernel-devicetree"  
PREFERRED\_PROVIDER\_u-boot-fw-utils = “u-boot-fw-utils”  
PREFERRED\_RPROVIDER\_u-boot-fw-utils = “u-boot-fw-utils”  
BIF\_PARTITION\_ATTR = “fsbl u-boot”  
BOOTBIN\_BASE\_NAME = “BOOT”  
IMAGE\_BOOT\_FILES = “uEnv.txt”

MENDER\_STORAGE\_DEVICE = “/dev/mmcblk0”  
MENDER\_STORAGE\_TOTAL\_SIZE\_MB = “7168”  
MENDER\_DATA\_PART\_SIZE\_MB = “6608”  
MENDER\_FEATURES\_ENABLE\_append = " mender-image mender-uboot mender-image-sd"  
MENDER\_FEATURES\_DISABLE\_append = " mender-grub mender-image-uefi mender-systemd"  
MENDER\_ARTIFACT\_NAME=“local-image”

Hope that helps in some way. There’s probably a better way, but it was consuming too much time trying to find an answer, so this works for us.

---

<div class="post-metadata">

**Author:** ![martin](https://avatars.discourse-cdn.com/v4/letter/m/73ab20/32.png) [@martin](https://hub.mender.io/u/martin)\
**Post date:** [June 18, 2020, 7:55am UTC](https://hub.mender.io/t/fit-image-with-initramfs-as-an-artifact/2057/6 "2020-06-18T07:55:36Z")

</div>

Thanks for the reply. I’ll post my implementation as well soon when its working and hopefully both of our posts can help other people in the future. 🙂

---

<div class="post-metadata">

**Author:** ![martin](https://avatars.discourse-cdn.com/v4/letter/m/73ab20/32.png) [@martin](https://hub.mender.io/u/martin)\
**Post date:** [June 18, 2020, 8:05am UTC](https://hub.mender.io/t/fit-image-with-initramfs-as-an-artifact/2057/7 "2020-06-18T08:05:37Z")

</div>

I managed to successfully get a menderised FIT Image using a custom bbclass. One thing I noticed is that I ended up cut and pasting a lot of code from

**mender-artifactimg.bbclass**

So I was wondering if there could be a way of turning this class into something that could easily be extended to create custom artifacts. In **IMAGE\_CMD\_mender** I copied most of this except the call to **mender-artifact** and I had to alter this line

```
rootfs_size=$(stat -Lc %s ${IMGDEPLOYDIR}/${ARTIFACTIMG_NAME}.${ARTIFACTIMG_FSTYPE})

```

to use the fitImage. Here’s the final _mender-artifact-fit.bbclass_

```
#
#
# By inherting this class you will automatically get a mender artifact of
# the FIT image containing the initramfs
#

inherit mender-helpers

# ------------------------------ CONFIGURATION ---------------------------------

# Extra arguments that should be passed to mender-artifact.
MENDER_ARTIFACT_EXTRA_ARGS ?= ""

# The key used to sign the mender update.
MENDER_ARTIFACT_SIGNING_KEY ?= ""

# --------------------------- END OF CONFIGURATION -----------------------------

# Piggyback on the back of do_deploy
do_deploy[postfuncs] += "do_deploy_artifact_fit"
# Ensure we have mender-artifact-native in the recipes native sysroot
do_deploy[depends] += "mender-artifact-native:do_populate_sysroot"

MENDER_ARTIFACT_NAME_DEPENDS ?= ""

MENDER_ARTIFACT_PROVIDES ?= ""
MENDER_ARTIFACT_PROVIDES_GROUP ?= ""

MENDER_ARTIFACT_DEPENDS ?= ""
MENDER_ARTIFACT_DEPENDS_GROUPS ?= ""

apply_arguments () {
	#
	# $1 -- the command line flag to apply to each element
	# $@ -- the list of arguments to give each its own flag
	#
	local res=""
	flag=$1
	shift
	for arg in $@; do
		res="$res $flag $arg"
	done
	cmd=$res
}

do_deploy_artifact_fit() {
	if [-z "${MENDER_ARTIFACT_NAME}"]; then
		bbfatal "Need to define MENDER_ARTIFACT_NAME variable."
	fi

	rootfs_size=$(stat -Lc %s ${DEPLOYDIR}/fitImage-${INITRAMFS_IMAGE_NAME}-${KERNEL_FIT_NAME}.bin)
	calc_rootfs_size=$(expr ${MENDER_CALC_ROOTFS_SIZE} \* 1024)
	if [$rootfs_size -gt $calc_rootfs_size]; then
		bbfatal "Size of rootfs is greater than the calculated partition space ($rootfs_size > $calc_rootfs_size). This image won't fit on a device with the current storage configuration. Try reducing IMAGE_OVERHEAD_FACTOR if it is higher than 1.0, or raise MENDER_STORAGE_TOTAL_SIZE_MB if the device in fact has more storage."
	fi

	if [-z "${MENDER_DEVICE_TYPES_COMPATIBLE}"]; then
		bbfatal "MENDER_DEVICE_TYPES_COMPATIBLE variable cannot be empty."
	fi

	extra_args=

	for dev in ${MENDER_DEVICE_TYPES_COMPATIBLE}; do
		extra_args="$extra_args -t $dev"
	done

	if [-n "${MENDER_ARTIFACT_SIGNING_KEY}"]; then
		extra_args="$extra_args -k ${MENDER_ARTIFACT_SIGNING_KEY}"
	fi

	if [-d "${DEPLOY_DIR_IMAGE}/mender-state-scripts"]; then
		extra_args="$extra_args -s ${DEPLOY_DIR_IMAGE}/mender-state-scripts"
	fi

	if mender-artifact write rootfs-image --help | grep -e '-u FILE'; then
		image_flag=-u
	else
		image_flag=-f
	fi

	if [-n "${MENDER_ARTIFACT_NAME_DEPENDS}"]; then
		cmd=""
		apply_arguments "--artifact-name-depends" "${MENDER_ARTIFACT_NAME_DEPENDS}"
		extra_args="$extra_args $cmd"
	fi

	if [-n "${MENDER_ARTIFACT_PROVIDES}"]; then
		cmd=""
		apply_arguments "--provides" "${MENDER_ARTIFACT_PROVIDES}"
		extra_args="$extra_args $cmd"
	fi

	if [-n "${MENDER_ARTIFACT_PROVIDES_GROUP}"]; then
		cmd=""
		apply_arguments "--provides-group" "${MENDER_ARTIFACT_PROVIDES_GROUP}"
		extra_args="$extra_args $cmd"
	fi

	if [-n "${MENDER_ARTIFACT_DEPENDS}"]; then
		cmd=""
		apply_arguments "--depends" "${MENDER_ARTIFACT_DEPENDS}"
		extra_args="$extra_args $cmd"
	fi

	if [-n "${MENDER_ARTIFACT_DEPENDS_GROUPS}"]; then
		cmd=""
		apply_arguments "--depends-groups" "${MENDER_ARTIFACT_DEPENDS_GROUPS}"
		extra_args="$extra_args $cmd"
	fi

	# Create the mender FIT image artifact
	# KERNEL_FIT_NAME = -${PV}-${PR}${IMAGE_VERSION_SUFFIX} 
	mender-artifact write rootfs-image \
		-n ${MENDER_ARTIFACT_NAME} \
		$extra_args \
		-f ${DEPLOYDIR}/fitImage-${INITRAMFS_IMAGE_NAME}-${KERNEL_FIT_NAME}.bin \
		${MENDER_ARTIFACT_EXTRA_ARGS} \
		-o ${DEPLOYDIR}/fitImage-${INITRAMFS_IMAGE_NAME}-${KERNEL_FIT_NAME}.mender \

	# Deploy it, creating symlinks as it's in the DEPLOYDIR it should be removed by cleansstate
	ln -snf fitImage-${INITRAMFS_IMAGE_NAME}-${KERNEL_FIT_NAME}.mender ${DEPLOYDIR}/fitImage-${INITRAMFS_IMAGE_NAME}-${MACHINE}.mender
}

```

and then in the kernel recipe

`inherit mender-artifact-fit`

---

<div class="post-metadata">

**Author:** ![martin](https://avatars.discourse-cdn.com/v4/letter/m/73ab20/32.png) [@martin](https://hub.mender.io/u/martin)\
**Post date:** [June 18, 2020, 8:12am UTC](https://hub.mender.io/t/fit-image-with-initramfs-as-an-artifact/2057/8 "2020-06-18T08:12:21Z")

</div>

I have one query, the final menderised kernel image is slightly smaller than the original

```
-rw-r--r-- 2 martin martin 20631160 Jun 18 08:36 fitImage-octave-cad-image-octopuck-mt7688an--5.4.40-r0-octopuck-mt7688an-20200618072941.bin
-rw-rw-r-- 2 martin martin 20585472 Jun 18 08:36 fitImage-octave-cad-image-octopuck-mt7688an--5.4.40-r0-octopuck-mt7688an-20200618072941.mender

```

I was expecting it to be slightly larger due to the artifact mender, have I messed up somewhere with the above code or would you expect it to be smaller?

---

<div class="post-metadata">

**Author:** ![mirzak](https://yyz2.discourse-cdn.com/flex036/user_avatar/hub.mender.io/mirzak/32/2056_2.png) [@mirzak](https://hub.mender.io/u/mirzak)\
**Post date:** [June 18, 2020, 8:15am UTC](https://hub.mender.io/t/fit-image-with-initramfs-as-an-artifact/2057/9 "2020-06-18T08:15:11Z")

</div>

> [@martin](#):
>
> `fitImage-octave-cad-image-octopuck-mt7688an--5.4.40-r0-octopuck-mt7688an-20200618072941.mender`

I would expect the `.mender` file to be smaller. The payload is compressed using `gzip`.

You can actually unpack it and inspect,

```auto
tar xvf fitImage-octave-cad-image-octopuck-mt7688an--5.4.40-r0-octopuck-mt7688an-20200618072941.mender

```

---

<div class="post-metadata">

**Author:** ![martin](https://avatars.discourse-cdn.com/v4/letter/m/73ab20/32.png) [@martin](https://hub.mender.io/u/martin)\
**Post date:** [June 18, 2020, 8:22am UTC](https://hub.mender.io/t/fit-image-with-initramfs-as-an-artifact/2057/10 "2020-06-18T08:22:12Z")

</div>

phew, that makes sense. The FIT image is already compressed I think hence why it’s only slightly smaller 🙂

---

<div class="post-metadata">

**Author:** ![martin](https://avatars.discourse-cdn.com/v4/letter/m/73ab20/32.png) [@martin](https://hub.mender.io/u/martin)\
**Post date:** [June 18, 2020, 12:59pm UTC](https://hub.mender.io/t/fit-image-with-initramfs-as-an-artifact/2057/11 "2020-06-18T12:59:17Z")

</div>

I can create my custom image now. Just waiting on a board with access to the SPI-NOR pins so I can program it to test it out.

In the initramfs image that I use I have disabled menderisation of the rootfs but left the dataimg partition creation as this is required. Note: **octimg** is my custom **ubimg**.

```
IMAGE_FSTYPES_remove = "mender mender.bmap octimg octimg.bmap mtdimg"
IMAGE_FSTYPES_append = " dataimg"

```

Then I created my dummy top level container image that is used just to create my custom image.

```
SUMMARY = "Dummy image for creating custom mender image octimg"

DESCRIPTION = "Blah Blah."

inherit image

DEPENDS = "virtual/kernel virtual/bootloader"
RDEPENDS = ""
# The Depends on virtual/kernel is not enough. This ensures that the kernel FIT image has
# been deployed to DEPLOY_DIR_IMAGE which is required by the mender-octimg.bbclass 
do_image[depends] += "virtual/kernel:do_deploy"

ROOTFS_BOOTSTRAP_INSTALL = ""

IMAGE_FSTYPES = "mender mender.bmap octimg octimg.bmap mtdimg"

IMAGE_INSTALL = "kernel-image"
IMAGE_INSTALL_remove = "mender-client"
LINGUAS_INSTALL = ""

```

Then mender-octimg.bbclass is a rip off of the mender-ubimg.bbclass expect for the ubinize configuration:

```
[rootfsA]
mode=ubi
image=${DEPLOY_DIR_IMAGE}/fitImage-${INITRAMFS_IMAGE_NAME}-${MACHINE}
vol_id=0
vol_size=${MENDER_CALC_ROOTFS_SIZE}KiB
vol_type=dynamic
vol_name=rootfsa

[rootfsB]
mode=ubi
image=${DEPLOY_DIR_IMAGE}/fitImage-${INITRAMFS_IMAGE_NAME}-${MACHINE}
vol_id=1
vol_size=${MENDER_CALC_ROOTFS_SIZE}KiB
vol_type=dynamic
vol_name=rootfsb

[data]
mode=ubi
image=${DEPLOY_DIR_IMAGE}/${INITRAMFS_IMAGE_NAME}.dataimg
vol_id=2
vol_size=${MENDER_DATA_PART_SIZE_MB}MiB
vol_type=dynamic
vol_name=data

```

Note how this uses **DEPLOY\_DIR\_IMAGE** instead of the **IMGDEPLOYDIR** as our image is just a dummy image and the files we want to use have already been built and deployed.

Creates the image fine and **cleansstate** clears things up nicely. I’ll let you know how I get on when I get the board I can flash.

If anyone spots any problems or has any suggestions I would be grateful for any feedback.
