riscv/esp32c3: Support SPI Flash encryption read/write

This commit is contained in:
Dong Heng 2021-05-11 15:08:29 +08:00 committed by Alan Carvalho de Assis
parent 48b0e48cd4
commit 76df958e34
6 changed files with 288 additions and 12 deletions

View File

@ -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
****************************************************************************/
@ -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);

View File

@ -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

View File

@ -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 );

View File

@ -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
*

View File

@ -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)
{

View File

@ -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);
}