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