boot: Add free space check for swap without scratch
Add a missing test which ensures that there is enough free sectors to
perform an upgrade when using the move strategy; this basically checks
that the sectors used by the trailer don't overlap the last sector
required for a move up operation.
Signed-off-by: Fabio Utzig <utzig@apache.org>
diff --git a/boot/bootutil/src/bootutil_priv.h b/boot/bootutil/src/bootutil_priv.h
index 99c94dd..d58ed41 100644
--- a/boot/bootutil/src/bootutil_priv.h
+++ b/boot/bootutil/src/bootutil_priv.h
@@ -280,6 +280,7 @@
const struct flash_area *fap_dst,
uint32_t off_src, uint32_t off_dst, uint32_t sz);
int boot_erase_region(const struct flash_area *fap, uint32_t off, uint32_t sz);
+bool boot_status_is_reset(const struct boot_status *bs);
#ifdef MCUBOOT_ENC_IMAGES
int boot_write_enc_key(const struct flash_area *fap, uint8_t slot,
diff --git a/boot/bootutil/src/swap_move.c b/boot/bootutil/src/swap_move.c
index b18c206..689e987 100644
--- a/boot/bootutil/src/swap_move.c
+++ b/boot/bootutil/src/swap_move.c
@@ -418,27 +418,51 @@
uint32_t copy_size)
{
uint32_t sz;
+ uint32_t sector_sz;
uint32_t idx;
- uint32_t slot_size;
+ uint32_t trailer_sz;
+ uint32_t first_trailer_idx;
uint8_t image_index;
const struct flash_area *fap_pri;
const struct flash_area *fap_sec;
int rc;
- slot_size = 0;
+ sz = 0;
g_last_idx = 0;
- //FIXME: assume all sectors of same size and just do math here...
- sz = boot_img_sector_size(state, BOOT_PRIMARY_SLOT, 0);
+ sector_sz = boot_img_sector_size(state, BOOT_PRIMARY_SLOT, 0);
while (1) {
- slot_size += sz;
+ sz += sector_sz;
/* Skip to next sector because all sectors will be moved up. */
g_last_idx++;
- if (slot_size >= copy_size) {
+ if (sz >= copy_size) {
break;
}
}
+ /*
+ * When starting a new swap upgrade, check that there is enough space.
+ */
+ if (boot_status_is_reset(bs)) {
+ sz = 0;
+ trailer_sz = boot_trailer_sz(BOOT_WRITE_SZ(state));
+ first_trailer_idx = boot_img_num_sectors(state, BOOT_PRIMARY_SLOT) - 1;
+
+ while (1) {
+ sz += sector_sz;
+ if (sz >= trailer_sz) {
+ break;
+ }
+ first_trailer_idx--;
+ }
+
+ if (g_last_idx >= first_trailer_idx) {
+ BOOT_LOG_WRN("Not enough free space to run swap upgrade");
+ bs->swap_type = BOOT_SWAP_TYPE_NONE;
+ return;
+ }
+ }
+
image_index = BOOT_CURR_IMG(state);
rc = flash_area_open(FLASH_AREA_IMAGE_PRIMARY(image_index), &fap_pri);
@@ -449,13 +473,11 @@
fixup_revert(state, bs, fap_sec, FLASH_AREA_IMAGE_SECONDARY(image_index));
- /* FIXME: assure last sector does not overrun trailer */
-
if (bs->op == BOOT_STATUS_OP_MOVE) {
idx = g_last_idx;
while (idx > 0) {
if (idx <= (g_last_idx - bs->idx + 1)) {
- boot_move_sector_up(idx, sz, state, bs, fap_pri, fap_sec);
+ boot_move_sector_up(idx, sector_sz, state, bs, fap_pri, fap_sec);
}
idx--;
}
@@ -467,7 +489,7 @@
idx = 1;
while (idx <= g_last_idx) {
if (idx >= bs->idx) {
- boot_swap_sectors(idx, sz, state, bs, fap_pri, fap_sec);
+ boot_swap_sectors(idx, sector_sz, state, bs, fap_pri, fap_sec);
}
idx++;
}