Use FIT Image with Embedded Device Tree - Patch on Patch or Custom Patch?

Hey all,

I’m working with the BeagleV-Fire, which in the boot method from Microchip, mainly uses FIT images and boot scripts which have both the kernel and dtb included via configurations.

Yocto Wrynose is moving more towards multi-config FIT images too with security verification, which is the highly preferred path forward.

The standard Mender boot command patch integration mainly uses ${mender_boot_kernel_type} and ${fdt_addr_r} for loading kernels and device trees. This fails for me if I am using FIT images since I’m not using a separate device tree file or those addresses. I’ve seen FIT image calls for choosing the kernel boot type, just want to avoid using local dtb files.

Obviously, I can make a patch but I hesitate on making a patch on a patch since that seems like using integration on integrations.

A. What is the recommended and supported approach so I avoid using ${kernel_addr_r}, ${fdt_addr_r} and ${mender_dtb_name}, while just using ${mender_kernel_name} and ${scriptaddr} in U-Boot? Do I patch the patch output of env_mender.h?

Here are the lines of interest:

140-144 env_mender.h

# define MENDER_LOAD_KERNEL_AND_FDT                                     \
    "if test \"${fdt_addr_r}\" != \"\"; then "                          \
    "load ${mender_uboot_root} ${fdt_addr_r} /boot/${mender_dtb_name}; " \
    "fi; "                                                              \
    "load ${mender_uboot_root} ${kernel_addr_r} /boot/${mender_kernel_name}; "

Which using stock mender patches returns the following error:

Wrong Image Type for bootm command
ERROR -91: can't get kernel image!

My preferred approach is using a boot.scr that calls the mender logic as seen in RAUC and other upgrade engine solutions. I’ve also seen this in articles and forums as a boot method. Preferably, there’s lines in the Microchip boot.scr that prepare the kernel and fdt addresses using bootm. I have modified to include Mender environment variables.

For example:

run mender_setup;
load ${mender_uboot_root} ${scriptaddr} /boot/${mender_kernel_name};
${mender_boot_kernel_type} start ${scriptaddr};
${mender_boot_kernel_type} loados;
${mender_boot_kernel_type} ramdisk;
${mender_boot_kernel_type} prep;
${mender_boot_kernel_type} go;

B. Lastly, what is the benefit of using the Mender boot partition environment variable?

Based on my Mender understanding kernels are found in the root filesystem so calls to loading files to addresses should be found there. Are there instances seen where the boot partition can be used that aligns with Mender logic?

We had a similar issue, we just completely replaced boot.cmd in a .bbappend. It’s a bit brittle perhaps but it works fine for now. e.g.

run mender_setup
load ${mender_uboot_root} ${kernel_addr_r} /boot/fitImage || run mender_try_to_recover
bootm ${kernel_addr_r}#${fitconf_${mender_boot_part}} || run mender_try_to_recover
run mender_try_to_recover

@lukehatpadl Thanks for the suggestion!

Ive tried that approach before and can get how it works as a solution.

My concern mainly is if somehow something fails in the boot.scr for any reason, then it would default to standard bootcmd from Mender, which goes back to the kernel_addr_r and fdt_addr_r boot method.

That’s what had me think of making a patch file for that env_mender.h but wasn’t sure if that would be supported/stable apprach.

Hi @Spellbind3162,

My gut feeling is that a patch is more straightforward here. The mender_boot_part provides the partition from which loading the kernel is expected to happen, as well as the root filesystem.

For a low-friction take on booting fitImages, I would take a look at the integration for the Allwinner D1 on the Nezha board: meta-mender-community/meta-mender-riscv/recipes-bsp/u-boot at scarthgap · TheYoctoJester/meta-mender-community · GitHub

The boot.scr as indicated would not be A/B aware as far as I can see, so by going for it you’d essentially just add the patching somewhere else, and include another moving part, so my take would be to avoid it.

Greetz,
Josef

@TheYoctoJester Thank you for the recommendation!

Originally I was looking at a loose boot.scr file that are in the IMAGE_BOOT_FILES, but realized that boot.scr’s are able to be embedded inside of the FIT. Microchip has this as a part of their standard BeagleV-Fire setup and if you load the fitImage to the ${scriptaddr}, it will use the built-in commands like in that example you sent over. If we want, RAM disks can also be embedded in FITs as well, only requiring:

${mender_boot_kernel_type} ramdisk

Trying to catch any gotchas early on, so if you can think of any other considerations, I’m all ears. The logic I am thinking is if kernels are put in the rootfs on upgrades, that would also upgrade the boot.scr if I make any changes. This also changes if I want to include an initramfs.

If I load the FIT to ${scriptaddr} rather than ${kernel_addr_r} or ${fdt_addr_r} in the mender_bootcmd logic, is there still room for altbootcmd post artifact install? I’m still thinking of using Mender environment variables for that dynamic A/B logic even in the FIT boot.scr.

Also, if I’m understanding you correctly, my diversion for A/B logic would be if I had a loose boot.scr in the boot directory?

Hi @Spellbind3162,

The question is, where does the A/B selection of fitImages happen? If it’s in the singular boot.scr script on the boot partition, then I don’t see how it reduces the maintenance burden versus just adjusting the boot login in u-boot itself. In either case, you have to patch one file.

If your boot.scr is expected to live inside the fitImage, then it is part of the A/B process already, and the logic has to live within earlier boot stages in u-boot itself again. Plus, I’d expect the passing of the correct root partition to such a “shipped” boot.scr to be a source of headaches: when deploying, there’s no way to tell if you are on A or B, so all logic must be partition agnostic.

On the “If I load the FIT to ${scriptaddr} rather than ${kernel_addr_r} or ${fdt_addr_r} in the mender_bootcmd logic, is there still room for altbootcmd post artifact install?” question, not sure I follow. The altbootcmd logic is meant to kick in once a boot attempt during an update failed, and the diversion is before loading the fitImage, only based on the information in the environment.

Greetz,
Josef

@TheYoctoJester

So bootcmd would still be used. This is a temporary test I was making in the generic boot code applied patch from Mender. It was working, even if I didnt have an embedded boot.scr. However, I am thinking the boot.scr isn’t even used in my setup so I am changing my approach. This is likely because the fitImage is loaded to an alternate address, then bootm starts that from memory so nothing is overwritten like how I’ve been seeing.

# define MENDER_LOAD_KERNEL_AND_FDT                                     \
    "if test \"${scriptaddr}\" != \"\"; then "                          \
    "load ${mender_uboot_root} ${scriptaddr} /boot/${mender_kernel_name}; " \
    "fi; "

Basically changed to that example above from this:

# define MENDER_LOAD_KERNEL_AND_FDT                                     \
    "if test \"${fdt_addr_r}\" != \"\"; then "                          \
    "load ${mender_uboot_root} ${fdt_addr_r} /boot/${mender_dtb_name}; " \
    "fi; "                                                              \
    "load ${mender_uboot_root} ${kernel_addr_r} /boot/${mender_kernel_name}; "

The usage of altbootcmd in its entirety wasn’t clear, so you cleared it up for me.

Moving forward, I think I’m going to move away from boot.scr, even embedded, and see how I can load the FIT to kernel_addr_r and fdt_addr_r. Still planning on doing some further testing, so will follow up here if I find out anything useful that aligns with Mender logic. Loading FIT images is a great resource, and I’d really like to use them with Mender boot commands.

1 Like