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

  1. 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

  2. Change the compile optimization level to low.

  3. 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, and mmcau_aes_decrypt are shown.

  4. Open the list file to see the MMCAU algorithm length - 1212 = 0x4BC.

  5. 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. See mmcau_function_cm4.bin.

  6. 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, the mmcau_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 where mmcau_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.

  7. 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 in mmcau_function_into (0x418 ~ 0x41b)

      The value is 0x00000424 (0x410 + 0x14 (mmcau_function_info structure size))

    • aes_encrypt_start in mmcau_function_info (0x41c ~ 0x41f)

      The value is 0x000004fa (0x424 + 0xd6 (mmcau_aes_init function size))

    • aes_decrypt_start in mmcau_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