Boot: Extend flash layout for multiple images
This patch introduces the BOOT_IMAGE_NUMBER macro and current_image
variable to support multiple updatable images and the associated
extended flash layout.
The FLASH_AREA_IMAGE_* object-like macros are replaced with
function-like ones and therefore some functions have been updated,
because the labels of a switch statement and the initialization
values of objects with static storage duration have to be constant
expressions.
Change-Id: Ib7b26ec3c94233e52db4f97825ddb6a3e55bb1d3
Signed-off-by: David Vincze <david.vincze@arm.com>
diff --git a/boot/bootutil/src/bootutil_misc.c b/boot/bootutil/src/bootutil_misc.c
index 041f6a2..b2a07d0 100644
--- a/boot/bootutil/src/bootutil_misc.c
+++ b/boot/bootutil/src/bootutil_misc.c
@@ -172,13 +172,12 @@
int
boot_status_entries(const struct flash_area *fap)
{
- switch (fap->fa_id) {
- case FLASH_AREA_IMAGE_PRIMARY:
- case FLASH_AREA_IMAGE_SECONDARY:
- return BOOT_STATUS_STATE_COUNT * BOOT_STATUS_MAX_ENTRIES;
- case FLASH_AREA_IMAGE_SCRATCH:
+ if (fap->fa_id == FLASH_AREA_IMAGE_SCRATCH) {
return BOOT_STATUS_STATE_COUNT;
- default:
+ } else if ((fap->fa_id == FLASH_AREA_IMAGE_PRIMARY) ||
+ (fap->fa_id == FLASH_AREA_IMAGE_SECONDARY)) {
+ return BOOT_STATUS_STATE_COUNT * BOOT_STATUS_MAX_ENTRIES;
+ } else {
return BOOT_EBADARGS;
}
}
@@ -301,16 +300,14 @@
const struct flash_area *fap;
int rc;
- switch (flash_area_id) {
- case FLASH_AREA_IMAGE_SCRATCH:
- case FLASH_AREA_IMAGE_PRIMARY:
- case FLASH_AREA_IMAGE_SECONDARY:
+ 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;
}
- break;
- default:
+ } else {
return BOOT_EBADARGS;
}
diff --git a/boot/bootutil/src/bootutil_priv.h b/boot/bootutil/src/bootutil_priv.h
index bc35a72..11d0a54 100644
--- a/boot/bootutil/src/bootutil_priv.h
+++ b/boot/bootutil/src/bootutil_priv.h
@@ -134,6 +134,12 @@
uint8_t image_num; /* Boot status belongs to this image */
};
+#ifdef MCUBOOT_IMAGE_NUMBER
+#define BOOT_IMAGE_NUMBER MCUBOOT_IMAGE_NUMBER
+#else
+#define BOOT_IMAGE_NUMBER 1
+#endif
+
#define BOOT_MAX_IMG_SECTORS MCUBOOT_MAX_IMG_SECTORS
/*
@@ -302,23 +308,21 @@
int num_sectors = BOOT_MAX_IMG_SECTORS;
int rc;
- switch (flash_area) {
- case FLASH_AREA_IMAGE_PRIMARY:
+ if (flash_area == FLASH_AREA_IMAGE_PRIMARY) {
rc = flash_area_to_sectors(flash_area, &num_sectors,
state->imgs[BOOT_PRIMARY_SLOT].sectors);
state->imgs[BOOT_PRIMARY_SLOT].num_sectors = (size_t)num_sectors;
- break;
- case FLASH_AREA_IMAGE_SECONDARY:
+
+ } else if (flash_area == FLASH_AREA_IMAGE_SECONDARY) {
rc = flash_area_to_sectors(flash_area, &num_sectors,
state->imgs[BOOT_SECONDARY_SLOT].sectors);
state->imgs[BOOT_SECONDARY_SLOT].num_sectors = (size_t)num_sectors;
- break;
- case FLASH_AREA_IMAGE_SCRATCH:
+
+ } else if (flash_area == FLASH_AREA_IMAGE_SCRATCH) {
rc = flash_area_to_sectors(flash_area, &num_sectors,
state->scratch.sectors);
state->scratch.num_sectors = (size_t)num_sectors;
- break;
- default:
+ } else {
return BOOT_EFLASH;
}
@@ -350,24 +354,19 @@
size_t *out_num_sectors;
int rc;
- switch (flash_area) {
- case FLASH_AREA_IMAGE_PRIMARY:
- num_sectors = BOOT_MAX_IMG_SECTORS;
+ num_sectors = BOOT_MAX_IMG_SECTORS;
+
+ if (flash_area == FLASH_AREA_IMAGE_PRIMARY) {
out_sectors = state->imgs[BOOT_PRIMARY_SLOT].sectors;
out_num_sectors = &state->imgs[BOOT_PRIMARY_SLOT].num_sectors;
- break;
- case FLASH_AREA_IMAGE_SECONDARY:
- num_sectors = BOOT_MAX_IMG_SECTORS;
+ } else if (flash_area == FLASH_AREA_IMAGE_SECONDARY) {
out_sectors = state->imgs[BOOT_SECONDARY_SLOT].sectors;
out_num_sectors = &state->imgs[BOOT_SECONDARY_SLOT].num_sectors;
- break;
- case FLASH_AREA_IMAGE_SCRATCH:
- num_sectors = BOOT_MAX_IMG_SECTORS;
+ } else if (flash_area == FLASH_AREA_IMAGE_SCRATCH) {
out_sectors = state->scratch.sectors;
out_num_sectors = &state->scratch.num_sectors;
- break;
- default:
- return -1;
+ } else {
+ return BOOT_EFLASH;
}
rc = flash_area_get_sectors(flash_area, &num_sectors, out_sectors);
diff --git a/boot/bootutil/src/loader.c b/boot/bootutil/src/loader.c
index fcbf082..a843d73 100644
--- a/boot/bootutil/src/loader.c
+++ b/boot/bootutil/src/loader.c
@@ -47,6 +47,7 @@
MCUBOOT_LOG_MODULE_DECLARE(mcuboot);
static struct boot_loader_state boot_data;
+uint8_t current_image = 0;
#if defined(MCUBOOT_VALIDATE_PRIMARY_SLOT) && !defined(MCUBOOT_OVERWRITE_ONLY)
static int boot_status_fails = 0;
@@ -1021,18 +1022,20 @@
uint32_t total_sz;
uint32_t off;
uint32_t sz;
+ int fa_id_primary;
+ int fa_id_secondary;
int rc;
BOOT_LOG_DBG("erasing trailer; fa_id=%d", fap->fa_id);
- switch (fap->fa_id) {
- case FLASH_AREA_IMAGE_PRIMARY:
+ fa_id_primary = flash_area_id_from_image_slot(BOOT_PRIMARY_SLOT);
+ fa_id_secondary = flash_area_id_from_image_slot(BOOT_SECONDARY_SLOT);
+
+ if (fap->fa_id == fa_id_primary) {
slot = BOOT_PRIMARY_SLOT;
- break;
- case FLASH_AREA_IMAGE_SECONDARY:
+ } else if (fap->fa_id == fa_id_secondary) {
slot = BOOT_SECONDARY_SLOT;
- break;
- default:
+ } else {
return BOOT_EFLASH;
}
diff --git a/boot/zephyr/flash_map_extended.c b/boot/zephyr/flash_map_extended.c
index 543a467..535e69a 100644
--- a/boot/zephyr/flash_map_extended.c
+++ b/boot/zephyr/flash_map_extended.c
@@ -55,9 +55,12 @@
*/
int flash_area_id_from_image_slot(int slot)
{
- static const int area_id_tab[] = {FLASH_AREA_IMAGE_PRIMARY,
- FLASH_AREA_IMAGE_SECONDARY,
- FLASH_AREA_IMAGE_SCRATCH};
+#if (MCUBOOT_IMAGE_NUMBER == 1)
+ static
+#endif
+ const int area_id_tab[] = {FLASH_AREA_IMAGE_PRIMARY,
+ FLASH_AREA_IMAGE_SECONDARY,
+ FLASH_AREA_IMAGE_SCRATCH};
if (slot >= 0 && slot < ARRAY_SIZE(area_id_tab)) {
return area_id_tab[slot];
@@ -68,15 +71,15 @@
int flash_area_id_to_image_slot(int area_id)
{
- switch (area_id) {
- case FLASH_AREA_IMAGE_PRIMARY:
+ if (area_id == FLASH_AREA_IMAGE_PRIMARY) {
return 0;
- case FLASH_AREA_IMAGE_SECONDARY:
- return 1;
- default:
- BOOT_LOG_ERR("invalid flash area ID");
- return -1;
}
+ if (area_id == FLASH_AREA_IMAGE_SECONDARY) {
+ return 1;
+ }
+
+ BOOT_LOG_ERR("invalid flash area ID");
+ return -1;
}
int flash_area_sector_from_off(off_t off, struct flash_sector *sector)
diff --git a/boot/zephyr/include/mcuboot_config/mcuboot_config.h b/boot/zephyr/include/mcuboot_config/mcuboot_config.h
index d79d556..925591c 100644
--- a/boot/zephyr/include/mcuboot_config/mcuboot_config.h
+++ b/boot/zephyr/include/mcuboot_config/mcuboot_config.h
@@ -1,5 +1,6 @@
/*
* Copyright (c) 2018 Open Source Foundries Limited
+ * Copyright (c) 2019 Arm Limited
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -65,6 +66,12 @@
#define MCUBOOT_BOOTSTRAP 1
#endif
+#ifdef CONFIG_UPDATEABLE_IMAGE_NUMBER
+#define MCUBOOT_IMAGE_NUMBER CONFIG_UPDATEABLE_IMAGE_NUMBER
+#else
+#define MCUBOOT_IMAGE_NUMBER 1
+#endif
+
/*
* Enabling this option uses newer flash map APIs. This saves RAM and
* avoids deprecated API usage.
diff --git a/boot/zephyr/include/sysflash/sysflash.h b/boot/zephyr/include/sysflash/sysflash.h
index 2492244..d4617bb 100644
--- a/boot/zephyr/include/sysflash/sysflash.h
+++ b/boot/zephyr/include/sysflash/sysflash.h
@@ -4,9 +4,32 @@
#define __SYSFLASH_H__
#include <generated_dts_board.h>
+#include <mcuboot_config/mcuboot_config.h>
+extern uint8_t current_image;
+
+#if (MCUBOOT_IMAGE_NUMBER == 1)
#define FLASH_AREA_IMAGE_PRIMARY DT_FLASH_AREA_IMAGE_0_ID
#define FLASH_AREA_IMAGE_SECONDARY DT_FLASH_AREA_IMAGE_1_ID
+#elif (MCUBOOT_IMAGE_NUMBER == 2)
+/* MCUBoot currently supports only up to 2 updateable firmware images.
+ * If the number of the current image is greater than MCUBOOT_IMAGE_NUMBER - 1
+ * then a dummy value will be assigned to the flash area macros.
+ */
+#define FLASH_AREA_IMAGE_PRIMARY ((current_image == 0) ? \
+ DT_FLASH_AREA_IMAGE_0_ID : \
+ (current_image == 1) ? \
+ DT_FLASH_AREA_IMAGE_2_ID : \
+ 255 )
+#define FLASH_AREA_IMAGE_SECONDARY ((current_image == 0) ? \
+ DT_FLASH_AREA_IMAGE_1_ID : \
+ (current_image == 1) ? \
+ DT_FLASH_AREA_IMAGE_3_ID : \
+ 255 )
+#else
+#error "Image slot and flash area mapping is not defined"
+#endif
+
#define FLASH_AREA_IMAGE_SCRATCH DT_FLASH_AREA_IMAGE_SCRATCH_ID
#endif /* __SYSFLASH_H__ */
diff --git a/boot/zephyr/include/target.h b/boot/zephyr/include/target.h
index 6e777fb..a11616f 100644
--- a/boot/zephyr/include/target.h
+++ b/boot/zephyr/include/target.h
@@ -1,5 +1,7 @@
/*
* Copyright (C) 2017, Linaro Ltd
+ * Copyright (c) 2019, Arm Limited
+ *
* SPDX-License-Identifier: Apache-2.0
*/
@@ -45,4 +47,11 @@
#error "Target support is incomplete; cannot build mcuboot."
#endif
+#if ((MCUBOOT_IMAGE_NUMBER == 2) && (!defined(FLASH_AREA_IMAGE_2_OFFSET) || \
+ !defined(FLASH_AREA_IMAGE_2_SIZE) || \
+ !defined(FLASH_AREA_IMAGE_3_OFFSET) || \
+ !defined(FLASH_AREA_IMAGE_3_SIZE)))
+#error "Target support is incomplete; cannot build mcuboot."
#endif
+
+#endif /* H_TARGETS_TARGET_ */