Skip to content

NCSDK-33289: Unify max app size methods #440

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

Open
wants to merge 6 commits into
base: main
Choose a base branch
from
Open
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
17 changes: 5 additions & 12 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

#if defined(MCUBOOT_DECOMPRESS_IMAGES)
#include <nrf_compress/implementation.h>
Expand Down Expand Up @@ -482,18 +485,8 @@ 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) state;

struct flash_sector sector;
/* get the last sector offset */
int rc = flash_area_get_sector(fap, boot_status_off(fap), &sector);
if (rc) {
BOOT_LOG_ERR("Unable to determine flash sector of the image trailer");
return 0; /* Returning of zero here should cause any check which uses
* this value to fail.
*/
}
return flash_sector_get_off(&sector);
(void) fap;
return app_max_size(state);
#elif defined(MCUBOOT_OVERWRITE_ONLY)
(void) state;
return boot_swap_info_off(fap);
Expand Down
9 changes: 8 additions & 1 deletion boot/bootutil/src/image_validate.c
Original file line number Diff line number Diff line change
Expand Up @@ -501,6 +501,7 @@ bootutil_img_validate(struct boot_loader_state *state,
uint32_t off;
uint16_t len;
uint16_t type;
uint32_t img_sz;
#ifdef EXPECTED_SIG_TLV
FIH_DECLARE(valid_signature, FIH_FAILURE);
#ifndef MCUBOOT_BUILTIN_KEY
Expand Down Expand Up @@ -637,7 +638,13 @@ bootutil_img_validate(struct boot_loader_state *state,
goto out;
}

if (it.tlv_end > bootutil_max_image_size(state, fap)) {
#ifdef MCUBOOT_SWAP_USING_OFFSET
img_sz = it.tlv_end - it.start_off;
#else
img_sz = it.tlv_end;
#endif

if (img_sz > bootutil_max_image_size(state, fap)) {
rc = -1;
goto out;
}
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 @@ -270,19 +247,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 @@ -292,7 +266,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 @@ -353,7 +327,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 @@ -378,10 +351,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 @@ -603,11 +574,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 @@ -920,7 +920,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 @@ -930,7 +930,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
Loading
Loading