This document describes the requirements and necessary steps required to port mcuboot
to a new target OS
.
mcuboot
requires that the target provides a flash
API with ability to get the flash's minimum write size, and read/write/erase individual sectors.
mcuboot
doesn't bundle a cryptographic library, which means the target OS must already have it bundled. The supported libraries at the moment are either mbed TLS
or the set tinycrypt
+ mbed TLS
(where mbed TLS
is used to provide functionality not existing in tinycrypt
).
From the perspective of the target OS, the bootloader can be seen as a library, so an entry point must be provided. This is likely a typical app
for the target OS, and it must call the following function to run the bootloader:
int boot_go(struct boot_rsp *rsp);
This function is located at boot/bootutil/loader.c
and receives a struct boot_rsp
pointer. The struct boot_rsp
is defined as:
struct boot_rsp { /** A pointer to the header of the image to be executed. */ const struct image_header *br_hdr; /** * The flash offset of the image to execute. Indicates the position of * the image header. */ uint8_t br_flash_id; uint32_t br_image_addr; };
After running the management functions of the bootloader, boot_go
returns an initialized boot_rsp
which has pointers to the location of the image where the target firmware is located which can be used to jump to.
mcuboot
needs to know the write size (and alignment) of the flash. To get this information it calls hal_flash_align
.
uint8_t hal_flash_align(uint8_t flash_id);
The bootloader requires a flash_map
to be able to know how the flash is partitioned. A flash_map
consists of struct flash_area
entries specifying the partitions, where a flash_area
defined as follows:
struct flash_area { uint8_t fa_id; /** The slot/scratch identification */ uint8_t fa_device_id; /** The device id (usually there's only one) */ uint16_t pad16; uint32_t fa_off; /** The flash offset from the beginning */ uint32_t fa_size; /** The size of this sector */ };
fa_id
is can be one of the following options:
#define FLASH_AREA_IMAGE_0 1 #define FLASH_AREA_IMAGE_1 2 #define FLASH_AREA_IMAGE_SCRATCH 3
The functions that must be defined for working with the flash_area
s are:
/*< Opens the area for use. id is one of the `fa_id`s */ int flash_area_open(uint8_t id, const struct flash_area **); void flash_area_close(const struct flash_area *); /*< Reads `len` bytes of flash memory at `off` to the buffer at `dst` */ int flash_area_read(const struct flash_area *, uint32_t off, void *dst, uint32_t len); /*< Writes `len` bytes of flash memory at `off` from the buffer at `src` */ int flash_area_write(const struct flash_area *, uint32_t off, const void *src, uint32_t len); /*< Erases `len` bytes of flash memory at `off` */ int flash_area_erase(const struct flash_area *, uint32_t off, uint32_t len); /*< Returns this `flash_area`s alignment */ uint8_t flash_area_align(const struct flash_area *); /*< Initializes an array of flash_area elements for the slot's sectors */ int flash_area_to_sectors(int idx, int *cnt, struct flash_area *ret); /*< Returns the `fa_id` for slot, where slot is 0 or 1 */ int flash_area_id_from_image_slot(int slot); /*< Returns the slot, for the `fa_id` supplied */ int flash_area_id_to_image_slot(int area_id);
mbed TLS
employs dynamic allocation of memory, making use of the pair calloc/free
. If mbed TLS
is to be used for crypto, your target RTOS needs to provide this pair of function.
To configure the what functions are called when allocating/deallocating memory mbed TLS
uses the following call [^cite1]:
int mbedtls_platform_set_calloc_free (void *(*calloc_func)(size_t, size_t), void (*free_func)(void *));
If your system already provides functions with compatible signatures, those can be used directly here, otherwise create new functions that glue to your calloc/free
implementations.
[^cite1]https://tls.mbed.org/api/platform_8h.html