I have started to work on some software for a Boundary Devices Nitrogen8M Mini SBC (i.MX8M Mini Soc). The early stage project is posted at GitHub - tbensonatl/oolong. I am using buildroot as the build system, but used the patches and scripts from the Yocto layer as a starting point. With that, I have successfully integrated Mender into the bootloader and confirmed that I can update via mender artifacts.
One complication is that the bootloader is stored to the eMMC hardware boot partition (/dev/mmcblk0boot0 in Linux) and the environment is stored in this same partition (and then redundantly in /dev/mmcblk0boot1). This partition is not writable by default, so the client is unable to update the U-Boot environment. I worked around that with the following patch: oolong/0010-make-boot-partition-writable.patch at main · tbensonatl/oolong · GitHub. The patch makes the partition writable when an update is needed and reverts back to read-only after completion.
That works, but I would prefer to not need to update the U-Boot environment at all so that I can embed the environment to be read-only in the bootloader image (i.e. set CONFIG_ENV_IS_NOWHERE=y). I realize that we minimally need to be able to store the active partition, bootcount, and upgrade_available variables, but has there been any work to store these elsewhere? I currently create 4 partitions and use p2 and p3 as the mender active/inactive partitions. p1 is currently unused, but e.g. I could create a
mender/env directory in that partition and read the relevant data from files in U-Boot as an alternative to the U-Boot environment. Are there any major downsides to using files in a user partition to maintain state rather than the U-Boot environment? File corruption is one obvious concern, although including a checksum (like the U-Boot environment) would help with integrity.
thanks for showing your project! That is really a cool thing, let me know if I can help you from the Mender side
For your question, the first thing that comes to my mind is using some form of non-volatile memory that the board provides. Is there maybe some EEPROM, battery-backed storage, or similar? It certainly needs a little more tuning than “just” using the U-Boot environment, but it should definitively be possible.
I have made some progress on storing the mender-relevant portions of the U-Boot environment externally on an ext4 filesystem. I made changes to both U-Boot and fw_printenv/fw_setenv to accommodate this approach. The change to uboot-tools (fw_printenv/fw_setenv) is to support using files and not just block devices.
The bigger change is to U-Boot. There, I added a function to import the external mender environment from an ext4 filesystem (the device and filename are specified in the Kconfig). I also implemented the bootcount interface so that the
bootcount_store command writes to the external mender environment. The U-Boot load/store functions also support a redundant external environment if it is selected via the Kconfig. The variables in the external mender environment and the environment files are as follows:
$ ls -l /recovery/mender/
-rwxr-xr-x 1 root root 8192 Jan 1 00:00 uboot-env-redundant.bin
-rwxr-xr-x 1 root root 8192 Jan 1 00:00 uboot-env.bin
These are normal U-Boot environments that include the typical CRC and flags fields, but they are treated as overlays of the built-in U-Boot environment rather than the full environment. Similarly, the writes only write out the variables included above.
Thus far I have only tested the normal upgrade path using mender artifacts, so I still need to test the rollback logic. If anyone is interested in taking a look, it is currently under the add-mender-external-environment branch: GitHub - tbensonatl/oolong at add-mender-external-environment. The relevant patches are oolong/0020-add-mender-external-env.patch at add-mender-external-environment · tbensonatl/oolong · GitHub and oolong/0010-add-file-env-support.patch at add-mender-external-environment · tbensonatl/oolong · GitHub.