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);
+}