Skip to content

Commit db995ee

Browse files
committed
espressif: fix flash write/erase operation when encryption is enabled
Add cache flush after write/erase operations to avoid getting invalid data when these are followed by read operation. Signed-off-by: Almir Okato <[email protected]>
1 parent cc42b77 commit db995ee

File tree

1 file changed

+52
-33
lines changed

1 file changed

+52
-33
lines changed

boot/espressif/port/esp_mcuboot.c

Lines changed: 52 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,9 @@
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+
151170
static 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

Comments
 (0)