blob: b5fc1ed790beeb8e34dfccda70b2aa3b43e600c2 [file] [log] [blame]
/*
* 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);
#define ERROR_VALUE (UINT32_MAX)
#if defined(MCUBOOT_SWAP_USING_STATUS)
static int
boot_find_status(int image_index, const struct flash_area **fap);
static int
boot_magic_decode(const union boot_img_magic_t *magic_p)
{
if (memcmp((const void*)magic_p->val, (const void *)&boot_img_magic.val, 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;
}
/* 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 boot_magic_off(fap) - BOOT_SWAP_STATUS_IMG_OK_SZ;
}
uint32_t
boot_copy_done_off(const struct flash_area *fap)
{
return boot_image_ok_off(fap) - BOOT_SWAP_STATUS_COPY_DONE_SZ;
}
uint32_t
boot_swap_info_off(const struct flash_area *fap)
{
return boot_copy_done_off(fap) - BOOT_SWAP_STATUS_SWAPINF_SZ;
}
uint32_t
boot_swap_size_off(const struct flash_area *fap)
{
return boot_swap_info_off(fap) - BOOT_SWAP_STATUS_SWAPSZ_SZ;
}
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
/**
* @returns ERROR_VALUE on error, otherwise result.
*/
static inline uint32_t
boot_enc_key_off(const struct flash_area *fap, uint8_t slot)
{
uint32_t slot_offset;
uint32_t res = ERROR_VALUE;
uint32_t boot_swap_size_offset = boot_swap_size_off(fap);
#ifdef MCUBOOT_SWAP_SAVE_ENCTLV
/* suggest encryption key is also stored in status partition */
slot_offset = ((uint32_t)slot + 1UL) * (uint32_t)BOOT_ENC_TLV_SIZE;
#else
slot_offset = ((uint32_t)slot + 1UL) * (uint32_t)BOOT_ENC_KEY_SIZE;
#endif
if (boot_swap_size_offset >= slot_offset)
{
res = boot_swap_size_offset - slot_offset;
}
return res;
}
#endif
/**
* Write trailer data; status bytes, swap_size, etc
*
* @returns 0 on success, -1 on error.
*/
int
boot_write_trailer(const struct flash_area *fap, uint32_t off,
const uint8_t *inbuf, uint8_t inlen)
{
int rc;
/* copy status part trailer to primary image before set copy_done flag */
if (boot_copy_done_off(fap) == off &&
fap->fa_id == FLASH_AREA_IMAGE_PRIMARY(0u) &&
BOOT_SWAP_STATUS_COPY_DONE_SZ == inlen) {
BOOT_LOG_DBG("copy status part trailer to primary image slot");
rc = swap_status_to_image_trailer(fap);
if (rc != 0) {
BOOT_LOG_ERR("trailer copy failed");
return -1;
}
}
rc = swap_status_update(fap->fa_id, off, inbuf, inlen);
if (rc != 0) {
return -1;
}
return rc;
}
#ifdef MCUBOOT_ENC_IMAGES
int
boot_write_enc_key(const struct flash_area *fap, uint8_t slot,
const struct boot_status *bs)
{
int rc;
uint32_t off = boot_enc_key_off(fap, slot);
if (ERROR_VALUE == off)
{
return -1;
}
#ifdef MCUBOOT_SWAP_SAVE_ENCTLV
rc = swap_status_update(fap->fa_id, off,
bs->enctlv[slot], BOOT_ENC_TLV_ALIGN_SIZE);
#else
rc = swap_status_update(fap->fa_id, off,
bs->enckey[slot], BOOT_ENC_KEY_SIZE);
#endif
if (rc != 0) {
return -1;
}
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;
int rc;
rc = boot_find_status(image_index, &fap);
if (0 == rc) {
off = boot_enc_key_off(fap, slot);
if (ERROR_VALUE == off)
{
return -1;
}
#ifdef MCUBOOT_SWAP_SAVE_ENCTLV
rc = swap_status_retrieve(fap->fa_id, off, bs->enctlv[slot], BOOT_ENC_TLV_ALIGN_SIZE);
if (0 == rc) {
uint8_t aes_iv[BOOTUTIL_CRYPTO_AES_CTR_BLOCK_SIZE];
/* Only try to decrypt initialized TLV metadata */
if (!bootutil_buffer_is_filled(bs->enctlv[slot],
BOOT_UNINITIALIZED_TLV_FILL,
BOOT_ENC_TLV_ALIGN_SIZE)) {
rc = boot_enc_decrypt(bs->enctlv[slot], bs->enckey[slot], 0, aes_iv);
}
}
#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,
(const uint8_t *)&boot_img_magic, BOOT_MAGIC_SZ);
if (rc != 0) {
return -1;
}
return 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;
uint8_t area_id;
uint8_t tmp_state;
int rc;
(void)state;
if (bs->idx < BOOT_STATUS_IDX_0) {
return BOOT_EFLASH;
}
/* 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 != 0U) {
/* Write to scratch status. */
area_id = (uint8_t)FLASH_AREA_IMAGE_SCRATCH;
} else
#endif
{
/* Write to the primary slot. */
area_id = FLASH_AREA_IMAGE_PRIMARY(BOOT_CURR_IMG(state));
}
rc = flash_area_open(area_id, &fap);
if (rc != 0) {
rc = BOOT_EFLASH;
goto done;
}
off = boot_status_off(fap) + boot_status_internal_off(bs, 1);
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;
}
#if defined (MCUBOOT_SWAP_STATUS_FAST_BOOT)
static inline int
boot_read_flag(const struct flash_area *fap, uint8_t *flag, uint32_t off)
{
int rc;
do {
rc = flash_area_read(fap, off, flag, sizeof *flag);
if (rc != 0) {
break;
}
if (*flag == flash_area_erased_val(fap)) {
*flag = BOOT_FLAG_UNSET;
} else {
*flag = boot_flag_decode(*flag);
}
} while (false);
return rc;
}
static inline uint32_t
boot_magic_off_trailer(const struct flash_area *fap)
{
return flash_area_get_size(fap) - BOOT_MAGIC_SZ;
}
static inline uint32_t
boot_image_ok_off_trailer(const struct flash_area *fap)
{
return ALIGN_DOWN(boot_magic_off_trailer(fap) - BOOT_MAX_ALIGN, BOOT_MAX_ALIGN);
}
static inline uint32_t
boot_copy_done_off_trailer(const struct flash_area *fap)
{
return boot_image_ok_off_trailer(fap) - BOOT_MAX_ALIGN;
}
static inline uint32_t
boot_swap_info_off_trailer(const struct flash_area *fap)
{
return boot_copy_done_off_trailer(fap) - BOOT_MAX_ALIGN;
}
int
boot_read_swap_state_trailer(const struct flash_area *fap,
struct boot_swap_state *state)
{
union boot_img_magic_t magic = {0U};
uint32_t off;
uint8_t swap_info;
int rc;
do {
off = boot_magic_off_trailer(fap);
rc = flash_area_read(fap, off, &magic, BOOT_MAGIC_SZ);
if (rc != 0) {
break;
}
if (bootutil_buffer_is_erased(fap, &magic, BOOT_MAGIC_SZ)) {
state->magic = BOOT_MAGIC_UNSET;
} else {
state->magic = boot_magic_decode(&magic);
}
off = boot_swap_info_off_trailer(fap);
rc = flash_area_read(fap, off, &swap_info, sizeof swap_info);
if (rc != 0) {
break;
}
/* Extract the swap type and image number */
state->swap_type = BOOT_GET_SWAP_TYPE(swap_info);
state->image_num = BOOT_GET_IMAGE_NUM(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;
}
off = boot_copy_done_off_trailer(fap);
rc = boot_read_flag(fap, &state->copy_done, off);
if (rc != 0) {
break;
}
off = boot_image_ok_off_trailer(fap);
rc = boot_read_flag(fap, &state->image_ok, off);
} while (false);
return rc;
}
#endif
int
boot_read_swap_state(const struct flash_area *fap,
struct boot_swap_state *state)
{
union boot_img_magic_t magic = {0U};
uint32_t off = 0U;
uint32_t trailer_off = 0U;
uint8_t swap_info = 0U;
int rc = 0;
uint32_t erase_trailer = 0;
bool buf_is_clean = false;
bool is_primary = false;
bool is_secondary = false;
uint32_t i;
const struct flash_area *fap_stat = NULL;
for (i = 0u; i < (uint32_t)BOOT_IMAGE_NUMBER; i++) {
if (fap->fa_id == FLASH_AREA_IMAGE_PRIMARY(i)) {
is_primary = true;
break;
}
if (fap->fa_id == FLASH_AREA_IMAGE_SECONDARY(i)) {
is_secondary = true;
break;
}
}
#if defined(MCUBOOT_SWAP_STATUS_FAST_BOOT)
{
bool is_scratch = fap->fa_id == FLASH_AREA_IMAGE_SCRATCH;
boot_read_swap_state_trailer(fap, state);
if (is_primary) {
if (state->image_ok == BOOT_FLAG_SET && state->copy_done == BOOT_FLAG_SET && state->magic == BOOT_MAGIC_GOOD) {
return 0;
}
}
if (is_secondary || is_scratch) {
if (state->image_ok == BOOT_FLAG_UNSET && state->copy_done == BOOT_FLAG_UNSET && state->magic == BOOT_MAGIC_UNSET) {
return 0;
}
}
}
#endif
rc = flash_area_open(FLASH_AREA_IMAGE_SWAP_STATUS, &fap_stat);
if (rc != 0) {
return -1;
}
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 -1;
}
/* fill magic number value if equal to expected */
if (bootutil_buffer_is_erased(fap_stat, &magic, BOOT_MAGIC_SZ)) {
state->magic = BOOT_MAGIC_UNSET;
/* attempt to find magic in upgrade img slot trailer */
if (is_secondary) {
trailer_off = fap->fa_size - BOOT_MAGIC_SZ;
rc = flash_area_read(fap, trailer_off, &magic, BOOT_MAGIC_SZ);
if (rc != 0) {
return -1;
}
buf_is_clean = bootutil_buffer_is_erased(fap, &magic, BOOT_MAGIC_SZ);
if (buf_is_clean) {
state->magic = BOOT_MAGIC_UNSET;
} else {
state->magic = (uint8_t)boot_magic_decode(&magic);
/* put magic to status partition for upgrade slot*/
if ((uint32_t)BOOT_MAGIC_GOOD == state->magic) {
rc = swap_status_update(fap->fa_id, off,
(uint8_t *)&magic, BOOT_MAGIC_SZ);
}
if (rc < 0) {
return -1;
} 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 -1;
}
if (bootutil_buffer_is_erased(fap_stat, &swap_info, sizeof swap_info) ||
state->swap_type >= (uint8_t)BOOT_SWAP_TYPE_FAIL) {
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 -1;
}
/* need to check swap_info was empty */
if (bootutil_buffer_is_erased(fap_stat, &state->copy_done, sizeof state->copy_done)) {
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 -1;
}
/* need to check swap_info was empty */
if (bootutil_buffer_is_erased(fap_stat, &state->image_ok, sizeof state->image_ok)) {
/* 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
*/
bool process_image_ok = (uint8_t)BOOT_FLAG_SET == state->copy_done;
if (fap->fa_id == FLASH_AREA_IMAGE_SCRATCH) {
BOOT_LOG_DBG(" * selected SCRATCH area, copy_done = %u", (unsigned)state->copy_done);
}
else if (is_secondary) {
process_image_ok = true;
}
else if (!is_primary) {
process_image_ok = false;
rc = -1;
}
else {
/* Fix MISRA Rule 15.7 */
}
if (process_image_ok) {
trailer_off = fap->fa_size - (uint8_t)BOOT_MAGIC_SZ - (uint8_t)BOOT_MAX_ALIGN;
rc = flash_area_read(fap, trailer_off, &state->image_ok, sizeof state->image_ok);
if (rc != 0) {
return -1;
}
buf_is_clean = bootutil_buffer_is_erased(fap, &state->image_ok, sizeof state->image_ok);
if (buf_is_clean) {
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 -1;
}
/* don't erase trailer, just move img_ok to status part */
erase_trailer = 0;
}
}
} else {
state->image_ok = (uint8_t)boot_flag_decode(state->image_ok);
}
if ((erase_trailer != 0u) && (fap->fa_id != FLASH_AREA_IMAGE_SCRATCH) && (0 == rc)) {
/* erase magic from upgrade img trailer */
rc = flash_area_erase(fap, trailer_off, BOOT_MAGIC_SZ);
if (rc != 0) {
return rc;
}
}
return rc;
}
/**
* 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)
{
union boot_img_magic_t magic = {0};
uint32_t off;
int rc = -1;
uint8_t area = FLASH_AREA_ERROR;
if ((image_index < 0) || (image_index >= MCUBOOT_IMAGE_NUMBER)) {
return rc;
}
/* the status is always in status partition */
area = FLASH_AREA_IMAGE_PRIMARY((uint32_t)image_index);
/*
* 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 (0 == rc) {
rc = memcmp((const void*)&magic.val, (const void *)&boot_img_magic.val, 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 (0 == rc) {
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)
{
int32_t sub_offs;
uint32_t trailer_offs;
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=%u", (unsigned)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 -1;
}
if (fap->fa_id != FLASH_AREA_IMAGE_SCRATCH) {
image_index = BOOT_CURR_IMG(state);
rc = flash_area_id_from_multi_image_slot((int32_t)image_index,
BOOT_PRIMARY_SLOT);
if (rc < 0) {
return -1;
}
fa_id_primary = (uint8_t)rc;
rc = flash_area_id_from_multi_image_slot((int32_t)image_index,
BOOT_SECONDARY_SLOT);
if (rc < 0) {
return -1;
}
fa_id_secondary = (uint8_t)rc;
/* skip if Flash Area is not recognizable */
if ((fap->fa_id != fa_id_primary) && (fap->fa_id != fa_id_secondary)) {
return -1;
}
}
sub_offs = swap_status_init_offset(fap->fa_id);
if (sub_offs < 0) {
return -1;
}
/* delete starting from last sector and moving to beginning */
/* calculate last sector of status sub-area */
rc = flash_area_erase(fap_stat, (uint32_t)sub_offs, (uint32_t)BOOT_SWAP_STATUS_SIZE);
if (rc != 0) {
return -1;
}
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 = {0};
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=%u", (unsigned)fap->fa_id);
rc = boot_read_swap_state_by_id((int32_t)FLASH_AREA_IMAGE_SECONDARY(image_index),
&swap_state);
assert(0 == rc);
if (bs->swap_type != (uint8_t)BOOT_SWAP_TYPE_NONE) {
rc = boot_write_swap_info(fap, bs->swap_type, image_index);
assert(0 == rc);
}
if ((uint8_t)BOOT_FLAG_SET == swap_state.image_ok) {
rc = boot_write_image_ok(fap);
assert(0 == rc);
}
rc = boot_write_swap_size(fap, bs->swap_size);
assert(0 == rc);
#ifdef MCUBOOT_ENC_IMAGES
rc = boot_write_enc_key(fap, 0, bs);
assert(0 == rc);
rc = boot_write_enc_key(fap, 1, bs);
assert(0 == rc);
#endif
rc = boot_write_magic(fap);
assert(0 == rc);
return rc;
}
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;
uint8_t area_id;
int rc = 0;
bs->source = swap_status_source(state);
if (BOOT_STATUS_SOURCE_NONE == bs->source) {
return 0;
}
else if (BOOT_STATUS_SOURCE_PRIMARY_SLOT == bs->source) {
area_id = FLASH_AREA_IMAGE_PRIMARY(BOOT_CURR_IMG(state));
}
else if (BOOT_STATUS_SOURCE_SCRATCH == bs->source) {
area_id = FLASH_AREA_IMAGE_SCRATCH;
}
else {
return -1;
}
rc = flash_area_open(area_id, &fap);
if (rc != 0) {
return -1;
}
rc = flash_area_open(FLASH_AREA_IMAGE_SWAP_STATUS, &fap_stat);
if (rc != 0) {
return -1;
}
rc = swap_read_status_bytes(fap, state, bs);
if (0 == rc) {
off = boot_swap_info_off(fap);
rc = swap_status_retrieve((uint8_t)area_id, off, &swap_info, sizeof swap_info);
if (rc < 0) {
return -1;
}
if (bootutil_buffer_is_erased(fap_stat, &swap_info, sizeof swap_info)) {
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 */