AM263x MCU+ SDK  09.01.00
Booting Tools

Note
To see the exact sequence of steps in which applications and secondary bootloader (SBL) are converted from compiler generated .out files to boot images, see the makefile makefile_ccs_bootimage_gen that is included in every example and secondary bootloader (SBL) CCS project.
If you are using makefile based build, then see the file named makefile in the example folder.

Introduction

This section describes the various tools that are used to create boot images for all the SDK applications

Important files and folders

Folder/Files Description
${SDK_INSTALL_PATH}/tools/boot/
multicoreImageGen/ Tool to combine multiple RPRC into a single binary
out2rprc/ Tool to convert compiler generated ELF .out for a CPU to a compact and loadable binary representation, called RPRC.
sbl_prebuilt/ Pre-built secondary bootloader (SBL) images and flash configuration files for different supported EVMs, see also Flashing Tools
signing/

Security signing scripts need to create boot images that can be booted by ROM bootloader (RBL)

uart_bootloader.py Python script used to send the SBL and appimage binaries over UART using XMODEM protocol in UART boot mode
uart_uniflash.py Python script used to flash SBL and applications to EVM flash using UART. See Flashing Tools for more details.

Out2RPRC

  • This tool converts the application executable (.out) into custom TI RPRC (.rprc) image - an image loadable by the secondary bootloader (SBL).
  • This tool strips out the initialized sections from the executable file (*.out) and places them in a compact format that the SBL can understand.
  • The output RPRC file is typically much smaller than the original executable (*.out) file.
  • The RPRC files are intermediate files in a format that is consumed by MulticoreImageGen tool that generates the final binary that is flashed (*.appimage)
  • The RPRC file format contains header to various sections in the executable like section run address, size and a overall header which mentions the number of sections and the start offset to the first section.
  • The RPRC magic word is 0x43525052 - which is ASCII equivalent for RPRC
  • Shown below is the file header and section format for RPRC files.

RPRC File Format
  • Given below are the structs used in the bootloader library to parse an RPRC image
typedef struct Bootloader_RprcFileHeader_s
{
uint32_t magic;
uint32_t entry;
uint32_t rsvdAddr;
uint32_t sectionCount;
uint32_t version;
} Bootloader_RprcFileHeader;
typedef struct Bootloader_RprcSectionHeader_s
{
uint32_t addr;
uint32_t rsvdAddr;
uint32_t size;
uint32_t rsvdCrc;
uint32_t rsvd;
} Bootloader_RprcSectionHeader;
  • This tool is provided as a minified JS script. To convert the application executable into RPRC image file, it can be used as
    cd ${SDK_INSTALL_PATH}/tools/boot/out2rprc
    ${NODE} elf2rprc.js {input application executable file (.out)}
  • RPRC mandates that the sections in the application image should be 8-byte aligned. Make sure that this is taken care in the linker.cmd file. Sample:
    GROUP {
    .text.hwi: palign(8)
    .text.cache: palign(8)
    .text.mpu: palign(8)
    .text.boot: palign(8)
    .text:abort: palign(8) /* this helps in loading symbols when using XIP mode */
    } > OCRAM

Multi-core Image Gen

  • This tool converts the RPRC files created for each CPU into a single combined multicore application image that can be booted by the secondary bootloader (SBL)
  • Shown below is the file format for multicore image files.

Multi-core Image File Format
  • Given below are the structs used in the bootloader library for parsing multicore images:
typedef struct Bootloader_MetaHeaderStart_s
{
uint32_t magicStr;
uint32_t numFiles;
uint32_t devId;
uint32_t rsvd;
} Bootloader_MetaHeaderStart;
typedef struct Bootloader_MetaHeaderCore_s
{
uint32_t coreId;
uint32_t imageOffset;
} Bootloader_MetaHeaderCore;
typedef struct Bootloader_MetaHeaderEnd_s
{
uint32_t rsvd;
uint32_t magicStringEnd;
} Bootloader_MetaHeaderEnd;
  • The number of core meta headers present is equal to the number of cores included.
  • The meta header magic word is 0x5254534D - which is ASCII equivalent for MSTR
  • In Windows or Linux, use the following command to convert RPRC images into a multicore .appimage file
    cd ${SDK_INSTALL_PATH}/tools/boot/multicoreImageGen
    ${NODE} multicoreImageGen.js --devID {DEV_ID} --out {Output image file (.appimage)} {core 1 rprc file}@{core 1 id} [ {core n rprc file}@{core n id} ... ]
  • In case of AM263X, DEV_ID is 55.
  • The various core ID to be used are as below.
CORE CORE ID
r5fss0-0 0
r5fss0-1 1
r5fss1-0 2
r5fss1-1 3

Signing Scripts

  • To run these scripts, one needs openssl installed as mentioned here, OpenSSL
  • Signing scripts are a collection of scripts needed to sign ROM images (image booted by ROM - mostly the SBL) and application images (image booted by the SBL)

Signing SBL

  • The RBL requires the boot image (mostly SBL), to be signed always, even if we are not using secure boot.

For SBL images, the script /tools/boot/signing/mcu_rom_image_gen.py.

For HS-FS devices:

cd ${SDK_INSTALL_PATH}/tools/boot/signing
$(PYTHON) mcu_rom_image_gen.py --image-bin <path-to-the-binary> --core R5 --swrv 1 --loadaddr $(SBL_RUN_ADDRESS) --sign-key <signing-key-configured-in-devconfig> --out-image <output-image-name> --debug $(DEBUG_OPTION)

For HS-SE devices:

cd ${SDK_INSTALL_PATH}/tools/boot/signing
$(PYTHON) mcu_rom_image_gen.py --sbl-enc --enc-key <encryption-key-configured-in-devconfig> --image-bin <path-to-the-binary> --core R5 --swrv 1 --loadaddr $(SBL_RUN_ADDRESS) --sign-key <signing-key-configured-in-devconfig> --kd-salt <path-to-key-derivation-salt> --out-image <output-image-name> --debug $(DEBUG_OPTION)

Here, we deep dive into the extension supported in SBL and HSM Runtime (TIFS-MCU) certificate by ROM. To get access to the HSM Runtime code and ability to build it for HS-SE device, please contact your TI represntative to get access to the TIFS-MCU package from MySecureSW.

Boot Information OID (1.3.6.1.4.1.294.1.1)

bootInfo ::= SEQUENCE {
cert_type: INTEGER, -- identifies the certificate type
boot_core: INTEGER, -- identifies the boot core
core_opts: INTEGER, -- Core Options
load_addr: OCTET STRING, -- Global address image destination
image_size: INTEGER, -- Image size in bytes
}

The Boot Information Object identifier provides information about the image which is being loaded. This information is mandatory and needs to be present else the image boot will fail.

Elements of the extension:

Certificate Type: The certificate type defines the type of the image which is being loaded by the Boot-ROM.

These are the supported values:

  • 0x1 R5 SBL Boot Image
  • 0x2 HSM Runtime (TIFS-MCU) Image

Boot core: The boot core identifies the core on which the image will be executing.

These are the supported values:

  • 0x0 HSM Core
  • 0x10 R5 Core

Core Options: The core options are documented in the table below.

These are the supported values:

  • 0x0 Lock Step Mode
  • Non-Zero Dual Core Mode
Note
Currently, configuring this option is not supported with Signing scripts. This feature will be added in future releases.

Core options are applicable only for the R5 SBL Images.

Load Address: The load address will be address in the system where the image will be loaded. This is applicable for both SBL and TIFS-MCU (HSMRt) images.

Image Size: This is the size in bytes of the R5 SBL or HSM Runtime Image to which the certificate has been attached.

Image Integrity OID (1.3.6.1.4.1.294.1.2)

imageIntegrity ::= SEQUENCE {
sha_type: OID, -- Identifies the SHA type
hash: OCTET STRING -- The SHA of the boot image
}

If the X.509 certificate provides the image integrity boot extension, the Boot-ROM will perform the SHA-512 on the entire image and will verify the computed hash with the hash provided in the boot extension. In the case of a mismatch the boot will fail.

Elements of the extension:

SHA Type: The Boot-ROM only supports SHA-512.

The following values are supported:

2.16.840.1.101.3.4.2.3 SHA-512 Object Identifier

Please refer to the Section 2.4 of the RFC-5754 for the SHA-512 Object Identifier.

Hash: This is SHA-512 hash which is calculated over the image (R5 SBL/HSM Runtime)

R5 SBL Image:

  • HS-SE Device: Image Integrity is mandatory
  • HS-FS Device: Image Integrity is optional

HSM Runtime Image:

  • HS-SE Device: Image Integrity is mandatory
  • HS-FS Device: Image Integrity is mandatory

Software Revision OID (1.3.6.1.4.1.294.1.3)

softwareRevision ::= SEQUENCE {
revision: INTEGER -- Software revision
}

The information in the software revision is used to indicate the version of the image which is being loaded.

Elements of the extension:

revision: This is the version number. This will be matched to the EFUSE programmed version to indicate if the image loading should be done or not. This is applicable only for SE devices.

EFUSE Revision Certificate Revision Description
0 0 Ignore the revision checking. Images will always be loaded
0 >0 Device does not mandate revision checking. Images will be loaded
>0 0 EFUSE Version > Certificate Version. Image will never be loaded.
>0 >0 Image will be loaded only if the Certificate revision >= EFUSE revision

The following fields in efuse ROM help support the above feature:

  • SWRV_SBL- This is used to perform the revision checking while loading the R5 SBL
  • SWRV_HSM- This is used to perform the revision checking while loading the HSM Runtime

For more information, about how to fuse in these values, please refer to OTP Keywriter Documentation available on MySecureSW.

Image Encryption OID (1.3.6.1.4.1.294.1.4)

imageEncryption ::= SEQUENCE {
iv: OCTET STRING -- The initialization vector
rs: OCTET STRING -- Random string
iter: INTEGER -- Iteration count
salt: OCTET STRING -- encryption salt value
}

The Boot-ROM only supports AES-CBC mode with 256bit keys. The information in the image encryption object identifier is used to decrypt the image.

Elements of the extension:

IV: The initialization vector is used during the AES-CBC decryption procedure. The initialization vector needs to be 16bytes.

rs: This is the random string which is 32bytes long and is appended by the script at the end of the image. The Boot-ROM will decrypt the image and will perform a random string comparison to determine if the decryption was successful.

iter: Iteration Count which is used to determine if the HKDF needs to be performed and key derivation needs to be done. If the iteration count is 0 then the key from the e-fuse is used as is for the decryption. If the iteration count is non-zero then the Boot-ROM will perform the HKDF key derivation using the salt with exactly one iteration (even if iteration count is > 1). The derived key is then used for the decryption operation.

salt: The salt is used only if the iteration count is non-zero and key derivation is being done. The salt is fed to the HKDF module to derive the key. The salt fields should be 32bytes.

For recommendation on the salt, please refer to Enabling Secure Boot.

Note
It is recommended to update key derivation salt everytime there is a firmware upgrade. SBL, HSMRt and application images need to be prepared again, once the salt is changed.
  • HS-SE device: Image Encryption is optional
  • HS-FS device: Image Encryption is optional

Derivation OID (1.3.6.1.4.1.294.1.5)

derivationKey ::= SEQUENCE {
salt: OCTET STRING -- encryption salt value
}

The Boot-ROM will leave a derived key in the assets interface for the TIFS-MCU. The key is derived using HKDF from the parameters specified here. This is useful for decrypting application images by sending request to TIFS-MCU. For recommendation on the salt, please refer to Enabling Secure Boot.

Elements of the extension:

salt: The salt is limited to be 32bytes and is used for key derivation

This OID is ignored as part of HSM Runtime certificates. This OID is ignored as part of SBL certificates if the device type is HS-FS. Key derivation is always done using the active user symmetric key.

Debug OID (1.3.6.1.4.1.294.1.8)

Debug::= SEQUENCE {
uid OCTET STRING -- Device unique ID
debugType INTEGER -- Debug type
coreDbgEn INTEGER -- Enable core debug mask
secCoreDbgEn INTEGER -- Enable secure core debug mask
}

The debug object identifier if specified allows the debug ports to be enabled for a specific device.

Elements of the extension:

UID: This is the unique identifier associated with the device. Device specific unique identifiers can be retrieved using the SOC_ID Parser.

The UID field of all 0s is considered to be a wildcard. This is what is supported by default in the script.

Debug Type: This is the privilege level of debug.

The privilege levels supported by ROM are as follows:

Privilege Level Value Description
DBG_PERM_DISABLE 0 Disable debug ports for all cores.
DBG_SOC_DEFAULT 1 Maintain debug ports for all cores to device type defaults.
DBG_PUBLIC_ENABLE 2 Enable debug ports on R5FSS0-0 core.

coreDbgEn and secCoreDbgEn: These fields are not used and will be ignored.

Note
The Debug OID is not applicable for HSM Runtime (TIFS-MCU) image.

In the SBL Signing scripts, DEBUG_OPTION is used to exercise the debug level if the SBL certificate has debug extension. The SBL certificate as mentioned before, is processed by ROM. This is different from the debug certificate supported by TIFS-MCU.

This feature is leveraged via compile time flags in MCU+ SDK for SBL images.

By default, in SDK, the debug extension is not engaged for SBL images. This is decided by the flag DEBUG_TIFS defined in devconfig.mak. By default, DEBUG_TIFS is set to yes.This means that the debug extension will not be added to SBL and if the debug needs to be exercised via the certificate to TIFS-MCU via the debug authentication service, it can be safely done. This is done to ensure that the registers are written once only to exercise the debug during a POR cycle. If the user wants to open up debug on an HS-SE device, they can set DEBUG_TIFS=no. This is when the debug extension is added to the certificate for SBL images.

Note
ROM does not allow FULL_ENABLE privilege level via SBL certificate. To open up debug on HSM core, please refer to Debug Authentication services provided via TIFS-MCU. In this case, please use the default value of DEBUG_TIFS i.e. yes when compiling SBL examples.

The default debug privilege used in SDK is DBG_SOC_DEFAULT.

To enable debug on public cores on HS-SE device, one can use the following command to compile SBL examples.

make -s -C examples/drivers/boot/sbl_qspi/am263x-cc/r5fss0-0_nortos/ti-arm-clang all DEVICE=am263x DEVICE_TYPE=HS DEBUG_TIFS=no DEBUG_OPTION=DBG_PUBLIC_ENABLE
  • Here,
    • SBL_RUN_ADDRESS is 0x70002000
    • In the case of HS-FS devices, the key value is disregarded. A degenerate RSA public key is used to sign the certificate. The image integrity is checked in ROM, nevertheless.
    • In the case of HS-SE device, more details can be found at Enabling Secure Boot
    • Refer to TRM Chapter on Initialization, section 5.6.4.1.1 to get help on RSA key pair generation.

These scripts are invoked in makefiles, and the image generation happens automatically along with the example build. So mostly these scripts need not be manually run. If the user build-system is different from TI's makefile system, it needs to be ensured that the same is followed as part of the post build steps. The devconfig has ENC_SBL_ENABLED=yes and that is why for HS-SE devices, the SBL image is encrypted by default.

Application Signing

For Application images, the script /tools/boot/signing/mcu_appimage_x509_cert_gen.py.

For HS-SE devices:

cd ${SDK_INSTALL_PATH}/tools/boot/signing
$(PYTHON) mcu_appimage_x509_cert_gen.py --bin <path-to-the-binary> --key <signing-key-configured-in-devconfig> --enc y --enckey <encryption-key-configured-in-devconfig> --kd-salt <path-to-key-derivation-salt> --output <output-image-name>

Signing of application images is not required for HS-FS device types.

Here, we deep dive into the extension supported with certificate for Application images as processed by TIFS-MCU. To get access to the HSM Runtime code and ability to build it for HS-SE device, please contact your TI represntative to get access to the TIFS-MCU package from MySecureSW.

Boot Information OID (1.3.6.1.4.1.294.1.1)

bootInfo ::= SEQUENCE {
cert_type: INTEGER, -- identifies the certificate type
boot_core: INTEGER, -- Reserved
core_opts: INTEGER, -- Reserved
load_addr: OCTET STRING, -- Reserved
image_size: INTEGER, -- Image size in bytes
}

The Boot Information Object identifier provides information about the image which is being loaded.

Elements of the extension:

Certificate Type: The certificate type defines the type of the image which is being loaded by the Boot-ROM.

These are the supported values:

  • 0xA5A50000 Application Image

Boot core: This field is reserved and should be assigned with 0.

Core Options: This field is reserved and should be assigned with 0.

Load Address: This field is reserved and should be assigned with 0.

Image Size: This is the size in bytes of the R5 SBL or HSM Runtime Image to which the certificate has been attached.

Image Integrity OID (1.3.6.1.4.1.294.1.2)

imageIntegrity ::= SEQUENCE {
sha_type: OID, -- Identifies the SHA type
hash: OCTET STRING -- The SHA of the boot image
}

If the X.509 certificate provides the image integrity boot extension, the TIFS-MCU will perform the hash calculation on the entire image and will verify the computed hash with the hash provided in the boot extension. In the case of a mismatch the boot will fail.

Elements of the extension:

SHA Type:

The following values are supported:

  • 2.16.840.1.101.3.4.2.1 SHA-256 Object Identifier
  • 2.16.840.1.101.3.4.2.2 SHA-384 Object Identifier
  • 2.16.840.1.101.3.4.2.3 SHA-512 Object Identifier

Amongst these, SDK has been validated against SHA-512 OID.

Hash: This is SHA-512 hash which is calculated over the application image

Software Revision OID (1.3.6.1.4.1.294.1.3)

softwareRevision ::= SEQUENCE {
revision: INTEGER -- Software revision
}

The information in the software revision is used to indicate the version of the image which is being loaded.

Elements of the extension:

revision: This is the version number. This will be matched to the EFUSE programmed version to indicate if the image loading should be done or not.

The following fields in efuse ROM help support the above feature:

  • SWRV_APP- This is used to perform the revision checking while loading the application

For more information, about how to fuse in these values, please refer to OTP Keywriter Documentation available on MySecureSW.

Image Encryption OID (1.3.6.1.4.1.294.1.4)

imageEncryption ::= SEQUENCE {
iv: OCTET STRING -- The initialization vector
rs: OCTET STRING -- Random string
iter: INTEGER -- Reserved
salt: OCTET STRING -- Reserved
}

TIFS-MCU only supports AES-CBC mode with 256bit keys. The information in the image encryption object identifier is used to decrypt the image.

Elements of the extension:

IV: The initialization vector is used during the AES-CBC decryption procedure. The initialization vector needs to be 16bytes.

rs: This is the random string which is 32bytes long and is appended by the script at the end of the image. TIFS-MCU will decrypt the image and will perform a random string comparison to determine if the decryption was successful.

iter: This field is unused and reserved.

salt: This field is unused and reserved.

UART Bootloader Python Script

  • This script is used in UART boot mode for sending the SBL and appimage binaries to the EVM via UART using XMODEM protocol
  • Make sure that python3 and its dependent modules are installed in the host machine as mentioned in Python3
  • Booting via UART is slow, but is useful if application loading via CCS or OSPI boot is not an option
  • Make sure the UART port used for terminal is identified as mentioned in Setup UART Terminal
  • Make sure you have the EVM power cable and UART cable connected as shown in Cable Connections
  • To boot applications using this script, POWER OFF the EVM
  • Switch to UART BOOT MODE.
  • POWER ON the EVM
  • To confirm that the board is in UART boot mode, open the UART terminal and confirm that you see the character 'C' getting printed on the console every 2-3 seconds.
  • Now close the terminal. This is important as the script won't be able to function properly if the UART terminal is open.
  • Open a command prompt and run the below command to send the SBL and application binary to the EVM
    cd ${SDK_INSTALL_PATH}/tools/boot
    python uart_bootloader.py -p COM<x> --bootloader=sbl_prebuilt/{board}/sbl_uart.release.tiimage --file=< path to multicore appimage of application binary >
  • When you execute this, the script first sends the uart bootloader, and then the multicore appimage
  • After the multicore appimage is successfully parsed, the uart bootloader sends an acknowledgment to the script and waits for 5 seconds before running the application binary
  • Upon receiving the ack, the script will exit successfully
  • Connect to the UART terminal within 5 seconds to see logs from the application
  • Below are the logs of the script after all the files have been sent
    Sending the UART bootloader sbl_prebuilt/{board}/sbl_uart.release.tiimage ...
    Sent bootloader sbl_prebuilt/{board}/sbl_uart.release.tiimage of size 243975 bytes in 23.94s.
    Sending the application ../../examples/drivers/udma/udma_memcpy_polling/{board}/r5fss0-0_nortos/ti-arm-clang/udma_memcpy_polling.release.appimage ...
    Sent application ../../examples/drivers/udma/udma_memcpy_polling/{board}/r5fss0-0_nortos/ti-arm-clang/udma_memcpy_polling.release.appimage of size 99580 bytes in 11.74s.
    [STATUS] Application load SUCCESS !!!
    Connect to UART in 2 seconds to see logs from UART !!!

SoC ID parser Python Script

  • Boot ROM reports SoC ID on UART console of the device when UART boot mode is selected. It reports on both GP and HS devices and it provides insights into device configuration which would be helpful for debugs.
  • uart_boot_socid.py is a python3 based parser to convert the hexadecimal numbers reported by ROM to human readable text, below are the steps involved to use this parser. This will be helpful in debugging the device boot issue. This will also help to see important information about device like device type, prime/non-prime, key count, key revision, MPK hash etc.
  • Make sure python3 is installed as mentioned in Python3
  • Steps to use the parser:
    • Copy the soc id reported in UART console
    • pass the copied id to the script either as a plain string or saving it into a file
    • execute the script
      $python uart_boot_socid.py -d am64x --string=<copied soc id>
      or
      $python uart_boot_socid.py -d am64x --file=soc_id.txt
  • Example Output:
    -----------------------
    SoC ID Header Info:
    -----------------------
    NumBlocks : 2
    -----------------------
    SoC ID Public ROM Info:
    -----------------------
    SubBlockId : 1
    SubBlockSize : 26
    DeviceName : am64x
    DeviceType : HSSE
    DMSC ROM Version : [0, 2, 0, 0]
    R5 ROM Version : [0, 2, 0, 0]
    -----------------------
    SoC ID Secure ROM Info:
    -----------------------
    Sec SubBlockId : 2
    Sec SubBlockSize : 166
    Sec Prime : 0
    Sec Key Revision : 1
    Sec Key Count : 1
    Sec TI MPK Hash : b018658ad99dc903c8c9bfb27b12751099920a042ad1dfea7b7ba57369f15546de285edde6a7b39a8bdc40a27b237f8fb1e57f245e80b929c1e28b024aa2ecc6
    Sec Cust MPK Hash : 1f6002b07cd9b0b7c47d9ca8d1aae57b8e8784a12f636b2b760d7d98a18f189760dfd0f23e2b0cb10ec7edc7c6edac3d9bdfefe0eddc3fff7fe9ad875195527d
    Sec Unique ID : 01f22176afca3a82692ce53b2738b8c982f7538602871e0bdb7dc2f7668d04b2

CAN Bootloader Python Script

  • This script is used in QSPI boot mode for sending the appimage binaries to the EVM via CAN, after flashing the SBL CAN. Refer Basic steps to flash files for flashing.
  • Make sure that python3 and its dependent modules are installed in the host machine as mentioned in Python3
  • Make sure the UART port used for terminal is identified as mentioned in Setup UART Terminal
  • Make sure you have the EVM power cable and CAN cable connected as shown in SBL CAN
  • To boot applications using this script, POWER OFF the EVM
  • Switch to QSPI BOOT MODE
  • POWER ON the EVM
  • Open a command prompt and run the below command to send the application binary to the EVM
    cd ${SDK_INSTALL_PATH}/tools/boot
    python can_bootloader.py --file=< path to multicore appimage of application binary >
  • When you execute this, the script first sends the multicore appimage to the EVM
  • After the multicore appimage is successfully parsed, the CAN bootloader sends an acknowledgment to the script
  • Upon receiving the ack, the script will exit successfully
  • Connect to the UART terminal to see logs from the application
  • Below are the logs of the script after all the files have been sent
    Sending the application ../../examples/drivers/udma/udma_memcpy_polling/{board}/r5fss0-0_nortos/ti-arm-clang/udma_memcpy_polling.release.appimage ...
    Sent application ../../examples/drivers/udma/udma_memcpy_polling/{board}/r5fss0-0_nortos/ti-arm-clang/udma_memcpy_polling.release.appimage of size 99580 bytes in 11.74s.
    [STATUS] BOOTLOADER_CAN_STATUS_LOAD_SUCCESS!!!
    Connect to UART to see logs from UART !!!