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/swap_status_part.c b/boot/bootutil/src/swap_status_part.c
index a2899a9..f6be047 100644
--- a/boot/bootutil/src/swap_status_part.c
+++ b/boot/bootutil/src/swap_status_part.c
@@ -26,97 +26,83 @@
  * under the License.
  */
 
-#include <assert.h>
 #include "crc32c.h"
 #include <string.h>
+#include <stdlib.h>
 #include "swap_status.h"
 
 #ifdef MCUBOOT_SWAP_USING_STATUS
 
-#define IMAGE_0_STATUS_OFFS        0
-#define IMAGE_0_STATUS_SIZE        (BOOT_SWAP_STATUS_SIZE)
-
-#define IMAGE_1_STATUS_OFFS        (IMAGE_0_STATUS_OFFS + IMAGE_0_STATUS_SIZE)
-#define IMAGE_1_STATUS_SIZE        (BOOT_SWAP_STATUS_SIZE)
-
-#define SCRATCH_STATUS_OFFS        (IMAGE_1_STATUS_OFFS + BOOT_SWAP_STATUS_SIZE)
-#ifdef MCUBOOT_SWAP_USING_SCRATCH
-#define SCRATCH_STATUS_SIZE        (BOOT_SWAP_STATUS_SIZE)
-#else
-#define SCRATCH_STATUS_SIZE        0
-#endif
-
-#if (MCUBOOT_IMAGE_NUMBER == 2)
-#define IMAGE_2_STATUS_OFFS        (SCRATCH_STATUS_OFFS + SCRATCH_STATUS_SIZE)
-#define IMAGE_2_STATUS_SIZE        (BOOT_SWAP_STATUS_SIZE)
-
-#define IMAGE_3_STATUS_OFFS        (IMAGE_2_STATUS_OFFS + IMAGE_2_STATUS_SIZE)
-#define IMAGE_3_STATUS_SIZE        (BOOT_SWAP_STATUS_SIZE)
-#endif
+static uint8_t record_buff[BOOT_SWAP_STATUS_ROW_SZ];
+static uint8_t status_buff[BOOT_SWAP_STATUS_PAYLD_SZ];
 
 const uint32_t stat_part_magic[] = {
     BOOT_SWAP_STATUS_MAGIC
 };
 
-uint32_t calc_rec_idx(uint32_t value)
+static inline uint32_t calc_rec_idx(uint32_t value)
 {
-    uint32_t rec_idx;
-
-    rec_idx = value/BOOT_SWAP_STATUS_PAYLD_SZ;
-
-    return rec_idx;
+    return value / BOOT_SWAP_STATUS_PAYLD_SZ;
 }
 
-uint32_t calc_record_offs(uint32_t offs)
+static inline uint32_t calc_record_offs(uint32_t offs)
 {
-    uint32_t rec_offs;
-
-    rec_offs = BOOT_SWAP_STATUS_ROW_SZ*calc_rec_idx(offs);
-
-    return rec_offs;
+    return BOOT_SWAP_STATUS_ROW_SZ * calc_rec_idx(offs);
 }
 
-uint32_t calc_record_crc(const uint8_t *data, uint32_t length)
+static inline uint32_t calc_record_crc(const uint8_t *data, uint32_t length)
 {
-    uint32_t crc;
-
-    crc = crc32c_checksum(data, length);
-
-    return crc;
+    return crc32c_checksum(data, length);
 }
 
-int32_t swap_status_init_offset(uint32_t area_id)
+static inline uint32_t pack_bytes_u32(const uint8_t *data)
 {
-    int32_t offset = -1;
-    /* calculate an offset caused by area type: primary_x/secondary_x */
-    switch (area_id) {
-    case FLASH_AREA_IMAGE_0:
-        offset = (int)IMAGE_0_STATUS_OFFS;
-        break;
-    case FLASH_AREA_IMAGE_1:
-        offset = (int)IMAGE_1_STATUS_OFFS;
-        break;
+    uint32_t result = 0U;
+
+    result = ((uint32_t)data[3U] << 24U) | ((uint32_t)data[2U] << 16U) |
+             ((uint32_t)data[1U] << 8U) | (uint32_t)data[0U];
+
+    return result;
+}
+
+int32_t swap_status_init_offset(uint8_t area_id)
+{
+    uint8_t order[] = {
+        FLASH_AREA_IMAGE_PRIMARY(0U)
+      , FLASH_AREA_IMAGE_SECONDARY(0U)
 #ifdef MCUBOOT_SWAP_USING_SCRATCH
-    case FLASH_AREA_IMAGE_SCRATCH:
-        offset = (int)SCRATCH_STATUS_OFFS;
-        break;
-#endif
-#if (MCUBOOT_IMAGE_NUMBER == 2)
-    case FLASH_AREA_IMAGE_2:
-        offset = (int)IMAGE_2_STATUS_OFFS;
-        break;
-    case FLASH_AREA_IMAGE_3:
-        offset = (int)IMAGE_3_STATUS_OFFS;
-        break;
-#endif
-    default:
-        offset = -1;
-        break;
+      , FLASH_AREA_IMAGE_SCRATCH
+#endif /* MCUBOOT_SWAP_USING_SCRATCH */
+#if BOOT_IMAGE_NUMBER >= 2
+      , FLASH_AREA_IMAGE_PRIMARY(1U)
+      , FLASH_AREA_IMAGE_SECONDARY(1U)
+#endif /* BOOT_IMAGE_NUMBER >= 2 */
+#if BOOT_IMAGE_NUMBER >= 3
+      , FLASH_AREA_IMAGE_PRIMARY(2U)
+      , FLASH_AREA_IMAGE_SECONDARY(2U)
+#endif /* BOOT_IMAGE_NUMBER >= 3 */
+#if BOOT_IMAGE_NUMBER == 4
+      , FLASH_AREA_IMAGE_PRIMARY(3U)
+      , FLASH_AREA_IMAGE_SECONDARY(3U)
+#endif /* BOOT_IMAGE_NUMBER == 4 */
+    };
+
+    int32_t result = -1;
+    int32_t offset = 0;
+    uint32_t i;
+
+    for (i = 0U; i < sizeof(order) / sizeof(order[0U]); i++) {
+        if (order[i] == area_id) {
+            result = offset;
+            break;
+        }
+        offset += BOOT_SWAP_STATUS_SIZE;
     }
-    return offset;
+
+    return result;
 }
 
-int swap_status_read_record(uint32_t rec_offset, uint8_t *data, uint32_t *copy_counter)
+static int swap_status_read_record(uint32_t rec_offset, uint8_t *data, uint32_t *copy_counter, uint32_t *max_idx)
 { /* returns BOOT_SWAP_STATUS_PAYLD_SZ of data */
     int rc = -1;
 
@@ -127,60 +113,56 @@
     uint32_t magic_fail = 0;
     uint32_t max_cnt = 0;
 
-    int32_t max_idx = 0;
-
-    uint8_t buff[BOOT_SWAP_STATUS_ROW_SZ];
-
     const struct flash_area *fap_stat = NULL;
 
     rc = flash_area_open(FLASH_AREA_IMAGE_SWAP_STATUS, &fap_stat);
     if (rc != 0) {
-        return BOOT_EFLASH;
+        return -1;
     }
+    else {
+        /* loop over copies/duplicates */
+        for (uint32_t i = 0; i < BOOT_SWAP_STATUS_MULT; i++) {
+            /* calculate final duplicate offset */
+            fin_offset = rec_offset + i * BOOT_SWAP_STATUS_D_SIZE;
 
-    /* loop over copies/duplicates */
-    for(uint32_t i = 0; i<BOOT_SWAP_STATUS_MULT; i++) {
-        /* calculate final duplicate offset */
-        fin_offset = rec_offset + i*BOOT_SWAP_STATUS_D_SIZE;
-
-        rc = flash_area_read(fap_stat, fin_offset, buff, sizeof(buff));
-        if (rc != 0) {
-            return BOOT_EFLASH;
-        }
-        /* read magic value to know if area was pre-erased */
-        magic = *((uint32_t *)&buff[BOOT_SWAP_STATUS_ROW_SZ -\
-                                  BOOT_SWAP_STATUS_MGCREC_SZ -\
-                                  BOOT_SWAP_STATUS_CNT_SZ-\
-                                  BOOT_SWAP_STATUS_CRC_SZ]);
-        if (magic == BOOT_SWAP_STATUS_MAGIC) {   /* read CRC */
-            crc = *((uint32_t *)&buff[BOOT_SWAP_STATUS_ROW_SZ -\
-                                      BOOT_SWAP_STATUS_CRC_SZ]);
-            /* check record data integrity first */
-            if (crc == calc_record_crc(buff, BOOT_SWAP_STATUS_ROW_SZ-BOOT_SWAP_STATUS_CRC_SZ)) {
-                /* look for counter */
-                counter = *((uint32_t *)&buff[BOOT_SWAP_STATUS_ROW_SZ -\
-                                              BOOT_SWAP_STATUS_CNT_SZ - \
-                                              BOOT_SWAP_STATUS_CRC_SZ]);
-                /* find out counter max */
-                if (counter >= max_cnt) {
-                    max_cnt = counter;
-                    max_idx = (int32_t)i;
-                    data_offset = fin_offset;
+            rc = flash_area_read(fap_stat, fin_offset, record_buff, sizeof(record_buff));
+            if (rc != 0) {
+                return -1;
+            }
+            else {
+                /* read magic value to know if area was pre-erased */
+                magic = pack_bytes_u32(&record_buff[BOOT_SWAP_STATUS_PAYLD_SZ]);
+                if (magic == BOOT_SWAP_STATUS_MAGIC) {   /* read CRC */
+                    crc = pack_bytes_u32(&record_buff[BOOT_SWAP_STATUS_ROW_SZ -
+                                            BOOT_SWAP_STATUS_CRC_SZ]);
+                    /* check record data integrity first */
+                    if (crc == calc_record_crc(record_buff, BOOT_SWAP_STATUS_ROW_SZ-BOOT_SWAP_STATUS_CRC_SZ)) {
+                        /* look for counter */
+                        counter = pack_bytes_u32(&record_buff[BOOT_SWAP_STATUS_ROW_SZ -
+                                                    BOOT_SWAP_STATUS_CNT_SZ -
+                                                    BOOT_SWAP_STATUS_CRC_SZ]);
+                        /* find out counter max */
+                        if (counter >= max_cnt) {
+                            max_cnt = counter;
+                            *max_idx = i;
+                            data_offset = fin_offset;
+                        }
+                    }
+                    /* if crc != calculated() */
+                    else {
+                        crc_fail++;
+                    }
+                }
+                else {
+                    magic_fail++;
                 }
             }
-            /* if crc != calculated() */
-            else {
-                crc_fail++;
-            }
-        }
-        else {
-            magic_fail++;
         }
     }
     /* no magic found - status area is pre-erased, start from scratch */
     if (magic_fail == BOOT_SWAP_STATUS_MULT) {
         /* emulate last index was received, so next will start from beginning */
-        max_idx = (int32_t)(BOOT_SWAP_STATUS_MULT-1U);
+        *max_idx = BOOT_SWAP_STATUS_MULT - 1U;
         *copy_counter = 0;
         /* return all erased values */
         (void)memset(data, (int32_t)flash_area_erased_val(fap_stat), BOOT_SWAP_STATUS_PAYLD_SZ);
@@ -188,21 +170,21 @@
     else {
         /* no valid CRC found - status pre-read failure */
         if (crc_fail == BOOT_SWAP_STATUS_MULT) {
-            max_idx = -1;
+            rc = -1;
         }
         else {
             *copy_counter = max_cnt;
             /* read payload data */
             rc = flash_area_read(fap_stat, data_offset, data, BOOT_SWAP_STATUS_PAYLD_SZ);
-	        if (rc != 0) {
-	            return BOOT_EFLASH;
-	        }
+            if (rc != 0) {
+                rc = -1;
+            }
         }
     }
     flash_area_close(fap_stat);
 
     /* return back duplicate index */
-    return max_idx;
+    return rc;
 }
 
 static int swap_status_write_record(uint32_t rec_offset, uint32_t copy_num, uint32_t copy_counter, const uint8_t *data)
@@ -214,35 +196,28 @@
     uint32_t next_counter = copy_counter + 1U;
     uint32_t next_crc;
 
-    uint8_t buff[BOOT_SWAP_STATUS_ROW_SZ];
-
     const struct flash_area *fap_stat = NULL;
 
     rc = flash_area_open(FLASH_AREA_IMAGE_SWAP_STATUS, &fap_stat);
     if (rc != 0) {
-        return BOOT_EFLASH;
+        return -1;
     }
 
     /* copy data into buffer */
-    (void)memcpy(buff, data, BOOT_SWAP_STATUS_PAYLD_SZ);
+    (void)memcpy(record_buff, data, BOOT_SWAP_STATUS_PAYLD_SZ);
     /* append next counter to whole record row */
-    (void)memcpy(&buff[BOOT_SWAP_STATUS_ROW_SZ-BOOT_SWAP_STATUS_CNT_SZ-BOOT_SWAP_STATUS_CRC_SZ], \
-            &next_counter, \
+    (void)memcpy(&record_buff[BOOT_SWAP_STATUS_ROW_SZ-BOOT_SWAP_STATUS_CNT_SZ-BOOT_SWAP_STATUS_CRC_SZ],
+            (uint8_t *)&next_counter,
             BOOT_SWAP_STATUS_CNT_SZ);
     /* append record magic */
-    (void)memcpy(&buff[BOOT_SWAP_STATUS_ROW_SZ-\
-                    BOOT_SWAP_STATUS_MGCREC_SZ-\
-                    BOOT_SWAP_STATUS_CNT_SZ-\
-                    BOOT_SWAP_STATUS_CRC_SZ], \
-                    stat_part_magic, \
-                    BOOT_SWAP_STATUS_MGCREC_SZ);
+    (void)memcpy(&record_buff[BOOT_SWAP_STATUS_PAYLD_SZ], (const uint8_t *)stat_part_magic, BOOT_SWAP_STATUS_MGCREC_SZ);
 
     /* calculate CRC field*/
-    next_crc = calc_record_crc(buff, BOOT_SWAP_STATUS_ROW_SZ-BOOT_SWAP_STATUS_CRC_SZ);
+    next_crc = calc_record_crc(record_buff, BOOT_SWAP_STATUS_ROW_SZ-BOOT_SWAP_STATUS_CRC_SZ);
 
     /* append new CRC to whole record row */
-    (void)memcpy(&buff[BOOT_SWAP_STATUS_ROW_SZ-BOOT_SWAP_STATUS_CRC_SZ], \
-            &next_crc, \
+    (void)memcpy(&record_buff[BOOT_SWAP_STATUS_ROW_SZ-BOOT_SWAP_STATUS_CRC_SZ],
+            (uint8_t *)&next_crc,
             BOOT_SWAP_STATUS_CRC_SZ);
 
     /* we already know what copy number was last and correct */
@@ -256,80 +231,108 @@
     }
     fin_offset = rec_offset + copy_num*BOOT_SWAP_STATUS_D_SIZE;
 
+    /* erase obsolete status record before write */
+    rc = flash_area_erase(fap_stat, fin_offset, sizeof(record_buff));
+    if (rc != 0) {
+        return -1;
+    }
+
     /* write prepared record into flash */
-    rc = flash_area_write(fap_stat, fin_offset, buff, sizeof(buff));
+    rc = flash_area_write(fap_stat, fin_offset, record_buff, sizeof(record_buff));
 
     flash_area_close(fap_stat);
 
     return rc;
 }
 
+static int boot_magic_decode(uint8_t *magic)
+{
+    if (memcmp(magic, (const uint8_t *)boot_img_magic, BOOT_MAGIC_SZ) == 0) {
+        return BOOT_MAGIC_GOOD;
+    }
+    return BOOT_MAGIC_BAD;
+}
+
 /**
  * Updates len bytes of status partition with values from *data-pointer.
  *
- * @param targ_area_id  Target area id for which status is being written.
- *                      Not a status-partition area id.
- * @param offset        Status byte offset inside status table. Should not include CRC and CNT.
- * @param data          Pointer to data status table to needs to be updated with.
- * @param len           Number of bytes to be written
+ * @param target_area_id Target area id for which status is being written.
+ *                       Not a status-partition area id.
+ * @param offset         Status byte offset inside status table. Should not include CRC and CNT.
+ * @param data           Pointer to data status table to needs to be updated with.
+ * @param len            Number of bytes to be written
  *
- * @return              0 on success; nonzero on failure.
+ * @return               0 on success; -1 on failure.
  */
-int swap_status_update(uint32_t targ_area_id, uint32_t offs, const void *data, uint32_t len)
+int swap_status_update(uint8_t target_area_id, uint32_t offs, const void *data, uint32_t len)
 {
     int rc = -1;
 
     int32_t init_offs;
-    int32_t length = (int32_t)len;
-    int32_t copy_num;
+    uint32_t copy_num = 0;
 
     uint32_t rec_offs;
     uint32_t copy_sz;
-    uint32_t copy_counter;
+    uint32_t copy_counter = 0;
     uint32_t data_idx = 0;
-    uint32_t buff_idx = offs%BOOT_SWAP_STATUS_PAYLD_SZ;
+    uint32_t buff_idx = offs % BOOT_SWAP_STATUS_PAYLD_SZ;
 
-    uint8_t buff[BOOT_SWAP_STATUS_PAYLD_SZ];
+    if ((UINT32_MAX - offs) < len) {
+        return -1;
+    }
 
     /* check if end of data is still inside writable area */
-    assert ((int)((offs + len) <= BOOT_SWAP_STATUS_D_SIZE_RAW));
+    if ((offs + len) > BOOT_SWAP_STATUS_D_SIZE_RAW) {
+        return -1;
+    }
 
     /* pre-calculate sub-area offset */
-    init_offs = swap_status_init_offset(targ_area_id);
-    assert ((int)(init_offs >= 0));
+    init_offs = swap_status_init_offset(target_area_id);
+    if (init_offs < 0) {
+        return -1;
+    }
 
     /* will start from it
      * this will be write-aligned */
     rec_offs = (uint32_t)init_offs + calc_record_offs(offs);
 
     /* go over all records to be updated */
-    while (length > 0) {
+    while (len != 0U) {
         /* preserve record */
-        copy_num = swap_status_read_record(rec_offs, buff, &copy_counter);
+        rc = swap_status_read_record(rec_offs, status_buff, &copy_counter, &copy_num);
         /* it returns copy number */
-        if (copy_num < 0)
+        if (rc < 0)
         {   /* something went wrong while read, exit */
             rc = -1;
             break;
         }
         /* update record data */
-        if (length > (int)BOOT_SWAP_STATUS_PAYLD_SZ) {
+        if (len > BOOT_SWAP_STATUS_PAYLD_SZ) {
             copy_sz = BOOT_SWAP_STATUS_PAYLD_SZ - buff_idx;
         }
         else {
-            copy_sz = (uint32_t)length;
+            copy_sz = len;
         }
-        (void)memcpy((void *)&buff[buff_idx], &((uint8_t *)data)[data_idx], copy_sz);
+
+        (void)memcpy(status_buff + buff_idx, (const uint8_t *)data + data_idx, copy_sz);
         buff_idx = 0;
 
         /* write record back */
-        rc = swap_status_write_record(rec_offs, (uint32_t)copy_num, copy_counter, buff);
-        assert ((int)(rc == 0));
+        rc = swap_status_write_record(rec_offs, copy_num, copy_counter, status_buff);
+        if (rc != 0) {
+            break;
+        }
 
         /* proceed to next record */
-        length -= (int32_t)BOOT_SWAP_STATUS_PAYLD_SZ;
-        rec_offs += BOOT_SWAP_STATUS_ROW_SZ;
-        data_idx += BOOT_SWAP_STATUS_PAYLD_SZ;
+        if (len < BOOT_SWAP_STATUS_PAYLD_SZ) {
+            len = 0;
+        }
+        else {
+            len -= BOOT_SWAP_STATUS_PAYLD_SZ;
+            rec_offs += BOOT_SWAP_STATUS_ROW_SZ;
+            data_idx += BOOT_SWAP_STATUS_PAYLD_SZ;
+        }
+
     }
     return rc;
 }
@@ -337,68 +340,206 @@
 /**
  * Reads len bytes of status partition with values from *data-pointer.
  *
- * @param targ_area_id  Target area id for which status is being read.
- *                      Not a status-partition area id.
- * @param offset        Status byte offset inside status table. Should not include CRC and CNT.
- * @param data          Pointer to data where status table values will be written.
- * @param len           Number of bytes to be read from status table.
+ * @param target_area_id Target area id for which status is being read.
+ *                       Not a status-partition area id.
+ * @param offset         Status byte offset inside status table. Should not include CRC and CNT.
+ * @param data           Pointer to data where status table values will be written.
+ * @param len            Number of bytes to be read from status table.
  *
- * @return              0 on success; nonzero on failure.
+ * @return               0 on success; -1 on failure.
  */
-int swap_status_retrieve(uint32_t target_area_id, uint32_t offs, void *data, uint32_t len)
+int swap_status_retrieve(uint8_t target_area_id, uint32_t offs, void *data, uint32_t len)
 {
     int rc = 0;
 
     int32_t init_offs;
-    int32_t length = (int32_t)len;
-    int32_t copy_num;
+    uint32_t copy_num = 0;
 
     uint32_t rec_offs;
     uint32_t copy_sz;
-    uint32_t copy_counter;
+    uint32_t copy_counter = 0;
     uint32_t data_idx = 0;
     uint32_t buff_idx = offs % BOOT_SWAP_STATUS_PAYLD_SZ;
 
-    uint8_t buff[BOOT_SWAP_STATUS_PAYLD_SZ];
+    if ((UINT32_MAX - offs) < len) {
+        return -1;
+    }
 
     /* check if end of data is still inside writable area */
-    // TODO: update for multi image
-    assert ((int)((offs + len) <= BOOT_SWAP_STATUS_D_SIZE_RAW));
+    if ((offs + len) > BOOT_SWAP_STATUS_D_SIZE_RAW) {
+        return -1;
+    }
 
     /* pre-calculate sub-area offset */
     init_offs = swap_status_init_offset(target_area_id);
-    assert ((int)(init_offs >= 0));
+    if (init_offs < 0) {
+        return -1;
+    }
 
     /* will start from it
      * this will be write-aligned */
     rec_offs = (uint32_t)init_offs + calc_record_offs(offs);
 
     /* go over all records to be updated */
-    while (length > 0) {
+    while (len != 0U) {
         /* preserve record */
-        copy_num = swap_status_read_record(rec_offs, buff, &copy_counter);
+        rc = swap_status_read_record(rec_offs, status_buff, &copy_counter, &copy_num);
         /* it returns copy number */
-        if (copy_num < 0) {
+        if (rc < 0) {
             /* something went wrong while read, exit */
             rc = -1;
             break;
         }
         /* update record data */
-        if (length > (int)BOOT_SWAP_STATUS_PAYLD_SZ) {
+        if (len > BOOT_SWAP_STATUS_PAYLD_SZ) {
             copy_sz = BOOT_SWAP_STATUS_PAYLD_SZ - buff_idx;
         }
         else {
-            copy_sz = (uint32_t)length;
+            copy_sz = len;
         }
-        (void)memcpy(&((uint8_t *)data)[data_idx], &buff[buff_idx], copy_sz);
+
+        (void)memcpy((uint8_t *)data + data_idx, status_buff + buff_idx, copy_sz);
         buff_idx = 0;
 
         /* proceed to next record */
-        length -= (int32_t)BOOT_SWAP_STATUS_PAYLD_SZ;
-        rec_offs += BOOT_SWAP_STATUS_ROW_SZ;
-        data_idx += BOOT_SWAP_STATUS_PAYLD_SZ;
+        if (len < BOOT_SWAP_STATUS_PAYLD_SZ) {
+            len = 0;
+        }
+        else {
+            len -= BOOT_SWAP_STATUS_PAYLD_SZ;
+            rec_offs += BOOT_SWAP_STATUS_ROW_SZ;
+            data_idx += BOOT_SWAP_STATUS_PAYLD_SZ;
+        }
     }
     return rc;
 }
 
+/**
+ * Copy trailer from status partition to primary image and set copy_done flag.
+ * This function calls only once, before set copy_done flag in status trailer
+ *
+ * @param fap           Target area id for which status is being read.
+ *
+ * @return              0 on success; -1 on failure.
+ */
+int swap_status_to_image_trailer(const struct flash_area *fap)
+{
+    uint8_t erased_val;
+    uint8_t stat_erased_val;
+    const uint8_t *copy_src;
+    uint32_t cur_trailer_pos;
+    uint32_t primary_trailer_sz;
+    uint32_t primary_trailer_buf_sz;
+    uint32_t align = CY_FLASH_ALIGN;
+    int rc = 0;
+    const struct flash_area *fap_stat = NULL;
+    uint8_t primary_trailer_buf[MAX_TRAILER_BUF_SIZE];
+
+    /* get the erased flash byte for status partition */
+    rc = flash_area_open(FLASH_AREA_IMAGE_SWAP_STATUS, &fap_stat);
+    if (rc != 0) {
+        return rc;
+    }
+    stat_erased_val = flash_area_erased_val(fap_stat);
+    flash_area_close(fap_stat);
+
+    /* get status partition trailer size and copy it to buffer */
+    const uint32_t status_trailer_buf_sz = BOOT_SWAP_STATUS_SWAPSZ_SZ + BOOT_SWAP_STATUS_SWAPINF_SZ +
+                BOOT_SWAP_STATUS_COPY_DONE_SZ + BOOT_SWAP_STATUS_IMG_OK_SZ + BOOT_SWAP_STATUS_MAGIC_SZ;
+    uint8_t status_trailer_buf[status_trailer_buf_sz];
+    (void)memset(&status_trailer_buf, 0, status_trailer_buf_sz);
+    rc = swap_status_retrieve(fap->fa_id, boot_swap_size_off(fap), (uint8_t *)status_trailer_buf, status_trailer_buf_sz);
+    if (rc != 0) {
+        return rc;
+    }
+
+    /* check trailer magic in status partition */
+    if (boot_magic_decode(&status_trailer_buf[status_trailer_buf_sz - BOOT_SWAP_STATUS_MAGIC_SZ]) != BOOT_MAGIC_GOOD) {
+        return -1;
+    }
+
+    /* get primary slot trailer size without status data fields */
+    primary_trailer_sz = boot_trailer_sz(0);
+
+    /* align image trailer buffer size to minimal write size */
+#if !defined(__BOOTSIM__)
+    align = flash_area_align(fap);
+#else
+    align = CY_FLASH_ALIGN;
+#endif
+
+    if ((align > MAX_TRAILER_BUF_SIZE) || (align == 0U)) {
+        return -1;
+    }
+
+    primary_trailer_buf_sz = align;
+    while (primary_trailer_buf_sz < primary_trailer_sz) {
+        primary_trailer_buf_sz += align;
+    }
+    if (primary_trailer_buf_sz > MAX_TRAILER_BUF_SIZE) {
+        return -1;
+    }
+
+    /* erase primary slot trailer */
+    rc= flash_area_erase(fap, fap->fa_size - primary_trailer_buf_sz, primary_trailer_buf_sz);
+    if (rc != 0) {
+        return rc;
+    }
+
+    /* erase trailer area */
+    erased_val = flash_area_erased_val(fap); /* stat_erased_val and erased_val may differ! */
+    (void)memset(&primary_trailer_buf[primary_trailer_buf_sz-primary_trailer_sz], (int) erased_val, primary_trailer_sz);
+
+    /* copy and align flags and data from status_trailer_buf to primary_trailer_buf
+                                         Status part trailer --> Pimary image trailer */
+
+    /* copy trailer magic */
+    cur_trailer_pos = primary_trailer_buf_sz - BOOT_SWAP_STATUS_MAGIC_SZ;
+    copy_src = &status_trailer_buf[status_trailer_buf_sz - BOOT_SWAP_STATUS_MAGIC_SZ];
+    if (stat_erased_val != erased_val &&
+        bootutil_buffer_is_filled(copy_src, stat_erased_val, BOOT_SWAP_STATUS_MAGIC_SZ)) {
+
+        (void)memset(&primary_trailer_buf[cur_trailer_pos], (int)erased_val, BOOT_SWAP_STATUS_MAGIC_SZ);
+    }
+    else {
+        (void)memcpy(&primary_trailer_buf[cur_trailer_pos], copy_src, BOOT_SWAP_STATUS_MAGIC_SZ);
+    }
+
+    /* copy image_ok flag */
+    cur_trailer_pos -= BOOT_MAX_ALIGN;
+    copy_src = &status_trailer_buf[BOOT_SWAP_STATUS_SWAPSZ_SZ + BOOT_SWAP_STATUS_SWAPINF_SZ + BOOT_SWAP_STATUS_COPY_DONE_SZ];
+    if (stat_erased_val != erased_val && stat_erased_val == *copy_src) {
+        copy_src = &erased_val;
+    }
+    primary_trailer_buf[cur_trailer_pos] = *copy_src;
+
+    /* set copy_done flag */
+    cur_trailer_pos -= BOOT_MAX_ALIGN;
+    primary_trailer_buf[cur_trailer_pos] = BOOT_FLAG_SET;
+
+    /* copy swap_type flag */
+    cur_trailer_pos -= BOOT_MAX_ALIGN;
+    copy_src = &status_trailer_buf[BOOT_SWAP_STATUS_SWAPSZ_SZ];
+    if (stat_erased_val != erased_val && stat_erased_val == *copy_src) {
+        copy_src = &erased_val;
+    }
+    primary_trailer_buf[cur_trailer_pos] = *copy_src;
+
+    /* copy swap_size field */
+    cur_trailer_pos -= BOOT_MAX_ALIGN;
+    if (stat_erased_val != erased_val &&
+        bootutil_buffer_is_filled(status_trailer_buf, stat_erased_val, BOOT_SWAP_STATUS_SWAPSZ_SZ)) {
+
+        (void)memset(&primary_trailer_buf[cur_trailer_pos], (int)erased_val, BOOT_SWAP_STATUS_SWAPSZ_SZ);
+    }
+    else {
+        (void)memcpy(&primary_trailer_buf[cur_trailer_pos], status_trailer_buf, BOOT_SWAP_STATUS_SWAPSZ_SZ);
+    }
+
+    /* write primary image trailer with copy_done flag set */
+    rc = flash_area_write(fap, fap->fa_size - primary_trailer_buf_sz, primary_trailer_buf, primary_trailer_buf_sz);
+
+    return rc;
+}
+
 #endif /* MCUBOOT_SWAP_USING_STATUS */