Note: What's described on this page is automated as part of Build Apalis iMX8/Colibri iMX8X OpenEmbedded/Yocto Project Bring-up Image. This page is useful for U-Boot or Linux kernel development where one wants to avoid the much longer development cycle times if one uses an OpenEmbedded setup for this.
The NXP i.MX 8QuadMax / i.MX 8QuadXPlus SoC boot process is a bit more involved than the typical SoC used by Toradex. This article describes how to build the boot container (including required integration of firmware and boot loader) and Linux manually.
The NXP i.MX 8QuadMax / i.MX 8QuadXPlus boots using a Cortex-M4 boot CPU called System Controller Unit (SCU). The SCU firmware is to a large part provided by NXP, but has been slightly altered by Toradex for the Apalis iMX8QM/Colibri iMX8QXP. The firmware also loads an intermediate firmware running on the Cortex-A class CPUs: The ARM trusted firmware (ATF). The ARM trusted firmware then hands over control to U-Boot which then is able to boot Linux.
The DDR memory timings, the SCU firmware, the ATF and U-Boot as well as any potential Cortex-M4 auxiliary firmware are all stored in a single boot container. This boot container is read by the boot ROM from the boot device starting at a specific offset (33kB for V1.0A modules booting from SD cards).
The Linaro cross-toolchain for AArch64 is required to build the Bootloaders/Linux from scratch. The toolchain can be found at linaro.org/downloads/. The latest aarch64-linux-gnu toolchain should work fine. At Toradex we tested the 2017.11 release which comes with GCC 7.2.1.
Make sure you extract the toolchain and setup the environment accordingly:
cd ~/
tar xJf gcc-linaro-7.2.1-2017.11-x86_64_aarch64-linux-gnu.tar.xz
export ARCH=arm64
export PATH=~/gcc-linaro-7.2.1-2017.11-x86_64_aarch64-linux-gnu/bin/:$PATH
export CROSS_COMPILE=aarch64-linux-gnu-
Note that if you already built an image with OpenEmbedded you already have the needed artefacts to assemble the final bootcontainer. They can be found in deploy/images/.
This is only needed for Apalis iMX8QM V1.0B and Colibri iMX8QXP V1.0B.
The SECO Firmware is provided by NXP in binary form. You will need to accept the NXP License Agreement as part of the unpacking process.
The files are called mx8qm-ahab-container.img and mx8qx-ahab-container.img respectively.
E.g. use wget for download, and extract the firmware:
wget https://www.nxp.com/lgfiles/NMG/MAD/YOCTO/firmware-imx-8.0.bin
chmod u+x firmware-imx-8.0.bin
./firmware-imx-8.0.bin
ls firmware-imx-8.0/firmware/seco/
Currently, the SCU Firmware for Apalis iMX8QM and Colibri iMX8QXP is stored in the Bring-up BSP layer.
E.g. use wget for download:
wget https://github.com/toradex/meta-fsl-bsp-release/raw/toradex-sumo-4.14.78-1.0.0_ga-bringup/imx/meta-bsp/recipes-bsp/imx-sc-firmware/files/mx8qm-apalis-scfw-tcm.bin
wget https://github.com/toradex/meta-fsl-bsp-release/raw/toradex-sumo-4.14.78-1.0.0_ga-bringup/imx/meta-bsp/recipes-bsp/imx-sc-firmware/files/mx8qx-colibri-scfw-tcm.bin
The relevant file renamed to scfw_tcm.bin will be used in the final container.
Currently, there are no changes necessary for ARM Trusted Firmware. Hence ATF can be built directly from sources provided by NXP:
Module |
ATF Branch |
Platform |
Binary File |
Apalis iMX8QM V1.0A |
imx_4.9.51_imx8_beta2 |
imx8qm |
build/imx8qm/release/bl31.bin |
Apalis iMX8QM V1.0B |
imx_4.14.78_1.0.0_ga |
imx8qm |
build/imx8qm/release/bl31.bin |
Colibri iMX8QXP V1.0A |
imx_4.9.123_imx8mm_ga |
imx8qxp |
build/imx8qxp/release/bl31.bin |
Colibri iMX8QXP V1.0B |
imx_4.14.78_1.0.0_ga |
imx8qxp |
build/imx8qxp/release/bl31.bin |
git clone https://source.codeaurora.org/external/imx/imx-atf
cd imx-atf
git checkout <ATF Branch>
Build the firmware:
make PLAT=<Platform> bl31
The resulting binary file bl31.bin created in build/<Platform>/release/
will be used in the final container.
Module |
U-Boot Git Branch |
U-Boot Configuration |
Apalis iMX8QM V1.0A |
toradex_imx_v2017.03_4.9.51_imx8_beta2-bring_up |
apalis-imx8_defconfig |
Apalis iMX8QM V1.0B |
toradex_imx_v2018.03_4.14.78_1.0.0_ga-bringup |
apalis-imx8_defconfig |
Colibri iMX8QXP V1.0A |
toradex_imx_v2017.03_4.9.123_imx8mm_ga-bring_up |
colibri-imx8qxp_defconfig |
Colibri iMX8QXP V1.0B |
toradex_imx_v2018.03_4.14.78_1.0.0_ga-bringup |
colibri-imx8qxp_defconfig |
Toradex uses a customized version of the U-Boot boot loader provided by the NXP BSP. It can be found on our git server in the u-boot-toradex repository.
git clone https://git.toradex.com/u-boot-toradex.git
cd u-boot-toradex
git checkout <U-Boot Git Branch>
make <U-Boot Configuration>
make -j 4
The binary u-boot.bin
will be used in the final container.
The utility imx-mkimage allows building the boot container.
For the V1.0A modules it needs small modifications which are available as patches from the Bring-up BSP layer. The patches do not hurt when building for V1.0B modules so we apply them here unconditionally.
Module |
imx-mkimage Git Branch |
Apalis iMX8QM V1.0A |
imx_4.9.123_imx8mm_ga |
Apalis iMX8QM V1.0B |
imx_4.14.78_1.0.0_ga |
Colibri iMX8QXP V1.0A |
imx_4.9.123_imx8mm_ga |
Colibri iMX8QXP V1.0B |
imx_4.14.78_1.0.0_ga |
git clone https://source.codeaurora.org/external/imx/imx-mkimage/
cd imx-mkimage
git checkout <imx-mkimage Git Branch>
curl https://raw.githubusercontent.com/toradex/meta-fsl-bsp-release/toradex_rocko-4.9.123-2.3.0_8mm_ga_bringup/imx/meta-bsp/recipes-bsp/imx-mkimage/files/0001-add-board-support-for-DCD-memory-timings.patch | patch -p 1
curl https://raw.githubusercontent.com/toradex/meta-fsl-bsp-release/toradex_rocko-4.9.123-2.3.0_8mm_ga_bringup/imx/meta-bsp/recipes-bsp/imx-mkimage/files/0002-add-memory-timings-for-Apalis-iMX8.patch | patch -p 1
curl https://raw.githubusercontent.com/toradex/meta-fsl-bsp-release/toradex_rocko-4.9.123-2.3.0_8mm_ga_bringup/imx/meta-bsp/recipes-bsp/imx-mkimage/files/0001-mx8x-add-board-support-for-DCD-memory-timings.patch | patch -p 1
curl https://raw.githubusercontent.com/toradex/meta-fsl-bsp-release/toradex_rocko-4.9.123-2.3.0_8mm_ga_bringup/imx/meta-bsp/recipes-bsp/imx-mkimage/files/0002-imx8x-add-memory-timings-for-Colibri-iMX8X.patch | patch -p 1
Copy all binaries SCU Firmware, ARM Trusted Firmware, U-Boot and for V1.0B modules the SECO Firmware into a SoC specific directory, iMX8QM for Apalis iMX8QM, iMX8QX for Colibri iMX8QXP. Rename the SCU Firmware to scfw_tcm.bin while copying.
Then use make to build the boot container and deploy flash.bin to the module's boot device.
You either need to install your distributions devel package for linking against a static libc or remove '-static' from the CFLAGS in the Makefile.
Assemble Apalis iMX8QM V1.0A
cp ../apalis-imx8-scfw-tcm.bin iMX8QM/scfw_tcm.bin
cp ../imx-atf/build/imx8qm/release/bl31.bin iMX8QM/
cp ../u-boot-toradex/u-boot.bin iMX8QM/
make SOC=iMX8QM DCD_BOARD=apalis-imx8 flash_dcd
dd if=iMX8QM/flash.bin of=/dev/<sdcard> bs=1k seek=33
Assemble Apalis iMX8QM V1.0B
cp ../apalis-imx8-scfw-tcm.bin iMX8QM/scfw_tcm.bin
cp ../imx-atf/build/imx8qm/release/bl31.bin iMX8QM/
cp ../u-boot-toradex/u-boot.bin iMX8QM/
cp ../firmware-imx-8.0/firmware/seco/mx8qm-ahab-container.img iMX8QM/
make SOC=iMX8QM flash_b0
The Boot Container is stored on the first boot area of the module's eMMC.
Copy iMX8QM/flash.bin to an SD-Card and use U-Boot to copy it to the eMMC as follows:
mmc dev 1
load mmc 1:1 $loadaddr flash.bin
setexpr blkcnt ${filesize} + 0x1ff && setexpr blkcnt ${blkcnt} / 0x200
mmc dev 0 1
mmc write ${loadaddr} 0x0 ${blkcnt}
Should you not have a working boot container anymore you can load and execute flash.bin using the recovery mode with the uuu tool.
Check here on how to get the tool and how to use it.
Once you have a running U-Boot use the above procedure to flash the working copy onto the eMMC.
Assemble Colibri iMX8QXP V1.0A
cp ../colibri-imx8qxp-scfw-tcm.bin iMX8QX/scfw_tcm.bin
cp ../imx-atf/build/imx8qxp/release/bl31.bin iMX8QX/
cp ../u-boot-toradex/u-boot.bin iMX8QX/
make SOC=iMX8QX DCD_BOARD=colibri-imx8qxp flash_dcd_a0
dd if=iMX8QX/flash.bin of=/dev/<sdcard> bs=1k seek=33
Assemble Colibri iMX8QXP V1.0B
cp ../colibri-imx8qxp-scfw-tcm.bin iMX8QX/scfw_tcm.bin
cp ../imx-atf/build/imx8qxp/release/bl31.bin iMX8QX/
cp ../u-boot-toradex/u-boot.bin iMX8QX/
cp ../firmware-imx-8.0/firmware/seco/mx8qx-ahab-container.img iMX8QX/
make SOC=iMX8QX flash
The Boot Container is stored on the first boot area of the module's eMMC.
Copy iMX8QX/flash.bin to an SD-Card and use U-Boot to copy it to the eMMC as follows:
mmc dev 1
load mmc 1:1 $loadaddr flash.bin
setexpr blkcnt ${filesize} + 0x1ff && setexpr blkcnt ${blkcnt} / 0x200
mmc dev 0 1
mmc write ${loadaddr} 0x0 ${blkcnt}
Should you not have a working boot container anymore you can load and execute flash.bin using the recovery mode with the uuu tool.
Check here on how to get the tool and how to use it
Once you have a running U-Boot use the above procedure to flash the working copy onto the eMMC.
Module |
Kernel Git Branch |
Kernel Configuration |
Device Tree |
Kernel Binary |
Apalis iMX8QM V1.0A |
toradex_imx_4.9.51_imx8_beta2-bring_up |
defconfig |
arch/arm64/boot/dts/freescale/fsl-imx8qm-apalis.dtb |
arch/arm64/boot/Image |
Apalis iMX8QM V1.0B |
toradex_imx_4.14.78_1.0.0_ga-bring_up |
defconfig |
arch/arm64/boot/dts/freescale/fsl-imx8qm-apalis.dtb |
arch/arm64/boot/Image |
Colibri iMX8QXP V1.0A |
toradex_imx_4.9.123_imx8mm_ga-bring_up |
defconfig |
arch/arm64/boot/dts/freescale/fsl-imx8qxp-colibri-eval-v3.dtb |
arch/arm64/boot/Image |
Colibri iMX8QXP V1.0B |
toradex_imx_4.14.78_1.0.0_ga-bring_up |
defconfig |
arch/arm64/boot/dts/freescale/fsl-imx8qxp-colibri-eval-v3.dtb |
arch/arm64/boot/Image |
git clone https://git.toradex.com/linux-toradex.git
cd linux-toradex
git checkout <Kernel Git Branch>
make defconfig
make -j 4
By default, the U-Boot boot scripts try to load the Linux kernel and device tree from the first FAT partition of the eMMC (resp. SD card on V1.0A modules).
Check Build U-Boot and Linux Kernel from Source Code on how to deploy kernel modules.