Skip to content

bootutil: Unify app_max_size() implementations #2318

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions boot/bootutil/include/bootutil/bootutil_public.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
*
Expand Down
24 changes: 4 additions & 20 deletions boot/bootutil/src/bootutil_misc.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down Expand Up @@ -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);
Expand Down
55 changes: 19 additions & 36 deletions boot/bootutil/src/swap_move.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
{
Expand All @@ -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");
Expand All @@ -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);
}

Expand Down Expand Up @@ -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)
Expand All @@ -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");
Expand Down Expand Up @@ -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
64 changes: 22 additions & 42 deletions boot/bootutil/src/swap_offset.c
Original file line number Diff line number Diff line change
Expand Up @@ -302,66 +302,37 @@ 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;
size_t num_sectors_sec;
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);

Expand Down Expand Up @@ -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)
Expand All @@ -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");
Expand Down Expand Up @@ -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. */
Expand Down
4 changes: 2 additions & 2 deletions boot/bootutil/src/swap_scratch.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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);
}
Expand Down