@@ -236,26 +236,38 @@ int flash_area_read(const struct flash_area *fa, uint32_t off, void *dst,
236
236
return 0 ;
237
237
}
238
238
239
- static bool aligned_flash_write (size_t dest_addr , const void * src , size_t size )
239
+ static bool aligned_flash_write (size_t dest_addr , const void * src , size_t size , bool erase )
240
240
{
241
241
#ifdef CONFIG_SECURE_FLASH_ENC_ENABLED
242
242
bool flash_encryption_enabled = esp_flash_encryption_enabled ();
243
243
#else
244
244
bool flash_encryption_enabled = false;
245
245
#endif
246
- size_t alignment = flash_encryption_enabled ? 32 : 4 ;
246
+
247
+ /* When flash encryption is enabled, write alignment is 32 bytes, however to avoid
248
+ * inconsistences the region may be erased right before writting, thus the alignment
249
+ * is set to the erase required alignment (FLASH_SECTOR_SIZE).
250
+ * When flash encryption is not enabled, regular write alignment is 4 bytes.
251
+ */
252
+ size_t alignment = flash_encryption_enabled ? (erase ? FLASH_SECTOR_SIZE : 32 ) : 4 ;
247
253
248
254
if (IS_ALIGNED (dest_addr , alignment ) && IS_ALIGNED ((uintptr_t )src , 4 ) && IS_ALIGNED (size , alignment )) {
249
255
/* A single write operation is enough when all parameters are aligned */
250
256
257
+ if (flash_encryption_enabled && erase ) {
258
+ if (bootloader_flash_erase_range (dest_addr , size ) != ESP_OK ) {
259
+ return false;
260
+ }
261
+ }
251
262
return bootloader_flash_write (dest_addr , (void * )src , size , flash_encryption_enabled ) == ESP_OK ;
252
263
}
253
- BOOT_LOG_DBG ("%s: forcing unaligned write dest_addr: 0x%08x src: 0x%08x size: 0x%x" , __func__ , (uint32_t )dest_addr , (uint32_t )src , size );
264
+ BOOT_LOG_DBG ("%s: forcing unaligned write dest_addr: 0x%08x src: 0x%08x size: 0x%x erase: %c" ,
265
+ __func__ , (uint32_t )dest_addr , (uint32_t )src , size , erase ? 't' : 'f' );
254
266
255
267
const uint32_t aligned_addr = ALIGN_DOWN (dest_addr , alignment );
256
268
const uint32_t addr_offset = ALIGN_OFFSET (dest_addr , alignment );
257
269
uint32_t bytes_remaining = size ;
258
- uint8_t write_data [FLASH_BUFFER_SIZE ] __attribute__((aligned (32 ))) = {0 };
270
+ uint8_t write_data [FLASH_SECTOR_SIZE ] __attribute__((aligned (32 ))) = {0 };
259
271
260
272
/* Perform a read operation considering an offset not aligned to 4-byte boundary */
261
273
@@ -264,6 +276,11 @@ static bool aligned_flash_write(size_t dest_addr, const void *src, size_t size)
264
276
return false;
265
277
}
266
278
279
+ if (flash_encryption_enabled && erase ) {
280
+ if (bootloader_flash_erase_range (aligned_addr , ALIGN_UP (bytes , FLASH_SECTOR_SIZE )) != ESP_OK ) {
281
+ return false;
282
+ }
283
+ }
267
284
uint32_t bytes_written = bytes - addr_offset ;
268
285
memcpy (& write_data [addr_offset ], src , bytes_written );
269
286
@@ -283,6 +300,12 @@ static bool aligned_flash_write(size_t dest_addr, const void *src, size_t size)
283
300
return false;
284
301
}
285
302
303
+ if (flash_encryption_enabled && erase ) {
304
+ if (bootloader_flash_erase_range (aligned_addr + offset , ALIGN_UP (bytes , FLASH_SECTOR_SIZE )) != ESP_OK ) {
305
+ return false;
306
+ }
307
+ }
308
+
286
309
memcpy (write_data , & ((uint8_t * )src )[bytes_written ], bytes );
287
310
288
311
if (bootloader_flash_write (aligned_addr + offset , write_data , ALIGN_UP (bytes , alignment ), flash_encryption_enabled ) != ESP_OK ) {
@@ -300,7 +323,7 @@ static bool aligned_flash_write(size_t dest_addr, const void *src, size_t size)
300
323
static bool aligned_flash_erase (size_t addr , size_t size )
301
324
{
302
325
if (IS_ALIGNED (addr , FLASH_SECTOR_SIZE ) && IS_ALIGNED (size , FLASH_SECTOR_SIZE )) {
303
- /* A single write operation is enough when all parameters are aligned */
326
+ /* A single erase operation is enough when all parameters are aligned */
304
327
305
328
return bootloader_flash_erase_range (addr , size ) == ESP_OK ;
306
329
}
@@ -328,13 +351,13 @@ static bool aligned_flash_erase(size_t addr, size_t size)
328
351
329
352
/* Write first part of non-erased data */
330
353
if (addr_offset > 0 ) {
331
- if (!aligned_flash_write (aligned_addr , write_data , addr_offset )) {
354
+ if (!aligned_flash_write (aligned_addr , write_data , addr_offset , false )) {
332
355
return false;
333
356
}
334
357
}
335
358
336
359
if (bytes < sizeof (write_data )) {
337
- if (!aligned_flash_write (aligned_addr + bytes , write_data + bytes , sizeof (write_data ) - bytes )) {
360
+ if (!aligned_flash_write (aligned_addr + bytes , write_data + bytes , sizeof (write_data ) - bytes , false )) {
338
361
return false;
339
362
}
340
363
}
@@ -356,7 +379,7 @@ static bool aligned_flash_erase(size_t addr, size_t size)
356
379
}
357
380
358
381
if (bytes < sizeof (write_data )) {
359
- if (!aligned_flash_write (aligned_addr + offset + bytes , write_data + bytes , sizeof (write_data ) - bytes )) {
382
+ if (!aligned_flash_write (aligned_addr + offset + bytes , write_data + bytes , sizeof (write_data ) - bytes , false )) {
360
383
return false;
361
384
}
362
385
}
@@ -383,9 +406,19 @@ int flash_area_write(const struct flash_area *fa, uint32_t off, const void *src,
383
406
}
384
407
385
408
const uint32_t start_addr = fa -> fa_off + off ;
386
- BOOT_LOG_DBG ("%s: Addr: 0x%08x Length: %d" , __func__ , (int )start_addr , (int )len );
409
+ bool erase = false;
410
+ BOOT_LOG_DBG ("%s: Addr: 0x%08x Length: %d (0x%x)" , __func__ , (int )start_addr , (int )len , (int )len );
387
411
388
- if (!aligned_flash_write (start_addr , src , len )) {
412
+ #ifdef CONFIG_SECURE_FLASH_ENC_ENABLED
413
+ if (esp_flash_encryption_enabled ()) {
414
+ /* Ensuring flash region has been erased before writing in order to
415
+ * avoid inconsistences when hardware flash encryption is enabled.
416
+ */
417
+ erase = true;
418
+ }
419
+ #endif
420
+
421
+ if (!aligned_flash_write (start_addr , src , len , erase )) {
389
422
BOOT_LOG_ERR ("%s: Flash write failed" , __func__ );
390
423
return -1 ;
391
424
}
@@ -402,7 +435,7 @@ int flash_area_erase(const struct flash_area *fa, uint32_t off, uint32_t len)
402
435
}
403
436
404
437
const uint32_t start_addr = fa -> fa_off + off ;
405
- BOOT_LOG_DBG ("%s: Addr: 0x%08x Length: %d" , __func__ , (int )start_addr , (int )len );
438
+ BOOT_LOG_DBG ("%s: Addr: 0x%08x Length: %d (0x%x) " , __func__ , (int )start_addr , ( int ) len , (int )len );
406
439
407
440
if (!aligned_flash_erase (start_addr , len )) {
408
441
BOOT_LOG_ERR ("%s: Flash erase failed" , __func__ );
@@ -411,7 +444,38 @@ int flash_area_erase(const struct flash_area *fa, uint32_t off, uint32_t len)
411
444
412
445
flush_cache (start_addr , len );
413
446
414
- #if VALIDATE_PROGRAM_OP
447
+ #ifdef CONFIG_SECURE_FLASH_ENC_ENABLED
448
+ uint8_t write_data [FLASH_BUFFER_SIZE ];
449
+ memset (write_data , flash_area_erased_val (fa ), sizeof (write_data ));
450
+ uint32_t bytes_remaining = len ;
451
+ uint32_t offset = start_addr ;
452
+
453
+ uint32_t bytes_written = MIN (sizeof (write_data ), len );
454
+ if (esp_flash_encryption_enabled ()) {
455
+ /* When hardware flash encryption is enabled, force expected erased
456
+ * value (0xFF) into flash when erasing a region.
457
+ *
458
+ * This is handled on this implementation because MCUboot's state
459
+ * machine relies on erased valued data (0xFF) readed from a
460
+ * previously erased region that was not written yet, however when
461
+ * hardware flash encryption is enabled, the flash read always
462
+ * decrypts whats being read from flash, thus a region that was
463
+ * erased would not be read as what MCUboot expected (0xFF).
464
+ */
465
+ while (bytes_remaining != 0 ) {
466
+ if (!aligned_flash_write (offset , write_data , bytes_written , false)) {
467
+ BOOT_LOG_ERR ("%s: Flash erase failed" , __func__ );
468
+ return -1 ;
469
+ }
470
+ offset += bytes_written ;
471
+ bytes_remaining -= bytes_written ;
472
+ }
473
+ }
474
+
475
+ flush_cache (start_addr , len );
476
+ #endif
477
+
478
+ #if VALIDATE_PROGRAM_OP && !defined(CONFIG_SECURE_FLASH_ENC_ENABLED )
415
479
for (size_t i = 0 ; i < len ; i ++ ) {
416
480
uint8_t * val = (void * )(start_addr + i );
417
481
if (* val != 0xff ) {
0 commit comments