AM243x MCU+ SDK  10.00.00
Understanding the bootflow and bootloaders

Introduction

This section is aimed at explaining what a bootloader is, why is it needed and details regarding the bootloader and bootflow used in the MCU+SDK.

What Is Bootloader?

Generally speaking, bootloader is a piece of software / firmware that runs as soon as you power on an SoC. A bootloader's main duty is to start the subsequent pieces of software, such an OS, a baremetal application or in some cases another bootloader. When it comes to embedded, the bootloader is usually closely tied with the underlying SoC architecture. The bootloader is usually stored in a protected, non-volatile on-chip memory. Typically the bootloader performs various hardware checks, initializes the processor and configures the SoC registers etc. Since the primary aim of the bootloader is to load the next piece of software, it needs to communicate to the external world to receive this firmware/application image. This can be over a number of protocols - USB, UART, SPI, I2C, External Flash, Internal Flash, SD Card, Ethernet, CAN etc. Bootloader is also a key component in embedded security. Hardware Root-of-Trust is usually passed onto the bootloader and is passed on down the line.

Note
In devices supported by MCU+SDK, the first stage bootloader is burned into read-only memory of the device and is considered as device firmware / ROM. Mostly in MCU+SDK when we say "bootloader" we are referring to the secondary bootloader, or the SBL

Multi-Stage Bootloader

As mentioned earlier, sometimes the bootloader would be loading another bootloader which can load another one and so on. This is usually the case in advanced SoCs, and there are various reasons for this. The first bootloader is usually kept on secure, read-only memory for security reasons and to have a known state always before application software starts. It makes sense then to keep this bootloader simple and let it do only the bare minimum configuration required. This secondary bootloader can be complex and configurable to suit the needs of the application. This can also be updated easily compared to the first stage bootloader. In fact for the devices in MCU+SDK, we have a two-stage bootloading - the first stage bootloader is called ROM Bootloader (RBL) and the second stage bootloader is called Secondary Bootloader (SBL).

Multi-Core Bootloading

Multi-core bootloading is almost always a follow up when there is a multi-stage bootloading. In this case the first bootloader technically might not be even aware of the other cores, it will just boot the next stage bootloader and this second stage bootloader will take care of the complex bootloading on the different cores.

Loading a multi-core application is slightly more complicated than loading a single core application. There would be concerns regarding image preparation, shared memory access, and so on. Mostly there would be a particular format in which the individual core images are created, and then they may/may not be concatenated into a single image for SBL to load. Whatever format the application image is in, the SBL should be aware of it so that it can parse and load the image correctly.

Bootloading in MCU+SDK

In the MCU+SDK, the bootflow takes place mainly in two steps after you power ON the device

  • ROM boot, in which the ROM bootloader boots a secondary bootloader or an SBL
  • SBL boot in which the secondary bootloader boots the application

ROM Boot

The RBL or ROM Bootloader is stored in read-only memory and is almost considered as part of the SoC. The details regarding the RBL and ROM Boot is out of scope for this user guide. Please refer to the Technical Reference Manual of the device for more details. But basically the ROM expects an x509 signed binary image of the secondary bootloader to be provided for boot.

  • As soon as the board is powered ON, the ROM bootloader or RBL starts running. The RBL is the primary bootloader.
  • Depending on which boot mode is selected, the RBL will load the secondary bootloader or SBL from a boot media (OSPI flash, SD card or via UART).
  • Rest of the booting is done by the SBL.
  • The RBL expects the image it boots (SBL in our case) to always be signed as mentioned above. Refer Booting Tools for more information on signing scripts.

The x509 template for ROM looks something like this:

[ req ]
distinguished_name = req_distinguished_name
x509_extensions = v3_ca
prompt = no
dirstring_type = nobmp
[ req_distinguished_name ]
C = US
ST = SC
L = New York
O = Texas Instruments., Inc.
OU = DSP
CN = Albert
emailAddress = Albert@gt.ti.com
[ v3_ca ]
basicConstraints = CA:true
1.3.6.1.4.1.294.1.3 = ASN1:SEQUENCE:swrv
1.3.6.1.4.1.294.1.9 = ASN1:SEQUENCE:ext_boot_info
[ swrv ]
swrv = INTEGER:1
[ ext_boot_info ]
extImgSize = INTEGER:0
numComp = INTEGER:3
sbl = SEQUENCE:sbl
fw = SEQUENCE:sysfw
bd2 = SEQUENCE:boardcfg
[ sbl ]
compType = INTEGER:1
bootCore = INTEGER:16
compOpts = INTEGER:0
destAddr = FORMAT:HEX,OCT:0000
compSize = INTEGER:0
shaType = OID:SHAOID
shaValue = FORMAT:HEX,OCT:0000
[ sysfw ]
compType = INTEGER:2
bootCore = INTEGER:0
compOpts = INTEGER:0
destAddr = FORMAT:HEX,OCT:0000
compSize = INTEGER:0000
shaType = OID:SHAOID
shaValue = FORMAT:HEX,OCT:0000
{SYSFW_INNER_CERT_SEQ}
[ boardcfg ]
compType = INTEGER:18
bootCore = INTEGER:0
compOpts = INTEGER:0
destAddr = FORMAT:HEX,OCT:0000
compSize = INTEGER:0000
shaType = OID:SHAOID
shaValue = FORMAT:HEX,OCT:0000

Depending on the device type, these are the validation requirements for ROM:

Validation for Device Types

System Controller Firmware (SYSFW)

  • In case of AM243X, there is one more component called the System Controller Firmware (SYSFW) which is important in the booting process and SoC operation. As the name suggests it is controller firmware which runs in the Cortex M3 core and acts as a centralized server for the SoC which grants services in
    • Resource Management (RM)
    • Power Management (PM)
    • Security
  • Since the services provided by SYSFW are fundamental, it needs to be loaded before the secondary bootloader can do pretty much anything.
  • In MCU+SDK we follow what's called the combined bootflow (for more details on combined bootflow refer Bootflow Migration Guide), where RBL boots the SBL and the SYSFW. For this we have to prepare the boot image for RBL specially. It will be a concatenation of the SBL binary, SYSFW binary and Board Configuration binary all signed with a single x509 certificate. This process is taken care in SBL makefiles, so in most cases the user need not worry about it. For details regarding the signing script used for this please refer Booting Tools
  • One of the first things SBL is going to do is wait for a boot notification from SYSFW.
  • There are different types of SYSFW images included in the SDK. You can find below binary files under source/drivers/sciclient/soc/${soc}:
    • sysfw-hs-fs-enc.bin: This is the encrypted and signed SYSFW binary to be packaged with SBL when preparing the SBL boot image for HS-FS device.
    • sysfw-hs-fs-enc-cert.bin: This is the x509 certificate binary generated while signing the above (sysfw-hs-fs-enc.bin) image. This is also to be packaged with SBL when preparing the SBL boot image for HS-FS device.
    • sysfw-hs-enc.bin: This is the encrypted and signed SYSFW binary to be packaged with SBL when preparing the SBL boot image for HS-SE device.
    • sysfw-hs-enc-cert.bin: This is the x509 certificate binary generated while signing the above (sysfw-hs-enc.bin) image. This is also to be packaged with SBL when preparing the SBL boot image for HS-SE device.
  • For more information regarding the SYSFW please refer to the TISCI Documentation : https://software-dl.ti.com/tisci/esd/latest/index.html
  • For ROM to accept any image to boot, there are some restrictions in the image preparation

Preparing the SBL for boot

The SBL is like any other application, created using the same compiler and linker toolchain. It is an example implementation rather than a deliverable. It is customizable by users, but must adhere to the requirements by RBL which is a constant as mentioned above. However the steps to convert the application .out into a bootable image are different for SBL as listed below:

  • Other special factors for SBL application are listed below
    • After entering main(), make sure to call Bootloader_socWaitForFWBoot to wait for the boot notification from the SYSFW
    • The linker command file for SBL has to place vectors at address 0x70000000 and this is the entry point for the SBL.
    • Nothing should be placed in ATCM or BTCM
    • Only the region 0x70000000 to 0x70080000 should be used by SBL code, data, stack etc
  • After building, the SBL application .out file is first converted to a binary format .bin using the TI ARM CLANG objcopy tool.
    • This copies the loadable sections from the .out into a binary image stripping all symbol and section information.
    • If there are two loadable sections in the image which are not contiguous then objcopy fills the gaps with 0x00.
    • It is highly recommended to keep all loadable sections together within a SBL application.
  • This .bin file is then signed using the Signing Scripts to create the final .tiimage bootable image.
    • The .tiimage file extension is kept to separate the SBL boot image from a normal application image
    • The rom_degenerateKey.pem is used for this.
    • This is a ROM bootloader requirement and is needed even on a non-secure device.
    • The signing tools take the .bin file
  • Depending on the device type for which we build the SBL, there will be certain prefixes to the .tiimage extension like so:
    • GP device:
      • sbl_xxx.release.tiimage [No prefix before .tiimage, plain image]
    • HS-FS device:
      • sbl_xxx.release.hs_fs.tiimage [hs_fs prefix before .tiimage]
    • HS-SE device:
      • sbl_xxx.release.hs.tiimage [hs prefix before .tiimage]
  • Note that if we just mentioned hs it is meant for HS-SE device and hs_fs or hs-fs is meant for HS-FS device.
  • The .tiimage file can then be flashed or copied to a boot image using the Flashing Tools
  • In case of AM243x/AM64x we use combined boot flow, so the tiimage will have SYSFW and BoardCfg as additional components as ROM is going to boot these as well. As you can see from the image the signing is done for a concatenated binary of all three. For more details on combined boot flow please refer to Bootflow Migration Guide

TIIMAGE

SBL Boot

  • An SBL typically does a bunch of SOC specific initializations and proceeds to the application loading.
  • Depending on the type of SBL loaded, SBL looks for the multicore appimage (refer Booting Tools for more on multicore appimage) of the application binary at a specified location in a boot media.
  • If the appimage is found, the multicore appimage is parsed into multiple RPRCs. These are optimized binaries which are then loaded into individual CPUs.
  • Each RPRC image will have information regarding the core on which it is to be loaded, entry points and multiple sections of that application binary
  • The SBL uses this information to initialize each core which has a valid RPRC. It then loads the RPRC according to the sections specified, sets the entry points and releases the core from reset. Now the core will start running.

SBL BOOT

  • To understand the steps to use XIP, see Enabling XIP or eXecute In Place
  • Now, as mentioned above, to boot an application with SBL it has to be specially prepared after it's compiled.

Preparing the application for boot

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.

Shown below are the different steps that are done to convert the compiler+linker generated application .out into a format suitable for flashing and booting

  • For each CPU, the compiler+linker toolchain is used to create the application .out "ELF" file which can be loaded and run via CCS
  • The below "post build" steps are then used to convert the application .out into a "flash" friendly format
    • For each CPU, out2rpc is used to convert the ELF .out to a binary file containing only the loadable sections. This is called a RPRC file.
    • For each CPU, xipGen is used to split this RPRC file into two RPRC files.
      • One RPRC, containing the section that during boot need to be loaded to RAM
      • Second RPRC, containing the section that during boot are not loaded to RAM but are instead "eXecuted In Place", i.e XIP
    • multiCoreGen is then used to combine all the non-XIP RPRC files per CPU into a single .appimage file which is a concatenation of the individual CPU specific RPRC files.
    • multiCoreGen is used again to combine all the XIP RPRC files per CPU into a single .appimage_xip file which is a concatenation of the individual CPU specific RPRC XIP files.
  • This .appimage and .appimage_xip is then flashed to the board

Post build steps

Flashing the application for boot

  • Once the application images (.appimage and .appimage_xip) are created one needs to copy or flash these to a supported boot media so that the application can start executing once the SOC is powered ON
  • When flashing the application we also need to flash a bootloader or SBL image.
  • See Flashing Tools for detailed steps that are done to flash a user application

Booting the application

After a SBL and application image is flashed, shown below is the high level boot flow, after the SOC is powered on.

HIGH LEVEL BOOTFLOW

Secure Boot

In secure device variants, there are slight differences in the bootflow. For details on secure boot, please refer Enabling Secure Boot

Deep Dive into SBLs

The SBL is like any other example of the SDK. They use the bootloader library APIs to carry out the bootloading process. Depending on the boot media from which we load the application binary, we have multiple SBLs like sbl_ospi,sbl_uart etc. A bare minimum SBL called the sbl_null is also included which aids the users to load their applications via CCS. Here are some details regarding those.

SBL NULL

  • The sbl_null is a secondary bootloader which doesn't load any application binary, but just does the SOC initialization and puts all the cores in WFI (Wait For Interrupt) mode.
  • This is supposed to be a "development form" bootloader which should be used only during initial development.
  • The other method is using NO-BOOT/DEV-BOOT boot modes of the devices and using GEL scripts to initialize the SoC via debugger. The application binaries can then be side-loaded. ROM is not involved in this case. The sbl_null is an alternative to this process.
  • In HS-SE devices, the debugger is usually closed. So using the sbl_null is the only option to initialize the device in this case.
  • This is referred to as the SOC initialization binary, refer Flash SOC Initialization Binary for more on this.

SBL SD

  • The sbl_sd is a secondary bootloader which reads the application image file from the SD card and then moves on to core initialization and other steps
  • To boot an application using the sbl_sd, the application image needs to be copied to the SD card as a file named "app". Make sure that the SD card is formatted to have a FAT partition. To know more about the SD card partitioning please refer SOC Initialization Using SD BOOT
  • Follow the steps in the above referred page to partition the SD card. For a complete boot from SD card, both the sbl_sd binary and the application image binary has to be present as files in the SD card. You have to rename the sbl_sd appimage as 'tiboot3.bin'.
      copy file to SD card => ${SDK_INSTALL_PATH}/tools/boot/sbl_prebuilt/am243x-evm/sbl_sd.release.hs_fs.tiimage
      rename in SD card as => tiboot3.bin
    
  • Similarly you can copy any appimage file to the SD card and rename in the SD card as "app" so that the SBL can pick it up.
  • Currently the sbl_sd reads the full appimage file into an MSRAM buffer and then parses the multicore appimage. Because of this reason appimages higher than ~380 KB in size can't be booted by sbl_sd as of now.

SBL OSPI

  • The sbl_ospi is a secondary bootloader which reads and parses the application image from a location in the OSPI flash and then moves on to core initialization and other steps
  • To boot an application using the sbl_ospi, the application image needs to be flashed at a particular location in the OSPI flash memory.
  • This location or offset is specified in the SysConfig of the sbl_ospi application. Currently this is 0x80000. This offset is chosen under the assumption that the sbl_ospi application takes at max 512 KB from the start of the flash. If a custom bootloader is used, make sure that this offset is chosen in such a way that it is greater than the size of the bootloader which is being flashed and also aligns with the block size of the flash.
  • To flash an application (or any file in fact) to a location in the OSPI flash memory, follow the steps mentioned in Basic steps to flash files

SBL OSPI MULTI-PARTITION

  • The sbl_ospi_multipartition is a secondary bootloader which reads and parses core-specific application images for a system project from pre-defined locations in the OSPI flash and then moves on to core initialization and other steps
  • To boot an application using the sbl_ospi_multipartition, the application images needs to be flashed at specific locations in the OSPI flash memory. The default offsets are 512 KB apart.
  • This locations or offsets are specified in the SysConfig of the sbl_ospi_multipartition application.
  • For more information please refer to the example documentation of sbl_ospi_multipartition here: SBL OSPI Multi-Partition
  • To flash an application (or any file in fact) to a location in the OSPI flash memory, follow the steps mentioned in Basic steps to flash files

SBL UART

  • The sbl_uart is a secondary bootloader which receives the multicore appimage via UART, stores it in memory and then does the parsing, core initialization etc.
  • To boot an application using the sbl_uart, you can refer to UART Bootloader Python Script subsection. Detailed steps on the usage is mentioned in the same subsection.

SBL PCIE

  • The sbl pcie is a secondary bootloader which receives the multicore appimage via PCIe to memory and then does the parsing, core initialization etc.
  • The bootloader and appimage for sbl pcie is send over to the target board from a host board running SBL PCIE HOST.
  • For detailed steps on running sbl pcie, you can refer to SBL PCIE.

SBL EMMC

  • The sbl_emmc is a secondary bootloader which reads and parses the application image from a location in the eMMC and then moves on to core initialization and other steps.
  • To boot an application using the sbl_emmc, the application image needs to be flashed at a particular location in the eMMC.
  • This location or offset is specified in the SysConfig of the sbl_emmc application. Currently this is 0x800000.
  • To flash an application (or any file in fact) to a location in the eMMC, follow the steps mentioned in Basic steps to flash files

Additional References

See also these additional pages for more details and examples about the boot flow,