1# Porting How-To 2 3This document describes the requirements and necessary steps required to port 4`mcuboot` to a new target `OS`. 5 6# Requirements 7 8* `mcuboot` requires a configuration file, which can be included as 9 mcuboot_config/mcuboot_config.h, which configures various options 10 (that begin with MCUBOOT_). 11 12* `mcuboot` requires that the target provides a `flash` API with ability to 13 get the flash's minimum write size, and read/write/erase individual sectors. 14 15* `mcuboot` doesn't bundle a cryptographic library, which means the target 16 OS must already have it bundled. The supported libraries at the moment are 17 either `mbed TLS` or the set `tinycrypt` + `mbed TLS` (where `mbed TLS` is 18 used to provide functionality not existing in `tinycrypt`). 19 20# Steps to port 21 22## Main app and calling the bootloader 23 24From the perspective of the target OS, the bootloader can be seen as a library, 25so an entry point must be provided. This is likely a typical `app` for the 26target OS, and it must call the following function to run the bootloader: 27 28```c 29int boot_go(struct boot_rsp *rsp); 30``` 31 32This function is located at `boot/bootutil/loader.c` and receives a `struct 33boot_rsp` pointer. The `struct boot_rsp` is defined as: 34 35```c 36struct boot_rsp { 37 /** A pointer to the header of the image to be executed. */ 38 const struct image_header *br_hdr; 39 40 /** 41 * The flash offset of the image to execute. Indicates the position of 42 * the image header. 43 */ 44 uint8_t br_flash_id; 45 uint32_t br_image_addr; 46}; 47``` 48 49After running the management functions of the bootloader, `boot_go` returns 50an initialized `boot_rsp` which has pointers to the location of the image 51where the target firmware is located which can be used to jump to. 52 53## Configuration file 54 55You must provide a file, mcuboot_config/mcuboot_config.h. This is 56included by several files in the "library" portion of MCUboot; it 57provides preprocessor definitions that configure the library's 58build. 59 60See the file samples/mcuboot_config/mcuboot_config.template.h for a 61starting point and more information. This is a good place to convert 62settings in your environment's configuration system to those required 63by MCUboot. For example, Mynewt uses MYNEWT_VAL() and Zephyr uses 64Kconfig; these configuration systems are converted to MCUBOOT_ options 65in the following files: 66 67- boot/zephyr/include/mcuboot_config/mcuboot_config.h 68- boot/mynewt/mcuboot_config/include/mcuboot_config/mcuboot_config.h 69 70## Flash Map 71 72The bootloader requires a `flash_map` to be able to know how the flash is 73partitioned. A `flash_map` consists of `struct flash_area` entries 74specifying the partitions, where a `flash_area` defined as follows: 75 76```c 77struct flash_area { 78 uint8_t fa_id; /** The slot/scratch identification */ 79 uint8_t fa_device_id; /** The device id (usually there's only one) */ 80 uint16_t pad16; 81 uint32_t fa_off; /** The flash offset from the beginning */ 82 uint32_t fa_size; /** The size of this sector */ 83}; 84``` 85 86`fa_id` is can be one of the following options: 87 88```c 89/* Independent from multiple image boot */ 90#define FLASH_AREA_BOOTLOADER 0 91#define FLASH_AREA_IMAGE_SCRATCH 3 92``` 93```c 94/* Flash area IDs of the first image in case of multiple images */ 95#define FLASH_AREA_IMAGE_PRIMARY 1 96#define FLASH_AREA_IMAGE_SECONDARY 2 97``` 98```c 99/* Flash area IDs of the second image in case of multiple images */ 100#define FLASH_AREA_IMAGE_PRIMARY 5 101#define FLASH_AREA_IMAGE_SECONDARY 6 102``` 103 104The functions that must be defined for working with the `flash_area`s are: 105 106```c 107/*< Opens the area for use. id is one of the `fa_id`s */ 108int flash_area_open(uint8_t id, const struct flash_area **); 109void flash_area_close(const struct flash_area *); 110/*< Reads `len` bytes of flash memory at `off` to the buffer at `dst` */ 111int flash_area_read(const struct flash_area *, uint32_t off, void *dst, 112 uint32_t len); 113/*< Writes `len` bytes of flash memory at `off` from the buffer at `src` */ 114int flash_area_write(const struct flash_area *, uint32_t off, 115 const void *src, uint32_t len); 116/*< Erases `len` bytes of flash memory at `off` */ 117int flash_area_erase(const struct flash_area *, uint32_t off, uint32_t len); 118/*< Returns this `flash_area`s alignment */ 119uint8_t flash_area_align(const struct flash_area *); 120/*< What is value is read from erased flash bytes. */ 121uint8_t flash_area_erased_val(const struct flash_area *); 122/*< Given flash area ID, return info about sectors within the area. */ 123int flash_area_get_sectors(int fa_id, uint32_t *count, 124 struct flash_sector *sectors); 125/*< Returns the `fa_id` for slot, where slot is 0 (primary) or 1 (secondary). 126 `image_index` (0 or 1) is the index of the image. Image index is 127 relevant only when multi-image support support is enabled */ 128int flash_area_id_from_multi_image_slot(int image_index, int slot); 129/*< Returns the slot (0 for primary or 1 for secondary), for the supplied 130 `image_index` and `area_id`. `area_id` is unique and is represented by 131 `fa_id` in the `flash_area` struct. */ 132int flash_area_id_to_multi_image_slot(int image_index, int area_id); 133``` 134 135**Note:** As of writing, it is possible that mcuboot will open a flash area multiple times simultaneously (through nested calls to `flash_area_open`). As a result, mcuboot may call `flash_area_close` on a flash area that is still opened by another part of mcuboot. As a workaround when porting, it may be necessary to implement a counter of the number of times a given flash area has been opened by mcuboot. The `flash_area_close` implementation should only fully deinitialize the underlying flash area when the open counter is decremented to 0. See [this GitHub PR](https://github.com/mcu-tools/mcuboot/pull/894/) for a more detailed discussion. 136 137## Memory management for mbed TLS 138 139`mbed TLS` employs dynamic allocation of memory, making use of the pair 140`calloc/free`. If `mbed TLS` is to be used for crypto, your target RTOS 141needs to provide this pair of function. 142 143To configure the what functions are called when allocating/deallocating 144memory `mbed TLS` uses the following call: 145 146``` 147int mbedtls_platform_set_calloc_free (void *(*calloc_func)(size_t, size_t), 148 void (*free_func)(void *)); 149``` 150 151For reference see [mbed TLS platform.h](https://tls.mbed.org/api/platform_8h.html). 152If your system already provides functions with compatible signatures, those can 153be used directly here, otherwise create new functions that glue to your 154`calloc/free` implementations. 155