@@ -257,65 +257,66 @@ static bool aligned_flash_write(size_t dest_addr, const void *src, size_t size,
257257
258258 if (flash_encryption_enabled && erase ) {
259259 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 );
260261 return false;
261262 }
263+ flush_cache (dest_addr , size );
262264 }
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 */
274265
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 );
282271 return false;
283272 }
284273 }
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' );
291276
292- bytes_remaining -= bytes_written ;
277+ uint8_t write_aux_buf [ FLASH_SECTOR_SIZE ] __attribute__(( aligned ( 32 ))) = { 0 } ;
293278
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 ;
295282
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 );
297287
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 );
301292 return false;
302293 }
303294
295+ /* Erase if needed */
304296 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 );
306300 return false;
307301 }
302+ flush_cache (aligned_curr_addr , ALIGN_UP (chunk_len , FLASH_SECTOR_SIZE ));
308303 }
309304
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 );
311307
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 );
313313 return false;
314314 }
315+ flush_cache (aligned_curr_addr , ALIGN_UP (chunk_len , alignment ));
315316
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 ;
319320 }
320321
321322 return true;
@@ -326,68 +327,82 @@ static bool aligned_flash_erase(size_t addr, size_t size)
326327 if (IS_ALIGNED (addr , FLASH_SECTOR_SIZE ) && IS_ALIGNED (size , FLASH_SECTOR_SIZE )) {
327328 /* A single erase operation is enough when all parameters are aligned */
328329
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 );
362335 return false;
363336 }
364337 }
365338
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+ }
369359
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 ;
371365
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 );
377369
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+ }
381384
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 );
384400 return false;
385401 }
386- }
402+ flush_cache ( current_addr , contiguous_size );
387403
388- offset += bytes ;
389- bytes_written += bytes ;
390- bytes_remaining -= bytes ;
404+ current_addr += contiguous_size ;
405+ }
391406 }
392407
393408 return true;
@@ -424,8 +439,6 @@ int flash_area_write(const struct flash_area *fa, uint32_t off, const void *src,
424439 return -1 ;
425440 }
426441
427- flush_cache (start_addr , len );
428-
429442 return 0 ;
430443}
431444
@@ -438,13 +451,11 @@ int flash_area_erase(const struct flash_area *fa, uint32_t off, uint32_t len)
438451 const uint32_t start_addr = fa -> fa_off + off ;
439452 BOOT_LOG_DBG ("%s: Addr: 0x%08x Length: %d (0x%x)" , __func__ , (int )start_addr , (int )len , (int )len );
440453
441- if (!aligned_flash_erase (start_addr , len )) {
454+ if (!aligned_flash_erase (start_addr , len )) {
442455 BOOT_LOG_ERR ("%s: Flash erase failed" , __func__ );
443456 return -1 ;
444457 }
445458
446- flush_cache (start_addr , len );
447-
448459#ifdef CONFIG_SECURE_FLASH_ENC_ENABLED
449460 uint8_t write_data [FLASH_BUFFER_SIZE ];
450461 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)
472483 bytes_remaining -= bytes_written ;
473484 }
474485 }
475-
476- flush_cache (start_addr , len );
477486#endif
478487
479488#if VALIDATE_PROGRAM_OP && !defined(CONFIG_SECURE_FLASH_ENC_ENABLED )
0 commit comments