diff --git a/arch/risc-v/src/esp32c3/esp32c3_spiflash.c b/arch/risc-v/src/esp32c3/esp32c3_spiflash.c index 96f19ad30ff..41e98101444 100644 --- a/arch/risc-v/src/esp32c3/esp32c3_spiflash.c +++ b/arch/risc-v/src/esp32c3/esp32c3_spiflash.c @@ -36,13 +36,41 @@ #include #include +#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 ****************************************************************************/ @@ -103,6 +162,14 @@ static ssize_t esp32c3_bwrite_encrypt(struct mtd_dev_s *dev, 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 ****************************************************************************/ @@ -154,6 +221,175 @@ static sem_t g_exclsem = SEM_INITIALIZER(1); * Private Functions ****************************************************************************/ +/**************************************************************************** + * 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 * @@ -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 e26862b59bd..40bd0dbdf8b 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 55dc5f3f767..f282eef8bff 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 ac4ba6d8e36..7f903521ca5 100644 --- a/boards/risc-v/esp32c3/esp32c3-devkit/src/esp32c3-devkit.h +++ b/boards/risc-v/esp32c3/esp32c3-devkit/src/esp32c3-devkit.h @@ -181,6 +181,24 @@ int board_bmp180_initialize(int devno, int busno); 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 * 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 55c4915ac09..405ee9d09bb 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 ea7f1df324a..17f24021167 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 +#include "inttypes.h" #include #include #include @@ -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); }