1 // Copyright 2020 Espressif Systems (Shanghai) PTE LTD
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 #include <string.h>
16 #include <sys/param.h>
17
18 #include "esp_spi_flash.h"
19 #include "soc/system_reg.h"
20 #include "soc/soc_memory_layout.h"
21 #include "esp32s3/rom/spi_flash.h"
22 #include "esp32s3/rom/cache.h"
23 #include "bootloader_flash.h"
24 #include "hal/spi_flash_hal.h"
25 #include "esp_flash.h"
26 #include "esp_log.h"
27
28 static const char *TAG = "spiflash_s3";
29
30 #define SPICACHE SPIMEM0
31 #define SPIFLASH SPIMEM1
32
33 extern void IRAM_ATTR flash_rom_init(void);
spi_flash_write_encrypted_chip(size_t dest_addr,const void * src,size_t size)34 esp_rom_spiflash_result_t IRAM_ATTR spi_flash_write_encrypted_chip(size_t dest_addr, const void *src, size_t size)
35 {
36 const spi_flash_guard_funcs_t *ops = spi_flash_guard_get();
37 esp_rom_spiflash_result_t rc;
38
39 assert((dest_addr % 16) == 0);
40 assert((size % 16) == 0);
41
42 if (!esp_ptr_internal(src)) {
43 uint8_t block[128]; // Need to buffer in RAM as we write
44 while (size > 0) {
45 size_t next_block = MIN(size, sizeof(block));
46 memcpy(block, src, next_block);
47
48 esp_rom_spiflash_result_t r = spi_flash_write_encrypted_chip(dest_addr, block, next_block);
49 if (r != ESP_ROM_SPIFLASH_RESULT_OK) {
50 return r;
51 }
52
53 size -= next_block;
54 dest_addr += next_block;
55 src = ((uint8_t *)src) + next_block;
56 }
57 memset(block, 0, sizeof(block));
58
59 return ESP_ROM_SPIFLASH_RESULT_OK;
60 } else { // Already in internal memory
61 ESP_LOGV(TAG, "calling SPI_Encrypt_Write addr 0x%x src %p size 0x%x", dest_addr, src, size);
62
63 #ifndef CONFIG_SPI_FLASH_USE_LEGACY_IMPL
64 /* The ROM function SPI_Encrypt_Write assumes ADDR_BITLEN is already set but new
65 implementation doesn't automatically set this to a usable value */
66 SPIFLASH.user1.usr_addr_bitlen = 23;
67 #endif
68
69 if (ops && ops->start) {
70 ops->start();
71 }
72 flash_rom_init();
73 rc = esp_rom_spiflash_write_encrypted(dest_addr, (void *)src, size);
74 if (ops && ops->end) {
75 ops->end();
76 }
77 return rc;
78 }
79 }
80
spi_flash_wrap_set(spi_flash_wrap_mode_t mode)81 esp_err_t spi_flash_wrap_set(spi_flash_wrap_mode_t mode)
82 {
83 return bootloader_flash_wrap_set(mode);
84 }
85
spi_flash_enable_wrap(uint32_t wrap_size)86 esp_err_t spi_flash_enable_wrap(uint32_t wrap_size)
87 {
88 switch (wrap_size) {
89 case 8:
90 return bootloader_flash_wrap_set(FLASH_WRAP_MODE_8B);
91 case 16:
92 return bootloader_flash_wrap_set(FLASH_WRAP_MODE_16B);
93 case 32:
94 return bootloader_flash_wrap_set(FLASH_WRAP_MODE_32B);
95 case 64:
96 return bootloader_flash_wrap_set(FLASH_WRAP_MODE_64B);
97 default:
98 return ESP_FAIL;
99 }
100 }
101
spi_flash_disable_wrap(void)102 void spi_flash_disable_wrap(void)
103 {
104 bootloader_flash_wrap_set(FLASH_WRAP_MODE_DISABLE);
105 }
106
spi_flash_support_wrap_size(uint32_t wrap_size)107 bool spi_flash_support_wrap_size(uint32_t wrap_size)
108 {
109 if (!REG_GET_BIT(SPI_MEM_CTRL_REG(0), SPI_MEM_FREAD_QIO) || !REG_GET_BIT(SPI_MEM_CTRL_REG(0), SPI_MEM_FASTRD_MODE)) {
110 return ESP_FAIL;
111 }
112 switch (wrap_size) {
113 case 0:
114 case 8:
115 case 16:
116 case 32:
117 case 64:
118 return true;
119 default:
120 return false;
121 }
122 }
123