Roman Okhrimenko | 977b375 | 2022-03-31 14:40:48 +0300 | [diff] [blame] | 1 | # MCUboot port for NuttX |
| 2 | |
| 3 | ## Description |
| 4 | |
| 5 | The NuttX port of MCUboot secure boot library expects that the platform provides a Flash storage with the following partitions: |
| 6 | - `CONFIG_MCUBOOT_PRIMARY_SLOT_PATH`: MTD partition for the application firmware image PRIMARY slot; |
| 7 | - `CONFIG_MCUBOOT_SECONDARY_SLOT_PATH`: MTD partition for the application firmware image SECONDARY slot; |
| 8 | - `CONFIG_MCUBOOT_SCRATCH_PATH`: MTD partition for the Scratch area; |
| 9 | |
| 10 | Also, these are optional features that may be enabled: |
| 11 | |
| 12 | - `CONFIG_MCUBOOT_WATCHDOG`: If `CONFIG_WATCHDOG` is enabled, MCUboot shall reset the watchdog timer indicated by `CONFIG_MCUBOOT_WATCHDOG_DEVPATH` to the current timeout value, preventing any imminent watchdog timeouts. |
| 13 | |
| 14 | The porting layer of MCUboot library consists of the following interfaces: |
| 15 | - `<flash_map_backend/flash_map_backend.h>`, for enabling MCUboot to manage the application firmware image slots in the device storage. |
| 16 | - `<mcuboot_config/mcuboot_config.h>`, for configuration of MCUboot's features. |
| 17 | - `<mcuboot_config/mcuboot_logging.h>`, for providing logging capabilities. |
| 18 | - `<os/os_malloc.h>`, for providing MCUboot access to the OS memory management interfaces. |
| 19 | - `<sysflash/sysflash.h>`, for configuration of the system's flash area organization. |
| 20 | |
| 21 | The NuttX port of MCUboot is implemented at application-level and requires minimal knowledge about characteristics of the underlying storage device. This is achieved by means of the `BCH` and `FTL` subsystems, which enable MCUboot to manage MTD partitions via character device drivers using standard POSIX filesystem operations (e.g. `open()` / `close()` / `read()` / `write()`). |
| 22 | |
| 23 | ## Creating MCUboot-compatible application firmware images |
| 24 | |
| 25 | One common use case for MCUboot is to integrate it to a firmware update agent, which is an important component of a secure firmware update subsystem. Through MCUboot APIs an application is able to install a newly received application firmware image and, once this application firmware image is assured to be valid, the application may confirm it as a stable image. In case that application firmware image is deemed bogus, MCUboot provides an API for invalidating that update, which will induce a rollback procedure to the most recent stable application firmware image. |
| 26 | |
| 27 | The `CONFIG_MCUBOOT_UPDATE_AGENT_EXAMPLE` example demonstrates this workflow by downloading an application firmware image from a webserver, installing it and triggering the firmware update process for the next boot after a system reset. There is also the `CONFIG_MCUBOOT_SLOT_CONFIRM_EXAMPLE`, which is a fairly simple example that just calls an MCUboot API for confirming the executing application firmware image as stable. |
| 28 | |
| 29 | ## Using MCUboot on NuttX as a secure boot solution |
| 30 | |
| 31 | NuttX port for MCUboot also enables the creation of a secure bootloader application requiring minimal platform-specific implementation. The logical implementation for the secure boot is performed at application-level by the MCUboot library. Once MCUboot validates the application firmware image, it delegates the loading and execution of the application firmware image to a platform-specific routine, which is accessed via `boardctl(BOARDIOC_BOOT_IMAGE)` call. Each platform must then provide an implementation for the `board_boot_image()` for executing the required actions in order to boot a new application firmware image (e.g. deinitialize peripherals, load the Program Counter register with the application firmware image entry point address). |
| 32 | |
| 33 | The MCUboot bootloader application may be enabled by selecting the `CONFIG_MCUBOOT_BOOTLOADER` option. |
| 34 | |
| 35 | ## Assumptions |
| 36 | |
| 37 | ### IOCTL MTD commands |
| 38 | |
| 39 | The implementation of `<flash_map_backend/flash_map_backend.h>` expects that the MTD driver for a given image partition handles the following `ioctl` commands: |
| 40 | - `MTDIOC_GEOMETRY`, for retrieving information about the geometry of the MTD, required for the configuration of the size of each flash area. |
| 41 | - `MTDIOC_ERASESTATE`, for retrieving the byte value of an erased cell of the MTD, required for the implementation of `flash_area_erased_val()` interface. |
| 42 | |
| 43 | ### Write access alignment |
| 44 | |
| 45 | Through `flash_area_align()` interface MCUboot expects that the implementation provides the shortest data length that may be written via `flash_area_write()` interface. The NuttX implementation passes through the `BCH` and `FTL` layers, which appropriately handle the write alignment restrictions of the underlying MTD. So The NuttX implementation of `flash_area_align()` is able to return a fixed value of 1 byte, even if the MTD does not support byte operations. |
| 46 | |
| 47 | ## Limitations |
| 48 | |
| 49 | ### `<flash_map_backend/flash_map_backend.h>` functions are not multitasking-safe |
| 50 | |
| 51 | MCUboot's documentation imposes no restrictions regarding the usage of its public interfaces, which doesn't mean they are thread-safe. |
| 52 | But, regarding NuttX implementation of the `<flash_map_backend/flash_map_backend.h>`, it is safe to state that they are **not** multitasking-safe. NuttX implementation manages the MTD partitions via character device drivers. As file-descriptors cannot be shared between different tasks, if one task calls `flash_area_open` and another task calls `flash_area_<read/write/close>` passing the same `struct flash_area` instance, it will result in failure. |