Fix swap status control
This fixes two issues related to swap status control:
1. During a swap, the status was written offset by one, because it was
being incremented before it was written to flash. With the increment
happening early the offset was calculated always one position after
where it should be, which would leave the first status index free,
and override the last one (worst case scenario).
2. When an image is too big it requires the swap status to be
temporarily stored on scratch, to allow the last sector on the
primary slot to be erased. The status is written to scratch for 2
status updates, and afterwards copied back to the primary slot, which
then receives future status updates. The code that copied the status
back from scratch to the primary slot was erroneously copying the space
of 3 status writes, which would result in a write over non-erased area
for the third byte.
Signed-off-by: Fabio Utzig <utzig@apache.org>
diff --git a/boot/bootutil/src/loader.c b/boot/bootutil/src/loader.c
index 466ea8c..4da6e8e 100644
--- a/boot/bootutil/src/loader.c
+++ b/boot/bootutil/src/loader.c
@@ -646,7 +646,6 @@
if (!found_idx) {
found_idx = i;
}
- found_idx--;
bs->idx = (found_idx / BOOT_STATUS_STATE_COUNT) + 1;
bs->state = (found_idx % BOOT_STATUS_STATE_COUNT) + 1;
}
@@ -1332,8 +1331,8 @@
img_off, 0, copy_sz);
assert(rc == 0);
- bs->state = BOOT_STATUS_STATE_1;
rc = boot_write_status(state, bs);
+ bs->state = BOOT_STATUS_STATE_1;
BOOT_STATUS_ASSERT(rc == 0);
}
@@ -1353,8 +1352,8 @@
assert(rc == 0);
}
- bs->state = BOOT_STATUS_STATE_2;
rc = boot_write_status(state, bs);
+ bs->state = BOOT_STATUS_STATE_2;
BOOT_STATUS_ASSERT(rc == 0);
}
@@ -1375,7 +1374,7 @@
/* copy current status that is being maintained in scratch */
rc = boot_copy_sector(state, fap_scratch, fap_primary_slot,
scratch_trailer_off, img_off + copy_sz,
- BOOT_STATUS_STATE_COUNT * BOOT_WRITE_SZ(state));
+ (BOOT_STATUS_STATE_COUNT - 1) * BOOT_WRITE_SZ(state));
BOOT_STATUS_ASSERT(rc == 0);
rc = boot_read_swap_state_by_id(FLASH_AREA_IMAGE_SCRATCH,
@@ -1415,9 +1414,9 @@
erase_scratch = bs->use_scratch;
bs->use_scratch = 0;
+ rc = boot_write_status(state, bs);
bs->idx++;
bs->state = BOOT_STATUS_STATE_0;
- rc = boot_write_status(state, bs);
BOOT_STATUS_ASSERT(rc == 0);
if (erase_scratch) {