This page explains how to manually update the bootloaders binary (including U-Boot and TF-A) on an SD card or on the e•MMC.
1. Update of SD card[edit source]
The user has access to the SD card device partitions:
- on a Linux®PC, with a card reader of this PC
- on target, with Linux® console or U-Boot console.
The 7 first GPT partitions on the SD card are by default in OpenSTLinux BSP:
- fsbl1 or fsbla1 = TF-A BL2
- fbsl2 or fsbla2 = TF-A BL2: second copy (a manual update is not needed by default, only used for fail-safe update)
- metadata1 = TF-A firmware update data : select FIP-A
- metadata2 = TF-A firmware update data : select FIP-A, second copy of the same binary
- fip-a = FIP, first slot
- fip-b = FIP, second slot, not required as the first slot is selected in metadata
- u-boot-env = U-Boot environment
See Boot_chain_overview for the bootloader definitions.
In the next chapters, the examples are provided for STM32MP1 series with FSBL partition name fsbl1/fsbl2 but it is also applicable for STM32MP2 series with partition name for cortex-A35, with name fsbla1/fsbla2.
1.1. On a Linux® console with the Linux® dd command[edit source]
Use the Linux® dd
command to copy the bootloader files directly to the correct partition:
dd if=<file> of=/dev/<dev> conv=fdatasync
<dev> is:
- mmcblk<X>p<n>: PC-embedded card reader case or target Linux® console
- sd<X><n>: USB-connected SD card reader case
where <X> is the ID of the device, and <n> the ID of the partition.
The dd
command must be repeated for each GPT partition to update.
Note: the dd option conv=fdatasync is used to force synchronous copying.
The U-Boot environment is saved in the partition, named "u-boot-env": ID = 7 in OpenSTLinux BSP.
You can erase this partition to clear this environment; for example, by using the dd
command this input file: if=/dev/zero.
When SD card device is mmcblk0, the GPT partition p<n> is /dev/mmcblk0p<n> (for example in OpenSTLinux target console or for a PC internal card reader), the update of the SD card is done with:
dd if=tf-a-sdcard.stm32 of=/dev/mmcblk0p1 conv=fdatasync dd if=tf-a-sdcard.stm32 of=/dev/mmcblk0p2 conv=fdatasync dd if=metadata.bin of=/dev/mmcblk0p3 conv=fdatasync dd if=metadata.bin of=/dev/mmcblk0p4 conv=fdatasync dd if=fip.bin of=/dev/mmcblk0p5 conv=fdatasync dd if=/dev/zero of=/dev/mmcblk0p7 conv=fdatasync
1.2. On a U-Boot console[edit source]
1.2.1. With ums command[edit source]
Alternatively, with U-Boot ums
command, on mmc dev = 0,the SD card device on STMicroelectronics board:
ums 0 mmc 0
The exported SD card is mounted on the Linux® PC as a block device named sd<X> and the GPT partitions are exported by sd<X><n> where:
- <X> is the ID of the device starting at a
- <n> the ID of the partition.
If the block device SD card is available in /dev/sda (with <X> = a but this value must be verified on your PC), the partitions are updated with the dd command:
dd if=tf-a-sdcard.stm32 of=/dev/sda1 conv=fdatasync dd if=tf-a-sdcard.stm32 of=/dev/sda2 conv=fdatasync dd if=metadata.bin of=/dev/sda3 conv=fdatasync dd if=metadata.bin of=/dev/sda4 conv=fdatasync dd if=fip.bin of=/dev/sda5 conv=fdatasync dd if=/dev/zero of=/dev/sda7 conv=fdatasync
1.2.2. With mmc command[edit source]
The command mmc
can be used also to directly write file previously loaded in memory by other U-boot command.
For example, to check partition offset on dev 0, SD Card on STMicroelectonics boards:
mmc dev 0
mmc part
Partition Map for MMC device 0 -- Partition Type: EFI
Part Start LBA End LBA Name Attributes Type GUID Partition GUID 1 0x00000022 0x00000221 "fsbl1" ....
To write TF-A, loaded at 0xC000000 at blk# = 22 for 256KB (0x200*512)
mmc write 0xC0000000 22 200
With block address (blk#) and clock count (ctn), multiple of block size = LBA of 512 bytes.
2. Update of e•MMC[edit source]
The user has access to the e•MMC device partitions on target, with Linux® console or U-Boot console.
The e•MMC memory mapping are by default:
- FSBL = TF-A is saved in the e•MMC boot partitions (2 copy for fail-safe update)
- Other binaries are in the GPT partitions of the e•MMC user area
- metadata1 = TF-A firmware update data : select FIP-A
- metadata2 = TF-A firmware update data : select FIP-A, second copy of the same binary
- fip-a = FIP, first slot
- fip-b = FIP, second slot, not required as the first slot is selected in metadata
- u-boot-env = U-Boot environment
The user must select the e•MMC hardware partition to update: user data, boot1, or boot2.
2.1. On a Linux® console[edit source]
If dev = mmcblk1 for e•MMC device (default on STMicroelectronics board).
The boot partitions are available in /dev/mmcblk1boot0 and /dev/mmcblk1boot1 [1].
The user could need to allow access, for example with:
echo 0 > /sys/class/block/mmcblk1boot0/force_ro
The mmc
tools allow the boot partition that can be selected [2].
The ROM code requires:
- <send_ack> =1 to enable the boot acknowledge bit in the e•MMC ext_csd register
- the eMMC boot configuration is: 1 wire configuration and 25 MHz, it is done with the command:
mmc bootbus set single_backward x1 x1 dev/mmcblk1
To update TF-A in boot1 and select this boot partition (default):
dd if=tf-a-emmc.stm32 of=/dev/mmcblk1boot0 conv=fdatasync mmc bootpart enable 1 1 /dev/mmcblk1
To update TF-A in boot2 and select this boot partition (not needed by default, only required for fail-safe update):
dd if=tf-a-emmc.stm32 of=/dev/mmcblk1boot1 conv=fdatasync mmc bootpart enable 2 1 /dev/mmcblk1
To update the GPT partitions:
dd if=/dev/zero of=/dev/mmcblk1p1 conv=fdatasync dd if=metadata.bin of=/dev/mmcblk1p1 conv=fdatasync dd if=metadata.bin of=/dev/mmcblk1p2 conv=fdatasync dd if=fip.bin of=/dev/mmcblk1p3 conv=fdatasync
The U-Boot environment is saved in the partition, named "u-boot-env": ID = 5 in OpenSTLinux.
You can erase this partition to clear this environment; for example, by using the dd command this input file: if=/dev/zero.
dd if=/dev/zero of=/dev/mmcblk1p5 conv=fdatasync
See also [3].
2.2. On a U-Boot console[edit source]
If mmc device [dev] = 1 for e•MMC device in U-Boot (default on STMicroelectronics board).
The command mmc
is used in U-Boot console for e•MMC device configuration.
mmc bootbus <dev> <boot_bus_width> <reset_boot_bus_width> <boot_mode>
Before the first boot, select the right e•MMC boot configuration (1 wire, 25 MHz) with the command:
mmc bootbus 1 0 0 0
2.2.1. Select boot partition[edit source]
The targeted e•MMC HW partition is selected in U-Boot by the command mmc partconf
:
mmc partconf <dev> [[varname] | [<boot_ack> <boot_partition> <partition_access>]]
With:
- dev = 1 (e•MMC device on STMicroelectronics board)
- boot_ack=1 (the boot acknowledge bit in the e•MMC ext_csd register is needed by ROM code)
- boot_partition = 1 (boot partition 1 enabled for boot)
- partition_access = 0
- 0: user data partition (default)
- 1: boot partition 1
- 2: boot partition 2
Do not change the last parameter partition_access value if you do not manually access the boot partition content with mmc read
or mmc write
.
The command to select the boot partition used by ROM code on e•MMC at next reboot is:
- for boot1:
mmc partconf 1 1 1 0
- for boot2 (not needed by default, only required for fail-safe update):
mmc partconf 1 1 2 0
2.2.2. With ums command[edit source]
The e•MMC update is done with the ums
command, with the U-Boot's partition syntax U-Boot's partition syntax:
<command> <interface> [devnum][.hwpartnum][:partnum|#partname]
The exported e•MMC is mounted on the Linux® PC as a block device named sd<X> and the GPT partitions are exported by sd<X><n> where
- <X> is the ID of the device starting at a
- <n> the ID of the partition.
In the next examples, we assume <X> = a, so the block device e•MMC available in /dev/sda but this value must be verified on your PC.
boot partitions
This boot partition by ROM code is selected in previous step #select boot partition, only the selected on needed to be updated.
To update FSBL=TF-A in the boot1 HW partition.
ums 0 mmc 1.1 UMS: LUN 0, dev 1, hwpart 1, sector 0x0, count 0x1000
On boot partitions, without GPT partitions, just copy TF-A binary on the block device /dev/sda exported by U-Boot.
dd if=tf-a-emmc.stm32 of=/dev/sda conv=fdatasync
To update boot2, change the mmc device to 1.2; but it not needed by default if boot1 is selected: mmc partconf 1 1 1 0
.
It is only required for fail-safe update, when the boot partition is selected after update with mmc partconf
.
ums 0 mmc 1.2 UMS: LUN 0, dev 1, hwpart 2, sector 0x0, count 0x1000 dd if=tf-a-emmc.stm32 of=/dev/sda conv=fdatasync
And select boot2 partition after update:
mmc partconf 1 1 2 0
user data partition
To export all the e•MMC in /dev/sda, including all GPT partitions in /dev/sdaN:
ums 0 mmc 1
And copy each binary in the GPT partitions of this block device:
dd if=metadata.bin of=/dev/sda1 conv=fdatasync dd if=metadata.bin of=/dev/sda2 conv=fdatasync dd if=fip.bin of=/dev/sda3 conv=fdatasync
And clear the U-Boot environment with
dd if=/dev/zero of=/dev/mmcblk1p5 conv=fdatasync
2.2.3. With mmc command[edit source]
The command mmc
can be used also to directly write file previously loaded in memory by an other U-Boot command.
For example, to check the GPT partition of e•MMC, on dev=1 for STMicroelectronics board:
mmc dev 1 mmc part
To write TF-A , loaded at 0xC000000 at blk# = 0 for boot1 for 256KB (0x200*512):
mmc partconf 1 1 1 1 mmc write 0xC0000000 0 200 mmc partconf 1 1 1 0
See in #select boot partition for details on boot_partition=1 and partition_access=1 and 0 of mmc partconf
.
To write metadata1, loaded at 0xC000000 at blk# = 0x00, size = 1KB (0x2*512)
mmc write 0xC0000000 00 2
With block address (blk#) and clock count (ctn), multiple of block size = LBA of 512 bytes.
3. Update of NOR[edit source]
The user has access to the NOR device partitions on target, with Linux® console or U-Boot console.
The 7 first partitions on the NOR device are by default in OpenSTLinux BSP:
- fsbl1 or fsbla1 = TF-A BL2
- fbsl2 or fsbla2 = TF-A BL2: second copy (a manual update is not needed by default, only used for fail-safe update)
- metadata1 = TF-A firmware update data : select FIP-A
- metadata2 = TF-A firmware update data : select FIP-A, second copy of the same binary
- fip-a = FIP, first slot
- fip-b = FIP, second slot, not required as the first slot is selected in metadata
- u-boot-env = U-Boot environment
In the next chapters, the examples are provided for STM32MP1 series with FSBL partition name fsbl1/fsbl2 but it is also applicable for STM32MP2 series with partition name for cortex-A35, with name fsbla1/fsbla2.
3.1. On a Linux® console with the Linux® mtd_debug command[edit source]
NOR device partitions can be listed using the mtdinfo command
root:~# mtdinfo -a Count of MTD devices: 8 Present MTD devices: mtd0, mtd1, mtd2, mtd3, mtd4, mtd5, mtd6, mtd7 Sysfs interface supported: yes mtd0 Name: fsbl1 Type: nor Eraseblock size: 65536 bytes, 64.0 KiB Amount of eraseblocks: 4 (262144 bytes, 256.0 KiB) Minimum input/output unit size: 1 byte Sub-page size: 1 byte Character device major/minor: 90:0 Bad blocks are allowed: false Device is writable: true mtd1 Name: fsbl2 Type: nor Eraseblock size: 65536 bytes, 64.0 KiB Amount of eraseblocks: 4 (262144 bytes, 256.0 KiB) Minimum input/output unit size: 1 byte Sub-page size: 1 byte Character device major/minor: 90:2 Bad blocks are allowed: false Device is writable: true mtd2 Name: metadata1 Type: nor Eraseblock size: 65536 bytes, 64.0 KiB Amount of eraseblocks: 4 (262144 bytes, 256.0 KiB) Minimum input/output unit size: 1 byte Sub-page size: 1 byte Character device major/minor: 90:4 Bad blocks are allowed: false Device is writable: true mtd3 Name: metadata2 Type: nor Eraseblock size: 65536 bytes, 64.0 KiB Amount of eraseblocks: 4 (262144 bytes, 256.0 KiB) Minimum input/output unit size: 1 byte Sub-page size: 1 byte Character device major/minor: 90:6 Bad blocks are allowed: false Device is writable: true mtd4 Name: fip-a Type: nor Eraseblock size: 65536 bytes, 64.0 KiB Amount of eraseblocks: 64 (4194304 bytes, 4.0 MiB) Minimum input/output unit size: 1 byte Sub-page size: 1 byte Character device major/minor: 90:8 Bad blocks are allowed: false Device is writable: true mtd5 Name: fip-b Type: nor Eraseblock size: 65536 bytes, 64.0 KiB Amount of eraseblocks: 64 (4194304 bytes, 4.0 MiB) Minimum input/output unit size: 1 byte Sub-page size: 1 byte Character device major/minor: 90:10 Bad blocks are allowed: false Device is writable: true mtd6 Name: u-boot-env Type: nor Eraseblock size: 65536 bytes, 64.0 KiB Amount of eraseblocks: 8 (524288 bytes, 512.0 KiB) Minimum input/output unit size: 1 byte Sub-page size: 1 byte Character device major/minor: 90:12 Bad blocks are allowed: false Device is writable: true mtd7 Name: nor-user Type: nor Eraseblock size: 65536 bytes, 64.0 KiB Amount of eraseblocks: 872 (57147392 bytes, 54.5 MiB) Minimum input/output unit size: 1 byte Sub-page size: 1 byte Character device major/minor: 90:14 Bad blocks are allowed: false Device is writable: true
Before writing a NOR partition, it must be erased. To erase NOR partitions :
root:~# mtd_debug erase /dev/mtd0 0 0x40000 root:~# mtd_debug erase /dev/mtd1 0 0x40000 root:~# mtd_debug erase /dev/mtd2 0 0x40000 root:~# mtd_debug erase /dev/mtd3 0 0x40000 root:~# mtd_debug erase /dev/mtd4 0 0x400000 root:~# mtd_debug erase /dev/mtd5 0 0x400000 root:~# mtd_debug erase /dev/mtd6 0 0x80000
To write binaries in their respective partition :
root:~# mtd_debug write /dev/mtd0 0 0x40000 tf-a-nor.stm32 root:~# mtd_debug write /dev/mtd1 0 0x40000 tf-a-nor.stm32 root:~# mtd_debug write /dev/mtd2 0 0x40000 metadata.bin root:~# mtd_debug write /dev/mtd3 0 0x40000 metadata.bin root:~# mtd_debug write /dev/mtd4 0 0x400000 fip.bin root:~# mtd_debug write /dev/mtd5 0 0x400000 fip.bin
3.2. On a U-Boot console[edit source]
NOR device partitions can be listed using the command mtd list which shows start and end offset of all partitions
mtd list List of MTD devices: * nor1 - device: flash@0 - parent: spi@40430000 - driver: jedec_spi_nor - path: /soc@0/ommanager@40500000/spi@40430000/flash@0 - type: NOR flash - block size: 0x10000 bytes - min I/O: 0x1 bytes - 0x000000000000-0x000004000000 : "nor1" - 0x000000000000-0x000000040000 : "fsbl1" - 0x000000040000-0x000000080000 : "fsbl2" - 0x000000080000-0x0000000c0000 : "metadata1" - 0x0000000c0000-0x000000100000 : "metadata2" - 0x000000100000-0x000000500000 : "fip-a" - 0x000000500000-0x000000900000 : "fip-b" - 0x000000900000-0x000000980000 : "u-boot-env" - 0x000000980000-0x000004000000 : "nor-user"
In this example, "fip-a" partition is located on nor1 device, starts at offset 0x000000100000 and ends at offset 0x000000500000, fip-a partition size is 0x400000.
Before writing NOR partitions, it must be erased. To erase NOR partitions :
mtd erase nor1 0x000000000000 0x40000 mtd erase nor1 0x000000040000 0x40000 mtd erase nor1 0x000000080000 0x40000 mtd erase nor1 0x0000000c0000 0x40000 mtd erase nor1 0x000000100000 0x400000 mtd erase nor1 0x000000500000 0x400000 mtd erase nor1 0x000000900000 0x80000
To write "fip-a" binaries previously loaded in DDR at 0xC0000000 in nor1 in "fip-a" partition
mtd write nor1 0xC0000000 0x000000100000 0x2DB1C9 Writing 2994633 byte(s) at offset 0x00100000
4. Update of NAND[edit source]
The user has access to the NAND device partitions on target, with Linux® console or U-Boot console.
The 8 first partitions on the NAND device are by default in OpenSTLinux BSP:
- fsbl1 or fsbla1 = TF-A BL2
- fbsl2 or fsbla2 = TF-A BL2: second copy (a manual update is not needed by default, only used for fail-safe update)
- metadata1 = TF-A firmware update data : select FIP-A
- metadata2 = TF-A firmware update data : select FIP-A, second copy of the same binary
- fip-a1 = FIP, first slot
- fip-a2 = FIP, copy of first slot
- fip-b1 = FIP, second slot, not required as the first slot is selected in metadata
- fip-b2 = FIP, copy of second slot, not required as the first slot is selected in metadata
In the next chapters, the examples are provided for STM32MP1 series with FSBL partition name fsbl1/fsbl2 but it is also applicable for STM32MP2 series with partition name for cortex-A35, with name fsbla1/fsbla2.
4.1. On a Linux® console with the Linux® flash_erase and nandwrite commands[edit source]
NAND device partitions can be listed using the mtdinfo command
root:~# mtdinfo -a Count of MTD devices: 8 Present MTD devices: mtd0, mtd1, mtd2, mtd3, mtd4, mtd5, mtd6, mtd7, mtd8 Sysfs interface supported: yes mtd0 Name: fsbl1 Type: nand Eraseblock size: 262144 bytes, 256.0 KiB Amount of eraseblocks: 2 (524288 bytes, 512.0 KiB) Minimum input/output unit size: 4096 bytes Sub-page size: 4096 bytes OOB size: 224 bytes Character device major/minor: 90:18 Bad blocks are allowed: true Device is writable: true mtd1 Name: fsbl2 Type: nand Eraseblock size: 262144 bytes, 256.0 KiB Amount of eraseblocks: 2 (524288 bytes, 512.0 KiB) Minimum input/output unit size: 4096 bytes Sub-page size: 4096 bytes OOB size: 224 bytes Character device major/minor: 90:20 Bad blocks are allowed: true Device is writable: true mtd2 Name: metadata1 Type: nand Eraseblock size: 262144 bytes, 256.0 KiB Amount of eraseblocks: 2 (524288 bytes, 512.0 KiB) Minimum input/output unit size: 4096 bytes Sub-page size: 4096 bytes OOB size: 224 bytes Character device major/minor: 90:22 Bad blocks are allowed: true Device is writable: true mtd3 Name: metadata2 Type: nand Eraseblock size: 262144 bytes, 256.0 KiB Amount of eraseblocks: 2 (524288 bytes, 512.0 KiB) Minimum input/output unit size: 4096 bytes Sub-page size: 4096 bytes OOB size: 224 bytes Character device major/minor: 90:24 Bad blocks are allowed: true Device is writable: true mtd4 Name: fip-a1 Type: nand Eraseblock size: 262144 bytes, 256.0 KiB Amount of eraseblocks: 16 (4194304 bytes, 4.0 MiB) Minimum input/output unit size: 4096 bytes Sub-page size: 4096 bytes OOB size: 224 bytes Character device major/minor: 90:26 Bad blocks are allowed: true Device is writable: true mtd5 Name: fip-a2 Type: nand Eraseblock size: 262144 bytes, 256.0 KiB Amount of eraseblocks: 16 (4194304 bytes, 4.0 MiB) Minimum input/output unit size: 4096 bytes Sub-page size: 4096 bytes OOB size: 224 bytes Character device major/minor: 90:28 Bad blocks are allowed: true Device is writable: true mtd6 Name: fip-b1 Type: nand Eraseblock size: 262144 bytes, 256.0 KiB Amount of eraseblocks: 16 (4194304 bytes, 4.0 MiB) Minimum input/output unit size: 4096 bytes Sub-page size: 4096 bytes OOB size: 224 bytes Character device major/minor: 90:30 Bad blocks are allowed: true Device is writable: true mtd7 Name: fip-b2 Type: nand Eraseblock size: 262144 bytes, 256.0 KiB Amount of eraseblocks: 16 (4194304 bytes, 4.0 MiB) Minimum input/output unit size: 4096 bytes Sub-page size: 4096 bytes OOB size: 224 bytes Character device major/minor: 90:32 Bad blocks are allowed: true Device is writable: true mtd8 Name: UBI Type: nand Eraseblock size: 262144 bytes, 256.0 KiB Amount of eraseblocks: 4024 (1054867456 bytes, 1006.0 MiB) Minimum input/output unit size: 4096 bytes Sub-page size: 4096 bytes OOB size: 224 bytes Character device major/minor: 90:34 Bad blocks are allowed: true Device is writable: true
In this example, "fip-a1" partition is located in /dev/mtd4 device
Before writing NAND partitions, it must be erased. To erase NAND partitions
root:~# flash_erase /dev/mtd0 0 0 root:~# flash_erase /dev/mtd1 0 0 root:~# flash_erase /dev/mtd2 0 0 root:~# flash_erase /dev/mtd3 0 0 root:~# flash_erase /dev/mtd4 0 0 root:~# flash_erase /dev/mtd5 0 0 root:~# flash_erase /dev/mtd6 0 0 root:~# flash_erase /dev/mtd7 0 0
To write binaries in NAND
root:~# root@stm32mp1:~# nandwrite -p /dev/mtd0 tf-a-nand.stm32 root:~# root@stm32mp1:~# nandwrite -p /dev/mtd1 tf-a-nand.stm32 root:~# root@stm32mp1:~# nandwrite -p /dev/mtd2 metadata.bin root:~# root@stm32mp1:~# nandwrite -p /dev/mtd3 metadata.bin root:~# root@stm32mp1:~# nandwrite -p /dev/mtd4 fip.bin root:~# root@stm32mp1:~# nandwrite -p /dev/mtd5 fip.bin root:~# root@stm32mp1:~# nandwrite -p /dev/mtd6 fip.bin root:~# root@stm32mp1:~# nandwrite -p /dev/mtd7 fip.bin
4.2. On a U-Boot console[edit source]
NAND device partitions can be listed using the command mtd list which shows start and end offset of all partitions
mtd list List of MTD devices: *nand0 - type: NAND flash - block size: 0x40000 bytes - min I/O: 0x1000 bytes - OOB size: 224 bytes - OOB available: 118 bytes - ECC strength: 8 bits - ECC step size: 512 bytes - bitflip threshold: 6 bits - 0x000000000000-0x000040000000 : "nand0" - 0x000000000000-0x000000080000 : "fsbl1" - 0x000000080000-0x000000100000 : "fsbl2" - 0x000000100000-0x000000180000 : "metadata1" - 0x000000180000-0x000000200000 : "metadata2" - 0x000000200000-0x000000600000 : "fip-a1" - 0x000000600000-0x000000a00000 : "fip-a2" - 0x000000a00000-0x000000e00000 : "fip-b1" - 0x000000e00000-0x000001200000 : "fip-b2" - 0x000001200000-0x000040000000 : "UBI"
In this example, "fip-a1" partition starts at offset 0x000000200000 and ends at offset 0x000000600000, fip-a1 partition size is 0x400000.
Before writing NAND partitions, it must be erased.
nand erase 0x000000000000 0x80000 nand erase 0x000000800000 0x80000 nand erase 0x000001000000 0x80000 nand erase 0x000001800000 0x80000 nand erase 0x000002000000 0x400000 nand erase 0x000006000000 0x400000 nand erase 0x00000a000000 0x400000 nand erase 0x00000e000000 0x400000
To write "fip-a1" binary previously loaded in DDR at 0xC0000000 in "fip-a1" partition
nand write 0xC0000000 0x000000200000 400000
5. References[edit source]
Please refer to the following links for additional information: