Skip to content

Commit b4174bb

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 0f338f9 commit b4174bb

File tree

1 file changed

+51
-33
lines changed

1 file changed

+51
-33
lines changed

boot/espressif/port/esp_mcuboot.c

Lines changed: 51 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@
1313

1414
#include "sdkconfig.h"
1515
#include "esp_err.h"
16+
#include "hal/cache_hal.h"
17+
#include "hal/mmu_hal.h"
1618
#include "bootloader_flash_priv.h"
1719
#include "esp_flash_encrypt.h"
1820
#include "mcuboot_config/mcuboot_config.h"
@@ -148,6 +150,22 @@ void flash_area_close(const struct flash_area *area)
148150

149151
}
150152

153+
static void flush_cache(size_t start_addr, size_t length)
154+
{
155+
#if CONFIG_IDF_TARGET_ESP32
156+
Cache_Read_Disable(0);
157+
Cache_Flush(0);
158+
Cache_Read_Enable(0);
159+
#else
160+
uint32_t vaddr = 0;
161+
162+
mmu_hal_paddr_to_vaddr(0, start_addr, MMU_TARGET_FLASH0, MMU_VADDR_DATA, &vaddr);
163+
if (vaddr != NULL) {
164+
cache_hal_invalidate_addr(vaddr, length);
165+
}
166+
#endif
167+
}
168+
151169
static bool aligned_flash_read(uintptr_t addr, void *dest, size_t size)
152170
{
153171
if (IS_ALIGNED(addr, 4) && IS_ALIGNED((uintptr_t)dest, 4) && IS_ALIGNED(size, 4)) {
@@ -225,29 +243,31 @@ static bool aligned_flash_write(size_t dest_addr, const void *src, size_t size)
225243
#else
226244
bool flash_encryption_enabled = false;
227245
#endif
246+
size_t alignment = flash_encryption_enabled ? 32 : 4;
228247

229-
if (IS_ALIGNED(dest_addr, 4) && IS_ALIGNED((uintptr_t)src, 4) && IS_ALIGNED(size, 4)) {
248+
if (IS_ALIGNED(dest_addr, alignment) && IS_ALIGNED((uintptr_t)src, 4) && IS_ALIGNED(size, alignment)) {
230249
/* A single write operation is enough when all parameters are aligned */
231250

232251
return bootloader_flash_write(dest_addr, (void *)src, size, flash_encryption_enabled) == ESP_OK;
233252
}
253+
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);
234254

235-
const uint32_t aligned_addr = ALIGN_DOWN(dest_addr, 4);
236-
const uint32_t addr_offset = ALIGN_OFFSET(dest_addr, 4);
255+
const uint32_t aligned_addr = ALIGN_DOWN(dest_addr, alignment);
256+
const uint32_t addr_offset = ALIGN_OFFSET(dest_addr, alignment);
237257
uint32_t bytes_remaining = size;
238-
uint8_t write_data[FLASH_BUFFER_SIZE] = {0};
258+
uint8_t write_data[FLASH_BUFFER_SIZE] __attribute__((aligned(32))) = {0};
239259

240260
/* Perform a read operation considering an offset not aligned to 4-byte boundary */
241261

242262
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) {
263+
if (bootloader_flash_read(aligned_addr, write_data, ALIGN_UP(bytes, alignment), true) != ESP_OK) {
244264
return false;
245265
}
246266

247267
uint32_t bytes_written = bytes - addr_offset;
248268
memcpy(&write_data[addr_offset], src, bytes_written);
249269

250-
if (bootloader_flash_write(aligned_addr, write_data, ALIGN_UP(bytes, 4), flash_encryption_enabled) != ESP_OK) {
270+
if (bootloader_flash_write(aligned_addr, write_data, ALIGN_UP(bytes, alignment), flash_encryption_enabled) != ESP_OK) {
251271
return false;
252272
}
253273

@@ -259,13 +279,13 @@ static bool aligned_flash_write(size_t dest_addr, const void *src, size_t size)
259279

260280
while (bytes_remaining != 0) {
261281
bytes = MIN(bytes_remaining, sizeof(write_data));
262-
if (bootloader_flash_read(aligned_addr + offset, write_data, ALIGN_UP(bytes, 4), true) != ESP_OK) {
282+
if (bootloader_flash_read(aligned_addr + offset, write_data, ALIGN_UP(bytes, alignment), true) != ESP_OK) {
263283
return false;
264284
}
265285

266286
memcpy(write_data, &((uint8_t *)src)[bytes_written], bytes);
267287

268-
if (bootloader_flash_write(aligned_addr + offset, write_data, ALIGN_UP(bytes, 4), flash_encryption_enabled) != ESP_OK) {
288+
if (bootloader_flash_write(aligned_addr + offset, write_data, ALIGN_UP(bytes, alignment), flash_encryption_enabled) != ESP_OK) {
269289
return false;
270290
}
271291

@@ -284,35 +304,39 @@ static bool aligned_flash_erase(size_t addr, size_t size)
284304

285305
return bootloader_flash_erase_range(addr, size) == ESP_OK;
286306
}
307+
BOOT_LOG_DBG("%s: forcing unaligned erase on sector Offset: 0x%x Length: 0x%x",
308+
__func__, (int)addr, (int)size);
287309

288310
const uint32_t aligned_addr = ALIGN_DOWN(addr, FLASH_SECTOR_SIZE);
289311
const uint32_t addr_offset = ALIGN_OFFSET(addr, FLASH_SECTOR_SIZE);
290312
uint32_t bytes_remaining = size;
291-
uint8_t write_data[FLASH_SECTOR_SIZE] = {0};
313+
uint8_t write_data[FLASH_SECTOR_SIZE] __attribute__((aligned(32))) = {0};
292314

293-
/* Perform a read operation considering an offset not aligned to 4-byte boundary */
315+
/* Perform a read operation considering an offset not aligned */
294316

295317
uint32_t bytes = MIN(bytes_remaining + addr_offset, sizeof(write_data));
296318

297319
if (bootloader_flash_read(aligned_addr, write_data, ALIGN_UP(bytes, FLASH_SECTOR_SIZE), true) != ESP_OK) {
298320
return false;
299321
}
300322

301-
302323
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;
324+
return false;
305325
}
306326

307327
uint32_t bytes_written = bytes - addr_offset;
308328

309329
/* Write first part of non-erased data */
310330
if(addr_offset > 0) {
311-
aligned_flash_write(aligned_addr, write_data, addr_offset);
331+
if (!aligned_flash_write(aligned_addr, write_data, addr_offset)) {
332+
return false;
333+
}
312334
}
313335

314336
if(bytes < sizeof(write_data)) {
315-
aligned_flash_write(aligned_addr + bytes, write_data + bytes, sizeof(write_data) - bytes);
337+
if (!aligned_flash_write(aligned_addr + bytes, write_data + bytes, sizeof(write_data) - bytes)) {
338+
return false;
339+
}
316340
}
317341

318342
bytes_remaining -= bytes_written;
@@ -328,12 +352,13 @@ static bool aligned_flash_erase(size_t addr, size_t size)
328352
}
329353

330354
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;
355+
return false;
333356
}
334357

335358
if(bytes < sizeof(write_data)) {
336-
aligned_flash_write(aligned_addr + offset + bytes, write_data + bytes, sizeof(write_data) - bytes);
359+
if (!aligned_flash_write(aligned_addr + offset + bytes, write_data + bytes, sizeof(write_data) - bytes)) {
360+
return false;
361+
}
337362
}
338363

339364
offset += bytes;
@@ -360,12 +385,13 @@ int flash_area_write(const struct flash_area *fa, uint32_t off, const void *src,
360385
const uint32_t start_addr = fa->fa_off + off;
361386
BOOT_LOG_DBG("%s: Addr: 0x%08x Length: %d", __func__, (int)start_addr, (int)len);
362387

363-
364388
if (!aligned_flash_write(start_addr, src, len)) {
365389
BOOT_LOG_ERR("%s: Flash write failed", __func__);
366390
return -1;
367391
}
368392

393+
flush_cache(start_addr, len);
394+
369395
return 0;
370396
}
371397

@@ -376,23 +402,15 @@ int flash_area_erase(const struct flash_area *fa, uint32_t off, uint32_t len)
376402
}
377403

378404
const uint32_t start_addr = fa->fa_off + off;
405+
BOOT_LOG_DBG("%s: Addr: 0x%08x Length: %d", __func__, (int)start_addr, (int)len);
379406

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-
}
407+
if(!aligned_flash_erase(start_addr, len)) {
408+
BOOT_LOG_ERR("%s: Flash erase failed", __func__);
409+
return -1;
394410
}
395411

412+
flush_cache(start_addr, len);
413+
396414
#if VALIDATE_PROGRAM_OP
397415
for (size_t i = 0; i < len; i++) {
398416
uint8_t *val = (void *)(start_addr + i);

0 commit comments

Comments
 (0)