@@ -1233,20 +1233,100 @@ boot_validated_swap_type(struct boot_loader_state *state,
1233
1233
* Erases a region of device that requires erase prior to write; does
1234
1234
* nothing on devices without erase.
1235
1235
*
1236
- * @param fap The flash_area containing the region to erase.
1236
+ * @param fa The flash_area containing the region to erase.
1237
1237
* @param off The offset within the flash area to start the
1238
1238
* 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.
1240
1243
*
1241
1244
* @return 0 on success; nonzero on failure.
1242
1245
*/
1243
1246
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 )
1245
1248
{
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
+ }
1248
1326
}
1249
- return 0 ;
1327
+
1328
+ end :
1329
+ return rc ;
1250
1330
}
1251
1331
1252
1332
/**
@@ -1259,36 +1339,70 @@ boot_erase_region(const struct flash_area *fap, uint32_t off, uint32_t sz)
1259
1339
* @param off The offset within the flash area to start the
1260
1340
* erase.
1261
1341
* @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.
1262
1345
*
1263
1346
* @return 0 on success; nonzero on failure.
1264
1347
*/
1265
1348
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 )
1267
1350
{
1268
- int ret = 0 ;
1351
+ int rc = 0 ;
1269
1352
1270
1353
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 ;
1272
1358
}
1273
1359
1274
1360
if (device_requires_erase (fa )) {
1275
- return flash_area_erase (fa , off , size );
1361
+ rc = boot_erase_region (fa , off , size , backwards );
1276
1362
} else {
1277
1363
uint8_t buf [BOOT_MAX_ALIGN ];
1278
- size_t size_done = 0 ;
1279
1364
const size_t write_block = flash_area_align (fa );
1365
+ uint32_t end_offset ;
1280
1366
1281
1367
memset (buf , flash_area_erased_val (fa ), sizeof (buf ));
1282
1368
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 ) {
1286
1381
break ;
1287
1382
}
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
+ }
1289
1401
}
1290
1402
}
1291
- return ret ;
1403
+
1404
+ done :
1405
+ return rc ;
1292
1406
}
1293
1407
1294
1408
/**
@@ -1304,90 +1418,6 @@ boot_scramble_region(const struct flash_area *fa, uint32_t off, uint32_t size)
1304
1418
*
1305
1419
* @return 0 on success; nonzero on failure.
1306
1420
*/
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
- }
1391
1421
1392
1422
/**
1393
1423
* Remove enough data from slot to mark is as unused
@@ -1412,7 +1442,7 @@ boot_scramble_slot(const struct flash_area *fa, int slot)
1412
1442
/* Without minimal entire area needs to be scrambled */
1413
1443
#if !defined(MCUBOOT_MINIMAL_SCRAMBLE )
1414
1444
size = flash_area_get_size (fa );
1415
- ret = boot_scramble_region (fa , 0 , size );
1445
+ ret = boot_scramble_region (fa , 0 , size , false );
1416
1446
#else
1417
1447
size_t off = 0 ;
1418
1448
@@ -1421,7 +1451,7 @@ boot_scramble_slot(const struct flash_area *fa, int slot)
1421
1451
return ret ;
1422
1452
}
1423
1453
1424
- ret = boot_scramble_region (fa , off , size );
1454
+ ret = boot_scramble_region (fa , off , size , false );
1425
1455
if (ret < 0 ) {
1426
1456
return ret ;
1427
1457
}
@@ -1431,7 +1461,7 @@ boot_scramble_slot(const struct flash_area *fa, int slot)
1431
1461
return ret ;
1432
1462
}
1433
1463
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 );
1435
1465
#endif
1436
1466
return ret ;
1437
1467
}
@@ -1663,7 +1693,7 @@ boot_copy_image(struct boot_loader_state *state, struct boot_status *bs)
1663
1693
sect_count = boot_img_num_sectors (state , BOOT_PRIMARY_SLOT );
1664
1694
for (sect = 0 , size = 0 ; sect < sect_count ; sect ++ ) {
1665
1695
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 );
1667
1697
assert (rc == 0 );
1668
1698
1669
1699
#if defined(MCUBOOT_OVERWRITE_ONLY_FAST )
@@ -1687,7 +1717,7 @@ boot_copy_image(struct boot_loader_state *state, struct boot_status *bs)
1687
1717
sector -- ;
1688
1718
} while (sz < trailer_sz );
1689
1719
1690
- rc = boot_erase_region (fap_primary_slot , off , sz );
1720
+ rc = boot_erase_region (fap_primary_slot , off , sz , false );
1691
1721
assert (rc == 0 );
1692
1722
#endif
1693
1723
@@ -1759,7 +1789,7 @@ boot_copy_image(struct boot_loader_state *state, struct boot_status *bs)
1759
1789
BOOT_LOG_DBG ("erasing secondary header" );
1760
1790
rc = boot_erase_region (fap_secondary_slot ,
1761
1791
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 );
1763
1793
assert (rc == 0 );
1764
1794
#endif
1765
1795
@@ -1769,7 +1799,7 @@ boot_copy_image(struct boot_loader_state *state, struct boot_status *bs)
1769
1799
boot_img_sector_off (state , BOOT_SECONDARY_SLOT ,
1770
1800
last_sector ),
1771
1801
boot_img_sector_size (state , BOOT_SECONDARY_SLOT ,
1772
- last_sector ));
1802
+ last_sector ), false );
1773
1803
assert (rc == 0 );
1774
1804
1775
1805
/* TODO: Perhaps verify the primary slot's signature again? */
@@ -2937,9 +2967,8 @@ boot_select_or_erase(struct boot_loader_state *state)
2937
2967
*/
2938
2968
BOOT_LOG_DBG ("Erasing faulty image in the %s slot." ,
2939
2969
(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 );
2941
2971
assert (rc == 0 );
2942
-
2943
2972
rc = -1 ;
2944
2973
} else {
2945
2974
if (active_swap_state -> copy_done != BOOT_FLAG_SET ) {
0 commit comments