Skip to content

Commit 5223612

Browse files
committed
boot: bootutil: Refactor erase functionality to fix watchdog feeding
Refactors the erase functionality in bootutil so that it can be used alongside feeding the watchdog. This has also optimised some functions out. Signed-off-by: Jamie McCrae <[email protected]>
1 parent f6e8e88 commit 5223612

File tree

9 files changed

+164
-131
lines changed

9 files changed

+164
-131
lines changed

boot/boot_serial/src/boot_serial.c

+2-2
Original file line numberDiff line numberDiff line change
@@ -875,7 +875,7 @@ static off_t erase_range(const struct flash_area *fap, off_t start, off_t end)
875875
BOOT_LOG_DBG("Erasing range 0x%jx:0x%jx", (intmax_t)start,
876876
(intmax_t)(start + size - 1));
877877

878-
rc = boot_erase_region(fap, start, size);
878+
rc = boot_erase_region(fap, start, size, false);
879879
if (rc != 0) {
880880
BOOT_LOG_ERR("Error %d while erasing range", rc);
881881
return -EINVAL;
@@ -1019,7 +1019,7 @@ bs_upload(char *buf, int len)
10191019
/* Non-progressive erase erases entire image slot when first chunk of
10201020
* an image is received.
10211021
*/
1022-
rc = boot_erase_region(fap, 0, area_size);
1022+
rc = boot_erase_region(fap, 0, area_size, false);
10231023
if (rc) {
10241024
goto out_invalid_data;
10251025
}

boot/boot_serial/src/boot_serial_encryption.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -187,7 +187,7 @@ decrypt_region_inplace(struct boot_loader_state *state,
187187
(off + bytes_copied + idx) - hdr->ih_hdr_size, blk_sz,
188188
blk_off, &buf[idx]);
189189
}
190-
rc = boot_erase_region(fap, off + bytes_copied, chunk_sz);
190+
rc = boot_erase_region(fap, off + bytes_copied, chunk_sz, false);
191191
if (rc != 0) {
192192
return BOOT_EFLASH;
193193
}

boot/bootutil/src/bootutil_misc.c

+92-6
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
* Copyright (c) 2017-2019 Linaro LTD
55
* Copyright (c) 2016-2019 JUUL Labs
66
* Copyright (c) 2019-2020 Arm Limited
7+
* Copyright (c) 2025 Nordic Semiconductor ASA
78
*
89
* Original license:
910
*
@@ -562,18 +563,103 @@ boot_read_image_size(struct boot_loader_state *state, int slot, uint32_t *size)
562563
* Erases a region of device that requires erase prior to write; does
563564
* nothing on devices without erase.
564565
*
565-
* @param fap The flash_area containing the region to erase.
566+
* @param fa The flash_area containing the region to erase.
566567
* @param off The offset within the flash area to start the
567568
* 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.
569573
*
570574
* @return 0 on success; nonzero on failure.
571575
*/
572576
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)
574578
{
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, &sector);
591+
592+
if (rc < 0) {
593+
goto end;
594+
}
595+
596+
end_offset = flash_sector_get_off(&sector);
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), &sector);
605+
606+
if (rc < 0) {
607+
goto end;
608+
}
609+
610+
end_offset = flash_sector_get_off(&sector);
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, &sector);
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(&sector);
626+
csize = flash_sector_get_size(&sector);
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+
}
577661
}
578-
return 0;
662+
663+
end:
664+
return rc;
579665
}

boot/bootutil/src/bootutil_priv.h

+2-4
Original file line numberDiff line numberDiff line change
@@ -346,11 +346,9 @@ int boot_copy_region(struct boot_loader_state *state,
346346
/* Prepare for write device that requires erase prior to write. This will
347347
* do nothing on devices without erase requirement.
348348
*/
349-
int boot_erase_region(const struct flash_area *fap, uint32_t off, uint32_t sz);
349+
int boot_erase_region(const struct flash_area *fap, uint32_t off, uint32_t sz, bool backwards);
350350
/* Similar to boot_erase_region but will always remove data */
351-
int boot_scramble_region(const struct flash_area *fap, uint32_t off, uint32_t sz);
352-
/* Similar to boot_scramble_region but works backwards */
353-
int boot_scramble_region_backwards(const struct flash_area *fap, uint32_t off, uint32_t sz);
351+
int boot_scramble_region(const struct flash_area *fap, uint32_t off, uint32_t sz, bool backwards);
354352
/* Makes slot unbootable, either by scrambling header magic, header sector
355353
* or entire slot, depending on settings.
356354
* Note: slot is passed here becuase at this point there is no function

0 commit comments

Comments
 (0)