This document intends to provide an overview of the i.MX8 Boot process and walk you through the process of creating a bootable image.
Coming out of a reset state the i.MX8 ROM (firmware that is stored in non-volatile memory of the i.MX8) reads the boot mode pins to determine the boot media/device that will be used.
The i.MX8 can boot out of the following boot devices:
The following table indicates the available options on a i.MX8QXP, the i.MX8 reads the boot mode pads and based in the configuration selects the desired boot device.
Once the boot device has been identified, ROM configures the boot media and attempts to read the image from a predefined address in the boot device, the following table shows the addresses where the image is expected to be on different boot devices.
ROM loads data from the predefined addresses above (depending on the selected boot device) to the System Controller Unit (SCU) internal memory (tightly coupled memory) and parses it to find the image container. It can also boot by downloading an image through USB.
The image container has all the information needed to load all the images to the system, the first images that get loaded are the System Controller Firmware (SCFW) and Security Controller Firmware (SECO).
The SECO FW needs to be loaded to refresh the watchdog timer (kick the dog) in the device, if the SECO FW is not loaded before the watchdog expires the device will reset, this usually happens when the device fails to fetch a valid image from the boot media.
Once the SCFW is loaded, ROM jumps to it and starts executing it.
The SCFW then initializes the DDR and starts loading the images for the Cortex-M4 (optional) and the Cortex-A cores (optional).
Once the images are loaded to their destination memory the SCFW boots the cores and sets them in their start address.
As a recap a bootable image is comprised of as minimum the System Controller Firmware and the Security Controller Firmware, optionally it can contain images for the Cortex M4 cores (if more than one available as in the case of QM devices) and Cortex A cores.
It is possible to boot an image that only contains the SCFW and SECO FW, this could be useful in the first stages of porting the SCFW to the target board. It is also possible to boot an image with only the Cortex-M4 image (baremetal, FreeRTOS, AutoSAR...), only the Cortex-A image (U-boot or any bootloader) or both Cortex-M4 and Cortex-A images.
The tool in charge of merging all these images and creating a bootable image for the i.MX8 is called mkimage, and can be obtained in source form in the following repository:
https://github.com/nxp-imx/imx-mkimage
mkimage is only supported in Linux
So the first step is to clone the mkimage repository into our machine and checkout the latest branch, at the time of writing this document the latest release is 4.14.98_02:
git clone https://source.codeaurora.org/external/imx/imx-mkimage
cd imx-mkimage
git checkout imx_4.14.98_2.0.0_ga
You should now be able to see the following folders:
Now that you have the mkimage tool you need some actual images to work with, if you are using a custom board you might need to port the SCFW and DDR configuration files for it (depending on how close it follows NXP's reference board).
The following is a compendium of documents on the basics of the SCFW and how to build it from scratch you can go there if you need help getting started with the porting process:
https://community.nxp.com/docs/DOC-342654
If you are trying this on one of NXP's reference board you can use a pre-built SCFW binary, this can be obtained through the building process of the Yocto project or by downloading the porting kit and following these steps:
Dowload SCFW binaries for release 4.14.98_02 here.
chmod a+x imx-sc-firmware-1.2.bin
./imx-sc-firmware-1.2.bin
You will prompted to accept a license agreement and after that the binaries will be extracted:
The Security Controller Firmware is only distributed in binary form and can be obtained from the NXP website.
Download SECO FW binaries for release 4.14.98_02 here.
chmod a+x firmware-imx-8.1.bin
./firmware-imx-8.1.bin
You will prompted to accept a license agreement and after that the binaries will be extracted:
The SECO FW is under firmware/seco
The image for the Cortex-M4 can be generated using the SDK:
https://mcuxpresso.nxp.com/en/select
Just select the device you are working with and click Build MCUXpresso SDK, then you will prompted to select your IDE and host.
Click on Download SDK and a compressed file containing the SDK will be dowloaded to your computer. Now you only need to uncompress the file and follow the steps in the getting started document to generate the image.
The getting started document includes steps to setup the toolchain and build an image for the M4.
An M4 binary for the QM and QXP MEKs is also attached in this document, the example outputs a hello world message on the M4 terminal.
The bootloader for the Cortex-A cores can be obtained through the Yocto BSP:
The steps on generating the image for the 4.14.98 release can be found here:
https://www.nxp.com/webapp/Download?colCode=imx-yocto-L4.14.98_2.0.0_ga
Some more details on the Yocto BSP can be found here:
https://community.nxp.com/docs/DOC-94849
All the required binaries to create a bootable image for the Cortex-A cores on the MEK platforms are attached here.
Once all the required pieces have been built/obtained, the bootable image can be created.
The SCFW, SECO FW and respective Cortex-M4/A images need to be copied to the folder for the target device, i.e. if you are building an image for an i.MX8QX variant copy the binaries for that variant to its folder:
Here is a list of the required files to build a bootable image:
Once the required binaries have been copied to the desired variant folder (QXP or QM in this example), you are ready to start building some images.
All the targets for building different images are defined on the soc.mak file contained in each folder, this file contains different examples for creating a lot of the supported bootable images.
The target used to create a SCFW only image is flash_b0_scfw and it is defined under the soc.mak file of each variant.
To invoke this target for QXP from the imx-mkimage directory:
make SOC=iMX8QX flash_b0_scfw
To invoke this target for QM from the imx-mkimage directory:
make SOC=iMX8QM flash_b0_scfw
The target definition for flash_b0_scfw can be seen below.
Definition for QXP:
flash_scfw flash_b0_scfw: $(MKIMG) mx8qx-ahab-container.img scfw_tcm.bin
./$(MKIMG) -soc QX -rev B0 -dcd skip -append mx8qx-ahab-container.img -c -scfw scfw_tcm.bin -out flash.bin
Definition for QM:
flash_b0_scfw: $(MKIMG) mx8qm-ahab-container.img scfw_tcm.bin
./$(MKIMG) -soc QM -rev B0 -dcd skip -append mx8qm-ahab-container.img -c -scfw scfw_tcm.bin -out flash.bin
The target used to create a Cortex-A image only is called flash_b0.
To invoke this target for QXP from the imx-mkimage directory:
make SOC=iMX8QX flash_b0
To invoke this target for QM from the imx-mkimage directory:
make SOC=iMX8QM flash_b0
The target definition for flash_b0 can be seen below.
Definition for QXP:
flash flash_b0: $(MKIMG) mx8qx-ahab-container.img scfw_tcm.bin u-boot-atf.bin
./$(MKIMG) -soc QX -rev B0 -append mx8qx-ahab-container.img -c -scfw scfw_tcm.bin -ap u-boot-atf.bin a35 0x80000000 -out flash.bin
Definition for QM:
flash_b0: $(MKIMG) mx8qm-ahab-container.img scfw_tcm.bin u-boot-atf.bin
./$(MKIMG) -soc QM -rev B0 -append mx8qm-ahab-container.img -c -scfw scfw_tcm.bin -ap u-boot-atf.bin a53 0x80000000 -out flash.bin
The target used to create a Cortex-m4 image only is called flash_b0_cm4 on QXP and QM has different targets since there are two M4s available in the system.
To invoke this target for QXP from the imx-mkimage directory:
make SOC=iMX8QX flash_b0_cm4
To invoke this target for QM from the imx-mkimage directory:
// For Cortex-M4_0 only
make SOC=iMX8QM flash_b0_cm4_0
// For Cortex-M4_1 only
make SOC=iMX8QM flash_b0_cm4_1
// For both Cortex-M4_0 and Cortex-M4_1
make SOC=iMX8QM flash_b0_m4s_tcm
The target definition for flash_b0_cm4 can be seen below.
Definition for QXP:
flash_cm4 flash_b0_cm4: $(MKIMG) mx8qx-ahab-container.img scfw_tcm.bin m4_image.bin
./$(MKIMG) -soc QX -rev B0 -append mx8qx-ahab-container.img -c -scfw scfw_tcm.bin -p1 -m4 m4_image.bin 0 0x34FE0000 -out flash.bin
Definitions for QM:
flash_b0_cm4_0: $(MKIMG) mx8qm-ahab-container.img scfw_tcm.bin m4_image.bin
./$(MKIMG) -soc QM -rev B0 -dcd skip -append mx8qm-ahab-container.img -c -scfw scfw_tcm.bin -p1 -m4 m4_image.bin 0 0x34FE0000 -out flash.bin
flash_b0_cm4_1: $(MKIMG) mx8qm-ahab-container.img scfw_tcm.bin m4_image.bin
./$(MKIMG) -soc QM -rev B0 -dcd skip -append mx8qm-ahab-container.img -c -scfw scfw_tcm.bin -p1 -m4 m4_image.bin 1 0x38FE0000 -out flash.bin
flash_b0_m4s_tcm: $(MKIMG) mx8qm-ahab-container.img scfw_tcm.bin m40_tcm.bin m41_tcm.bin
./$(MKIMG) -soc QM -rev B0 -dcd skip -append mx8qm-ahab-container.img -c -scfw scfw_tcm.bin -p1 -m4 m40_tcm.bin 0 0x34FE0000 -m4 m41_tcm.bin 1 0x38FE0000 -out flash.bin
The examples above are for M4 images booting from TCM, the M4 is capable of booting and executing from DDR and it is also able to XIP (execute in place) from SPI memory, for examples on this targets please look at the soc.mak for the desired variant.
The target used to create an image with software for all the cores is called flash_linux_m4.
To invoke this target for QXP from the imx-mkimage directory:
make SOC=iMX8QX flash_linux_m4
To invoke this target for QM from the imx-mkimage directory:
make SOC=iMX8QM flash_linux_m4
The target definition for flash_linux_m4 can be seen below.
Definition for QXP:
flash_linux_m4: $(MKIMG) mx8qx-ahab-container.img scfw_tcm.bin u-boot-atf.bin m4_image.bin
./$(MKIMG) -soc QX -rev B0 -append mx8qx-ahab-container.img -c -flags 0x00200000 -scfw scfw_tcm.bin -ap u-boot-atf.bin a35 0x80000000 -p3 -m4 m4_image.bin 0 0x34FE0000 -out flash.bin
Definition for QM:
flash_linux_m4: $(MKIMG) mx8qm-ahab-container.img scfw_tcm.bin u-boot-atf.bin m4_0_image.bin m4_1_image.bin
./$(MKIMG) -soc QM -rev B0 -append mx8qm-ahab-container.img -c -flags 0x00200000 -scfw scfw_tcm.bin -ap u-boot-atf.bin a53 0x80000000 -p3 -m4 m4_0_image.bin 0 0x34FE0000 -p4 -m4 m4_1_image.bin 1 0x38FE0000 -out flash.bin
This will create a bootable image named flash.bin, to flash this image to the SD card and boot it on your MEK simply do:
sudo dd if=iMX8QX/flash.bin of=/dev/mmcblkX bs=1k seek=32
If the desired target is a QM variant change if=iMX8QX... to if=iMX8QM.
Then match your SD card device on "of=/dev/mmcblkX" you can see how your SD card enumerates by typing lsblk on your console before and after inserting your SD card.
Remember from the information above that the i.MX8 will search for the image at 32k on the SD card, that is why we are flashing it there.
For more examples please look at the soc.mak file, it includes examples for different boot media (NAND/QSPI) as well as different configurations and usage.
Reference Manual Chapter 5 System Boot
SCFW API and Port document
this post is great, but it is outdated.
@manuelrodriguez This article needs to be updated, all the links are broken, thanks.