diff --git a/boot/zephyr/CMakeLists.txt b/boot/zephyr/CMakeLists.txt index 3737157c..121e5842 100644 --- a/boot/zephyr/CMakeLists.txt +++ b/boot/zephyr/CMakeLists.txt @@ -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( diff --git a/boot/zephyr/flash_map_extended.c b/boot/zephyr/flash_map_extended.c index 4723af18..c77f96cf 100644 --- a/boot/zephyr/flash_map_extended.c +++ b/boot/zephyr/flash_map_extended.c @@ -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; diff --git a/boot/zephyr/include/mcuboot_config/mcuboot_config.h b/boot/zephyr/include/mcuboot_config/mcuboot_config.h index a6420883..044ec3d5 100644 --- a/boot/zephyr/include/mcuboot_config/mcuboot_config.h +++ b/boot/zephyr/include/mcuboot_config/mcuboot_config.h @@ -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 diff --git a/boot/zephyr/include/sysflash/sysflash.h b/boot/zephyr/include/sysflash/sysflash.h index 66dce1d2..f651779a 100644 --- a/boot/zephyr/include/sysflash/sysflash.h +++ b/boot/zephyr/include/sysflash/sysflash.h @@ -6,6 +6,8 @@ #include #include +#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__ */ diff --git a/boot/zephyr/include/target.h b/boot/zephyr/include/target.h index 2e0f5fda..d585b9c5 100644 --- a/boot/zephyr/include/target.h +++ b/boot/zephyr/include/target.h @@ -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 diff --git a/boot/zephyr/single_loader.c b/boot/zephyr/single_loader.c new file mode 100644 index 00000000..258d38be --- /dev/null +++ b/boot/zephyr/single_loader.c @@ -0,0 +1,126 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * Copyright (c) 2020 Nordic Semiconductor ASA + */ + +#include +#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; +}