You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@nuttx.apache.org by ag...@apache.org on 2020/11/13 07:38:11 UTC
[incubator-nuttx] branch master updated: xtensa/esp32: Add SPI
Flash hardware encryption I/O support
This is an automated email from the ASF dual-hosted git repository.
aguettouche 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 bfb5214 xtensa/esp32: Add SPI Flash hardware encryption I/O support
bfb5214 is described below
commit bfb5214ef8a4ac5e32323908c7865782c21912af
Author: Dong Heng <do...@espressif.com>
AuthorDate: Wed Oct 28 17:59:12 2020 +0800
xtensa/esp32: Add SPI Flash hardware encryption I/O support
---
arch/xtensa/src/esp32/esp32_spiflash.c | 806 +++++++++++++++++----
arch/xtensa/src/esp32/esp32_spiflash.h | 16 +
arch/xtensa/src/esp32/hardware/esp32_dport.h | 8 +
arch/xtensa/src/esp32/hardware/esp32_soc.h | 14 +
boards/xtensa/esp32/esp32-core/Kconfig | 16 +
.../xtensa/esp32/esp32-core/scripts/esp32_rom.ld | 1 +
boards/xtensa/esp32/esp32-core/src/esp32-core.h | 20 +
boards/xtensa/esp32/esp32-core/src/esp32_bringup.c | 5 +
.../xtensa/esp32/esp32-core/src/esp32_spiflash.c | 161 ++++
9 files changed, 906 insertions(+), 141 deletions(-)
diff --git a/arch/xtensa/src/esp32/esp32_spiflash.c b/arch/xtensa/src/esp32/esp32_spiflash.c
index eb077c7..95611b5 100644
--- a/arch/xtensa/src/esp32/esp32_spiflash.c
+++ b/arch/xtensa/src/esp32/esp32_spiflash.c
@@ -53,6 +53,14 @@
#define SPI_FLASH_WRITE_BUF_SIZE (32)
#define SPI_FLASH_READ_BUF_SIZE (64)
+#define SPI_FLASH_WRITE_WORDS (SPI_FLASH_WRITE_BUF_SIZE / 4)
+#define SPI_FLASH_READ_WORDS (SPI_FLASH_READ_BUF_SIZE / 4)
+
+#define SPI_FLASH_MAP_PAGE_SIZE (0x10000)
+
+#define SPI_FLASH_ENCRYPT_UNIT_SIZE (32)
+#define SPI_FLASH_ENCRYPT_WORDS (32 / 4)
+
#define ESP32_MTD_OFFSET CONFIG_ESP32_MTD_OFFSET
#define ESP32_MTD_SIZE CONFIG_ESP32_MTD_SIZE
@@ -63,10 +71,26 @@
#define MTD_BLK2SIZE(_priv, _b) (MTD_BLKSIZE(_priv) * (_b))
#define MTD_SIZE2BLK(_priv, _s) ((_s) / MTD_BLKSIZE(_priv))
+#define MMU_ADDR2PAGE(_addr) ((_addr) / SPI_FLASH_MAP_PAGE_SIZE)
+#define MMU_ADDR2OFF(_addr) ((_addr) % SPI_FLASH_MAP_PAGE_SIZE)
+#define MMU_BYTES2PAGES(_n) (((_n) + SPI_FLASH_MAP_PAGE_SIZE - 1) \
+ / SPI_FLASH_MAP_PAGE_SIZE)
+
#ifndef MIN
# define MIN(a, b) (((a) < (b)) ? (a) : (b))
#endif
+#define DPORT_INTERRUPT_DISABLE()
+#define DPORT_INTERRUPT_RESTORE()
+
+/* Flash MMU table for PRO CPU */
+
+#define PRO_MMU_TABLE ((volatile uint32_t *)DPORT_PRO_FLASH_MMU_TABLE_REG)
+
+/* Flash MMU table for APP CPU */
+
+#define APP_MMU_TABLE ((volatile uint32_t *)DPORT_APP_FLASH_MMU_TABLE_REG)
+
/****************************************************************************
* Private Types
****************************************************************************/
@@ -99,6 +123,31 @@ struct esp32_spiflash_s
uint8_t *dummies;
};
+/* SPI Flash map request data */
+
+struct spiflash_map_req
+{
+ /* 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;
+};
+
/****************************************************************************
* ROM function prototypes
****************************************************************************/
@@ -121,7 +170,6 @@ static inline void spi_set_regbits(struct esp32_spiflash_s *priv,
int offset, uint32_t bits);
static inline void spi_reset_regbits(struct esp32_spiflash_s *priv,
int offset, uint32_t bits);
-static inline void IRAM_ATTR spi_memcpy(void *d, const void *s, uint32_t n);
/* Misc. helpers */
@@ -161,12 +209,24 @@ static int esp32_erase(FAR struct mtd_dev_s *dev, off_t startblock,
size_t nblocks);
static ssize_t esp32_read(FAR struct mtd_dev_s *dev, off_t offset,
size_t nbytes, FAR uint8_t *buffer);
+static ssize_t esp32_read_decrypt(FAR struct mtd_dev_s *dev,
+ off_t offset,
+ size_t nbytes,
+ FAR uint8_t *buffer);
static ssize_t esp32_bread(FAR struct mtd_dev_s *dev, off_t startblock,
size_t nblocks, FAR uint8_t *buffer);
+static ssize_t esp32_bread_decrypt(FAR struct mtd_dev_s *dev,
+ off_t startblock,
+ size_t nblocks,
+ FAR uint8_t *buffer);
static ssize_t esp32_write(FAR struct mtd_dev_s *dev, off_t offset,
size_t nbytes, FAR const uint8_t *buffer);
static ssize_t esp32_bwrite(FAR struct mtd_dev_s *dev, off_t startblock,
size_t nblocks, FAR const uint8_t *buffer);
+static ssize_t esp32_bwrite_encrypt(FAR struct mtd_dev_s *dev,
+ off_t startblock,
+ size_t nblocks,
+ FAR const uint8_t *buffer);
static int esp32_ioctl(FAR struct mtd_dev_s *dev, int cmd,
unsigned long arg);
@@ -198,7 +258,26 @@ static struct esp32_spiflash_s g_esp32_spiflash1 =
.dummies = g_rom_spiflash_dummy_len_plus
};
-/* Ensure exclusive access to the driver */
+static struct esp32_spiflash_s g_esp32_spiflash1_encrypt =
+{
+ .mtd =
+ {
+ .erase = esp32_erase,
+ .bread = esp32_bread_decrypt,
+ .bwrite = esp32_bwrite_encrypt,
+ .read = esp32_read_decrypt,
+ .ioctl = esp32_ioctl,
+#ifdef CONFIG_MTD_BYTE_WRITE
+ .write = NULL,
+#endif
+ .name = "esp32_mainflash_encrypt"
+ },
+ .config = &g_esp32_spiflash1_config,
+ .chip = &g_rom_flashchip,
+ .dummies = g_rom_spiflash_dummy_len_plus
+};
+
+/* Enxusre exculisve access to the driver */
static sem_t g_exclsem = SEM_INITIALIZER(1);
@@ -298,35 +377,6 @@ static inline void spi_reset_regbits(struct esp32_spiflash_s *priv,
}
/****************************************************************************
- * Name: spi_memcpy
- *
- * Description:
- * Copy data from one block of memory to another block of memory.
- * The function must be linked in IRAM not in flash, so add this function
- * instead of libc memcpy.
- *
- * Input Parameters:
- * d - destination address
- * s - source address
- * n - data bytes
- *
- * Returned Value:
- * None
- *
- ****************************************************************************/
-
-static inline void IRAM_ATTR spi_memcpy(void *d, const void *s, uint32_t n)
-{
- uint8_t *dest = (uint8_t *)d;
- const uint8_t *src = (const uint8_t *)s;
-
- while (n--)
- {
- *dest++ = *src++;
- }
-}
-
-/****************************************************************************
* Name: esp32_spiflash_opstart
*
* Description:
@@ -719,7 +769,7 @@ static int esp32_write_status(FAR struct esp32_spiflash_s *priv,
*
****************************************************************************/
-static int esp32_enable_write(FAR struct esp32_spiflash_s *priv)
+static int IRAM_ATTR esp32_enable_write(FAR struct esp32_spiflash_s *priv)
{
uint32_t flags;
uint32_t regval;
@@ -772,6 +822,8 @@ static int IRAM_ATTR esp32_erasesector(FAR struct esp32_spiflash_s *priv,
int me;
uint32_t flags;
+ esp32_set_write_opt(priv);
+
if (esp32_wait_idle(priv) != OK)
{
return -EIO;
@@ -807,50 +859,110 @@ static int IRAM_ATTR esp32_erasesector(FAR struct esp32_spiflash_s *priv,
}
/****************************************************************************
- * Name: esp32_writedata
+ * Name: esp32_writeonce
*
* Description:
- * Write data to SPI Flash at designated address.
+ * Write max 32 byte data to SPI Flash at designated address.
+ *
+ * ESP32 can write max 32 byte once transmission by hardware.
*
* Input Parameters:
* spi - ESP32 SPI Flash chip data
* addr - target address
* buffer - data buffer pointer
- * size - data number
+ * size - data number by bytes
*
* Returned Value:
* 0 if success or a negative value if fail.
*
****************************************************************************/
-static int esp32_writedata(FAR struct esp32_spiflash_s *priv, uint32_t addr,
- const uint8_t *buffer, uint32_t size)
+static int IRAM_ATTR esp32_writeonce(FAR struct esp32_spiflash_s *priv,
+ uint32_t addr,
+ const uint32_t *buffer,
+ uint32_t size)
{
uint32_t regval;
uint32_t i;
- uint32_t bytes;
- uint32_t tmp;
- uint32_t res;
- const uint8_t *tmpbuff = buffer;
- int ret = OK;
- int me;
- uint32_t flags;
+
+ if (size > SPI_FLASH_WRITE_BUF_SIZE)
+ {
+ return -EINVAL;
+ }
if (esp32_wait_idle(priv) != OK)
{
return -EIO;
}
- while (size > 0)
+ if (esp32_enable_write(priv) != OK)
{
- flags = esp32_spiflash_opstart(priv, &me);
+ return -EIO;
+ }
- if (esp32_enable_write(priv) != OK)
- {
- esp32_spiflash_opdone(priv, flags, me);
- return -EIO;
- }
+ regval = addr & 0xffffff;
+ regval |= size << ESP_ROM_SPIFLASH_BYTES_LEN;
+ spi_set_reg(priv, SPI_ADDR_OFFSET, regval);
+
+ for (i = 0; i < (size / 4); i++)
+ {
+ spi_set_reg(priv, SPI_W0_OFFSET + i * 4, buffer[i]);
+ }
+
+ if (size & 0x3)
+ {
+ memcpy(®val, &buffer[i], size & 0x3);
+ spi_set_reg(priv, SPI_W0_OFFSET + i * 4, regval);
+ }
+
+ spi_set_reg(priv, SPI_RD_STATUS_OFFSET, 0);
+ spi_set_reg(priv, SPI_CMD_OFFSET, SPI_FLASH_PP);
+ while (spi_get_reg(priv, SPI_CMD_OFFSET) != 0)
+ {
+ ;
+ }
+
+ if (esp32_wait_idle(priv) != OK)
+ {
+ return -EIO;
+ }
+
+ return OK;
+}
+/****************************************************************************
+ * Name: esp32_writedata
+ *
+ * Description:
+ * Write data to SPI Flash at designated address.
+ *
+ * Input Parameters:
+ * spi - ESP32 SPI Flash chip data
+ * addr - target address
+ * buffer - data buffer pointer
+ * size - data number
+ *
+ * Returned Value:
+ * 0 if success or a negative value if fail.
+ *
+ ****************************************************************************/
+
+static int IRAM_ATTR esp32_writedata(FAR struct esp32_spiflash_s *priv,
+ uint32_t addr,
+ const uint8_t *buffer,
+ uint32_t size)
+{
+ int ret;
+ int me;
+ uint32_t flags;
+ uint32_t off = 0;
+ uint32_t bytes;
+ uint32_t tmp_buf[SPI_FLASH_WRITE_WORDS];
+
+ esp32_set_write_opt(priv);
+
+ while (size > 0)
+ {
bytes = MTD_BLKSIZE(priv) - addr % MTD_BLKSIZE(priv) ;
if (!bytes)
{
@@ -862,38 +974,108 @@ static int esp32_writedata(FAR struct esp32_spiflash_s *priv, uint32_t addr,
bytes = MIN(bytes, SPI_FLASH_WRITE_BUF_SIZE);
}
- regval = addr & 0xffffff;
- regval |= bytes << ESP_ROM_SPIFLASH_BYTES_LEN;
- spi_set_reg(priv, SPI_ADDR_OFFSET, regval);
+ memcpy(tmp_buf, &buffer[off], bytes);
- for (i = 0; i < bytes; i += 4)
- {
- res = MIN(4, bytes - i);
+ flags = esp32_spiflash_opstart(priv, &me);
+ ret = esp32_writeonce(priv, addr, tmp_buf, bytes);
+ esp32_spiflash_opdone(priv, flags, me);
- spi_memcpy(&tmp, tmpbuff, res);
- spi_set_reg(priv, SPI_W0_OFFSET + i, tmp);
- tmpbuff += res;
+ if (ret)
+ {
+ return ret;
}
- spi_set_reg(priv, SPI_RD_STATUS_OFFSET, 0);
- spi_set_reg(priv, SPI_CMD_OFFSET, SPI_FLASH_PP);
- while (spi_get_reg(priv, SPI_CMD_OFFSET) != 0)
+ addr += bytes;
+ size -= bytes;
+ off += bytes;
+ }
+
+ return OK;
+}
+
+/****************************************************************************
+ * Name: esp32_writedata
+ *
+ * Description:
+ * Write plaintext data to SPI Flash at designated address by SPI Flash
+ * hardware encryption, and written data in SPI Flash is ciphertext.
+ *
+ * Input Parameters:
+ * spi - ESP32 SPI Flash chip data
+ * addr - target address
+ * buffer - data buffer pointer
+ * size - data number
+ *
+ * Returned Value:
+ * 0 if success or a negative value if fail.
+ *
+ ****************************************************************************/
+
+static int IRAM_ATTR esp32_writedata_encrypted(
+ FAR struct esp32_spiflash_s *priv,
+ uint32_t addr,
+ const uint8_t *buffer,
+ uint32_t size)
+{
+ int i;
+ int blocks;
+ int ret = OK;
+ int me;
+ uint32_t flags;
+ uint32_t tmp_buf[SPI_FLASH_ENCRYPT_WORDS];
+
+ if (addr % SPI_FLASH_ENCRYPT_UNIT_SIZE)
+ {
+ ferr("ERROR: address=0x%x is not %d-byte align\n",
+ addr, SPI_FLASH_ENCRYPT_UNIT_SIZE);
+ return -EINVAL;
+ }
+
+ if (size % SPI_FLASH_ENCRYPT_UNIT_SIZE)
+ {
+ ferr("ERROR: size=%u is not %d-byte align\n",
+ size, SPI_FLASH_ENCRYPT_UNIT_SIZE);
+ return -EINVAL;
+ }
+
+ blocks = size / SPI_FLASH_ENCRYPT_UNIT_SIZE;
+
+ for (i = 0; i < blocks; i++)
+ {
+ memcpy(tmp_buf, buffer, SPI_FLASH_ENCRYPT_UNIT_SIZE);
+
+ flags = esp32_spiflash_opstart(priv, &me);
+ esp_rom_spiflash_write_encrypted_enable();
+
+ ret = esp_rom_spiflash_prepare_encrypted_data(addr, tmp_buf);
+ if (ret)
{
- ;
+ ferr("ERROR: Failed to prepare encrypted data\n");
+ goto exit;
}
- if (esp32_wait_idle(priv) != OK)
+ ret = esp32_writeonce(priv, addr, tmp_buf,
+ SPI_FLASH_ENCRYPT_UNIT_SIZE);
+ if (ret)
{
- esp32_spiflash_opdone(priv, flags, me);
- return -EIO;
+ ferr("ERROR: Failed to write encrypted data @ 0x%x\n", addr);
+ goto exit;
}
- addr += bytes;
- size -= bytes;
-
+ esp_rom_spiflash_write_encrypted_disable();
esp32_spiflash_opdone(priv, flags, me);
+
+ addr += SPI_FLASH_ENCRYPT_UNIT_SIZE;
+ buffer += SPI_FLASH_ENCRYPT_UNIT_SIZE;
+ size -= SPI_FLASH_ENCRYPT_UNIT_SIZE;
}
+ return 0;
+
+exit:
+ esp_rom_spiflash_write_encrypted_disable();
+ esp32_spiflash_opdone(priv, flags, me);
+
return ret;
}
@@ -901,69 +1083,271 @@ static int esp32_writedata(FAR struct esp32_spiflash_s *priv, uint32_t addr,
* Name: esp32_readdata
*
* Description:
- * Read data from SPI Flash at designated address.
+ * Read max 64 byte data data from SPI Flash at designated address.
+ *
+ * ESP32 can read max 64 byte once transmission by hardware.
*
* Input Parameters:
* spi - ESP32 SPI Flash chip data
* addr - target address
* buffer - data buffer pointer
- * size - data number
+ * size - data number by bytes
*
* Returned Value:
* OK if success or a negative value if fail.
*
****************************************************************************/
-static int esp32_readdata(FAR struct esp32_spiflash_s *priv, uint32_t addr,
- uint8_t *buffer, uint32_t size)
+static int IRAM_ATTR esp32_readonce(FAR struct esp32_spiflash_s *priv,
+ uint32_t addr,
+ uint32_t *buffer,
+ uint32_t size)
{
uint32_t regval;
uint32_t i;
- uint32_t bytes;
- uint32_t tmp;
- uint32_t res;
- uint8_t *tmpbuff = buffer;
- int me;
- uint32_t flags;
+
+ if (size > SPI_FLASH_READ_BUF_SIZE)
+ {
+ return -EINVAL;
+ }
if (esp32_wait_idle(priv) != OK)
{
return -EIO;
}
- while (size > 0)
+ regval = ((size << 3) - 1) << SPI_USR_MISO_DBITLEN_S;
+ spi_set_reg(priv, SPI_MISO_DLEN_OFFSET, regval);
+
+ regval = addr << 8;
+ spi_set_reg(priv, SPI_ADDR_OFFSET, regval);
+
+ spi_set_reg(priv, SPI_RD_STATUS_OFFSET, 0);
+ spi_set_reg(priv, SPI_CMD_OFFSET, SPI_USR);
+ while (spi_get_reg(priv, SPI_CMD_OFFSET) != 0)
{
- flags = esp32_spiflash_opstart(priv, &me);
+ ;
+ }
+
+ for (i = 0; i < (size / 4); i++)
+ {
+ buffer[i] = spi_get_reg(priv, SPI_W0_OFFSET + i * 4);
+ }
+
+ if (size & 0x3)
+ {
+ regval = spi_get_reg(priv, SPI_W0_OFFSET + i * 4);
+ memcpy(&buffer[i], ®val, size & 0x3);
+ }
+
+ return OK;
+}
+/****************************************************************************
+ * Name: esp32_readdata
+ *
+ * Description:
+ * Read data from SPI Flash at designated address.
+ *
+ * Input Parameters:
+ * spi - ESP32 SPI Flash chip data
+ * addr - target address
+ * buffer - data buffer pointer
+ * size - data number
+ *
+ * Returned Value:
+ * OK if success or a negative value if fail.
+ *
+ ****************************************************************************/
+
+static int IRAM_ATTR esp32_readdata(FAR struct esp32_spiflash_s *priv,
+ uint32_t addr,
+ uint8_t *buffer,
+ uint32_t size)
+{
+ int ret;
+ int me;
+ uint32_t flags;
+ uint32_t off = 0;
+ uint32_t bytes;
+ uint32_t tmp_buf[SPI_FLASH_READ_WORDS];
+
+ while (size > 0)
+ {
bytes = MIN(size, SPI_FLASH_READ_BUF_SIZE);
- regval = ((bytes << 3) - 1) << SPI_USR_MISO_DBITLEN_S;
- spi_set_reg(priv, SPI_MISO_DLEN_OFFSET, regval);
- regval = addr << 8;
- spi_set_reg(priv, SPI_ADDR_OFFSET, regval);
+ flags = esp32_spiflash_opstart(priv, &me);
+ ret = esp32_readonce(priv, addr, tmp_buf, bytes);
+ esp32_spiflash_opdone(priv, flags, me);
- spi_set_reg(priv, SPI_RD_STATUS_OFFSET, 0);
- spi_set_reg(priv, SPI_CMD_OFFSET, SPI_USR);
- while (spi_get_reg(priv, SPI_CMD_OFFSET) != 0)
+ if (ret)
{
- ;
+ return ret;
}
- for (i = 0; i < bytes; i += 4)
+ memcpy(&buffer[off], tmp_buf, bytes);
+
+ addr += bytes;
+ size -= bytes;
+ off += bytes;
+ }
+
+ return OK;
+}
+
+/****************************************************************************
+ * Name: esp32_mmap
+ *
+ * Description:
+ * Mapped SPI Flash address to ESP32'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:
+ * spi - ESP32 SPI Flash chip data
+ * req - SPI Flash mapping requesting parameters
+ *
+ * Returned Value:
+ * 0 if success or a negative value if fail.
+ *
+ ****************************************************************************/
+
+static int IRAM_ATTR esp32_mmap(FAR struct esp32_spiflash_s *priv,
+ struct spiflash_map_req *req)
+{
+ int ret;
+ int i;
+ int me;
+ int start_page;
+ int flash_page;
+ int page_cnt;
+ uint32_t flags;
+
+ flags = esp32_spiflash_opstart(priv, &me);
+
+ for (start_page = DROM0_PAGES_START;
+ start_page < DROM0_PAGES_END;
+ ++start_page)
+ {
+ if (PRO_MMU_TABLE[start_page] == INVALID_MMU_VAL
+#ifdef CONFIG_SMP
+ && APP_MMU_TABLE[start_page] == INVALID_MMU_VAL
+#endif
+ )
{
- res = MIN(4, bytes - i);
+ break;
+ }
+ }
- tmp = spi_get_reg(priv, SPI_W0_OFFSET + i);
- spi_memcpy(tmpbuff, &tmp, res);
- tmpbuff += res;
+ flash_page = MMU_ADDR2PAGE(req->src_addr);
+ page_cnt = MMU_BYTES2PAGES(req->size);
+
+ if (start_page + page_cnt < DROM0_PAGES_END)
+ {
+ for (i = 0; i < page_cnt; i++)
+ {
+ PRO_MMU_TABLE[start_page + i] = flash_page + i;
+#ifdef CONFIG_SMP
+ APP_MMU_TABLE[start_page + i] = flash_page + i;
+#endif
}
- addr += bytes;
- size -= bytes;
+ req->start_page = start_page;
+ req->page_cnt = page_cnt;
+ req->ptr = (void *)(VADDR0_START_ADDR +
+ start_page * SPI_FLASH_MAP_PAGE_SIZE +
+ MMU_ADDR2OFF(req->src_addr));
- esp32_spiflash_opdone(priv, flags, me);
+ ret = 0;
+ }
+ else
+ {
+ ret = -ENOBUFS;
+ }
+
+ esp32_spiflash_opdone(priv, flags, me);
+
+ return ret;
+}
+
+/****************************************************************************
+ * Name: esp32_ummap
+ *
+ * Description:
+ * Unmap SPI Flash address in ESP32's address bus, and free resource.
+ *
+ * Input Parameters:
+ * spi - ESP32 SPI Flash chip data
+ * req - SPI Flash mapping requesting paramters
+ *
+ * Returned Value:
+ * None.
+ *
+ ****************************************************************************/
+
+static void IRAM_ATTR esp32_ummap(FAR struct esp32_spiflash_s *priv,
+ const struct spiflash_map_req *req)
+{
+ uint32_t flags;
+ int me;
+ int i;
+
+ flags = esp32_spiflash_opstart(priv, &me);
+
+ for (i = req->start_page; i < req->start_page + req->page_cnt; ++i)
+ {
+ PRO_MMU_TABLE[i] = INVALID_MMU_VAL;
+#ifdef CONFIG_SMP
+ APP_MMU_TABLE[i] = INVALID_MMU_VAL;
+#endif
}
+ esp32_spiflash_opdone(priv, flags, me);
+}
+
+/****************************************************************************
+ * Name: esp32_readdata_encrypted
+ *
+ * Description:
+ * Read decrypted data from SPI Flash at designated address when
+ * enable SPI Flash hardware encryption.
+ *
+ * Input Parameters:
+ * spi - ESP32 SPI Flash chip data
+ * addr - target address
+ * buffer - data buffer pointer
+ * size - data number
+ *
+ * Returned Value:
+ * OK if success or a negative value if fail.
+ *
+ ****************************************************************************/
+
+static int IRAM_ATTR esp32_readdata_encrypted(
+ FAR struct esp32_spiflash_s *priv,
+ uint32_t addr,
+ uint8_t *buffer,
+ uint32_t size)
+{
+ int ret;
+ struct spiflash_map_req req =
+ {
+ .src_addr = addr,
+ .size = size
+ };
+
+ ret = esp32_mmap(priv, &req);
+ if (ret)
+ {
+ return ret;
+ }
+
+ memcpy(buffer, req.ptr, size);
+
+ esp32_ummap(priv, &req);
+
return OK;
}
@@ -1006,7 +1390,6 @@ static int esp32_erase(FAR struct mtd_dev_s *dev, off_t startblock,
return ret;
}
- esp32_set_write_opt(priv);
ret = esp32_erasesector(priv, addr, size);
nxsem_post(&g_exclsem);
@@ -1044,24 +1427,12 @@ static ssize_t esp32_read(FAR struct mtd_dev_s *dev, off_t offset,
size_t nbytes, FAR uint8_t *buffer)
{
int ret;
- uint8_t *tmpbuff = buffer;
FAR struct esp32_spiflash_s *priv = MTD2PRIV(dev);
#ifdef CONFIG_ESP32_SPIFLASH_DEBUG
finfo("esp32_read(%p, 0x%x, %d, %p)\n", dev, offset, nbytes, buffer);
#endif
-#ifdef CONFIG_XTENSA_USE_SEPARATE_IMEM
- if (esp32_ptr_extram(buffer))
- {
- tmpbuff = xtensa_imm_malloc(nbytes);
- if (tmpbuff == NULL)
- {
- return (ssize_t)-ENOMEM;
- }
- }
-#endif
-
/* Acquire the semaphore. */
ret = nxsem_wait(&g_exclsem);
@@ -1071,7 +1442,7 @@ static ssize_t esp32_read(FAR struct mtd_dev_s *dev, off_t offset,
}
esp32_set_read_opt(priv);
- ret = esp32_readdata(priv, offset, tmpbuff, nbytes);
+ ret = esp32_readdata(priv, offset, buffer, nbytes);
nxsem_post(&g_exclsem);
@@ -1085,13 +1456,6 @@ static ssize_t esp32_read(FAR struct mtd_dev_s *dev, off_t offset,
#endif
error_with_buffer:
-#ifdef CONFIG_XTENSA_USE_SEPARATE_IMEM
- if (esp32_ptr_extram(buffer))
- {
- memcpy(buffer, tmpbuff, (ret == OK) ? nbytes : 0);
- xtensa_imm_free(tmpbuff);
- }
-#endif
return (ssize_t)ret;
}
@@ -1140,6 +1504,109 @@ static ssize_t esp32_bread(FAR struct mtd_dev_s *dev, off_t startblock,
}
/****************************************************************************
+ * Name: esp32_read_decrypt
+ *
+ * Description:
+ * Read encrypted data and decrypt automatically from SPI Flash
+ * at designated address.
+ *
+ * Input Parameters:
+ * dev - ESP32 MTD device data
+ * offset - target address offset
+ * nbytes - data number
+ * buffer - data buffer pointer
+ *
+ * Returned Value:
+ * Read data bytes if success or a negative value if fail.
+ *
+ ****************************************************************************/
+
+static ssize_t esp32_read_decrypt(FAR struct mtd_dev_s *dev,
+ off_t offset,
+ size_t nbytes,
+ FAR uint8_t *buffer)
+{
+ int ret;
+ uint8_t *tmpbuff = buffer;
+ FAR struct esp32_spiflash_s *priv = MTD2PRIV(dev);
+
+#ifdef CONFIG_ESP32_SPIFLASH_DEBUG
+ finfo("esp32_read_decrypt(%p, 0x%x, %d, %p)\n",
+ dev, offset, nbytes, buffer);
+#endif
+
+ /* Acquire the semaphore. */
+
+ ret = nxsem_wait(&g_exclsem);
+ if (ret < 0)
+ {
+ goto error_with_buffer;
+ }
+
+ ret = esp32_readdata_encrypted(priv, offset, tmpbuff, nbytes);
+
+ nxsem_post(&g_exclsem);
+
+ if (ret == OK)
+ {
+ ret = nbytes;
+ }
+
+#ifdef CONFIG_ESP32_SPIFLASH_DEBUG
+ finfo("esp32_read_decrypt()=%d\n", ret);
+#endif
+
+error_with_buffer:
+
+ return (ssize_t)ret;
+}
+
+/****************************************************************************
+ * Name: esp32_bread_decrypt
+ *
+ * Description:
+ * Read encrypted data and decrypt automatically from designated blocks.
+ *
+ * Input Parameters:
+ * dev - ESP32 MTD device data
+ * startblock - start block number, it is not equal to SPI Flash's block
+ * nblocks - blocks number
+ * buffer - data buffer pointer
+ *
+ * Returned Value:
+ * Read block number if success or a negative value if fail.
+ *
+ ****************************************************************************/
+
+static ssize_t esp32_bread_decrypt(FAR struct mtd_dev_s *dev,
+ off_t startblock,
+ size_t nblocks,
+ FAR uint8_t *buffer)
+{
+ int ret;
+ FAR struct esp32_spiflash_s *priv = MTD2PRIV(dev);
+ uint32_t addr = MTD_BLK2SIZE(priv, startblock);
+ uint32_t size = MTD_BLK2SIZE(priv, nblocks);
+
+#ifdef CONFIG_ESP32_SPIFLASH_DEBUG
+ finfo("esp32_bread_decrypt(%p, 0x%x, %d, %p)\n",
+ dev, startblock, nblocks, buffer);
+#endif
+
+ ret = esp32_read_decrypt(dev, addr, size, buffer);
+ if (ret == size)
+ {
+ ret = nblocks;
+ }
+
+#ifdef CONFIG_ESP32_SPIFLASH_DEBUG
+ finfo("esp32_bread_decrypt()=%d\n", ret);
+#endif
+
+ return ret;
+}
+
+/****************************************************************************
* Name: esp32_write
*
* Description:
@@ -1160,7 +1627,6 @@ static ssize_t esp32_write(FAR struct mtd_dev_s *dev, off_t offset,
size_t nbytes, FAR const uint8_t *buffer)
{
int ret;
- uint8_t *tmpbuff = (uint8_t *)buffer;
FAR struct esp32_spiflash_s *priv = MTD2PRIV(dev);
ASSERT(buffer);
@@ -1170,19 +1636,6 @@ static ssize_t esp32_write(FAR struct mtd_dev_s *dev, off_t offset,
return -EINVAL;
}
-#ifdef CONFIG_XTENSA_USE_SEPARATE_IMEM
- if (esp32_ptr_extram(buffer))
- {
- tmpbuff = xtensa_imm_malloc(nbytes);
- if (tmpbuff == NULL)
- {
- return (ssize_t)-ENOMEM;
- }
-
- memcpy(tmpbuff, buffer, nbytes);
- }
-#endif
-
#ifdef CONFIG_ESP32_SPIFLASH_DEBUG
finfo("esp32_write(%p, 0x%x, %d, %p)\n", dev, offset, nbytes, buffer);
#endif
@@ -1195,8 +1648,7 @@ static ssize_t esp32_write(FAR struct mtd_dev_s *dev, off_t offset,
goto error_with_buffer;
}
- esp32_set_write_opt(priv);
- ret = esp32_writedata(priv, offset, tmpbuff, nbytes);
+ ret = esp32_writedata(priv, offset, buffer, nbytes);
nxsem_post(&g_exclsem);
@@ -1210,12 +1662,6 @@ static ssize_t esp32_write(FAR struct mtd_dev_s *dev, off_t offset,
#endif
error_with_buffer:
-#ifdef CONFIG_XTENSA_USE_SEPARATE_IMEM
- if (esp32_ptr_extram(buffer))
- {
- xtensa_imm_free(tmpbuff);
- }
-#endif
return (ssize_t)ret;
}
@@ -1265,6 +1711,63 @@ static ssize_t esp32_bwrite(FAR struct mtd_dev_s *dev, off_t startblock,
}
/****************************************************************************
+ * Name: esp32_bwrite_encrypt
+ *
+ * Description:
+ * Write data to designated blocks by SPI Flash hardware encryption.
+ *
+ * Input Parameters:
+ * dev - ESP32 MTD device data
+ * startblock - start MTD block number,
+ * it is not equal to SPI Flash's block
+ * nblocks - blocks number
+ * buffer - data buffer pointer
+ *
+ * Returned Value:
+ * Writen block number if success or a negative value if fail.
+ *
+ ****************************************************************************/
+
+static ssize_t esp32_bwrite_encrypt(FAR struct mtd_dev_s *dev,
+ off_t startblock,
+ size_t nblocks,
+ FAR const uint8_t *buffer)
+{
+ ssize_t ret;
+ FAR struct esp32_spiflash_s *priv = MTD2PRIV(dev);
+ uint32_t addr = MTD_BLK2SIZE(priv, startblock);
+ uint32_t size = MTD_BLK2SIZE(priv, nblocks);
+
+#ifdef CONFIG_ESP32_SPIFLASH_DEBUG
+ finfo("esp32_bwrite_encrypt(%p, 0x%x, %d, %p)\n",
+ dev, startblock, nblocks, buffer);
+#endif
+
+ ret = nxsem_wait(&g_exclsem);
+ if (ret < 0)
+ {
+ goto error_with_buffer;
+ }
+
+ ret = esp32_writedata_encrypted(priv, addr, buffer, size);
+
+ nxsem_post(&g_exclsem);
+
+ if (ret == OK)
+ {
+ ret = nblocks;
+ }
+
+#ifdef CONFIG_ESP32_SPIFLASH_DEBUG
+ finfo("esp32_bwrite_encrypt()=%d\n", ret);
+#endif
+
+error_with_buffer:
+
+ return ret;
+}
+
+/****************************************************************************
* Name: esp32_ioctl
*
* Description:
@@ -1398,4 +1901,25 @@ FAR struct mtd_dev_s *esp32_spiflash_get_mtd(void)
return &priv->mtd;
}
+/****************************************************************************
+ * Name: esp32_spiflash_get_mtd
+ *
+ * Description:
+ * Get ESP32 SPI Flash encryption raw MTD.
+ *
+ * Input Parameters:
+ * None
+ *
+ * Returned Value:
+ * ESP32 SPI Flash encryption raw MTD data pointer.
+ *
+ ****************************************************************************/
+
+FAR struct mtd_dev_s *esp32_spiflash_encrypt_get_mtd(void)
+{
+ struct esp32_spiflash_s *priv = &g_esp32_spiflash1_encrypt;
+
+ return &priv->mtd;
+}
+
#endif /* CONFIG_ESP32_SPIFLASH */
diff --git a/arch/xtensa/src/esp32/esp32_spiflash.h b/arch/xtensa/src/esp32/esp32_spiflash.h
index 1b3702d..3c9099a 100644
--- a/arch/xtensa/src/esp32/esp32_spiflash.h
+++ b/arch/xtensa/src/esp32/esp32_spiflash.h
@@ -78,6 +78,22 @@ FAR struct mtd_dev_s *esp32_spiflash_alloc_mtdpart(void);
FAR struct mtd_dev_s *esp32_spiflash_get_mtd(void);
+/****************************************************************************
+ * Name: esp32_spiflash_get_mtd
+ *
+ * Description:
+ * Get ESP32 SPI Flash encryption raw MTD.
+ *
+ * Input Parameters:
+ * None
+ *
+ * Returned Value:
+ * ESP32 SPI Flash encryption raw MTD data pointer.
+ *
+ ****************************************************************************/
+
+FAR struct mtd_dev_s *esp32_spiflash_encrypt_get_mtd(void);
+
#ifdef __cplusplus
}
#endif
diff --git a/arch/xtensa/src/esp32/hardware/esp32_dport.h b/arch/xtensa/src/esp32/hardware/esp32_dport.h
index f81b6de..d5a74be 100644
--- a/arch/xtensa/src/esp32/hardware/esp32_dport.h
+++ b/arch/xtensa/src/esp32/hardware/esp32_dport.h
@@ -4387,4 +4387,12 @@
#define DPORT_DATE_S 0
#define DPORT_DPORT_DATE_VERSION 0x1605190
+/* SPI Flash MMU table regitser base address for PRO CPU */
+
+#define DPORT_PRO_FLASH_MMU_TABLE_REG (DR_REG_DPORT_BASE + 0x10000)
+
+/* SPI Flash MMU table regitser base address for APP CPU */
+
+#define DPORT_APP_FLASH_MMU_TABLE_REG (DR_REG_DPORT_BASE + 0x12000)
+
#endif /* __ARCH_XTENSA_SRC_ESP32_HARDWARE_ESP32_DPORT_H */
diff --git a/arch/xtensa/src/esp32/hardware/esp32_soc.h b/arch/xtensa/src/esp32/hardware/esp32_soc.h
index 2109315..214108e 100644
--- a/arch/xtensa/src/esp32/hardware/esp32_soc.h
+++ b/arch/xtensa/src/esp32/hardware/esp32_soc.h
@@ -275,6 +275,11 @@
#define SOC_EXTRAM_DATA_LOW 0x3f800000
#define SOC_EXTRAM_DATA_HIGH 0x3fc00000
+/* Virtual address 0 */
+
+#define VADDR0_START_ADDR SOC_DROM_LOW
+#define VADDR0_END_ADDR (SOC_DROM_HIGH - 1)
+
/* Interrupt hardware source table
* This table is decided by hardware, don't touch this.
*/
@@ -776,6 +781,15 @@ extern int rom_i2c_writeReg(int block, int block_id, int reg_add,
#define FE2_TX_INF_FORCE_PD_V 1
#define FE2_TX_INF_FORCE_PD_S 9
+/* RO data page in MMU index */
+
+#define DROM0_PAGES_START 0
+#define DROM0_PAGES_END 64
+
+/* MMU invaild value */
+
+#define INVALID_MMU_VAL 0x100
+
/****************************************************************************
* Inline Functions
****************************************************************************/
diff --git a/boards/xtensa/esp32/esp32-core/Kconfig b/boards/xtensa/esp32/esp32-core/Kconfig
index e6a5e29..9a42a5d 100644
--- a/boards/xtensa/esp32/esp32-core/Kconfig
+++ b/boards/xtensa/esp32/esp32-core/Kconfig
@@ -63,6 +63,22 @@ choice
depends on FS_LITTLEFS
endchoice
+config ESP32_SPIFLASH_ENCRYPTION_TEST
+ bool "SPI Flash encryption test"
+ default n
+ depends on ESP32_SPIFLASH
+ select DEBUG_ASSERTIONS
+ help
+ Enable SPI Flash encryption test. This option will also select
+ DEBUG_ASSERTIONS to enable kernel assert macro.
+
+config ESP32_SPIFLASH_TEST_ADDRESS
+ hex "SPI Flash test address"
+ default 0x180000
+ depends on ESP32_SPIFLASH_ENCRYPTION_TEST
+ help
+ SPI Flash encryption test read/write address.
+
if PM
config PM_ALARM_SEC
diff --git a/boards/xtensa/esp32/esp32-core/scripts/esp32_rom.ld b/boards/xtensa/esp32/esp32-core/scripts/esp32_rom.ld
index 870c405..306f4ef 100644
--- a/boards/xtensa/esp32/esp32-core/scripts/esp32_rom.ld
+++ b/boards/xtensa/esp32/esp32-core/scripts/esp32_rom.ld
@@ -1851,6 +1851,7 @@ PROVIDE ( g_rom_flashchip = 0x3ffae270 );
PROVIDE ( g_rom_spiflash_dummy_len_plus = 0x3ffae290 );
PROVIDE ( esp_rom_spiflash_read_user_cmd = 0x400621b0 );
PROVIDE ( esp_rom_spiflash_write_encrypted_enable = 0x40062df4 );
+PROVIDE ( esp_rom_spiflash_write_encrypted_disable = 0x40062e60 );
PROVIDE ( esp_rom_spiflash_prepare_encrypted_data = 0x40062e1c );
PROVIDE ( esp_rom_printf = ets_printf );
diff --git a/boards/xtensa/esp32/esp32-core/src/esp32-core.h b/boards/xtensa/esp32/esp32-core/src/esp32-core.h
index 0bce83f..3627b23 100644
--- a/boards/xtensa/esp32/esp32-core/src/esp32-core.h
+++ b/boards/xtensa/esp32/esp32-core/src/esp32-core.h
@@ -118,5 +118,25 @@ int esp32_timer_driver_init(void);
int esp32_wtd_driver_init(void);
#endif
+/****************************************************************************
+ * Name: esp32_spiflash_encrypt_test
+ *
+ * Description:
+ * Test ESP32 SPI Flash driver read/write with encryption.
+ *
+ * Input Parameters:
+ * None
+ *
+ * Returned Value:
+ * None.
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_ESP32_SPIFLASH_ENCRYPTION_TEST
+
+void esp32_spiflash_encrypt_test(void);
+
+#endif
+
#endif /* __ASSEMBLY__ */
#endif /* __BOARDS_XTENSA_ESP32_ESP32_CORE_SRC_ESP32_CORE_H */
diff --git a/boards/xtensa/esp32/esp32-core/src/esp32_bringup.c b/boards/xtensa/esp32/esp32-core/src/esp32_bringup.c
index c337c06..867ac4a 100644
--- a/boards/xtensa/esp32/esp32-core/src/esp32_bringup.c
+++ b/boards/xtensa/esp32/esp32-core/src/esp32_bringup.c
@@ -162,6 +162,11 @@ int esp32_bringup(void)
#endif
#ifdef CONFIG_ESP32_SPIFLASH
+
+#ifdef CONFIG_ESP32_SPIFLASH_ENCRYPTION_TEST
+ esp32_spiflash_encrypt_test();
+#endif
+
ret = esp32_spiflash_init();
if (ret)
{
diff --git a/boards/xtensa/esp32/esp32-core/src/esp32_spiflash.c b/boards/xtensa/esp32/esp32-core/src/esp32_spiflash.c
index 3ac6ca6..7407117 100644
--- a/boards/xtensa/esp32/esp32-core/src/esp32_spiflash.c
+++ b/boards/xtensa/esp32/esp32-core/src/esp32_spiflash.c
@@ -99,3 +99,164 @@ int esp32_spiflash_init(void)
return ret;
}
+/****************************************************************************
+ * Name: esp32_spiflash_encrypt_test
+ *
+ * Description:
+ * Test ESP32 SPI Flash driver read/write with encryption.
+ *
+ * Input Parameters:
+ * None
+ *
+ * Returned Value:
+ * None.
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_ESP32_SPIFLASH_ENCRYPTION_TEST
+
+void esp32_spiflash_encrypt_test(void)
+{
+ int i;
+ int ret;
+ uint8_t *wbuf;
+ uint8_t *rbuf;
+ struct mtd_geometry_s geo;
+ uint32_t erase_block;
+ uint32_t erase_nblocks;
+ uint32_t rw_block;
+ uint32_t rw_nblocks;
+ struct mtd_dev_s *mtd = esp32_spiflash_get_mtd();
+ struct mtd_dev_s *enc_mtd = esp32_spiflash_encrypt_get_mtd();
+ const uint32_t address = CONFIG_ESP32_SPIFLASH_TEST_ADDRESS;
+ const uint32_t size = 4096;
+
+ ret = MTD_IOCTL(enc_mtd, MTDIOC_GEOMETRY,
+ (unsigned long)(uintptr_t)&geo);
+ if (ret < 0)
+ {
+ ferr("ERROR: Failed to get GEO errno =%d\n", ret);
+ DEBUGASSERT(0);
+ }
+
+ wbuf = kmm_malloc(size);
+ if (!wbuf)
+ {
+ ferr("ERROR: Failed to alloc %d heap\n", size);
+ DEBUGASSERT(0);
+ }
+
+ rbuf = kmm_malloc(size);
+ if (!rbuf)
+ {
+ ferr("ERROR: Failed to alloc %d heap\n", size);
+ DEBUGASSERT(0);
+ }
+
+ for (i = 0; i < size; i++)
+ {
+ wbuf[i] = (uint8_t)random();
+ }
+
+ erase_block = address / geo.erasesize;
+ erase_nblocks = size / geo.erasesize;
+
+ rw_block = address / geo.blocksize;
+ rw_nblocks = size / geo.blocksize;
+
+ ret = MTD_ERASE(enc_mtd, erase_block, erase_nblocks);
+ if (ret != erase_nblocks)
+ {
+ ferr("ERROR: Failed to erase block errno=%d\n", ret);
+ DEBUGASSERT(0);
+ }
+
+ ret = MTD_BWRITE(enc_mtd, rw_block, rw_nblocks, wbuf);
+ if (ret != rw_nblocks)
+ {
+ ferr("ERROR: Failed to encrypt write errno=%d\n", ret);
+ DEBUGASSERT(0);
+ }
+
+ memset(rbuf, 0, size);
+ ret = MTD_BREAD(enc_mtd, rw_block, rw_nblocks, rbuf);
+ if (ret != rw_nblocks)
+ {
+ ferr("ERROR: Failed to decrypt read errno=%d\n", ret);
+ DEBUGASSERT(0);
+ }
+
+ if (memcmp(wbuf, rbuf, size))
+ {
+ ferr("ASSERT: Encrypted and decrypted data is not same\n");
+ DEBUGASSERT(0);
+ }
+
+ memset(rbuf, 0, size);
+ ret = MTD_BREAD(mtd, rw_block, rw_nblocks, rbuf);
+ if (ret != rw_nblocks)
+ {
+ ferr("ERROR: Failed to read errno=%d\n", ret);
+ DEBUGASSERT(0);
+ }
+
+ if (!memcmp(wbuf, rbuf, size))
+ {
+ ferr("ASSERT: Encrypted and normal data is same\n");
+ DEBUGASSERT(0);
+ }
+
+ for (i = 0; i < size; i++)
+ {
+ wbuf[i] = (uint8_t)random();
+ }
+
+ ret = MTD_ERASE(enc_mtd, erase_block, erase_nblocks);
+ if (ret != erase_nblocks)
+ {
+ ferr("ERROR: Failed to erase errno=%d\n", ret);
+ DEBUGASSERT(0);
+ }
+
+ ret = MTD_BWRITE(mtd, rw_block, rw_nblocks, wbuf);
+ if (ret != rw_nblocks)
+ {
+ ferr("ERROR: Failed to write errno=%d\n", ret);
+ DEBUGASSERT(0);
+ }
+
+ memset(rbuf, 0, size);
+ ret = MTD_BREAD(enc_mtd, rw_block, rw_nblocks, rbuf);
+ if (ret != rw_nblocks)
+ {
+ ferr("ERROR: Failed to decrypt read errno=%d\n", ret);
+ DEBUGASSERT(0);
+ }
+
+ if (!memcmp(wbuf, rbuf, size))
+ {
+ ferr("ASSERT: Normal and decrypted data is same\n");
+ DEBUGASSERT(0);
+ }
+
+ memset(rbuf, 0, size);
+ ret = MTD_BREAD(mtd, rw_block, rw_nblocks, rbuf);
+ if (ret != rw_nblocks)
+ {
+ ferr("ERROR: Failed to read errno=%d\n", ret);
+ DEBUGASSERT(0);
+ }
+
+ if (memcmp(wbuf, rbuf, size))
+ {
+ ferr("ASSERT: Normal and normal data is not same\n");
+ DEBUGASSERT(0);
+ }
+
+ kmm_free(wbuf);
+ kmm_free(rbuf);
+
+ finfo("INFO: ESP32 SPI Flash encryption test successfully\n");
+}
+
+#endif /* CONFIG_ESP32_SPIFLASH_ENCRYPTION_TEST */