|
4 | 4 | * Copyright (c) 2017-2019 Linaro LTD
|
5 | 5 | * Copyright (c) 2016-2019 JUUL Labs
|
6 | 6 | * Copyright (c) 2019-2021 Arm Limited
|
7 |
| - * Copyright (c) 2020 Nordic Semiconductor ASA |
| 7 | + * Copyright (c) 2020-2023 Nordic Semiconductor ASA |
8 | 8 | *
|
9 | 9 | * Original license:
|
10 | 10 | *
|
@@ -458,6 +458,77 @@ boot_swap_type_multi(int image_index)
|
458 | 458 | return BOOT_SWAP_TYPE_NONE;
|
459 | 459 | }
|
460 | 460 |
|
| 461 | +int |
| 462 | +boot_set_next(const struct flash_area *fa, bool active, bool confirm) |
| 463 | +{ |
| 464 | + struct boot_swap_state slot_state; |
| 465 | + int rc; |
| 466 | + |
| 467 | + if (active) { |
| 468 | + confirm = true; |
| 469 | + } |
| 470 | + |
| 471 | + rc = boot_read_swap_state(fa, &slot_state); |
| 472 | + if (rc != 0) { |
| 473 | + return rc; |
| 474 | + } |
| 475 | + |
| 476 | + switch (slot_state.magic) { |
| 477 | + case BOOT_MAGIC_GOOD: |
| 478 | + /* If non-active then swap already scheduled, else confirm needed.*/ |
| 479 | + |
| 480 | + if (active && slot_state.image_ok == BOOT_FLAG_UNSET) { |
| 481 | + /* Intentionally do not check copy_done flag to be able to |
| 482 | + * confirm a padded image which has been programmed using |
| 483 | + * a programming interface. |
| 484 | + */ |
| 485 | + rc = boot_write_image_ok(fa); |
| 486 | + } |
| 487 | + |
| 488 | + break; |
| 489 | + |
| 490 | + case BOOT_MAGIC_UNSET: |
| 491 | + if (!active) { |
| 492 | + rc = boot_write_magic(fa); |
| 493 | + |
| 494 | + if (rc == 0 && confirm) { |
| 495 | + rc = boot_write_image_ok(fa); |
| 496 | + } |
| 497 | + |
| 498 | + if (rc == 0) { |
| 499 | + uint8_t swap_type; |
| 500 | + |
| 501 | + if (confirm) { |
| 502 | + swap_type = BOOT_SWAP_TYPE_PERM; |
| 503 | + } else { |
| 504 | + swap_type = BOOT_SWAP_TYPE_TEST; |
| 505 | + } |
| 506 | + rc = boot_write_swap_info(fa, swap_type, 0); |
| 507 | + } |
| 508 | + } |
| 509 | + break; |
| 510 | + |
| 511 | + case BOOT_MAGIC_BAD: |
| 512 | + if (active) { |
| 513 | + rc = BOOT_EBADVECT; |
| 514 | + } else { |
| 515 | + /* The image slot is corrupt. There is no way to recover, so erase the |
| 516 | + * slot to allow future upgrades. |
| 517 | + */ |
| 518 | + flash_area_erase(fa, 0, flash_area_get_size(fa)); |
| 519 | + rc = BOOT_EBADIMAGE; |
| 520 | + } |
| 521 | + break; |
| 522 | + |
| 523 | + default: |
| 524 | + /* Something is not OK, this should never happen */ |
| 525 | + assert(0); |
| 526 | + rc = BOOT_EBADIMAGE; |
| 527 | + } |
| 528 | + |
| 529 | + return rc; |
| 530 | +} |
| 531 | + |
461 | 532 | /*
|
462 | 533 | * This function is not used by the bootloader itself, but its required API
|
463 | 534 | * by external tooling like mcumgr.
|
@@ -486,57 +557,15 @@ int
|
486 | 557 | boot_set_pending_multi(int image_index, int permanent)
|
487 | 558 | {
|
488 | 559 | const struct flash_area *fap;
|
489 |
| - struct boot_swap_state state_secondary_slot; |
490 |
| - uint8_t swap_type; |
491 | 560 | int rc;
|
492 | 561 |
|
493 | 562 | rc = flash_area_open(FLASH_AREA_IMAGE_SECONDARY(image_index), &fap);
|
494 | 563 | if (rc != 0) {
|
495 | 564 | return BOOT_EFLASH;
|
496 | 565 | }
|
497 | 566 |
|
498 |
| - rc = boot_read_swap_state(fap, &state_secondary_slot); |
499 |
| - if (rc != 0) { |
500 |
| - goto done; |
501 |
| - } |
502 |
| - |
503 |
| - switch (state_secondary_slot.magic) { |
504 |
| - case BOOT_MAGIC_GOOD: |
505 |
| - /* Swap already scheduled. */ |
506 |
| - break; |
507 |
| - |
508 |
| - case BOOT_MAGIC_UNSET: |
509 |
| - rc = boot_write_magic(fap); |
510 |
| - |
511 |
| - if (rc == 0 && permanent) { |
512 |
| - rc = boot_write_image_ok(fap); |
513 |
| - } |
| 567 | + rc = boot_set_next(fap, false, !(permanent == 0)); |
514 | 568 |
|
515 |
| - if (rc == 0) { |
516 |
| - if (permanent) { |
517 |
| - swap_type = BOOT_SWAP_TYPE_PERM; |
518 |
| - } else { |
519 |
| - swap_type = BOOT_SWAP_TYPE_TEST; |
520 |
| - } |
521 |
| - rc = boot_write_swap_info(fap, swap_type, 0); |
522 |
| - } |
523 |
| - |
524 |
| - break; |
525 |
| - |
526 |
| - case BOOT_MAGIC_BAD: |
527 |
| - /* The image slot is corrupt. There is no way to recover, so erase the |
528 |
| - * slot to allow future upgrades. |
529 |
| - */ |
530 |
| - flash_area_erase(fap, 0, flash_area_get_size(fap)); |
531 |
| - rc = BOOT_EBADIMAGE; |
532 |
| - break; |
533 |
| - |
534 |
| - default: |
535 |
| - assert(0); |
536 |
| - rc = BOOT_EBADIMAGE; |
537 |
| - } |
538 |
| - |
539 |
| -done: |
540 | 569 | flash_area_close(fap);
|
541 | 570 | return rc;
|
542 | 571 | }
|
@@ -573,47 +602,15 @@ int
|
573 | 602 | boot_set_confirmed_multi(int image_index)
|
574 | 603 | {
|
575 | 604 | const struct flash_area *fap = NULL;
|
576 |
| - struct boot_swap_state state_primary_slot; |
577 | 605 | int rc;
|
578 | 606 |
|
579 | 607 | rc = flash_area_open(FLASH_AREA_IMAGE_PRIMARY(image_index), &fap);
|
580 | 608 | if (rc != 0) {
|
581 | 609 | return BOOT_EFLASH;
|
582 | 610 | }
|
583 | 611 |
|
584 |
| - rc = boot_read_swap_state(fap, &state_primary_slot); |
585 |
| - if (rc != 0) { |
586 |
| - goto done; |
587 |
| - } |
588 |
| - |
589 |
| - switch (state_primary_slot.magic) { |
590 |
| - case BOOT_MAGIC_GOOD: |
591 |
| - /* Confirm needed; proceed. */ |
592 |
| - break; |
593 |
| - |
594 |
| - case BOOT_MAGIC_UNSET: |
595 |
| - /* Already confirmed. */ |
596 |
| - goto done; |
597 |
| - |
598 |
| - case BOOT_MAGIC_BAD: |
599 |
| - /* Unexpected state. */ |
600 |
| - rc = BOOT_EBADVECT; |
601 |
| - goto done; |
602 |
| - } |
603 |
| - |
604 |
| - /* Intentionally do not check copy_done flag |
605 |
| - * so can confirm a padded image which was programed using a programing |
606 |
| - * interface. |
607 |
| - */ |
608 |
| - |
609 |
| - if (state_primary_slot.image_ok != BOOT_FLAG_UNSET) { |
610 |
| - /* Already confirmed. */ |
611 |
| - goto done; |
612 |
| - } |
613 |
| - |
614 |
| - rc = boot_write_image_ok(fap); |
| 612 | + rc = boot_set_next(fap, true, true); |
615 | 613 |
|
616 |
| -done: |
617 | 614 | flash_area_close(fap);
|
618 | 615 | return rc;
|
619 | 616 | }
|
|
0 commit comments