@@ -362,9 +362,14 @@ swap_status_source(struct boot_loader_state *state)
362
362
BOOT_LOG_SWAP_STATE ("Secondary image" , & state_secondary_slot );
363
363
364
364
if (state_primary_slot .magic == BOOT_MAGIC_GOOD &&
365
- state_primary_slot .copy_done == BOOT_FLAG_UNSET &&
366
- state_secondary_slot .magic != BOOT_MAGIC_GOOD ) {
367
-
365
+ state_primary_slot .copy_done == BOOT_FLAG_UNSET ) {
366
+ /* In this case, either:
367
+ * - A swap operation was interrupted and can be resumed from the status stored in the
368
+ * primary slot's trailer.
369
+ * - No swap was ever made and the initial firmware image has been written with a MCUboot
370
+ * trailer. In this case, the status in the primary slot's trailer is empty and there is
371
+ * no harm in loading it.
372
+ */
368
373
source = BOOT_STATUS_SOURCE_PRIMARY_SLOT ;
369
374
370
375
BOOT_LOG_INF ("Boot source: primary slot" );
@@ -380,8 +385,7 @@ swap_status_source(struct boot_loader_state *state)
380
385
*/
381
386
static void
382
387
boot_move_sector_up (size_t idx , uint32_t sz , struct boot_loader_state * state ,
383
- struct boot_status * bs , const struct flash_area * fap_pri ,
384
- const struct flash_area * fap_sec )
388
+ struct boot_status * bs , const struct flash_area * fap_pri )
385
389
{
386
390
uint32_t new_off ;
387
391
uint32_t old_off ;
@@ -425,12 +429,6 @@ boot_move_sector_up(size_t idx, uint32_t sz, struct boot_loader_state *state,
425
429
copy_sz = bs -> swap_size % sz ;
426
430
sector_erased_with_trailer = true;
427
431
}
428
-
429
- /* Remove status from secondary slot trailer, in case of device with
430
- * erase requirement this will also prepare traier for write.
431
- */
432
- rc = swap_scramble_trailer_sectors (state , fap_sec );
433
- assert (rc == 0 );
434
432
}
435
433
436
434
if (!sector_erased_with_trailer ) {
@@ -448,7 +446,7 @@ boot_move_sector_up(size_t idx, uint32_t sz, struct boot_loader_state *state,
448
446
}
449
447
450
448
static void
451
- boot_swap_sectors (int idx , uint32_t sz , struct boot_loader_state * state ,
449
+ boot_swap_sectors (size_t idx , size_t last_idx , uint32_t sz , struct boot_loader_state * state ,
452
450
struct boot_status * bs , const struct flash_area * fap_pri ,
453
451
const struct flash_area * fap_sec )
454
452
{
@@ -474,10 +472,43 @@ boot_swap_sectors(int idx, uint32_t sz, struct boot_loader_state *state,
474
472
}
475
473
476
474
if (bs -> state == BOOT_STATUS_STATE_1 ) {
477
- rc = boot_erase_region (fap_sec , sec_off , sz );
478
- assert (rc == 0 );
475
+ bool sector_erased_with_trailer = false;
476
+ uint32_t copy_sz = sz ;
477
+
478
+ if (idx == last_idx ) {
479
+ rc = swap_scramble_trailer_sectors (state , fap_sec );
480
+ assert (rc == 0 );
481
+
482
+ size_t first_trailer_sector_pri =
483
+ boot_get_first_trailer_sector (state , BOOT_PRIMARY_SLOT );
484
+ size_t first_trailer_sector_sec =
485
+ boot_get_first_trailer_sector (state , BOOT_SECONDARY_SLOT );
486
+
487
+ if (first_trailer_sector_sec == idx - 1 ) {
488
+ /* The destination sector was containing part of the trailer and has therefore
489
+ * already been erased.
490
+ */
491
+ sector_erased_with_trailer = true;
492
+ }
493
+
494
+ if (first_trailer_sector_pri == idx ) {
495
+ /* The source sector contains both firmware and trailer data, so only the firmware
496
+ * data must be copied to the destination sector.
497
+ *
498
+ * Swap-move => constant sector size, so 'sz' is the size of a sector and 'swap_size
499
+ * % sz' gives the number of bytes used by the largest firmware image in the last
500
+ * sector to be moved.
501
+ */
502
+ copy_sz = bs -> swap_size % sz ;
503
+ }
504
+ }
505
+
506
+ if (!sector_erased_with_trailer ) {
507
+ rc = boot_erase_region (fap_sec , sec_off , sz );
508
+ assert (rc == 0 );
509
+ }
479
510
480
- rc = boot_copy_region (state , fap_pri , fap_sec , pri_up_off , sec_off , sz );
511
+ rc = boot_copy_region (state , fap_pri , fap_sec , pri_up_off , sec_off , copy_sz );
481
512
assert (rc == 0 );
482
513
483
514
rc = boot_write_status (state , bs );
@@ -592,7 +623,7 @@ swap_run(struct boot_loader_state *state, struct boot_status *bs,
592
623
idx = last_idx ;
593
624
while (idx > 0 ) {
594
625
if (idx <= (last_idx - bs -> idx + 1 )) {
595
- boot_move_sector_up (idx , sector_sz , state , bs , fap_pri , fap_sec );
626
+ boot_move_sector_up (idx , sector_sz , state , bs , fap_pri );
596
627
}
597
628
idx -- ;
598
629
}
@@ -604,7 +635,7 @@ swap_run(struct boot_loader_state *state, struct boot_status *bs,
604
635
idx = 1 ;
605
636
while (idx <= last_idx ) {
606
637
if (idx >= bs -> idx ) {
607
- boot_swap_sectors (idx , sector_sz , state , bs , fap_pri , fap_sec );
638
+ boot_swap_sectors (idx , last_idx , sector_sz , state , bs , fap_pri , fap_sec );
608
639
}
609
640
idx ++ ;
610
641
}
0 commit comments