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