How to manually update bootloaders

Revision as of 20:51, 4 March 2022 by Registered User (→‎With mmc command)
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
  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.

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 previous dd command this input file: if=/dev/zero.

1.1.1. SD card update example[edit source]

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):

  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/sda{HighlightParam|2}} 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:

  mmc dev 1
  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 partition
  • 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 with the Linux dd command[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

   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:

For example:

* 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 (user data partition - default)  

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:
  mmc partconf 1 1 2 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:

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

For boot2, change the mmc device to 1.2.

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: