Implement new swap scheme for devices with large erase size using scratch with status area
diff --git a/boot/bootutil/src/swap_scratch.c b/boot/bootutil/src/swap_scratch.c
index 55fa61f..9b9228a 100644
--- a/boot/bootutil/src/swap_scratch.c
+++ b/boot/bootutil/src/swap_scratch.c
@@ -24,13 +24,16 @@
#include "bootutil/bootutil.h"
#include "bootutil_priv.h"
#include "swap_priv.h"
+#ifdef MCUBOOT_SWAP_USING_STATUS
+#include "swap_status.h"
+#endif
#include "bootutil/bootutil_log.h"
#include "mcuboot_config/mcuboot_config.h"
MCUBOOT_LOG_MODULE_DECLARE(mcuboot);
-#if !defined(MCUBOOT_SWAP_USING_MOVE)
+#ifndef MCUBOOT_SWAP_USING_MOVE
#if defined(MCUBOOT_VALIDATE_PRIMARY_SLOT)
/*
@@ -45,7 +48,7 @@
} while (0)
#else
#define BOOT_STATUS_ASSERT(x) ASSERT(x)
-#endif
+#endif /* defined(MCUBOOT_VALIDATE_PRIMARY_SLOT) */
int
boot_read_image_header(struct boot_loader_state *state, int slot,
@@ -55,12 +58,30 @@
int area_id;
int rc;
+ int saved_slot = slot;
+
(void)bs;
#if (BOOT_IMAGE_NUMBER == 1)
(void)state;
#endif
+ if (bs != NULL) {
+ if (bs->state == BOOT_STATUS_STATE_1) {
+ if (slot == 1) {
+ slot = 2;
+ }
+ }
+ else if (bs->state == BOOT_STATUS_STATE_2) {
+ if (slot == 0) {
+ slot = 1;
+ }
+ else {
+ slot = 2;
+ }
+ }
+ }
+
area_id = flash_area_id_from_multi_image_slot(BOOT_CURR_IMG(state), slot);
rc = flash_area_open(area_id, &fap);
if (rc != 0) {
@@ -68,12 +89,43 @@
goto done;
}
- rc = flash_area_read(fap, 0, out_hdr, sizeof *out_hdr);
- if (rc != 0) {
+ rc = flash_area_read_is_empty(fap, 0, out_hdr, sizeof *out_hdr);
+ if (rc < 0) {
rc = BOOT_EFLASH;
goto done;
}
+ if (rc == 1) {
+ memset(out_hdr, 0, sizeof(*out_hdr));
+ }
+
+ /* We only know where the headers are located when bs is valid */
+ if (bs != NULL && out_hdr->ih_magic != IMAGE_MAGIC) {
+
+ if (bs->state != BOOT_STATUS_STATE_0) {
+
+ flash_area_close(fap);
+
+ area_id = flash_area_id_from_multi_image_slot(BOOT_CURR_IMG(state), saved_slot);
+ rc = flash_area_open(area_id, &fap);
+ if (rc != 0) {
+ rc = BOOT_EFLASH;
+ goto done;
+ }
+
+ rc = flash_area_read(fap, 0, out_hdr, sizeof *out_hdr);
+ if (rc < 0) {
+ rc = BOOT_EFLASH;
+ goto done;
+ }
+
+ if (out_hdr->ih_magic != IMAGE_MAGIC) {
+ rc = -1;
+ goto done;
+ }
+ }
+ }
+
rc = 0;
done:
@@ -82,6 +134,8 @@
}
#if !defined(MCUBOOT_DIRECT_XIP) && !defined(MCUBOOT_RAM_LOAD)
+
+#ifndef MCUBOOT_SWAP_USING_STATUS
/**
* Reads the status of a partially-completed swap, if any. This is necessary
* to recover in case the boot lodaer was reset in the middle of a swap
@@ -165,6 +219,7 @@
return (bs->idx - BOOT_STATUS_IDX_0) * idx_sz +
(bs->state - BOOT_STATUS_STATE_0) * elem_sz;
}
+#endif /* !MCUBOOT_SWAP_USING_STATUS */
/*
* Slots are compatible when all sectors that store up to to size of the image
@@ -187,9 +242,17 @@
num_sectors_primary = boot_img_num_sectors(state, BOOT_PRIMARY_SLOT);
num_sectors_secondary = boot_img_num_sectors(state, BOOT_SECONDARY_SLOT);
+
+ if (num_sectors_secondary == 0) {
+ BOOT_LOG_WRN("Upgrade disabled for image %d", BOOT_CURR_IMG(state));
+ return 0;
+ }
+
if ((num_sectors_primary > BOOT_MAX_IMG_SECTORS) ||
(num_sectors_secondary > BOOT_MAX_IMG_SECTORS)) {
BOOT_LOG_WRN("Cannot upgrade: more sectors than allowed");
+ BOOT_LOG_DBG("sectors_primary (%d) or sectors_secondary (%d) > BOOT_MAX_IMG_SECTORS (%d)",
+ num_sectors_primary, num_sectors_secondary, BOOT_MAX_IMG_SECTORS);
return 0;
}
@@ -399,7 +462,7 @@
source = table->bst_status_source;
#if (BOOT_IMAGE_NUMBER > 1)
- /* In case of multi-image boot it can happen that if boot status
+ /* In case of multi image boot it can happen that if boot status
* info is found on scratch area then it does not belong to the
* currently examined image.
*/
@@ -500,7 +563,8 @@
img_off = boot_img_sector_off(state, BOOT_PRIMARY_SLOT, idx);
copy_sz = sz;
- trailer_sz = boot_trailer_sz(BOOT_WRITE_SZ(state));
+ // trailer_sz = boot_trailer_sz(BOOT_WRITE_SZ(state)); // TODO: fixme for status use case
+ trailer_sz = BOOT_WRITE_SZ(state);
/* sz in this function is always sized on a multiple of the sector size.
* The check against the start offset of the last sector
@@ -557,8 +621,13 @@
assert(rc == 0);
/* Erase the temporary trailer from the scratch area. */
+#ifndef MCUBOOT_SWAP_USING_STATUS
rc = boot_erase_region(fap_scratch, 0, fap_scratch->fa_size);
assert(rc == 0);
+#else
+ rc = swap_erase_trailer_sectors(state, fap_scratch);
+ assert(rc == 0);
+#endif
}
}
@@ -655,8 +724,16 @@
BOOT_STATUS_ASSERT(rc == 0);
if (erase_scratch) {
+#ifndef MCUBOOT_SWAP_USING_STATUS
rc = boot_erase_region(fap_scratch, 0, sz);
assert(rc == 0);
+#else
+ rc = swap_erase_trailer_sectors(state, fap_scratch);
+ assert(rc == 0);
+
+ rc = swap_erase_trailer_sectors(state, fap_secondary_slot); // TODO: check if needed and fix
+ assert(rc == 0);
+#endif
}
}
@@ -709,6 +786,8 @@
last_idx_secondary_slot++;
}
+ bs->op = BOOT_STATUS_OP_SWAP;
+
swap_idx = 0;
while (last_sector_idx >= 0) {
sz = boot_copy_sz(state, last_sector_idx, &first_sector_idx);