Infineon: Add cyw20829 platform, shared slot feature, json memory map, psoc6 xip
Based in 1.8.0 release of MCUBoot library
This commit adds CYW20829 Infineon platform support with following capabilities:
1. Overwrite and swap upgrade mode support
2. Multi-image with up to 4 images
3. Hardware security counter is supported for CYW20829 platform
Add XIP support for PSOC6 platform - place BOOT slot in external memory and execute it in place using SMIF in XIP mode
and some new features for Infineon devices.
1. Shared upgrade slot feature - use one shared area for upgrade slots of multiple images
2. Memory map defined using JSON file - define memory regions for bootloader and user app in conventional way using JSON file
diff --git a/boot/bootutil/src/bootutil_public.c b/boot/bootutil/src/bootutil_public.c
index 6057b41..f045fae 100644
--- a/boot/bootutil/src/bootutil_public.c
+++ b/boot/bootutil/src/bootutil_public.c
@@ -3,7 +3,7 @@
*
* Copyright (c) 2017-2019 Linaro LTD
* Copyright (c) 2016-2019 JUUL Labs
- * Copyright (c) 2019-2020 Arm Limited
+ * Copyright (c) 2019-2021 Arm Limited
* Copyright (c) 2020 Nordic Semiconductor ASA
*
* Original license:
@@ -51,10 +51,12 @@
#include "bootutil/enc_key_public.h"
#endif
+#include "bootutil/boot_public_hooks.h"
+
#ifdef CONFIG_MCUBOOT
-MCUBOOT_LOG_MODULE_DECLARE(mcuboot);
+BOOT_LOG_MODULE_DECLARE(mcuboot);
#else
-MCUBOOT_LOG_MODULE_REGISTER(mcuboot_util);
+BOOT_LOG_MODULE_REGISTER(mcuboot_util);
#endif
const uint32_t boot_img_magic[] = {
@@ -142,7 +144,7 @@
static inline uint32_t
boot_magic_off(const struct flash_area *fap)
{
- return fap->fa_size - BOOT_MAGIC_SZ;
+ return flash_area_get_size(fap) - BOOT_MAGIC_SZ;
}
static inline uint32_t
@@ -172,15 +174,14 @@
* @param val The magic value in a trailer, encoded as a
* BOOT_MAGIC_[...].
*
- * @return 1 if the two values are compatible;
- * 0 otherwise.
+ * @return true - if the two values are compatible;
+ * false - otherwise.
*/
-int
-boot_magic_compatible_check(uint8_t tbl_val, uint8_t val)
+bool boot_magic_compatible_check(uint8_t tbl_val, uint8_t val)
{
switch (tbl_val) {
case BOOT_MAGIC_ANY:
- return 1;
+ return true;
case BOOT_MAGIC_NOTGOOD:
return val != BOOT_MAGIC_GOOD;
@@ -190,20 +191,16 @@
}
}
-bool bootutil_buffer_is_erased(const struct flash_area *area,
- const void *buffer, size_t len)
+bool bootutil_buffer_is_filled(const void *buffer, uint8_t fill, size_t len)
{
- size_t i;
- uint8_t *u8b;
- uint8_t erased_val;
+ uint8_t *p;
if (buffer == NULL || len == 0) {
return false;
}
- erased_val = flash_area_erased_val(area);
- for (i = 0, u8b = (uint8_t *)buffer; i < len; i++) {
- if (u8b[i] != erased_val) {
+ for (p = (uint8_t *)buffer; len-- > 0; p++) {
+ if (*p != fill) {
return false;
}
}
@@ -211,16 +208,30 @@
return true;
}
+bool bootutil_buffer_is_erased(const struct flash_area *area,
+ const void *buffer, size_t len)
+{
+ uint8_t erased_val;
+
+ if (area == NULL) {
+ return false;
+ }
+
+ erased_val = flash_area_erased_val(area);
+
+ return bootutil_buffer_is_filled(buffer, erased_val, len);
+}
+
static int
boot_read_flag(const struct flash_area *fap, uint8_t *flag, uint32_t off)
{
int rc;
rc = flash_area_read(fap, off, flag, sizeof *flag);
- if (rc < 0) {
+ if (rc != 0) {
return BOOT_EFLASH;
}
- if (bootutil_buffer_is_erased(fap, flag, sizeof *flag)) {
+ if (*flag == flash_area_erased_val(fap)) {
*flag = BOOT_FLAG_UNSET;
} else {
*flag = boot_flag_decode(*flag);
@@ -248,7 +259,7 @@
off = boot_magic_off(fap);
rc = flash_area_read(fap, off, magic, BOOT_MAGIC_SZ);
- if (rc < 0) {
+ if (rc != 0) {
return BOOT_EFLASH;
}
if (bootutil_buffer_is_erased(fap, magic, BOOT_MAGIC_SZ)) {
@@ -259,7 +270,7 @@
off = boot_swap_info_off(fap);
rc = flash_area_read(fap, off, &swap_info, sizeof swap_info);
- if (rc < 0) {
+ if (rc != 0) {
return BOOT_EFLASH;
}
@@ -267,14 +278,14 @@
state->swap_type = BOOT_GET_SWAP_TYPE(swap_info);
state->image_num = BOOT_GET_IMAGE_NUM(swap_info);
- if (bootutil_buffer_is_erased(fap, &swap_info, sizeof swap_info) ||
+ if (swap_info == flash_area_erased_val(fap) ||
state->swap_type > BOOT_SWAP_TYPE_REVERT) {
state->swap_type = BOOT_SWAP_TYPE_NONE;
state->image_num = 0;
}
rc = boot_read_copy_done(fap, &state->copy_done);
- if (rc) {
+ if (rc != 0) {
return BOOT_EFLASH;
}
@@ -286,7 +297,7 @@
int
boot_read_swap_state_by_id(int flash_area_id, struct boot_swap_state *state)
{
- const struct flash_area *fap;
+ const struct flash_area *fap = NULL;
int rc;
rc = flash_area_open(flash_area_id, &fap);
@@ -309,9 +320,9 @@
off = boot_magic_off(fap);
- BOOT_LOG_DBG("writing magic; fa_id=%d off=0x%lx (0x%lx)",
- fap->fa_id, (unsigned long)off,
- (unsigned long)(fap->fa_off + off));
+ BOOT_LOG_DBG("writing magic; fa_id=%u off=0x%" PRIx32
+ " (0x%" PRIx32 ")", (unsigned)flash_area_get_id(fap),
+ off, flash_area_get_off(fap) + off);
rc = flash_area_write(fap, off, boot_img_magic, BOOT_MAGIC_SZ);
if (rc != 0) {
return BOOT_EFLASH;
@@ -330,11 +341,14 @@
const uint8_t *inbuf, uint8_t inlen)
{
uint8_t buf[BOOT_MAX_ALIGN];
- uint8_t align;
+ size_t align;
uint8_t erased_val;
int rc;
align = flash_area_align(fap);
+ if (align == 0u) {
+ return BOOT_EFLASH;
+ }
align = (inlen + align - 1) & ~(align - 1);
if (align > BOOT_MAX_ALIGN) {
return -1;
@@ -368,9 +382,9 @@
uint32_t off;
off = boot_image_ok_off(fap);
- BOOT_LOG_DBG("writing image_ok; fa_id=%d off=0x%lx (0x%lx)",
- fap->fa_id, (unsigned long)off,
- (unsigned long)(fap->fa_off + off));
+ BOOT_LOG_DBG("writing image_ok; fa_id=%u off=0x%" PRIx32
+ " (0x%" PRIx32 ")", (unsigned)flash_area_get_id(fap),
+ off, flash_area_get_off(fap) + off);
return boot_write_trailer_flag(fap, off, BOOT_FLAG_SET);
}
@@ -394,23 +408,23 @@
BOOT_SET_SWAP_INFO(swap_info, image_num, swap_type);
off = boot_swap_info_off(fap);
- BOOT_LOG_DBG("writing swap_info; fa_id=%d off=0x%lx (0x%lx), swap_type=0x%x"
- " image_num=0x%x",
- fap->fa_id, (unsigned long)off,
- (unsigned long)(fap->fa_off + off), swap_type, image_num);
+ BOOT_LOG_DBG("writing swap_info; fa_id=%u off=0x%" PRIx32
+ " (0x%" PRIx32 "), swap_type=0x%x image_num=0x%x",
+ (unsigned)flash_area_get_id(fap), off,
+ flash_area_get_off(fap) + off,
+ (unsigned)swap_type, (unsigned)image_num);
return boot_write_trailer(fap, off, (const uint8_t *) &swap_info, 1);
}
-#define BOOT_LOG_SWAP_STATE(area, state) \
- BOOT_LOG_INF("%s: magic=%s, swap_type=0x%x, copy_done=0x%x, " \
- "image_ok=0x%x", \
- (area), \
- ((state)->magic == BOOT_MAGIC_GOOD ? "good" : \
- (state)->magic == BOOT_MAGIC_UNSET ? "unset" : \
- "bad"), \
- (state)->swap_type, \
- (state)->copy_done, \
- (state)->image_ok)
+#define BOOT_LOG_SWAP_STATE(area, state) \
+ BOOT_LOG_INF("%s: magic=%s, swap_type=0x%x, copy_done=0x%x, image_ok=0x%x", \
+ (area), \
+ ((state)->magic == BOOT_MAGIC_GOOD ? "good" : \
+ (state)->magic == BOOT_MAGIC_UNSET ? "unset" : \
+ "bad"), \
+ (unsigned)(state)->swap_type, \
+ (unsigned)(state)->copy_done, \
+ (unsigned)(state)->image_ok)
int
boot_swap_type_multi(int image_index)
@@ -421,15 +435,28 @@
int rc;
size_t i;
- rc = boot_read_swap_state_by_id(FLASH_AREA_IMAGE_PRIMARY(image_index),
- &primary_slot);
+ rc = BOOT_HOOK_CALL(boot_read_swap_state_primary_slot_hook,
+ BOOT_HOOK_REGULAR, image_index, &primary_slot);
+ if (rc == BOOT_HOOK_REGULAR)
+ {
+ rc = boot_read_swap_state_by_id(FLASH_AREA_IMAGE_PRIMARY(image_index),
+ &primary_slot);
+ }
if (rc) {
return BOOT_SWAP_TYPE_PANIC;
}
rc = boot_read_swap_state_by_id(FLASH_AREA_IMAGE_SECONDARY(image_index),
&secondary_slot);
- if (rc) {
+ if (rc == BOOT_EFLASH) {
+ BOOT_LOG_INF("Secondary image of image pair (%d.) "
+ "is unreachable. Treat it as empty", image_index);
+ secondary_slot.magic = BOOT_MAGIC_UNSET;
+ secondary_slot.swap_type = BOOT_SWAP_TYPE_NONE;
+ secondary_slot.copy_done = BOOT_FLAG_UNSET;
+ secondary_slot.image_ok = BOOT_FLAG_UNSET;
+ secondary_slot.image_num = 0;
+ } else if (rc) {
return BOOT_SWAP_TYPE_PANIC;
}
@@ -478,42 +505,44 @@
}
/**
- * Marks the image in the secondary slot as pending. On the next reboot,
- * the system will perform a one-time boot of the the secondary slot image.
+ * Marks the image with the given index in the secondary slot as pending. On the
+ * next reboot, the system will perform a one-time boot of the the secondary
+ * slot image.
+ *
+ * @param image_index Image pair index.
*
* @param permanent Whether the image should be used permanently or
- * only tested once:
- * 0=run image once, then confirm or revert.
- * 1=run image forever.
+ * only tested once:
+ * 0=run image once, then confirm or revert.
+ * 1=run image forever.
*
* @return 0 on success; nonzero on failure.
*/
int
-boot_set_pending(int permanent)
+boot_set_pending_multi(int image_index, int permanent)
{
- const struct flash_area *fap;
- struct boot_swap_state state_secondary_slot;
+ const struct flash_area *fap = NULL;
+ struct boot_swap_state state_secondary_slot = {0};
uint8_t swap_type;
int rc;
- rc = boot_read_swap_state_by_id(FLASH_AREA_IMAGE_SECONDARY(0),
- &state_secondary_slot);
+ rc = flash_area_open(FLASH_AREA_IMAGE_SECONDARY(image_index), &fap);
if (rc != 0) {
- return rc;
+ return BOOT_EFLASH;
+ }
+
+ rc = boot_read_swap_state(fap, &state_secondary_slot);
+ if (rc != 0) {
+ goto done;
}
switch (state_secondary_slot.magic) {
case BOOT_MAGIC_GOOD:
/* Swap already scheduled. */
- return 0;
+ break;
case BOOT_MAGIC_UNSET:
- rc = flash_area_open(FLASH_AREA_IMAGE_SECONDARY(0), &fap);
- if (rc != 0) {
- rc = BOOT_EFLASH;
- } else {
- rc = boot_write_magic(fap);
- }
+ rc = boot_write_magic(fap);
if (rc == 0 && permanent) {
rc = boot_write_image_ok(fap);
@@ -528,46 +557,69 @@
rc = boot_write_swap_info(fap, swap_type, 0);
}
- flash_area_close(fap);
- return rc;
+ break;
case BOOT_MAGIC_BAD:
/* The image slot is corrupt. There is no way to recover, so erase the
* slot to allow future upgrades.
*/
- rc = flash_area_open(FLASH_AREA_IMAGE_SECONDARY(0), &fap);
- if (rc != 0) {
- return BOOT_EFLASH;
- }
-
- flash_area_erase(fap, 0, fap->fa_size);
- flash_area_close(fap);
- return BOOT_EBADIMAGE;
+ flash_area_erase(fap, 0, flash_area_get_size(fap));
+ rc = BOOT_EBADIMAGE;
+ break;
default:
assert(0);
- return BOOT_EBADIMAGE;
+ rc = BOOT_EBADIMAGE;
}
+
+done:
+ flash_area_close(fap);
+ return rc;
}
/**
- * Marks the image in the primary slot as confirmed. The system will continue
- * booting into the image in the primary slot until told to boot from a
- * different slot.
+ * Marks the image with index 0 in the secondary slot as pending. On the next
+ * reboot, the system will perform a one-time boot of the the secondary slot
+ * image. Note that this API is kept for compatibility. The
+ * boot_set_pending_multi() API is recommended.
+ *
+ * @param permanent Whether the image should be used permanently or
+ * only tested once:
+ * 0=run image once, then confirm or revert.
+ * 1=run image forever.
*
* @return 0 on success; nonzero on failure.
*/
int
-boot_set_confirmed(void)
+boot_set_pending(int permanent)
{
- const struct flash_area *fap;
- struct boot_swap_state state_primary_slot;
+ return boot_set_pending_multi(0, permanent);
+}
+
+/**
+ * Marks the image with the given index in the primary slot as confirmed. The
+ * system will continue booting into the image in the primary slot until told to
+ * boot from a different slot.
+ *
+ * @param image_index Image pair index.
+ *
+ * @return 0 on success; nonzero on failure.
+ */
+int
+boot_set_confirmed_multi(int image_index)
+{
+ const struct flash_area *fap = NULL;
+ struct boot_swap_state state_primary_slot = {0};
int rc;
- rc = boot_read_swap_state_by_id(FLASH_AREA_IMAGE_PRIMARY(0),
- &state_primary_slot);
+ rc = flash_area_open(FLASH_AREA_IMAGE_PRIMARY(image_index), &fap);
if (rc != 0) {
- return rc;
+ return BOOT_EFLASH;
+ }
+
+ rc = boot_read_swap_state(fap, &state_primary_slot);
+ if (rc != 0) {
+ goto done;
}
switch (state_primary_slot.magic) {
@@ -577,25 +629,19 @@
case BOOT_MAGIC_UNSET:
/* Already confirmed. */
- return 0;
+ goto done;
case BOOT_MAGIC_BAD:
/* Unexpected state. */
- return BOOT_EBADVECT;
- }
-
- rc = flash_area_open(FLASH_AREA_IMAGE_PRIMARY(0), &fap);
- if (rc) {
- rc = BOOT_EFLASH;
- goto done;
- }
-
- if (state_primary_slot.copy_done == BOOT_FLAG_UNSET) {
- /* Swap never completed. This is unexpected. */
rc = BOOT_EBADVECT;
goto done;
}
+ /* Intentionally do not check copy_done flag
+ * so can confirm a padded image which was programed using a programing
+ * interface.
+ */
+
if (state_primary_slot.image_ok != BOOT_FLAG_UNSET) {
/* Already confirmed. */
goto done;
@@ -607,3 +653,17 @@
flash_area_close(fap);
return rc;
}
+
+/**
+ * Marks the image with index 0 in the primary slot as confirmed. The system
+ * will continue booting into the image in the primary slot until told to boot
+ * from a different slot. Note that this API is kept for compatibility. The
+ * boot_set_confirmed_multi() API is recommended.
+ *
+ * @return 0 on success; nonzero on failure.
+ */
+int
+boot_set_confirmed(void)
+{
+ return boot_set_confirmed_multi(0);
+}