Skip to content

Commit 5893f04

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 47d826e commit 5893f04

File tree

8 files changed

+158
-131
lines changed

8 files changed

+158
-131
lines changed

boot/boot_serial/src/boot_serial.c

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

859-
rc = boot_erase_region(fap, start, size);
859+
rc = boot_erase_region(fap, start, size, false);
860860
if (rc != 0) {
861861
BOOT_LOG_ERR("Error %d while erasing range", rc);
862862
return -EINVAL;
@@ -1000,7 +1000,7 @@ bs_upload(char *buf, int len)
10001000
/* Non-progressive erase erases entire image slot when first chunk of
10011001
* an image is received.
10021002
*/
1003-
rc = boot_erase_region(fap, 0, area_size);
1003+
rc = boot_erase_region(fap, 0, area_size, false);
10041004
if (rc) {
10051005
goto out_invalid_data;
10061006
}

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_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

boot/bootutil/src/loader.c

+138-109
Original file line numberDiff line numberDiff line change
@@ -1233,20 +1233,100 @@ boot_validated_swap_type(struct boot_loader_state *state,
12331233
* Erases a region of device that requires erase prior to write; does
12341234
* nothing on devices without erase.
12351235
*
1236-
* @param fap The flash_area containing the region to erase.
1236+
* @param fa The flash_area containing the region to erase.
12371237
* @param off The offset within the flash area to start the
12381238
* erase.
1239-
* @param sz The number of bytes to erase.
1239+
* @param size The number of bytes to erase.
1240+
* @param backwards If set to true will erase from end to start
1241+
* addresses, otherwise erases from start to end
1242+
* addresses.
12401243
*
12411244
* @return 0 on success; nonzero on failure.
12421245
*/
12431246
int
1244-
boot_erase_region(const struct flash_area *fap, uint32_t off, uint32_t sz)
1247+
boot_erase_region(const struct flash_area *fa, uint32_t off, uint32_t size, bool backwards)
12451248
{
1246-
if (device_requires_erase(fap)) {
1247-
return flash_area_erase(fap, off, sz);
1249+
int rc = 0;
1250+
1251+
if (device_requires_erase(fa)) {
1252+
// return flash_area_erase(fap, off, sz);
1253+
uint32_t end_offset = 0;
1254+
struct flash_sector sector;
1255+
1256+
if (backwards) {
1257+
/* Get the lowest erased page offset first */
1258+
rc = flash_area_get_sector(fa, off, &sector);
1259+
1260+
if (rc < 0) {
1261+
goto end;
1262+
}
1263+
1264+
end_offset = flash_sector_get_off(&sector);
1265+
1266+
/* Set boundary condition, the highest probable offset to erase, within
1267+
* last sector to erase
1268+
*/
1269+
off += size - 1;
1270+
} else {
1271+
/* Get the lowest erased page offset first */
1272+
rc = flash_area_get_sector(fa, (off + size - 1), &sector);
1273+
1274+
if (rc < 0) {
1275+
goto end;
1276+
}
1277+
1278+
end_offset = flash_sector_get_off(&sector);
1279+
}
1280+
1281+
while (true) {
1282+
/* Size to read in this iteration */
1283+
size_t csize;
1284+
1285+
/* Get current sector and, also, correct offset */
1286+
rc = flash_area_get_sector(fa, off, &sector);
1287+
1288+
if (rc < 0) {
1289+
goto end;
1290+
}
1291+
1292+
/* Corrected offset and size of current sector to erase */
1293+
off = flash_sector_get_off(&sector);
1294+
csize = flash_sector_get_size(&sector);
1295+
1296+
rc = flash_area_erase(fa, off, csize);
1297+
1298+
if (rc < 0) {
1299+
goto end;
1300+
}
1301+
1302+
MCUBOOT_WATCHDOG_FEED();
1303+
1304+
if (backwards) {
1305+
if (end_offset >= off) {
1306+
/* Reached the first offset in range and already erased it */
1307+
break;
1308+
}
1309+
1310+
/* Move down to previous sector, the flash_area_get_sector will
1311+
* correct the value to real page offset
1312+
*/
1313+
off -= 1;
1314+
} else {
1315+
/* Move down to previous sector, the flash_area_get_sector will
1316+
* correct the value to real page offset
1317+
*/
1318+
off += csize;
1319+
1320+
if (off > end_offset) {
1321+
/* Reached the first offset in range and already erased it */
1322+
break;
1323+
}
1324+
}
1325+
}
12481326
}
1249-
return 0;
1327+
1328+
end:
1329+
return rc;
12501330
}
12511331

12521332
/**
@@ -1259,36 +1339,70 @@ boot_erase_region(const struct flash_area *fap, uint32_t off, uint32_t sz)
12591339
* @param off The offset within the flash area to start the
12601340
* erase.
12611341
* @param size The number of bytes to erase.
1342+
* @param backwards If set to true will erase from end to start
1343+
* addresses, otherwise erases from start to end
1344+
* addresses.
12621345
*
12631346
* @return 0 on success; nonzero on failure.
12641347
*/
12651348
int
1266-
boot_scramble_region(const struct flash_area *fa, uint32_t off, uint32_t size)
1349+
boot_scramble_region(const struct flash_area *fa, uint32_t off, uint32_t size, bool backwards)
12671350
{
1268-
int ret = 0;
1351+
int rc = 0;
12691352

12701353
if (size == 0) {
1271-
return 0;
1354+
goto done;
1355+
} else if (off >= flash_area_get_size(fa) || (flash_area_get_size(fa) - off) < size) {
1356+
rc = -1;
1357+
goto done;
12721358
}
12731359

12741360
if (device_requires_erase(fa)) {
1275-
return flash_area_erase(fa, off, size);
1361+
rc = boot_erase_region(fa, off, size, backwards);
12761362
} else {
12771363
uint8_t buf[BOOT_MAX_ALIGN];
1278-
size_t size_done = 0;
12791364
const size_t write_block = flash_area_align(fa);
1365+
uint32_t end_offset;
12801366

12811367
memset(buf, flash_area_erased_val(fa), sizeof(buf));
12821368

1283-
while (size_done < size) {
1284-
ret = flash_area_write(fa, size_done + off, buf, write_block);
1285-
if (ret != 0) {
1369+
if (backwards) {
1370+
end_offset = ALIGN_DOWN(off, write_block);
1371+
/* Starting at the last write block in range */
1372+
off += size - write_block;
1373+
} else {
1374+
end_offset = ALIGN_DOWN((off + size), write_block);
1375+
}
1376+
1377+
while (true) {
1378+
/* Write over the area to scramble data that is there */
1379+
rc = flash_area_write(fa, off, buf, write_block);
1380+
if (rc != 0) {
12861381
break;
12871382
}
1288-
size_done += write_block;
1383+
1384+
MCUBOOT_WATCHDOG_FEED();
1385+
1386+
if (backwards) {
1387+
if (end_offset >= off) {
1388+
/* Reached the first offset in range and already scrambled it */
1389+
break;
1390+
}
1391+
1392+
off -= write_block;
1393+
} else {
1394+
if (end_offset < off) {
1395+
/* Reached the first offset in range and already scrambled it */
1396+
break;
1397+
}
1398+
1399+
off += write_block;
1400+
}
12891401
}
12901402
}
1291-
return ret;
1403+
1404+
done:
1405+
return rc;
12921406
}
12931407

12941408
/**
@@ -1304,90 +1418,6 @@ boot_scramble_region(const struct flash_area *fa, uint32_t off, uint32_t size)
13041418
*
13051419
* @return 0 on success; nonzero on failure.
13061420
*/
1307-
int boot_scramble_region_backwards(const struct flash_area *fa, uint32_t off, uint32_t size)
1308-
{
1309-
int ret = 0;
1310-
uint32_t first_offset = 0;
1311-
1312-
if (size == 0) {
1313-
return 0;
1314-
}
1315-
1316-
if (off >= flash_area_get_size(fa) || (flash_area_get_size(fa) - off) < size) {
1317-
return -1;
1318-
}
1319-
1320-
if (device_requires_erase(fa)) {
1321-
struct flash_sector sector;
1322-
1323-
/* Get the lowest erased page offset first */
1324-
ret = flash_area_get_sector(fa, off, &sector);
1325-
if (ret < 0) {
1326-
return ret;
1327-
}
1328-
first_offset = flash_sector_get_off(&sector);
1329-
1330-
/* Set boundary condition, the highest probable offset to erase, within
1331-
* last sector to erase
1332-
*/
1333-
off += size - 1;
1334-
1335-
while (true) {
1336-
/* Size to read in this iteration */
1337-
size_t csize;
1338-
1339-
/* Get current sector and, also, correct offset */
1340-
ret = flash_area_get_sector(fa, off, &sector);
1341-
if (ret < 0) {
1342-
return ret;
1343-
}
1344-
1345-
/* Corrected offset and size of current sector to erase */
1346-
off = flash_sector_get_off(&sector);
1347-
csize = flash_sector_get_size(&sector);
1348-
1349-
ret = flash_area_erase(fa, off, csize);
1350-
if (ret < 0) {
1351-
return ret;
1352-
}
1353-
1354-
if (first_offset >= off) {
1355-
/* Reached the first offsset in range and already erased it */
1356-
break;
1357-
}
1358-
1359-
/* Move down to previous sector, the flash_area_get_sector will
1360-
* correct the value to real page offset
1361-
*/
1362-
off -= 1;
1363-
}
1364-
} else {
1365-
uint8_t buf[BOOT_MAX_ALIGN];
1366-
const size_t write_block = flash_area_align(fa);
1367-
uint32_t first_offset = ALIGN_DOWN(off, write_block);
1368-
1369-
memset(buf, flash_area_erased_val(fa), sizeof(buf));
1370-
1371-
/* Starting at the last write block in range */
1372-
off += size - write_block;
1373-
1374-
while (true) {
1375-
/* Write over the area to scramble data that is there */
1376-
ret = flash_area_write(fa, off, buf, write_block);
1377-
if (ret != 0) {
1378-
break;
1379-
}
1380-
1381-
if (first_offset >= off) {
1382-
/* Reached the first offset in range and already scrambled it */
1383-
break;
1384-
}
1385-
1386-
off -= write_block;
1387-
}
1388-
}
1389-
return ret;
1390-
}
13911421

13921422
/**
13931423
* Remove enough data from slot to mark is as unused
@@ -1412,7 +1442,7 @@ boot_scramble_slot(const struct flash_area *fa, int slot)
14121442
/* Without minimal entire area needs to be scrambled */
14131443
#if !defined(MCUBOOT_MINIMAL_SCRAMBLE)
14141444
size = flash_area_get_size(fa);
1415-
ret = boot_scramble_region(fa, 0, size);
1445+
ret = boot_scramble_region(fa, 0, size, false);
14161446
#else
14171447
size_t off = 0;
14181448

@@ -1421,7 +1451,7 @@ boot_scramble_slot(const struct flash_area *fa, int slot)
14211451
return ret;
14221452
}
14231453

1424-
ret = boot_scramble_region(fa, off, size);
1454+
ret = boot_scramble_region(fa, off, size, false);
14251455
if (ret < 0) {
14261456
return ret;
14271457
}
@@ -1431,7 +1461,7 @@ boot_scramble_slot(const struct flash_area *fa, int slot)
14311461
return ret;
14321462
}
14331463

1434-
ret = boot_scramble_region_backwards(fa, off, flash_area_get_size(fa) - off);
1464+
ret = boot_scramble_region(fa, off, (flash_area_get_size(fa) - off), true);
14351465
#endif
14361466
return ret;
14371467
}
@@ -1663,7 +1693,7 @@ boot_copy_image(struct boot_loader_state *state, struct boot_status *bs)
16631693
sect_count = boot_img_num_sectors(state, BOOT_PRIMARY_SLOT);
16641694
for (sect = 0, size = 0; sect < sect_count; sect++) {
16651695
this_size = boot_img_sector_size(state, BOOT_PRIMARY_SLOT, sect);
1666-
rc = boot_erase_region(fap_primary_slot, size, this_size);
1696+
rc = boot_erase_region(fap_primary_slot, size, this_size, false);
16671697
assert(rc == 0);
16681698

16691699
#if defined(MCUBOOT_OVERWRITE_ONLY_FAST)
@@ -1687,7 +1717,7 @@ boot_copy_image(struct boot_loader_state *state, struct boot_status *bs)
16871717
sector--;
16881718
} while (sz < trailer_sz);
16891719

1690-
rc = boot_erase_region(fap_primary_slot, off, sz);
1720+
rc = boot_erase_region(fap_primary_slot, off, sz, false);
16911721
assert(rc == 0);
16921722
#endif
16931723

@@ -1759,7 +1789,7 @@ boot_copy_image(struct boot_loader_state *state, struct boot_status *bs)
17591789
BOOT_LOG_DBG("erasing secondary header");
17601790
rc = boot_erase_region(fap_secondary_slot,
17611791
boot_img_sector_off(state, BOOT_SECONDARY_SLOT, 0),
1762-
boot_img_sector_size(state, BOOT_SECONDARY_SLOT, 0));
1792+
boot_img_sector_size(state, BOOT_SECONDARY_SLOT, 0), false);
17631793
assert(rc == 0);
17641794
#endif
17651795

@@ -1769,7 +1799,7 @@ boot_copy_image(struct boot_loader_state *state, struct boot_status *bs)
17691799
boot_img_sector_off(state, BOOT_SECONDARY_SLOT,
17701800
last_sector),
17711801
boot_img_sector_size(state, BOOT_SECONDARY_SLOT,
1772-
last_sector));
1802+
last_sector), false);
17731803
assert(rc == 0);
17741804

17751805
/* TODO: Perhaps verify the primary slot's signature again? */
@@ -2937,9 +2967,8 @@ boot_select_or_erase(struct boot_loader_state *state)
29372967
*/
29382968
BOOT_LOG_DBG("Erasing faulty image in the %s slot.",
29392969
(active_slot == BOOT_PRIMARY_SLOT) ? "primary" : "secondary");
2940-
rc = flash_area_erase(fap, 0, flash_area_get_size(fap));
2970+
rc = boot_scramble_region(fap, off, flash_area_get_size(fap), false);
29412971
assert(rc == 0);
2942-
29432972
rc = -1;
29442973
} else {
29452974
if (active_swap_state->copy_done != BOOT_FLAG_SET) {

0 commit comments

Comments
 (0)