Skip to content

Commit

Permalink
New OVERWRITE_ONLY_KEEP_BACKUP option
Browse files Browse the repository at this point in the history
It builds on top of OVERWRITE_ONLY mode and uses secondary slot
as a backup of the primary slot. The main difference is that after
image copy to the primary slot the secondary slot is not erased.
This is meant to be used together with BOOTSTRAP option that will
reinstall the primary image with the backup in case it's not valid.
The backup is checked on every boot. It case it's invalid the image
from the primary slot is used to create a valid backup again.
  • Loading branch information
PetrBuchtaNXP committed Feb 24, 2024
1 parent 304fd41 commit 919733e
Showing 1 changed file with 82 additions and 0 deletions.
82 changes: 82 additions & 0 deletions boot/bootutil/src/loader.c
Original file line number Diff line number Diff line change
Expand Up @@ -1215,6 +1215,7 @@ boot_copy_image(struct boot_loader_state *state, struct boot_status *bs)
}
#endif /* MCUBOOT_HW_ROLLBACK_PROT */

#ifndef MCUBOOT_OVERWRITE_ONLY_KEEP_BACKUP
/*
* Erases header and trailer. The trailer is erased because when a new
* image is written without a trailer as is the case when using newt, the
Expand All @@ -1225,6 +1226,8 @@ boot_copy_image(struct boot_loader_state *state, struct boot_status *bs)
boot_img_sector_off(state, BOOT_SECONDARY_SLOT, 0),
boot_img_sector_size(state, BOOT_SECONDARY_SLOT, 0));
assert(rc == 0);
#endif

last_sector = boot_img_num_sectors(state, BOOT_SECONDARY_SLOT) - 1;
BOOT_LOG_DBG("erasing secondary trailer");
rc = boot_erase_region(fap_secondary_slot,
Expand All @@ -1243,6 +1246,82 @@ boot_copy_image(struct boot_loader_state *state, struct boot_status *bs)
}
#endif

#ifdef MCUBOOT_OVERWRITE_ONLY_KEEP_BACKUP

/**
* Validates backup of the primary image in the secondary slot.
* In case of invalid image, it tries to clone the primary slot
* into the secondary slot to restore a valid backup.
*/

static void
check_primary_backup(struct boot_loader_state *state,
struct boot_status *bs)
{
int rc;
FIH_DECLARE(fih_rc, FIH_FAILURE);
size_t sect_count;
size_t sect;
size_t size;
size_t this_size;
size_t last_sector;
const struct flash_area *fap_primary_slot;
const struct flash_area *fap_secondary_slot;
uint8_t image_index;

FIH_CALL(boot_validate_slot, fih_rc, state, BOOT_SECONDARY_SLOT, bs);

if (FIH_EQ(fih_rc, FIH_SUCCESS)) {
/* Secondary image is valid; Nothing to do. */
return;
}

FIH_CALL(boot_validate_slot, fih_rc, state, BOOT_PRIMARY_SLOT, bs);

if (FIH_NOT_EQ(fih_rc, FIH_SUCCESS)) {
/* Invalid primary image; Nothing to backup */
return;
}

BOOT_LOG_INF("Restoring invalid primary image backup");

image_index = BOOT_CURR_IMG(state);

rc = flash_area_open(FLASH_AREA_IMAGE_PRIMARY(image_index), &fap_primary_slot);
assert(rc == 0);

rc = flash_area_open(FLASH_AREA_IMAGE_SECONDARY(image_index), &fap_secondary_slot);
assert(rc == 0);

BOOT_LOG_INF("Erasing secondary slot");

sect_count = boot_img_num_sectors(state, BOOT_SECONDARY_SLOT);
for (sect = 0, size = 0; sect < sect_count; sect++) {
this_size = boot_img_sector_size(state, BOOT_SECONDARY_SLOT, sect);
rc = boot_erase_region(fap_secondary_slot, size, this_size);
assert(rc == 0);
size += this_size;
}

BOOT_LOG_INF("Copying primary -> secondary");

rc = boot_copy_region(state, fap_primary_slot, fap_secondary_slot, 0, 0, size);
if (rc != 0) {
BOOT_LOG_ERR("Failed to backup primary image!");
}

last_sector = boot_img_num_sectors(state, BOOT_SECONDARY_SLOT) - 1;
BOOT_LOG_DBG("Erasing secondary trailer");
rc = boot_erase_region(fap_secondary_slot,
boot_img_sector_off(state, BOOT_SECONDARY_SLOT, last_sector),
boot_img_sector_size(state, BOOT_SECONDARY_SLOT, last_sector));
assert(rc == 0);

flash_area_close(fap_primary_slot);
flash_area_close(fap_secondary_slot);
}
#endif

#if !defined(MCUBOOT_OVERWRITE_ONLY)
/**
* Swaps the two images in flash. If a prior copy operation was interrupted
Expand Down Expand Up @@ -2178,6 +2257,9 @@ context_boot_go(struct boot_loader_state *state, struct boot_rsp *rsp)
BOOT_SWAP_TYPE(state) = BOOT_SWAP_TYPE_PANIC;
}

#ifdef MCUBOOT_OVERWRITE_ONLY_KEEP_BACKUP
check_primary_backup(state, &bs);
#endif
if (BOOT_SWAP_TYPE(state) == BOOT_SWAP_TYPE_PANIC) {
BOOT_LOG_ERR("panic!");
assert(0);
Expand Down

0 comments on commit 919733e

Please sign in to comment.