Boot: Sync MCUBoot code base
This patch performs a partial synchronization between the MCUBoot files
in TF-M and in the original repository. The hash of the source commit
in the original MCUBoot repo: 3c469bc698a9767859ed73cd0201c44161204d5c.
Change-Id: I244b47f21ebdfc73381accc007ee88737f7ccdf7
Signed-off-by: David Vincze <david.vincze@arm.com>
diff --git a/bl2/ext/mcuboot/bootutil/src/bootutil_misc.c b/bl2/ext/mcuboot/bootutil/src/bootutil_misc.c
index b4c6ee7..5ad8bcf 100644
--- a/bl2/ext/mcuboot/bootutil/src/bootutil_misc.c
+++ b/bl2/ext/mcuboot/bootutil/src/bootutil_misc.c
@@ -112,27 +112,45 @@
return BOOT_FLAG_SET;
}
+/**
+ * Determines if a status source table is satisfied by the specified magic
+ * code.
+ *
+ * @param tbl_val A magic field from a status source table.
+ * @param val The magic value in a trailer, encoded as a
+ * BOOT_MAGIC_[...].
+ *
+ * @return 1 if the two values are compatible;
+ * 0 otherwise.
+ */
+int
+boot_magic_compatible_check(uint8_t tbl_val, uint8_t val)
+{
+ switch (tbl_val) {
+ case BOOT_MAGIC_ANY:
+ return 1;
+
+ case BOOT_MAGIC_NOTGOOD:
+ return val != BOOT_MAGIC_GOOD;
+
+ default:
+ return tbl_val == val;
+ }
+}
+
uint32_t
-boot_slots_trailer_sz(uint8_t min_write_sz)
+boot_trailer_sz(uint8_t min_write_sz)
{
return /* state for all sectors */
BOOT_STATUS_MAX_ENTRIES * BOOT_STATUS_STATE_COUNT * min_write_sz +
- BOOT_MAX_ALIGN * 3 /* copy_done + image_ok + swap_size */ +
- BOOT_MAGIC_SZ;
-}
-
-static uint32_t
-boot_scratch_trailer_sz(uint8_t min_write_sz)
-{
- return BOOT_STATUS_STATE_COUNT * min_write_sz + /* state for one sector */
- BOOT_MAX_ALIGN * 2 + /* image_ok + swap_size */
+ /* swap_type + copy_done + image_ok + swap_size */
+ BOOT_MAX_ALIGN * 4 +
BOOT_MAGIC_SZ;
}
static uint32_t
boot_magic_off(const struct flash_area *fap)
{
- assert(offsetof(struct image_trailer, magic) == 16);
return fap->fa_size - BOOT_MAGIC_SZ;
}
@@ -158,43 +176,34 @@
elem_sz = flash_area_align(fap);
- if (fap->fa_id == FLASH_AREA_IMAGE_SCRATCH) {
- off_from_end = boot_scratch_trailer_sz(elem_sz);
- } else {
- off_from_end = boot_slots_trailer_sz(elem_sz);
- }
+ off_from_end = boot_trailer_sz(elem_sz);
assert(off_from_end <= fap->fa_size);
return fap->fa_size - off_from_end;
}
+uint32_t
+boot_swap_type_off(const struct flash_area *fap)
+{
+ return fap->fa_size - BOOT_MAGIC_SZ - BOOT_MAX_ALIGN * 3;
+}
+
static uint32_t
boot_copy_done_off(const struct flash_area *fap)
{
- assert(fap->fa_id != FLASH_AREA_IMAGE_SCRATCH);
- assert(offsetof(struct image_trailer, copy_done) == 0);
return fap->fa_size - BOOT_MAGIC_SZ - BOOT_MAX_ALIGN * 2;
}
static uint32_t
boot_image_ok_off(const struct flash_area *fap)
{
- assert(offsetof(struct image_trailer, image_ok) == 8);
return fap->fa_size - BOOT_MAGIC_SZ - BOOT_MAX_ALIGN;
}
static uint32_t
boot_swap_size_off(const struct flash_area *fap)
{
- /*
- * The "swap_size" field if located just before the trailer.
- * The scratch slot doesn't store "copy_done"...
- */
- if (fap->fa_id == FLASH_AREA_IMAGE_SCRATCH) {
- return fap->fa_size - BOOT_MAGIC_SZ - BOOT_MAX_ALIGN * 2;
- }
-
- return fap->fa_size - BOOT_MAGIC_SZ - BOOT_MAX_ALIGN * 3;
+ return fap->fa_size - BOOT_MAGIC_SZ - BOOT_MAX_ALIGN * 4;
}
int
@@ -216,22 +225,31 @@
state->magic = boot_magic_decode(magic);
}
- if (fap->fa_id != FLASH_AREA_IMAGE_SCRATCH) {
- off = boot_copy_done_off(fap);
- rc = flash_area_read_is_empty(fap, off, &state->copy_done,
- sizeof state->copy_done);
- if (rc < 0) {
- return BOOT_EFLASH;
- }
- if (rc == 1) {
- state->copy_done = BOOT_FLAG_UNSET;
- } else {
- state->copy_done = boot_flag_decode(state->copy_done);
- }
+ off = boot_swap_type_off(fap);
+ rc = flash_area_read_is_empty(fap, off, &state->swap_type,
+ sizeof state->swap_type);
+ if (rc < 0) {
+ return BOOT_EFLASH;
+ }
+ if (rc == 1 || state->swap_type > BOOT_SWAP_TYPE_REVERT) {
+ state->swap_type = BOOT_SWAP_TYPE_NONE;
+ }
+
+ off = boot_copy_done_off(fap);
+ rc = flash_area_read_is_empty(fap, off, &state->copy_done,
+ sizeof state->copy_done);
+ if (rc < 0) {
+ return BOOT_EFLASH;
+ }
+ if (rc == 1) {
+ state->copy_done = BOOT_FLAG_UNSET;
+ } else {
+ state->copy_done = boot_flag_decode(state->copy_done);
}
off = boot_image_ok_off(fap);
- rc = flash_area_read_is_empty(fap, off, &state->image_ok, sizeof state->image_ok);
+ rc = flash_area_read_is_empty(fap, off, &state->image_ok,
+ sizeof state->image_ok);
if (rc < 0) {
return BOOT_EFLASH;
}
@@ -341,6 +359,8 @@
off = boot_magic_off(fap);
+ BOOT_LOG_DBG("writing magic; fa_id=%d off=0x%x (0x%x)",
+ fap->fa_id, off, fap->fa_off + off);
rc = flash_area_write(fap, off, boot_img_magic, BOOT_MAGIC_SZ);
if (rc != 0) {
return BOOT_EFLASH;
@@ -350,30 +370,19 @@
}
static int
-boot_write_flag(int flag, const struct flash_area *fap)
+boot_write_trailer_byte(const struct flash_area *fap, uint32_t off,
+ uint8_t val)
{
- uint32_t off;
- int rc;
uint8_t buf[BOOT_MAX_ALIGN];
uint8_t align;
uint8_t erased_val;
-
- switch (flag) {
- case BOOT_FLAG_COPY_DONE:
- off = boot_copy_done_off(fap);
- break;
- case BOOT_FLAG_IMAGE_OK:
- off = boot_image_ok_off(fap);
- break;
- default:
- return BOOT_EBADARGS;
- }
+ int rc;
align = flash_area_align(fap);
assert(align <= BOOT_MAX_ALIGN);
erased_val = flash_area_erased_val(fap);
memset(buf, erased_val, BOOT_MAX_ALIGN);
- buf[0] = BOOT_FLAG_SET;
+ buf[0] = val;
rc = flash_area_write(fap, off, buf, align);
if (rc != 0) {
@@ -386,13 +395,39 @@
int
boot_write_copy_done(const struct flash_area *fap)
{
- return boot_write_flag(BOOT_FLAG_COPY_DONE, fap);
+ uint32_t off;
+
+ off = boot_copy_done_off(fap);
+ BOOT_LOG_DBG("writing copy_done; fa_id=%d off=0x%x (0x%x)",
+ fap->fa_id, off, fap->fa_off + off);
+ return boot_write_trailer_byte(fap, off, BOOT_FLAG_SET);
}
int
boot_write_image_ok(const struct flash_area *fap)
{
- return boot_write_flag(BOOT_FLAG_IMAGE_OK, fap);
+ uint32_t off;
+
+ off = boot_image_ok_off(fap);
+ BOOT_LOG_DBG("writing image_ok; fa_id=%d off=0x%x (0x%x)",
+ fap->fa_id, off, fap->fa_off + off);
+ return boot_write_trailer_byte(fap, off, BOOT_FLAG_SET);
+}
+
+/**
+ * Writes the specified value to the `swap-type` field of an image trailer.
+ * This value is persisted so that the boot loader knows what swap operation to
+ * resume in case of an unexpected reset.
+ */
+int
+boot_write_swap_type(const struct flash_area *fap, uint8_t swap_type)
+{
+ uint32_t off;
+
+ off = boot_swap_type_off(fap);
+ BOOT_LOG_DBG("writing swap_type; fa_id=%d off=0x%x (0x%x), swap_type=0x%x",
+ fap->fa_id, off, fap->fa_off + off, swap_type);
+ return boot_write_trailer_byte(fap, off, swap_type);
}
int
@@ -414,6 +449,9 @@
memset(buf, erased_val, BOOT_MAX_ALIGN);
memcpy(buf, (uint8_t *)&swap_size, sizeof(swap_size));
+ BOOT_LOG_DBG("writing swap_size; fa_id=%d off=0x%x (0x%x)",
+ fap->fa_id, off, fap->fa_off + off);
+
rc = flash_area_write(fap, off, buf, align);
if (rc != 0) {
return BOOT_EFLASH;
@@ -445,10 +483,10 @@
for (i = 0; i < BOOT_SWAP_TABLES_COUNT; i++) {
table = boot_swap_tables + i;
- if ((table->magic_primary_slot == BOOT_MAGIC_ANY ||
- table->magic_primary_slot == primary_slot.magic) &&
- (table->magic_secondary_slot == BOOT_MAGIC_ANY ||
- table->magic_secondary_slot == secondary_slot.magic) &&
+ if (boot_magic_compatible_check(table->magic_primary_slot,
+ primary_slot.magic) &&
+ boot_magic_compatible_check(table->magic_secondary_slot,
+ secondary_slot.magic) &&
(table->image_ok_primary_slot == BOOT_FLAG_ANY ||
table->image_ok_primary_slot == primary_slot.image_ok) &&
(table->image_ok_secondary_slot == BOOT_FLAG_ANY ||
@@ -487,6 +525,7 @@
{
const struct flash_area *fap = NULL;
struct boot_swap_state state_secondary_slot;
+ uint8_t swap_type;
int rc;
rc = boot_read_swap_state_by_id(FLASH_AREA_IMAGE_SECONDARY,
@@ -512,13 +551,34 @@
rc = boot_write_image_ok(fap);
}
+ if (rc == 0) {
+ if (permanent) {
+ swap_type = BOOT_SWAP_TYPE_PERM;
+ } else {
+ swap_type = BOOT_SWAP_TYPE_TEST;
+ }
+ rc = boot_write_swap_type(fap, swap_type);
+ }
+
flash_area_close(fap);
return rc;
+ case BOOT_MAGIC_BAD:
+ /* The image slot is corrupt. There is no way to recover, so erase the
+ * slot to allow future upgrades.
+ */
+ rc = flash_area_open(FLASH_AREA_IMAGE_SECONDARY, &fap);
+ if (rc != 0) {
+ return BOOT_EFLASH;
+ }
+
+ flash_area_erase(fap, 0, fap->fa_size);
+ flash_area_close(fap);
+ return BOOT_EBADIMAGE;
+
default:
- /* XXX: Temporary assert. */
assert(0);
- return -1;
+ return BOOT_EBADIMAGE;
}
}