@@ -257,65 +257,66 @@ static bool aligned_flash_write(size_t dest_addr, const void *src, size_t size,
257
257
258
258
if (flash_encryption_enabled && erase ) {
259
259
if (bootloader_flash_erase_range (dest_addr , size ) != ESP_OK ) {
260
+ BOOT_LOG_ERR ("%s: Flash erase failed at 0x%08x" , __func__ , (uint32_t )dest_addr );
260
261
return false;
261
262
}
263
+ flush_cache (dest_addr , size );
262
264
}
263
- return bootloader_flash_write (dest_addr , (void * )src , size , flash_encryption_enabled ) == ESP_OK ;
264
- }
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' );
267
-
268
- const uint32_t aligned_addr = ALIGN_DOWN (dest_addr , alignment );
269
- const uint32_t addr_offset = ALIGN_OFFSET (dest_addr , alignment );
270
- uint32_t bytes_remaining = size ;
271
- uint8_t write_data [FLASH_SECTOR_SIZE ] __attribute__((aligned (32 ))) = {0 };
272
-
273
- /* Perform a read operation considering an offset not aligned to 4-byte boundary */
274
265
275
- uint32_t bytes = MIN (bytes_remaining + addr_offset , sizeof (write_data ));
276
- if (bootloader_flash_read (aligned_addr , write_data , ALIGN_UP (bytes , alignment ), true) != ESP_OK ) {
277
- return false;
278
- }
279
-
280
- if (flash_encryption_enabled && erase ) {
281
- if (bootloader_flash_erase_range (aligned_addr , ALIGN_UP (bytes , FLASH_SECTOR_SIZE )) != ESP_OK ) {
266
+ if (bootloader_flash_write (dest_addr , (void * )src , size , flash_encryption_enabled ) == ESP_OK ) {
267
+ flush_cache (dest_addr , size );
268
+ return true;
269
+ } else {
270
+ BOOT_LOG_ERR ("%s: Flash write failed at 0x%08x" , __func__ , (uint32_t )dest_addr );
282
271
return false;
283
272
}
284
273
}
285
- uint32_t bytes_written = bytes - addr_offset ;
286
- memcpy (& write_data [addr_offset ], src , bytes_written );
287
-
288
- if (bootloader_flash_write (aligned_addr , write_data , ALIGN_UP (bytes , alignment ), flash_encryption_enabled ) != ESP_OK ) {
289
- return false;
290
- }
274
+ BOOT_LOG_DBG ("%s: forcing unaligned write dest_addr: 0x%08x src: 0x%08x size: 0x%x erase: %c" ,
275
+ __func__ , (uint32_t )dest_addr , (uint32_t )src , size , erase ? 't' : 'f' );
291
276
292
- bytes_remaining -= bytes_written ;
277
+ uint8_t write_aux_buf [ FLASH_SECTOR_SIZE ] __attribute__(( aligned ( 32 ))) = { 0 } ;
293
278
294
- /* Write remaining data to Flash if any */
279
+ size_t write_addr = dest_addr ;
280
+ size_t bytes_remaining = size ;
281
+ size_t src_offset = 0 ;
295
282
296
- uint32_t offset = bytes ;
283
+ while (bytes_remaining > 0 ) {
284
+ size_t aligned_curr_addr = ALIGN_DOWN (write_addr , alignment );
285
+ size_t curr_buf_off = write_addr - aligned_curr_addr ;
286
+ size_t chunk_len = MIN (bytes_remaining , FLASH_SECTOR_SIZE - curr_buf_off );
297
287
298
- while (bytes_remaining != 0 ) {
299
- bytes = MIN (bytes_remaining , sizeof (write_data ));
300
- if (bootloader_flash_read (aligned_addr + offset , write_data , ALIGN_UP (bytes , alignment ), true) != ESP_OK ) {
288
+ /* Read data before modifying */
289
+ if (bootloader_flash_read (aligned_curr_addr , write_aux_buf ,
290
+ ALIGN_UP (chunk_len , alignment ), true) != ESP_OK ) {
291
+ BOOT_LOG_ERR ("%s: Flash read failed at 0x%08x" , __func__ , (uint32_t )aligned_curr_addr );
301
292
return false;
302
293
}
303
294
295
+ /* Erase if needed */
304
296
if (flash_encryption_enabled && erase ) {
305
- if (bootloader_flash_erase_range (aligned_addr + offset , ALIGN_UP (bytes , FLASH_SECTOR_SIZE )) != ESP_OK ) {
297
+ if (bootloader_flash_erase_range (aligned_curr_addr ,
298
+ ALIGN_UP (chunk_len , FLASH_SECTOR_SIZE )) != ESP_OK ) {
299
+ BOOT_LOG_ERR ("%s: Flash erase failed at 0x%08x" , __func__ , (uint32_t )aligned_curr_addr );
306
300
return false;
307
301
}
302
+ flush_cache (aligned_curr_addr , ALIGN_UP (chunk_len , FLASH_SECTOR_SIZE ));
308
303
}
309
304
310
- memcpy (write_data , & ((uint8_t * )src )[bytes_written ], bytes );
305
+ /* Merge data into buffer */
306
+ memcpy (& write_aux_buf [curr_buf_off ], & ((uint8_t * )src )[src_offset ], chunk_len );
311
307
312
- if (bootloader_flash_write (aligned_addr + offset , write_data , ALIGN_UP (bytes , alignment ), flash_encryption_enabled ) != ESP_OK ) {
308
+ /* Write back aligned chunk */
309
+ if (bootloader_flash_write (aligned_curr_addr , write_aux_buf ,
310
+ ALIGN_UP (chunk_len , alignment ),
311
+ flash_encryption_enabled ) != ESP_OK ) {
312
+ BOOT_LOG_ERR ("%s: Flash write failed at 0x%08x" , __func__ , (uint32_t )aligned_curr_addr );
313
313
return false;
314
314
}
315
+ flush_cache (aligned_curr_addr , ALIGN_UP (chunk_len , alignment ));
315
316
316
- offset += bytes ;
317
- bytes_written += bytes ;
318
- bytes_remaining -= bytes ;
317
+ write_addr += chunk_len ;
318
+ src_offset += chunk_len ;
319
+ bytes_remaining -= chunk_len ;
319
320
}
320
321
321
322
return true;
@@ -326,68 +327,82 @@ static bool aligned_flash_erase(size_t addr, size_t size)
326
327
if (IS_ALIGNED (addr , FLASH_SECTOR_SIZE ) && IS_ALIGNED (size , FLASH_SECTOR_SIZE )) {
327
328
/* A single erase operation is enough when all parameters are aligned */
328
329
329
- return bootloader_flash_erase_range (addr , size ) == ESP_OK ;
330
- }
331
- BOOT_LOG_DBG ("%s: forcing unaligned erase on sector Offset: 0x%x Length: 0x%x" ,
332
- __func__ , (int )addr , (int )size );
333
-
334
- const uint32_t aligned_addr = ALIGN_DOWN (addr , FLASH_SECTOR_SIZE );
335
- const uint32_t addr_offset = ALIGN_OFFSET (addr , FLASH_SECTOR_SIZE );
336
- uint32_t bytes_remaining = size ;
337
- uint8_t write_data [FLASH_SECTOR_SIZE ] __attribute__((aligned (32 ))) = {0 };
338
-
339
- /* Perform a read operation considering an offset not aligned */
340
-
341
- uint32_t bytes = MIN (bytes_remaining + addr_offset , sizeof (write_data ));
342
-
343
- if (bootloader_flash_read (aligned_addr , write_data , ALIGN_UP (bytes , FLASH_SECTOR_SIZE ), true) != ESP_OK ) {
344
- return false;
345
- }
346
-
347
- if (bootloader_flash_erase_range (aligned_addr , ALIGN_UP (bytes , FLASH_SECTOR_SIZE )) != ESP_OK ) {
348
- return false;
349
- }
350
-
351
- uint32_t bytes_written = bytes - addr_offset ;
352
-
353
- /* Write first part of non-erased data */
354
- if (addr_offset > 0 ) {
355
- if (!aligned_flash_write (aligned_addr , write_data , addr_offset , false)) {
356
- return false;
357
- }
358
- }
359
-
360
- if (bytes < sizeof (write_data )) {
361
- if (!aligned_flash_write (aligned_addr + bytes , write_data + bytes , sizeof (write_data ) - bytes , false)) {
330
+ if (bootloader_flash_erase_range (addr , size ) == ESP_OK ) {
331
+ flush_cache (addr , size );
332
+ return true;
333
+ } else {
334
+ BOOT_LOG_ERR ("%s: Flash erase failed at 0x%08x" , __func__ , (uint32_t )addr );
362
335
return false;
363
336
}
364
337
}
365
338
366
- bytes_remaining -= bytes_written ;
367
-
368
- /* Write remaining data to Flash if any */
339
+ const size_t sector_size = FLASH_SECTOR_SIZE ;
340
+ const size_t start_addr = ALIGN_DOWN (addr , sector_size );
341
+ const size_t end_addr = ALIGN_UP (addr + size , sector_size );
342
+ const size_t total_len = end_addr - start_addr ;
343
+
344
+ BOOT_LOG_DBG ("%s: forcing unaligned erase on sector Offset: 0x%08x Length: 0x%x total_len: 0x%x" ,
345
+ __func__ , (uint32_t )addr , (int )size , total_len );
346
+
347
+ uint8_t erase_aux_buf [FLASH_SECTOR_SIZE ] __attribute__((aligned (32 ))) = {0 };
348
+ size_t current_addr = start_addr ;
349
+ while (current_addr < end_addr ) {
350
+ bool preserve_head = (addr > current_addr );
351
+ bool preserve_tail = ((addr + size ) < (current_addr + sector_size ));
352
+
353
+ if (preserve_head || preserve_tail ) {
354
+ /* Read full sector before erasing */
355
+ if (bootloader_flash_read (current_addr , erase_aux_buf , sector_size , true) != ESP_OK ) {
356
+ BOOT_LOG_ERR ("%s: Flash read failed at 0x%08x" , __func__ , (uint32_t )current_addr );
357
+ return false;
358
+ }
369
359
370
- uint32_t offset = bytes ;
360
+ /* Calculate the range of the erase: data between erase_start and erase_end
361
+ * will not be written back
362
+ */
363
+ size_t erase_start = (addr > current_addr ) ? (addr - current_addr ) : 0 ;
364
+ size_t erase_end = MIN (current_addr + sector_size , addr + size ) - current_addr ;
371
365
372
- while (bytes_remaining != 0 ) {
373
- bytes = MIN (bytes_remaining , sizeof (write_data ));
374
- if (bootloader_flash_read (aligned_addr + offset , write_data , ALIGN_UP (bytes , FLASH_SECTOR_SIZE ), true) != ESP_OK ) {
375
- return false;
376
- }
366
+ BOOT_LOG_INF ("%s: partial sector erase from: 0x%08x to: 0x%08x Length: 0x%x" ,
367
+ __func__ , (uint32_t )(current_addr + erase_start ),
368
+ (uint32_t )(current_addr + erase_end ), erase_end - erase_start );
377
369
378
- if (bootloader_flash_erase_range (aligned_addr + offset , ALIGN_UP (bytes , FLASH_SECTOR_SIZE )) != ESP_OK ) {
379
- return false;
380
- }
370
+ /* Erase full sector */
371
+ if (bootloader_flash_erase_range (current_addr , sector_size ) != ESP_OK ) {
372
+ BOOT_LOG_ERR ("%s: Flash erase failed at 0x%08x" , __func__ , (uint32_t )current_addr );
373
+ return false;
374
+ }
375
+ flush_cache (current_addr , sector_size );
376
+
377
+ if (preserve_head ) {
378
+ /* Write back preserved head data up to erase_start */
379
+ if (!aligned_flash_write (current_addr , erase_aux_buf , erase_start , false)) {
380
+ BOOT_LOG_ERR ("%s: Flash write failed at 0x%08x" , __func__ , (uint32_t )current_addr );
381
+ return false;
382
+ }
383
+ }
381
384
382
- if (bytes < sizeof (write_data )) {
383
- if (!aligned_flash_write (aligned_addr + offset + bytes , write_data + bytes , sizeof (write_data ) - bytes , false)) {
385
+ if (preserve_tail ) {
386
+ /* Write back preserved tail data from erase_end up to sector end */
387
+ if (!aligned_flash_write (current_addr + erase_end , & erase_aux_buf [erase_end ], sector_size - erase_end , false)) {
388
+ BOOT_LOG_ERR ("%s: Flash write failed at 0x%08x" , __func__ , (uint32_t )current_addr + erase_end );
389
+ return false;
390
+ }
391
+ }
392
+ current_addr += sector_size ;
393
+ } else {
394
+ /* Full sector erase is safe, erase the next consecutive full sectors */
395
+ size_t contiguous_size = ALIGN_DOWN (addr + size , sector_size ) - current_addr ;
396
+ BOOT_LOG_DBG ("%s: sectors erased from: 0x%08x length: 0x%x" ,
397
+ __func__ , (uint32_t )current_addr , contiguous_size );
398
+ if (bootloader_flash_erase_range (current_addr , contiguous_size ) != ESP_OK ) {
399
+ BOOT_LOG_ERR ("%s: Flash erase failed at 0x%08x" , __func__ , (uint32_t )current_addr );
384
400
return false;
385
401
}
386
- }
402
+ flush_cache ( current_addr , contiguous_size );
387
403
388
- offset += bytes ;
389
- bytes_written += bytes ;
390
- bytes_remaining -= bytes ;
404
+ current_addr += contiguous_size ;
405
+ }
391
406
}
392
407
393
408
return true;
@@ -424,8 +439,6 @@ int flash_area_write(const struct flash_area *fa, uint32_t off, const void *src,
424
439
return -1 ;
425
440
}
426
441
427
- flush_cache (start_addr , len );
428
-
429
442
return 0 ;
430
443
}
431
444
@@ -438,13 +451,11 @@ int flash_area_erase(const struct flash_area *fa, uint32_t off, uint32_t len)
438
451
const uint32_t start_addr = fa -> fa_off + off ;
439
452
BOOT_LOG_DBG ("%s: Addr: 0x%08x Length: %d (0x%x)" , __func__ , (int )start_addr , (int )len , (int )len );
440
453
441
- if (!aligned_flash_erase (start_addr , len )) {
454
+ if (!aligned_flash_erase (start_addr , len )) {
442
455
BOOT_LOG_ERR ("%s: Flash erase failed" , __func__ );
443
456
return -1 ;
444
457
}
445
458
446
- flush_cache (start_addr , len );
447
-
448
459
#ifdef CONFIG_SECURE_FLASH_ENC_ENABLED
449
460
uint8_t write_data [FLASH_BUFFER_SIZE ];
450
461
memset (write_data , flash_area_erased_val (fa ), sizeof (write_data ));
@@ -472,8 +483,6 @@ int flash_area_erase(const struct flash_area *fa, uint32_t off, uint32_t len)
472
483
bytes_remaining -= bytes_written ;
473
484
}
474
485
}
475
-
476
- flush_cache (start_addr , len );
477
486
#endif
478
487
479
488
#if VALIDATE_PROGRAM_OP && !defined(CONFIG_SECURE_FLASH_ENC_ENABLED )
0 commit comments