Implement new swap scheme for devices with large erase size using scratch with status area
diff --git a/boot/bootutil/src/swap_status_misc.c b/boot/bootutil/src/swap_status_misc.c
new file mode 100644
index 0000000..c8f8f95
--- /dev/null
+++ b/boot/bootutil/src/swap_status_misc.c
@@ -0,0 +1,718 @@
+/*
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Copyright (c) 2017-2019 Linaro LTD
+ * Copyright (c) 2016-2019 JUUL Labs
+ * Copyright (c) 2019-2020 Arm Limited
+ * Copyright (c) 2020 Cypress Semiconductors
+ *
+ * Original license:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#include <assert.h>
+#include <stddef.h>
+#include <stdbool.h>
+#include <inttypes.h>
+#include <stdlib.h>
+#include <string.h>
+#include "bootutil/bootutil.h"
+#include "bootutil_priv.h"
+#include "swap_priv.h"
+#include "bootutil/bootutil_log.h"
+
+#include "swap_status.h"
+
+#include "mcuboot_config/mcuboot_config.h"
+
+MCUBOOT_LOG_MODULE_DECLARE(mcuboot);
+
+#if defined(MCUBOOT_SWAP_USING_STATUS)
+
+#define BOOT_MAGIC_ARR_SZ \
+    (sizeof boot_img_magic / sizeof boot_img_magic[0])
+
+static int
+boot_find_status(int image_index, const struct flash_area **fap);
+
+static int
+boot_magic_decode(const uint32_t *magic)
+{
+    if (memcmp(magic, boot_img_magic, BOOT_MAGIC_SZ) == 0) {
+        return BOOT_MAGIC_GOOD;
+    }
+    return BOOT_MAGIC_BAD;
+}
+
+static int
+boot_flag_decode(uint8_t flag)
+{
+    if (flag != (uint8_t)BOOT_FLAG_SET) {
+        return BOOT_FLAG_BAD;
+    }
+    return BOOT_FLAG_SET;
+}
+
+static inline size_t
+boot_status_sector_size(const struct boot_loader_state *state, size_t sector)
+{
+    return state->status.sectors[sector].fs_size;
+}
+
+static inline uint32_t
+boot_status_sector_off(const struct boot_loader_state *state,
+                    size_t sector)
+{
+    return state->status.sectors[sector].fs_off -
+           state->status.sectors[0].fs_off;
+}
+
+/* Offset Section */
+static inline uint32_t
+boot_magic_off(const struct flash_area *fap)
+{
+    (void)fap;
+    return ((uint32_t)BOOT_SWAP_STATUS_D_SIZE_RAW - (uint32_t)BOOT_MAGIC_SZ);
+}
+
+uint32_t
+boot_image_ok_off(const struct flash_area *fap)
+{
+    return (uint32_t)(boot_magic_off(fap) - 1u);
+}
+
+uint32_t
+boot_copy_done_off(const struct flash_area *fap)
+{
+    return (uint32_t)(boot_image_ok_off(fap) - 1u);
+}
+
+uint32_t
+boot_swap_info_off(const struct flash_area *fap)
+{
+    return (uint32_t)(boot_copy_done_off(fap) - 1u);
+}
+
+uint32_t
+boot_swap_size_off(const struct flash_area *fap)
+{
+    return (uint32_t)(boot_swap_info_off(fap) - 4u);
+}
+
+uint32_t
+boot_status_off(const struct flash_area *fap)
+{
+    (void)fap;
+    /* this offset is equal to 0, because swap status fields
+       in this implementation count from the start of partition */
+    return 0;
+}
+
+#ifdef MCUBOOT_ENC_IMAGES
+static inline uint32_t
+boot_enc_key_off(const struct flash_area *fap, uint8_t slot)
+{
+#ifdef MCUBOOT_SWAP_SAVE_ENCTLV
+    /* suggest encryption key is also stored in status partition */
+    return (uint32_t)(boot_swap_size_off(fap) - (uint32_t)((slot + 1u) * (uint32_t)BOOT_ENC_TLV_SIZE));
+#else
+    return (uint32_t)(boot_swap_size_off(fap) - (uint32_t)((slot + 1u) * (uint32_t)BOOT_ENC_KEY_SIZE));
+#endif
+}
+#endif
+
+/**
+ * Write trailer data; status bytes, swap_size, etc
+ *
+ * @returns 0 on success, != 0 on error.
+ */
+int
+boot_write_trailer(const struct flash_area *fap, uint32_t off,
+        const uint8_t *inbuf, uint8_t inlen)
+{
+    int rc;
+
+    rc = swap_status_update(fap->fa_id, off, (uint8_t *)inbuf, inlen);
+
+    if (rc != 0) {
+        return BOOT_EFLASH;
+    }
+    return rc;
+}
+
+#ifdef MCUBOOT_ENC_IMAGES
+int
+boot_write_enc_key(const struct flash_area *fap, uint8_t slot,
+        const struct boot_status *bs)
+{
+    uint32_t off;
+    int rc;
+
+    off = boot_enc_key_off(fap, slot);
+#ifdef MCUBOOT_SWAP_SAVE_ENCTLV
+    rc = swap_status_update(fap->fa_id, off,
+                            (uint8_t *) bs->enctlv[slot], BOOT_ENC_TLV_ALIGN_SIZE);
+#else
+    rc = swap_status_update(fap->fa_id, off,
+                            (uint8_t *) bs->enckey[slot], BOOT_ENC_KEY_SIZE);
+#endif
+   if (rc != 0) {
+       return BOOT_EFLASH;
+   }
+
+    return 0;
+}
+
+int
+boot_read_enc_key(int image_index, uint8_t slot, struct boot_status *bs)
+{
+    uint32_t off;
+    const struct flash_area *fap;
+#ifdef MCUBOOT_SWAP_SAVE_ENCTLV
+    int i;
+#endif
+    int rc;
+
+    rc = boot_find_status(image_index, &fap);
+    if (rc == 0) {
+        off = boot_enc_key_off(fap, slot);
+#ifdef MCUBOOT_SWAP_SAVE_ENCTLV
+        rc = swap_status_retrieve(fap->fa_id, off, bs->enctlv[slot], BOOT_ENC_TLV_ALIGN_SIZE);
+        if (rc == 0) {
+            for (i = 0; i < BOOT_ENC_TLV_ALIGN_SIZE; i++) {
+                if (bs->enctlv[slot][i] != 0xff) {
+                    break;
+                }
+            }
+            /* Only try to decrypt non-erased TLV metadata */
+            if (i != BOOT_ENC_TLV_ALIGN_SIZE) {
+                rc = boot_enc_decrypt(bs->enctlv[slot], bs->enckey[slot]);
+            }
+        }
+#else
+        rc = swap_status_retrieve(fap->fa_id, off, bs->enckey[slot], BOOT_ENC_KEY_SIZE);
+#endif
+        flash_area_close(fap);
+    }
+
+    return rc;
+}
+#endif /* MCUBOOT_ENC_IMAGES */
+
+/* Write Section */
+int
+boot_write_magic(const struct flash_area *fap)
+{
+    uint32_t off;
+    int rc;
+
+    off = boot_magic_off(fap);
+
+    rc = swap_status_update(fap->fa_id, off,
+                            (uint8_t *) boot_img_magic, BOOT_MAGIC_SZ);
+
+    if (rc != 0) {
+        return BOOT_EFLASH;
+    }
+    return 0;
+}
+
+int boot_status_num_sectors(const struct boot_loader_state *state)
+{
+    return (int)(BOOT_SWAP_STATUS_SIZE / boot_status_sector_size(state, 0));
+}
+
+/**
+ * Writes the supplied boot status to the flash file system.  The boot status
+ * contains the current state of an in-progress image copy operation.
+ *
+ * @param bs                    The boot status to write.
+ *
+ * @return                      0 on success; nonzero on failure.
+ */
+int
+boot_write_status(const struct boot_loader_state *state, struct boot_status *bs)
+{
+    const struct flash_area *fap = NULL;
+    uint32_t off;
+    int area_id;
+    int rc;
+    (void)state;
+
+    /* NOTE: The first sector copied (that is the last sector on slot) contains
+     *       the trailer. Since in the last step the primary slot is erased, the
+     *       first two status writes go to the scratch which will be copied to
+     *       the primary slot!
+     */
+
+#ifdef MCUBOOT_SWAP_USING_SCRATCH
+    if (bs->use_scratch) {
+        /* Write to scratch status. */
+        area_id = FLASH_AREA_IMAGE_SCRATCH;
+    } else
+#endif
+    {
+        /* Write to the primary slot. */
+        area_id = (int)FLASH_AREA_IMAGE_PRIMARY(BOOT_CURR_IMG(state));
+    }
+
+    rc = flash_area_open((uint8_t)area_id, &fap);
+    if (rc != 0) {
+        rc = BOOT_EFLASH;
+        goto done;
+    }
+    off = boot_status_off(fap) + boot_status_internal_off(bs, 1);
+
+    uint8_t tmp_state = bs->state;
+
+    rc = swap_status_update(fap->fa_id, off, &tmp_state, 1);
+    if (rc != 0) {
+        rc = BOOT_EFLASH;
+        goto done;
+    }
+
+done:
+    flash_area_close(fap);
+
+    return rc;
+}
+
+int
+boot_read_data_empty(const struct flash_area *fap, void *data, uint32_t len)
+{
+    uint8_t *buf;
+
+    buf = (uint8_t *)data;
+    for (uint32_t i = 0; i < len; i++) {
+        if (buf[i] != flash_area_erased_val(fap)) {
+            return 0;
+        }
+    }
+    return 1;
+}
+
+int
+boot_read_swap_state(const struct flash_area *fap,
+                     struct boot_swap_state *state)
+{
+    uint32_t magic[BOOT_MAGIC_ARR_SZ];
+    uint32_t off;
+    uint32_t trailer_off = 0U;
+    uint8_t swap_info = 0U;
+    int rc;
+    uint32_t erase_trailer = 0;
+
+    const struct flash_area *fap_stat = NULL;
+
+    rc = flash_area_open(FLASH_AREA_IMAGE_SWAP_STATUS, &fap_stat);
+    if (rc != 0) {
+        return BOOT_EFLASH;
+    }
+
+    off = boot_magic_off(fap);
+    /* retrieve value for magic field from status partition area */
+    rc = swap_status_retrieve(fap->fa_id, off, magic, BOOT_MAGIC_SZ);
+    if (rc < 0) {
+        return BOOT_EFLASH;
+    }
+    rc = boot_read_data_empty(fap_stat, magic, BOOT_MAGIC_SZ);
+    if (rc < 0) {
+        return BOOT_EFLASH;
+    }
+    /* fill magic number value if equal to expected */
+    if (rc == 1) {
+
+        state->magic = BOOT_MAGIC_UNSET;
+
+        /* attempt to find magic in upgrade img slot trailer */
+        if (fap->fa_id == FLASH_AREA_IMAGE_1 ||
+            fap->fa_id == FLASH_AREA_IMAGE_3) {
+
+                trailer_off = fap->fa_size - BOOT_MAGIC_SZ;
+
+                rc = flash_area_read_is_empty(fap, trailer_off, magic, BOOT_MAGIC_SZ);
+                if (rc < 0) {
+                    return BOOT_EFLASH;
+                }
+                if (rc == 1) {
+                    state->magic = BOOT_MAGIC_UNSET;
+                } else {
+                    state->magic = (uint8_t)boot_magic_decode(magic);
+                    /* put magic to status partition for upgrade slot*/
+                    if (state->magic == (uint32_t)BOOT_MAGIC_GOOD) {
+                        rc = swap_status_update(fap->fa_id, off,
+                                        (uint8_t *) magic, BOOT_MAGIC_SZ);
+                    }
+                    if (rc < 0) {
+                        return BOOT_EFLASH;
+                    } else {
+                        erase_trailer = 1;
+                    }
+                }
+        }
+    } else {
+        state->magic = (uint8_t)boot_magic_decode(magic);
+    }
+
+    off = boot_swap_info_off(fap);
+    rc = swap_status_retrieve(fap->fa_id, off, &swap_info, sizeof swap_info);
+    if (rc < 0) {
+        return BOOT_EFLASH;
+    }
+    rc = boot_read_data_empty(fap_stat, &swap_info, sizeof swap_info);
+    if (rc < 0) {
+        return BOOT_EFLASH;
+    }
+    if (rc == 1 || state->swap_type > (uint8_t)BOOT_SWAP_TYPE_REVERT) {
+        state->swap_type = (uint8_t)BOOT_SWAP_TYPE_NONE;
+        state->image_num = 0;
+    }
+    else {
+        /* Extract the swap type and image number */
+        state->swap_type = (uint8_t)BOOT_GET_SWAP_TYPE_M(swap_info);
+        state->image_num = (uint8_t)BOOT_GET_IMAGE_NUM_M(swap_info);
+    }
+
+    off = boot_copy_done_off(fap);
+    rc = swap_status_retrieve(fap->fa_id, off, &state->copy_done, sizeof state->copy_done);
+    if (rc < 0) {
+        return BOOT_EFLASH;
+    }
+    rc = boot_read_data_empty(fap_stat, &state->copy_done, sizeof state->copy_done);
+    /* need to check swap_info was empty */
+    if (rc < 0) {
+       return BOOT_EFLASH;
+    }
+    if (rc == 1) {
+       state->copy_done = BOOT_FLAG_UNSET;
+    } else {
+       state->copy_done = (uint8_t)boot_flag_decode(state->copy_done);
+    }
+
+    off = boot_image_ok_off(fap);
+    rc = swap_status_retrieve(fap->fa_id, off, &state->image_ok, sizeof state->image_ok);
+    if (rc < 0) {
+       return BOOT_EFLASH;
+    }
+    rc = boot_read_data_empty(fap_stat, &state->image_ok, sizeof state->image_ok);
+    /* need to check swap_info was empty */
+    if (rc < 0) {
+       return BOOT_EFLASH;
+    }
+    if (rc == 1) {
+        /* assign img_ok unset */
+        state->image_ok = BOOT_FLAG_UNSET;
+
+        /* attempt to read img_ok value in upgrade img slots trailer area
+         * it is set when image in slot for upgrade is signed for swap_type permanent
+        */
+        uint32_t process_image_ok = 0;
+        switch (fap->fa_id) {
+            case FLASH_AREA_IMAGE_0:
+            case FLASH_AREA_IMAGE_2:
+            {
+                if (state->copy_done == (uint8_t)BOOT_FLAG_SET)
+                    process_image_ok = 1;
+            }
+            break;
+            case FLASH_AREA_IMAGE_1:
+            case FLASH_AREA_IMAGE_3:
+            {
+                process_image_ok = 1;
+            }
+            break;
+            case FLASH_AREA_IMAGE_SCRATCH:
+            {
+                BOOT_LOG_DBG(" * selected SCRATCH area, copy_done = %d", state->copy_done);
+                {
+                    if (state->copy_done == (uint8_t)BOOT_FLAG_SET)
+                        process_image_ok = 1;
+                }
+            }
+            break;
+            default:
+            {
+                return BOOT_EFLASH;
+            }
+            break;
+        }
+        if (process_image_ok != 0u) {
+            trailer_off = fap->fa_size - (uint8_t)BOOT_MAGIC_SZ - (uint8_t)BOOT_MAX_ALIGN;
+
+            rc = flash_area_read_is_empty(fap, trailer_off, &state->image_ok, sizeof state->image_ok);
+            if (rc < 0) {
+                return BOOT_EFLASH;
+            }
+            if (rc == 1) {
+                state->image_ok = BOOT_FLAG_UNSET;
+            } else {
+                state->image_ok = (uint8_t)boot_flag_decode(state->image_ok);
+
+                /* put img_ok to status partition for upgrade slot */
+                if (state->image_ok != (uint8_t)BOOT_FLAG_BAD) {
+                    rc = swap_status_update(fap->fa_id, off,
+                                &state->image_ok, sizeof state->image_ok);
+                }
+                if (rc < 0) {
+                    return BOOT_EFLASH;
+                }
+
+                /* mark img trailer needs to be erased */
+                erase_trailer = 1;
+            }
+        }
+    } else {
+       state->image_ok = (uint8_t)boot_flag_decode(state->image_ok);
+    }
+
+    if ((erase_trailer != 0u) && (fap->fa_id != FLASH_AREA_IMAGE_SCRATCH)) {
+        /* erase magic from upgrade img trailer */
+        rc = flash_area_erase(fap, trailer_off, BOOT_MAGIC_SZ);
+        if (rc != 0)
+            return rc;
+    }
+    return 0;
+}
+
+/**
+ * This functions tries to locate the status area after an aborted swap,
+ * by looking for the magic in the possible locations.
+ *
+ * If the magic is successfully found, a flash_area * is returned and it
+ * is the responsibility of the called to close it.
+ *
+ * @returns 0 on success, -1 on errors
+ */
+static int
+boot_find_status(int image_index, const struct flash_area **fap)
+{
+    uint32_t magic[BOOT_MAGIC_ARR_SZ] = {0};
+    uint32_t off;
+
+    /* the status is always in status partition */
+    uint8_t area = FLASH_AREA_IMAGE_PRIMARY((uint32_t)image_index);
+    int rc = -1;
+
+    /*
+     * In the middle a swap, tries to locate the area that is currently
+     * storing a valid magic, first on the primary slot, then on scratch.
+     * Both "slots" can end up being temporary storage for a swap and it
+     * is assumed that if magic is valid then other metadata is too,
+     * because magic is always written in the last step.
+     */
+    rc = flash_area_open(area, fap);
+    if (rc != 0) {
+         return rc;
+    }
+    off = boot_magic_off(*fap);
+    rc = swap_status_retrieve(area, off, magic, BOOT_MAGIC_SZ);
+
+    if (rc == 0) {
+        rc = memcmp(magic, boot_img_magic, BOOT_MAGIC_SZ);
+    }
+
+    flash_area_close(*fap);
+    return rc;
+}
+
+int
+boot_read_swap_size(int image_index, uint32_t *swap_size)
+{
+    uint32_t off;
+    const struct flash_area *fap;
+    int rc;
+
+    rc = boot_find_status(image_index, &fap);
+    if (rc == 0) {
+        off = boot_swap_size_off(fap);
+
+        rc = swap_status_retrieve(fap->fa_id, off, swap_size, sizeof *swap_size);
+    }
+    return rc;
+}
+
+int
+swap_erase_trailer_sectors(const struct boot_loader_state *state,
+                           const struct flash_area *fap)
+{
+    uint32_t sub_offs, trailer_offs;
+    uint32_t sz;
+    uint8_t fa_id_primary;
+    uint8_t fa_id_secondary;
+    uint8_t image_index;
+    int rc;
+    (void)state;
+
+    BOOT_LOG_INF("Erasing trailer; fa_id=%d", fap->fa_id);
+    /* trailer is located in status-partition */
+    const struct flash_area *fap_stat = NULL;
+
+    rc = flash_area_open(FLASH_AREA_IMAGE_SWAP_STATUS, &fap_stat);
+    if (rc != 0) {
+        return BOOT_EFLASH;
+    }
+
+    if (fap->fa_id != FLASH_AREA_IMAGE_SCRATCH)
+    {
+        image_index = BOOT_CURR_IMG(state);
+        fa_id_primary = (uint8_t)flash_area_id_from_multi_image_slot((int32_t)image_index,
+                BOOT_PRIMARY_SLOT);
+        fa_id_secondary = (uint8_t)flash_area_id_from_multi_image_slot((int32_t)image_index,
+                BOOT_SECONDARY_SLOT);
+
+        /* skip if Flash Area is not recognizable */
+        if ((fap->fa_id != fa_id_primary) && (fap->fa_id != fa_id_secondary)) {
+            return BOOT_EFLASH;
+        }
+    }
+
+    sub_offs = (uint32_t)swap_status_init_offset(fap->fa_id);
+
+    /* delete starting from last sector and moving to beginning */
+    /* calculate last sector of status sub-area */
+    sz = (uint32_t)BOOT_SWAP_STATUS_SIZE;
+
+    rc = flash_area_erase(fap_stat, sub_offs, sz);
+    assert((int)(rc == 0));
+
+    if (fap->fa_id != FLASH_AREA_IMAGE_SCRATCH)
+    {
+        /*
+         * it is also needed to erase trailer area in slots since they may contain
+         * data, which is already cleared in corresponding status partition
+         */
+        trailer_offs = fap->fa_size - BOOT_SWAP_STATUS_TRAILER_SIZE;
+        rc = flash_area_erase(fap, trailer_offs, BOOT_SWAP_STATUS_TRAILER_SIZE);
+    }
+
+    flash_area_close(fap_stat);
+
+    return rc;
+}
+
+int
+swap_status_init(const struct boot_loader_state *state,
+                 const struct flash_area *fap,
+                 const struct boot_status *bs)
+{
+    struct boot_swap_state swap_state;
+    uint8_t image_index;
+    int rc;
+
+#if (BOOT_IMAGE_NUMBER == 1)
+    (void)state;
+#endif
+
+    image_index = BOOT_CURR_IMG(state);
+
+    BOOT_LOG_DBG("initializing status; fa_id=%d", fap->fa_id);
+
+    rc = boot_read_swap_state_by_id((int32_t)FLASH_AREA_IMAGE_SECONDARY(image_index),
+            &swap_state);
+    assert((int)(rc == 0));
+
+    if (bs->swap_type != (uint8_t)BOOT_SWAP_TYPE_NONE) {
+        rc = boot_write_swap_info(fap, bs->swap_type, image_index);
+        assert((int)(rc == 0));
+    }
+
+    if (swap_state.image_ok == (uint8_t)BOOT_FLAG_SET) {
+        rc = boot_write_image_ok(fap);
+        assert((int)(rc == 0));
+    }
+
+    rc = boot_write_swap_size(fap, bs->swap_size);
+    assert((int)(rc == 0));
+
+#ifdef MCUBOOT_ENC_IMAGES
+    rc = boot_write_enc_key(fap, 0, bs);
+    assert((int)(rc == 0));
+
+    rc = boot_write_enc_key(fap, 1, bs);
+    assert((int)(rc == 0));
+#endif
+
+    rc = boot_write_magic(fap);
+    assert((int)(rc == 0));
+
+    return 0;
+}
+
+int
+swap_read_status(struct boot_loader_state *state, struct boot_status *bs)
+{
+    const struct flash_area *fap = NULL;
+    const struct flash_area *fap_stat = NULL;
+    uint32_t off;
+    uint8_t swap_info = 0;
+    int area_id;
+    int rc = 0;
+
+    bs->source = swap_status_source(state);
+
+    if (bs->source == BOOT_STATUS_SOURCE_NONE) {
+        return 0;
+    }
+
+    if (bs->source ==  BOOT_STATUS_SOURCE_PRIMARY_SLOT) {
+        area_id = (int32_t)FLASH_AREA_IMAGE_PRIMARY(BOOT_CURR_IMG(state));
+    } else if (bs->source ==  BOOT_STATUS_SOURCE_SCRATCH) {
+        area_id = FLASH_AREA_IMAGE_SCRATCH;
+    } else {
+        return BOOT_EBADARGS;
+    }
+
+    rc = flash_area_open((uint8_t)area_id, &fap);
+    if (rc != 0) {
+        return BOOT_EFLASH;
+    }
+
+    rc = flash_area_open(FLASH_AREA_IMAGE_SWAP_STATUS, &fap_stat);
+    if (rc != 0) {
+        return BOOT_EFLASH;
+    }
+
+    rc = swap_read_status_bytes(fap, state, bs);
+    if (rc == 0) {
+        off = boot_swap_info_off(fap);
+        rc = swap_status_retrieve((uint8_t)area_id, off, &swap_info, sizeof swap_info);
+        if (rc < 0) {
+            return BOOT_EFLASH;
+        }
+        rc = boot_read_data_empty(fap_stat, &swap_info, sizeof swap_info);
+        if (rc < 0) {
+            return BOOT_EFLASH;
+        }
+
+        if (rc == 1) {
+            BOOT_SET_SWAP_INFO_M(swap_info, 0u, (uint8_t)BOOT_SWAP_TYPE_NONE);
+            rc = 0;
+        }
+
+        /* Extract the swap type info */
+        bs->swap_type = BOOT_GET_SWAP_TYPE_M(swap_info);
+    }
+
+    flash_area_close(fap);
+    flash_area_close(fap_stat);
+
+    return rc;
+}
+
+#endif /* MCUBOOT_SWAP_USING_STATUS */