Image Loading Using MCUboot

MCUboot is a secure boot library used by Trusted Firmware-M (TF-M).

TF-M loads SCP, MCP and LCP images using MCUboot from flash into designated RAM regions for execution. This is MCUboot’s ram-load configuration. During image signing/creation additional information such as load address, header size, padding, signing key etc. that the bootloader expects can be facilitated using ‘imgtool’. Each mcuboot image is accompanied with a header region and a trailer region that hold the booloader information. After each boot image load, MCUboot records boot measurements into the shared data region. For more info, go to MCUboot Documentation.

Flash memory is partitioned according to the flash map and each flash area is identified with an id (Refer <workspace>/tf-m/platform/ext/target/arm/rse/rdv3/bl2/flash_map_bl2.c). Flash memory can include multiple image regions each of which contains two image slots, namely, primary and secondary. Before authentication and execution, the image is loaded into the RAM. Following represents a rough overview of SCP image loading:

                                 Flash
 FLASH_BASE_ADDRESS <--- +--------------------+
                         ~                    ~             Seperate Header region
                         ~        ~~~         ~             +--------------------+ ---> RSE_HEAD_PHYS_BASE /
                         ~                    ~             |                    |      HOST_SCP_HEAD_REGION_S
FLASH_AREA_6_OFFSET <--- +--------------------+             |     ~ unused ~     |       (Logical Address)
                         | SCP primary image  |             |                    |
                         | +----------------+-------------> +--------------------+ ---> HOST_SCP_IMAGE_BASE_S
                         | |    Header      | |             |   Image Header     |       (Logical Address)
                         | +----------------+-------+       +--------------------+
                         | |                | |     |
                         | |     code       | |     |
                         | +----------------+ |     |
                         | |                | |     |                RAM
                         | |      TLV       | |     +-----> +--------------------+ ---> HOST_SCP_PHYS_BASE /
                         | |       &        | |             |                    |      HOST_SCP_CODE_BASE_S
                         | |    padding     | |             |       Code         |       (Logical Address)
                         | |                | |             |                    |
                         | |                | |             +--------------------+
                         | +----------------+ |             |                    |
                         +--------------------+             |                    |
                         ~                    ~             |        TLV         |
                         ~        ~~~         ~             |         &          |
                         ~                    ~             |      padding       |
                         +--------------------+             |                    |
                                                            |                    |
                                                            +--------------------+
                                                            ~                    ~
                                                            ~        ~~~         ~
                                                            ~                    ~
                                                            +--------------------+

To load an image, boot_go_for_image_id() is invoked by passing the respective image id. boot_platform_pre_load() and boot_platform_post_load() functions are invoked before and after loading images respectively to map image specific ATU regions. Before loading the image, MCUboot checks for address overlaps. After loading the image, it is validated and boot measurements are recorded. MCUboot loads the image including the image header. Components such as SCP, expect the code region rather than the image header at the start of the RAM. To ensure this, ATU region of RSE is mapped such that the logical address is linear from RSE perspective, but the physical addresses are remapped such that the code region of the image is loaded to the start of the RAM, and the image header to a separate memory region.

ATU region base address and size should be aligned to the ATU page size, i.e, 8KB (0x2000) for RD-V3 platform. The ATU region is configured such that the header alone is loaded into a temporary region (with ATU minimum size of 0x2000) and rest of the image is loaded in the RAM region. Due to the memory constraints of LCP, this temporary region is made common for SCP, MCP and LCP, at the bottom of MCP RAM region. The header size is fixed at BL2_HEADER_SIZE (0x400) for the the host images. So, the load address has an offset of 0x2000 - 0x400 = 0x1C00 from HOST_SCP_HEAD_REGION_S to ensure that the image header ends up in the bottom on the temporary region.

SCP and MCP images are loaded into single address, whereas the LCP images needs to be loaded into multiple LCPs ITCM address. Currently, this is handled by remapping ATU regions iteratively to redirect the boot load into respective LCP ITCM (Refer <workspace>/tf-m/platform/ext/target/arm/rse/rdv3/bl2/boot_hal_bl2.c:boot_platform_post_load_lcp()). Additionally, recording of LCP boot measurements into the shared data is skipped after each image loads. A single common boot measurement for LCP is recorded after each LCP image is loaded, i.e., at the end of boot_platform_post_load_lcp(), since the measurement for LCPs are identical.