Boot: Synchronize MCUBoot code base
Perform a partial synchronization between the MCUBoot files in TF-M
and in the original repository. The hash of the source commit in the
original repository: 4f0ea747c314547daa6b6299ccbd77ae4dee6758.
Main changes:
- Remove current_image global variable and make it part
of the boot state struct
- Update routines to receive the boot state by parameter
- Refactor dependency check functions
- Reorganize the flash map and related files
- Fix swap status control
Change-Id: Ibe948792b306e96282fb82447bb3f05a0c6389ef
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 f83db99..8af74ca 100644
--- a/bl2/ext/mcuboot/bootutil/src/bootutil_misc.c
+++ b/bl2/ext/mcuboot/bootutil/src/bootutil_misc.c
@@ -20,7 +20,7 @@
/*
* Original code taken from mcuboot project at:
* https://github.com/JuulLabs-OSS/mcuboot
- * Git SHA of the original version: 3c469bc698a9767859ed73cd0201c44161204d5c
+ * Git SHA of the original version: 4f0ea747c314547daa6b6299ccbd77ae4dee6758
* Modifications are Copyright (c) 2019 Arm Limited.
*/
@@ -36,6 +36,7 @@
#include "bootutil_priv.h"
#include "bootutil/bootutil_log.h"
+/* Currently only used by imgmgr */
int boot_current_slot;
const uint32_t boot_img_magic[] = {
@@ -182,23 +183,16 @@
BOOT_MAGIC_SZ;
}
-static uint32_t
-boot_magic_off(const struct flash_area *fap)
-{
- return fap->fa_size - BOOT_MAGIC_SZ;
-}
-
int
-boot_status_entries(const struct flash_area *fap)
+boot_status_entries(int image_index, const struct flash_area *fap)
{
if (fap->fa_id == FLASH_AREA_IMAGE_SCRATCH) {
return BOOT_STATUS_STATE_COUNT;
- } else if ((fap->fa_id == FLASH_AREA_IMAGE_PRIMARY) ||
- (fap->fa_id == FLASH_AREA_IMAGE_SECONDARY)) {
+ } else if ((fap->fa_id == FLASH_AREA_IMAGE_PRIMARY(image_index)) ||
+ (fap->fa_id == FLASH_AREA_IMAGE_SECONDARY(image_index))) {
return BOOT_STATUS_STATE_COUNT * BOOT_STATUS_MAX_ENTRIES;
- } else {
- return BOOT_EBADARGS;
}
+ return -1;
}
uint32_t
@@ -215,28 +209,34 @@
return fap->fa_size - off_from_end;
}
+static inline uint32_t
+boot_magic_off(const struct flash_area *fap)
+{
+ return fap->fa_size - BOOT_MAGIC_SZ;
+}
+
+static inline uint32_t
+boot_image_ok_off(const struct flash_area *fap)
+{
+ return boot_magic_off(fap) - BOOT_MAX_ALIGN;
+}
+
+static inline uint32_t
+boot_copy_done_off(const struct flash_area *fap)
+{
+ return boot_image_ok_off(fap) - BOOT_MAX_ALIGN;
+}
+
uint32_t
boot_swap_info_off(const struct flash_area *fap)
{
- return fap->fa_size - BOOT_MAGIC_SZ - BOOT_MAX_ALIGN * 3;
+ return boot_copy_done_off(fap) - BOOT_MAX_ALIGN;
}
-static uint32_t
-boot_copy_done_off(const struct flash_area *fap)
-{
- return fap->fa_size - BOOT_MAGIC_SZ - BOOT_MAX_ALIGN * 2;
-}
-
-static uint32_t
-boot_image_ok_off(const struct flash_area *fap)
-{
- return fap->fa_size - BOOT_MAGIC_SZ - BOOT_MAX_ALIGN;
-}
-
-static uint32_t
+static inline uint32_t
boot_swap_size_off(const struct flash_area *fap)
{
- return fap->fa_size - BOOT_MAGIC_SZ - BOOT_MAX_ALIGN * 4;
+ return boot_swap_info_off(fap) - BOOT_MAX_ALIGN;
}
int
@@ -310,15 +310,9 @@
const struct flash_area *fap;
int rc;
- if (flash_area_id == FLASH_AREA_IMAGE_SCRATCH ||
- flash_area_id == FLASH_AREA_IMAGE_PRIMARY ||
- flash_area_id == FLASH_AREA_IMAGE_SECONDARY) {
- rc = flash_area_open(flash_area_id, &fap);
- if (rc != 0) {
- return BOOT_EFLASH;
- }
- } else {
- return BOOT_EBADARGS;
+ rc = flash_area_open(flash_area_id, &fap);
+ if (rc != 0) {
+ return BOOT_EFLASH;
}
rc = boot_read_swap_state(fap, state);
@@ -326,68 +320,76 @@
return rc;
}
-int
-boot_read_swap_size(uint32_t *swap_size)
+/**
+ * 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 sucessfully 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)
{
uint32_t magic[BOOT_MAGIC_ARR_SZ];
uint32_t off;
+ uint8_t areas[2] = {
+ FLASH_AREA_IMAGE_PRIMARY(image_index),
+ FLASH_AREA_IMAGE_SCRATCH,
+ };
+ unsigned int i;
+ int rc;
+
+ /*
+ * 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.
+ */
+
+ for (i = 0; i < sizeof(areas) / sizeof(areas[0]); i++) {
+ rc = flash_area_open(areas[i], fap);
+ if (rc != 0) {
+ return rc;
+ }
+
+ off = boot_magic_off(*fap);
+ rc = flash_area_read(*fap, off, magic, BOOT_MAGIC_SZ);
+ if (rc != 0) {
+ flash_area_close(*fap);
+ return rc;
+ }
+
+ if (memcmp(magic, boot_img_magic, BOOT_MAGIC_SZ) == 0) {
+ return 0;
+ }
+
+ flash_area_close(*fap);
+ }
+
+ /* If we got here, no magic was found */
+ return -1;
+}
+
+int
+boot_read_swap_size(int image_index, uint32_t *swap_size)
+{
+ uint32_t off;
const struct flash_area *fap;
int rc;
- /*
- * In the middle a swap, tries to locate the saved swap size. Looks
- * for 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 swap size is too, because
- * magic is always written in the last step.
- */
-
- rc = flash_area_open(FLASH_AREA_IMAGE_PRIMARY, &fap);
- if (rc != 0) {
- return BOOT_EFLASH;
- }
-
- off = boot_magic_off(fap);
- rc = flash_area_read(fap, off, magic, BOOT_MAGIC_SZ);
- if (rc != 0) {
- rc = BOOT_EFLASH;
- goto out;
- }
-
- if (boot_secure_memequal(magic, boot_img_magic, BOOT_MAGIC_SZ) != 0) {
- /*
- * If the primary slot's magic is not valid, try scratch...
- */
-
+ rc = boot_find_status(image_index, &fap);
+ if (rc == 0) {
+ off = boot_swap_size_off(fap);
+ rc = flash_area_read(fap, off, swap_size, sizeof *swap_size);
flash_area_close(fap);
-
- rc = flash_area_open(FLASH_AREA_IMAGE_SCRATCH, &fap);
- if (rc != 0) {
- return BOOT_EFLASH;
- }
-
- off = boot_magic_off(fap);
- rc = flash_area_read(fap, off, magic, BOOT_MAGIC_SZ);
- if (rc != 0) {
- rc = BOOT_EFLASH;
- goto out;
- }
-
- assert(boot_secure_memequal(magic, boot_img_magic, BOOT_MAGIC_SZ) == 0);
}
- off = boot_swap_size_off(fap);
- rc = flash_area_read(fap, off, swap_size, sizeof(*swap_size));
- if (rc != 0) {
- rc = BOOT_EFLASH;
- }
-
-out:
- flash_area_close(fap);
return rc;
}
-
int
boot_write_magic(const struct flash_area *fap)
{
@@ -396,8 +398,9 @@
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);
+ BOOT_LOG_DBG("writing magic; fa_id=%d off=0x%lx (0x%lx)",
+ fap->fa_id, (unsigned long)off,
+ (unsigned long)(fap->fa_off + off));
rc = flash_area_write(fap, off, boot_img_magic, BOOT_MAGIC_SZ);
if (rc != 0) {
return BOOT_EFLASH;
@@ -406,20 +409,30 @@
return 0;
}
+/**
+ * Write trailer data; status bytes, swap_size, etc
+ *
+ * @returns 0 on success, != 0 on error.
+ */
static int
-boot_write_trailer_byte(const struct flash_area *fap, uint32_t off,
- uint8_t val)
+boot_write_trailer(const struct flash_area *fap, uint32_t off,
+ const uint8_t *inbuf, uint8_t inlen)
{
uint8_t buf[BOOT_MAX_ALIGN];
- uint32_t align;
+ uint8_t align;
uint8_t erased_val;
int rc;
align = flash_area_align(fap);
- assert(align <= BOOT_MAX_ALIGN);
+ if (inlen > BOOT_MAX_ALIGN || align > BOOT_MAX_ALIGN) {
+ return -1;
+ }
erased_val = flash_area_erased_val(fap);
- memset(buf, erased_val, BOOT_MAX_ALIGN);
- buf[0] = val;
+ if (align < inlen) {
+ align = inlen;
+ }
+ memcpy(buf, inbuf, inlen);
+ memset(&buf[inlen], erased_val, align - inlen);
rc = flash_area_write(fap, off, buf, align);
if (rc != 0) {
@@ -429,15 +442,24 @@
return 0;
}
+static int
+boot_write_trailer_flag(const struct flash_area *fap, uint32_t off,
+ uint8_t flag_val)
+{
+ const uint8_t buf[1] = { flag_val };
+ return boot_write_trailer(fap, off, buf, 1);
+}
+
int
boot_write_copy_done(const struct flash_area *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);
+ BOOT_LOG_DBG("writing copy_done; fa_id=%d off=0x%lx (0x%lx)",
+ fap->fa_id, (unsigned long)off,
+ (unsigned long)(fap->fa_off + off));
+ return boot_write_trailer_flag(fap, off, BOOT_FLAG_SET);
}
int
@@ -446,9 +468,10 @@
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);
+ BOOT_LOG_DBG("writing image_ok; fa_id=%d off=0x%lx (0x%lx)",
+ fap->fa_id, (unsigned long)off,
+ (unsigned long)(fap->fa_off + off));
+ return boot_write_trailer_flag(fap, off, BOOT_FLAG_SET);
}
/**
@@ -465,46 +488,27 @@
BOOT_SET_SWAP_INFO(swap_info, image_num, swap_type);
off = boot_swap_info_off(fap);
- BOOT_LOG_DBG("writing swap_info; fa_id=%d off=0x%x (0x%x), swap_type=0x%x"
+ BOOT_LOG_DBG("writing swap_info; fa_id=%d off=0x%lx (0x%lx), swap_type=0x%x"
" image_num=0x%x",
- fap->fa_id, off, fap->fa_off + off,
- BOOT_GET_SWAP_TYPE(swap_info),
- BOOT_GET_IMAGE_NUM(swap_info));
- return boot_write_trailer_byte(fap, off, swap_info);
+ fap->fa_id, (unsigned long)off,
+ (unsigned long)(fap->fa_off + off), swap_type, image_num);
+ return boot_write_trailer(fap, off, (const uint8_t *) &swap_info, 1);
}
int
boot_write_swap_size(const struct flash_area *fap, uint32_t swap_size)
{
uint32_t off;
- int rc;
- uint8_t buf[BOOT_MAX_ALIGN];
- uint32_t align;
- uint8_t erased_val;
off = boot_swap_size_off(fap);
- align = flash_area_align(fap);
- assert(align <= BOOT_MAX_ALIGN);
- if (align < sizeof(swap_size)) {
- align = sizeof(swap_size);
- }
- erased_val = flash_area_erased_val(fap);
- 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;
- }
-
- return 0;
+ BOOT_LOG_DBG("writing swap_size; fa_id=%d off=0x%lx (0x%lx)",
+ fap->fa_id, (unsigned long)off,
+ (unsigned long)fap->fa_off + off);
+ return boot_write_trailer(fap, off, (const uint8_t *) &swap_size, 4);
}
int
-boot_swap_type(void)
+boot_swap_type_multi(int image_index)
{
const struct boot_swap_table *table;
struct boot_swap_state primary_slot;
@@ -512,12 +516,13 @@
int rc;
size_t i;
- rc = boot_read_swap_state_by_id(FLASH_AREA_IMAGE_PRIMARY, &primary_slot);
+ rc = boot_read_swap_state_by_id(FLASH_AREA_IMAGE_PRIMARY(image_index),
+ &primary_slot);
if (rc) {
return BOOT_SWAP_TYPE_PANIC;
}
- rc = boot_read_swap_state_by_id(FLASH_AREA_IMAGE_SECONDARY,
+ rc = boot_read_swap_state_by_id(FLASH_AREA_IMAGE_SECONDARY(image_index),
&secondary_slot);
if (rc) {
return BOOT_SWAP_TYPE_PANIC;
@@ -541,9 +546,11 @@
table->swap_type == BOOT_SWAP_TYPE_PERM ? "perm" :
table->swap_type == BOOT_SWAP_TYPE_REVERT ? "revert" :
"BUG; can't happen");
- assert(table->swap_type == BOOT_SWAP_TYPE_TEST ||
- table->swap_type == BOOT_SWAP_TYPE_PERM ||
- table->swap_type == BOOT_SWAP_TYPE_REVERT);
+ if (table->swap_type != BOOT_SWAP_TYPE_TEST &&
+ table->swap_type != BOOT_SWAP_TYPE_PERM &&
+ table->swap_type != BOOT_SWAP_TYPE_REVERT) {
+ return BOOT_SWAP_TYPE_PANIC;
+ }
return table->swap_type;
}
}
@@ -552,6 +559,16 @@
return BOOT_SWAP_TYPE_NONE;
}
+/*
+ * This function is not used by the bootloader itself, but its required API
+ * by external tooling like mcumgr.
+ */
+int
+boot_swap_type(void)
+{
+ return boot_swap_type_multi(0);
+}
+
/**
* Marks the image in the secondary slot as pending. On the next reboot,
* the system will perform a one-time boot of the the secondary slot image.
@@ -571,7 +588,7 @@
uint8_t swap_type;
int rc;
- rc = boot_read_swap_state_by_id(FLASH_AREA_IMAGE_SECONDARY,
+ rc = boot_read_swap_state_by_id(FLASH_AREA_IMAGE_SECONDARY(0),
&state_secondary_slot);
if (rc != 0) {
return rc;
@@ -583,7 +600,7 @@
return 0;
case BOOT_MAGIC_UNSET:
- rc = flash_area_open(FLASH_AREA_IMAGE_SECONDARY, &fap);
+ rc = flash_area_open(FLASH_AREA_IMAGE_SECONDARY(0), &fap);
if (rc != 0) {
rc = BOOT_EFLASH;
} else {
@@ -610,7 +627,7 @@
/* 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);
+ rc = flash_area_open(FLASH_AREA_IMAGE_SECONDARY(0), &fap);
if (rc != 0) {
return BOOT_EFLASH;
}
@@ -639,7 +656,7 @@
struct boot_swap_state state_primary_slot;
int rc;
- rc = boot_read_swap_state_by_id(FLASH_AREA_IMAGE_PRIMARY,
+ rc = boot_read_swap_state_by_id(FLASH_AREA_IMAGE_PRIMARY(0),
&state_primary_slot);
if (rc != 0) {
return rc;
@@ -659,6 +676,12 @@
return BOOT_EBADVECT;
}
+ rc = flash_area_open(FLASH_AREA_IMAGE_PRIMARY(0), &fap);
+ if (rc) {
+ rc = BOOT_EFLASH;
+ goto done;
+ }
+
if (state_primary_slot.copy_done == BOOT_FLAG_UNSET) {
/* Swap never completed. This is unexpected. */
rc = BOOT_EBADVECT;
@@ -670,59 +693,13 @@
goto done;
}
- rc = flash_area_open(FLASH_AREA_IMAGE_PRIMARY, &fap);
- if (rc) {
- rc = BOOT_EFLASH;
- goto done;
- }
-
rc = boot_write_image_ok(fap);
- if (rc != 0) {
- goto done;
- }
-
- rc = 0;
done:
flash_area_close(fap);
return rc;
}
-#if (BOOT_IMAGE_NUMBER > 1)
-/**
- * Check if the version of the image is not older than required.
- *
- * @param req Required minimal image version.
- * @param ver Version of the image to be checked.
- *
- * @return 0 if the version is sufficient, nonzero otherwise.
- */
-int
-boot_is_version_sufficient(struct image_version *req,
- struct image_version *ver)
-{
- if (ver->iv_major > req->iv_major) {
- return 0;
- }
- if (ver->iv_major < req->iv_major) {
- return BOOT_EBADVERSION;
- }
- /* The major version numbers are equal. */
- if (ver->iv_minor > req->iv_minor) {
- return 0;
- }
- if (ver->iv_minor < req->iv_minor) {
- return BOOT_EBADVERSION;
- }
- /* The minor version numbers are equal. */
- if (ver->iv_revision < req->iv_revision) {
- return BOOT_EBADVERSION;
- }
-
- return 0;
-}
-#endif /* BOOT_IMAGE_NUMBER > 1 */
-
/**
* Checks whether on overflow can happen during a summation operation
*