|
4 | 4 | * Copyright (c) 2017-2019 Linaro LTD
|
5 | 5 | * Copyright (c) 2016-2019 JUUL Labs
|
6 | 6 | * Copyright (c) 2019-2020 Arm Limited
|
| 7 | + * Copyright (c) 2025 Nordic Semiconductor ASA |
7 | 8 | *
|
8 | 9 | * Original license:
|
9 | 10 | *
|
@@ -562,18 +563,103 @@ boot_read_image_size(struct boot_loader_state *state, int slot, uint32_t *size)
|
562 | 563 | * Erases a region of device that requires erase prior to write; does
|
563 | 564 | * nothing on devices without erase.
|
564 | 565 | *
|
565 |
| - * @param fap The flash_area containing the region to erase. |
| 566 | + * @param fa The flash_area containing the region to erase. |
566 | 567 | * @param off The offset within the flash area to start the
|
567 | 568 | * erase.
|
568 |
| - * @param sz The number of bytes to erase. |
| 569 | + * @param size The number of bytes to erase. |
| 570 | + * @param backwards If set to true will erase from end to start |
| 571 | + * addresses, otherwise erases from start to end |
| 572 | + * addresses. |
569 | 573 | *
|
570 | 574 | * @return 0 on success; nonzero on failure.
|
571 | 575 | */
|
572 | 576 | int
|
573 |
| -boot_erase_region(const struct flash_area *fap, uint32_t off, uint32_t sz) |
| 577 | +boot_erase_region(const struct flash_area *fa, uint32_t off, uint32_t size, bool backwards) |
574 | 578 | {
|
575 |
| - if (device_requires_erase(fap)) { |
576 |
| - return flash_area_erase(fap, off, sz); |
| 579 | + int rc = 0; |
| 580 | + |
| 581 | + if (off >= flash_area_get_size(fa) || (flash_area_get_size(fa) - off) < size) { |
| 582 | + rc = -1; |
| 583 | + goto end; |
| 584 | + } else if (device_requires_erase(fa)) { |
| 585 | + uint32_t end_offset = 0; |
| 586 | + struct flash_sector sector; |
| 587 | + |
| 588 | + if (backwards) { |
| 589 | + /* Get the lowest page offset first */ |
| 590 | + rc = flash_area_get_sector(fa, off, §or); |
| 591 | + |
| 592 | + if (rc < 0) { |
| 593 | + goto end; |
| 594 | + } |
| 595 | + |
| 596 | + end_offset = flash_sector_get_off(§or); |
| 597 | + |
| 598 | + /* Set boundary condition, the highest probable offset to erase, within |
| 599 | + * last sector to erase |
| 600 | + */ |
| 601 | + off += size - 1; |
| 602 | + } else { |
| 603 | + /* Get the highest page offset first */ |
| 604 | + rc = flash_area_get_sector(fa, (off + size - 1), §or); |
| 605 | + |
| 606 | + if (rc < 0) { |
| 607 | + goto end; |
| 608 | + } |
| 609 | + |
| 610 | + end_offset = flash_sector_get_off(§or); |
| 611 | + } |
| 612 | + |
| 613 | + while (true) { |
| 614 | + /* Size to read in this iteration */ |
| 615 | + size_t csize; |
| 616 | + |
| 617 | + /* Get current sector and, also, correct offset */ |
| 618 | + rc = flash_area_get_sector(fa, off, §or); |
| 619 | + |
| 620 | + if (rc < 0) { |
| 621 | + goto end; |
| 622 | + } |
| 623 | + |
| 624 | + /* Corrected offset and size of current sector to erase */ |
| 625 | + off = flash_sector_get_off(§or); |
| 626 | + csize = flash_sector_get_size(§or); |
| 627 | + |
| 628 | + rc = flash_area_erase(fa, off, csize); |
| 629 | + |
| 630 | + if (rc < 0) { |
| 631 | + goto end; |
| 632 | + } |
| 633 | + |
| 634 | + MCUBOOT_WATCHDOG_FEED(); |
| 635 | + |
| 636 | + if (backwards) { |
| 637 | + if (end_offset >= off) { |
| 638 | + /* Reached the first offset in range and already erased it */ |
| 639 | + break; |
| 640 | + } |
| 641 | + |
| 642 | + /* Move down to previous sector, the flash_area_get_sector will |
| 643 | + * correct the value to real page offset |
| 644 | + */ |
| 645 | + off -= 1; |
| 646 | + } else { |
| 647 | + /* Move up to next sector */ |
| 648 | + off += csize; |
| 649 | + |
| 650 | + if (off > end_offset) { |
| 651 | + /* Reached the end offset in range and already erased it */ |
| 652 | + break; |
| 653 | + } |
| 654 | + |
| 655 | + /* Workaround for flash_sector_get_off() being broken in mynewt, hangs with |
| 656 | + * infinite loop if this is not present, should be removed if bug is fixed. |
| 657 | + */ |
| 658 | + off += 1; |
| 659 | + } |
| 660 | + } |
577 | 661 | }
|
578 |
| - return 0; |
| 662 | + |
| 663 | +end: |
| 664 | + return rc; |
579 | 665 | }
|
0 commit comments