You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@nuttx.apache.org by ac...@apache.org on 2021/05/23 11:37:37 UTC

[incubator-nuttx] branch master updated: riscv/esp32c3: Support SPI Flash encryption read/write

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

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


The following commit(s) were added to refs/heads/master by this push:
     new 76df958  riscv/esp32c3: Support SPI Flash encryption read/write
76df958 is described below

commit 76df958e34cc5e1cf32a204c3b6ce524eb644496
Author: Dong Heng <do...@espressif.com>
AuthorDate: Tue May 11 15:08:29 2021 +0800

    riscv/esp32c3: Support SPI Flash encryption read/write
---
 arch/risc-v/src/esp32c3/esp32c3_spiflash.c         | 246 ++++++++++++++++++++-
 boards/risc-v/esp32c3/esp32c3-devkit/Kconfig       |  16 ++
 .../esp32c3/esp32c3-devkit/scripts/esp32c3_rom.ld  |   6 +-
 .../esp32c3/esp32c3-devkit/src/esp32c3-devkit.h    |  18 ++
 .../esp32c3/esp32c3-devkit/src/esp32c3_bringup.c   |   5 +
 .../esp32c3/esp32c3-devkit/src/esp32c3_spiflash.c  |   9 +-
 6 files changed, 288 insertions(+), 12 deletions(-)

diff --git a/arch/risc-v/src/esp32c3/esp32c3_spiflash.c b/arch/risc-v/src/esp32c3/esp32c3_spiflash.c
index 96f19ad..41e9810 100644
--- a/arch/risc-v/src/esp32c3/esp32c3_spiflash.c
+++ b/arch/risc-v/src/esp32c3/esp32c3_spiflash.c
@@ -36,13 +36,41 @@
 #include <nuttx/semaphore.h>
 #include <nuttx/mtd/mtd.h>
 
+#include "esp32c3_attr.h"
 #include "esp32c3_spiflash.h"
 #include "rom/esp32c3_spiflash.h"
+#include "hardware/esp32c3_soc.h"
 
 /****************************************************************************
  * Pre-processor Definitions
  ****************************************************************************/
 
+/* RO data page in MMU index */
+
+#define DROM0_PAGES_START           (2)
+#define DROM0_PAGES_END             (128)
+
+/* MMU invalid value */
+
+#define INVALID_MMU_VAL             (0x100)
+
+/* MMU page size */
+
+#define SPI_FLASH_MMU_PAGE_SIZE     (0x10000)
+
+/* MMU base virtual mapped address */
+
+#define VADDR0_START_ADDR           (0x3c020000)
+
+/* Flash MMU table for CPU */
+
+#define MMU_TABLE                   ((volatile uint32_t *)DR_REG_MMU_TABLE)
+
+#define MMU_ADDR2PAGE(_addr)        ((_addr) / SPI_FLASH_MMU_PAGE_SIZE)
+#define MMU_ADDR2OFF(_addr)         ((_addr) % SPI_FLASH_MMU_PAGE_SIZE)
+#define MMU_BYTES2PAGES(_n)         (((_n) + SPI_FLASH_MMU_PAGE_SIZE - 1) / \
+                                     SPI_FLASH_MMU_PAGE_SIZE)
+
 #define SPI_FLASH_BLK_SIZE          256
 #define SPI_FLASH_ERASE_SIZE        4096
 #define SPI_FLASH_SIZE              (4 * 1024 * 1024)
@@ -72,6 +100,37 @@ struct esp32c3_spiflash_s
   const struct spiflash_legacy_data_s **data;
 };
 
+/* SPI Flash map request data */
+
+struct spiflash_map_req_s
+{
+  /* Request mapping SPI Flash base address */
+
+  uint32_t  src_addr;
+
+  /* Request mapping SPI Flash size */
+
+  uint32_t  size;
+
+  /* Mapped memory pointer */
+
+  void      *ptr;
+
+  /* Mapped started MMU page index */
+
+  uint32_t  start_page;
+
+  /* Mapped MMU page count */
+
+  uint32_t  page_cnt;
+};
+
+struct spiflash_cachestate_s
+{
+  irqstate_t flags;
+  uint32_t val;
+};
+
 /****************************************************************************
  * Private Functions Prototypes
  ****************************************************************************/
@@ -104,6 +163,14 @@ static int esp32c3_ioctl(struct mtd_dev_s *dev, int cmd,
                          unsigned long arg);
 
 /****************************************************************************
+ * Public Functions Declaration
+ ****************************************************************************/
+
+extern int cache_invalidate_addr(uint32_t addr, uint32_t size);
+extern uint32_t cache_suspend_icache(void);
+extern void cache_resume_icache(uint32_t val);
+
+/****************************************************************************
  * Public Data
  ****************************************************************************/
 
@@ -155,6 +222,175 @@ static sem_t g_exclsem = SEM_INITIALIZER(1);
  ****************************************************************************/
 
 /****************************************************************************
+ * Name: spiflash_opstart
+ *
+ * Description:
+ *   Prepare for an SPIFLASH operation.
+ *
+ ****************************************************************************/
+
+static inline void spiflash_opstart(struct spiflash_cachestate_s *state)
+{
+  state->flags = enter_critical_section();
+  state->val   = cache_suspend_icache() << 16;
+}
+
+/****************************************************************************
+ * Name: spiflash_opdone
+ *
+ * Description:
+ *   Undo all the steps of opstart.
+ *
+ ****************************************************************************/
+
+static inline void spiflash_opdone(const struct spiflash_cachestate_s *state)
+{
+  cache_resume_icache(state->val >> 16);
+  leave_critical_section(state->flags);
+}
+
+/****************************************************************************
+ * Name: esp32c3_mmap
+ *
+ * Description:
+ *   Mapped SPI Flash address to ESP32-C3's address bus, so that software
+ *   can read SPI Flash data by reading data from memory access.
+ *
+ *   If SPI Flash hardware encryption is enable, the read from mapped
+ *   address is decrypted.
+ *
+ * Input Parameters:
+ *   req - SPI Flash mapping requesting parameters
+ *
+ * Returned Value:
+ *   0 if success or a negative value if fail.
+ *
+ ****************************************************************************/
+
+static int IRAM_ATTR esp32c3_mmap(struct spiflash_map_req_s *req)
+{
+  int ret;
+  int i;
+  int start_page;
+  int flash_page;
+  int page_cnt;
+  uint32_t mapped_addr;
+  struct spiflash_cachestate_s state;
+
+  spiflash_opstart(&state);
+
+  for (start_page = DROM0_PAGES_START;
+       start_page < DROM0_PAGES_END;
+       ++start_page)
+    {
+      if (MMU_TABLE[start_page] == INVALID_MMU_VAL)
+        {
+          break;
+        }
+    }
+
+  flash_page = MMU_ADDR2PAGE(req->src_addr);
+  page_cnt   = MMU_BYTES2PAGES(req->size);
+
+  if (start_page + page_cnt < DROM0_PAGES_END)
+    {
+      mapped_addr = (start_page - DROM0_PAGES_START) *
+                    SPI_FLASH_MMU_PAGE_SIZE +
+                    VADDR0_START_ADDR;
+
+      for (i = 0; i < page_cnt; i++)
+        {
+          MMU_TABLE[start_page + i] = flash_page + i;
+          cache_invalidate_addr(mapped_addr + i * SPI_FLASH_MMU_PAGE_SIZE,
+                                SPI_FLASH_MMU_PAGE_SIZE);
+        }
+
+      req->start_page = start_page;
+      req->page_cnt = page_cnt;
+      req->ptr = (void *)(mapped_addr + MMU_ADDR2OFF(req->src_addr));
+      ret = OK;
+    }
+  else
+    {
+      ret = -ENOBUFS;
+    }
+
+  spiflash_opdone(&state);
+
+  return ret;
+}
+
+/****************************************************************************
+ * Name: esp32c3_ummap
+ *
+ * Description:
+ *   Unmap SPI Flash address in ESP32-C3's address bus, and free resource.
+ *
+ * Input Parameters:
+ *   req - SPI Flash mapping requesting parameters
+ *
+ * Returned Value:
+ *   None.
+ *
+ ****************************************************************************/
+
+static void IRAM_ATTR esp32c3_ummap(const struct spiflash_map_req_s *req)
+{
+  int i;
+  struct spiflash_cachestate_s state;
+
+  spiflash_opstart(&state);
+
+  for (i = req->start_page; i < req->start_page + req->page_cnt; ++i)
+    {
+      MMU_TABLE[i] = INVALID_MMU_VAL;
+    }
+
+  spiflash_opdone(&state);
+}
+
+/****************************************************************************
+ * Name: esp32c3_readdata_encrypted
+ *
+ * Description:
+ *   Read decrypted data from SPI Flash at designated address when
+ *   enable SPI Flash hardware encryption.
+ *
+ * Input Parameters:
+ *   addr   - target address
+ *   buffer - data buffer pointer
+ *   size   - data number
+ *
+ * Returned Value:
+ *   OK if success or a negative value if fail.
+ *
+ ****************************************************************************/
+
+static IRAM_ATTR int esp32c3_readdata_encrypted(uint32_t addr,
+                                                uint8_t *buffer,
+                                                uint32_t size)
+{
+  int ret;
+  struct spiflash_map_req_s req =
+    {
+      .src_addr = addr,
+      .size = size
+    };
+
+  ret = esp32c3_mmap(&req);
+  if (ret < 0)
+    {
+      return ret;
+    }
+
+  memcpy(buffer, req.ptr, size);
+
+  esp32c3_ummap(&req);
+
+  return OK;
+}
+
+/****************************************************************************
  * Name: esp32c3_erase
  *
  * Description:
@@ -359,7 +595,7 @@ static ssize_t esp32c3_read_decrypt(struct mtd_dev_s *dev,
       return ret;
     }
 
-  ret = spi_flash_read_encrypted(offset, buffer, nbytes);
+  ret = esp32c3_readdata_encrypted(offset, buffer, nbytes);
 
   nxsem_post(&g_exclsem);
 
@@ -393,9 +629,9 @@ static ssize_t esp32c3_read_decrypt(struct mtd_dev_s *dev,
  ****************************************************************************/
 
 static ssize_t esp32c3_bread_decrypt(struct mtd_dev_s *dev,
-                                   off_t startblock,
-                                   size_t nblocks,
-                                   uint8_t *buffer)
+                                     off_t startblock,
+                                     size_t nblocks,
+                                     uint8_t *buffer)
 {
   ssize_t ret;
   uint32_t addr = startblock * SPI_FLASH_BLK_SIZE;
@@ -412,7 +648,7 @@ static ssize_t esp32c3_bread_decrypt(struct mtd_dev_s *dev,
       return ret;
     }
 
-  ret = spi_flash_read_encrypted(addr, buffer, size);
+  ret = esp32c3_readdata_encrypted(addr, buffer, size);
 
   nxsem_post(&g_exclsem);
 
diff --git a/boards/risc-v/esp32c3/esp32c3-devkit/Kconfig b/boards/risc-v/esp32c3/esp32c3-devkit/Kconfig
index e26862b..40bd0db 100644
--- a/boards/risc-v/esp32c3/esp32c3-devkit/Kconfig
+++ b/boards/risc-v/esp32c3/esp32c3-devkit/Kconfig
@@ -65,4 +65,20 @@ choice
 
 endchoice
 
+config ESP32C3_SPIFLASH_ENCRYPTION_TEST
+	bool "SPI Flash encryption test"
+	default n
+	depends on ESP32C3_SPIFLASH
+	select DEBUG_ASSERTIONS
+	---help---
+		Enable SPI Flash encryption test. This option will also select
+		DEBUG_ASSERTIONS to enable kernel assert macro.
+
+config ESP32C3_SPIFLASH_TEST_ADDRESS
+	hex "SPI Flash test address"
+	default 0x180000
+	depends on ESP32C3_SPIFLASH_ENCRYPTION_TEST
+	---help---
+		SPI Flash encryption test read/write address.
+
 endif # ARCH_BOARD_ESP32C3_DEVKIT
diff --git a/boards/risc-v/esp32c3/esp32c3-devkit/scripts/esp32c3_rom.ld b/boards/risc-v/esp32c3/esp32c3-devkit/scripts/esp32c3_rom.ld
index 55dc5f3..f282eef 100644
--- a/boards/risc-v/esp32c3/esp32c3-devkit/scripts/esp32c3_rom.ld
+++ b/boards/risc-v/esp32c3/esp32c3-devkit/scripts/esp32c3_rom.ld
@@ -296,7 +296,7 @@ PROVIDE( Cache_Enable_Defalut_ICache_Mode = 0x400004c4 );
 PROVIDE( ROM_Boot_Cache_Init = 0x400004c8 );
 PROVIDE( Cache_Invalidate_ICache_Items = 0x400004cc );
 PROVIDE( Cache_Op_Addr = 0x400004d0 );
-PROVIDE( Cache_Invalidate_Addr = 0x400004d4 );
+PROVIDE( cache_invalidate_addr = 0x400004d4 );
 PROVIDE( Cache_Invalidate_ICache_All = 0x400004d8 );
 PROVIDE( Cache_Mask_All = 0x400004dc );
 PROVIDE( Cache_UnMask_Dram0 = 0x400004e0 );
@@ -316,8 +316,8 @@ PROVIDE( Cache_Lock_Addr = 0x40000514 );
 PROVIDE( Cache_Unlock_Addr = 0x40000518 );
 PROVIDE( Cache_Disable_ICache = 0x4000051c );
 PROVIDE( Cache_Enable_ICache = 0x40000520 );
-PROVIDE( Cache_Suspend_ICache = 0x40000524 );
-PROVIDE( Cache_Resume_ICache = 0x40000528 );
+PROVIDE( cache_suspend_icache = 0x40000524 );
+PROVIDE( cache_resume_icache = 0x40000528 );
 PROVIDE( Cache_Freeze_ICache_Enable = 0x4000052c );
 PROVIDE( Cache_Freeze_ICache_Disable = 0x40000530 );
 PROVIDE( Cache_Pms_Lock = 0x40000534 );
diff --git a/boards/risc-v/esp32c3/esp32c3-devkit/src/esp32c3-devkit.h b/boards/risc-v/esp32c3/esp32c3-devkit/src/esp32c3-devkit.h
index ac4ba6d..7f90352 100644
--- a/boards/risc-v/esp32c3/esp32c3-devkit/src/esp32c3-devkit.h
+++ b/boards/risc-v/esp32c3/esp32c3-devkit/src/esp32c3-devkit.h
@@ -182,6 +182,24 @@ int esp32c3_spiflash_init(void);
 #endif
 
 /****************************************************************************
+ * Name: esp32c3_spiflash_encrypt_test
+ *
+ * Description:
+ *   Test ESP32-C3 SPI Flash driver read/write with encryption.
+ *
+ * Input Parameters:
+ *   None
+ *
+ * Returned Value:
+ *   None.
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_ESP32C3_SPIFLASH_ENCRYPTION_TEST
+void esp32c3_spiflash_encrypt_test(void);
+#endif
+
+/****************************************************************************
  * Name: esp32c3_ledc_setup
  *
  * Description:
diff --git a/boards/risc-v/esp32c3/esp32c3-devkit/src/esp32c3_bringup.c b/boards/risc-v/esp32c3/esp32c3-devkit/src/esp32c3_bringup.c
index 55c4915..405ee9d 100644
--- a/boards/risc-v/esp32c3/esp32c3-devkit/src/esp32c3_bringup.c
+++ b/boards/risc-v/esp32c3/esp32c3-devkit/src/esp32c3_bringup.c
@@ -144,6 +144,11 @@ int esp32c3_bringup(void)
 #endif
 
 #ifdef CONFIG_ESP32C3_SPIFLASH
+
+#  ifdef CONFIG_ESP32C3_SPIFLASH_ENCRYPTION_TEST
+  esp32c3_spiflash_encrypt_test();
+#  endif
+
   ret = esp32c3_spiflash_init();
   if (ret)
     {
diff --git a/boards/risc-v/esp32c3/esp32c3-devkit/src/esp32c3_spiflash.c b/boards/risc-v/esp32c3/esp32c3-devkit/src/esp32c3_spiflash.c
index ea7f1df..17f2402 100644
--- a/boards/risc-v/esp32c3/esp32c3-devkit/src/esp32c3_spiflash.c
+++ b/boards/risc-v/esp32c3/esp32c3-devkit/src/esp32c3_spiflash.c
@@ -26,6 +26,7 @@
 
 #include <sys/mount.h>
 
+#include "inttypes.h"
 #include <stdbool.h>
 #include <stdlib.h>
 #include <stdio.h>
@@ -126,8 +127,8 @@ void esp32c3_spiflash_encrypt_test(void)
   uint32_t erase_nblocks;
   uint32_t rw_block;
   uint32_t rw_nblocks;
-  struct mtd_dev_s *mtd = esp32c3_spiflash_get_mtd();
-  struct mtd_dev_s *enc_mtd = esp32c3_spiflash_encrypt_get_mtd();
+  struct mtd_dev_s *mtd = esp32c3_spiflash_mtd();
+  struct mtd_dev_s *enc_mtd = esp32c3_spiflash_encrypt_mtd();
   const uint32_t address = CONFIG_ESP32C3_SPIFLASH_TEST_ADDRESS;
   const uint32_t size = 4096;
 
@@ -142,14 +143,14 @@ void esp32c3_spiflash_encrypt_test(void)
   wbuf = kmm_malloc(size);
   if (!wbuf)
     {
-      ferr("ERROR: Failed to alloc %d heap\n", size);
+      ferr("ERROR: Failed to alloc %" PRIu32 " heap\n", size);
       DEBUGASSERT(0);
     }
 
   rbuf = kmm_malloc(size);
   if (!rbuf)
     {
-      ferr("ERROR: Failed to alloc %d heap\n", size);
+      ferr("ERROR: Failed to alloc %" PRIu32 " heap\n", size);
       DEBUGASSERT(0);
     }