Last edited 2 years ago

How to manually update bootloaders

Applicable for STM32MP13x lines, STM32MP15x lines

This page explains how to manually update the bootloaders binary (including U-Boot and TF-A) on an SD card or on the eMMC.

1. Update of SD card[edit source]

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:

  1. fsbl1 = TF-A BL2
  2. fbsl2 = TF-A BL2: second copy (a manual update is not needed by default, only used for fail-safe update)
  3. metadata1 = TF-A firmware update data : select FIP-A
  4. metadata2 = TF-A firmware update data : select FIP-A, second copy of the same binary
  5. fip-a = FIP, first slot
  6. fip-b = FIP, second slot, not required as the first slot is selected in metadata
  7. 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]

You can 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 needs to 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 need to 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 use 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 eMMC[edit source]

User has access to the eMMC 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 eMMC boot partitions (2 copy for fail-safe update)
  • Other binaries are in the GPT partitions of the eMMC user area
  1. metadata1 = TF-A firmware update data : select FIP-A
  2. metadata2 = TF-A firmware update data : select FIP-A, second copy of the same binary
  3. fip-a = FIP, first slot
  4. fip-b = FIP, second slot, not required as the first slot is selected in metadata
  5. u-boot-env = U-Boot environment

The user needs to select the eMMC hardware partition to update: user data, boot1, or boot2.

2.1. On a Linux® console[edit source]

If dev = mmcblk1 for eMMC 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 eMMC 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 eMMC device in U-Boot (default on STMicroelectronics board).

The command mmc is used in U-Boot console for eMMC device configuration.

 mmc bootbus <dev> <boot_bus_width> <reset_boot_bus_width> <boot_mode>

Before the first boot, select the right eMMC 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 eMMC 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 (eMMC device on STMicroelectronics board)
  • boot_ack=1 (the boot acknowledge bit in the eMMC 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 to the boot partition content with mmc read or mmc write.

The command to select the boot partition used by ROM code on eMMC 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 eMMC 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 eMMC 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 eMMC available in /dev/sda but this value need to 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 eMMC 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 use also to directly write file previously loaded in memory by an other U-Boot command.

For example, to check the GPT partition of eMMC, 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. References[edit source]

Please refer to the following links for additional information: