blob: 48040960add67dc9155651e6818a246870f31566 [file] [log] [blame] [view]
Francesco Servidio5bc98322021-11-03 13:19:22 +01001# Porting how-to
Fabio Utzig01ccb192017-05-08 09:17:50 -03002
3This document describes the requirements and necessary steps required to port
Francesco Servidio4ff0c182021-10-20 15:27:16 +02004`MCUboot` to a new target `OS`.
Fabio Utzig01ccb192017-05-08 09:17:50 -03005
6# Requirements
7
Francesco Servidio4ff0c182021-10-20 15:27:16 +02008* `MCUboot` requires a configuration file, which can be included as
Marti Bolivarf91bca52018-04-12 12:40:46 -04009 mcuboot_config/mcuboot_config.h, which configures various options
10 (that begin with MCUBOOT_).
11
Francesco Servidio4ff0c182021-10-20 15:27:16 +020012* `MCUboot` requires that the target provides a `flash` API with ability to
Fabio Utzige2d99f82017-06-28 19:33:33 -030013 get the flash's minimum write size, and read/write/erase individual sectors.
Fabio Utzig01ccb192017-05-08 09:17:50 -030014
Francesco Servidio4ff0c182021-10-20 15:27:16 +020015* `MCUboot` doesn't bundle a cryptographic library, which means the target
Fabio Utzig01ccb192017-05-08 09:17:50 -030016 OS must already have it bundled. The supported libraries at the moment are
Francesco Servidio582367c2021-10-20 15:36:45 +020017 either `Mbed TLS` or the set `tinycrypt` + `Mbed TLS` (where `Mbed TLS` is
Fabio Utzige2d99f82017-06-28 19:33:33 -030018 used to provide functionality not existing in `tinycrypt`).
Fabio Utzig01ccb192017-05-08 09:17:50 -030019
Fabio Utzig01ccb192017-05-08 09:17:50 -030020# Steps to port
21
Fabio Utzig01ccb192017-05-08 09:17:50 -030022## 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
Marti Bolivarf91bca52018-04-12 12:40:46 -040053## 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
Fabio Utzig6f9c7952018-07-19 07:53:20 -030070## Flash Map
Fabio Utzig01ccb192017-05-08 09:17:50 -030071
Dominik Ermeld3f36092021-05-07 11:16:15 +000072The bootloader requires to be able to address flash regions where the code
Francesco Servidio4ff0c182021-10-20 15:27:16 +020073for MCUboot and images of applications are stored, in system-agnostic way.
74For that purpose the MCUboot uses ID, which is integer (uint8_t) number
Dominik Ermeld3f36092021-05-07 11:16:15 +000075that 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`.
Francesco Servidio4ff0c182021-10-20 15:27:16 +020078The common code of MCUboot, that is non-system specific, does not directly
Dominik Ermeld3f36092021-05-07 11:16:15 +000079access 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.
Fabio Utzig01ccb192017-05-08 09:17:50 -030084
Francesco Servidio4ff0c182021-10-20 15:27:16 +020085Changes to common MCUboot code should not affect system specific internals
86of flash map, on the other side system specific code, within MCUboot, is
Dominik Ermeld3f36092021-05-07 11:16:15 +000087is not restricted from directly accessing `struct flash_area` elements.
88
89
90An implementation of `struct flash_area` may take form of:
Fabio Utzig01ccb192017-05-08 09:17:50 -030091```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```
Dominik Ermeld3f36092021-05-07 11:16:15 +0000100The above example of structure hold all information that is currently required
Francesco Servidio4ff0c182021-10-20 15:27:16 +0200101by MCUboot, although the MCUboot will not be trying to access them directly,
Dominik Ermeld3f36092021-05-07 11:16:15 +0000102instead a system is required to provide following mandatory getter functions:
Fabio Utzig01ccb192017-05-08 09:17:50 -0300103
Dominik Ermeld3f36092021-05-07 11:16:15 +0000104```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
Francesco Servidio4ff0c182021-10-20 15:27:16 +0200117The MCUboot common code uses following defines that should be defined by system
Dominik Ermeld3f36092021-05-07 11:16:15 +0000118specific header files and are used to identify destination of flash area by ID:
Fabio Utzig01ccb192017-05-08 09:17:50 -0300119
120```c
David Vinczeb75c12a2019-03-22 14:58:33 +0100121/* 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
Fabio Utzig01ccb192017-05-08 09:17:50 -0300134```
135
Dominik Ermeld3f36092021-05-07 11:16:15 +0000136The 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:
Fabio Utzig01ccb192017-05-08 09:17:50 -0300141
142```c
143/*< Opens the area for use. id is one of the `fa_id`s */
Gustavo Henrique Nihei4aa286d2021-11-24 14:54:56 -0300144int flash_area_open(uint8_t id, const struct flash_area **);
145void flash_area_close(const struct flash_area *);
Fabio Utzig01ccb192017-05-08 09:17:50 -0300146/*< Reads `len` bytes of flash memory at `off` to the buffer at `dst` */
Gustavo Henrique Nihei4aa286d2021-11-24 14:54:56 -0300147int flash_area_read(const struct flash_area *, uint32_t off, void *dst,
148 uint32_t len);
Fabio Utzig01ccb192017-05-08 09:17:50 -0300149/*< Writes `len` bytes of flash memory at `off` from the buffer at `src` */
Gustavo Henrique Nihei4aa286d2021-11-24 14:54:56 -0300150int flash_area_write(const struct flash_area *, uint32_t off,
151 const void *src, uint32_t len);
Fabio Utzig01ccb192017-05-08 09:17:50 -0300152/*< Erases `len` bytes of flash memory at `off` */
Gustavo Henrique Nihei4aa286d2021-11-24 14:54:56 -0300153int flash_area_erase(const struct flash_area *, uint32_t off, uint32_t len);
Fabio Utzig01ccb192017-05-08 09:17:50 -0300154/*< Returns this `flash_area`s alignment */
Gustavo Henrique Nihei4aa286d2021-11-24 14:54:56 -0300155uint32_t flash_area_align(const struct flash_area *);
Rajiv Ranganathb976a4c2020-01-13 16:54:19 +0530156/*< What is value is read from erased flash bytes. */
Gustavo Henrique Nihei4aa286d2021-11-24 14:54:56 -0300157uint8_t flash_area_erased_val(const struct flash_area *);
Rajiv Ranganathb976a4c2020-01-13 16:54:19 +0530158/*< Given flash area ID, return info about sectors within the area. */
Gustavo Henrique Nihei4aa286d2021-11-24 14:54:56 -0300159int flash_area_get_sectors(int fa_id, uint32_t *count,
160 struct flash_sector *sectors);
Rajiv Ranganathb976a4c2020-01-13 16:54:19 +0530161/*< 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 */
Gustavo Henrique Nihei4aa286d2021-11-24 14:54:56 -0300164int flash_area_id_from_multi_image_slot(int image_index, int slot);
Rajiv Ranganathb976a4c2020-01-13 16:54:19 +0530165/*< 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. */
Gustavo Henrique Nihei4aa286d2021-11-24 14:54:56 -0300168int flash_area_id_to_multi_image_slot(int image_index, int area_id);
Fabio Utzig01ccb192017-05-08 09:17:50 -0300169```
170
Francesco Servidio2fe449d2021-10-21 12:38:36 +0200171---
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---
George Becksteind1233e12020-12-02 01:57:30 -0500177
Francesco Servidio582367c2021-10-20 15:36:45 +0200178## Memory management for Mbed TLS
Fabio Utzig01ccb192017-05-08 09:17:50 -0300179
Francesco Servidio582367c2021-10-20 15:36:45 +0200180`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
Fabio Utzig01ccb192017-05-08 09:17:50 -0300182needs to provide this pair of function.
183
184To configure the what functions are called when allocating/deallocating
Francesco Servidio582367c2021-10-20 15:36:45 +0200185memory `Mbed TLS` uses the following call:
Fabio Utzig01ccb192017-05-08 09:17:50 -0300186
187```
188int mbedtls_platform_set_calloc_free (void *(*calloc_func)(size_t, size_t),
189 void (*free_func)(void *));
190```
191
Francesco Servidio582367c2021-10-20 15:36:45 +0200192For reference see [Mbed TLS platform.h](https://tls.mbed.org/api/platform_8h.html).
Fabio Utzig8ebe5352020-10-01 08:09:52 -0300193If 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.