STM32CubeProgrammer can be used to read and update the OTP of the device, which is seen as a partition on the device.
This page describes the format of the partition used by the embedded programming service to allow OTP access by STM32CubeProgrammer (see AN5275: USB DFU/USART protocols used in STM32MP1 series bootloaders for protocol details).
Refer to the STM32CubeProgrammer article to know how to use the STM32CubeProgrammer that is the official STMicroelectronics tool to update OTP on STM32 platforms.
1. OTP partition[edit | edit source]
The OTP partition is identified with the reserved Id 0xF2 and is exported as:
- a specific alternate setting of the USB DFU [1].
- a special operation: OTP write (0xF2), for UART download command (0x31) and read partition command (0x12)
This is used to access the STM32MP's on-chip one time-programmable memory by the ST32CubeProgrammer (see option -otp). It is only supported in the embedded programming service = U-Boot.
The OTP partition must be programmed without a header and have a fixed size following the structure described in the chapter #Data Structure.
The OTP operation can be limited in OP-TEE or in SP_MIN, that is for security reason. In OpenSTLinux distribution the service is available only for open device (see OP-TEE PTA for details) or for serial boot (TF-A support with SMC and SP-MIN); The OTP partition is only present when the operations are supported.
1.1. Access operation[edit | edit source]
To allow provisioning, all the OTPs accessible by the secure world are exposed by this partition (upper or lower OTP) without any device tree modification. To restrict access to OTP, for example, for security reason, the device can be closed or the the provisioning TA can be deactivated in the final software delivery.
For read operation, the host requests the OTP partition data, and the platform replies with all the partition content.
For write operation, the host needs to send the full structure containing one or more modifications. The platform analyses each field.
First the OTP values are updated, then the OTP controls (such as lock) are updated.
After any write operation, a read must be done to update the Host information.
1.2. Data structure[edit | edit source]
The data structure version 2 is described in the table below.
For ecosystem release ≥ v4.0.0 , the same structure is used for
- OP-TEE support with the provisioning TA
- TF-A support with SMC when OP-TEE is not used.
The previous data structure version 1 used for ecosystem release ≤ v3.1.0 is no more used.
Its size is 776 bytes with 96 OTP for STM32MP1 series = (2 * 96 + 2) * 4 bytes for 32 bits word, with M = 0 to 95:
Word | Field name | Description |
---|---|---|
0 | Version | Version of this structure = 2 |
1 | Global State | bit-field with state of BSEC the OTP provider[GlobalState 1]
|
2 | OTP[0] | OTP value
|
3 | OTP[0] status | Status of OTP:
|
4 | OTP[1] | OTP value |
5 | OTP[1] status | Status of OTP |
... | ... | ... |
2+M*2 | OTP[M] | Value of OTP M |
3+M*2 | OTP[M] status | Status of OTP M |
- ↑ Global state: is not used during a write operation, its value should be 0 for write request
- ↑ Provisioning = OTP-SECURED open_device BSEC state, the secrets are not provisioned (see Life cycle for detail).
- ↑ Secured = OTP-SECURED closed_device BSEC state, the secrets are provisioned and protected (see Life cycle for detail).
- ↑ Hardware Key set bit indicates the provisioned firmware encryption key for STM32MP13x lines , not used for STM32MP15x lines
- ↑ Encrypted data bit is reserved to indicate an encrypted content of OTP for read or write operation, not yet implemented.
You can write OTP without read operation by using a buffer initialized with 0x0, except the version word set to 0x2.
You can also read the current value of the OTP in a buffer and reuse the same buffer for the write operation, as bit 31 of OTP status is 0 for read.
To update an OTP, you need to update the used buffer for the modified OTP:
- the OTP value, set at 0x0 if unmodified for lock only operation
- the OTP status lock values for prog lock and/or read lock after OTP value update, set to 0x0 if unmodified
- request the update: set the bit 31 of the OTP status to indicate a modification request of this OTP
The operation is interrupted on the first error.
2. Examples[edit | edit source]
2.1. Operations with OTP status[edit | edit source]
With OTP[0] status bit-field values:
- programmation request: bit31 => 0x80000000
- permanent lock: bit 30 => 0x40000000
Some simple operations are, with the structure full of zero except:
- write X in OTP_N
- OTP[N] value = X
- OTP[N] status = 0x80000000
- prog lock OTP N
- OTP[N] value = 0x0
- OTP[N] status = 0xC0000000
- write and lock OTP N
- OTP[N] value = X
- OTP[N] status = 0xC0000000
- write value and sticky read+permanent lock for OTP N to N+2
- OTP[N] value = X
- OTP[N] status = 0xE0000000
- OTP[N + 1] value = Y
- OTP[N + 1] status = 0xE0000000
- OTP[N + 2] value = Z
- OTP[N + 2] status = 0xE0000000
2.2. Examples with STM32Programmer[edit | edit source]
The OTP can be updated bt STM32Programmer in graphical mode or in CLI mode, see STM32CubeProgrammer for details, all the operations on the OTP partition are managed in the tool.
./STM32_Programmer_CLI --help Usage : STM32_Programmer_CLI.exe [command_1] [Arguments_1][[command_2] [Arguments_2]...] Generic commands: -?, -h, --help : Show this help ... OTP structure v2 commands: -otp displ : This command allows the user to display all or parts of the OTP structure [word=<id>] : {Optional} display a specific OTP registers {values and status} Up to 96 OTP words [0 to 95], id value in hex/dec format -otp write : This command allows to fuse or update OTP words Up to 96 OTP words [0 to 95] at the same command line [lock] : {Optional} indicate the operation type, update or permanent lock [word=<id>] : This field contains the OTP word number in hex/dec format [value=<value>] : Value to be written in hex format -otp lock : This command allows to fuse permanently OTP words Up to 96 OTP words [0 to 95] at the same command line [word=<id>] : This field contains the OTP word number in hex/dec format -otp fwrite : This command allows to program a binary file [lock] : {Optional} indicate the operation type, update or permanent lock <bin_path> : Binary file path, 32-bits aligned data [word=<id>] : OTP word number in hex/dec format, start word of program ...
Load U-Boot in DDR with minimal flashlayout.tsv file.
./STM32_Programmer_CLI -c port=usb1 -w FlashLayout_stm32mp157c-dk2.tsv
Read the OTP with -otp displ
./STM32_Programmer_CLI -c port=usb1 -otp displ ------------------------------------------------------------------- STM32CubeProgrammer v2.11.0 ------------------------------------------------------------------- USB speed : High Speed (480MBit/s) Manuf. ID : STMicroelectronics Product ID : USB download gadget@Device ID /0x500, @Revision ID /0x2000, @Name /STM32MP157CAC Rev.B, SN : 004100323338511634383330 DFU protocol: 1.1 Board : -- Device ID : 0x0500 Device name : STM32MP157CAC Rev.B Device type : MPU Revision ID : -- Device CPU : Cortex-A7 UPLOADING OTP STRUCTURE ... Partition : 0xF2 Size : 1024 Bytes Uploading OTP data: [==================================================] 100% OTP Partition read successfully OTP DATA WORDS : Struct_version : | none : 0x00000002 BSEC_OTP_CONFIG : |_ State : Secure Open |_ Hardware Key Set : N |_ Encrypted data : N OTP REGISTERS: --------------------------------------------------------------------------- ID | value | status --------------------------------------------------------------------------- 00 | 0x00000017 | 0x30000000 |_[28] Shadow write sticky lock |_[29] Shadow read sticky lock | | 01 | 0x00008000 | 0x50000000 |_[28] Shadow write sticky lock |_[30] Permanent write lock | | 02 | 0x00000000 | 0x18000000 |_[27] Sticky programming lock |_[28] Shadow write sticky lock | | 03 | 0x00000000 | 0x00000000 04 | 0x00000000 | 0x00000000 05 | 0x00000000 | 0x00000000 06 | 0x00000000 | 0x00000000 07 | 0xDEADBEEF | 0x40000000 |_[30] Permanent write lock | | 08 | 0x00000000 | 0x10000000 |_[28] Shadow write sticky lock | | 09 | 0x00000000 | 0x00000000 10 | 0x00000000 | 0x00000000 11 | 0x00000000 | 0x00000000 12 | 0x7CF5F0F9 | 0x40000000 |_[30] Permanent write lock | | 13 | 0x00410032 | 0x40000000 |_[30] Permanent write lock | | 14 | 0x33385116 | 0x40000000 |_[30] Permanent write lock | | 15 | 0x34383330 | 0x40000000 |_[30] Permanent write lock | | 16 | 0x129675AA | 0x58000000 |_[27] Sticky programming lock |_[28] Shadow write sticky lock |_[30] Permanent write lock | | 17 | 0x2931215E | 0x40000000 |_[30] Permanent write lock | | 18 | 0x7A550140 | 0x30000000 |_[28] Shadow write sticky lock |_[29] Shadow read sticky lock | | 19 | 0x069013EC | 0x40000000 |_[30] Permanent write lock | | 20 | 0x5E360042 | 0x40000000 |_[30] Permanent write lock | | 21 | 0x00000000 | 0x40000000 |_[30] Permanent write lock | | 22 | 0x00000000 | 0x40000000 |_[30] Permanent write lock | | 23 | 0x40133023 | 0x40000000 |_[30] Permanent write lock | | 24 | 0x4E31BBCD | 0x50000000 |_[28] Shadow write sticky lock |_[30] Permanent write lock | | 25 | 0x51E827DD | 0x50000000 |_[28] Shadow write sticky lock |_[30] Permanent write lock | | 26 | 0xAABBCC11 | 0x10000000 |_[28] Shadow write sticky lock | | 27 | 0x00000000 | 0x10000000 |_[28] Shadow write sticky lock | | 28 | 0x00000000 | 0x10000000 |_[28] Shadow write sticky lock | | 29 | 0x00000000 | 0x10000000 |_[28] Shadow write sticky lock | | 30 | 0x00000000 | 0x10000000 |_[28] Shadow write sticky lock | | 31 | 0x00000000 | 0x10000000 |_[28] Shadow write sticky lock | | 32 | 0x00000000 | 0x78000000 |_[27] Sticky programming lock |_[28] Shadow write sticky lock |_[29] Shadow read sticky lock |_[30] Permanent write lock | | 33 | 0x00000000 | 0x78000000 |_[27] Sticky programming lock |_[28] Shadow write sticky lock |_[29] Shadow read sticky lock |_[30] Permanent write lock | | 34 | 0x00000000 | 0x78000000 |_[27] Sticky programming lock |_[28] Shadow write sticky lock |_[29] Shadow read sticky lock |_[30] Permanent write lock | | 35 | 0x00000000 | 0x78000000 |_[27] Sticky programming lock |_[28] Shadow write sticky lock |_[29] Shadow read sticky lock |_[30] Permanent write lock | | 36 | 0x00000000 | 0x78000000 |_[27] Sticky programming lock |_[28] Shadow write sticky lock |_[29] Shadow read sticky lock |_[30] Permanent write lock | | 37 | 0x00000000 | 0x78000000 |_[27] Sticky programming lock |_[28] Shadow write sticky lock |_[29] Shadow read sticky lock |_[30] Permanent write lock | | 38 | 0x00000000 | 0x78000000 |_[27] Sticky programming lock |_[28] Shadow write sticky lock |_[29] Shadow read sticky lock |_[30] Permanent write lock | | 39 | 0x00000000 | 0x78000000 |_[27] Sticky programming lock |_[28] Shadow write sticky lock |_[29] Shadow read sticky lock |_[30] Permanent write lock | | 40 | 0xAA333E40 | 0x58000000 |_[27] Sticky programming lock |_[28] Shadow write sticky lock |_[30] Permanent write lock | | 41 | 0xB5E90DDA | 0x58000000 |_[27] Sticky programming lock |_[28] Shadow write sticky lock |_[30] Permanent write lock | | 42 | 0xF15F4678 | 0x58000000 |_[27] Sticky programming lock |_[28] Shadow write sticky lock |_[30] Permanent write lock | | 43 | 0x8AB41400 | 0x58000000 |_[27] Sticky programming lock |_[28] Shadow write sticky lock |_[30] Permanent write lock | | 44 | 0xB74EFE3A | 0x58000000 |_[27] Sticky programming lock |_[28] Shadow write sticky lock |_[30] Permanent write lock | | 45 | 0xF0A03B1B | 0x58000000 |_[27] Sticky programming lock |_[28] Shadow write sticky lock |_[30] Permanent write lock | | 46 | 0x01E016B3 | 0x58000000 |_[27] Sticky programming lock |_[28] Shadow write sticky lock |_[30] Permanent write lock | | 47 | 0xD06A79DD | 0x58000000 |_[27] Sticky programming lock |_[28] Shadow write sticky lock |_[30] Permanent write lock | | 48 | 0x48B96FBE | 0x58000000 |_[27] Sticky programming lock |_[28] Shadow write sticky lock |_[30] Permanent write lock | | 49 | 0x20FBD352 | 0x58000000 |_[27] Sticky programming lock |_[28] Shadow write sticky lock |_[30] Permanent write lock | | 50 | 0x6732DBF4 | 0x58000000 |_[27] Sticky programming lock |_[28] Shadow write sticky lock |_[30] Permanent write lock | | 51 | 0xEDC395F9 | 0x58000000 |_[27] Sticky programming lock |_[28] Shadow write sticky lock |_[30] Permanent write lock | | 52 | 0xCDF15575 | 0x58000000 |_[27] Sticky programming lock |_[28] Shadow write sticky lock |_[30] Permanent write lock | | 53 | 0x418FD3D0 | 0x58000000 |_[27] Sticky programming lock |_[28] Shadow write sticky lock |_[30] Permanent write lock | | 54 | 0x0BB7D994 | 0x58000000 |_[27] Sticky programming lock |_[28] Shadow write sticky lock |_[30] Permanent write lock | | 55 | 0x8DC929D0 | 0x58000000 |_[27] Sticky programming lock |_[28] Shadow write sticky lock |_[30] Permanent write lock | | 56 | 0x00000000 | 0x30000000 |_[28] Shadow write sticky lock |_[29] Shadow read sticky lock | | 57 | 0x42E18000 | 0x40000000 |_[30] Permanent write lock | | 58 | 0x0000E448 | 0x40000000 |_[30] Permanent write lock | | 59 | 0x12722301 | 0x40000000 |_[30] Permanent write lock | | 60 | 0x00000000 | 0x00000000 61 | 0x00000000 | 0x00000000 62 | 0x00000000 | 0x00000000 63 | 0x00000000 | 0x00000000 64 | 0x00000000 | 0x00000000 65 | 0x00000000 | 0x00000000 66 | 0x00000000 | 0x00000000 67 | 0x00000000 | 0x00000000 68 | 0x00000000 | 0x00000000 69 | 0x00000000 | 0x00000000 70 | 0x00000000 | 0x00000000 71 | 0x00000000 | 0x00000000 72 | 0x00000000 | 0x00000000 73 | 0x00000000 | 0x00000000 74 | 0x00000000 | 0x00000000 75 | 0x00000000 | 0x00000000 76 | 0x00000000 | 0x00000000 77 | 0x00000000 | 0x00000000 78 | 0x00000000 | 0x00000000 79 | 0x00000000 | 0x00000000 80 | 0x00000000 | 0x00000000 81 | 0x00000000 | 0x00000000 82 | 0x00000000 | 0x00000000 83 | 0x00000000 | 0x00000000 84 | 0x00000000 | 0x00000000 85 | 0x00000000 | 0x00000000 86 | 0x00000000 | 0x00000000 87 | 0x00000000 | 0x00000000 88 | 0x00000000 | 0x00000000 89 | 0x00000000 | 0x00000000 90 | 0x00000000 | 0x00000000 91 | 0x00000000 | 0x00000000 92 | 0x00000000 | 0x40000000 |_[30] Permanent write lock | | 93 | 0x00000000 | 0x40000000 |_[30] Permanent write lock | | 94 | 0x00000000 | 0x00000000 95 | 0x00000000 | 0x00000000 ---------------------------------------------------------------------------
The serial number (SN) returned by STM32CubeProgrammer is the Unique device ID (96-bit) present in OTP words 13 to 15 for STM32MP15x lines .
Write and lock the OTP with -otp write
./STM32_Programmer_CLI -c port=usb1 -otp write lock word=9 value=0x12345678 ------------------------------------------------------------------- STM32CubeProgrammer v2.11.0 ------------------------------------------------------------------- USB speed : High Speed (480MBit/s) Manuf. ID : STMicroelectronics Product ID : USB download gadget@Device ID /0x500, @Revision ID /0x2000, @Name /STM32MP157CAC Rev.B, SN : 004100323338511634383330 DFU protocol: 1.1 Board : -- Device ID : 0x0500 Device name : STM32MP157CAC Rev.B Device type : MPU Revision ID : -- Device CPU : Cortex-A7 UPLOADING OTP STRUCTURE ... Partition : 0xF2 Size : 1024 Bytes Uploading OTP data: [==================================================] 100% OTP Partition read successfully OTP Write command: You are trying to write on OTP partition with the following inputs : -------------------------- Word | Value -------------------------- 09 | 0x12345678 Lock | YES -------------------------- Warning: This operation cannot be reverted and may brick your device. Warning: Do you confirm ? [yes/no] y The operation was confirmed... WRITING TO OTP PARTITION ... Partition : 0xF2 Size : 1024 Bytes Downloading OTP data: [==================================================] 100% Uploading OTP data: [==================================================] 100% OTP Partition read successfully Warning: The OTP locking behavior will be introduced after the next system reset. OTP words programming done successfully
2.3. Examples with dfu-util[edit | edit source]
The tools dfu-util can be also used to download/upload directly the OTP structure without STM32CubeProgrammer; the resulting binary file need to be be treated directly by the user and any means; all the OTP accessible by the secure world are available for provisioning as explained in the #Access operation chapter.
The user need to load U-Boot with dfu-util on an open device to support the TA provisioning in OP-TEE and the DFU stack is automatically started with the U-Boot command:
stm32prog usb 0
Search the alternate associated to OTP, phase 0xf2:
dfu-util -l dfu-util 0.9 Copyright 2005-2009 Weston Schmidt, Harald Welte and OpenMoko Inc. Copyright 2010-2016 Tormod Volden and Stefan Schmidt This program is Free Software and has ABSOLUTELY NO WARRANTY Please report bugs to http://sourceforge.net/p/dfu-util/tickets/ Found DFU: [0483:df11] ver=0200, devnum=9, cfg=1, intf=0, path="1-5.4.4", alt=3, name="@PMIC/0xf4/1*8Be", serial="004100323338511634383330" Found DFU: [0483:df11] ver=0200, devnum=9, cfg=1, intf=0, path="1-5.4.4", alt=2, name="@OTP/0xf2/1*776Be", serial="004100323338511634383330" Found DFU: [0483:df11] ver=0200, devnum=9, cfg=1, intf=0, path="1-5.4.4", alt=1, name="@virtual/0xf1/1*512Be", serial="004100323338511634383330" Found DFU: [0483:df11] ver=0200, devnum=9, cfg=1, intf=0, path="1-5.4.4", alt=0, name="@FlashLayout/0x00/1*256Ke", serial="004100323338511634383330"
2.3.1. Read OTP with upload command[edit | edit source]
dfu-util -a 2 -U otp.bin dfu-util 0.9 Copyright 2005-2009 Weston Schmidt, Harald Welte and OpenMoko Inc. Copyright 2010-2016 Tormod Volden and Stefan Schmidt This program is Free Software and has ABSOLUTELY NO WARRANTY Please report bugs to http://sourceforge.net/p/dfu-util/tickets/ Opening DFU capable USB device... ID 0483:df11 Run-time device DFU version 0110 Claiming USB DFU Interface... Setting Alternate Setting #2 ... Determining device status: state = dfuIDLE, status = 0 dfuIDLE, continuing DFU mode device DFU version 0110 Device returned transfer size 4096 Copying data from DFU device to PC Upload [=========================] 100% 776 bytes Upload done.
Then you can display the OTP structure version 2, including the header. For example:
hexdump otp.bin 0000000 0002 0000 0000 0000 0017 0000 0000 3000 0000010 8000 0000 0000 5000 0000 0000 0000 1800 0000020 0000 0000 0000 0000 0000 0000 0000 0000 * 0000040 beef dead 0000 4000 0000 0000 0000 1000 0000050 0000 0000 0000 0000 0000 0000 0000 0000 0000060 0000 0000 0000 0000 f0f9 7cf5 0000 4000 0000070 0032 0041 0000 4000 5116 3338 0000 4000 0000080 3330 3438 0000 4000 75aa 1296 0000 5800 0000090 215e 2931 0000 4000 0140 7a55 0000 3000 00000a0 13ec 0690 0000 4000 0042 5e36 0000 4000 00000b0 0000 0000 0000 4000 0000 0000 0000 4000 00000c0 3023 4013 0000 4000 bbcd 4e31 0000 5000 00000d0 27dd 51e8 0000 5000 cc11 aabb 0000 1000 00000e0 0000 0000 0000 1000 0000 0000 0000 1000 * 0000100 0000 0000 0000 1000 0000 0000 0000 7800 0000110 0000 0000 0000 7800 0000 0000 0000 7800 * 0000140 0000 0000 0000 7800 3e40 aa33 0000 5800 0000150 0dda b5e9 0000 5800 4678 f15f 0000 5800 0000160 1400 8ab4 0000 5800 fe3a b74e 0000 5800 0000170 3b1b f0a0 0000 5800 16b3 01e0 0000 5800 0000180 79dd d06a 0000 5800 6fbe 48b9 0000 5800 0000190 d352 20fb 0000 5800 dbf4 6732 0000 5800 00001a0 95f9 edc3 0000 5800 5575 cdf1 0000 5800 00001b0 d3d0 418f 0000 5800 d994 0bb7 0000 5800 00001c0 29d0 8dc9 0000 5800 0000 0000 0000 3000 00001d0 8000 42e1 0000 4000 e448 0000 0000 4000 00001e0 2301 1272 0000 4000 0000 0000 0000 0000 00001f0 0000 0000 0000 0000 0000 0000 0000 0000 * 00002e0 0000 0000 0000 0000 0000 0000 0000 4000 00002f0 0000 0000 0000 4000 0000 0000 0000 0000 0000300 0000 0000 0000 0000 0000308
In this example the OTP7 value is 0xdeadbeef at 0x40 offset and the status 40000000 indicate a permanent lock.
2.3.2. Write OTP with download command[edit | edit source]
To update OTP you need to prepare a binary file with the operation to performs, see OTP status description #Data structure for details.
You can update the previous file or start with an empty file, and request programmation with bit31 of the status to update.
For example:
hexdump otp.bin 0000000 0002 0000 0000 0000 0000 0000 0000 0000 0000010 0000 0000 0000 0000 0000 0000 0000 0000 0000020 0000 0000 0000 0000 0000 0000 0000 0000 * 0000040 0000 0000 0000 0000 0000 0000 0000 0000 0000050 4567 0123 0000 C000 DEF0 8ABC C000 0000 0000060 0000 0000 0000 0000 0000 0000 0000 0000 * 0000300 0000 0000 0000 0000 0000308
Request write and lock in OTP9 and OTP10 with
- 0x50: OTP[9] value = 0x01234567
- 0x54: OTP[9] status = 0xC0000000
- 0x58: OTP[10] value = 0xABCDEF0
- 0x5C: OTP[10] status = 0xC0000000
See OTP status for other operations examples.
Download this file with dfu-util
dfu-util -a 2 -D otp.bin dfu-util -a 2 -D otp.bin dfu-util 0.9 Copyright 2005-2009 Weston Schmidt, Harald Welte and OpenMoko Inc. Copyright 2010-2016 Tormod Volden and Stefan Schmidt This program is Free Software and has ABSOLUTELY NO WARRANTY Please report bugs to http://sourceforge.net/p/dfu-util/tickets/ dfu-util: Invalid DFU suffix signature dfu-util: A valid DFU suffix will be required in a future dfu-util release!!! Opening DFU capable USB device... ID 0483:df11 Run-time device DFU version 0110 Claiming USB DFU Interface... Setting Alternate Setting #2 ... Determining device status: state = dfuIDLE, status = 0 dfuIDLE, continuing DFU mode device DFU version 0110 Device returned transfer size 4096 Copying data from PC to DFU device Download [=========================] 100% 776 bytes Download done. state(7) = dfuMANIFEST, status(0) = No error condition is present state(2) = dfuIDLE, status(0) = No error condition is present Done!
3. Reference list[edit | edit source]