Introduction
For one of our customers building a product based on i.MX6 with a fairly low-volume, we had to design a mechanism to perform the factory flashing of each product. The goal is to be able to take a freshly produced device from the state of a brick to a state where it has a working embedded Linux system flashed on it. This specific product is using an eMMC as its main storage, and our solution only needs a USB connection with the platform, which makes it a lot simpler than solutions based on network (TFTP, NFS, etc.).
In order to achieve this goal, we have combined the imx-usb-loader
tool with the fastboot support in U-Boot and some scripting. Thanks to this combination of a tool, running a single script is sufficient to perform the factory flashing, or even restore an already flashed device back to a known state.
The overall flow of our solution, executed by a shell script, is:
imx-usb-loader
pushes over USB a U-Boot bootloader into the i.MX6 RAM, and runs it;- This U-Boot automatically enters fastboot mode;
- Using the fastboot protocol and its support in U-Boot, we send and flash each part of the system: partition table, bootloader, bootloader environment and root filesystem (which contains the kernel image).
imx-usb-loader
imx-usb-loader is a tool written by Boundary Devices that leverages the Serial Download Procotol (SDP) available in Freescale i.MX5/i.MX6 processors. Implemented in the ROM code of the Freescale SoCs, this protocol allows to send some code over USB or UART to a Freescale processor, even on a platform that has nothing flashed (no bootloader, no operating system). It is therefore a very handy tool to recover i.MX6 platforms, or as an initial step for factory flashing: you can send a U-Boot image over USB and have it run on your platform.
This tool already existed, we only created a package for it in the Buildroot build system, since Buildroot is used for this particular project.
Fastboot
Fastboot is a protocol originally created for Android, which is used primarily to modify the flash filesystem via a USB connection from a host computer. Most Android systems run a bootloader that implements the fastboot protocol, and therefore can be reflashed from a host computer running the corresponding fastboot
tool. It sounded like a good candidate for the second step of our factory flashing process, to actually flash the different parts of our system.
Setting up fastboot on the device side
The well known U-Boot bootloader has limited support for this protocol:
- usb/gadget: add the fastboot gadget
- usb/gadget: fastboot: add eMMC support for flash command
- usb/gadget: fastboot: add support for flash command
The fastboot documentation in U-Boot can be found in the source code, in the doc/README.android-fastboot file. A description of the available fastboot
options in U-Boot can be found in this documentation as well as examples. This gives us the device side of the protocol.
In order to make fastboot work in U-Boot, we modified the board configuration file to add the following configuration options:
#define CONFIG_CMD_FASTBOOT #define CONFIG_USB_FASTBOOT_BUF_ADDR CONFIG_SYS_LOAD_ADDR #define CONFIG_USB_FASTBOOT_BUF_SIZE 0x10000000 #define CONFIG_FASTBOOT_FLASH #define CONFIG_FASTBOOT_FLASH_MMC_DEV 0
Other options have to be selected, depending on the platform to fullfil the fastboot dependencies, such as USB Gadget support, GPT partition support, partitions UUID support or the USB download gadget. They aren’t explicitly defined anywhere, but have to be enabled for the build to succeed.
You can find the patch enabling fastboot on the Seco MX6Q uQ7 here: 0002-secomx6quq7-enable-fastboot.patch.
U-Boot enters the fastboot
mode on demand: it has to be explicitly started from the U-Boot command line:
U-Boot> fastboot
From now on, U-Boot waits over USB for the host computer to send fastboot commands.
Using fastboot on the host computer side
Fastboot needs a user-space program on the host computer side to talk to the board. This tool can be found in the Android SDK and is often available through packages in many Linux distributions. However, to make things easier and like we did for imx-usb-loader
, we sent a patch to add the Android tools such as fastboot and adb
to the Buildroot build system. As of this writing, our patch is still waiting to be applied by the Buildroot maintainers.
Thanks to this, we can use the fastboot tool to list the available fastboot devices connected:
# fastboot devices
Flashing eMMC partitions
For its flashing feature, fastboot
identifies the different parts of the system by names. U-Boot maps those names to the name of GPT partitions, so your eMMC normally requires to be partitioned using a GPT partition table and not an old MBR partition table. For example, provided your eMMC has a GPT partition called rootfs
, you can do:
# fastboot flash rootfs rootfs.ext4
To reflash the contents of the rootfs
partition with the rootfs.ext4
image.
However, while using GPT partitioning is fine in most cases, i.MX6 has a constraint that the bootloader needs to be at a specific location on the eMMC that conflicts with the location of the GPT partition table.
To work around this problem, we patched U-Boot to allow the fastboot flash
command to use an absolute offset in the eMMC instead of a partition name. Instead of displaying an error if a partition does not exists, fastboot
tries to use the name as an absolute offset. This allowed us to use MBR partitions and to flash at defined offset our images, including U-Boot. For example, to flash U-Boot, we use:
# fastboot flash 0x400 u-boot.imx
The patch adding this work around in U-Boot can be found at 0001-fastboot-allow-to-flash-at-a-given-address.patch. We are working on implementing a better solution that can potentially be accepted upstream.
Automatically starting fastboot
The fastboot
command must be explicitly called from the U-Boot prompt in order to enter fastboot mode. This is an issue for our use case, because the flashing process can’t be fully automated and required a human interaction. Using imx-usb-loader
, we want to send a U-Boot image that automatically enters fastmode mode.
To achieve this, we modified the U-Boot configuration, to start the fastboot command at boot time:
#define CONFIG_BOOTCOMMAND "fastboot" #define CONFIG_BOOTDELAY 0
Of course, this configuration is only used for the U-Boot sent using imx-usb-loader
. The final U-Boot flashed on the device will not have the same configuration. To distinguish the two images, we named the U-Boot image dedicated to fastboot uboot_DO_NOT_TOUCH
.
Putting it all together
We wrote a shell script to automatically launch the modified U-Boot image on the board, and then flash the different images on the eMMC (U-Boot and the root filesystem). We also added an option to flash an MBR partition table as well as flashing a zeroed file to wipe the U-Boot environment. In our project, Buildroot is being used, so our tool makes some assumptions about the location of the tools and image files.
Our script can be found here: flash.sh. To flash the entire system:
# ./flash.sh -a
To flash only certain parts, like the bootloader:
# ./flash.sh -b
By default, our script expects the Buildroot output directory to be in buildroot/output
, but this can be overridden using the BUILDROOT
environment variable.
Conclusion
By assembling existing tools and mechanisms, we have been able to quickly create a factory flashing process for i.MX6 platforms that is really simple and efficient. It is worth mentioning that we have re-used the same idea for the factory flashing process of the C.H.I.P computer. On the C.H.I.P, instead of using imx-usb-loader
, we have used FEL based booting: the C.H.I.P indeed uses an Allwinner ARM processor, providing a different recovery mechanism than the one available on i.MX6.
Hi,
Thanks for the article on imx6 fast boot usage.
I have a question on how to use fastboot commands on the imx6 processor together with a NOR Flash storage.
Currently “rx_process_flash” function in “cmd_fastboot.c” file supports three storage types.
CONFIG_FASTBOOT_STORAGE_MMC
CONFIG_FASTBOOT_STORAGE_NAND
CONFIG_FASTBOOT_STORAGE_SATA
However, there is no CONFIG type for NOR storage. Sending a fastboot flash command from the host machine result in the following response from the U-Boot console.
Not support flash command for current device 0
send: FAILfailed to flash device
Does fastboot provides support for NOR flash? What modifications do I need to do in order to in the U-Boot configuration file in-order to support fastboot for NOR storage?
NXP themselves have a hassle free tool to factory program i.MX6 based boards- its called IMX6_L4.1.15_2.0.0_MFG-TOOL. It can simultaneously flash 4 boards.
Here is the link to the tools page:
https://www.nxp.com/products/microcontrollers-and-processors/arm-based-processors-and-mcus/i.mx-applications-processors/i.mx-6-processors/i.mx-6ull-single-core-processor-with-arm-cortex-a7-core:i.MX6ULL?tab=Design_Tools_Tab
Now replaced by UUU (Universal Update Utility)
See: https://github.com/NXPmicro/mfgtools