1313
1414#include "sdkconfig.h"
1515#include "esp_err.h"
16+ #include "rom/cache.h"
17+ #include "hal/cache_hal.h"
18+ #include "hal/mmu_hal.h"
1619#include "bootloader_flash_priv.h"
1720#include "esp_flash_encrypt.h"
1821#include "mcuboot_config/mcuboot_config.h"
@@ -148,6 +151,22 @@ void flash_area_close(const struct flash_area *area)
148151
149152}
150153
154+ static void flush_cache (size_t start_addr , size_t length )
155+ {
156+ #if CONFIG_IDF_TARGET_ESP32
157+ Cache_Read_Disable (0 );
158+ Cache_Flush (0 );
159+ Cache_Read_Enable (0 );
160+ #else
161+ uint32_t vaddr = 0 ;
162+
163+ mmu_hal_paddr_to_vaddr (0 , start_addr , MMU_TARGET_FLASH0 , MMU_VADDR_DATA , & vaddr );
164+ if ((void * )vaddr != NULL ) {
165+ cache_hal_invalidate_addr (vaddr , length );
166+ }
167+ #endif
168+ }
169+
151170static bool aligned_flash_read (uintptr_t addr , void * dest , size_t size )
152171{
153172 if (IS_ALIGNED (addr , 4 ) && IS_ALIGNED ((uintptr_t )dest , 4 ) && IS_ALIGNED (size , 4 )) {
@@ -225,29 +244,31 @@ static bool aligned_flash_write(size_t dest_addr, const void *src, size_t size)
225244#else
226245 bool flash_encryption_enabled = false;
227246#endif
247+ size_t alignment = flash_encryption_enabled ? 32 : 4 ;
228248
229- if (IS_ALIGNED (dest_addr , 4 ) && IS_ALIGNED ((uintptr_t )src , 4 ) && IS_ALIGNED (size , 4 )) {
249+ if (IS_ALIGNED (dest_addr , alignment ) && IS_ALIGNED ((uintptr_t )src , 4 ) && IS_ALIGNED (size , alignment )) {
230250 /* A single write operation is enough when all parameters are aligned */
231251
232252 return bootloader_flash_write (dest_addr , (void * )src , size , flash_encryption_enabled ) == ESP_OK ;
233253 }
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 );
234255
235- const uint32_t aligned_addr = ALIGN_DOWN (dest_addr , 4 );
236- const uint32_t addr_offset = ALIGN_OFFSET (dest_addr , 4 );
256+ const uint32_t aligned_addr = ALIGN_DOWN (dest_addr , alignment );
257+ const uint32_t addr_offset = ALIGN_OFFSET (dest_addr , alignment );
237258 uint32_t bytes_remaining = size ;
238- uint8_t write_data [FLASH_BUFFER_SIZE ] = {0 };
259+ uint8_t write_data [FLASH_BUFFER_SIZE ] __attribute__(( aligned ( 32 ))) = {0 };
239260
240261 /* Perform a read operation considering an offset not aligned to 4-byte boundary */
241262
242263 uint32_t bytes = MIN (bytes_remaining + addr_offset , sizeof (write_data ));
243- if (bootloader_flash_read (aligned_addr , write_data , ALIGN_UP (bytes , 4 ), true) != ESP_OK ) {
264+ if (bootloader_flash_read (aligned_addr , write_data , ALIGN_UP (bytes , alignment ), true) != ESP_OK ) {
244265 return false;
245266 }
246267
247268 uint32_t bytes_written = bytes - addr_offset ;
248269 memcpy (& write_data [addr_offset ], src , bytes_written );
249270
250- if (bootloader_flash_write (aligned_addr , write_data , ALIGN_UP (bytes , 4 ), flash_encryption_enabled ) != ESP_OK ) {
271+ if (bootloader_flash_write (aligned_addr , write_data , ALIGN_UP (bytes , alignment ), flash_encryption_enabled ) != ESP_OK ) {
251272 return false;
252273 }
253274
@@ -259,13 +280,13 @@ static bool aligned_flash_write(size_t dest_addr, const void *src, size_t size)
259280
260281 while (bytes_remaining != 0 ) {
261282 bytes = MIN (bytes_remaining , sizeof (write_data ));
262- if (bootloader_flash_read (aligned_addr + offset , write_data , ALIGN_UP (bytes , 4 ), true) != ESP_OK ) {
283+ if (bootloader_flash_read (aligned_addr + offset , write_data , ALIGN_UP (bytes , alignment ), true) != ESP_OK ) {
263284 return false;
264285 }
265286
266287 memcpy (write_data , & ((uint8_t * )src )[bytes_written ], bytes );
267288
268- if (bootloader_flash_write (aligned_addr + offset , write_data , ALIGN_UP (bytes , 4 ), flash_encryption_enabled ) != ESP_OK ) {
289+ if (bootloader_flash_write (aligned_addr + offset , write_data , ALIGN_UP (bytes , alignment ), flash_encryption_enabled ) != ESP_OK ) {
269290 return false;
270291 }
271292
@@ -284,35 +305,39 @@ static bool aligned_flash_erase(size_t addr, size_t size)
284305
285306 return bootloader_flash_erase_range (addr , size ) == ESP_OK ;
286307 }
308+ BOOT_LOG_DBG ("%s: forcing unaligned erase on sector Offset: 0x%x Length: 0x%x" ,
309+ __func__ , (int )addr , (int )size );
287310
288311 const uint32_t aligned_addr = ALIGN_DOWN (addr , FLASH_SECTOR_SIZE );
289312 const uint32_t addr_offset = ALIGN_OFFSET (addr , FLASH_SECTOR_SIZE );
290313 uint32_t bytes_remaining = size ;
291- uint8_t write_data [FLASH_SECTOR_SIZE ] = {0 };
314+ uint8_t write_data [FLASH_SECTOR_SIZE ] __attribute__(( aligned ( 32 ))) = {0 };
292315
293- /* Perform a read operation considering an offset not aligned to 4-byte boundary */
316+ /* Perform a read operation considering an offset not aligned */
294317
295318 uint32_t bytes = MIN (bytes_remaining + addr_offset , sizeof (write_data ));
296319
297320 if (bootloader_flash_read (aligned_addr , write_data , ALIGN_UP (bytes , FLASH_SECTOR_SIZE ), true) != ESP_OK ) {
298321 return false;
299322 }
300323
301-
302324 if (bootloader_flash_erase_range (aligned_addr , ALIGN_UP (bytes , FLASH_SECTOR_SIZE )) != ESP_OK ) {
303- BOOT_LOG_ERR ("%s: Flash erase failed" , __func__ );
304- return -1 ;
325+ return false;
305326 }
306327
307328 uint32_t bytes_written = bytes - addr_offset ;
308329
309330 /* Write first part of non-erased data */
310331 if (addr_offset > 0 ) {
311- aligned_flash_write (aligned_addr , write_data , addr_offset );
332+ if (!aligned_flash_write (aligned_addr , write_data , addr_offset )) {
333+ return false;
334+ }
312335 }
313336
314337 if (bytes < sizeof (write_data )) {
315- aligned_flash_write (aligned_addr + bytes , write_data + bytes , sizeof (write_data ) - bytes );
338+ if (!aligned_flash_write (aligned_addr + bytes , write_data + bytes , sizeof (write_data ) - bytes )) {
339+ return false;
340+ }
316341 }
317342
318343 bytes_remaining -= bytes_written ;
@@ -328,12 +353,13 @@ static bool aligned_flash_erase(size_t addr, size_t size)
328353 }
329354
330355 if (bootloader_flash_erase_range (aligned_addr + offset , ALIGN_UP (bytes , FLASH_SECTOR_SIZE )) != ESP_OK ) {
331- BOOT_LOG_ERR ("%s: Flash erase failed" , __func__ );
332- return -1 ;
356+ return false;
333357 }
334358
335359 if (bytes < sizeof (write_data )) {
336- aligned_flash_write (aligned_addr + offset + bytes , write_data + bytes , sizeof (write_data ) - bytes );
360+ if (!aligned_flash_write (aligned_addr + offset + bytes , write_data + bytes , sizeof (write_data ) - bytes )) {
361+ return false;
362+ }
337363 }
338364
339365 offset += bytes ;
@@ -360,12 +386,13 @@ int flash_area_write(const struct flash_area *fa, uint32_t off, const void *src,
360386 const uint32_t start_addr = fa -> fa_off + off ;
361387 BOOT_LOG_DBG ("%s: Addr: 0x%08x Length: %d" , __func__ , (int )start_addr , (int )len );
362388
363-
364389 if (!aligned_flash_write (start_addr , src , len )) {
365390 BOOT_LOG_ERR ("%s: Flash write failed" , __func__ );
366391 return -1 ;
367392 }
368393
394+ flush_cache (start_addr , len );
395+
369396 return 0 ;
370397}
371398
@@ -376,23 +403,15 @@ int flash_area_erase(const struct flash_area *fa, uint32_t off, uint32_t len)
376403 }
377404
378405 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 );
379407
380- if ((len % FLASH_SECTOR_SIZE ) != 0 || (off % FLASH_SECTOR_SIZE ) != 0 ) {
381- BOOT_LOG_DBG ("%s: Not aligned on sector Offset: 0x%x Length: 0x%x" ,
382- __func__ , (int )start_addr , (int )len );
383-
384- if (!aligned_flash_erase (start_addr , len )) {
385- return -1 ;
386- }
387- } else {
388- BOOT_LOG_DBG ("%s: Aligned Addr: 0x%08x Length: %d" , __func__ , (int )start_addr , (int )len );
389-
390- if (bootloader_flash_erase_range (start_addr , len ) != ESP_OK ) {
391- BOOT_LOG_ERR ("%s: Flash erase failed" , __func__ );
392- return -1 ;
393- }
408+ if (!aligned_flash_erase (start_addr , len )) {
409+ BOOT_LOG_ERR ("%s: Flash erase failed" , __func__ );
410+ return -1 ;
394411 }
395412
413+ flush_cache (start_addr , len );
414+
396415#if VALIDATE_PROGRAM_OP
397416 for (size_t i = 0 ; i < len ; i ++ ) {
398417 uint8_t * val = (void * )(start_addr + i );
0 commit comments