Skip to content

boot: bootutil: swap-move: Allow trailer area not be a multiple of the sector size #2247

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 10 commits into
base: main
Choose a base branch
from
Open
42 changes: 34 additions & 8 deletions boot/bootutil/src/bootutil_misc.c
Original file line number Diff line number Diff line change
@@ -397,12 +397,13 @@ boot_write_enc_key(const struct flash_area *fap, uint8_t slot,
}
#endif

#ifdef MCUBOOT_SWAP_USING_SCRATCH
#if defined(MCUBOOT_SWAP_USING_SCRATCH) || defined(MCUBOOT_SWAP_USING_MOVE)
size_t
boot_get_first_trailer_sector(struct boot_loader_state *state, size_t slot, size_t trailer_sz)
boot_get_first_trailer_sector(struct boot_loader_state *state, size_t slot)
{
size_t first_trailer_sector = boot_img_num_sectors(state, slot) - 1;
size_t sector_sz = boot_img_sector_size(state, slot, first_trailer_sector);
size_t trailer_sz = boot_trailer_sz(BOOT_WRITE_SZ(state));
size_t trailer_sector_sz = sector_sz;

while (trailer_sector_sz < trailer_sz) {
@@ -415,20 +416,21 @@ boot_get_first_trailer_sector(struct boot_loader_state *state, size_t slot, size

return first_trailer_sector;
}
#endif /* MCUBOOT_SWAP_USING_SCRATCH || MCUBOOT_SWAP_USING_MOVE */

#ifdef MCUBOOT_SWAP_USING_SCRATCH
/**
* Returns the offset to the end of the first sector of a given slot that holds image trailer data.
*
* @param state Current bootloader's state.
* @param slot The index of the slot to consider.
* @param trailer_sz The size of the trailer, in bytes.
*
* @return The offset to the end of the first sector of the slot that holds image trailer data.
*/
static uint32_t
get_first_trailer_sector_end_off(struct boot_loader_state *state, size_t slot, size_t trailer_sz)
get_first_trailer_sector_end_off(struct boot_loader_state *state, size_t slot)
{
size_t first_trailer_sector = boot_get_first_trailer_sector(state, slot, trailer_sz);
size_t first_trailer_sector = boot_get_first_trailer_sector(state, slot);

return boot_img_sector_off(state, slot, first_trailer_sector) +
boot_img_sector_size(state, slot, first_trailer_sector);
@@ -455,9 +457,9 @@ uint32_t bootutil_max_image_size(struct boot_loader_state *state, const struct f
* trailer containing part of the trailer in the primary and secondary slot.
*/
size_t trailer_sector_primary_end_off =
get_first_trailer_sector_end_off(state, BOOT_PRIMARY_SLOT, slot_trailer_sz);
get_first_trailer_sector_end_off(state, BOOT_PRIMARY_SLOT);
size_t trailer_sector_secondary_end_off =
get_first_trailer_sector_end_off(state, BOOT_SECONDARY_SLOT, slot_trailer_sz);
get_first_trailer_sector_end_off(state, BOOT_SECONDARY_SLOT);

size_t trailer_sz_in_first_sector;

@@ -475,7 +477,31 @@ 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)
#elif defined(MCUBOOT_SWAP_USING_MOVE)
(void) fap;

const struct flash_area *fap_pri = BOOT_IMG_AREA(state, BOOT_PRIMARY_SLOT);
assert(fap_pri != NULL);

/* Swap-move needs to reserve in the primary slot the size of one full sector plus some space at
* the end of the slot to write the trailer. Also, it must be ensured at least
* BOOT_MAGIC_ALIGN_SIZE bytes are available in the last sector that is not containing part of
* the slot's trailer to be able to write the fallback trailer. That is always the case unless
* the trailer is only a few bytes larger than the size of a sector, i.e. unless:
* 0 < trailer_sz % sector_sz < BOOT_MAGIC_ALIGN_SIZE
*/
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 = sector_sz;

size_t trailer_sz_in_padding_sector = trailer_sz % sector_sz;

if (trailer_sz_in_padding_sector > 0 && trailer_sz_in_padding_sector < BOOT_MAGIC_ALIGN_SIZE) {
padding += BOOT_MAGIC_ALIGN_SIZE - trailer_sz_in_padding_sector;
}

return flash_area_get_size(fap_pri) - trailer_sz - padding;
#elif defined(MCUBOOT_SWAP_USING_OFFSET)
(void) state;

struct flash_sector sector;
2 changes: 1 addition & 1 deletion boot/bootutil/src/bootutil_misc.h
Original file line number Diff line number Diff line change
@@ -16,7 +16,7 @@
#include "bootutil/enc_key.h"
#endif

static int
static inline int
boot_magic_decode(const uint8_t *magic)
{
if (memcmp(magic, BOOT_IMG_MAGIC, BOOT_MAGIC_SZ) == 0) {
8 changes: 4 additions & 4 deletions boot/bootutil/src/bootutil_priv.h
Original file line number Diff line number Diff line change
@@ -317,6 +317,7 @@ uint32_t boot_status_off(const struct flash_area *fap);
int boot_read_swap_state(const struct flash_area *fap,
struct boot_swap_state *state);
int boot_write_magic(const struct flash_area *fap);
int boot_write_magic_at_off(const struct flash_area *fap, uint32_t off);
int boot_write_status(const struct boot_loader_state *state, struct boot_status *bs);
int boot_write_copy_done(const struct flash_area *fap);
int boot_write_image_ok(const struct flash_area *fap);
@@ -365,19 +366,18 @@ int boot_read_enc_key(const struct flash_area *fap, uint8_t slot,
struct boot_status *bs);
#endif

#ifdef MCUBOOT_SWAP_USING_SCRATCH
#if defined(MCUBOOT_SWAP_USING_SCRATCH) || defined(MCUBOOT_SWAP_USING_MOVE)
/**
* Finds the first sector of a given slot that holds image trailer data.
*
* @param state Current bootloader's state.
* @param slot The index of the slot to consider.
* @param trailer_sz The size of the trailer, in bytes.
*
* @return The index of the first sector of the slot that holds image trailer data.
*/
size_t
boot_get_first_trailer_sector(struct boot_loader_state *state, size_t slot, size_t trailer_sz);
#endif
boot_get_first_trailer_sector(struct boot_loader_state *state, size_t slot);
#endif /* MCUBOOT_SWAP_USING_SCRATCH || MCUBOOT_SWAP_USING_MOVE */

/**
* Checks that a buffer is erased according to what the erase value for the
13 changes: 11 additions & 2 deletions boot/bootutil/src/bootutil_public.c
Original file line number Diff line number Diff line change
@@ -302,14 +302,23 @@ boot_read_swap_state_by_id(int flash_area_id, struct boot_swap_state *state)
int
boot_write_magic(const struct flash_area *fap)
{
int rc = 0;
uint32_t off;

off = boot_magic_off(fap);
rc = boot_write_magic_at_off(fap, off);

return rc;
}

int
boot_write_magic_at_off(const struct flash_area *fap, uint32_t off)
{
uint32_t pad_off;
int rc;
uint8_t magic[BOOT_MAGIC_ALIGN_SIZE];
uint8_t erased_val;

off = boot_magic_off(fap);

/* image_trailer structure was modified with additional padding such that
* the pad+magic ends up in a flash minimum write region. The address
* returned by boot_magic_off() is the start of magic which is not the
Loading
Loading