Variscite VAR-SOM-MX8M-MINI : NXP i.MX 8M Mini

Board description

The VAR-SOM-MX8M-MINI is a highly scalable, low power System on Module (SoM), offering a mainstream solution to fit a wide range of applications and cost requirements.

Based on NXP’s i.MX 8M Mini with up to 1.8GHz Quad-core ARM Cortex-A53™ plus 400MHz Cortex-M4™ real-time processor and up to 4 GB DDR4, the VAR-SOM-MX8M-MINI supports advanced features and a variety of connectivity options, including integrated HW engines supporting 1080p video encoding and decoding, 2D and 3D graphics, HQ audio, integrated certified single band 802.11 b/g/n or dual-band 802.11 ac/a/b/g/n, integrated CAN bus, LVDS, and a variety of additional interfaces.

The VAR-SOM-MX8M-MINI is a pin2pin platform compatible with the ‘VAR-SOM Pin2Pin’ products family, providing a maximum scalability range; from the entry-level i.MX6UL/6ULL platform, through the i.MX 6 platforms, i.MX 8X, and up to the i.MX 8QuadMax.

The VAR-SOM-MX8M-MINI Development Kit and Starter Kit can serve as a complete development platform for both evaluation and application development purposes. The kits provide a great showcase of the VAR-SOM-MX8M-MINI connectivity features and performance.


Test results

The Yocto Project releases in the table below have been tested by the Mender community. Please update it if you have tested this integration on other Yocto Project releases:

SD Card Root Filesystem

Yocto Project Build Runtime
warrior (2.7) :test_works: :test_works:

eMMC Root Filesystem

Yocto Project Build Runtime
warrior (2.7) :test_works: :test_works:

Build Means that the Yocto Project build using this Mender integration completes without errors and outputs images.
Runtime Means that Mender has been verified to work on the board. For U-Boot-based boards, the integration checklist has been verified.

Getting started


  • A supported Linux distribution and dependencies installed on your workstation/laptop as described in the Yocto Mega Manual
    • NOTE. Instructions depend on which Yocto version you intend to use.
  • Google repo tool installed and in your PATH.

Configuring the build

Setup Yocto environment

Set the Yocto Project branch you are building for:

# set to your branch, make sure it is supported (see table above)
export BRANCH="warrior"

Create a directory for your mender-variscite setup to live in and clone the
meta information.

mkdir mender-variscite && cd mender-variscite

Initialize repo manifest:

repo init -u -b fsl-warrior -m imx-4.19.35-1.1.0-var01.xml                                                                                       
mkdir .repo/local_manifests
cd .repo/local_manifests/
cd -

Fetch layers in manifest:

repo sync
cd .repo/local_manifests/
ln -sf ../../sources/meta-mender-community/scripts/mender-no-setup.xml .
cd -

Determine root filesystem media

The Variscite VAR-SOM-MX8M-MINI platform supports running U-Boot directly from the following media:

  • SD-Card
  • eMMC

The root filesystem can be stored on any of the following media:

  • SD-Card
  • eMMC

Set the shell variable for your desired root filesystem media:

export MEDIA="sdcard"
export MEDIA="emmc"

Setup build environment

Initialize the build environment:

MACHINE=imx8mm-var-dart DISTRO=fsl-imx-xwayland . -b build
cat ../sources/meta-mender-community/meta-mender-variscite/templates/bblayers.conf.append >> conf/bblayers.conf
cat ../sources/meta-mender-community/templates/local.conf.append >> conf/local.conf
cat ../sources/meta-mender-community/meta-mender-variscite/templates/local.conf.append >> conf/local.conf
cat ../sources/meta-mender-community/meta-mender-variscite/templates/local-${MEDIA}.conf.append >> conf/local.conf

Building the image

You can now proceed with building an image:

bitbake core-image-base

Replace core-image-base with your desired image target.

Using the build output

SD Card

Provision an SD Card with the built above. WARNING, make sure you use the correct device node as the of= parameter to avoid overwriting the wrong device:

sudo dd if=tmp/deploy/images/imx8mm-var-dart/core-image-base-imx8mm-var-dart.sdimg of=<SDCARD-DEVICE-NODE> conv=fdatasync bs=8M

Remove the SD Card from your build host and insert it into the target. Configure your board to boot from SD Card by moving the Boot Select switch (also labeled as SW3 ) to the SD position. Now turn on power to the board and it will boot from the SDCard and Mender will connect to the server configured in your local.conf file.


Using either the above built SDCard Yocto image or the Variscite Yocto Recovery SD card, boot your system off of SD. Transfer the following file from your build PC to the target board with a USB drive:

  • tmp/deploy/images/imx8mm-var-dart/core-image-base-imx8mm-var-dart.sdimg

Assuming the USB drive is mounted on the target at /mnt, run the following commands:

sudo dd if=/mnt/core-image-base-imx8mm-var-dart.sdimg of=/dev/mmcblk0 conv=fdatasync bs=8M

Then change the Boot Select switch (also labeled as SW3 ) to the Internal position and power cycle your board.

eMMC - USB Mass Storage Installation

An alternative mechanism exists if you already have a working UBoot running from either SD-Card or eMMC running on the target board. This mechanism will present the eMMC device to your development PC as a mass storage device and you can flash the image directly from there.

  1. Boot the system and press any key to interrupt the boot process, leaving you at the U-Boot> prompt.
  2. Connect a USB cable from USB3/J26 port on the target board to your PC.
  3. Enable USB mass storage mode from the U-Boot> prompt:
U-Boot> ums 0 mmc 1
  1. Determine what device node was added on your PC. This can be done using the Disk Utility or viewing system logs. Consult your PC OS documentation for more details
  2. Write the flash directly to the eMMC. This assumes the new device was enumerated as /dev/sdd. WARNING: this will destroy any contents on the device listed under the of= parameter below.
sudo dd if=tmp/deploy/images/imx8mm-var-dart/core-image-base-imx8mm-var-dart.sdimg of=<EMMC-DEVICE-NODE> conv=fdatasync bs=8M

On the other hand, if you already have Mender running on your device and want to deploy a rootfs update using this build, you should use the Mender Artifact files, which have .mender suffix. You can either deploy this Artifact in managed mode with the Mender server (upload it under Releases in the server UI) or by using the Mender client only in Standalone deployments.


  • The Variscite imx8m-var-dart template files can be found in meta-mender-community.
  • The official Mender documentation explains how Mender works. This is simply a board-specific complement to the official documentation.

If this post was useful to you, please press like, or leave a thank you note to the contributor who put valuable time into this and made it available to you. It will be much appreciated!


Dear drewmoseley,
thank you very much for this guide. I’m using this module in a project and the mender integration went very well so far, thanks to your effort.
(Just on thing to add maybe: I needed to ‘bitbake -c populate_sdk …’ before building the image itself. Without this step there was some mender compilation error regarding ‘pseudo-native’, which could not be found.)

Now I would like to use OP-TEE for some security features. There are examples by NXP for their EVKs, but none really for the Variscite modules (see the NXP community board). I tried a few approaches and the best one resulted in appending ‘optee’ to the MACHINE_FEATURES and inserting a node into the devicetree - so far, so good.

Then there’s the problem: OP-TEE needs to add a file called ‘tee.bin’ to u-boot, i. e. to the boot partition via IMAGE_BOOT_FILES variable, but following your guide it is manually set to empty by the ‘meta-mender-variscite/templates/local.conf.append’ and the boot partition size is set to ‘0’.

Do you have an idea how to solve this? I tried commenting the overrides in ‘local.conf’, but the board won’t boot then, since it seems to be unable to find the bootloader.
Would it be possible to add the file to ‘/boot’, where kernel and devicetrees are located?

I just looked at the u-boot env and there seems to be a new bootcmd with optee content:
bootcmd_mfg=run mfgtool_args;if iminfo ${initrd_addr}; then if test ${tee} = yes; then bootm ${tee_addr} ${initrd_addr} ${fdt_addr}; else booti ${loadaddr} ${initrd_addr} ${fdt_addr}; fi; else echo "Run fastboot ..."; fastboot 0; fi;

u-boot=> printenv

altbootcmd=run mender_altbootcmd; run bootcmd
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} {img_addr} /boot/{mender_kernel_name};unzip {img_addr} {loadaddr}; {mender_boot_kernel_type} {kernel_addr_r} - {fdt_addr_r}; run mender_try_to_recover
bootcmd_mfg=run mfgtool_args;if iminfo {initrd_addr}; then if test {tee} = yes; then bootm {tee_addr} {initrd_addr} {fdt_addr}; else booti {loadaddr} {initrd_addr} {fdt_addr}; fi; else echo “Run fastboot …”; fastboot 0; fi;
bootscript=echo Running bootscript from mmc …; source
console=ttymxc3,115200 earlycon=ec_imx6q,0x30a60000,115200
findfdt=if test $fdt_file = undefined; then if test $board_name = VAR-SOM-MX8M-MINI; then if test som_rev = som_rev10; then setenv fdt_file fsl-imx8mm-var-som-rev10.dtb; else setenv fdt_file fsl-imx8mm-var-som.dtb; fi;else setenv fdt_file fsl-imx8mm-var-dart.dtb;fi; fi; image=Image.gz img_addr=0x42000000 initrd_addr=0x43800000 initrd_high=0xffffffffffffffff ip_dyn=yes kboot=booti loadaddr=0x40480000 loadbootscript=load mmc {mmcdev}:{mmcpart} {loadaddr} {bootdir}/{script};
loadfdt=run findfdt; echo fdt_file={fdt_file}; load mmc {mmcdev}:{mmcpart} {fdt_addr} {bootdir}/{fdt_file}
loadimage=load mmc {mmcdev}:{mmcpart} {img_addr} {bootdir}/{image};unzip {img_addr} {loadaddr} loadm4bin=load mmc {mmcdev}:{mmcpart} {m4_addr} {bootdir}/{m4_bin}
mender_altbootcmd=if test {mender_boot_part} = 1; then setenv mender_boot_part 2; setenv mender_boot_part_hex 2; else setenv mender_boot_part 1; setenv mender_boot_part_hex 1; fi; setenv upgrade_available 0; saveenv; run mender_setup mender_boot_kernel_type=booti mender_boot_part=1 mender_boot_part_hex=1 mender_check_saveenv_canary=1 mender_dtb_name=fsl-imx8mm-var-som-rev10-m4.dtb mender_kernel_name=Image.gz mender_pre_setup_commands= setenv bootargs console={console},{baudrate}; if test "{mmcargs}” != “”; then run mmcargs; fi; if test “{videoargs}" != ""; then run videoargs; fi; if test "{optargs}” != “”; then run optargs; fi; if test “{ramsize_check}" != ""; then run ramsize_check; fi; run findfdt; setenv mender_dtb_name {fdt_file}; setenv kernel_addr_r {loadaddr}; 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/mmcblk1p${mender_boot_part}; if test {mender_boot_part} = 1; then setenv mender_boot_part_name /dev/mmcblk1p1; else setenv mender_boot_part_name /dev/mmcblk1p2; fi; setenv mender_kernel_root_name {mender_boot_part_name}; setenv mender_uboot_root mmc 0:{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 0:1 mender_uboot_dev=0 mender_uboot_if=mmc mfgtool_args=setenv bootargs console={console},{baudrate} rdinit=/linuxrc clk_ignore_unused mmcargs=setenv bootargs console={console} rootwait rw {cma_size} mmcautodetect=yes mmcblk=1 mmcboot=echo Booting from mmc ...; run mmcargs; run optargs; if test {boot_fdt} = yes || test {boot_fdt} = try; then if run loadfdt; then booti {loadaddr} - {fdt_addr}; else echo WARN: Cannot load the DT; fi; else echo wait for boot; fi; mmcdev=0 mmcpart=1 netargs=setenv bootargs console={console} {cma_size} ip=dhcp nfsroot={serverip}:{nfsroot},v3,tcp netboot=echo Booting from net ...; if test {ip_dyn} = yes; then setenv get_cmd dhcp; else setenv get_cmd tftp; fi; {get_cmd} {img_addr} {image}; unzip {img_addr} {loadaddr};run ramsize_check; run netargs; run optargs; if test {boot_fdt} = yes || test {boot_fdt} = try; then run findfdt; echo fdt_file={fdt_file}; if {get_cmd} {fdt_addr} {fdt_file}; then booti {loadaddr} - {fdt_addr}; else echo WARN: Cannot load the DT; fi; else booti; fi; optargs=setenv bootargs {bootargs} ${kernelargs};
ramsize_check=if test sdram_size -le 512; then setenv cma_size cma=320M; else setenv cma_size cma=640M@1376M; fi; runm4bin=if test {m4_addr} = 0x7e0000; then echo Booting M4 from TCM; else echo Booting M4 from DRAM; dcache flush; fi; bootaux ${m4_addr};
splashdisable=setenv splashfile; setenv splashimage
splashenable=setenv splashfile /boot/splash.bmp; setenv splashimage 0x43100000

However, it is not called by the default bootcmd and if I try ‘run bootcmd_mfg’ it says ## Checking Image at 43800000 ... Unknown image format! because the ‘iminfo’ command cannot find a valid image at ‘initrd_addr’.

I would appreciate your help very much.

Hello @KTCdjoh welcome to Mender Hub. I’m glad that you are finding it useful.

As for the OP-TEE integration we have not investigated that. As you noticed with Mender, there is no need for a separate boot partition. U-Boot and it’s environment are stored in inter-partition space and no other files are needed. The kernel and DTB are instead loaded from the root filesystem partition making it easy to upgrade them with an OTA deployment.

My guess is the simplest solution would be to simply set MENDER_BOOT_PARTITION_SIZE_MB to something non-zero and then ensure tee.bin is in IMAGE_BOOT_FILES. I don’t know exactly how that file is loaded and processed so you may need to modify the bootcmd some as well.

The downside of that approach is that there is no way to upgrade tee.bin should it be needed.

The proper approach would be to ensure that tee.bin is in the root filesystem somewhere and that the logic in the U-Boot environment that processes it is updated to find the file there.


1 Like

Hello @drewmoseley, thanks for your reply.

Just in case you’re interested, here’s the guide by NXP I followed: (chapter ‘4.6 Freescale MX6UL EVK’, especially the part ‘Run using U-Boot’ - imx6, I know, just for guidance) and also the link specified therein

In my understanding, tee.bin is simply loaded and executed before the kernel. It initializes its separate secure environment and then continues to start the kernel in the non-secure world.

I guess I’ll try both approaches and report status, when I’m back from holiday :wink:
But you’re right, the rootfs approach would be better for maintainability.
So far, I completely switched to the boot partition layout without u-boot in the bootsector, which logically didn’t work.

Best regards