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 = TF-A BL2
- fbsl2 = 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.
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 = TF-A BL2
- fbsl2 = 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
3.1. On a Linux® console with the Linux® dd 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: fsbla1 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: fsbla2 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
In this example, "fip-a" partition is located in /dev/mtd4 device
Before writing "fip-a" partition, it must be erased. To erase "fip-a" partition located in /dev/mtd4 device with size of 0x40000
root:~# mtd_debug erase /dev/mtd4 0 0x40000 Erased 4194304 bytes from address 0x00000000 in flash
To write a new fip binary located in /dev/mtd4
root:~# mtd_debug write /dev/mtd4 0 0x40000 fip.bin Copied 400000 bytes from fip.bin to address 0x00000000 in flash
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 : "fsbla1" - 0x000000040000-0x000000080000 : "fsbla2" - 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 0x40000.
Before writing "fip-a" partition, it must be erased. To erase "fip-a" partition located on nor1 which start at 0x000000100000 with size of 0x40000
mtd erase nor1 0x000000100000 0x40000 Erasing 0x00100000 ... 0x004fffff (64 eraseblock(s))
To write a new fip binary loaded 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 = TF-A BL2
- fbsl2 = 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
4.1. On a Linux® console with the Linux® dd command[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 "fip-a1" partition, it must be erased. To erase "fip-a" partition located in /dev/mtd4 device
root:~# flash_erase /dev/mtd4 0 0
Erasing 4096 Kibyte @ 0 -- 100 % complete
To write a new fip binary in /dev/mtd4
root:~# root@stm32mp1:~# nandwrite -p /dev/mtd4 fip.bin
Writing data to block 0 at offset 0x0 Writing data to block 1 at offset 0x40000 Writing data to block 2 at offset 0x80000 Writing data to block 3 at offset 0xc0000
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 is located on nand0 device, starts at offset 0x000000200000 and ends at offset 0x000000600000, fip-a1 partition size is 0x40000.
Before writing "fip-a1" partition, it must be erased. To erase "fip-a1" partition located on nand0 which start at 0x000000200000 with size of 0x40000
nand erase 0x000000100000 0x40000 NAND erase: device 0 offset 0x200000, size 0x400000 Erasing at 0x5c0000 -- 100% complete. OK
To write a new fip binary loaded at 0xC0000000 in nor1 in "fip-a" partition
mtd write nor1 0xC0000000 0x000000100000 0x2DB1C9 nand write 0xC0000000 0x000000200000 40000 NAND write: device 0 offset 0x200000, size 0x40000 262144 bytes written: OK
5. References[edit source]
Please refer to the following links for additional information: