Compulab IOT-GATE-IMX8 does not generate uboot.env file anymore

Hello,

my goal is to update an NXP imx8mm based Compulab iot-gate-imx8 from Yocto Zeus to Kirkstone.

We have made some modifications two years ago:
We are using u-boot without grub because we wanted to have a read-only boot partition and that was apparently not possible with grub (Making boot filesystem read-only - #8 by rbarlow_bel).
U-Boot then had to be patched to provide a custom environment, which worked as expected in Zeus.

Now I am upgrading to Kirkstone. I have not touched the configs except for updating to Bitbake 2 syntax and I had to include mender-artifact-info because the artifact_info was not generated anymore.

Now at the very end of the compilation it throws an error that uboot.env is missing in tmp/deploy/...

With Kirkstone, u-boot-compulab has been updated from 2020.04 to 2021.04.
I have checked the patch for a custom env manually with

bitbake -c unpack u-boot-compulab
bitbake -c configure u-boot-compulab
bitbake -c compile u-boot-compulab

and it is still applied.
The patch changes the include/configs/iot-gate-imx8.h file, which is only generated after the configure step.

As soon as I remove mender-uboot from the distro features, everything works as expected.

After extensive research, I could not find out why the uboot.env could fail.
Can someone help me what else I should do or what I should try out?

I appreciate any help or reference to resources.
Thank you,
Dominik

After more research I have found that since dunfell (meta-mender patch notes) libubootenv is being used. We have used u-boot-fw-utils by Mender in the past. Might this be the problem?

Hi @Dominik-Hstein,

Thanks for reaching out. The question rather is, where or what is falling over in the build process. For example, if u-boot.env is nowhere needed, then it is not a problem if it not being built. Just guessing, I would think that somehow u-boot.env is added to IMAGE_BOOT_FILES somewhere, and therefore expected to be available during image creation. So that is what I would check first, and then make my way from there.

In the end for Mender it is just important that a form of environment is around, and there is a way to interact with it.

If you can provide us with a build setup to replicate then we can also have a look.

Greetz,
Josef

Hello Josef,

Thank you for the answer.

Regarding the boot files, I have found that some vendors use IMAGE_BOOT_FILES:remove = "uboot.env" in their local.conf.append, but this had no effect for me.

I have attached a build setup as code blocks below.
It is basically the minimal reproduceable setup I could get, even without a custom layer.

In summary, the local.conf consists of the .conf.appends that are given by Compulab and there are no changes to our zeus setup except that I added mender-artifact-info and linux-firmware-ax200.

The build fails as well when adding the following, respectively:

IMAGE_BOOT_FILES:append = " boot.scr "
CORE_IMAGE_EXTRA_INSTALL += " u-boot-script "
MACHINE_EXTRA_RDEPENDS:remove = "u-boot-fw-utils"
BBMASK += "meta-mender-core/recipes-bsp/grub/grub_%.bbappend"
CORE_IMAGE_EXTRA_INSTALL += " mender-artifact "

Build instructions

  1. Synchronize repo with iot-gate-imx8.xml as the start point
  2. Set up environment: MACHINE=iot-gate-imx8 DISTRO=fsl-imx-xwayland source compulab-setup-env -b build
  3. Replace conf/*.conf files with those from the attachment.
  4. Build with bitbake -k core-image-full-cmdline
  5. The error missing uboot.env will appear

Appendix

A: local.conf

MACHINE ??= 'iot-gate-imx8'
DISTRO ?= 'fsl-imx-xwayland'
PACKAGE_CLASSES ?= 'package_rpm'
USER_CLASSES ?= "buildstats"
PATCHRESOLVE = "noop"
BB_DISKMON_DIRS ??= "\
    STOPTASKS,${TMPDIR},1G,100K \
    STOPTASKS,${DL_DIR},1G,100K \
    STOPTASKS,${SSTATE_DIR},1G,100K \
    STOPTASKS,/tmp,100M,100K \
    HALT,${TMPDIR},100M,1K \
    HALT,${DL_DIR},100M,1K \
    HALT,${SSTATE_DIR},100M,1K \
    HALT,/tmp,10M,1K"
PACKAGECONFIG:append:pn-qemu-system-native = " sdl"
CONF_VERSION = "2"
DL_DIR ?= "${BSPDIR}/downloads/"
ACCEPT_FSL_EULA = "1"
INHERIT += "mender-full"
LICENSE_FLAGS_ACCEPTED = "commercial"

CORE_IMAGE_EXTRA_INSTALL:append:iot-gate-imx8 = " linux-firmware-ax200"
EXTRA_IMAGE_FEATURES:append:iot-gate-imx8 = " ssh-server-openssh "

HOSTTOOLS += " git-lfs"
MENDER_IMAGE_BOOTLOADER_FILE = "imx-boot"
MENDER_IMAGE_BOOTLOADER_BOOTSECTOR_OFFSET = "66"
IMAGE_FSTYPES:remove = "tar.gz ext4 wic.gz wic.bmap multiubi mender.bmap"
MENDER_FEATURES_ENABLE:append = " mender-uboot mender-image-sd "
MENDER_FEATURES_DISABLE:append = " mender-grub mender-image-uefi "

MENDER_STORAGE_DEVICE = "/dev/mmcblk2"
MENDER_UBOOT_STORAGE_DEVICE = "2"
UBOOT_CONFIG = "sd"
MENDER_ARTIFACT_NAME = "kirkstone-mender-image"

DISTRO_FEATURES:append = " systemd"
VIRTUAL-RUNTIME_init_manager = "systemd"
DISTRO_FEATURES_BACKFILL_CONSIDERED = "sysvinit"
VIRTUAL-RUNTIME_initscripts = ""
VIRTUAL-RUNTIME_syslog = "rsyslog"
ARTIFACTIMG_FSTYPE = "ext4"

IMAGE_FEATURES = "read-only-rootfs hwcodecs"

MENDER_STORAGE_TOTAL_SIZE_MB = "5264"
MENDER_BOOT_PART_SIZE_MB = "40"
MENDER_DATA_PART_SIZE_MB = "512"

DISTRO_FEATURES:append = " \
                          wifi \
                          3g \
                          ipsec \
                          ipv6 \
                          zeroconf \
                          "
# this is necessary since zeus because it does not generate an artifact info
DISTRO_EXTRA_RDEPENDS:append = " mender-artifact-info "
IMAGE_INSTALL:append = " \
                         kernel-image \
                         kernel-devicetree \
                         wireless-regdb-static \
                         "
HOSTTOOLS += " bc "
CONFIG_AUTOBOOT_KEYED = "1"
CONFIG_AUTOBOOT_ENCRYPTION = "1"
IMAGE_FEATURES:remove = "splash"

DL_DIR ?= "${BSPDIR}/downloads/"

B: bblayers.conf

LCONF_VERSION = "7"

BBPATH = "${TOPDIR}"
BSPDIR := "${@os.path.abspath(os.path.dirname(d.getVar('FILE', True)) + '/../..')}"

BBFILES ?= ""
BBLAYERS = " \
  ${BSPDIR}/sources/poky/meta \
  ${BSPDIR}/sources/poky/meta-poky \
  \
  ${BSPDIR}/sources/meta-openembedded/meta-oe \
  ${BSPDIR}/sources/meta-openembedded/meta-python \
  \
  ${BSPDIR}/sources/meta-freescale \
  ${BSPDIR}/sources/meta-freescale-3rdparty \
  ${BSPDIR}/sources/meta-freescale-distro \
"
#${BSPDIR}/sources/meta-openembedded/meta-multimedia

# i.MX Yocto Project Release layers
BBLAYERS += "${BSPDIR}/sources/meta-imx/meta-bsp"
BBLAYERS += "${BSPDIR}/sources/meta-imx/meta-sdk"
#BBLAYERS += "${BSPDIR}/sources/meta-imx/meta-ml"
#BBLAYERS += "${BSPDIR}/sources/meta-imx/meta-v2x"
#BBLAYERS += "${BSPDIR}/sources/meta-nxp-demo-experience"

#BBLAYERS += "${BSPDIR}/sources/meta-browser/meta-chromium"
#BBLAYERS += "${BSPDIR}/sources/meta-clang"
#BBLAYERS += "${BSPDIR}/sources/meta-openembedded/meta-gnome"
BBLAYERS += "${BSPDIR}/sources/meta-openembedded/meta-networking"
BBLAYERS += "${BSPDIR}/sources/meta-openembedded/meta-filesystems"
#BBLAYERS += "${BSPDIR}/sources/meta-qt6"
#BBLAYERS += "${BSPDIR}/sources/meta-virtualization"
BBLAYERS += "${BSPDIR}/sources/meta-bsp-imx8mm"
BBLAYERS += " \
  ${BSPDIR}/sources/meta-compulab \
  ${BSPDIR}/sources/meta-compulab-bsp/meta-bsp \
  ${BSPDIR}/sources/meta-compulab-bsp/meta-net \
  ${BSPDIR}/sources/meta-compulab-bsp/meta-utils \
"
#${BSPDIR}/sources/meta-compulab-bsp/meta-graphics
#${BSPDIR}/sources/meta-compulab-bsp/meta-devtool
#${BSPDIR}/sources/meta-compulab-bsp/meta-multimedia
#${BSPDIR}/sources/meta-compulab-bsp/meta-desktop
BBLAYERS += "${BSPDIR}/sources/meta-mender/meta-mender-core"
BBLAYERS += "${BSPDIR}/sources/meta-mender-compulab"

# not using these
BBMASK .= "meta-compulab/recipes-browser"
BBMASK .= "|meta-imx/meta-sdk/dynamic-layers/openembedded-layer/recipes-multimedia"

C: Main Manifest

<?xml version="1.0" encoding="UTF-8"?>
<manifest>
  // This file includes manifests from vendors like board support package, mender support, etc.

  <include name="manifests/imx-5.15.32-2.0.0.xml" />
  <include name="manifests/imx_5.15.32-2.0.0-compulab.xml" />
  <include name="manifests/mender-compulab-kirkstone.xml" />
</manifest>

D: imx Manifest

<?xml version="1.0" encoding="UTF-8"?>
<manifest>
  // from here: https://github.com/nxp-imx/imx-manifest/blob/imx-linux-kirkstone/imx-5.15.32-2.0.0.xml

  <default sync-j="2"/>

  <remote fetch="https://github.com/nxp-imx" name="nxp-imx"/>
  <remote fetch="https://github.com/OSSystems" name="OSSystems"/>
  <remote fetch="https://code.qt.io/yocto"  name="QT6"/>
  <remote fetch="https://github.com/TimesysGit"  name="Timesys"/>
  <remote fetch="https://github.com/kraj" name="clang"/>
  <remote fetch="https://github.com/Freescale" name="community"/>
  <remote fetch="https://github.com/openembedded" name="oe"/>
  <remote fetch="https://git.yoctoproject.org/git" name="yocto"/>
  <remote fetch="https://github.com/nxp-imx-support" name="imx-support"/>

  <project name="fsl-community-bsp-base" path="sources/base" remote="community" revision="60f79f7af60537146298560079ae603260f0bd14" upstream="kirkstone">
    <linkfile dest="README" src="README"/>
    <linkfile dest="setup-environment" src="setup-environment"/>
  </project>
  <project name="meta-browser" path="sources/meta-browser" remote="OSSystems" revision="d25d8ee98a656b2534d0eec6138ef264529fab4f"/>
  <project name="meta-clang" path="sources/meta-clang" remote="clang" revision="85d956d95401479ca666139e31f662f60c156d5f" upstream="kirkstone"/>
  <project name="meta-freescale" path="sources/meta-freescale" remote="community" revision="2fb1ce365338126aad365012ebb913b3e4a9f1be" upstream="kirkstone"/>
  <project name="meta-freescale-3rdparty" path="sources/meta-freescale-3rdparty" remote="community" revision="de0eb1408150d77f9cce97c559f9a5a3c71e5d6c" upstream="kirkstone"/>
  <project name="meta-freescale-distro" path="sources/meta-freescale-distro" remote="community" revision="fc15f5003043da23212596be7366ae2547c308ad" upstream="kirkstone"/>

  <project name="meta-imx" path="sources/meta-imx" remote="nxp-imx" revision="refs/tags/rel_imx_5.15.32_2.0.0_gh" upstream="kirkstone-5.15.32-2.0.0">
    <linkfile dest="imx-setup-release.sh" src="tools/imx-setup-release.sh"/>
    <linkfile dest="README-IMXBSP" src="README"/>
  </project>

  <project name="meta-nxp-demo-experience" path="sources/meta-nxp-demo-experience" remote="imx-support" revision="35c364933945dd15b7a96b60675fc304ce6fb881" upstream="kirkstone-5.15.32-2.0.0"/>
  <project name="meta-openembedded" path="sources/meta-openembedded" remote="oe" revision="5357c7a40eaf8d1bcf7ff58edbba8e9527e40c7d" upstream="kirkstone"/>
  <project name="meta-qt6" path="sources/meta-qt6" remote="QT6" revision="b2894aad5c1aaa85f2f5c7b94391b7c51c39e555" upstream="6.3"/>
  <project name="meta-timesys" path="sources/meta-timesys" remote="Timesys" revision="edce180f0389a13e678cb0edafb7f8980648e1a4"/>
  <project name="meta-virtualization" path="sources/meta-virtualization" remote="yocto" revision="973c8d0964c6f40338857efe5b8009b2f647d485"/>
  <project name="poky" path="sources/poky" remote="yocto" revision="27de52e402ae000dfa502d52908cd6e6aef923ec" upstream="kirkstone"/>
</manifest>

E: Compulab Manifest

<?xml version="1.0" encoding="UTF-8"?>
<manifest>
  // origin: https://github.com/compulab-yokneam/meta-bsp-imx8mm/blob/iot-gate-imx8-r3.2.1/scripts/imx_5.15.32-2.0.0-compulab.xml

  <remote fetch="https://github.com/compulab-yokneam" name="compulab"/>

  <project name="meta-compulab" remote="compulab" revision="6316d8ca737f7460ea24d83f3aeec9f8d00b6e8a" path="sources/meta-compulab"/>
  <project name="meta-compulab-bsp" remote="compulab" revision="7f5882eb9bd139e4dde204ffa6b0aa96577b36d0" path="sources/meta-compulab-bsp"/>
  <project name="meta-bsp-imx8mm" remote="compulab" revision="iot-gate-imx8-r3.2.1" path="sources/meta-bsp-imx8mm" >
    <linkfile src="tools/compulab-setup-env" dest="compulab-setup-env" />
  </project>

</manifest>

F: Mender Manifest

<?xml version="1.0" encoding="UTF-8"?>
<manifest>
  // from here: https://github.com/compulab-yokneam/meta-mender-compulab/blob/c39f00e092598c0404fb572aeb3edda622c080a4/scripts/mender-compulab-kirkstone.xml
  // Had to make some minor adjustments: e.g. compulab was using kirkstone-next but we want a stable kirkstone

  <project name="meta-mender-compulab" remote="compulab" revision="kirkstone-nxp" path="sources/meta-mender-compulab">
    <linkfile src="tools/mender-setup-environment" dest="mender-setup-environment" />
  </project>

  <remote fetch="https://github.com/mendersoftware" name="mender"/>

  <project name="meta-mender" remote="mender" revision="kirkstone" path="sources/meta-mender"/>
  <project name="meta-mender-community" remote="mender" revision="kirkstone" path="sources/meta-mender-community"/>

</manifest>

I am pretty sure that the problem is that Compulab has changed the bootloader provider since zeus.

In Zeus, they were using u-boot-imx as a provider and applied their patches to that.
Now they have introduced their own u-boot-compulab.

I guess that the environment is not set up correctly for mender and that there needs to be a different env script, which we included in the past, but now have trouble getting to be included.

Nevertheless, the default config like above should still build without needing a custom env script, because it is derived from the meta-mender-compulab.

Hi @Dominik-Hstein,

Thanks for the detailed description. I’m just getting started working my way through it to understand the build architecture. Will get back to you as soon as possible!

Greetz,
Josef

Hi @Dominik-Hstein,

the good news first: I could reproduce the problem.
The bad news, I don’t have a solution, at least not right off the cuff. Some findings and thoughts to share:

  • the u-boot fork feels quite a bit whacked to me, especially given the patch count in the layer
  • digging around a bit, the environment creation seems to not be part of the main u-boot build, but being done additionally in the specific BSP. One that I could find for example is on Atmel.

My suggestion would be to get in touch with the Compulab support, this definitely is something they should fix in their provided integration layer.

Greetz,
Josef

Hi Josef,

thank you very much for the investigation. This definitely helps.

  • Yes, the patches add changes, then remove them again, then add a few lines and remove again. It seems to have grown over time and not really cleaned up.
  • We create our own env by modifying the u-boot’s CONFIG_EXTRA_ENV_SETTINGS in include/configs/iot-gate-imx8.h, so the default env is not needed anyway. So if I get this correctly, the env variables are present, but are just not installed.
    I can try to add a compile task similar to the one from Atmel and I might make progress. I will try that.

I will write Compulab with the information you provided.
Thank you again.

Best Regards,
Dominik

1 Like

Thanks to your investigation Compulab could help me and when I apply the following patch it can build:

index 7fd4bef..89a9490 100644
--- a/recipes-bsp/u-boot/u-boot-compulab_2021.04.bb
+++ b/recipes-bsp/u-boot/u-boot-compulab_2021.04.bb
@@ -42,6 +42,9 @@ do_deploy:append () {
         unset  i
     fi
 
+    if [ -n "${UBOOT_INITIAL_ENV}" ]; then
+        install -D -m 644 ${B}/${config}/u-boot-initial-env-${type} ${DEPLOYDIR}/uboot.env
+    fi
 }
 
 require u-boot-compulab-env.inc
1 Like

Great, thanks for sharing!

Hello again,

Sadly, our vendor only supports Mender with GRUB. Therefore, we have to integrate it ourselves, but are struggling.
Although the patch above installs the correct environment in the deploy directory, it does not work properly on hardware.

In summary, after flashing the image onto the eMMC with bzcat /home/root/core-image-full-cmdline-iot-gate-imx8-2023.sdimg.bz2 | dd of=/dev/mmcblk2 bs=32M status=progress,

  • the correct U-Boot version shows up
  • when adding u-boot-mender.inc to u-boot-compulab, the mender env is built and deployed to one location but uboot.env is empty, while u-boot-compulab-initial-env-iot-gate-imx8-sd-2021.04-r0 holds the desired environment
  • (A) printenv displays the correct environment
  • (B) the saveenv command throws an error
  • (C) the image is bootable
  • (D) inside user space, fw_printenv prints an error
  • (E) the sdimg has its environment at a different location than the previous image, and only 1 time instead of three times
  • (F) the environment offset in the sdimg is never at the configured offset in the sdimg, but a hexdump on the mmc inside the user space of the zeus image shows the environment at the desired offsets
  • (G) we have made some modifications to u-boot-compulab since it does not include Mender by default
  • (H) diff between zeus and kirkstone iot-gate-imx8_defconfig

Questions upfront:

  1. Do we need to force the Mender overhead back to the zeus value?
  2. Why is uboot.env empty? It is also empty in the older zeus build, but it works in that case. But if I understood your first answer correctly, we don’t need to care about uboot.env, as long as the env is present at 0x800000 and 0x1000000
  3. Edit: maybe this is an issue because Compulab has provided their own u-boot-fw-utils, while mender appends on libubootenv? I have now removed compulab’s fw-utils, no change.

A: printenv displays the correct environment

IOT-GATE-iMX8 => printenv
altbootcmd=run mender_altbootcmd; run bootcmd
baudrate=115200
bluerange_mender_post_setup_commands=setenv bootargs ${bootargs} rootwait console=ttymxc2,115200 earlycon=ec_imx6q,0x30880000,115200 net.ifnames=0; echo "bootargs set to ${bootargs}"
bluerange_mender_pre_setup_commands=setenv mender_dtb_name "${fdt_file}"; echo "mender_dtb_name set to ${mender_dtb_name}";
bootcmd=run mender_setup; setenv bootargs root=${mender_kernel_root} ${bootargs}; 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}; ${mender_boot_kernel_type} ${kernel_addr_r} - ${fdt_addr_r}; run mender_try_to_recover
bootcount=1
bootdelay=2
bootdev=2
bootlimit=1
bootstopkeysha256=<blurred>
ethaddr=00:01:c0:30:3b:41
ethprime=FEC
fastboot_dev=mmc2
fdt_addr_r=0x43000000
fdt_file=sb-iotgimx8.dtb
fdtcontroladdr=b6d20230
kernel_addr_r=0x40480000
loadaddr=0x40480000
mender_altbootcmd=if test ${mender_boot_part} = 2; then setenv mender_boot_part 3; setenv mender_boot_part_hex 3; else setenv mender_boot_part 2; setenv mender_boot_part_hex 2; fi; setenv upgrade_available 0; saveenv; run mender_setup
mender_boot_kernel_type=booti
mender_boot_part=2
mender_boot_part_hex=2
mender_check_saveenv_canary=1
mender_dtb_name=sb-iotgimx8.dtb
mender_kernel_name=Image
mender_post_setup_commands= run bluerange_mender_post_setup_commands;
mender_pre_setup_commands= run bluerange_mender_pre_setup_commands;
mender_setup=if test "${mender_saveenv_canary}" != "1"; then setenv mender_saveenv_canary 1; saveenv; fi; if test "${mender_pre_setup_commands}" != ""; then run mender_pre_setup_commands; fi; if test "${mender_systemd_machine_id}" != ""; then setenv bootargs "systemd.machine_id=${mender_systemd_machine_id} ${bootargs}"; fi; setenv mender_kernel_root /dev/mmcblk2p${mender_boot_part}; if test ${mender_boot_part} = 2; then setenv mender_boot_part_name /dev/mmcblk2p2; else setenv mender_boot_part_name /dev/mmcblk2p3; fi; setenv mender_kernel_root_name ${mender_boot_part_name}; setenv mender_uboot_root mmc 2:${mender_boot_part_hex}; setenv mender_uboot_root_name ${mender_boot_part_name}; setenv expand_bootargs "setenv bootargs \\"${bootargs}\\""; run expand_bootargs; setenv expand_bootargs; if test "${mender_post_setup_commands}" != ""; then run mender_post_setup_commands; fi
mender_try_to_recover=if test ${upgrade_available} = 1; then reset; fi
mender_uboot_boot=mmc 2:1
mender_uboot_dev=2
mender_uboot_if=mmc
serial#=1a3999aac2a41100
soc_type=imx8mm
upgrade_available=0

Environment size: 2632/131067 bytes

There are some changes in the env compared to zeus. If we try to remove fastboot again, the compilation fails. Also, the an address has changed.
The diff compared to our zeus environment is:

diff --git a/zeus_uboot.env b/kirkstone_uboot.env
index 5393848..1c64ec8 100644
--- a/zeus_uboot.env
+++ b/kirkstone_uboot.env
@@ -8,11 +8,12 @@ bootdelay=2
 bootdev=2
 bootlimit=1
 bootstopkeysha256=<blurred>
-ethaddr=00:01:c0:2a:a6:23
+ethaddr=00:01:c0:30:3b:41
 ethprime=FEC
+fastboot_dev=mmc2
 fdt_addr_r=0x43000000
 fdt_file=sb-iotgimx8.dtb
-fdtcontroladdr=74d29ee0
+fdtcontroladdr=b6d20230
 kernel_addr_r=0x40480000
 loadaddr=0x40480000
 mender_altbootcmd=if test ${mender_boot_part} = 2; then setenv mender_boot_part 3; setenv mender_boot_part_hex 3; else setenv mender_boot_part 2; setenv mender_boot_part_hex 2; fi; setenv upgrade_available 0; saveenv; run mender_setup
@@ -24,10 +25,11 @@ mender_dtb_name=sb-iotgimx8.dtb
 mender_kernel_name=Image
 mender_post_setup_commands= run bluerange_mender_post_setup_commands;
 mender_pre_setup_commands= run bluerange_mender_pre_setup_commands;
-mender_saveenv_canary=1
 mender_setup=if test "${mender_saveenv_canary}" != "1"; then setenv mender_saveenv_canary 1; saveenv; fi; if test "${mender_pre_setup_commands}" != ""; then run mender_pre_setup_commands; fi; if test "${mender_systemd_machine_id}" != ""; then setenv bootargs "systemd.machine_id=${mender_systemd_machine_id} ${bootargs}"; fi; setenv mender_kernel_root /dev/mmcblk2p${mender_boot_part}; if test ${mender_boot_part} = 2; then setenv mender_boot_part_name /dev/mmcblk2p2; else setenv mender_boot_part_name /dev/mmcblk2p3; fi; setenv mender_kernel_root_name ${mender_boot_part_name}; setenv mender_uboot_root mmc 2:${mender_boot_part_hex}; setenv mender_uboot_root_name ${mender_boot_part_name}; setenv expand_bootargs "setenv bootargs \\"${bootargs}\\""; run expand_bootargs; setenv expand_bootargs; if test "${mender_post_setup_commands}" != ""; then run mender_post_setup_commands; fi
 mender_try_to_recover=if test ${upgrade_available} = 1; then reset; fi
 mender_uboot_boot=mmc 2:1
 mender_uboot_dev=2
 mender_uboot_if=mmc
+serial#=1a3999aac2a41100
+soc_type=imx8mm
 upgrade_available=0

B: saveenv throws an error

IOT-GATE-iMX8 => saveenv
Saving Environment to MMC... MMC partition switch failed
MMC partition switch failed
Failed (1)
IOT-GATE-iMX8 =>

C: image is bootable

Out:   serial
Err:   serial

 BuildInfo:
  - ATF cb51a0f

FDT[det]: sb-iotgimx8.dtb
flash target is MMC:2
Net:   phy: RTL8211E@0  eth0: ethernet@30be0000
Fastboot: Normal
Normal Boot
Autoboot in 2 seconds
Saving Environment to MMC... MMC partition switch failed
MMC partition switch failed
Failed (1)
mender_dtb_name set to sb-iotgimx8.dtb
bootargs set to rootwait console=ttymxc2,115200 earlycon=ec_imx6q,0x30880000,115200 net.ifnames=0
41995 bytes read in 3 ms (13.3 MiB/s)
30073344 bytes read in 627 ms (45.7 MiB/s)
Moving Image from 0x40480000 to 0x40600000, end=423c0000
## Flattened Device Tree blob at 43000000
   Booting using the fdt blob at 0x43000000
   Loading Device Tree to 00000000b6d11000, end 00000000b6d1e40a ... OK
Modify /vpu_g1@38300000:status disabled
Modify /vpu_g2@38310000:status disabled
Modify /vpu_h1@38320000:status disabled

Starting kernel ...

[    0.000000] Booting Linux on physical CPU 0x0000000000 [0x410fd034]
[    0.000000] Linux version 5.15.32-iot-gate-imx8m-3.2.1+ (oe-user@oe-host) (aarch64-poky-linux-gcc (GCC) 11.2.0, GNU ld (GNU Binutils) 2.38.20220313) #1 SMP PREEMPT Tue Jul 18 09:22:22 UTC 2023
[    0.000000] Machine model: CompuLab SB-IOTGIMX8 board

D: inside user space, fw_printenv prints an error

fw_printenv does not find the environment

root@localhost:~# fw_printenv
Cannot read environment, using default
Cannot read default environment from file

But the file has the desired offsets

root@localhost:~# cat /etc/fw_env.config
/dev/mmcblk2 0x800000 0x20000
/dev/mmcblk2 0x1000000 0x20000

E: Environment start address in sdimg has changed

  • kirkstone: 0xE7800
  • zeus: 0xD5988, 0x11455110 and 0x1145F110

These were found with a hex editor and searching the sdimg for the altbootcmd=, which is the beginning of our env.

Q:

  1. Between zeus and kirkstone, we had to reduce the MENDER_STORAGE_TOTAL_SIZE_MB from 5272 to 5264 because the mender overhead has increased. Can this cause the increase in the first offset?
  2. In the old zeus image, why are the environments at these locations and not at 0x800000?
    When looking at the .wic image, there is something at 0x800000: mkfs.fat .... boot FAT16 ... This is not a bootable disk.
  3. Also, why are they so close together, unlike specified in redundant offset 0x1000000?

G: our patches and modifications

Our patch is the following: (please note that the bootstopkey is blurred)

diff --git a/include/configs/iot-gate-imx8.h b/include/configs/iot-gate-imx8.h
index 565d53e..ae41f29 100644
--- a/include/configs/iot-gate-imx8.h
+++ b/include/configs/iot-gate-imx8.h
@@ -14,47 +14,29 @@
    #endif
    #endif
    
+#define ENV_CONSOLE console=ttymxc2,115200 earlycon=ec_imx6q,0x30880000,115200
+
+// MWAY: U-Boot Environment Settings
+//
+// Required for Mender integration:
+//
+// `fdt_addr_r`: Load address (RAM) of the device tree.
+//
+// `kernel_addr_r`: Load address (RAM) of the kernel image.
+//
+// `bluerange_mender_{pre,post}_setup_commands`:
+// Board specific command sequences to setup environment variables
+// required by menders u-boot integration.
+//
+// Required for BlueRange production:
+//
+// `bootstopkeysha256`: Default 'password' for unlocking the U-Boot CLI.
+
    #undef CONFIG_EXTRA_ENV_SETTINGS
-#undef CONFIG_BOOTCOMMAND
+#define CONFIG_EXTRA_ENV_SETTINGS \
+    "fdt_addr_r=0x43000000\0" \
+    "kernel_addr_r=" __stringify(CONFIG_SYS_LOAD_ADDR) "\0" \
+    "bluerange_mender_pre_setup_commands=setenv mender_dtb_name \"${fdt_file}\"; echo \"mender_dtb_name set to ${mender_dtb_name}\";\0" \
+    "bluerange_mender_post_setup_commands=setenv bootargs ${bootargs} rootwait "__stringify(ENV_CONSOLE)" net.ifnames=0; echo \"bootargs set to ${bootargs}\"\0" \
+    "bootstopkeysha256=<blurred>\0"
    
-#define ENV_CONSOLE console=ttymxc2,115200 earlycon=ec_imx6q,0x30880000,115200
-#define CONFIG_EXTRA_ENV_SETTINGS		\
-	CONFIG_MFG_ENV_SETTINGS \
-	"autoload=off\0" \
-	"script=boot.scr\0" \
-	"image=Image\0" \
-	"fdt_addr=0x43000000\0"	\
-	"fdt_high=0xffffffffffffffff\0"	\
-	"initrd_high=0xffffffffffffffff\0" \
-	"root_opt=rootwait rw\0" \
-	"bootargs_common="__stringify(ENV_CONSOLE)" net.ifnames=0\0" \
-	"sd_ul=setenv boot_dev_str SD; run boot_try_msg; " \
-	"setenv iface mmc; setenv dev 1; setenv part 1;" \
-	"setenv bootargs console=${console} root=/dev/mmcblk1p2 ${root_opt};\0" \
-	"emmc_ul=setenv boot_dev_str eMMC; run boot_try_msg; " \
-	"setenv iface mmc; setenv dev 2; setenv part 1;" \
-	"setenv bootargs ${bootargs_common} root=/dev/mmcblk2p2 " \
-	"${root_opt};\0" \
-	"usb_ul=setenv boot_dev_str USB; run boot_try_msg; usb reset; " \
-	"setenv iface usb; setenv dev 0; setenv part 1; " \
-	"setenv bootargs ${bootargs_common} root=/dev/sda2 ${root_opt};\0" \
-	"ulbootscript=load ${iface} ${dev}:${part} ${loadaddr} ${script};\0" \
-	"ulimage=load ${iface} ${dev}:${part} ${loadaddr} ${image}\0" \
-	"ulfdt=load ${iface} ${dev}:${part} ${fdt_addr} ${fdt_file};\0" \
-	"bootscript=echo Running bootscript from ${boot_dev_str} ...; " \
-	"source;\0" \
-	"boot_try_msg=echo Trying to boot from ${boot_dev_str} ...;\0"
-#define CONFIG_BOOTCOMMAND \
-	"for src in sd_ul usb_ul emmc_ul; do " \
-		"run ${src}; " \
-		"if run ulbootscript; then " \
-			"run bootscript; " \
-		"else " \
-			"if run ulimage; then " \
-				"if run ulfdt; then " \
-					"echo Booting from ${boot_dev_str} script ...; " \
-					"booti ${loadaddr} - ${fdt_addr}; " \
-				"fi; " \
-			"fi; " \
-		"fi; " \
-	"done; "
diff --git a/tools/env/fw_env.config b/tools/env/fw_env.config
index 988ef9f..10ad3dc 100644
--- a/tools/env/fw_env.config
+++ b/tools/env/fw_env.config
@@ -5,7 +5,25 @@
    # Futhermore, if the Flash sector size is omitted, this value is assumed to
    # be the same as the Environment size, which is valid for NOR and SPI-dataflash
    # Device offset must be prefixed with 0x to be parsed as a hexadecimal value.
-
-# Block devices for CompuLab imx8m-mini
-/dev/mmcblk2boot0	0x4400	0x1000
-#/dev/mmcblk1		0x4400	0x1000
+#
+# == Format
+#
+# ----
+# (Block Device) (Offset in Bytes) (Size in Bytes) [Sector Size] [Sector Count]
+# ----
+#
+# Numbers can be specified in hex with a `0x` prefix.
+#
+# The fields `Sector Size` and `Sector Count` are optional for MMC devices.
+#
+# == BlueRange Gateway V4 - CompuLab IOT-GATE-iMX8
+#
+# Mender on U-Boot, without using GRUB as an intermediate bootloader.
+#
+# The U-Boot image compiled into the .sdimg is setup such that the environment
+# is loaded from the MMC user-partition (i.e. where the boot, root-a, root-b
+# and data partitions of the OS are stored). It lives between the start of the
+# block device and the first partition at the offsets specified below.
+#
+/dev/mmcblk2 0x800000  0x20000
+/dev/mmcblk2 0x1000000 0x20000

We have modified u-boot-compulab_%.bbappend to look more like the u-boot append from toradex nxp:

FILESEXTRAPATHS:prepend:mender-uboot := "${THISDIR}/compulab/imx8mm:"

include ${@mender_feature_is_enabled("mender-uboot","recipes-bsp/u-boot/u-boot-mender.inc","",d)}

MENDER_UBOOT_AUTO_CONFIGURE:mender-uboot = "1"
# same results without the following 3 lines
MENDER_UBOOT_ENV_STORAGE_DEVICE_OFFSET_1 = "0x800000"
MENDER_UBOOT_ENV_STORAGE_DEVICE_OFFSET_2 = "0x1000000"
BOOTENV_SIZE = "0x20000"

PROVIDES += "${@mender_feature_is_enabled("mender-uboot","u-boot-default-env","",d)}"
PROVIDES += "${@mender_feature_is_enabled("mender-uboot","u-boot","",d)}"
RPROVIDES:${PN} += "${@mender_feature_is_enabled("mender-uboot","u-boot","",d)}"
PROVIDES += "${@mender_feature_is_enabled("mender-uboot","u-boot-default-env","",d)}"

SRC_URI:append:mender-uboot = " \
    file://0200-iot-gate-imx8-config-Add-the-SD-as-a-boot-candidate.patch \
"

H: differences between zeus and kirkstone iot-gate-imx8_defconfig

I have tried the old defconfig, the new and basically everything in between.

--- a/configs/iot-gate-imx8_defconfig
+++ b/configs/iot-gate-imx8_defconfig
@@ -5,27 +5,29 @@
 CONFIG_SYS_TEXT_BASE=0x40200000
 CONFIG_SPL_GPIO_SUPPORT=y
 CONFIG_DM_GPIO=y
+CONFIG_SPL_TEXT_BASE=0x7E1000
 CONFIG_TARGET_IOT_GATE_IMX8=y
 CONFIG_SPL_MMC_SUPPORT=y
 CONFIG_SPL_SERIAL_SUPPORT=y
 CONFIG_SPL=y
-CONFIG_CSF_SIZE=0x2000
-CONFIG_SPL_TEXT_BASE=0x7E1000
-CONFIG_LOCALVERSION="-iot-gate-imx8-2.5"
+CONFIG_DEFAULT_DEVICE_TREE="iot-gate-imx8"
+CONFIG_LOCALVERSION="-iot-gate-imx8-3.2"
 CONFIG_FIT=y
 CONFIG_FIT_EXTERNAL_OFFSET=0x3000
 CONFIG_SPL_LOAD_FIT=y
 CONFIG_SPL_FIT_GENERATOR="arch/arm/mach-imx/mkimage_fit_atf.sh"
 CONFIG_OF_SYSTEM_SETUP=y
 CONFIG_SYS_EXTRA_OPTIONS="IMX_CONFIG=arch/arm/mach-imx/imx8m/imximage-8mm-lpddr4.cfg"
-CONFIG_CONSOLE_MUX=y
 CONFIG_DEFAULT_FDT_FILE="sb-iotgimx8-can.dtb"
-CONFIG_BOARD_LATE_INIT=y
 CONFIG_ARCH_MISC_INIT=y
 CONFIG_BOARD_EARLY_INIT_F=y
+CONFIG_BOARD_LATE_INIT=y
 CONFIG_SPL_BOARD_INIT=y
 CONFIG_SPL_SEPARATE_BSS=y
 CONFIG_SPL_POWER_SUPPORT=y
+CONFIG_SPL_USB_HOST_SUPPORT=y
+CONFIG_SPL_USB_GADGET=y
+CONFIG_SPL_USB_SDP_SUPPORT=y
 CONFIG_HUSH_PARSER=y
 CONFIG_SYS_PROMPT="IOT-GATE-iMX8 => "
 # CONFIG_BOOTM_NETBSD is not set
@@ -47,15 +49,17 @@
 CONFIG_CMD_EXT4=y
 CONFIG_CMD_FAT=y
 CONFIG_CMD_FS_GENERIC=y
-CONFIG_EFI_PARTITION=y
 CONFIG_OF_CONTROL=y
-CONFIG_DEFAULT_DEVICE_TREE="iot-gate-imx8"
 CONFIG_SYS_RELOC_GD_ENV_ADDR=y
 CONFIG_ENV_VARS_UBOOT_RUNTIME_CONFIG=y
 CONFIG_REGMAP=y
 CONFIG_SYSCON=y
 CONFIG_CLK_COMPOSITE_CCF=y
 CONFIG_CLK_IMX8MM=y
+CONFIG_USB_FUNCTION_FASTBOOT=y
+CONFIG_FASTBOOT_BUF_ADDR=0x42800000
+CONFIG_FASTBOOT_BUF_SIZE=0x40000000
+CONFIG_FASTBOOT_FLASH=y
 CONFIG_MXC_GPIO=y
 CONFIG_CMD_PCA953X=y
 CONFIG_DM_PCA953X=y
@@ -78,9 +82,9 @@
 CONFIG_DM_REGULATOR_GPIO=y
 CONFIG_MXC_UART=y
 CONFIG_DM_THERMAL=y
-CONFIG_NXP_TMU=y
 CONFIG_USB=y
 CONFIG_DM_USB=y
+# CONFIG_DM_USB_GADGET is not set
 CONFIG_USB_EHCI_HCD=y
 CONFIG_USB_GADGET=y
 CONFIG_USB_GADGET_MANUFACTURER="FSL"
@@ -88,12 +92,11 @@
 CONFIG_USB_GADGET_PRODUCT_NUM=0xa4a5
 CONFIG_CI_UDC=y
 CONFIG_SDP_LOADADDR=0x40400000
-CONFIG_USB_GADGET_DOWNLOAD=y
+CONFIG_USB_FUNCTION_SDP=y
 CONFIG_USB_HOST_ETHER=y
 CONFIG_USB_ETHER_ASIX88179=y
 CONFIG_USB_ETHER_SMSC95XX=y
 CONFIG_EXT4_WRITE=y
-CONFIG_FAT_WRITE=y
 CONFIG_OF_LIBFDT_OVERLAY=y
 CONFIG_AUTOBOOT_KEYED=y
 CONFIG_AUTOBOOT_ENCRYPTION=y
@@ -101,6 +104,8 @@
 CONFIG_ENV_OFFSET=0x800000
 CONFIG_ENV_OFFSET_REDUND=0x1000000
 CONFIG_SYS_REDUNDAND_ENVIRONMENT=y
+CONFIG_SYS_MMC_ENV_DEV=2
+CONFIG_SYS_MMC_ENV_PART=0
 # CONFIG_ENV_IS_NOWHERE is not set
 # CONFIG_ENV_IS_IN_EEPROM is not set
 # CONFIG_ENV_IS_IN_FAT is not set
@@ -122,7 +127,7 @@
 # CONFIG_BOOTCOUNT_RAM is not set
 # CONFIG_BOOTCOUNT_I2C is not set
 # CONFIG_BOOTCOUNT_AT91 is not set
+# CONFIG_BOOTCOUNT_MEM is not set
 # CONFIG_BOOTCOUNT_ALEN is not set
 CONFIG_BOOTCOUNT_LIMIT=y
 CONFIG_BOOTCOUNT_ENV=y
-# CONFIG_BOOTCOMMAND is not set

I know this is a lot. Would appreciate any hint so we can dig deeper.

Best regards,
Dominik

1 Like

After many more trial and error we could boil the problem down to the following:

The only error is

Autoboot in 2 seconds
Saving Environment to MMC... MMC partition switch failed
MMC partition switch failed
Failed (1)
  • U-Boot does not need anything useful in uboot.env, it just needs to be present
  • We only need the default, read-only environment in the sdimg. The user environments at 0x800000 and 0x1000000 are - under normal conditions - generated with the saveenv command. Both are present after saving the env two times. However, this fails.

What could possible problems be?

  • The user environment is read only for some reason
  • The env offset is wrong, even though the mender Kconfig fragment and the iot-gate-imx8_defconfig show them correctly, including the redundant environment
  • Something different with ‘switching’ the partition

The offsets could be checked by compiling a few printf statements into u-boot.

@Dominik-Hstein I’m also working on solution without grub. I’ll let you know when have something new in this regard. Thanks!

Great to hear that we’re not alone.

Do you use Compulab as well and have the same issues?

Yes I’m using compulab iot-gate-imx8plu machine. I’ve added kas support for building instead of repo and now adding custom mender support as compulab mender layer seems to be not right :wink:

@MarekBelisko we have just lately added a big bunch of kas configuration files to meta-mender-community, so you can easily have it added there without needing the layer+repo chores.

Greetz,
Josef

Very happy to hear that, as I have wasted many days if not weeks on this so far.
I am using the standard iot-gate-imx8 but there is hopefully just a difference in the defconfig.

Will this be published to meta-mender-community for the public?

@Dominik-Hstein I’m facing strange issue also with env:

MMC:   FSL_SDHC: 2
Loading Environment from MMC... MMC: block number 0x4100 exceeds max(0x2000)
MMC: block number 0x8100 exceeds max(0x2000)
*** Error - No Valid Environment Area found
*** Warning - bad env area, using default environment

it looks like env is stored in emmc boot partition but I cannot disable it. Weird…

Have you added the following to the .conf? It’s from here: https://github.com/compulab-yokneam/meta-mender-compulab/blob/kirkstone-nxp/templates/local-emmc.conf.append

MENDER_STORAGE_DEVICE = "/dev/mmcblk2"
MENDER_UBOOT_STORAGE_DEVICE = "2"
UBOOT_CONFIG = "sd"

Compulab’s default is to use mmcblk2boot0