This is an automated email from the ASF dual-hosted git repository.

simbit18 pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/nuttx.git

commit 0835b345e89962010b8ebb546a850e54de7c5bcf
Author: Filipe Cavalcanti <[email protected]>
AuthorDate: Thu Sep 4 13:18:33 2025 -0300

    arch/risc-v: flash encryption support for ESP32-C3|C6|H2
    
    Add Kconfig option to enable flash encryption.
    Default E-Fuse state is now VIRTUAL.
    Modifies SPI Flash driver for encrypted operation.
    Limitations:
    - Requires MCUBoot
    - Flash fully encrypted (no unencrypted MTD part. support)
    
    Signed-off-by: Filipe Cavalcanti <[email protected]>
---
 arch/risc-v/src/common/espressif/Bootloader.mk  |   7 +-
 arch/risc-v/src/common/espressif/Kconfig        |  81 +++-
 arch/risc-v/src/common/espressif/esp_spiflash.c | 484 +++++++++++++++++++++++-
 arch/risc-v/src/esp32c6/hal_esp32c6.mk          |   4 +-
 arch/risc-v/src/esp32h2/hal_esp32h2.mk          |   4 +-
 tools/espressif/Config.mk                       |   4 +
 6 files changed, 560 insertions(+), 24 deletions(-)

diff --git a/arch/risc-v/src/common/espressif/Bootloader.mk 
b/arch/risc-v/src/common/espressif/Bootloader.mk
index 701b2dcd46a..dff1cb8c935 100644
--- a/arch/risc-v/src/common/espressif/Bootloader.mk
+++ b/arch/risc-v/src/common/espressif/Bootloader.mk
@@ -46,7 +46,7 @@ ifndef MCUBOOT_URL
 endif
 
 ifndef ESP_HAL_3RDPARTY_VERSION_FOR_MCUBOOT
-       ESP_HAL_3RDPARTY_VERSION_FOR_MCUBOOT = 
3f02f2139e79ddc60f98ca35ed65c62c6914f079
+       ESP_HAL_3RDPARTY_VERSION_FOR_MCUBOOT = 
911dbec8e4a92e70056b58a3d2b0d965b8b7bcc9
 endif
 
 # Helpers for creating the configuration file
@@ -94,6 +94,11 @@ ifeq ($(CONFIG_ESPRESSIF_BOOTLOADER_MCUBOOT),y)
                $(if $(CONFIG_UART0_SERIAL_CONSOLE),$(call 
cfg_val,CONFIG_ESP_CONSOLE_ROM_SERIAL_PORT_NUM,0)) \
                $(if $(CONFIG_UART1_SERIAL_CONSOLE),$(call 
cfg_val,CONFIG_ESP_CONSOLE_ROM_SERIAL_PORT_NUM,1)) \
                $(if $(CONFIG_ESPRESSIF_USBSERIAL),$(call 
cfg_val,CONFIG_ESP_CONSOLE_UART_NUM,0)) \
+               $(if $(CONFIG_ESPRESSIF_SECURE_FLASH_ENC_ENABLED),$(call 
cfg_en,CONFIG_SECURE_FLASH_ENC_ENABLED)) \
+               $(if 
$(CONFIG_ESPRESSIF_SECURE_FLASH_ENCRYPTION_MODE_DEVELOPMENT),$(call 
cfg_en,CONFIG_SECURE_FLASH_ENCRYPTION_MODE_DEVELOPMENT)) \
+               $(if 
$(CONFIG_ESPRESSIF_SECURE_FLASH_UART_BOOTLOADER_ALLOW_ENC),$(call 
cfg_en,CONFIG_SECURE_FLASH_UART_BOOTLOADER_ALLOW_ENC)) \
+               $(if 
$(CONFIG_ESPRESSIF_SECURE_FLASH_UART_BOOTLOADER_ALLOW_DEC),$(call 
cfg_en,CONFIG_SECURE_FLASH_UART_BOOTLOADER_ALLOW_DEC)) \
+               $(if 
$(CONFIG_ESPRESSIF_SECURE_FLASH_UART_BOOTLOADER_ALLOW_CACHE),$(call 
cfg_en,CONFIG_SECURE_FLASH_UART_BOOTLOADER_ALLOW_CACHE)) \
                $(call cfg_val,CONFIG_BOOTLOADER_LOG_LEVEL,3) \
        } >> $(BOOTLOADER_CONFIG)
 ifeq ($(CONFIG_ESPRESSIF_EFUSE_VIRTUAL_KEEP_IN_FLASH),y)
diff --git a/arch/risc-v/src/common/espressif/Kconfig 
b/arch/risc-v/src/common/espressif/Kconfig
index f347053bba0..3f987cb87e1 100644
--- a/arch/risc-v/src/common/espressif/Kconfig
+++ b/arch/risc-v/src/common/espressif/Kconfig
@@ -146,7 +146,7 @@ config ESPRESSIF_BOOTLOADER_MCUBOOT
 config ESPRESSIF_MCUBOOT_VERSION
        string "MCUboot version"
        depends on ESPRESSIF_BOOTLOADER_MCUBOOT
-       default "aa4fa2b6e17361dd3ce16a60883059778fd147a9"
+       default "8a07053d42e592c85cb35b79c4de1b7749943387"
 
 choice ESPRESSIF_ESPTOOL_TARGET_SLOT
        prompt "Target slot for image flashing"
@@ -225,6 +225,82 @@ config ESPRESSIF_OTA_SCRATCH_DEVPATH
 
 endif # ESPRESSIF_HAVE_OTA_PARTITION
 
+config ESPRESSIF_SECURE_FLASH_ENC_ENABLED
+       bool "Enable Flash Encryption on boot (READ DOCS FIRST)"
+       default n
+       depends on ESPRESSIF_BOOTLOADER_MCUBOOT
+       select ESPRESSIF_EFUSE
+       ---help---
+               If this option is set, flash contents will be encrypted by the 
bootloader on first boot.
+
+               Note: After first boot, the system will be permanently 
encrypted. Re-flashing an encrypted
+               system is complicated and not always possible.
+
+               Read 
https://docs.espressif.com/projects/esp-idf/en/latest/security/flash-encryption.html
+               before enabling.
+
+               Note: enabling this option will automatically select 
ESPRESSIF_EFUSE and ESPRESSIF_EFUSE_VIRTUAL,
+               as a mean to avoid accidental burning of the E-Fuses.
+
+if ESPRESSIF_SECURE_FLASH_ENC_ENABLED
+
+config ESPRESSIF_SECURE_FLASH_UART_BOOTLOADER_ALLOW_ENC
+       bool "Leave UART bootloader encryption enabled"
+       depends on ESPRESSIF_SECURE_FLASH_ENCRYPTION_MODE_DEVELOPMENT
+       default n
+       help
+               If not set (default), the bootloader will permanently disable 
UART bootloader encryption access on
+               first boot. If set, the UART bootloader will still be able to 
access hardware encryption.
+
+               It is recommended to only set this option in testing 
environments.
+
+config ESPRESSIF_SECURE_FLASH_UART_BOOTLOADER_ALLOW_DEC
+       bool "Leave UART bootloader decryption enabled"
+       default n
+       depends on ESPRESSIF_SECURE_FLASH_ENCRYPTION_MODE_DEVELOPMENT
+       ---help---
+               If not set (default), the bootloader will permanently disable 
UART bootloader decryption access on
+               first boot. If set, the UART bootloader will still be able to 
access hardware decryption.
+
+               Only set this option in testing environments. Setting this 
option allows complete bypass of flash
+               encryption.
+
+config ESPRESSIF_SECURE_FLASH_UART_BOOTLOADER_ALLOW_CACHE
+       bool "Leave UART bootloader flash cache enabled"
+       default n
+       depends on ESPRESSIF_SECURE_FLASH_ENCRYPTION_MODE_DEVELOPMENT
+       ---help---
+               If not set (default), the bootloader will permanently disable 
UART bootloader flash cache access on
+               first boot. If set, the UART bootloader will still be able to 
access the flash cache.
+
+               Only set this option in testing environments.
+
+choice ESPRESSIF_SECURE_FLASH_ENCRYPTION_MODE
+       bool "Enable usage mode"
+       default ESPRESSIF_SECURE_FLASH_ENCRYPTION_MODE_DEVELOPMENT
+       ---help---
+               By default, Development mode is enabled which allows ROM 
download mode to perform Flash Encryption
+               operations (plaintext is sent to the device, and it encrypts it 
internally and writes ciphertext
+               to flash). This mode is not secure, it's possible for an 
attacker to write their own chosen plaintext
+               to flash.
+
+               Release mode should always be selected for production or 
manufacturing. Once enabled it's no longer
+               possible for the device in ROM Download Mode to use the Flash 
Encryption hardware.
+
+               Refer to the Flash Encryption section of the ESP-IDF 
Programmer's Guide for details:
+               
https://docs.espressif.com/projects/esp-idf/en/latest/esp32/security/flash-encryption.html#flash-encryption-configuration
+
+       config ESPRESSIF_SECURE_FLASH_ENCRYPTION_MODE_DEVELOPMENT
+               bool "Development (NOT SECURE)"
+               select ESPRESSIF_SECURE_FLASH_UART_BOOTLOADER_ALLOW_ENC
+
+       config ESPRESSIF_SECURE_FLASH_ENCRYPTION_MODE_RELEASE
+               bool "Release"
+
+endchoice
+
+endif # ESPRESSIF_SECURE_FLASH_ENC_ENABLED
+
 endmenu # Bootloader and Image Configuration
 
 menu "LP Core (Low-power core) Coprocessor Configuration"
@@ -952,7 +1028,7 @@ config ESPRESSIF_EFUSE
 config ESPRESSIF_EFUSE_VIRTUAL
        bool "Virtual E-Fuses support"
        depends on ESPRESSIF_EFUSE
-       default n
+       default y
        ---help---
                Enable virtual E-Fuse support to simulate E-Fuse operations in 
RAM.
                Changes will be reverted each reboot unless enabling 
ESPRESSIF_EFUSE_VIRTUAL_KEEP_IN_FLASH.
@@ -960,6 +1036,7 @@ config ESPRESSIF_EFUSE_VIRTUAL
 config ESPRESSIF_EFUSE_VIRTUAL_KEEP_IN_FLASH
        bool "Keep E-Fuses in flash"
        depends on ESPRESSIF_EFUSE_VIRTUAL
+       default y
        ---help---
                In addition to the "Virtual E-Fuses support" option, this 
option just adds
                a feature to keep E-Fuses after reboots in flash memory.
diff --git a/arch/risc-v/src/common/espressif/esp_spiflash.c 
b/arch/risc-v/src/common/espressif/esp_spiflash.c
index b6efa248140..2403109abe6 100644
--- a/arch/risc-v/src/common/espressif/esp_spiflash.c
+++ b/arch/risc-v/src/common/espressif/esp_spiflash.c
@@ -27,6 +27,7 @@
 #include <nuttx/config.h>
 #include <nuttx/arch.h>
 #include <nuttx/init.h>
+#include <nuttx/nuttx.h>
 
 #include <stdint.h>
 #include <assert.h>
@@ -39,24 +40,422 @@
 #include "esp_flash_internal.h"
 #include "esp_flash.h"
 #include "esp_flash_encrypt.h"
-#ifdef CONFIG_SMP
 #include "esp_private/cache_utils.h"
-#endif
+#include "hal/efuse_hal.h"
+#include "bootloader_flash_priv.h"
 
 /****************************************************************************
  * Pre-processor Definitions
  ****************************************************************************/
 
-#define SPIFLASH_OP_TASK_STACKSIZE 768
+#ifdef CONFIG_ESPRESSIF_EFUSE_VIRTUAL_KEEP_IN_FLASH
+#define ENCRYPTION_IS_VIRTUAL (!efuse_hal_flash_encryption_enabled())
+#else
+#define ENCRYPTION_IS_VIRTUAL 0
+#endif
+
+#ifndef ALIGN_OFFSET
+#define ALIGN_OFFSET(num, align) ((num) & ((align) - 1))
+#endif
+
+#ifndef ROUND_DOWN
+#define ROUND_DOWN(x, align) ((unsigned long)(x) & ~((unsigned long)align - 1))
+#endif
+
+#ifndef ROUND_UP
+#define ROUND_UP(x, align) \
+        (((unsigned long)(x) + ((unsigned long)align - 1)) & \
+        ~((unsigned long)align - 1))
+#endif
+
+ #define FLASH_BUFFER_SIZE          32
+ #define FLASH_ERASE_VALUE          0xff
+ #define SPIFLASH_OP_TASK_STACKSIZE 768
 
 /****************************************************************************
  * Private Data
  ****************************************************************************/
 
+#if CONFIG_ESPRESSIF_SECURE_FLASH_ENC_ENABLED
+static uint8_t write_aux_buf[FLASH_SECTOR_SIZE] =
+{
+  0
+};
+static uint8_t erase_aux_buf[FLASH_SECTOR_SIZE] =
+{
+  0
+};
+#endif
+
 /****************************************************************************
  * Private Functions
  ****************************************************************************/
 
+/****************************************************************************
+ * Name: flash_esp32_read_check_enc
+ *
+ * Description:
+ *   Read data from flash, automatically handling encryption if enabled.
+ *   This function checks if flash encryption is enabled and uses the
+ *   appropriate read function (encrypted or raw).
+ *
+ * Input Parameters:
+ *   address - Source address of the data in flash.
+ *   buffer  - Pointer to the destination buffer.
+ *   length  - Length of data in bytes.
+ *
+ * Returned Value:
+ *   OK on success; -EIO on failure.
+ *
+ ****************************************************************************/
+
+static int flash_esp32_read_check_enc(uint32_t address, void *buffer,
+                                      size_t length)
+{
+  int ret;
+
+  if (esp_flash_encryption_enabled())
+    {
+      finfo("Flash read ENCRYPTED - address 0x%lx size 0x%x",
+            address, length);
+      ret = esp_flash_read_encrypted(NULL, address, buffer, length);
+    }
+  else
+    {
+      finfo("Flash read RAW - address 0x%lx size 0x%x", address, length);
+      ret = esp_flash_read(NULL, buffer, address, length);
+    }
+
+  if (ret != OK)
+    {
+      ferr("ERROR: failed to read: ret=%d", ret);
+      return -EIO;
+    }
+
+  return OK;
+}
+
+/****************************************************************************
+ * Name: flash_esp32_write_check_enc
+ *
+ * Description:
+ *   Write data to flash, automatically handling encryption if enabled.
+ *   This function checks if flash encryption is enabled and uses the
+ *   appropriate write function (encrypted or raw).
+ *
+ * Input Parameters:
+ *   address - Destination address in flash.
+ *   buffer  - Pointer to the source buffer.
+ *   length  - Length of data in bytes.
+ *
+ * Returned Value:
+ *   OK on success; -EIO on failure.
+ *
+ ****************************************************************************/
+
+static int flash_esp32_write_check_enc(uint32_t address, const void *buffer,
+                                       size_t length)
+{
+  int ret;
+
+  if (esp_flash_encryption_enabled() && !ENCRYPTION_IS_VIRTUAL)
+    {
+      finfo("Flash write ENCRYPTED - address 0x%lx size 0x%x",
+            address, length);
+      ret = esp_flash_write_encrypted(NULL, address, buffer, length);
+    }
+  else
+    {
+      finfo("Flash write RAW - address 0x%lx size 0x%x",
+            address, length);
+      ret = esp_flash_write(NULL, buffer, address, length);
+    }
+
+  if (ret != 0)
+    {
+      ferr("ERROR: failed to write: ret=%d", ret);
+      return -EIO;
+    }
+
+  return OK;
+}
+
+#if CONFIG_ESPRESSIF_SECURE_FLASH_ENC_ENABLED
+/****************************************************************************
+ * Name: aligned_flash_write
+ *
+ * Description:
+ *   Write data to flash with proper alignment handling. This function
+ *   ensures that writes are aligned according to flash encryption
+ *   requirements. When flash encryption is enabled, writes must be
+ *   aligned to 32 bytes (or FLASH_SECTOR_SIZE if erase is required).
+ *   For unaligned writes, the function reads the existing data, merges
+ *   it with the new data, and writes back the aligned chunk.
+ *
+ * Input Parameters:
+ *   dest_addr - Destination address in flash.
+ *   src       - Pointer to the source buffer.
+ *   size      - Length of data in bytes.
+ *   erase     - If true, erase the region before writing (required when
+ *               flash encryption is enabled).
+ *
+ * Returned Value:
+ *   true on success; false on failure.
+ *
+ ****************************************************************************/
+
+static bool aligned_flash_write(size_t dest_addr, const void *src,
+                                size_t size, bool erase)
+{
+  bool flash_enc_enabled = esp_flash_encryption_enabled();
+  size_t alignment;
+  size_t write_addr = dest_addr;
+  size_t bytes_remaining = size;
+  size_t src_offset = 0;
+
+  /* When flash encryption is enabled, write alignment is 32 bytes, however
+   * to avoid inconsistences the region may be erased right before writing,
+   * thus the alignment is set to the erase required alignment
+   * (FLASH_SECTOR_SIZE).
+   * When flash encryption is not enabled, regular write alignment
+   * is 4 bytes.
+   */
+
+  alignment = flash_enc_enabled ? (erase ? FLASH_SECTOR_SIZE : 32) : 4;
+
+  if (IS_ALIGNED(dest_addr, alignment) && IS_ALIGNED((uintptr_t)src, 4) &&
+      IS_ALIGNED(size, alignment))
+    {
+      /* A single write operation is enough when all parameters are aligned */
+
+      if (flash_enc_enabled && erase)
+        {
+          if (esp_flash_erase_region(NULL, dest_addr, size) != OK)
+            {
+              ferr("ERROR: erase failed at 0x%08x", (uintptr_t)dest_addr);
+              return false;
+            }
+        }
+
+      return flash_esp32_write_check_enc(dest_addr, (void *)src, size) == OK;
+    }
+
+  finfo("forcing unaligned write dest_addr: "
+        "0x%08x src: 0x%08x size: 0x%x erase: %c",
+        (uintptr_t)dest_addr, (uintptr_t)src, size, erase ? 't' : 'f');
+
+  while (bytes_remaining > 0)
+    {
+      size_t aligned_curr_addr = ROUND_DOWN(write_addr, alignment);
+      size_t curr_buf_off = write_addr - aligned_curr_addr;
+      size_t chunk_len = MIN(bytes_remaining,
+                             FLASH_SECTOR_SIZE - curr_buf_off);
+
+      /* Read data before modifying */
+
+      if (flash_esp32_read_check_enc(aligned_curr_addr, write_aux_buf,
+                                     ROUND_UP(chunk_len, alignment)) != OK)
+        {
+          ferr("ERROR: flash read failed at 0x%08x",
+               (uintptr_t)aligned_curr_addr);
+          return false;
+        }
+
+      /* Erase if needed */
+
+      if (flash_enc_enabled && erase)
+        {
+          if (esp_flash_erase_region(NULL, aligned_curr_addr,
+                                     ROUND_UP(
+                                      chunk_len, FLASH_SECTOR_SIZE)) != OK)
+            {
+              ferr("ERROR: flash erase failed at 0x%08x",
+                   (uintptr_t)aligned_curr_addr);
+              return false;
+            }
+        }
+
+      /* Merge data into buffer */
+
+      memcpy(&write_aux_buf[curr_buf_off],
+             &((const uint8_t *)src)[src_offset],
+             chunk_len);
+
+      /* Write back aligned chunk */
+
+      if (flash_esp32_write_check_enc(aligned_curr_addr, write_aux_buf,
+                                      ROUND_UP(chunk_len, alignment)) != OK)
+        {
+          ferr("ERROR: flash write failed at 0x%08x",
+               (uintptr_t)aligned_curr_addr);
+          return false;
+        }
+
+      write_addr += chunk_len;
+      src_offset += chunk_len;
+      bytes_remaining -= chunk_len;
+    }
+
+  return true;
+}
+
+/****************************************************************************
+ * Name: erase_partial_sector
+ *
+ * Description:
+ *   Erase a partial sector while preserving data outside the erase region.
+ *   This function reads the full sector, erases it, then writes back the
+ *   preserved data at the head and tail of the sector.
+ *
+ * Input Parameters:
+ *   addr        - Base address of the sector to erase.
+ *   sector_size - Size of the sector in bytes.
+ *   erase_start - Offset from sector start where erase begins.
+ *   erase_end   - Offset from sector start where erase ends.
+ *
+ * Returned Value:
+ *   true on success; false on failure.
+ *
+ ****************************************************************************/
+
+static bool erase_partial_sector(size_t addr, size_t sector_size,
+                                 size_t erase_start, size_t erase_end)
+{
+  /* Read full sector before erasing */
+
+  if (flash_esp32_read_check_enc(addr, erase_aux_buf, sector_size) != OK)
+    {
+      ferr("ERROR: flash read failed at 0x%08x", (uintptr_t)addr);
+      return false;
+    }
+
+  /* Erase full sector */
+
+  if (esp_flash_erase_region(NULL, addr, sector_size) != OK)
+    {
+      ferr("ERROR: flash erase failed at 0x%08x", (uintptr_t)addr);
+      return false;
+    }
+
+  /* Write back preserved head data up to erase_start */
+
+  if (erase_start > 0)
+    {
+      if (!aligned_flash_write(addr, erase_aux_buf, erase_start, false))
+        {
+          ferr("ERROR: flash write failed at 0x%08x", (uintptr_t)addr);
+          return false;
+        }
+    }
+
+  /* Write back preserved tail data from erase_end up to sector end */
+
+  if (erase_end < sector_size)
+    {
+      if (!aligned_flash_write(addr + erase_end, &erase_aux_buf[erase_end],
+                               sector_size - erase_end, false))
+        {
+          ferr("ERROR: flash write failed at 0x%08x",
+               (uintptr_t)(addr + erase_end));
+          return false;
+        }
+    }
+
+  return true;
+}
+
+/****************************************************************************
+ * Name: aligned_flash_erase
+ *
+ * Description:
+ *   Erase a region of flash with proper sector alignment handling.
+ *   This function handles both aligned and unaligned erase operations.
+ *   For unaligned operations, it preserves data outside the erase region
+ *   by reading sectors, erasing them, and writing back the preserved data.
+ *
+ * Input Parameters:
+ *   addr - Start address of the region to erase.
+ *   size - Length of the region to erase in bytes.
+ *
+ * Returned Value:
+ *   true on success; false on failure.
+ *
+ ****************************************************************************/
+
+static bool aligned_flash_erase(size_t addr, size_t size)
+{
+  const size_t sector_size = FLASH_SECTOR_SIZE;
+  const size_t start_addr = ROUND_DOWN(addr, sector_size);
+  const size_t end_addr = ROUND_UP(addr + size, sector_size);
+  const size_t total_len = end_addr - start_addr;
+  size_t current_addr;
+
+  if (IS_ALIGNED(addr, FLASH_SECTOR_SIZE) && \
+      IS_ALIGNED(size, FLASH_SECTOR_SIZE))
+    {
+      /* A single erase operation is enough when all parameters are aligned */
+
+      return esp_flash_erase_region(NULL, addr, size) == OK;
+    }
+
+  finfo("forcing unaligned erase on sector offset: "
+        "0x%08x Length: 0x%x total_len: 0x%x",
+        (uintptr_t)addr, (int)size, total_len);
+
+  current_addr = start_addr;
+
+  while (current_addr < end_addr)
+    {
+      bool preserve_head = (addr > current_addr);
+      bool preserve_tail = ((addr + size) < (current_addr + sector_size));
+
+      if (preserve_head || preserve_tail)
+        {
+          size_t erase_start = preserve_head ? (addr - current_addr) : 0;
+          size_t erase_end =
+            MIN(current_addr + sector_size, addr + size) - current_addr;
+
+          finfo("partial sector erase: 0x%08x to: 0x%08x length: 0x%x",
+                (uintptr_t)(current_addr + erase_start),
+                (uintptr_t)(current_addr + erase_end),
+                erase_end - erase_start);
+
+          if (!erase_partial_sector(current_addr, sector_size, erase_start,
+                                    erase_end))
+            {
+              return false;
+            }
+
+          current_addr += sector_size;
+        }
+      else
+        {
+          /* Full sector erase is safe, erase the next consecutive full
+           * sectors
+           */
+
+          size_t contiguous_size =
+            ROUND_DOWN(addr + size, sector_size) - current_addr;
+
+          finfo("sectors erased from: 0x%08x length: 0x%x",
+                (uintptr_t)current_addr, contiguous_size);
+
+          if (esp_flash_erase_region(
+                NULL, current_addr, contiguous_size) != OK)
+            {
+              ferr("ERROR: flash erase failed at 0x%08x",
+                   (uintptr_t)current_addr);
+              return false;
+            }
+
+          current_addr += contiguous_size;
+        }
+    }
+
+  return true;
+}
+#endif /* CONFIG_ESP_FLASH_ENCRYPTION */
+
 /****************************************************************************
  * Name: spi_flash_op_block_task
  *
@@ -202,15 +601,7 @@ int esp_spiflash_read(uint32_t address, void *buffer,
 {
   int ret = OK;
 
-  if (!esp_flash_encryption_enabled())
-    {
-      ret = esp_flash_read(NULL, buffer, address, length);
-    }
-  else
-    {
-      ret = esp_flash_read_encrypted(NULL, address, buffer, length);
-    }
-
+  ret = flash_esp32_read_check_enc(address, buffer, length);
   if (ret != 0)
     {
       ferr("esp_flash_read failed %d", ret);
@@ -240,19 +631,32 @@ int esp_spiflash_write(uint32_t address, const void 
*buffer,
                        uint32_t length)
 {
   int ret = OK;
+#if CONFIG_ESPRESSIF_SECURE_FLASH_ENC_ENABLED
+  bool erase = false;
+#endif
 
-  if (!esp_flash_encryption_enabled())
+#if CONFIG_ESPRESSIF_SECURE_FLASH_ENC_ENABLED
+  if (esp_flash_encryption_enabled())
     {
-      ret = esp_flash_write(NULL, buffer, address, length);
+      /* Ensuring flash region has been erased before writing in order to
+       * avoid inconsistences when hardware flash encryption is enabled.
+       */
+
+      erase = true;
     }
-  else
+
+  if (!aligned_flash_write(address, buffer, length, erase))
     {
-      ret = esp_flash_write_encrypted(NULL, address, buffer, length);
+      ferr("flash erase before write failed\n");
+      ret = ERROR;
     }
+#else
+    ret = flash_esp32_write_check_enc(address, buffer, length);
+#endif
 
-  if (ret != 0)
+  if (ret != OK)
     {
-      ferr("ERROR: esp_flash_write failed %d", ret);
+      ferr("ERROR: write failed: ret=%d", ret);
       ret = ERROR;
     }
 
@@ -278,8 +682,50 @@ int esp_spiflash_erase(uint32_t address, uint32_t length)
 {
   int ret = OK;
 
+#if CONFIG_ESPRESSIF_SECURE_FLASH_ENC_ENABLED
+  if (!aligned_flash_erase(address, length))
+    {
+      ret = -EIO;
+    }
+
+  if (esp_flash_encryption_enabled())
+    {
+      uint8_t erased_val_buf[FLASH_BUFFER_SIZE];
+      uint32_t bytes_remaining = length;
+      uint32_t offset = address;
+      uint32_t bytes_written = MIN(sizeof(erased_val_buf), length);
+
+      memset(erased_val_buf, FLASH_ERASE_VALUE, sizeof(erased_val_buf));
+
+      /* When hardware flash encryption is enabled, force expected erased
+       * value (0xFF) into flash when erasing a region.
+       * This is handled on this implementation because MCUboot's state
+       * machine relies on erased valued data (0xFF) read from a
+       * previously erased region that was not written yet, however when
+       * hardware flash encryption is enabled, the flash read always
+       * decrypts what's being read from flash, thus a region that was
+       * erased would not be read as what MCUboot expected (0xFF).
+       */
+
+      while (bytes_remaining != 0)
+        {
+          if (!aligned_flash_write(offset, erased_val_buf, bytes_written,
+                                   false))
+            {
+              ferr("ERROR: aligned_flash_write failed during erase\n");
+              ret = ERROR;
+              break;
+            }
+
+          offset += bytes_written;
+          bytes_remaining -= bytes_written;
+        }
+    }
+#else
   ret = esp_flash_erase_region(NULL, address, length);
-  if (ret != 0)
+#endif
+
+  if (ret != OK)
     {
       ferr("ERROR: erase failed: ret=%d", ret);
       ret = ERROR;
diff --git a/arch/risc-v/src/esp32c6/hal_esp32c6.mk 
b/arch/risc-v/src/esp32c6/hal_esp32c6.mk
index 6fa5f7d9119..80f1c99caec 100644
--- a/arch/risc-v/src/esp32c6/hal_esp32c6.mk
+++ b/arch/risc-v/src/esp32c6/hal_esp32c6.mk
@@ -112,7 +112,6 @@ ARCHSCRIPT += 
$(ARCH_SRCDIR)$(DELIM)chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)
 ARCHSCRIPT += 
$(ARCH_SRCDIR)$(DELIM)chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)components$(DELIM)esp_rom$(DELIM)$(CHIP_SERIES)$(DELIM)ld$(DELIM)$(CHIP_SERIES).rom.newlib.ld
 ARCHSCRIPT += 
$(ARCH_SRCDIR)$(DELIM)chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)components$(DELIM)esp_rom$(DELIM)$(CHIP_SERIES)$(DELIM)ld$(DELIM)$(CHIP_SERIES).rom.phy.ld
 ARCHSCRIPT += 
$(ARCH_SRCDIR)$(DELIM)chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)components$(DELIM)esp_rom$(DELIM)$(CHIP_SERIES)$(DELIM)ld$(DELIM)$(CHIP_SERIES).rom.pp.ld
-ARCHSCRIPT += 
$(ARCH_SRCDIR)$(DELIM)chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)components$(DELIM)esp_rom$(DELIM)$(CHIP_SERIES)$(DELIM)ld$(DELIM)$(CHIP_SERIES).rom.spiflash.ld
 ARCHSCRIPT += 
$(ARCH_SRCDIR)$(DELIM)chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)components$(DELIM)esp_rom$(DELIM)$(CHIP_SERIES)$(DELIM)ld$(DELIM)$(CHIP_SERIES).rom.version.ld
 ARCHSCRIPT += 
$(ARCH_SRCDIR)$(DELIM)chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)components$(DELIM)esp_rom$(DELIM)$(CHIP_SERIES)$(DELIM)ld$(DELIM)$(CHIP_SERIES).rom.wdt.ld
 ARCHSCRIPT += 
$(ARCH_SRCDIR)$(DELIM)chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)components$(DELIM)esp_rom$(DELIM)$(CHIP_SERIES)$(DELIM)ld$(DELIM)$(CHIP_SERIES).rom.heap.ld
@@ -122,6 +121,9 @@ ARCHSCRIPT += 
$(ARCH_SRCDIR)$(DELIM)chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)
 ifeq ($(CONFIG_ESPRESSIF_USE_LP_CORE),y)
   ARCHSCRIPT += 
$(TOPDIR)$(DELIM)arch$(DELIM)$(CONFIG_ARCH)$(DELIM)src$(DELIM)board$(DELIM)scripts$(DELIM)ulp_aliases.ld
 endif
+ifeq ($(CONFIG_ESPRESSIF_SPI_FLASH_USE_ROM_CODE),y)
+  ARCHSCRIPT += 
$(ARCH_SRCDIR)$(DELIM)chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)components$(DELIM)esp_rom$(DELIM)$(CHIP_SERIES)$(DELIM)ld$(DELIM)$(CHIP_SERIES).rom.spiflash.ld
+endif
 
 # Source files
 
diff --git a/arch/risc-v/src/esp32h2/hal_esp32h2.mk 
b/arch/risc-v/src/esp32h2/hal_esp32h2.mk
index 9baa02ec277..d4abd2146cf 100644
--- a/arch/risc-v/src/esp32h2/hal_esp32h2.mk
+++ b/arch/risc-v/src/esp32h2/hal_esp32h2.mk
@@ -96,13 +96,15 @@ ARCHSCRIPT += 
$(ARCH_SRCDIR)$(DELIM)chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)
 ARCHSCRIPT += 
$(ARCH_SRCDIR)$(DELIM)chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)components$(DELIM)esp_rom$(DELIM)$(CHIP_SERIES)$(DELIM)ld$(DELIM)$(CHIP_SERIES).rom.ld
 ARCHSCRIPT += 
$(ARCH_SRCDIR)$(DELIM)chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)components$(DELIM)esp_rom$(DELIM)$(CHIP_SERIES)$(DELIM)ld$(DELIM)$(CHIP_SERIES).rom.libgcc.ld
 ARCHSCRIPT += 
$(ARCH_SRCDIR)$(DELIM)chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)components$(DELIM)esp_rom$(DELIM)$(CHIP_SERIES)$(DELIM)ld$(DELIM)$(CHIP_SERIES).rom.newlib.ld
-ARCHSCRIPT += 
$(ARCH_SRCDIR)$(DELIM)chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)components$(DELIM)esp_rom$(DELIM)$(CHIP_SERIES)$(DELIM)ld$(DELIM)$(CHIP_SERIES).rom.spiflash.ld
 ARCHSCRIPT += 
$(ARCH_SRCDIR)$(DELIM)chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)components$(DELIM)esp_rom$(DELIM)$(CHIP_SERIES)$(DELIM)ld$(DELIM)$(CHIP_SERIES).rom.systimer.ld
 ARCHSCRIPT += 
$(ARCH_SRCDIR)$(DELIM)chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)components$(DELIM)esp_rom$(DELIM)$(CHIP_SERIES)$(DELIM)ld$(DELIM)$(CHIP_SERIES).rom.version.ld
 ARCHSCRIPT += 
$(ARCH_SRCDIR)$(DELIM)chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)components$(DELIM)esp_rom$(DELIM)$(CHIP_SERIES)$(DELIM)ld$(DELIM)$(CHIP_SERIES).rom.wdt.ld
 ARCHSCRIPT += 
$(ARCH_SRCDIR)$(DELIM)chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)components$(DELIM)riscv$(DELIM)ld$(DELIM)rom.api.ld
 ARCHSCRIPT += 
$(ARCH_SRCDIR)$(DELIM)chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)components$(DELIM)soc$(DELIM)$(CHIP_SERIES)$(DELIM)ld$(DELIM)$(CHIP_SERIES).peripherals.ld
 ARCHSCRIPT += 
$(ARCH_SRCDIR)$(DELIM)chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)components$(DELIM)esp_rom$(DELIM)$(CHIP_SERIES)$(DELIM)ld$(DELIM)$(CHIP_SERIES).rom.heap.ld
+ifeq ($(CONFIG_ESPRESSIF_SPI_FLASH_USE_ROM_CODE),y)
+  ARCHSCRIPT += 
$(ARCH_SRCDIR)$(DELIM)chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)components$(DELIM)esp_rom$(DELIM)$(CHIP_SERIES)$(DELIM)ld$(DELIM)$(CHIP_SERIES).rom.spiflash.ld
+endif
 
 # Source files
 
diff --git a/tools/espressif/Config.mk b/tools/espressif/Config.mk
index 6d8c1799061..17b1fc68708 100644
--- a/tools/espressif/Config.mk
+++ b/tools/espressif/Config.mk
@@ -101,7 +101,11 @@ ifeq ($(CONFIG_ESPRESSIF_BOOTLOADER_MCUBOOT),y)
 
        APP_IMAGE      := nuttx.bin
        FLASH_APP      := $(APP_OFFSET) $(APP_IMAGE)
+ifeq ($(CONFIG_ESPRESSIF_SECURE_FLASH_ENC_ENABLED),y)
+       IMGTOOL_ALIGN_ARGS := --align 32 --max-align 32
+else
        IMGTOOL_ALIGN_ARGS := --align 4
+endif
        IMGTOOL_SIGN_ARGS  := --pad $(VERIFIED) $(IMGTOOL_ALIGN_ARGS) -v 
$(CONFIG_ESPRESSIF_MCUBOOT_SIGN_IMAGE_VERSION) -s auto \
                -H $(CONFIG_ESPRESSIF_APP_MCUBOOT_HEADER_SIZE) --pad-header \
                -S $(CONFIG_ESPRESSIF_OTA_SLOT_SIZE)

Reply via email to