Boot: Sync MCUBoot code base
The MCUBoot files were added from the original MCUBoot
repository with version 1.0.0 and since then the code bases
have diverged from each other significantly. This patch
performs a partial synchronization between the MCUBoot files
in TF-M and in the original repo.
The hash of source commit in the original MCUBoot repo:
178be54bd6e5f035cc60e98205535682acd26e64.
The flash interface has also been extended and this patch
includes the implementation of these new functions too.
Change-Id: I16897ba884b56f90c9d35f99b709de86704a11ad
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 a22e6c1..79fdc9a 100644
--- a/bl2/ext/mcuboot/bootutil/src/bootutil_misc.c
+++ b/bl2/ext/mcuboot/bootutil/src/bootutil_misc.c
@@ -26,8 +26,6 @@
#include "bootutil/image.h"
#include "bootutil/bootutil.h"
#include "bootutil_priv.h"
-
-#define BOOT_LOG_LEVEL BOOT_LOG_LEVEL_INFO
#include "bootutil/bootutil_log.h"
int boot_current_slot;
@@ -39,11 +37,13 @@
0x8079b62c,
};
+#define BOOT_MAGIC_ARR_SZ \
+ (sizeof boot_img_magic / sizeof boot_img_magic[0])
+
const uint32_t BOOT_MAGIC_SZ = sizeof(boot_img_magic);
const uint32_t BOOT_MAX_ALIGN = MAX_FLASH_ALIGN;
struct boot_swap_table {
- /** * For each field, a value of 0 means "any". */
uint8_t magic_slot0;
uint8_t magic_slot1;
uint8_t image_ok_slot0;
@@ -65,27 +65,27 @@
*/
static const struct boot_swap_table boot_swap_tables[] = {
{
- .magic_slot0 = 0,
+ .magic_slot0 = BOOT_MAGIC_ANY,
.magic_slot1 = BOOT_MAGIC_GOOD,
- .image_ok_slot0 = 0,
- .image_ok_slot1 = 0xff,
- .copy_done_slot0 = 0,
+ .image_ok_slot0 = BOOT_FLAG_ANY,
+ .image_ok_slot1 = BOOT_FLAG_UNSET,
+ .copy_done_slot0 = BOOT_FLAG_ANY,
.swap_type = BOOT_SWAP_TYPE_TEST,
},
{
- .magic_slot0 = 0,
+ .magic_slot0 = BOOT_MAGIC_ANY,
.magic_slot1 = BOOT_MAGIC_GOOD,
- .image_ok_slot0 = 0,
- .image_ok_slot1 = 0x01,
- .copy_done_slot0 = 0,
+ .image_ok_slot0 = BOOT_FLAG_ANY,
+ .image_ok_slot1 = BOOT_FLAG_SET,
+ .copy_done_slot0 = BOOT_FLAG_ANY,
.swap_type = BOOT_SWAP_TYPE_PERM,
},
{
.magic_slot0 = BOOT_MAGIC_GOOD,
.magic_slot1 = BOOT_MAGIC_UNSET,
- .image_ok_slot0 = 0xff,
- .image_ok_slot1 = 0,
- .copy_done_slot0 = 0x01,
+ .image_ok_slot0 = BOOT_FLAG_UNSET,
+ .image_ok_slot1 = BOOT_FLAG_ANY,
+ .copy_done_slot0 = BOOT_FLAG_SET,
.swap_type = BOOT_SWAP_TYPE_REVERT,
},
};
@@ -93,22 +93,22 @@
#define BOOT_SWAP_TABLES_COUNT \
(sizeof(boot_swap_tables) / sizeof(boot_swap_tables[0]))
-int
-boot_magic_code(const uint32_t *magic)
+static int
+boot_magic_decode(const uint32_t *magic)
{
- int i;
-
if (memcmp(magic, boot_img_magic, BOOT_MAGIC_SZ) == 0) {
return BOOT_MAGIC_GOOD;
}
+ return BOOT_MAGIC_BAD;
+}
- for (i = 0; i < BOOT_MAGIC_SZ / sizeof(*magic); i++) {
- if (magic[i] != 0xffffffff) {
- return BOOT_MAGIC_BAD;
- }
+static int
+boot_flag_decode(uint8_t flag)
+{
+ if (flag != BOOT_FLAG_SET) {
+ return BOOT_FLAG_BAD;
}
-
- return BOOT_MAGIC_UNSET;
+ return BOOT_FLAG_SET;
}
uint32_t
@@ -200,31 +200,45 @@
boot_read_swap_state(const struct flash_area *fap,
struct boot_swap_state *state)
{
- uint32_t magic[BOOT_MAGIC_SZ];
+ uint32_t magic[BOOT_MAGIC_ARR_SZ];
uint32_t off;
int rc;
off = boot_magic_off(fap);
- rc = flash_area_read(fap, off, magic, BOOT_MAGIC_SZ);
- if (rc != 0) {
+ rc = flash_area_read_is_empty(fap, off, magic, BOOT_MAGIC_SZ);
+ if (rc < 0) {
return BOOT_EFLASH;
}
- state->magic = boot_magic_code(magic);
+ if (rc == 1) {
+ state->magic = BOOT_MAGIC_UNSET;
+ } else {
+ state->magic = boot_magic_decode(magic);
+ }
if (fap->fa_id != FLASH_AREA_IMAGE_SCRATCH) {
off = boot_copy_done_off(fap);
- rc = flash_area_read(fap, off, &state->copy_done,
- sizeof(state->copy_done));
- if (rc != 0) {
+ 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(fap, off, &state->image_ok, sizeof(state->image_ok));
- if (rc != 0) {
+ rc = flash_area_read_is_empty(fap, off, &state->image_ok, sizeof state->image_ok);
+ if (rc < 0) {
return BOOT_EFLASH;
}
+ if (rc == 1) {
+ state->image_ok = BOOT_FLAG_UNSET;
+ } else {
+ state->image_ok = boot_flag_decode(state->image_ok);
+ }
return 0;
}
@@ -259,7 +273,7 @@
int
boot_read_swap_size(uint32_t *swap_size)
{
- uint32_t magic[BOOT_MAGIC_SZ];
+ uint32_t magic[BOOT_MAGIC_ARR_SZ];
uint32_t off;
const struct flash_area *fap;
int rc;
@@ -341,6 +355,7 @@
int rc;
uint8_t buf[BOOT_MAX_ALIGN];
uint8_t align;
+ uint8_t erased_val;
switch (flag) {
case BOOT_FLAG_COPY_DONE:
@@ -355,7 +370,8 @@
align = flash_area_align(fap);
assert(align <= BOOT_MAX_ALIGN);
- memset(buf, 0xFF, BOOT_MAX_ALIGN);
+ erased_val = flash_area_erased_val(fap);
+ memset(buf, erased_val, BOOT_MAX_ALIGN);
buf[0] = BOOT_FLAG_SET;
rc = flash_area_write(fap, off, buf, align);
@@ -385,6 +401,7 @@
int rc;
uint8_t buf[BOOT_MAX_ALIGN];
uint8_t align;
+ uint8_t erased_val;
off = boot_swap_size_off(fap);
align = flash_area_align(fap);
@@ -392,7 +409,8 @@
if (align < sizeof(swap_size)) {
align = sizeof(swap_size);
}
- memset(buf, 0xFF, BOOT_MAX_ALIGN);
+ erased_val = flash_area_erased_val(fap);
+ memset(buf, erased_val, BOOT_MAX_ALIGN);
memcpy(buf, (uint8_t *)&swap_size, sizeof(swap_size));
rc = flash_area_write(fap, off, buf, align);
@@ -410,7 +428,7 @@
struct boot_swap_state slot0;
struct boot_swap_state slot1;
int rc;
- int i;
+ size_t i;
rc = boot_read_swap_state_by_id(FLASH_AREA_IMAGE_0, &slot0);
if (rc) {
@@ -425,11 +443,16 @@
for (i = 0; i < BOOT_SWAP_TABLES_COUNT; i++) {
table = boot_swap_tables + i;
- if ((!table->magic_slot0 || table->magic_slot0 == slot0.magic ) &&
- (!table->magic_slot1 || table->magic_slot1 == slot1.magic ) &&
- (!table->image_ok_slot0 || table->image_ok_slot0 == slot0.image_ok ) &&
- (!table->image_ok_slot1 || table->image_ok_slot1 == slot1.image_ok ) &&
- (!table->copy_done_slot0 || table->copy_done_slot0 == slot0.copy_done)) {
+ if ((table->magic_slot0 == BOOT_MAGIC_ANY ||
+ table->magic_slot0 == slot0.magic) &&
+ (table->magic_slot1 == BOOT_MAGIC_ANY ||
+ table->magic_slot1 == slot1.magic) &&
+ (table->image_ok_slot0 == BOOT_FLAG_ANY ||
+ table->image_ok_slot0 == slot0.image_ok) &&
+ (table->image_ok_slot1 == BOOT_FLAG_ANY ||
+ table->image_ok_slot1 == slot1.image_ok) &&
+ (table->copy_done_slot0 == BOOT_FLAG_ANY ||
+ table->copy_done_slot0 == slot0.copy_done)) {
BOOT_LOG_INF("Swap type: %s",
table->swap_type == BOOT_SWAP_TYPE_TEST ? "test" :
table->swap_type == BOOT_SWAP_TYPE_PERM ? "perm" :
@@ -530,12 +553,13 @@
if (state_slot0.copy_done == BOOT_FLAG_UNSET) {
/* Swap never completed. This is unexpected. */
- return BOOT_EBADVECT;
+ rc = BOOT_EBADVECT;
+ goto done;
}
if (state_slot0.image_ok != BOOT_FLAG_UNSET) {
/* Already confirmed. */
- return 0;
+ goto done;
}
rc = flash_area_open(FLASH_AREA_IMAGE_0, &fap);
diff --git a/bl2/ext/mcuboot/bootutil/src/bootutil_priv.h b/bl2/ext/mcuboot/bootutil/src/bootutil_priv.h
index a8969e3..918d2d1 100644
--- a/bl2/ext/mcuboot/bootutil/src/bootutil_priv.h
+++ b/bl2/ext/mcuboot/bootutil/src/bootutil_priv.h
@@ -17,6 +17,13 @@
* under the License.
*/
+/*
+ * Original code taken from mcuboot project at:
+ * https://github.com/JuulLabs-OSS/mcuboot
+ * Git SHA of the original version: 178be54bd6e5f035cc60e98205535682acd26e64
+ * Modifications are Copyright (c) 2018-2019 Arm Limited.
+ */
+
#ifndef H_BOOTUTIL_PRIV_
#define H_BOOTUTIL_PRIV_
@@ -50,9 +57,24 @@
uint32_t swap_size; /* Total size of swapped image */
};
-#define BOOT_MAGIC_GOOD 1
-#define BOOT_MAGIC_BAD 2
-#define BOOT_MAGIC_UNSET 3
+#define BOOT_MAGIC_GOOD 1
+#define BOOT_MAGIC_BAD 2
+#define BOOT_MAGIC_UNSET 3
+#define BOOT_MAGIC_ANY 4 /* NOTE: control only, not dependent on sector */
+
+/*
+ * NOTE: leave BOOT_FLAG_SET equal to one, this is written to flash!
+ */
+#define BOOT_FLAG_SET 1
+#define BOOT_FLAG_BAD 2
+#define BOOT_FLAG_UNSET 3
+#define BOOT_FLAG_ANY 4 /* NOTE: control only, not dependent on sector */
+
+#define BOOT_STATUS_IDX_0 1
+
+#define BOOT_STATUS_STATE_0 1
+#define BOOT_STATUS_STATE_1 2
+#define BOOT_STATUS_STATE_2 3
/**
* End-of-image slot structure.
@@ -66,11 +88,11 @@
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Swap size |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * ~ 0xff padding (MAX ALIGN - 4) ~
+ * ~ padding with erased val (MAX ALIGN - 4) ~
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * | Copy done | 0xff padding (MAX ALIGN - 1) ~
+ * | Copy done | padding with erased val (MAX ALIGN - 1) ~
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * | Image OK | 0xff padding (MAX ALIGN - 1) ~
+ * | Image OK | padding with erased val (MAX ALIGN - 1) ~
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* ~ MAGIC (16 octets) ~
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
@@ -84,7 +106,22 @@
uint8_t image_ok;
};
-#define BOOT_STATUS_STATE_COUNT 3
+/*
+ * The current flashmap API does not check the amount of space allocated when
+ * loading sector data from the flash device, allowing for smaller counts here
+ * would most surely incur in overruns.
+ *
+ * TODO: make flashmap API receive the current sector array size.
+ */
+#if BOOT_MAX_IMG_SECTORS < 32
+#error "Too few sectors, please increase BOOT_MAX_IMG_SECTORS to at least 32"
+#endif
+
+/** Number of image slots in flash; currently limited to two. */
+#define BOOT_NUM_SLOTS 2
+
+/** Maximum number of image sectors supported by the bootloader. */
+#define BOOT_STATUS_STATE_COUNT 3
#define BOOT_STATUS_SOURCE_NONE 0
#define BOOT_STATUS_SOURCE_SCRATCH 1
@@ -93,14 +130,8 @@
#define BOOT_FLAG_IMAGE_OK 0
#define BOOT_FLAG_COPY_DONE 1
-#define BOOT_FLAG_SET 0x01
-#define BOOT_FLAG_UNSET 0xff
-
extern const uint32_t BOOT_MAGIC_SZ;
-/** Number of image slots in flash; currently limited to two. */
-#define BOOT_NUM_SLOTS 2
-
/**
* Compatibility shim for flash sector type.
*
@@ -126,8 +157,8 @@
uint8_t write_sz;
};
-int bootutil_verify_sig(uint8_t *hash, uint32_t hlen, uint8_t *sig, int slen,
- uint8_t key_id);
+int bootutil_verify_sig(uint8_t *hash, uint32_t hlen, uint8_t *sig,
+ size_t slen, uint8_t key_id);
uint32_t boot_slots_trailer_sz(uint8_t min_write_sz);
int boot_status_entries(const struct flash_area *fap);
diff --git a/bl2/ext/mcuboot/bootutil/src/image_rsa.c b/bl2/ext/mcuboot/bootutil/src/image_rsa.c
index 3b100e3..3ab03ce 100644
--- a/bl2/ext/mcuboot/bootutil/src/image_rsa.c
+++ b/bl2/ext/mcuboot/bootutil/src/image_rsa.c
@@ -17,6 +17,13 @@
* under the License.
*/
+/*
+ * Original code taken from mcuboot project at:
+ * https://github.com/JuulLabs-OSS/mcuboot
+ * Git SHA of the original version: 178be54bd6e5f035cc60e98205535682acd26e64
+ * Modifications are Copyright (c) 2018-2019 Arm Limited.
+ */
+
#include <string.h>
#ifdef MCUBOOT_SIGN_RSA
@@ -264,7 +271,7 @@
}
int
-bootutil_verify_sig(uint8_t *hash, uint32_t hlen, uint8_t *sig, int slen,
+bootutil_verify_sig(uint8_t *hash, uint32_t hlen, uint8_t *sig, size_t slen,
uint8_t key_id)
{
mbedtls_rsa_context ctx;
diff --git a/bl2/ext/mcuboot/bootutil/src/image_validate.c b/bl2/ext/mcuboot/bootutil/src/image_validate.c
index f6ae619..5cb4b49 100644
--- a/bl2/ext/mcuboot/bootutil/src/image_validate.c
+++ b/bl2/ext/mcuboot/bootutil/src/image_validate.c
@@ -19,8 +19,9 @@
/*
* Original code taken from mcuboot project at:
- * https://github.com/runtimeco/mcuboot
- * Modifications are Copyright (c) 2018 Arm Limited.
+ * https://github.com/JuulLabs-OSS/mcuboot
+ * Git SHA of the original version: 178be54bd6e5f035cc60e98205535682acd26e64
+ * Modifications are Copyright (c) 2018-2019 Arm Limited.
*/
#include <assert.h>
@@ -62,12 +63,11 @@
bootutil_sha256_update(&sha256_ctx, seed, seed_len);
}
- size = hdr->ih_img_size + hdr->ih_hdr_size;
-
/*
* Hash is computed over image header and image itself. No TLV is
* included ATM.
*/
+ size = hdr->ih_img_size + hdr->ih_hdr_size;
for (off = 0; off < size; off += blk_sz) {
blk_sz = size - off;
if (blk_sz > tmp_buf_sz) {
diff --git a/bl2/ext/mcuboot/bootutil/src/loader.c b/bl2/ext/mcuboot/bootutil/src/loader.c
index 52602b8..b787d32 100644
--- a/bl2/ext/mcuboot/bootutil/src/loader.c
+++ b/bl2/ext/mcuboot/bootutil/src/loader.c
@@ -19,7 +19,8 @@
/*
* Original code taken from mcuboot project at:
- * https://github.com/runtimeco/mcuboot
+ * https://github.com/JuulLabs-OSS/mcuboot
+ * Git SHA of the original version: 178be54bd6e5f035cc60e98205535682acd26e64
* Modifications are Copyright (c) 2018-2019 Arm Limited.
*/
@@ -47,10 +48,20 @@
static struct boot_loader_state boot_data;
#if !defined(MCUBOOT_NO_SWAP) && !defined(MCUBOOT_RAM_LOADING)
+
+#if defined(MCUBOOT_VALIDATE_SLOT0) && !defined(MCUBOOT_OVERWRITE_ONLY)
+static int boot_status_fails = 0;
+#define BOOT_STATUS_ASSERT(x) \
+ do { \
+ if (!(x)) { \
+ boot_status_fails++; \
+ } \
+ } while (0)
+#else
+#define BOOT_STATUS_ASSERT(x) assert(x)
+#endif
+
struct boot_status_table {
- /**
- * For each field, a value of 0 means "any".
- */
uint8_t bst_magic_slot0;
uint8_t bst_magic_scratch;
uint8_t bst_copy_done_slot0;
@@ -66,14 +77,14 @@
/* | slot-0 | scratch |
* ----------+------------+------------|
* magic | Good | Any |
- * copy-done | 0x01 | N/A |
+ * copy-done | Set | N/A |
* ----------+------------+------------'
* source: none |
* ------------------------------------'
*/
.bst_magic_slot0 = BOOT_MAGIC_GOOD,
- .bst_magic_scratch = 0,
- .bst_copy_done_slot0 = 0x01,
+ .bst_magic_scratch = BOOT_MAGIC_ANY,
+ .bst_copy_done_slot0 = BOOT_FLAG_SET,
.bst_status_source = BOOT_STATUS_SOURCE_NONE,
},
@@ -81,14 +92,14 @@
/* | slot-0 | scratch |
* ----------+------------+------------|
* magic | Good | Any |
- * copy-done | 0xff | N/A |
+ * copy-done | Unset | N/A |
* ----------+------------+------------'
* source: slot 0 |
* ------------------------------------'
*/
.bst_magic_slot0 = BOOT_MAGIC_GOOD,
- .bst_magic_scratch = 0,
- .bst_copy_done_slot0 = 0xff,
+ .bst_magic_scratch = BOOT_MAGIC_ANY,
+ .bst_copy_done_slot0 = BOOT_FLAG_UNSET,
.bst_status_source = BOOT_STATUS_SOURCE_SLOT0,
},
@@ -101,9 +112,9 @@
* source: scratch |
* ------------------------------------'
*/
- .bst_magic_slot0 = 0,
+ .bst_magic_slot0 = BOOT_MAGIC_ANY,
.bst_magic_scratch = BOOT_MAGIC_GOOD,
- .bst_copy_done_slot0 = 0,
+ .bst_copy_done_slot0 = BOOT_FLAG_ANY,
.bst_status_source = BOOT_STATUS_SOURCE_SCRATCH,
},
@@ -111,7 +122,7 @@
/* | slot-0 | scratch |
* ----------+------------+------------|
* magic | Unset | Any |
- * copy-done | 0xff | N/A |
+ * copy-done | Unset | N/A |
* ----------+------------+------------|
* source: varies |
* ------------------------------------+------------------------------+
@@ -121,8 +132,8 @@
* -------------------------------------------------------------------'
*/
.bst_magic_slot0 = BOOT_MAGIC_UNSET,
- .bst_magic_scratch = 0,
- .bst_copy_done_slot0 = 0xff,
+ .bst_magic_scratch = BOOT_MAGIC_ANY,
+ .bst_copy_done_slot0 = BOOT_FLAG_UNSET,
.bst_status_source = BOOT_STATUS_SOURCE_SLOT0,
},
};
@@ -169,7 +180,7 @@
}
static int
-boot_read_image_headers(void)
+boot_read_image_headers(bool require_all)
{
int rc;
int i;
@@ -177,11 +188,13 @@
for (i = 0; i < BOOT_NUM_SLOTS; i++) {
rc = boot_read_image_header(i, boot_img_hdr(&boot_data, i));
if (rc != 0) {
- /* If at least the first slot's header was read successfully, then
- * the boot loader can attempt a boot. Failure to read any headers
- * is a fatal error.
+ /* If `require_all` is set, fail on any single fail, otherwise
+ * if at least the first slot's header was read successfully,
+ * then the boot loader can attempt a boot.
+ *
+ * Failure to read any headers is a fatal error.
*/
- if (i > 0) {
+ if (i > 0 && !require_all) {
return 0;
} else {
return rc;
@@ -262,6 +275,18 @@
return 0;
}
+static inline int
+boot_magic_is_erased(uint8_t erased_val, uint32_t magic)
+{
+ uint8_t i;
+ for (i = 0; i < sizeof(magic); i++) {
+ if (erased_val != *(((uint8_t *)&magic) + i)) {
+ return 0;
+ }
+ }
+ return 1;
+}
+
static int
boot_validate_slot(int slot)
{
@@ -269,17 +294,18 @@
struct image_header *hdr;
int rc;
- hdr = boot_img_hdr(&boot_data, slot);
- if (hdr->ih_magic == 0xffffffff || hdr->ih_flags & IMAGE_F_NON_BOOTABLE) {
- /* No bootable image in slot; continue booting from slot 0. */
- return -1;
- }
-
rc = flash_area_open(flash_area_id_from_image_slot(slot), &fap);
if (rc != 0) {
return BOOT_EFLASH;
}
+ hdr = boot_img_hdr(&boot_data, slot);
+ if (boot_magic_is_erased(flash_area_erased_val(fap), hdr->ih_magic) ||
+ (hdr->ih_flags & IMAGE_F_NON_BOOTABLE)) {
+ /* No bootable image in slot; continue booting from slot 0. */
+ return -1;
+ }
+
if ((hdr->ih_magic != IMAGE_MAGIC ||
boot_image_check(hdr, fap) != 0)) {
if (slot != 0) {
@@ -358,7 +384,7 @@
struct boot_swap_state state_scratch;
struct boot_swap_state state_slot0;
int rc;
- int i;
+ size_t i;
uint8_t source;
rc = boot_read_swap_state_by_id(FLASH_AREA_IMAGE_0, &state_slot0);
@@ -373,11 +399,11 @@
for (i = 0; i < BOOT_STATUS_TABLES_COUNT; i++) {
table = &boot_status_tables[i];
- if ((table->bst_magic_slot0 == 0 ||
+ if ((table->bst_magic_slot0 == BOOT_MAGIC_ANY ||
table->bst_magic_slot0 == state_slot0.magic) &&
- (table->bst_magic_scratch == 0 ||
+ (table->bst_magic_scratch == BOOT_MAGIC_ANY ||
table->bst_magic_scratch == state_scratch.magic) &&
- (table->bst_copy_done_slot0 == 0 ||
+ (table->bst_copy_done_slot0 == BOOT_FLAG_ANY ||
table->bst_copy_done_slot0 == state_slot0.copy_done)) {
source = table->bst_status_source;
BOOT_LOG_INF("Boot source: %s",
@@ -407,9 +433,9 @@
post_swap_type = boot_swap_type();
switch (post_swap_type) {
- case BOOT_SWAP_TYPE_NONE: return BOOT_SWAP_TYPE_PERM;
- case BOOT_SWAP_TYPE_REVERT: return BOOT_SWAP_TYPE_TEST;
- case BOOT_SWAP_TYPE_PANIC: return BOOT_SWAP_TYPE_PANIC;
+ case BOOT_SWAP_TYPE_NONE : return BOOT_SWAP_TYPE_PERM;
+ case BOOT_SWAP_TYPE_REVERT : return BOOT_SWAP_TYPE_TEST;
+ case BOOT_SWAP_TYPE_PANIC : return BOOT_SWAP_TYPE_PANIC;
}
return BOOT_SWAP_TYPE_FAIL;
@@ -423,14 +449,22 @@
size_t size_0, size_1;
size_t i;
- /* Ensure both image slots have identical sector layouts. */
- if (num_sectors_0 != num_sectors_1) {
+ if (num_sectors_0 > BOOT_MAX_IMG_SECTORS || num_sectors_1 > BOOT_MAX_IMG_SECTORS) {
+ BOOT_LOG_WRN("Cannot upgrade: more sectors than allowed");
return 0;
}
+
+ /* Ensure both image slots have identical sector layouts. */
+ if (num_sectors_0 != num_sectors_1) {
+ BOOT_LOG_WRN("Cannot upgrade: number of sectors differ between slots");
+ return 0;
+ }
+
for (i = 0; i < num_sectors_0; i++) {
size_0 = boot_img_sector_size(&boot_data, 0, i);
size_1 = boot_img_sector_size(&boot_data, 1, i);
if (size_0 != size_1) {
+ BOOT_LOG_WRN("Cannot upgrade: an incompatible sector was found");
return 0;
}
}
@@ -438,7 +472,6 @@
return 1;
}
-
static uint32_t
boot_status_internal_off(int idx, int state, int elem_sz)
{
@@ -446,7 +479,8 @@
idx_sz = elem_sz * BOOT_STATUS_STATE_COUNT;
- return idx * idx_sz + state * elem_sz;
+ return (idx - BOOT_STATUS_IDX_0) * idx_sz +
+ (state - BOOT_STATUS_STATE_0) * elem_sz;
}
/**
@@ -461,6 +495,8 @@
uint8_t status;
int max_entries;
int found;
+ int found_idx;
+ int invalid;
int rc;
int i;
@@ -468,26 +504,48 @@
max_entries = boot_status_entries(fap);
found = 0;
+ found_idx = 0;
+ invalid = 0;
for (i = 0; i < max_entries; i++) {
- rc = flash_area_read(fap, off + i * BOOT_WRITE_SZ(&boot_data),
- &status, 1);
- if (rc != 0) {
+ rc = flash_area_read_is_empty(fap, off + i * BOOT_WRITE_SZ(&boot_data),
+ &status, 1);
+ if (rc < 0) {
return BOOT_EFLASH;
}
- if (status == 0xff) {
- if (found) {
- break;
+ if (rc == 1) {
+ if (found && !found_idx) {
+ found_idx = i;
}
} else if (!found) {
found = 1;
+ } else if (found_idx) {
+ invalid = 1;
+ break;
}
}
+ if (invalid) {
+ /* This means there was an error writing status on the last
+ * swap. Tell user and move on to validation!
+ */
+ BOOT_LOG_ERR("Detected inconsistent status!");
+
+#if !defined(MCUBOOT_VALIDATE_SLOT0)
+ /* With validation of slot0 disabled, there is no way to be sure the
+ * swapped slot0 is OK, so abort!
+ */
+ assert(0);
+#endif
+ }
+
if (found) {
- i--;
- bs->idx = i / BOOT_STATUS_STATE_COUNT;
- bs->state = i % BOOT_STATUS_STATE_COUNT;
+ 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;
}
return 0;
@@ -507,7 +565,14 @@
int area_id;
int rc;
- memset(bs, 0, sizeof(*bs));
+ memset(bs, 0, sizeof *bs);
+ bs->idx = BOOT_STATUS_IDX_0;
+ bs->state = BOOT_STATUS_STATE_0;
+
+#ifdef MCUBOOT_OVERWRITE_ONLY
+ /* Overwrite-only doesn't make use of the swap status area. */
+ return 0;
+#endif
status_loc = boot_status_source();
switch (status_loc) {
@@ -535,6 +600,7 @@
rc = boot_read_status_bytes(fap, bs);
flash_area_close(fap);
+
return rc;
}
@@ -555,6 +621,7 @@
int rc;
uint8_t buf[BOOT_MAX_ALIGN];
uint8_t align;
+ uint8_t erased_val;
/* NOTE: The first sector copied (that is the last sector on slot) contains
* the trailer. Since in the last step SLOT 0 is erased, the first
@@ -580,7 +647,8 @@
BOOT_WRITE_SZ(&boot_data));
align = flash_area_align(fap);
- memset(buf, 0xFF, BOOT_MAX_ALIGN);
+ erased_val = flash_area_erased_val(fap);
+ memset(buf, erased_val, BOOT_MAX_ALIGN);
buf[0] = bs->state;
rc = flash_area_write(fap, off, buf, align);
@@ -878,9 +946,9 @@
copy_sz -= trailer_sz;
}
- bs->use_scratch = (bs->idx == 0 && copy_sz != sz);
+ bs->use_scratch = (bs->idx == BOOT_STATUS_IDX_0 && copy_sz != sz);
- if (bs->state == 0) {
+ if (bs->state == BOOT_STATUS_STATE_0) {
rc = boot_erase_sector(FLASH_AREA_IMAGE_SCRATCH, 0, sz);
assert(rc == 0);
@@ -888,7 +956,7 @@
img_off, 0, copy_sz);
assert(rc == 0);
- if (bs->idx == 0) {
+ if (bs->idx == BOOT_STATUS_IDX_0) {
if (bs->use_scratch) {
boot_status_init_by_id(FLASH_AREA_IMAGE_SCRATCH, bs);
} else {
@@ -903,12 +971,12 @@
}
}
- bs->state = 1;
+ bs->state = BOOT_STATUS_STATE_1;
rc = boot_write_status(bs);
- assert(rc == 0);
+ BOOT_STATUS_ASSERT(rc == 0);
}
- if (bs->state == 1) {
+ if (bs->state == BOOT_STATUS_STATE_1) {
rc = boot_erase_sector(FLASH_AREA_IMAGE_1, img_off, sz);
assert(rc == 0);
@@ -916,7 +984,7 @@
img_off, img_off, copy_sz);
assert(rc == 0);
- if (bs->idx == 0 && !bs->use_scratch) {
+ if (bs->idx == BOOT_STATUS_IDX_0 && !bs->use_scratch) {
/* If not all sectors of the slot are being swapped,
* guarantee here that only slot0 will have the state.
*/
@@ -924,12 +992,12 @@
assert(rc == 0);
}
- bs->state = 2;
+ bs->state = BOOT_STATUS_STATE_2;
rc = boot_write_status(bs);
- assert(rc == 0);
+ BOOT_STATUS_ASSERT(rc == 0);
}
- if (bs->state == 2) {
+ if (bs->state == BOOT_STATUS_STATE_2) {
rc = boot_erase_sector(FLASH_AREA_IMAGE_0, img_off, sz);
assert(rc == 0);
@@ -954,7 +1022,7 @@
scratch_trailer_off,
img_off + copy_sz,
BOOT_STATUS_STATE_COUNT * BOOT_WRITE_SZ(&boot_data));
- assert(rc == 0);
+ BOOT_STATUS_ASSERT(rc == 0);
rc = boot_read_swap_state_by_id(FLASH_AREA_IMAGE_SCRATCH,
&swap_state);
@@ -975,10 +1043,10 @@
}
bs->idx++;
- bs->state = 0;
+ bs->state = BOOT_STATUS_STATE_0;
bs->use_scratch = 0;
rc = boot_write_status(bs);
- assert(rc == 0);
+ BOOT_STATUS_ASSERT(rc == 0);
}
}
#endif /* !MCUBOOT_OVERWRITE_ONLY */
@@ -1004,6 +1072,9 @@
int rc;
size_t size = 0;
size_t this_size;
+ size_t last_sector;
+
+ (void)bs;
BOOT_LOG_INF("Image upgrade slot1 -> slot0");
BOOT_LOG_INF("Erasing slot0");
@@ -1023,11 +1094,22 @@
rc = boot_copy_sector(FLASH_AREA_IMAGE_1, FLASH_AREA_IMAGE_0,
0, 0, size);
- /* Erase slot 1 so that we don't do the upgrade on every boot.
- * TODO: Perhaps verify slot 0's signature again? */
+ /*
+ * Erases header and trailer. The trailer is erased because when a new
+ * image is written without a trailer as is the case when using newt, the
+ * trailer that was left might trigger a new upgrade.
+ */
rc = boot_erase_sector(FLASH_AREA_IMAGE_1,
- 0, boot_img_sector_size(&boot_data, 1, 0));
+ boot_img_sector_off(&boot_data, 1, 0),
+ boot_img_sector_size(&boot_data, 1, 0));
assert(rc == 0);
+ last_sector = boot_img_num_sectors(&boot_data, 1) - 1;
+ rc = boot_erase_sector(FLASH_AREA_IMAGE_1,
+ boot_img_sector_off(&boot_data, 1, last_sector),
+ boot_img_sector_size(&boot_data, 1, last_sector));
+ assert(rc == 0);
+
+ /* TODO: Perhaps verify slot 0's signature again? */
return 0;
}
@@ -1038,7 +1120,7 @@
uint32_t sz;
int first_sector_idx;
int last_sector_idx;
- int swap_idx;
+ uint32_t swap_idx;
struct image_header *hdr;
uint32_t size;
uint32_t copy_size;
@@ -1048,7 +1130,7 @@
size = copy_size = 0;
- if (bs->idx == 0 && bs->state == 0) {
+ if (bs->idx == BOOT_STATUS_IDX_0 && bs->state == BOOT_STATUS_STATE_0) {
/*
* No swap ever happened, so need to find the largest image which
* will be used to determine the amount of sectors to swap.
@@ -1094,7 +1176,7 @@
swap_idx = 0;
while (last_sector_idx >= 0) {
sz = boot_copy_sz(last_sector_idx, &first_sector_idx);
- if (swap_idx >= bs->idx) {
+ if (swap_idx >= (bs->idx - BOOT_STATUS_IDX_0)) {
boot_swap_sectors(first_sector_idx, sz, bs);
}
@@ -1102,6 +1184,12 @@
swap_idx++;
}
+#ifdef MCUBOOT_VALIDATE_SLOT0
+ if (boot_status_fails > 0) {
+ BOOT_LOG_WRN("%d status write fails performing the swap", boot_status_fails);
+ }
+#endif
+
return 0;
}
#endif
@@ -1190,7 +1278,7 @@
}
/* If a partial swap was detected, complete it. */
- if (bs.idx != 0 || bs.state != 0) {
+ if (bs.idx != BOOT_STATUS_IDX_0 || bs.state != BOOT_STATUS_STATE_0) {
rc = boot_copy_image(&bs);
assert(rc == 0);
@@ -1262,11 +1350,13 @@
/* Determine the sector layout of the image slots and scratch area. */
rc = boot_read_sectors();
if (rc != 0) {
+ BOOT_LOG_WRN("Failed reading sectors; BOOT_MAX_IMG_SECTORS=%d - too small?",
+ BOOT_MAX_IMG_SECTORS);
goto out;
}
/* Attempt to read an image header from each slot. */
- rc = boot_read_image_headers();
+ rc = boot_read_image_headers(false);
if (rc != 0) {
goto out;
}
@@ -1334,13 +1424,11 @@
assert(0);
/* Loop forever... */
- while (1)
- ;
+ while (1) {}
}
-#ifdef MCUBOOT_VALIDATE_SLOT0
if (reload_headers) {
- rc = boot_read_image_headers();
+ rc = boot_read_image_headers(false);
if (rc != 0) {
goto out;
}
@@ -1352,6 +1440,7 @@
slot = 0;
}
+#ifdef MCUBOOT_VALIDATE_SLOT0
rc = boot_validate_slot(0);
assert(rc == 0);
if (rc != 0) {
@@ -1359,7 +1448,15 @@
goto out;
}
#else /* MCUBOOT_VALIDATE_SLOT0 */
- (void)reload_headers;
+ /* Even if we're not re-validating slot 0, we could be booting
+ * onto an empty flash chip. At least do a basic sanity check that
+ * the magic number on the image is OK.
+ */
+ if (boot_data.imgs[0].hdr.ih_magic != IMAGE_MAGIC) {
+ BOOT_LOG_ERR("bad image magic 0x%lx", (unsigned long)boot_data.imgs[0].hdr.ih_magic);
+ rc = BOOT_EBADIMAGE;
+ goto out;
+ }
#endif /* MCUBOOT_VALIDATE_SLOT0 */
/* Always boot from the primary slot. */
@@ -1487,7 +1584,7 @@
if (hdr->ih_magic == IMAGE_MAGIC) {
if (slot_state.magic == BOOT_MAGIC_GOOD ||
- slot_state.image_ok == 0x01) {
+ slot_state.image_ok == BOOT_FLAG_SET) {
/* Valid cases:
* - Test mode: magic is OK in image trailer
* - Permanent mode: image_ok flag has previously set
@@ -1619,11 +1716,13 @@
/* Determine the sector layout of the image slots. */
rc = boot_read_sectors();
if (rc != 0) {
+ BOOT_LOG_WRN("Failed reading sectors; BOOT_MAX_IMG_SECTORS=%d - too small?",
+ BOOT_MAX_IMG_SECTORS);
goto out;
}
/* Attempt to read an image header from each slot. */
- rc = boot_read_image_headers();
+ rc = boot_read_image_headers(false);
if (rc != 0) {
goto out;
}
diff --git a/bl2/ext/mcuboot/flash_map.c b/bl2/ext/mcuboot/flash_map.c
index b476517..09d0ad0 100644
--- a/bl2/ext/mcuboot/flash_map.c
+++ b/bl2/ext/mcuboot/flash_map.c
@@ -17,6 +17,13 @@
* under the License.
*/
+/*
+ * Original code taken from mcuboot project at:
+ * https://github.com/JuulLabs-OSS/mcuboot
+ * Git SHA of the original version: b69841820462fa0227d7fb407620405f6426bb4b
+ * Modifications are Copyright (c) 2018-2019 Arm Limited.
+ */
+
#include <errno.h>
#include <stdbool.h>
@@ -155,13 +162,46 @@
}
}
-int flash_area_read(const struct flash_area *area, uint32_t off, void *dst,
- uint32_t len)
+uint8_t flash_area_erased_val(const struct flash_area *area)
{
- BOOT_LOG_DBG("read area=%d, off=%#x, len=%#x", area->fa_id, off, len);
+ (void)area;
+
+ return FLASH_DEV_NAME.GetInfo()->erased_value;
+}
+
+int flash_area_read(const struct flash_area *area, uint32_t off, void *dst,
+ uint32_t len)
+{
+ BOOT_LOG_DBG("read area=%d, off=%#x, len=%#x", area->fa_id, off, len);
return FLASH_DEV_NAME.ReadData(area->fa_off + off, dst, len);
}
+int flash_area_read_is_empty(const struct flash_area *area, uint32_t off,
+ void *dst, uint32_t len)
+{
+ uint32_t i;
+ uint8_t *u8dst;
+ int rc;
+
+ BOOT_LOG_DBG("read_is_empty area=%d, off=%#x, len=%#x",
+ area->fa_id, off, len);
+
+ rc = FLASH_DEV_NAME.ReadData(area->fa_off + off, dst, len);
+ if(rc != 0) {
+ return -1;
+ }
+
+ u8dst = (uint8_t*)dst;
+
+ for (i = 0; i < len; i++) {
+ if (u8dst[i] != flash_area_erased_val(area)) {
+ return 0;
+ }
+ }
+
+ return 1;
+}
+
int flash_area_write(const struct flash_area *area, uint32_t off,
const void *src, uint32_t len)
{
diff --git a/bl2/ext/mcuboot/include/flash_map/flash_map.h b/bl2/ext/mcuboot/include/flash_map/flash_map.h
index 2eba8e2..78934a5 100644
--- a/bl2/ext/mcuboot/include/flash_map/flash_map.h
+++ b/bl2/ext/mcuboot/include/flash_map/flash_map.h
@@ -18,9 +18,10 @@
*/
/*
- Original code taken from mcuboot project at:
- https://github.com/runtimeco/mcuboot
- Modifications are Copyright (c) 2018 Arm Limited.
+ * Original code taken from mcuboot project at:
+ * https://github.com/JuulLabs-OSS/mcuboot
+ * Git SHA of the original version: b69841820462fa0227d7fb407620405f6426bb4b
+ * Modifications are Copyright (c) 2018-2019 Arm Limited.
*/
#ifndef H_UTIL_FLASH_MAP_
@@ -127,12 +128,24 @@
int flash_area_read(const struct flash_area *area, uint32_t off, void *dst,
uint32_t len);
+/*
+ * Returns 1 if read data is erased, 0 if non-erased, and -1 on failure.
+ */
+int flash_area_read_is_empty(const struct flash_area *area, uint32_t off,
+ void *dst, uint32_t len);
+
int flash_area_write(const struct flash_area *area, uint32_t off,
const void *src, uint32_t len);
int flash_area_erase(const struct flash_area *area, uint32_t off, uint32_t len);
/*
+ * Returns the value expected to be read when accessing any erased
+ * flash byte.
+ */
+uint8_t flash_area_erased_val(const struct flash_area *area);
+
+/*
* Alignment restriction for flash writes.
*/
uint8_t flash_area_align(const struct flash_area *area);