Skip to content

boot: bootutil: Fix max image size computation for swap-move and swap-offset #2283

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 4 commits into
base: main
Choose a base branch
from

Conversation

taltenbach
Copy link
Contributor

@taltenbach taltenbach commented Apr 27, 2025

When computing the maximum image size in bootutil_max_image_size for the swap-move or swap-offset strategy, the computation was using the size of the flash area provided as argument and was not taking into account the size of the padding sector. This was causing an incorrect (too large) size to be returned in the following cases:

  • Both primary and secondary slots have the same size.
  • The primary and secondary slots don't have the same size, but the routine is called for the slot containing the padding sector.

For example, let's imagine swap-move is being used on a device having a sector size S and two slots of N bytes. This is valid configuration and the maximum image size is N - S - T, T being the size of the trailer rounded up to the next multiple of S. When calling bootutil_max_image_size with either the primary or secondary slot, the size N - T is returned, which is incorrect.

This was not detected by the tests since, due to limitations of the simulator, the swap-move and swap-offset strategies were not tested with the largest possible images. In addition to fixing the issue in bootutil_max_image_size, this PR modifies the simulator to allow the simulator to use largest possible images for all strategies and therefore detect those kind of issues.

Comment on lines 478 to 500
#elif defined(MCUBOOT_SWAP_USING_MOVE)
(void) fap;

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);
const struct flash_area *fap_pri = BOOT_IMG_AREA(state, BOOT_PRIMARY_SLOT);
assert(fap_pri != NULL);

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);

return flash_area_get_size(fap_pri) - trailer_sz - padding_sz;
#elif defined(MCUBOOT_SWAP_USING_OFFSET)
(void) fap;

const struct flash_area *fap_sec = BOOT_IMG_AREA(state, BOOT_SECONDARY_SLOT);
assert(fap_sec != NULL);

size_t trailer_sz = boot_trailer_sz(BOOT_WRITE_SZ(state));
size_t sector_sz = boot_img_sector_size(state, BOOT_SECONDARY_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_sec) - trailer_sz - padding_sz;
#elif defined(MCUBOOT_OVERWRITE_ONLY)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you ifdef around variable assigned with BOOT_PRIMARY_SLOT or BOOT_SECONDARY_SLOT, and passed where these are accepted, then there is no difference between both blocks.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@de-nordic You're right, I was anticipating #2247, which will need different logic for swap-move and swap-offset. But considering only this PR, it makes indeed more sense to merge the two blocks. I updated my changes accordingly

taltenbach added 4 commits May 1, 2025 17:07
When computing the maximum image size in bootutil_max_image_size for
swap-move or swap-offset strategy, the computation was using the size of
the flash area provided as argument and was not taking into account the
size of the padding sector. This was causing an incorrect size to be
returned in some cases, for example when the two slots have the same
size or when the slots haven't the same size but the routine is called
for the slot containing the padding sector.

For example, let's imagine swap-move is being used on a device having a
sector size S and two slots of N bytes. This is valid configuration and
the maximum image size is N - S - T, T being the size of the trailer
rounded up to the next multiple of S. When calling
bootutil_max_image_size with either the primary or secondary slot, the
size N - T is returned, which is incorrect.

This commit fixes the issue by computing always the maximum image using
the size of the slot containing the padding and substracting the size of
the padding and of the aligned trailer.

Signed-off-by: Thomas Altenbach <[email protected]>
When checking the size of an image in bootutil_img_validate, the offset
to the end of the TLV area was used as the image size in all cases.
However, when using swap-offset, the upgrade image is written in the
secondary with an offset. This offset is not part of the image and must
therefore not be taken into account in the image size.

Signed-off-by: Thomas Altenbach <[email protected]>
For the swap-move and swap-offset strategies, the computation of the
largest image size was not taking taking into account the padding that
is needed when using those strategies. Due to this limitation, the
simulator is currently using hardcoded image sizes, smaller than the
maximum possible size, when running tests for the swap-move or
swap-offset strategies. This commit fixes the maximum image size
computation for those strategies.

Signed-off-by: Thomas Altenbach <[email protected]>
The simulator was testing the upgrade with the largest image possible
for all strategies, except for overwrite-only, swap-move and swap-offset
because some tests were failing when the maximum image size was used.

For overwrite-only, this was due to an incorrect trailer size
computation. This has been fixed by
88294be.

For swap-move and swap-offset, this was due to the simulator not taking
into account the padding needed by those strategies in the primary or
secondary slot, but also to incorrect computation of the maximum image
size in some cases by the MCUboot library. Both issues have been fixed
by the previous commits.

Since all those issues have been fixed, the simulator can now be
configured to test upgrade with the largest possible image for all
strategies.

Note that logic needed to generate image of a given image is kept even
if not useful anymore at the moment, since that might be needed when
test will be added to ensure proper behavior when images of different
sizes are used.

Signed-off-by: Thomas Altenbach <[email protected]>
@taltenbach taltenbach force-pushed the fix/swap-move-swap-offset-max-img-size branch from a494479 to 52ba928 Compare May 1, 2025 15:08
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants