Creating a custom flash-resident bootloader
Introduction
In some situations the ROM-based or full-featured flash-resident bootloader cannot meet the requirements of a use application. Examples of such situations include special signaling requirements on IO and peripherals not supported by the bootloader, or the more basic need to have as small of a code footprint as possible (for the flash-resident bootloader). This section discusses how to customize the flash-resident bootloader for a specific use case. The IAR tool chain is used for this example. Other supported tool chains can be similarly configured.
Parent topic:Creating a custom flash-resident bootloader
Where to start
The MCU bootloader comes with various preconfigured projects, including configurations for a flashloader (if applicable for the device) and a flash-resident bootloader. For all of these projects, supported features can easily be enabled or disabled to suit the needs of a custom application.
The projects containing these preconfigured options are located in the <sdk_package>/ boards/<board>/bootloader_examples folder. Inside of this folder there are bootloader projects including flash-resident bootloader, flashloader, flashloader_loader, and demo_apps. The figure below shows the bootloader projects for FRDM-K64F board.
Parent topic:Creating a custom flash-resident bootloader
Flash-resident bootloader source tree
It is important to understand the source tree to understand where modifications are possible. Here is an example of a source tree for one of the bootloader configurations.
There are two folders in each bootloader project: a device-specific folder and a “source” folder. All files in the device-specific folder are located in the <sdk_package>/ middleware/mcu-boot/targets/<device>/src folder, and are specific to the target device. The “source” folder is located at the top level of the bootloader tree, and the subfolders in the project correspond to the real folder/file structure on the PC. The files in the “source” folder are the core files of the bootloader.
The bootloader source is separated in a way that creates a clear line between what a user needs to modify and what they do not. Among other things, the files in the devicespecific folder allow the application to select which peripherals are active as well as how to configure the clock, and are intended to be modified by the user. The files in the “source” folder can be modified, but should only require modification where very specific customization is needed in the bootloader.
Parent topic:Creating a custom flash-resident bootloader
Modifying source files
The files that cover the majority of the customization options needed by applications are located in the device-specific folder. These files allow modification to the basic configuration elements of the bootloader application, and are not associated with the core functionality of the bootloader.
In the device-specific folder, the source files contain this information:
bootloader_config.h – Bootloader configuration options such as encryption, timeouts, CRC checking, the UART module number and baud rate, and most importantly, the vector table offset for the user application.
clock_config_<device>.c – Configures the clock for the device. This includes system, bus, etc.
hardware_init_<device>.c – Enables and configures peripherals used by the application. This includes pin muxing, peripheral initialization, and the pin used as a bootloader re-entry (bootstrap) mechanism.
memory_map_<device>.c – Contains a table that stores the memory map information for the targeted device.
peripherals_<device>.c – Contains the table used by the bootloader to check which peripheral interfaces are enabled. This is the file used to disable any unused peripheral interfaces.
peripherals_pinmux.h - Contains macros to identifiy peripheral pin mux, typically specific to a target platform.
Parent topic:Creating a custom flash-resident bootloader
Example
One of the most common customizations performed on the MCU bootloader is removing unused or unwanted peripheral interfaces. The default configuration of the bootloader enables multiple interfaces, including UART, SPI, I2C and (on some devices) USB and CAN. This example will describe how to remove the SPI0 interface from the provided bootloader projects . The same methodology can be used to select any of the supported interfaces.
Parent topic:Creating a custom flash-resident bootloader
Modifying a peripheral configuration macro
The bootloader_confg.h file is located in <sdk_package>/middleware/mcu-boot/targets/<device>/src. It contains macros such as:
#if !defined(BL_CONFIG_SPI0)
#define BL_CONFIG_SPI0 (1)
#endif
To remove an interface, either modify this file to set the macro to (0), or pass the macro define to the toolchain compiler in the project settings. For example:
BL_CONFIG_SPI0=0
Setting this macro to zero removes the interface from the g_peripherals table and prevents related code from linking into the bootloader image.
Parent topic:Creating a custom flash-resident bootloader
How to generate MMCAU functions in binary image
Add the MMCAU driver to the project.
Add the MMCAU driver
mmcau_aes_functions.c
to the project. There are only three functions in this driver.//! @brief An initialization function for the decryption peripheral void mmcau_aes_init(uint32_t *key, uint32_t *keySchedule, uint32_t *rcon); //! @brief Encrypts a 16 byte block of data//! in and out may use the same address so encrypting in place is supported void mmcau_aes_encrypt(uint32_t *in, uint32_t *key, uint32_t *keySchedule, uint32_t *out); //! @brief Decrypts a 16 byte block of data//! in and out may use the same address so decrypting in place is supported void mmcau_aes_decrypt(uint32_t *in, uint32_t *key, uint32_t *keySchedule, uint32_t *out);
The following figure shows that the driver has been added to the K80F256 bootloader project
Change the compile optimization level to low.
Compile the project and view the map file while generating the binary file for the entire project. The start address and offset of
mmcau_aes_init, mmcau_aes_encrypt,
andmmcau_aes_decrypt
are shown.Open the list file to see the MMCAU algorithm length - 1212 = 0x4BC.
Extract functions from the address of
mmcau_aes_init
(0x2058 in this case) by the MMCAU algorithm length (0x4BC) and save it. This is the MMCAU algorithm only. Seemmcau_function_cm4.bin
.Add the MMCAU algorithm to the Bootloader Configuration Area (BCA).
The MMCAU algorithm can be loaded to any accesible memory, such as RAM or flash. However, you need to update the BCA in order to have a pointer to an MMCAu set-up structure. See
aeas_security.h
for the structure definition.{ uint32_t tag; // 'kcau' = 0x uint32_t length; // number of bytes to copy, copied from the start of aes_init uint32_t aes_init_start; uint32_t aes_encrypt_start; uint32_t aes_decrypt_start; } mmcau_function_info_t;
The location offset of the MMCAU algorithm is x020. The BCA start is 0x3C0, and the
mmcau_function_info
address is 0x3E0. For decryption to work properly, themmcau_function_info
must contain valid values for all the fields in this structure. This structure size is 20 bytes (0x14 bytes).Tag
The tag field must equal ‘kcau’
Length
It is the total length of all MMCAU AES algorithms. See
mmcau_aes_functions.lst
. It is 1212 bytes (0x4BC).aes_init_start
Memory location of the
aes_init
function, the address wheremmcau_function_cm4.bin
is to be loaded. This function size is 0xD6.aes_encrypt_start
Memory location of the
aes_encrypt
function. This function size is 0x1B0.aes_decrypt_start
Memory location of the
aes_decrypt
function. This function size is 0x1BE.The figure below contains information for each function.
Example - Add the MMCAU algorithm after the BCA.
BCA 0x30 ~ 0x3DF
MMCAU setup in BCA - 0x3E0, which shows the start of
mmcau_function_info
Tag in
mmcau_function_info
(0x410 ~ 0x413)The values of 0x410 ~ 0x4`3 are ‘kcau’
Length in
mmcau_function_into
(0x414 ~ 0x417)The value is 0x000004BC
aes_init_start
inmmcau_function_into
(0x418 ~ 0x41b)The value is 0x00000424 (0x410 + 0x14 (
mmcau_function_info
structure size))aes_encrypt_start
inmmcau_function_info
(0x41c ~ 0x41f)The value is 0x000004fa (0x424 + 0xd6 (
mmcau_aes_init
function size))aes_decrypt_start
inmmcau_function_info
(0x420 ~ 0x423)The value is 0x000006aa (0x4fa + 0x1b0 (
mmcau_aes_encrypt
function size))The MMCAU algorithm starts from flash address 0x424
Parent topic:Creating a custom flash-resident bootloader