Last edited one month ago

How to manually update bootloaders

Applicable for STM32MP13x lines, STM32MP15x lines, STM32MP21x lines, STM32MP23x lines, STM32MP25x lines

This page explains how to manually update the bootloaders binary (including U-Boot and TF-A) on boot device (SD card, eMMC, NOR, NAND)

1. Update of SD card[edit | 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:

  1. fsbl1 or fsbla1 = TF-A BL2
  2. fbsl2 or fsbla2 = 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.

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 | 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 | edit source]

1.2.1. With ums command[edit | 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 | 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 eMMC[edit | edit source]

The 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 must select the eMMC hardware partition to update: user data, boot1, or boot2.

2.1. On a Linux® console[edit | 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 | 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 | 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 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 | 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 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 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 | 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 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. Update of NOR[edit | 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:

  1. fsbl1 or fsbla1 = TF-A BL2
  2. fbsl2 or fsbla2 = 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

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

Or with MTD partition name and with variable $filesize, the size of file loaded with load command in DDR at 0xC0000000:

mtd erase fip-a
mtd write fip-a 0xC0000000 $filesize

4. Update of NAND[edit | 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:

  1. fsbl1 or fsbla1 = TF-A BL2
  2. fbsl2 or fsbla2 = 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-a1 = FIP, first slot
  6. fip-a2 = FIP, copy of first slot
  7. fip-b1 = FIP, second slot, not required as the first slot is selected in metadata
  8. 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 | 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 | edit source]

4.2.1. With nand command[edit | 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

Or you can use command with MTD partition name (with ${filesize}: the size of the loaded binary set by many command as load) :

nand erase.part fip-a1
nand write 0xC0000000 fip-a1 $filesize

4.2.2. With mtd command[edit | 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 with offset and size in MTD device.

mtd erase nand0 0x000000000000 0x80000
mtd erase nand0 0x000000800000 0x80000
mtd erase nand0 0x000001000000 0x80000
mtd erase nand0 0x000001800000 0x80000
mtd erase nand0 0x000002000000 0x400000
mtd erase nand0 0x000006000000 0x400000
mtd erase nand0 0x00000a000000 0x400000
mtd erase nand0 0x00000e000000 0x400000

To write "fip-a1" binary previously loaded in DDR at 0xC0000000 in "fip-a1" partition.

Be careful to use .dontskipff option which forces writing empty pages[4]

mtd write.dontskipff nand0 0xC0000000 0x000000200000 400000

Or you can use the MTD partition name, for example to write binary previously loaded in DDR at 0xC0000000 in the fip-a1 partition and $filesize is the size of the loaded binary.

mtd erase fip-a1
mtd write.dontskipff fip-a1 0xC0000000 $filesize

5. References[edit | edit source]

Please refer to the following links for additional information:

  1. https://www.kernel.org/doc/Documentation/mmc/mmc-dev-parts.txt
  2. https://manpages.debian.org/buster/mmc-utils/mmc.1.en.html
  3. https://www.emcraft.com/som/stm32mp1/booting-linux-from-emmc
  4. http://www.linux-mtd.infradead.org/doc/ubi.html#L_flasher_algo: indicated the expected content of empty page for UBI
    The .dontskipff option of mtdcommand forces writing empty pages; it must be used for boot-loader images, it must be not used for UBI images.
    The inverse option .trimfss is defined for nand command, it is required only when flashing UBI images or by default empty pages are written.