|
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