boot_serial: Add optional img mgmt slot info feature
Adds a minimal version of the slot info feature to serial recovery,
and enables it by default.
Signed-off-by: Jamie McCrae <jamie.mccrae@nordicsemi.no>
diff --git a/boot/bootutil/src/loader.c b/boot/bootutil/src/loader.c
index 4b0299f..8663fbf 100644
--- a/boot/bootutil/src/loader.c
+++ b/boot/bootutil/src/loader.c
@@ -63,10 +63,23 @@
static struct boot_loader_state boot_data;
-#if defined(MCUBOOT_DATA_SHARING)
+#if defined(MCUBOOT_SERIAL_IMG_GRP_SLOT_INFO) || defined(MCUBOOT_DATA_SHARING)
static struct image_max_size image_max_sizes[BOOT_IMAGE_NUMBER] = {0};
#endif
+#if !defined(__BOOTSIM__)
+/* Used for holding static buffers in multiple functions to work around issues
+ * in older versions of gcc (e.g. 4.8.4)
+ */
+struct sector_buffer_t {
+ boot_sector_t *primary;
+ boot_sector_t *secondary;
+#if MCUBOOT_SWAP_USING_SCRATCH
+ boot_sector_t *scratch;
+#endif
+};
+#endif
+
#if (BOOT_IMAGE_NUMBER > 1)
#define IMAGES_ITER(x) for ((x) = 0; (x) < BOOT_IMAGE_NUMBER; ++(x))
#else
@@ -1840,7 +1853,7 @@
int rc;
FIH_DECLARE(fih_rc, FIH_FAILURE);
-#if defined(MCUBOOT_DATA_SHARING)
+#if defined(MCUBOOT_SERIAL_IMG_GRP_SLOT_INFO) || defined(MCUBOOT_DATA_SHARING)
int max_size;
#endif
@@ -1870,7 +1883,7 @@
return;
}
-#if defined(MCUBOOT_DATA_SHARING)
+#if defined(MCUBOOT_SERIAL_IMG_GRP_SLOT_INFO) || defined(MCUBOOT_DATA_SHARING)
/* Fetch information on maximum sizes for later usage, if needed */
max_size = app_max_size(state);
@@ -2100,11 +2113,36 @@
#endif
}
+#if !defined(__BOOTSIM__)
+static void boot_get_sector_buffers(struct sector_buffer_t *buffers)
+{
+ /* The array of slot sectors are defined here (as opposed to file scope) so
+ * that they don't get allocated for non-boot-loader apps. This is
+ * necessary because the gcc option "-fdata-sections" doesn't seem to have
+ * any effect in older gcc versions (e.g., 4.8.4).
+ */
+ static boot_sector_t primary_slot_sectors[BOOT_IMAGE_NUMBER][BOOT_MAX_IMG_SECTORS];
+ static boot_sector_t secondary_slot_sectors[BOOT_IMAGE_NUMBER][BOOT_MAX_IMG_SECTORS];
+#if MCUBOOT_SWAP_USING_SCRATCH
+ static boot_sector_t scratch_sectors[BOOT_MAX_IMG_SECTORS];
+#endif
+
+ buffers->primary = (boot_sector_t *)&primary_slot_sectors;
+ buffers->secondary = (boot_sector_t *)&secondary_slot_sectors;
+#if MCUBOOT_SWAP_USING_SCRATCH
+ buffers->scratch = (boot_sector_t *)&scratch_sectors;
+#endif
+}
+#endif
+
fih_ret
context_boot_go(struct boot_loader_state *state, struct boot_rsp *rsp)
{
size_t slot;
struct boot_status bs;
+#if !defined(__BOOTSIM__)
+ struct sector_buffer_t sector_buffers;
+#endif
int rc = -1;
FIH_DECLARE(fih_rc, FIH_FAILURE);
int fa_id;
@@ -2112,6 +2150,7 @@
bool has_upgrade;
volatile int fih_cnt;
+#if defined(__BOOTSIM__)
/* The array of slot sectors are defined here (as opposed to file scope) so
* that they don't get allocated for non-boot-loader apps. This is
* necessary because the gcc option "-fdata-sections" doesn't seem to have
@@ -2122,6 +2161,7 @@
#if MCUBOOT_SWAP_USING_SCRATCH
TARGET_STATIC boot_sector_t scratch_sectors[BOOT_MAX_IMG_SECTORS];
#endif
+#endif
has_upgrade = false;
@@ -2129,6 +2169,10 @@
(void)has_upgrade;
#endif
+#if !defined(__BOOTSIM__)
+ boot_get_sector_buffers(§or_buffers);
+#endif
+
/* Iterate over all the images. By the end of the loop the swap type has
* to be determined for each image and all aborted swaps have to be
* completed.
@@ -2149,6 +2193,15 @@
image_index = BOOT_CURR_IMG(state);
+#if !defined(__BOOTSIM__)
+ BOOT_IMG(state, BOOT_PRIMARY_SLOT).sectors =
+ §or_buffers.primary[image_index];
+ BOOT_IMG(state, BOOT_SECONDARY_SLOT).sectors =
+ §or_buffers.secondary[image_index];
+#if MCUBOOT_SWAP_USING_SCRATCH
+ state->scratch.sectors = sector_buffers.scratch;
+#endif
+#else
BOOT_IMG(state, BOOT_PRIMARY_SLOT).sectors =
primary_slot_sectors[image_index];
BOOT_IMG(state, BOOT_SECONDARY_SLOT).sectors =
@@ -2156,6 +2209,7 @@
#if MCUBOOT_SWAP_USING_SCRATCH
state->scratch.sectors = scratch_sectors;
#endif
+#endif
/* Open primary and secondary image areas for the duration
* of this call.
@@ -3337,12 +3391,100 @@
}
}
-#if defined(MCUBOOT_DATA_SHARING)
+#if defined(MCUBOOT_SERIAL_IMG_GRP_SLOT_INFO)
/**
-* Fetches the maximum allowed size of the image
-*/
+ * Reads image data to find out the maximum application sizes. Only needs to
+ * be called in serial recovery mode, as the state informatio is unpopulated
+ * at that time
+ */
+static void boot_fetch_slot_state_sizes(void)
+{
+ struct sector_buffer_t sector_buffers;
+ size_t slot;
+ int rc = -1;
+ int fa_id;
+ int image_index;
+
+ boot_get_sector_buffers(§or_buffers);
+
+ IMAGES_ITER(BOOT_CURR_IMG(&boot_data)) {
+ int max_size = 0;
+
+ image_index = BOOT_CURR_IMG(&boot_data);
+
+ BOOT_IMG(&boot_data, BOOT_PRIMARY_SLOT).sectors =
+ §or_buffers.primary[image_index];
+ BOOT_IMG(&boot_data, BOOT_SECONDARY_SLOT).sectors =
+ §or_buffers.secondary[image_index];
+#if MCUBOOT_SWAP_USING_SCRATCH
+ boot_data.scratch.sectors = sector_buffers.scratch;;
+#endif
+
+ /* Open primary and secondary image areas for the duration
+ * of this call.
+ */
+ for (slot = 0; slot < BOOT_NUM_SLOTS; slot++) {
+ fa_id = flash_area_id_from_multi_image_slot(image_index, slot);
+ rc = flash_area_open(fa_id, &BOOT_IMG_AREA(&boot_data, slot));
+ assert(rc == 0);
+
+ if (rc != 0) {
+ goto finish;
+ }
+ }
+
+#if MCUBOOT_SWAP_USING_SCRATCH
+ rc = flash_area_open(FLASH_AREA_IMAGE_SCRATCH,
+ &BOOT_SCRATCH_AREA(&boot_data));
+ assert(rc == 0);
+
+ if (rc != 0) {
+ goto finish;
+ }
+#endif
+
+ /* Determine the sector layout of the image slots and scratch area. */
+ rc = boot_read_sectors(&boot_data);
+
+ if (rc == 0) {
+ max_size = app_max_size(&boot_data);
+
+ if (max_size > 0) {
+ image_max_sizes[image_index].calculated = true;
+ image_max_sizes[image_index].max_size = max_size;
+ }
+ }
+ }
+
+finish:
+ close_all_flash_areas(&boot_data);
+ memset(&boot_data, 0x00, sizeof(boot_data));
+}
+#endif
+
+#if defined(MCUBOOT_SERIAL_IMG_GRP_SLOT_INFO) || defined(MCUBOOT_DATA_SHARING)
+/**
+ * Fetches the maximum allowed size of the image
+ */
const struct image_max_size *boot_get_max_app_size(void)
{
+#if defined(MCUBOOT_SERIAL_IMG_GRP_SLOT_INFO)
+ uint8_t i = 0;
+
+ while (i < BOOT_IMAGE_NUMBER) {
+ if (image_max_sizes[i].calculated == true) {
+ break;
+ }
+
+ ++i;
+ }
+
+ if (i == BOOT_IMAGE_NUMBER) {
+ /* Information not available, need to fetch it */
+ boot_fetch_slot_state_sizes();
+ }
+#endif
+
return image_max_sizes;
}
#endif