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