diff --git a/arch/xtensa/src/esp32/esp32_spiflash.c b/arch/xtensa/src/esp32/esp32_spiflash.c index 769c0f6684..477c663e0c 100644 --- a/arch/xtensa/src/esp32/esp32_spiflash.c +++ b/arch/xtensa/src/esp32/esp32_spiflash.c @@ -47,6 +47,7 @@ #include "hardware/esp32_soc.h" #include "hardware/esp32_spi.h" #include "hardware/esp32_dport.h" +#include "hardware/efuse_reg.h" #ifdef CONFIG_ESP32_SPIRAM #include "esp32_spiram.h" @@ -73,6 +74,8 @@ #define SPI_FLASH_ENCRYPT_WORDS (32 / 4) #define SPI_FLASH_ERASED_STATE (0xff) +#define SPI_FLASH_ENCRYPT_MIN_SIZE (16) + #define MTD2PRIV(_dev) ((struct esp32_spiflash_s *)_dev) #define MTD_SIZE(_priv) ((_priv)->chip->chip_size) #define MTD_BLKSIZE(_priv) ((_priv)->chip->page_size) @@ -242,8 +245,10 @@ static ssize_t esp32_bread_decrypt(struct mtd_dev_s *dev, off_t startblock, size_t nblocks, uint8_t *buffer); +#ifdef CONFIG_MTD_BYTE_WRITE static ssize_t esp32_write(struct mtd_dev_s *dev, off_t offset, size_t nbytes, const uint8_t *buffer); +#endif static ssize_t esp32_bwrite(struct mtd_dev_s *dev, off_t startblock, size_t nblocks, const uint8_t *buffer); static ssize_t esp32_bwrite_encrypt(struct mtd_dev_s *dev, @@ -252,6 +257,8 @@ static ssize_t esp32_bwrite_encrypt(struct mtd_dev_s *dev, const uint8_t *buffer); static int esp32_ioctl(struct mtd_dev_s *dev, int cmd, unsigned long arg); +static int esp32_ioctl_encrypt(struct mtd_dev_s *dev, int cmd, + unsigned long arg); /**************************************************************************** * Private Data @@ -289,7 +296,7 @@ static struct esp32_spiflash_s g_esp32_spiflash1_encrypt = .bread = esp32_bread_decrypt, .bwrite = esp32_bwrite_encrypt, .read = esp32_read_decrypt, - .ioctl = esp32_ioctl, + .ioctl = esp32_ioctl_encrypt, #ifdef CONFIG_MTD_BYTE_WRITE .write = NULL, #endif @@ -1731,6 +1738,7 @@ static ssize_t esp32_bread_decrypt(struct mtd_dev_s *dev, * ****************************************************************************/ +#ifdef CONFIG_MTD_BYTE_WRITE static ssize_t esp32_write(struct mtd_dev_s *dev, off_t offset, size_t nbytes, const uint8_t *buffer) { @@ -1770,6 +1778,7 @@ static ssize_t esp32_write(struct mtd_dev_s *dev, off_t offset, return ret; } +#endif /**************************************************************************** * Name: esp32_bwrite @@ -1839,9 +1848,21 @@ static ssize_t esp32_bwrite_encrypt(struct mtd_dev_s *dev, const uint8_t *buffer) { ssize_t ret; + ssize_t n; + off_t addr; + uint8_t *wbuf; + uint8_t *rbuf; + uint8_t tmp_buf[SPI_FLASH_ENCRYPT_UNIT_SIZE]; + size_t wbytes = 0; struct esp32_spiflash_s *priv = MTD2PRIV(dev); - uint32_t addr = MTD_BLK2SIZE(priv, startblock); - uint32_t size = MTD_BLK2SIZE(priv, nblocks); + uint32_t offset = MTD_BLK2SIZE(priv, startblock); + uint32_t nbytes = MTD_BLK2SIZE(priv, nblocks); + + if ((offset % SPI_FLASH_ENCRYPT_MIN_SIZE) || + (nbytes % SPI_FLASH_ENCRYPT_MIN_SIZE)) + { + return -EINVAL; + } #ifdef CONFIG_ESP32_SPIFLASH_DEBUG finfo("esp32_bwrite_encrypt(%p, 0x%x, %d, %p)\n", @@ -1854,7 +1875,77 @@ static ssize_t esp32_bwrite_encrypt(struct mtd_dev_s *dev, return ret; } - ret = esp32_writedata_encrypted(priv, addr, buffer, size); + while (nbytes) + { + if (offset % SPI_FLASH_ENCRYPT_UNIT_SIZE) + { + wbuf = tmp_buf; + rbuf = tmp_buf; + addr = offset - SPI_FLASH_ENCRYPT_MIN_SIZE; + + n = SPI_FLASH_ENCRYPT_MIN_SIZE; + + ret = esp32_readdata_encrypted(priv, addr, rbuf, n); + if (ret < 0) + { + ferr("esp32_readdata_encrypted failed ret=%d\n", ret); + break; + } + + memcpy(wbuf + n, buffer, n); + } + else if (nbytes % SPI_FLASH_ENCRYPT_UNIT_SIZE) + { + wbuf = tmp_buf; + if (offset % SPI_FLASH_ENCRYPT_UNIT_SIZE) + { + rbuf = tmp_buf; + addr = offset - SPI_FLASH_ENCRYPT_MIN_SIZE; + } + else + { + rbuf = tmp_buf + SPI_FLASH_ENCRYPT_MIN_SIZE; + addr = offset; + } + + n = SPI_FLASH_ENCRYPT_MIN_SIZE; + + ret = esp32_readdata_encrypted(priv, addr, rbuf, n); + if (ret < 0) + { + ferr("esp32_readdata_encrypted failed ret=%d\n", ret); + break; + } + + if (offset % SPI_FLASH_ENCRYPT_UNIT_SIZE) + { + memcpy(wbuf + n, buffer, n); + } + else + { + memcpy(wbuf, buffer, n); + } + } + else + { + n = SPI_FLASH_ENCRYPT_UNIT_SIZE; + wbuf = (uint8_t *)buffer; + addr = offset; + } + + ret = esp32_writedata_encrypted(priv, addr, wbuf, + SPI_FLASH_ENCRYPT_UNIT_SIZE); + if (ret < 0) + { + ferr("esp32_writedata_encrypted failed ret=%d\n", ret); + break; + } + + offset += n; + nbytes -= n; + buffer += n; + wbytes += n; + } nxmutex_unlock(&g_lock); if (ret == OK) @@ -1943,6 +2034,82 @@ static int esp32_ioctl(struct mtd_dev_s *dev, int cmd, return ret; } +/**************************************************************************** + * Name: esp32_ioctl_encrypt + * + * Description: + * Set/Get option to/from ESP32 SPI Flash Hardware Encryption MTD + * device data. + * + * Input Parameters: + * dev - ESP32 MTD device data + * cmd - operation command + * arg - operation argument + * + * Returned Value: + * 0 if success or a negative value if fail. + * + ****************************************************************************/ + +static int esp32_ioctl_encrypt(struct mtd_dev_s *dev, int cmd, + unsigned long arg) +{ + int ret = -EINVAL; + struct esp32_spiflash_s *priv = MTD2PRIV(dev); + + finfo("cmd: %d\n", cmd); + + switch (cmd) + { + case MTDIOC_GEOMETRY: + { + struct mtd_geometry_s *geo = (struct mtd_geometry_s *)arg; + if (geo) + { + geo->blocksize = SPI_FLASH_ENCRYPT_MIN_SIZE; + geo->erasesize = MTD_ERASESIZE(priv); + geo->neraseblocks = MTD_SIZE(priv) / geo->erasesize; + ret = OK; + + finfo("blocksize: %d erasesize: %d neraseblocks: %d\n", + geo->blocksize, geo->erasesize, geo->neraseblocks); + } + } + break; + + case BIOC_PARTINFO: + { + struct partition_info_s *info = + (struct partition_info_s *)arg; + if (info != NULL) + { + info->sectorsize = SPI_FLASH_ENCRYPT_MIN_SIZE; + info->numsectors = MTD_SIZE(priv) / info->sectorsize; + info->startsector = 0; + info->parent[0] = '\0'; + ret = OK; + } + } + break; + + case MTDIOC_ERASESTATE: + { + uint8_t *result = (uint8_t *)arg; + *result = SPI_FLASH_ERASED_STATE; + + ret = OK; + } + break; + + default: + ret = -ENOTTY; + break; + } + + finfo("return %d\n", ret); + return ret; +} + /**************************************************************************** * Public Functions ****************************************************************************/ @@ -2065,4 +2232,41 @@ struct mtd_dev_s *esp32_spiflash_encrypt_get_mtd(void) return &priv->mtd; } +/**************************************************************************** + * Name: esp32_flash_encryption_enabled + * + * Description: + * Check if ESP32 enables SPI Flash encryption. + * + * Input Parameters: + * None + * + * Returned Value: + * True: SPI Flash encryption is enable, False if not. + * + ****************************************************************************/ + +bool esp32_flash_encryption_enabled(void) +{ + bool enabled = false; + uint32_t regval; + uint32_t flash_crypt_cnt; + + regval = getreg32(EFUSE_BLK0_RDATA0_REG); + flash_crypt_cnt = (regval >> EFUSE_RD_FLASH_CRYPT_CNT_S) & + EFUSE_RD_FLASH_CRYPT_CNT_V; + + while (flash_crypt_cnt) + { + if (flash_crypt_cnt & 1) + { + enabled = !enabled; + } + + flash_crypt_cnt >>= 1; + } + + return enabled; +} + #endif /* CONFIG_ESP32_SPIFLASH */ diff --git a/arch/xtensa/src/esp32/esp32_spiflash.h b/arch/xtensa/src/esp32/esp32_spiflash.h index 0023f18d01..a2eb5f5ffa 100644 --- a/arch/xtensa/src/esp32/esp32_spiflash.h +++ b/arch/xtensa/src/esp32/esp32_spiflash.h @@ -101,6 +101,22 @@ struct mtd_dev_s *esp32_spiflash_get_mtd(void); struct mtd_dev_s *esp32_spiflash_encrypt_get_mtd(void); +/**************************************************************************** + * Name: esp32_flash_encryption_enabled + * + * Description: + * Check if ESP32 enables SPI Flash encryption. + * + * Input Parameters: + * None + * + * Returned Value: + * True: SPI Flash encryption is enable, False if not. + * + ****************************************************************************/ + +bool esp32_flash_encryption_enabled(void); + #ifdef __cplusplus } #endif