diff --git a/arch/xtensa/src/esp32s3/esp32s3_spiflash.c b/arch/xtensa/src/esp32s3/esp32s3_spiflash.c index 5378beee594..01b66cc3f97 100644 --- a/arch/xtensa/src/esp32s3/esp32s3_spiflash.c +++ b/arch/xtensa/src/esp32s3/esp32s3_spiflash.c @@ -41,10 +41,65 @@ #include "esp32s3_spiflash.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) + /**************************************************************************** * Private Types ****************************************************************************/ +/* 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; +}; + /* Structure holding SPI flash access critical sections management * functions. */ @@ -83,6 +138,7 @@ static void spiflash_end(void); extern void spi_flash_guard_set(const struct spiflash_guard_funcs_s *funcs); extern uint32_t cache_suspend_icache(void); extern void cache_resume_icache(uint32_t val); +extern int cache_invalidate_addr(uint32_t addr, uint32_t size); /**************************************************************************** * Private Data @@ -98,7 +154,7 @@ static struct spiflash_guard_funcs_s g_spi_flash_guard_funcs = .yield = NULL, }; -struct spiflash_cachestate_s g_state; +static struct spiflash_cachestate_s g_state; /**************************************************************************** * Name: spiflash_opstart @@ -128,10 +184,147 @@ static IRAM_ATTR void spiflash_end(void) leave_critical_section(g_state.flags); } +/**************************************************************************** + * Name: esp32s3_mmap + * + * Description: + * Mapped SPI Flash address to ESP32-S3'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 IRAM_ATTR int esp32s3_mmap(struct spiflash_map_req_s *req) +{ + int ret; + int i; + int start_page; + int flash_page; + int page_cnt; + uint32_t mapped_addr; + + spiflash_start(); + + 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(MMU_ADDR2OFF(req->src_addr) + 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_end(); + + return ret; +} + +/**************************************************************************** + * Name: esp32s3_ummap + * + * Description: + * Unmap SPI Flash address in ESP32-S3's address bus, and free resource. + * + * Input Parameters: + * req - SPI Flash mapping requesting parameters + * + * Returned Value: + * None. + * + ****************************************************************************/ + +static IRAM_ATTR void esp32s3_ummap(const struct spiflash_map_req_s *req) +{ + int i; + + spiflash_start(); + + for (i = req->start_page; i < req->start_page + req->page_cnt; ++i) + { + MMU_TABLE[i] = INVALID_MMU_VAL; + } + + spiflash_end(); +} + /**************************************************************************** * Public Functions ****************************************************************************/ +/**************************************************************************** + * Name: spi_flash_read_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. + * + ****************************************************************************/ + +int spi_flash_read_encrypted(uint32_t addr, void *buffer, uint32_t size) +{ + int ret; + struct spiflash_map_req_s req = + { + .src_addr = addr, + .size = size + }; + + ret = esp32s3_mmap(&req); + if (ret < 0) + { + return ret; + } + + memcpy(buffer, req.ptr, size); + + esp32s3_ummap(&req); + + return OK; +} + /**************************************************************************** * Name: esp32s3_spiflash_init * diff --git a/arch/xtensa/src/esp32s3/esp32s3_spiflash.h b/arch/xtensa/src/esp32s3/esp32s3_spiflash.h index b2eb6a8c293..cb4528e3f26 100644 --- a/arch/xtensa/src/esp32s3/esp32s3_spiflash.h +++ b/arch/xtensa/src/esp32s3/esp32s3_spiflash.h @@ -46,6 +46,32 @@ extern "C" * Public Function Prototypes ****************************************************************************/ +/**************************************************************************** + * Name: spi_flash_read_encrypted + * + * Description: + * + * Read data from Encrypted Flash. + * + * If flash encryption is enabled, this function will transparently + * decrypt data as it is read. + * If flash encryption is not enabled, this function behaves the same as + * spi_flash_read(). + * + * See esp_flash_encryption_enabled() for a function to check if flash + * encryption is enabled. + * + * Parameters: + * addr - source address of the data in Flash. + * buffer - pointer to the destination buffer + * size - length of data + * + * Returned Values: esp_err_t + * + ****************************************************************************/ + +int spi_flash_read_encrypted(uint32_t addr, void *buffer, uint32_t size); + /**************************************************************************** * Name: esp32s3_spiflash_init * diff --git a/arch/xtensa/src/esp32s3/esp32s3_spiflash_mtd.c b/arch/xtensa/src/esp32s3/esp32s3_spiflash_mtd.c index 862befcf31e..d59d5dc8800 100644 --- a/arch/xtensa/src/esp32s3/esp32s3_spiflash_mtd.c +++ b/arch/xtensa/src/esp32s3/esp32s3_spiflash_mtd.c @@ -84,12 +84,24 @@ static int esp32s3_erase(struct mtd_dev_s *dev, off_t startblock, size_t nblocks); static ssize_t esp32s3_read(struct mtd_dev_s *dev, off_t offset, size_t nbytes, uint8_t *buffer); +static ssize_t esp32s3_read_decrypt(struct mtd_dev_s *dev, + off_t offset, + size_t nbytes, + uint8_t *buffer); static ssize_t esp32s3_bread(struct mtd_dev_s *dev, off_t startblock, size_t nblocks, uint8_t *buffer); +static ssize_t esp32s3_bread_decrypt(struct mtd_dev_s *dev, + off_t startblock, + size_t nblocks, + uint8_t *buffer); static ssize_t esp32s3_write(struct mtd_dev_s *dev, off_t offset, size_t nbytes, const uint8_t *buffer); static ssize_t esp32s3_bwrite(struct mtd_dev_s *dev, off_t startblock, size_t nblocks, const uint8_t *buffer); +static ssize_t esp32s3_bwrite_encrypt(struct mtd_dev_s *dev, + off_t startblock, + size_t nblocks, + const uint8_t *buffer); static int esp32s3_ioctl(struct mtd_dev_s *dev, int cmd, unsigned long arg); @@ -114,6 +126,23 @@ static const struct esp32s3_mtd_dev_s g_esp32s3_spiflash = .data = &rom_spiflash_legacy_data, }; +static const struct esp32s3_mtd_dev_s g_esp32s3_spiflash_encrypt = +{ + .mtd = + { + .erase = esp32s3_erase, + .bread = esp32s3_bread_decrypt, + .bwrite = esp32s3_bwrite_encrypt, + .read = esp32s3_read_decrypt, + .ioctl = esp32s3_ioctl, +#ifdef CONFIG_MTD_BYTE_WRITE + .write = NULL, +#endif + .name = "esp32s3_spiflash_encrypt" + }, + .data = &rom_spiflash_legacy_data, +}; + /* Ensure exclusive access to the driver */ static sem_t g_exclsem = SEM_INITIALIZER(1); @@ -293,6 +322,117 @@ static ssize_t esp32s3_bread(struct mtd_dev_s *dev, off_t startblock, return ret; } +/**************************************************************************** + * Name: esp32s3_read_decrypt + * + * Description: + * Read encrypted data and decrypt automatically from SPI Flash + * at designated address. + * + * Input Parameters: + * dev - 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 esp32s3_read_decrypt(struct mtd_dev_s *dev, + off_t offset, + size_t nbytes, + uint8_t *buffer) +{ + ssize_t ret; + +#ifdef CONFIG_ESP32S3_STORAGE_MTD_DEBUG + finfo("%s(%p, 0x%x, %d, %p)\n", __func__, dev, offset, nbytes, buffer); + + finfo("spi_flash_read_encrypted(0x%x, %p, %d)\n", offset, buffer, + nbytes); +#endif + + /* Acquire the semaphore. */ + + ret = nxsem_wait(&g_exclsem); + if (ret < 0) + { + return ret; + } + + ret = spi_flash_read_encrypted(offset, buffer, nbytes); + + nxsem_post(&g_exclsem); + + if (ret == OK) + { + ret = nbytes; + } + +#ifdef CONFIG_ESP32S3_STORAGE_MTD_DEBUG + finfo("%s()=%d\n", __func__, ret); +#endif + + return ret; +} + +/**************************************************************************** + * Name: esp32s3_bread_decrypt + * + * Description: + * Read encrypted data and decrypt automatically from designated blocks. + * + * Input Parameters: + * dev - 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 esp32s3_bread_decrypt(struct mtd_dev_s *dev, + off_t startblock, + size_t nblocks, + uint8_t *buffer) +{ + ssize_t ret; + uint32_t addr = startblock * MTD_BLK_SIZE; + uint32_t size = nblocks * MTD_BLK_SIZE; + +#ifdef CONFIG_ESP32S3_STORAGE_MTD_DEBUG + finfo("%s(%p, 0x%x, %d, %p)\n", __func__, dev, startblock, nblocks, + buffer); + + finfo("spi_flash_read_encrypted(0x%x, %p, %d)\n", addr, buffer, size); +#endif + + ret = nxsem_wait(&g_exclsem); + if (ret < 0) + { + return ret; + } + + ret = spi_flash_read_encrypted(addr, buffer, size); + + nxsem_post(&g_exclsem); + + if (ret == OK) + { + ret = nblocks; + } + +#ifdef CONFIG_ESP32S3_STORAGE_MTD_DEBUG + finfo("%s()=%d\n", __func__, ret); +#endif + + return ret; +} + /**************************************************************************** * Name: esp32s3_write * @@ -355,6 +495,64 @@ error_with_buffer: return (ssize_t)ret; } +/**************************************************************************** + * Name: esp32s3_bwrite_encrypt + * + * Description: + * Write data to designated blocks by SPI Flash hardware encryption. + * + * Input Parameters: + * dev - 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 esp32s3_bwrite_encrypt(struct mtd_dev_s *dev, + off_t startblock, + size_t nblocks, + const uint8_t *buffer) +{ + ssize_t ret; + uint32_t addr = startblock * MTD_BLK_SIZE; + uint32_t size = nblocks * MTD_BLK_SIZE; + +#ifdef CONFIG_ESP32S3_STORAGE_MTD_DEBUG + finfo("%s(%p, 0x%x, %d, %p)\n", __func__, dev, startblock, + nblocks, buffer); + + finfo("spi_flash_write_encrypted(0x%x, %p, %d)\n", addr, buffer, size); +#endif + + ret = nxsem_wait(&g_exclsem); + if (ret < 0) + { + goto error_with_buffer; + } + + ret = spi_flash_write_encrypted(addr, buffer, size); + + nxsem_post(&g_exclsem); + + if (ret == OK) + { + ret = nblocks; + } + +#ifdef CONFIG_ESP32S3_STORAGE_MTD_DEBUG + finfo("%s()=%d\n", __func__, ret); +#endif + +error_with_buffer: + + return ret; +} + /**************************************************************************** * Name: esp32s3_bwrite * @@ -496,6 +694,8 @@ static int esp32s3_ioctl(struct mtd_dev_s *dev, int cmd, * Input Parameters: * mtd_offset - MTD Partition offset from the base address in SPI Flash. * mtd_size - Size for the MTD partition. + * encrypted - Flag indicating whether the newly allocated partition will + * have its content encrypted. * * Returned Value: * ESP32-S3 SPI Flash MTD data pointer if success or NULL if fail. @@ -503,7 +703,8 @@ static int esp32s3_ioctl(struct mtd_dev_s *dev, int cmd, ****************************************************************************/ struct mtd_dev_s *esp32s3_spiflash_alloc_mtdpart(uint32_t mtd_offset, - uint32_t mtd_size) + uint32_t mtd_size, + bool encrypted) { const struct esp32s3_mtd_dev_s *priv; const esp32s3_spiflash_chip_t *chip; @@ -512,7 +713,14 @@ struct mtd_dev_s *esp32s3_spiflash_alloc_mtdpart(uint32_t mtd_offset, uint32_t startblock; uint32_t size; - priv = &g_esp32s3_spiflash; + if (encrypted) + { + priv = &g_esp32s3_spiflash_encrypt; + } + else + { + priv = &g_esp32s3_spiflash; + } chip = &(*priv->data)->chip; @@ -575,3 +783,25 @@ struct mtd_dev_s *esp32s3_spiflash_mtd(void) return &priv->mtd; } + +/**************************************************************************** + * Name: esp32s3_spiflash_encrypt_mtd + * + * Description: + * Get SPI Flash encryption MTD. + * + * Input Parameters: + * None + * + * Returned Value: + * SPI Flash encryption MTD pointer. + * + ****************************************************************************/ + +struct mtd_dev_s *esp32s3_spiflash_encrypt_mtd(void) +{ + struct esp32s3_mtd_dev_s *priv = + (struct esp32s3_mtd_dev_s *)&g_esp32s3_spiflash_encrypt; + + return &priv->mtd; +} diff --git a/arch/xtensa/src/esp32s3/esp32s3_spiflash_mtd.h b/arch/xtensa/src/esp32s3/esp32s3_spiflash_mtd.h index 2742c9cdc68..86f1c1f1741 100644 --- a/arch/xtensa/src/esp32s3/esp32s3_spiflash_mtd.h +++ b/arch/xtensa/src/esp32s3/esp32s3_spiflash_mtd.h @@ -62,6 +62,22 @@ extern "C" struct mtd_dev_s *esp32s3_spiflash_mtd(void); +/**************************************************************************** + * Name: esp32s3_spiflash_encrypt_mtd + * + * Description: + * Get SPI Flash encryption MTD. + * + * Input Parameters: + * None + * + * Returned Value: + * SPI Flash encryption MTD pointer. + * + ****************************************************************************/ + +struct mtd_dev_s *esp32s3_spiflash_encrypt_mtd(void); + /**************************************************************************** * Name: esp32s3_spiflash_alloc_mtdpart * @@ -80,7 +96,8 @@ struct mtd_dev_s *esp32s3_spiflash_mtd(void); ****************************************************************************/ struct mtd_dev_s *esp32s3_spiflash_alloc_mtdpart(uint32_t mtd_offset, - uint32_t mtd_size); + uint32_t mtd_size, + bool encrypted); #ifdef __cplusplus } diff --git a/boards/xtensa/esp32s3/common/src/esp32s3_board_spiflash.c b/boards/xtensa/esp32s3/common/src/esp32s3_board_spiflash.c index 230c0d757d9..f74748ea8b2 100644 --- a/boards/xtensa/esp32s3/common/src/esp32s3_board_spiflash.c +++ b/boards/xtensa/esp32s3/common/src/esp32s3_board_spiflash.c @@ -262,7 +262,8 @@ static int init_storage_partition(void) FAR struct mtd_dev_s *mtd; mtd = esp32s3_spiflash_alloc_mtdpart(CONFIG_ESP32S3_STORAGE_MTD_OFFSET, - CONFIG_ESP32S3_STORAGE_MTD_SIZE); + CONFIG_ESP32S3_STORAGE_MTD_SIZE, + false); if (!mtd) { ferr("ERROR: Failed to alloc MTD partition of SPI Flash\n");