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 to be able to address flash regions where the code 73for MCUboot and images of applications are stored, in system-agnostic way. 74For that purpose the MCUboot uses ID, which is integer (uint8_t) number 75that should uniquely identify each flash region. 76Such flash regions are served by object of `const struct flash_area` type while 77layout of these objects is gathered under `flash_map`. 78The common code of MCUboot, that is non-system specific, does not directly 79access contents of that object and never modifies it, instead it calls 80`flash_area_` API to perform any actions on that object. 81This way systems are free to implement internal logic of flash map or define 82`struct flash_area` as they wish; the only restriction is that ID should be 83uniquely tied to region characterized by device, offset and size. 84 85Changes to common MCUboot code should not affect system specific internals 86of flash map, on the other side system specific code, within MCUboot, is 87is not restricted from directly accessing `struct flash_area` elements. 88 89 90An implementation of `struct flash_area` may take form of: 91```c 92struct flash_area { 93 uint8_t fa_id; /** The slot/scratch identification */ 94 uint8_t fa_device_id; /** The device id (usually there's only one) */ 95 uint16_t pad16; 96 uint32_t fa_off; /** The flash offset from the beginning */ 97 uint32_t fa_size; /** The size of this sector */ 98}; 99``` 100The above example of structure hold all information that is currently required 101by MCUboot, although the MCUboot will not be trying to access them directly, 102instead a system is required to provide following mandatory getter functions: 103 104```c 105/*< Obtains ID of the flash area characterized by `fa` */ 106int flash_area_get_id(const struct flash_area *fa); 107/*< Obtains ID of a device the flash area `fa` described region resides on */ 108int flash_area_get_device_id(const struct flash_area *fa) 109/*< Obtains offset, from the beginning of a device, the flash area described 110 * region starts at */ 111uint32_t flash_area_get_off(const struct flash_area *fa) 112/*< Obtains size, from the offset, of the flash area `fa` characterized region */ 113uint32_t flash_area_get_size(const struct flash_area *fa) 114 115``` 116 117The MCUboot common code uses following defines that should be defined by system 118specific header files and are used to identify destination of flash area by ID: 119 120```c 121/* Independent from multiple image boot */ 122#define FLASH_AREA_BOOTLOADER 0 123#define FLASH_AREA_IMAGE_SCRATCH 3 124``` 125```c 126/* Flash area IDs of the first image in case of multiple images */ 127#define FLASH_AREA_IMAGE_PRIMARY 1 128#define FLASH_AREA_IMAGE_SECONDARY 2 129``` 130```c 131/* Flash area IDs of the second image in case of multiple images */ 132#define FLASH_AREA_IMAGE_PRIMARY 5 133#define FLASH_AREA_IMAGE_SECONDARY 6 134``` 135 136The numbers, given above, are provided as an example and depend on system 137implementation. 138 139The main, also required, set of API functions that perform operations on 140flash characterized by `struct flash_area` objects is as follows: 141 142```c 143/*< Opens the area for use. id is one of the `fa_id`s */ 144int flash_area_open(uint8_t id, const struct flash_area **); 145void flash_area_close(const struct flash_area *); 146/*< Reads `len` bytes of flash memory at `off` to the buffer at `dst` */ 147int flash_area_read(const struct flash_area *, uint32_t off, void *dst, 148 uint32_t len); 149/*< Writes `len` bytes of flash memory at `off` from the buffer at `src` */ 150int flash_area_write(const struct flash_area *, uint32_t off, 151 const void *src, uint32_t len); 152/*< Erases `len` bytes of flash memory at `off` */ 153int flash_area_erase(const struct flash_area *, uint32_t off, uint32_t len); 154/*< Returns this `flash_area`s alignment */ 155uint32_t flash_area_align(const struct flash_area *); 156/*< What is value is read from erased flash bytes. */ 157uint8_t flash_area_erased_val(const struct flash_area *); 158/*< Given flash area ID, return info about sectors within the area. */ 159int flash_area_get_sectors(int fa_id, uint32_t *count, 160 struct flash_sector *sectors); 161/*< Returns the `fa_id` for slot, where slot is 0 (primary) or 1 (secondary). 162 `image_index` (0 or 1) is the index of the image. Image index is 163 relevant only when multi-image support support is enabled */ 164int flash_area_id_from_multi_image_slot(int image_index, int slot); 165/*< Returns the slot (0 for primary or 1 for secondary), for the supplied 166 `image_index` and `area_id`. `area_id` is unique and is represented by 167 `fa_id` in the `flash_area` struct. */ 168int flash_area_id_to_multi_image_slot(int image_index, int area_id); 169``` 170 171--- 172***Note*** 173 174*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.* 175 176--- 177 178## Memory management for Mbed TLS 179 180`Mbed TLS` employs dynamic allocation of memory, making use of the pair 181`calloc/free`. If `Mbed TLS` is to be used for crypto, your target RTOS 182needs to provide this pair of function. 183 184To configure the what functions are called when allocating/deallocating 185memory `Mbed TLS` uses the following call: 186 187``` 188int mbedtls_platform_set_calloc_free (void *(*calloc_func)(size_t, size_t), 189 void (*free_func)(void *)); 190``` 191 192For reference see [Mbed TLS platform.h](https://tls.mbed.org/api/platform_8h.html). 193If your system already provides functions with compatible signatures, those can 194be used directly here, otherwise create new functions that glue to your 195`calloc/free` implementations. 196