2021-11-03 20:19:22 +08:00
# Porting how-to
2017-05-08 20:17:50 +08:00
This document describes the requirements and necessary steps required to port
2021-10-20 21:27:16 +08:00
`MCUboot` to a new target `OS` .
2017-05-08 20:17:50 +08:00
# Requirements
2021-10-20 21:27:16 +08:00
* `MCUboot` requires a configuration file, which can be included as
2018-04-13 00:40:46 +08:00
mcuboot_config/mcuboot_config.h, which configures various options
(that begin with MCUBOOT_).
2021-10-20 21:27:16 +08:00
* `MCUboot` requires that the target provides a `flash` API with ability to
2017-06-29 06:33:33 +08:00
get the flash's minimum write size, and read/write/erase individual sectors.
2017-05-08 20:17:50 +08:00
2021-10-20 21:27:16 +08:00
* `MCUboot` doesn't bundle a cryptographic library, which means the target
2017-05-08 20:17:50 +08:00
OS must already have it bundled. The supported libraries at the moment are
2021-10-20 21:36:45 +08:00
either `Mbed TLS` or the set `tinycrypt` + `Mbed TLS` (where `Mbed TLS` is
2017-06-29 06:33:33 +08:00
used to provide functionality not existing in `tinycrypt` ).
2017-05-08 20:17:50 +08:00
# Steps to port
## Main app and calling the bootloader
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:
```c
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:
```c
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.
2018-04-13 00:40:46 +08:00
## Configuration file
You must provide a file, mcuboot_config/mcuboot_config.h. This is
included by several files in the "library" portion of MCUboot; it
provides preprocessor definitions that configure the library's
build.
See the file samples/mcuboot_config/mcuboot_config.template.h for a
starting point and more information. This is a good place to convert
settings in your environment's configuration system to those required
by MCUboot. For example, Mynewt uses MYNEWT_VAL() and Zephyr uses
Kconfig; these configuration systems are converted to MCUBOOT_ options
in the following files:
- boot/zephyr/include/mcuboot_config/mcuboot_config.h
- boot/mynewt/mcuboot_config/include/mcuboot_config/mcuboot_config.h
2018-07-19 18:53:20 +08:00
## Flash Map
2017-05-08 20:17:50 +08:00
2021-05-07 19:16:15 +08:00
The bootloader requires to be able to address flash regions where the code
2021-10-20 21:27:16 +08:00
for MCUboot and images of applications are stored, in system-agnostic way.
For that purpose the MCUboot uses ID, which is integer (uint8_t) number
2021-05-07 19:16:15 +08:00
that should uniquely identify each flash region.
Such flash regions are served by object of `const struct flash_area` type while
layout of these objects is gathered under `flash_map` .
2021-10-20 21:27:16 +08:00
The common code of MCUboot, that is non-system specific, does not directly
2021-05-07 19:16:15 +08:00
access contents of that object and never modifies it, instead it calls
`flash_area_` API to perform any actions on that object.
This way systems are free to implement internal logic of flash map or define
`struct flash_area` as they wish; the only restriction is that ID should be
uniquely tied to region characterized by device, offset and size.
2021-10-20 21:27:16 +08:00
Changes to common MCUboot code should not affect system specific internals
of flash map, on the other side system specific code, within MCUboot, is
2021-05-07 19:16:15 +08:00
is not restricted from directly accessing `struct flash_area` elements.
An implementation of `struct flash_area` may take form of:
2017-05-08 20:17:50 +08:00
```c
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 */
};
2021-05-07 19:16:15 +08:00
```
The above example of structure hold all information that is currently required
2021-10-20 21:27:16 +08:00
by MCUboot, although the MCUboot will not be trying to access them directly,
2021-05-07 19:16:15 +08:00
instead a system is required to provide following mandatory getter functions:
```c
/*< Obtains ID of the flash area characterized by `fa` */
int flash_area_get_id(const struct flash_area *fa);
/*< Obtains ID of a device the flash area `fa` described region resides on */
int flash_area_get_device_id(const struct flash_area *fa)
/*< Obtains offset , from the beginning of a device , the flash area described
* region starts at */
uint32_t flash_area_get_off(const struct flash_area *fa)
/*< Obtains size , from the offset , of the flash area `fa` characterized region */
uint32_t flash_area_get_size(const struct flash_area *fa)
2017-05-08 20:17:50 +08:00
```
2021-10-20 21:27:16 +08:00
The MCUboot common code uses following defines that should be defined by system
2021-05-07 19:16:15 +08:00
specific header files and are used to identify destination of flash area by ID:
2017-05-08 20:17:50 +08:00
```c
2019-03-22 21:58:33 +08:00
/* Independent from multiple image boot */
#define FLASH_AREA_BOOTLOADER 0
#define FLASH_AREA_IMAGE_SCRATCH 3
```
```c
/* Flash area IDs of the first image in case of multiple images */
#define FLASH_AREA_IMAGE_PRIMARY 1
#define FLASH_AREA_IMAGE_SECONDARY 2
```
```c
/* Flash area IDs of the second image in case of multiple images */
#define FLASH_AREA_IMAGE_PRIMARY 5
#define FLASH_AREA_IMAGE_SECONDARY 6
2017-05-08 20:17:50 +08:00
```
2021-05-07 19:16:15 +08:00
The numbers, given above, are provided as an example and depend on system
implementation.
The main, also required, set of API functions that perform operations on
flash characterized by `struct flash_area` objects is as follows:
2017-05-08 20:17:50 +08:00
```c
/*< 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 *);
2020-01-13 19:24:19 +08:00
/*< What is value is read from erased flash bytes . * /
uint8_t flash_area_erased_val(const struct flash_area *);
/*< Given flash area ID , return info about sectors within the area . * /
int flash_area_get_sectors(int fa_id, uint32_t *count,
struct flash_sector *sectors);
/*< Returns the `fa_id` for slot , where slot is 0 ( primary ) or 1 ( secondary ).
`image_index` (0 or 1) is the index of the image. Image index is
relevant only when multi-image support support is enabled */
int flash_area_id_from_multi_image_slot(int image_index, int slot);
/*< Returns the slot ( 0 for primary or 1 for secondary ) , for the supplied
`image_index` and `area_id` . `area_id` is unique and is represented by
`fa_id` in the `flash_area` struct. */
int flash_area_id_to_multi_image_slot(int image_index, int area_id);
2017-05-08 20:17:50 +08:00
```
2021-10-21 18:38:36 +08:00
---
***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.*
---
2020-12-02 14:57:30 +08:00
2021-10-20 21:36:45 +08:00
## Memory management for Mbed TLS
2017-05-08 20:17:50 +08:00
2021-10-20 21:36:45 +08:00
`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
2017-05-08 20:17:50 +08:00
needs to provide this pair of function.
To configure the what functions are called when allocating/deallocating
2021-10-20 21:36:45 +08:00
memory `Mbed TLS` uses the following call:
2017-05-08 20:17:50 +08:00
```
int mbedtls_platform_set_calloc_free (void *(*calloc_func)(size_t, size_t),
void (*free_func)(void *));
```
2021-10-20 21:36:45 +08:00
For reference see [Mbed TLS platform.h ](https://tls.mbed.org/api/platform_8h.html ).
2020-10-01 19:09:52 +08:00
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.