Skip to content

Commit

Permalink
bootutil: Add support for devices without erase
Browse files Browse the repository at this point in the history
add boot_scramble_slot function and modify boot_erase_region to check
if device requires erase.
The change reduces wear on devices that do not require erase and improves
swap times.

Signed-off-by: Dominik Ermel <[email protected]>
  • Loading branch information
de-nordic committed Nov 11, 2024
1 parent f74b77c commit 373872d
Show file tree
Hide file tree
Showing 10 changed files with 85 additions and 9 deletions.
4 changes: 2 additions & 2 deletions boot/boot_serial/src/boot_serial.c
Original file line number Diff line number Diff line change
Expand Up @@ -759,7 +759,7 @@ static off_t erase_range(const struct flash_area *fap, off_t start, off_t end)
BOOT_LOG_DBG("Erasing range 0x%jx:0x%jx", (intmax_t)start,
(intmax_t)(start + size - 1));

rc = flash_area_erase(fap, start, size);
rc = boot_erase_region(fap, start, size);
if (rc != 0) {
BOOT_LOG_ERR("Error %d while erasing range", rc);
return -EINVAL;
Expand Down Expand Up @@ -895,7 +895,7 @@ bs_upload(char *buf, int len)
/* Non-progressive erase erases entire image slot when first chunk of
* an image is received.
*/
rc = flash_area_erase(fap, 0, area_size);
rc = boot_erase_region(fap, 0, area_size);
if (rc) {
goto out_invalid_data;
}
Expand Down
2 changes: 1 addition & 1 deletion boot/boot_serial/src/boot_serial_encryption.c
Original file line number Diff line number Diff line change
Expand Up @@ -175,7 +175,7 @@ decrypt_region_inplace(struct boot_loader_state *state,
(off + bytes_copied + idx) - hdr->ih_hdr_size, blk_sz,
blk_off, &buf[idx]);
}
rc = flash_area_erase(fap, off + bytes_copied, chunk_sz);
rc = boot_erase_region(fap, off + bytes_copied, chunk_sz);
if (rc != 0) {
return BOOT_EFLASH;
}
Expand Down
3 changes: 3 additions & 0 deletions boot/bootutil/src/bootutil_priv.h
Original file line number Diff line number Diff line change
Expand Up @@ -301,6 +301,9 @@ int boot_copy_region(struct boot_loader_state *state,
const struct flash_area *fap_dst,
uint32_t off_src, uint32_t off_dst, uint32_t sz);
int boot_erase_region(const struct flash_area *fap, uint32_t off, uint32_t sz);
/* Makes slot unbootable, either by scrambling header magic, header sector
* or entire slot, depending on settings */
int boot_scramble_slot(const struct flash_area *fap);
bool boot_status_is_reset(const struct boot_status *bs);

#ifdef MCUBOOT_ENC_IMAGES
Expand Down
60 changes: 54 additions & 6 deletions boot/bootutil/src/loader.c
Original file line number Diff line number Diff line change
Expand Up @@ -1089,7 +1089,7 @@ boot_validate_slot(struct boot_loader_state *state, int slot,
&boot_img_hdr(state, BOOT_PRIMARY_SLOT)->ih_ver);
if (rc < 0 && boot_check_header_erased(state, BOOT_PRIMARY_SLOT)) {
BOOT_LOG_ERR("insufficient version in secondary slot");
flash_area_erase(fap, 0, flash_area_get_size(fap));
boot_scramble_slot(fap);
/* Image in the secondary slot does not satisfy version requirement.
* Erase the image and continue booting from the primary slot.
*/
Expand All @@ -1109,7 +1109,7 @@ boot_validate_slot(struct boot_loader_state *state, int slot,
}
if (FIH_NOT_EQ(fih_rc, FIH_SUCCESS)) {
if ((slot != BOOT_PRIMARY_SLOT) || ARE_SLOTS_EQUIVALENT()) {
flash_area_erase(fap, 0, flash_area_get_size(fap));
boot_scramble_slot(fap);
/* Image is invalid, erase it to prevent further unnecessary
* attempts to validate and boot it.
*/
Expand Down Expand Up @@ -1150,7 +1150,7 @@ boot_validate_slot(struct boot_loader_state *state, int slot,
*
* Erase the image and continue booting from the primary slot.
*/
flash_area_erase(fap, 0, fap->fa_size);
boot_scramble_slot(fap);
fih_rc = FIH_NO_BOOTABLE_IMAGE;
goto out;
}
Expand Down Expand Up @@ -1256,7 +1256,54 @@ boot_validated_swap_type(struct boot_loader_state *state,
int
boot_erase_region(const struct flash_area *fap, uint32_t off, uint32_t sz)
{
return flash_area_erase(fap, off, sz);
if (flash_area_erase_required(fap)) {
return flash_area_erase(fap, off, sz);
}
return 0;
}

int
boot_scramble_slot(const struct flash_area *fap)
{
int ret = 0;
size_t size;

#if !defined(MCUBOOT_MINIMAL_SCRAMBLE)
size = flash_area_get_size(fap);
#endif

if (flash_area_erase_required(fap)) {
#if defined(MCUBOOT_MINIMAL_SCRAMBLE)
struct flash_sector header;
size_t size;

ret = flash_area_get_sector(fap, 0, &header);
size = header.size;

if (ret != 0) {
return ret;
}
#endif
return flash_area_erase(fap, 0, size);
} else {
uint8_t buf[BOOT_MAX_ALIGN];
size_t size_done = 0;

#if defined(MCUBOOT_MINIMAL_SCRAMBLE)
size_t size = MAX(image_header.magic, BOOT_MAX_ALIGN);
size = (size + BOOT_MAX_ALIGN - 1) & ~(BOOT_MAX_ALIGN - 1);
#endif
memset(buf, 0x00, sizeof(buf));

while (size_done < size) {
ret = flash_area_write(fap, size_done, buf, sizeof(buf));
if (ret != 0) {
break;
}
size_done += sizeof(buf);
}
}
return ret;
}

#if !defined(MCUBOOT_DIRECT_XIP) && !defined(MCUBOOT_RAM_LOAD)
Expand Down Expand Up @@ -2181,8 +2228,8 @@ check_downgrade_prevention(struct boot_loader_state *state)
if (rc < 0) {
/* Image in slot 0 prevents downgrade, delete image in slot 1 */
BOOT_LOG_INF("Image %d in slot 1 erased due to downgrade prevention", BOOT_CURR_IMG(state));
flash_area_erase(BOOT_IMG(state, 1).area, 0,
flash_area_get_size(BOOT_IMG(state, 1).area));
/* TODO: removal of header should be enough */
boot_scramble_slot(fap);
} else {
rc = 0;
}
Expand Down Expand Up @@ -2732,6 +2779,7 @@ boot_select_or_erase(struct boot_loader_state *state)
*/
BOOT_LOG_DBG("Erasing faulty image in the %s slot.",
(active_slot == BOOT_PRIMARY_SLOT) ? "primary" : "secondary");
/* TODO: Scramble header should be enough */
rc = flash_area_erase(fap, 0, flash_area_get_size(fap));
assert(rc == 0);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -192,4 +192,6 @@ uint8_t flash_area_erased_val(const struct flash_area *fap);
int flash_area_read_is_empty(const struct flash_area *fa, uint32_t off,
void *dst, uint32_t len);

#define flash_area_erase_required(fa) (true)

#endif /* __FLASH_MAP_BACKEND_H__ */
2 changes: 2 additions & 0 deletions boot/espressif/include/flash_map_backend/flash_map_backend.h
Original file line number Diff line number Diff line change
Expand Up @@ -91,3 +91,5 @@ int flash_area_get_sector(const struct flash_area *area, uint32_t off,
int flash_area_id_from_multi_image_slot(int image_index, int slot);
int flash_area_id_from_image_slot(int slot);
int flash_area_to_sectors(int idx, int *cnt, struct flash_area *fa);

#define flash_area_erase_required(fa) (true)
2 changes: 2 additions & 0 deletions boot/mbed/include/flash_map_backend/flash_map_backend.h
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,8 @@ int flash_area_id_from_multi_image_slot(int image_index, int slot);
*/
int flash_area_id_to_multi_image_slot(int image_index, int area_id);

#define flash_area_erase_required(fa) (true)

#ifdef __cplusplus
}
#endif
Expand Down
2 changes: 2 additions & 0 deletions boot/nuttx/include/flash_map_backend/flash_map_backend.h
Original file line number Diff line number Diff line change
Expand Up @@ -442,6 +442,8 @@ int flash_area_id_to_multi_image_slot(int image_index, int area_id);

int flash_area_id_from_image_offset(uint32_t offset);

#define flash_area_erase_required(fa) (true)

#ifdef __cplusplus
}
#endif
Expand Down
15 changes: 15 additions & 0 deletions boot/zephyr/include/flash_map_backend/flash_map_backend.h
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,21 @@ static inline uint32_t flash_sector_get_size(const struct flash_sector *fs)
int flash_area_get_sector(const struct flash_area *fa, off_t off,
struct flash_sector *fs);

static inline bool flash_area_erase_required(const struct flash_area *fa)
{
#if defined(CONFIG_FLASH_HAS_EXPLICIT_ERASE) && defined(CONFIG_FLASH_HAS_NO_EXPLICIT_ERASE)
const struct flash_parameters *fp = flash_get_parameters(flash_area_get_device(fap));

return flash_params_get_erase_cap(flash_get_parameters(flash_area_get_device(fap))) & FLASH_ERASE_C_EXPLICIT;
#else
#if defined(CONFIG_FLASH_HAS_EXPLICIT_ERASE)
return true;
#else
return false;
#endif
#endif

}
#ifdef __cplusplus
}
#endif
Expand Down
2 changes: 2 additions & 0 deletions sim/mcuboot-sys/csupport/storage/flash_map.h
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,8 @@ int flash_area_id_from_image_slot(int slot);
int flash_area_id_from_multi_image_slot(int image_index, int slot);
int flash_area_id_to_multi_image_slot(int image_index, int area_id);

#define flash_area_erase_required (true)

#ifdef __cplusplus
}
#endif
Expand Down

0 comments on commit 373872d

Please sign in to comment.