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