Skip to content

Commit 95f6eba

Browse files
committed
espressif: fix flash write/erase operation when encryption is enabled
Signed-off-by: Almir Okato <[email protected]>
1 parent d1881ca commit 95f6eba

File tree

1 file changed

+57
-33
lines changed

1 file changed

+57
-33
lines changed

boot/espressif/port/esp_mcuboot.c

Lines changed: 57 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,24 @@ void flash_area_close(const struct flash_area *area)
148150

149151
}
150152

153+
#ifdef CONFIG_SECURE_FLASH_ENC_ENABLED
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 (vaddr != NULL) {
165+
cache_hal_invalidate_addr(vaddr, length);
166+
}
167+
#endif
168+
}
169+
#endif
170+
151171
static bool aligned_flash_read(uintptr_t addr, void *dest, size_t size)
152172
{
153173
if (IS_ALIGNED(addr, 4) && IS_ALIGNED((uintptr_t)dest, 4) && IS_ALIGNED(size, 4)) {
@@ -225,29 +245,31 @@ static bool aligned_flash_write(size_t dest_addr, const void *src, size_t size)
225245
#else
226246
bool flash_encryption_enabled = false;
227247
#endif
248+
size_t alignment = flash_encryption_enabled ? 32 : 4;
228249

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

232253
return bootloader_flash_write(dest_addr, (void *)src, size, flash_encryption_enabled) == ESP_OK;
233254
}
255+
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);
234256

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

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

242264
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) {
265+
if (bootloader_flash_read(aligned_addr, write_data, ALIGN_UP(bytes, alignment), true) != ESP_OK) {
244266
return false;
245267
}
246268

247269
uint32_t bytes_written = bytes - addr_offset;
248270
memcpy(&write_data[addr_offset], src, bytes_written);
249271

250-
if (bootloader_flash_write(aligned_addr, write_data, ALIGN_UP(bytes, 4), flash_encryption_enabled) != ESP_OK) {
272+
if (bootloader_flash_write(aligned_addr, write_data, ALIGN_UP(bytes, alignment), flash_encryption_enabled) != ESP_OK) {
251273
return false;
252274
}
253275

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

260282
while (bytes_remaining != 0) {
261283
bytes = MIN(bytes_remaining, sizeof(write_data));
262-
if (bootloader_flash_read(aligned_addr + offset, write_data, ALIGN_UP(bytes, 4), true) != ESP_OK) {
284+
if (bootloader_flash_read(aligned_addr + offset, write_data, ALIGN_UP(bytes, alignment), true) != ESP_OK) {
263285
return false;
264286
}
265287

266288
memcpy(write_data, &((uint8_t *)src)[bytes_written], bytes);
267289

268-
if (bootloader_flash_write(aligned_addr + offset, write_data, ALIGN_UP(bytes, 4), flash_encryption_enabled) != ESP_OK) {
290+
if (bootloader_flash_write(aligned_addr + offset, write_data, ALIGN_UP(bytes, alignment), flash_encryption_enabled) != ESP_OK) {
269291
return false;
270292
}
271293

@@ -284,35 +306,39 @@ static bool aligned_flash_erase(size_t addr, size_t size)
284306

285307
return bootloader_flash_erase_range(addr, size) == ESP_OK;
286308
}
309+
BOOT_LOG_DBG("%s: forcing unaligned erase on sector Offset: 0x%x Length: 0x%x",
310+
__func__, (int)addr, (int)size);
287311

288312
const uint32_t aligned_addr = ALIGN_DOWN(addr, FLASH_SECTOR_SIZE);
289313
const uint32_t addr_offset = ALIGN_OFFSET(addr, FLASH_SECTOR_SIZE);
290314
uint32_t bytes_remaining = size;
291-
uint8_t write_data[FLASH_SECTOR_SIZE] = {0};
315+
uint8_t write_data[FLASH_SECTOR_SIZE] __attribute__((aligned(32))) = {0};
292316

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

295319
uint32_t bytes = MIN(bytes_remaining + addr_offset, sizeof(write_data));
296320

297321
if (bootloader_flash_read(aligned_addr, write_data, ALIGN_UP(bytes, FLASH_SECTOR_SIZE), true) != ESP_OK) {
298322
return false;
299323
}
300324

301-
302325
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;
326+
return false;
305327
}
306328

307329
uint32_t bytes_written = bytes - addr_offset;
308330

309331
/* Write first part of non-erased data */
310332
if(addr_offset > 0) {
311-
aligned_flash_write(aligned_addr, write_data, addr_offset);
333+
if (!aligned_flash_write(aligned_addr, write_data, addr_offset)) {
334+
return false;
335+
}
312336
}
313337

314338
if(bytes < sizeof(write_data)) {
315-
aligned_flash_write(aligned_addr + bytes, write_data + bytes, sizeof(write_data) - bytes);
339+
if (!aligned_flash_write(aligned_addr + bytes, write_data + bytes, sizeof(write_data) - bytes)) {
340+
return false;
341+
}
316342
}
317343

318344
bytes_remaining -= bytes_written;
@@ -328,12 +354,13 @@ static bool aligned_flash_erase(size_t addr, size_t size)
328354
}
329355

330356
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;
357+
return false;
333358
}
334359

335360
if(bytes < sizeof(write_data)) {
336-
aligned_flash_write(aligned_addr + offset + bytes, write_data + bytes, sizeof(write_data) - bytes);
361+
if (!aligned_flash_write(aligned_addr + offset + bytes, write_data + bytes, sizeof(write_data) - bytes)) {
362+
return false;
363+
}
337364
}
338365

339366
offset += bytes;
@@ -360,12 +387,15 @@ int flash_area_write(const struct flash_area *fa, uint32_t off, const void *src,
360387
const uint32_t start_addr = fa->fa_off + off;
361388
BOOT_LOG_DBG("%s: Addr: 0x%08x Length: %d", __func__, (int)start_addr, (int)len);
362389

363-
364390
if (!aligned_flash_write(start_addr, src, len)) {
365391
BOOT_LOG_ERR("%s: Flash write failed", __func__);
366392
return -1;
367393
}
368394

395+
#ifdef CONFIG_SECURE_FLASH_ENC_ENABLED
396+
flush_cache(start_addr, len);
397+
#endif
398+
369399
return 0;
370400
}
371401

@@ -376,23 +406,17 @@ int flash_area_erase(const struct flash_area *fa, uint32_t off, uint32_t len)
376406
}
377407

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

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-
}
411+
if(!aligned_flash_erase(start_addr, len)) {
412+
BOOT_LOG_ERR("%s: Flash erase failed", __func__);
413+
return -1;
394414
}
395415

416+
#ifdef CONFIG_SECURE_FLASH_ENC_ENABLED
417+
flush_cache(start_addr, len);
418+
#endif
419+
396420
#if VALIDATE_PROGRAM_OP
397421
for (size_t i = 0; i < len; i++) {
398422
uint8_t *val = (void *)(start_addr + i);

0 commit comments

Comments
 (0)