diff --git a/boot/bootutil/include/bootutil/bootutil_public.h b/boot/bootutil/include/bootutil/bootutil_public.h index e2795ab3e..e56580779 100644 --- a/boot/bootutil/include/bootutil/bootutil_public.h +++ b/boot/bootutil/include/bootutil/bootutil_public.h @@ -302,6 +302,12 @@ boot_set_next(const struct flash_area *fa, bool active, bool confirm); /** * Attempts to load image header from flash; verifies flash header fields. * + * The selected update method (i.e. swap move) may impose additional restrictions + * on the image size (i.e. due to the presence of the image trailer). + * Such restrictions are not verified by this function. + * These checks are implemented as part of the boot_image_validate(..) that uses + * sizes from the bootutil_max_image_size(..). + * * @param[in] fa_p flash area pointer * @param[out] hdr buffer for image header * diff --git a/boot/bootutil/src/bootutil_misc.c b/boot/bootutil/src/bootutil_misc.c index 031a003d0..12d7a50ac 100644 --- a/boot/bootutil/src/bootutil_misc.c +++ b/boot/bootutil/src/bootutil_misc.c @@ -42,6 +42,9 @@ #ifdef MCUBOOT_ENC_IMAGES #include "bootutil/enc_key.h" #endif +#if defined(MCUBOOT_SWAP_USING_MOVE) || defined(MCUBOOT_SWAP_USING_OFFSET) +#include "swap_priv.h" +#endif BOOT_LOG_MODULE_DECLARE(mcuboot); @@ -478,26 +481,7 @@ uint32_t bootutil_max_image_size(struct boot_loader_state *state, const struct f return slot_trailer_off - trailer_padding; #elif defined(MCUBOOT_SWAP_USING_MOVE) || defined(MCUBOOT_SWAP_USING_OFFSET) (void) fap; - - /* The slot whose size is used to compute the maximum image size must be the one containing the - * padding required for the swap. */ -#ifdef MCUBOOT_SWAP_USING_MOVE - size_t slot = BOOT_PRIMARY_SLOT; -#else - size_t slot = BOOT_SECONDARY_SLOT; -#endif - - const struct flash_area *fap_padded_slot = BOOT_IMG_AREA(state, slot); - assert(fap_padded_slot != NULL); - - size_t trailer_sz = boot_trailer_sz(BOOT_WRITE_SZ(state)); - size_t sector_sz = boot_img_sector_size(state, slot, 0); - size_t padding_sz = sector_sz; - - /* The trailer size needs to be sector-aligned */ - trailer_sz = ALIGN_UP(trailer_sz, sector_sz); - - return flash_area_get_size(fap_padded_slot) - trailer_sz - padding_sz; + return app_max_size(state); #elif defined(MCUBOOT_OVERWRITE_ONLY) (void) state; return boot_swap_info_off(fap); diff --git a/boot/bootutil/src/swap_move.c b/boot/bootutil/src/swap_move.c index 9349cde37..8b7bcab13 100644 --- a/boot/bootutil/src/swap_move.c +++ b/boot/bootutil/src/swap_move.c @@ -227,29 +227,6 @@ boot_status_internal_off(const struct boot_status *bs, int elem_sz) return off; } -static int app_max_sectors(struct boot_loader_state *state) -{ - uint32_t sz = 0; - uint32_t sector_sz; - uint32_t trailer_sz; - uint32_t first_trailer_idx; - - sector_sz = boot_img_sector_size(state, BOOT_PRIMARY_SLOT, 0); - trailer_sz = boot_trailer_sz(BOOT_WRITE_SZ(state)); - /* subtract 1 for swap and at least 1 for trailer */ - first_trailer_idx = boot_img_num_sectors(state, BOOT_PRIMARY_SLOT) - 2; - - while (1) { - sz += sector_sz; - if (sz >= trailer_sz) { - break; - } - first_trailer_idx--; - } - - return first_trailer_idx; -} - int boot_slots_compatible(struct boot_loader_state *state) { @@ -258,19 +235,16 @@ boot_slots_compatible(struct boot_loader_state *state) size_t sector_sz_pri = 0; size_t sector_sz_sec = 0; size_t i; - size_t num_usable_sectors_pri; num_sectors_pri = boot_img_num_sectors(state, BOOT_PRIMARY_SLOT); num_sectors_sec = boot_img_num_sectors(state, BOOT_SECONDARY_SLOT); - num_usable_sectors_pri = app_max_sectors(state); if ((num_sectors_pri != num_sectors_sec) && - (num_sectors_pri != (num_sectors_sec + 1)) && - (num_usable_sectors_pri != (num_sectors_sec + 1))) { + (num_sectors_pri != (num_sectors_sec + 1))) { BOOT_LOG_WRN("Cannot upgrade: not a compatible amount of sectors"); BOOT_LOG_DBG("slot0 sectors: %d, slot1 sectors: %d, usable slot0 sectors: %d", (int)num_sectors_pri, (int)num_sectors_sec, - (int)(num_usable_sectors_pri - 1)); + (int)(num_sectors_pri - 1)); return 0; } else if (num_sectors_pri > BOOT_MAX_IMG_SECTORS) { BOOT_LOG_WRN("Cannot upgrade: more sectors than allowed"); @@ -280,7 +254,7 @@ boot_slots_compatible(struct boot_loader_state *state) /* Optimal says primary has one more than secondary. Always. Both have trailers. */ if (num_sectors_pri != (num_sectors_sec + 1)) { BOOT_LOG_DBG("Non-optimal sector distribution, slot0 has %d usable sectors (%d assigned) " - "but slot1 has %d assigned", (int)num_usable_sectors_pri, + "but slot1 has %d assigned", (int)(num_sectors_pri - 1), (int)num_sectors_pri, (int)num_sectors_sec); } @@ -340,7 +314,6 @@ swap_status_source(struct boot_loader_state *state) struct boot_swap_state state_primary_slot; struct boot_swap_state state_secondary_slot; int rc; - uint8_t source; uint8_t image_index; #if (BOOT_IMAGE_NUMBER == 1) @@ -365,10 +338,8 @@ swap_status_source(struct boot_loader_state *state) state_primary_slot.copy_done == BOOT_FLAG_UNSET && state_secondary_slot.magic != BOOT_MAGIC_GOOD) { - source = BOOT_STATUS_SOURCE_PRIMARY_SLOT; - BOOT_LOG_INF("Boot source: primary slot"); - return source; + return BOOT_STATUS_SOURCE_PRIMARY_SLOT; } BOOT_LOG_INF("Boot source: none"); @@ -590,11 +561,23 @@ swap_run(struct boot_loader_state *state, struct boot_status *bs, int app_max_size(struct boot_loader_state *state) { - uint32_t sector_sz_primary; + uint32_t available_pri_sz; + uint32_t available_sec_sz; + + size_t trailer_sz = boot_trailer_sz(BOOT_WRITE_SZ(state)); + size_t sector_sz = boot_img_sector_size(state, BOOT_PRIMARY_SLOT, 0); + size_t padding_sz = sector_sz; - sector_sz_primary = boot_img_sector_size(state, BOOT_PRIMARY_SLOT, 0); + /* The trailer size needs to be sector-aligned */ + trailer_sz = ALIGN_UP(trailer_sz, sector_sz); + + /* The slot whose size is used to compute the maximum image size must be the one containing the + * padding required for the swap. + */ + available_pri_sz = boot_img_num_sectors(state, BOOT_PRIMARY_SLOT) * sector_sz - trailer_sz - padding_sz; + available_sec_sz = boot_img_num_sectors(state, BOOT_SECONDARY_SLOT) * sector_sz - trailer_sz; - return app_max_sectors(state) * sector_sz_primary; + return (available_pri_sz < available_sec_sz ? available_pri_sz : available_sec_sz); } #endif diff --git a/boot/bootutil/src/swap_offset.c b/boot/bootutil/src/swap_offset.c index 8bc6e760a..d8bfac318 100644 --- a/boot/bootutil/src/swap_offset.c +++ b/boot/bootutil/src/swap_offset.c @@ -302,33 +302,6 @@ uint32_t boot_status_internal_off(const struct boot_status *bs, int elem_sz) return off; } -static int app_max_sectors(struct boot_loader_state *state) -{ - uint32_t sz = 0; - uint32_t sector_sz; - uint32_t trailer_sz; - uint32_t available_sectors_pri; - uint32_t available_sectors_sec; - uint32_t trailer_sectors = 0; - - sector_sz = boot_img_sector_size(state, BOOT_PRIMARY_SLOT, 0); - trailer_sz = boot_trailer_sz(BOOT_WRITE_SZ(state)); - - while (1) { - sz += sector_sz; - ++trailer_sectors; - - if (sz >= trailer_sz) { - break; - } - } - - available_sectors_pri = boot_img_num_sectors(state, BOOT_PRIMARY_SLOT) - trailer_sectors; - available_sectors_sec = boot_img_num_sectors(state, BOOT_SECONDARY_SLOT) - 1; - - return (available_sectors_pri < available_sectors_sec ? available_sectors_pri : available_sectors_sec); -} - int boot_slots_compatible(struct boot_loader_state *state) { size_t num_sectors_pri; @@ -336,32 +309,30 @@ int boot_slots_compatible(struct boot_loader_state *state) size_t sector_sz_pri = 0; size_t sector_sz_sec = 0; size_t i; - size_t num_usable_sectors; num_sectors_pri = boot_img_num_sectors(state, BOOT_PRIMARY_SLOT); num_sectors_sec = boot_img_num_sectors(state, BOOT_SECONDARY_SLOT); - num_usable_sectors = app_max_sectors(state); if (num_sectors_pri != num_sectors_sec && - (num_sectors_pri + 1) != num_sectors_sec && - num_usable_sectors != (num_sectors_sec - 1)) { + (num_sectors_pri + 1) != num_sectors_sec) { BOOT_LOG_WRN("Cannot upgrade: not a compatible amount of sectors"); BOOT_LOG_DBG("slot0 sectors: %d, slot1 sectors: %d, usable sectors: %d", (int)num_sectors_pri, (int)num_sectors_sec, - (int)(num_usable_sectors)); + (int)(num_sectors_sec - 1)); return 0; } else if (num_sectors_pri > BOOT_MAX_IMG_SECTORS) { BOOT_LOG_WRN("Cannot upgrade: more sectors than allowed"); return 0; } - if ((num_usable_sectors + 1) != num_sectors_sec) { + /* Optimal says secondary has one more than primary. Always. Both have trailers. */ + if ((num_sectors_pri + 1) != num_sectors_sec) { BOOT_LOG_DBG("Non-optimal sector distribution, slot0 has %d usable sectors " - "but slot1 has %d usable sectors", (int)(num_usable_sectors), + "but slot1 has %d usable sectors", (int)(num_sectors_pri), ((int)num_sectors_sec - 1)); } - for (i = 0; i < num_usable_sectors; i++) { + for (i = 0; i < (num_sectors_sec - 1); i++) { sector_sz_pri = boot_img_sector_size(state, BOOT_PRIMARY_SLOT, i); sector_sz_sec = boot_img_sector_size(state, BOOT_SECONDARY_SLOT, i); @@ -417,7 +388,6 @@ int swap_status_source(struct boot_loader_state *state) struct boot_swap_state state_primary_slot; struct boot_swap_state state_secondary_slot; int rc; - uint8_t source; uint8_t image_index; #if (BOOT_IMAGE_NUMBER == 1) @@ -439,10 +409,8 @@ int swap_status_source(struct boot_loader_state *state) state_primary_slot.copy_done == BOOT_FLAG_UNSET && state_secondary_slot.magic != BOOT_MAGIC_GOOD) { - source = BOOT_STATUS_SOURCE_PRIMARY_SLOT; - BOOT_LOG_INF("Boot source: primary slot"); - return source; + return BOOT_STATUS_SOURCE_PRIMARY_SLOT; } BOOT_LOG_INF("Boot source: none"); @@ -729,11 +697,23 @@ void swap_run(struct boot_loader_state *state, struct boot_status *bs, int app_max_size(struct boot_loader_state *state) { - uint32_t sector_sz_primary; + uint32_t available_pri_sz; + uint32_t available_sec_sz; + + size_t trailer_sz = boot_trailer_sz(BOOT_WRITE_SZ(state)); + size_t sector_sz = boot_img_sector_size(state, BOOT_PRIMARY_SLOT, 0); + size_t padding_sz = sector_sz; + + /* The trailer size needs to be sector-aligned */ + trailer_sz = ALIGN_UP(trailer_sz, sector_sz); - sector_sz_primary = boot_img_sector_size(state, BOOT_PRIMARY_SLOT, 0); + /* The slot whose size is used to compute the maximum image size must be the one containing the + * padding required for the swap. + */ + available_pri_sz = boot_img_num_sectors(state, BOOT_PRIMARY_SLOT) * sector_sz - trailer_sz; + available_sec_sz = boot_img_num_sectors(state, BOOT_SECONDARY_SLOT) * sector_sz - trailer_sz - padding_sz; - return app_max_sectors(state) * sector_sz_primary; + return (available_pri_sz < available_sec_sz ? available_pri_sz : available_sec_sz); } /* Compute the total size of the given image. Includes the size of the TLVs. */ diff --git a/boot/bootutil/src/swap_scratch.c b/boot/bootutil/src/swap_scratch.c index f9dbb7103..3bc6b8f48 100644 --- a/boot/bootutil/src/swap_scratch.c +++ b/boot/bootutil/src/swap_scratch.c @@ -907,7 +907,7 @@ int app_max_size(struct boot_loader_state *state) fap = BOOT_IMG_AREA(state, active_slot); assert(fap != NULL); - primary_sz = flash_area_get_size(fap); + primary_sz = bootutil_max_image_size(state, fap); if (active_slot == BOOT_PRIMARY_SLOT) { active_slot = BOOT_SECONDARY_SLOT; @@ -917,7 +917,7 @@ int app_max_size(struct boot_loader_state *state) fap = BOOT_IMG_AREA(state, active_slot); assert(fap != NULL); - secondary_sz = flash_area_get_size(fap); + secondary_sz = bootutil_max_image_size(state, fap); return (secondary_sz < primary_sz ? secondary_sz : primary_sz); }