How to manually update bootloaders

Revision as of 21:13, 4 March 2022 by Registered User (→‎select boot partition)
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:

  1. FSBL1 = TF-A BL2
  2. FSBL2 = TF-A BL2 (second copy)
  3. metadata1 (select FIP-A)
  4. metadata2 (select FIP-A, second copy)
  5. FIP-A
  6. FIP-B (not required as FIP-A is selected)
  7. u-boot-env

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 need 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; 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=metadata1.bin of=/dev/mmcblk0p3 conv=fdatasync
  dd if=metadata2.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 (SD card device on STMicroelectronics board), GPT partition <n> is /dev/sda<n> :

  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=metadata1.bin of=/dev/sda3 conv=fdatasync
  dd if=metadata2.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.

   help mmc
 mmc - MMC sub system
 
 Usage:
 mmc info - display info of the current MMC device
 mmc read addr blk# ctn
 mmc write addr blk# cnt
 mmc erase blk# cnt
 mmc rescan [mode]
 mmc part - lists available partition on current mmc device
 mmc dev [dev] [part] [mode] - show or set current mmc device [partition] and set mode
   - the required speed mode is passed as the index from the following list
     [MMC_LEGACY, MMC_HS, SD_HS, MMC_HS_52, MMC_DDR_52, UHS_SDR12, UHS_SDR25,
     UHS_SDR50, UHS_DDR50, UHS_SDR104, MMC_HS_200, MMC_HS_400, MMC_HS_400_ES]
 mmc list - lists available devices
 ...

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	{{HighlightParam|0x00000022}	0x00000221	"fsbl1"
 ....

To write TF-A, loaded at 0xC000000 at blk# = {{HighlightParam|22} for 256KB (0x200*512)

  mmc write 0xC0000000 {{HighlightParam|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 failsafe update)
  • Other binaries are in the GPT partitions of the eMMC user area
  1. metadata1 (select FIP-A)
  2. metadata2 (select FIP-A, second copy)
  3. FIP-A
  4. FIP-B (not required as FIP-A is selected)
  5. u-boot-env

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 perhaps needs to allow access, for example with:

   echo 0 > /sys/class/block/mmcblk1boot0/force_ro

The mmc tools allow the boot partition to be selected [2].

The ROM code requires:

  • <send_ack> =1
  • 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=metadata1.bin of=/dev/mmcblk1p1 conv=fdatasync
  dd if=metadata2.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; 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.

   help mmc    
 mmc - MMC sub system
 
 Usage:
 mmc info - display info of the current MMC device
 mmc read addr blk# cnt
 mmc write addr blk# cnt
 mmc erase blk# cnt
 mmc rescan [mode]
 mmc part - lists available partition on current mmc device
 mmc dev [dev] [part] [mode] - show or set current mmc device [partition] and set mode
   - the required speed mode is passed as the index from the following list
     [MMC_LEGACY, MMC_HS, SD_HS, MMC_HS_52, MMC_DDR_52, UHS_SDR12, UHS_SDR25,
     UHS_SDR50, UHS_DDR50, UHS_SDR104, MMC_HS_200, MMC_HS_400, MMC_HS_400_ES]
 mmc list - lists available devices
 mmc wp - power on write protect boot partitions
 mmc hwpartition <USER> <GP> <MODE> - does hardware partitioning
   arguments (sizes in 512-byte blocks):
    USER - <user> <enh> <start> <cnt> <wrrel> <{on|off}>
 	: sets user data area attributes
    GP - <{gp1|gp2|gp3|gp4}> <cnt> <enh> <wrrel> <{on|off}>
 	: general purpose partition
    MODE - <{check|set|complete}>
 	: mode, complete set partitioning completed
   WARNING: Partitioning is a write-once setting once it is set to complete.
   Power cycling is required to initialize partitions after set to complete.
 mmc bootbus <dev> <boot_bus_width> <reset_boot_bus_width> <boot_mode>
  - Set the BOOT_BUS_WIDTH field of the specified device
 mmc bootpart-resize <dev> <boot part size MB> <RPMB part size MB>
  - Change sizes of boot and RPMB partitions of specified device
 mmc partconf <dev> [[varname] | [<boot_ack> <boot_partition> <partition_access>]]
  - Show or change the bits of the PARTITION_CONFIG field of the specified device
    If showing the bits, optionally store the boot_partition field into varname
 ...


Before the first boot, select the eMMC correct 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 (Boot Acknowledge 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

Don't change the last parameter partition_access value if you don't 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[4]:

 <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

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.

  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

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=metadata1.bin of=/dev/sda1 conv=fdatasync
  dd if=metadata2.bin of=/dev/sda2conv=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 other U-boot command.

To check the GPT partition of eMMC, on dev=1 for STMicroelectronics board:

  mmc dev 1
  mmc part

To write metadata1, loaded at 0xC000000 at blk# = {{HighlightParam|0x00}, size = 1KB (0x2*512)

  mmc write 0xC0000000 {{HighlightParam|00} 2

With block address (blk#) and clock count (ctn), multiple of block size = LBA of 512 bytes.

2.3. References[edit source]

Please refer to the following links for additional information: