boot/zephyr: Allow single image applications

The change enables usage of single image applications. This can be used
when user does not need multiple boot images and wants to use more flash
are for main application or other purposes.

Signed-off-by: Dominik Ermel <dominik.ermel@nordicsemi.no>
This commit is contained in:
Dominik Ermel 2020-05-19 13:01:16 +00:00 committed by David Brown
parent 24d93738d5
commit 8101c0cd4e
6 changed files with 177 additions and 16 deletions

View File

@ -92,20 +92,31 @@ endif()
# Generic bootutil sources and includes.
zephyr_library_include_directories(${BOOT_DIR}/bootutil/include)
zephyr_library_sources(
${BOOT_DIR}/bootutil/src/image_validate.c
${BOOT_DIR}/bootutil/src/tlv.c
${BOOT_DIR}/bootutil/src/encrypted.c
${BOOT_DIR}/bootutil/src/image_rsa.c
${BOOT_DIR}/bootutil/src/image_ec256.c
${BOOT_DIR}/bootutil/src/image_ed25519.c
)
if(CONFIG_SINGLE_IMAGE_DFU)
zephyr_library_sources(
${BOOT_DIR}/zephyr/single_loader.c
)
zephyr_library_include_directories(${BOOT_DIR}/bootutil/src)
else()
zephyr_library_sources(
${BOOT_DIR}/bootutil/src/loader.c
${BOOT_DIR}/bootutil/src/swap_misc.c
${BOOT_DIR}/bootutil/src/swap_scratch.c
${BOOT_DIR}/bootutil/src/swap_move.c
${BOOT_DIR}/bootutil/src/bootutil_misc.c
${BOOT_DIR}/bootutil/src/image_validate.c
${BOOT_DIR}/bootutil/src/encrypted.c
${BOOT_DIR}/bootutil/src/image_rsa.c
${BOOT_DIR}/bootutil/src/image_ec256.c
${BOOT_DIR}/bootutil/src/image_ed25519.c
${BOOT_DIR}/bootutil/src/caps.c
${BOOT_DIR}/bootutil/src/tlv.c
)
endif()
if(CONFIG_BOOT_SIGNATURE_TYPE_ECDSA_P256 OR CONFIG_BOOT_ENCRYPT_EC256)
zephyr_library_include_directories(

View File

@ -57,9 +57,11 @@ int flash_area_id_from_multi_image_slot(int image_index, int slot)
{
switch (slot) {
case 0: return FLASH_AREA_IMAGE_PRIMARY(image_index);
#if !defined(CONFIG_SINGLE_IMAGE_DFU)
case 1: return FLASH_AREA_IMAGE_SECONDARY(image_index);
#if !defined(CONFIG_BOOT_SWAP_USING_MOVE)
case 2: return FLASH_AREA_IMAGE_SCRATCH;
#endif
#endif
}
@ -76,9 +78,11 @@ int flash_area_id_to_multi_image_slot(int image_index, int area_id)
if (area_id == FLASH_AREA_IMAGE_PRIMARY(image_index)) {
return 0;
}
#if !defined(CONFIG_SINGLE_IMAGE_DFU)
if (area_id == FLASH_AREA_IMAGE_SECONDARY(image_index)) {
return 1;
}
#endif
BOOT_LOG_ERR("invalid flash area ID");
return -1;

View File

@ -58,18 +58,30 @@
#define MCUBOOT_OVERWRITE_ONLY_FAST
#endif
#ifdef CONFIG_SINGLE_IMAGE_DFU
#define MCUBOOT_SINGLE_IMAGE_DFU 1
#else
#ifdef CONFIG_BOOT_SWAP_USING_MOVE
#define MCUBOOT_SWAP_USING_MOVE 1
#endif
#ifdef CONFIG_LOG
#define MCUBOOT_HAVE_LOGGING 1
#ifdef CONFIG_UPDATEABLE_IMAGE_NUMBER
#define MCUBOOT_IMAGE_NUMBER CONFIG_UPDATEABLE_IMAGE_NUMBER
#else
#define MCUBOOT_IMAGE_NUMBER 1
#endif
#ifdef CONFIG_BOOT_SWAP_SAVE_ENCTLV
#define MCUBOOT_SWAP_SAVE_ENCTLV 1
#endif
#endif /* CONFIG_SINGLE_IMAGE_DFU */
#ifdef CONFIG_LOG
#define MCUBOOT_HAVE_LOGGING 1
#endif
#ifdef CONFIG_BOOT_ENCRYPT_RSA
#define MCUBOOT_ENC_IMAGES
#define MCUBOOT_ENCRYPT_RSA
@ -93,12 +105,6 @@
#define MCUBOOT_USE_BENCH 1
#endif
#ifdef CONFIG_UPDATEABLE_IMAGE_NUMBER
#define MCUBOOT_IMAGE_NUMBER CONFIG_UPDATEABLE_IMAGE_NUMBER
#else
#define MCUBOOT_IMAGE_NUMBER 1
#endif
#ifdef CONFIG_MCUBOOT_DOWNGRADE_PREVENTION
#define MCUBOOT_DOWNGRADE_PREVENTION 1
#endif

View File

@ -6,6 +6,8 @@
#include <devicetree.h>
#include <mcuboot_config/mcuboot_config.h>
#ifndef CONFIG_SINGLE_IMAGE_DFU
#if (MCUBOOT_IMAGE_NUMBER == 1)
/*
* NOTE: the definition below returns the same values for true/false on
@ -41,4 +43,16 @@
#define FLASH_AREA_IMAGE_SCRATCH FLASH_AREA_ID(image_scratch)
#endif
#else /* CONFIG_SINGLE_IMAGE_DFU */
#define FLASH_AREA_IMAGE_PRIMARY(x) FLASH_AREA_ID(image_0)
#define FLASH_AREA_IMAGE_SECONDARY(x) FLASH_AREA_ID(image_0)
/* NOTE: Scratch parition is not used by single image DFU but some of
* functions in common files reference it, so the definitions has been
* provided to allow compilation of common units.
*/
#define FLASH_AREA_IMAGE_SCRATCH 0
#endif /* CONFIG_SINGLE_IMAGE_DFU */
#endif /* __SYSFLASH_H__ */

View File

@ -37,8 +37,8 @@
(defined(CONFIG_XTENSA) && !defined(JEDEC_SPI_NOR_0_LABEL)) || \
!defined(FLASH_ALIGN) || \
!(FLASH_AREA_LABEL_EXISTS(image_0)) || \
!(FLASH_AREA_LABEL_EXISTS(image_1)) || \
(!defined(CONFIG_BOOT_SWAP_USING_MOVE) && !(FLASH_AREA_LABEL_EXISTS(image_scratch)))
!(FLASH_AREA_LABEL_EXISTS(image_1) || CONFIG_SINGLE_IMAGE_DFU) || \
(!defined(CONFIG_BOOT_SWAP_USING_MOVE) && !FLASH_AREA_LABEL_EXISTS(image_scratch) && !defined(CONFIG_SINGLE_IMAGE_DFU))
#error "Target support is incomplete; cannot build mcuboot."
#endif

126
boot/zephyr/single_loader.c Normal file
View File

@ -0,0 +1,126 @@
/*
* SPDX-License-Identifier: Apache-2.0
*
* Copyright (c) 2020 Nordic Semiconductor ASA
*/
#include <assert.h>
#include "bootutil/image.h"
#include "bootutil_priv.h"
#include "bootutil/bootutil_log.h"
#include "mcuboot_config/mcuboot_config.h"
MCUBOOT_LOG_MODULE_DECLARE(mcuboot);
/* Variables passed outside of unit via poiters. */
static const struct flash_area *_fa_p;
static struct image_header _hdr = { 0 };
#ifdef MCUBOOT_VALIDATE_PRIMARY_SLOT
/**
* Validate hash of a primary boot image.
*
* @param[in] fa_p flash area pointer
* @param[in] hdr boot image header pointer
*
* @return 0 on success, error code otherwise
*/
inline static int
boot_image_validate(const struct flash_area *fa_p,
struct image_header *hdr)
{
static uint8_t tmpbuf[BOOT_TMPBUF_SZ];
/* NOTE: The enc-state pointer may be NULL only because when there is
* only one image (BOOT_IMAGE_NUMBER == 1), the code that uses the
* pointer, within bootutil_img_validate and down the call path,
* is excluded from compilation.
*/
/* Validate hash */
if (bootutil_img_validate(NULL, 0, hdr, fa_p, tmpbuf,
BOOT_TMPBUF_SZ, NULL, 0, NULL)) {
return BOOT_EBADIMAGE;
}
return 0;
}
#endif /* MCUBOOT_VALIDATE_PRIMARY_SLOT */
/**
* Attempts to load image header from flash; verifies flash header fields.
*
* @param[in] fa_p flash area pointer
* @param[out] hdr buffer for image header
*
* @return 0 on success, error code otherwise
*/
static int
boot_image_load_header(const struct flash_area *fa_p,
struct image_header *hdr)
{
uint32_t size;
int rc = flash_area_read(fa_p, 0, hdr, sizeof *hdr);
if (rc != 0) {
rc = BOOT_EFLASH;
BOOT_LOG_ERR("Failed reading image header");
return BOOT_EFLASH;
}
if (hdr->ih_magic != IMAGE_MAGIC) {
BOOT_LOG_ERR("Bad image magic 0x%lx", (unsigned long)hdr->ih_magic);
return BOOT_EBADIMAGE;
}
if (hdr->ih_flags & IMAGE_F_NON_BOOTABLE) {
BOOT_LOG_ERR("Image not bootable");
return BOOT_EBADIMAGE;
}
if (!boot_u32_safe_add(&size, hdr->ih_img_size, hdr->ih_hdr_size) ||
size >= fa_p->fa_size) {
return BOOT_EBADIMAGE;
}
return 0;
}
/**
* Gather information on image and prepare for booting.
*
* @parami[out] rsp Parameters for booting image, on success
*
* @return 0 on success, error code otherwise.
*/
int
boot_go(struct boot_rsp *rsp)
{
int rc = -1;
rc = flash_area_open(FLASH_AREA_IMAGE_PRIMARY(0), &_fa_p);
assert(rc == 0);
rc = boot_image_load_header(_fa_p, &_hdr);
if (rc != 0)
goto out;
#ifdef MCUBOOT_VALIDATE_PRIMARY_SLOT
rc = boot_image_validate(_fa_p, &_hdr);
if (rc != 0) {
goto out;
}
#endif /* MCUBOOT_VALIDATE_PRIMARY_SLOT */
rsp->br_flash_dev_id = _fa_p->fa_device_id;
rsp->br_image_off = _fa_p->fa_off;
rsp->br_hdr = &_hdr;
out:
flash_area_close(_fa_p);
return rc;
}