|
31 | 31 | #include "esp_spi_flash.h"
|
32 | 32 | #include "esp_log.h"
|
33 | 33 | #include "esp_clk.h"
|
| 34 | +#include "esp_flash_partitions.h" |
| 35 | +#include "esp_ota_ops.h" |
34 | 36 | #include "cache_utils.h"
|
35 | 37 |
|
36 | 38 | /* bytes erased by SPIEraseBlock() ROM function */
|
@@ -83,6 +85,45 @@ const DRAM_ATTR spi_flash_guard_funcs_t g_flash_guard_no_os_ops = {
|
83 | 85 |
|
84 | 86 | static const spi_flash_guard_funcs_t *s_flash_guard_ops;
|
85 | 87 |
|
| 88 | +#ifdef CONFIG_SPI_FLASH_WRITING_DANGEROUS_REGIONS_ABORTS |
| 89 | +#define UNSAFE_WRITE_ADDRESS abort() |
| 90 | +#else |
| 91 | +#define UNSAFE_WRITE_ADDRESS return false |
| 92 | +#endif |
| 93 | + |
| 94 | + |
| 95 | +/* CHECK_WRITE_ADDRESS macro to fail writes which land in the |
| 96 | + bootloader, partition table, or running application region. |
| 97 | +*/ |
| 98 | +#if CONFIG_SPI_FLASH_WRITING_DANGEROUS_REGIONS_ALLOWED |
| 99 | +#define CHECK_WRITE_ADDRESS(ADDR, SIZE) |
| 100 | +#else /* FAILS or ABORTS */ |
| 101 | +#define CHECK_WRITE_ADDRESS(ADDR, SIZE) do { \ |
| 102 | + if (!is_safe_write_address(ADDR, SIZE)) { \ |
| 103 | + return ESP_ERR_INVALID_ARG; \ |
| 104 | + } \ |
| 105 | + } while(0) |
| 106 | +#endif // CONFIG_SPI_FLASH_WRITING_DANGEROUS_REGIONS_ALLOWED |
| 107 | + |
| 108 | +static __attribute__((unused)) bool is_safe_write_address(size_t addr, size_t size) |
| 109 | +{ |
| 110 | + bool result = true; |
| 111 | + if (addr <= ESP_PARTITION_TABLE_OFFSET + ESP_PARTITION_TABLE_MAX_LEN) { |
| 112 | + UNSAFE_WRITE_ADDRESS; |
| 113 | + } |
| 114 | + |
| 115 | + const esp_partition_t *p = esp_ota_get_running_partition(); |
| 116 | + if (addr >= p->address && addr < p->address + p->size) { |
| 117 | + UNSAFE_WRITE_ADDRESS; |
| 118 | + } |
| 119 | + if (addr < p->address && addr + size > p->address) { |
| 120 | + UNSAFE_WRITE_ADDRESS; |
| 121 | + } |
| 122 | + |
| 123 | + return result; |
| 124 | +} |
| 125 | + |
| 126 | + |
86 | 127 | void spi_flash_init()
|
87 | 128 | {
|
88 | 129 | spi_flash_init_lock();
|
@@ -146,11 +187,13 @@ static esp_rom_spiflash_result_t IRAM_ATTR spi_flash_unlock()
|
146 | 187 |
|
147 | 188 | esp_err_t IRAM_ATTR spi_flash_erase_sector(size_t sec)
|
148 | 189 | {
|
| 190 | + CHECK_WRITE_ADDRESS(sec * SPI_FLASH_SEC_SIZE, SPI_FLASH_SEC_SIZE); |
149 | 191 | return spi_flash_erase_range(sec * SPI_FLASH_SEC_SIZE, SPI_FLASH_SEC_SIZE);
|
150 | 192 | }
|
151 | 193 |
|
152 | 194 | esp_err_t IRAM_ATTR spi_flash_erase_range(uint32_t start_addr, uint32_t size)
|
153 | 195 | {
|
| 196 | + CHECK_WRITE_ADDRESS(start_addr, size); |
154 | 197 | if (start_addr % SPI_FLASH_SEC_SIZE != 0) {
|
155 | 198 | return ESP_ERR_INVALID_ARG;
|
156 | 199 | }
|
@@ -187,6 +230,7 @@ esp_err_t IRAM_ATTR spi_flash_erase_range(uint32_t start_addr, uint32_t size)
|
187 | 230 |
|
188 | 231 | esp_err_t IRAM_ATTR spi_flash_write(size_t dst, const void *srcv, size_t size)
|
189 | 232 | {
|
| 233 | + CHECK_WRITE_ADDRESS(dst, size); |
190 | 234 | // Out of bound writes are checked in ROM code, but we can give better
|
191 | 235 | // error code here
|
192 | 236 | if (dst + size > g_rom_flashchip.chip_size) {
|
@@ -281,6 +325,7 @@ esp_err_t IRAM_ATTR spi_flash_write(size_t dst, const void *srcv, size_t size)
|
281 | 325 |
|
282 | 326 | esp_err_t IRAM_ATTR spi_flash_write_encrypted(size_t dest_addr, const void *src, size_t size)
|
283 | 327 | {
|
| 328 | + CHECK_WRITE_ADDRESS(dest_addr, size); |
284 | 329 | const uint8_t *ssrc = (const uint8_t *)src;
|
285 | 330 | if ((dest_addr % 16) != 0) {
|
286 | 331 | return ESP_ERR_INVALID_ARG;
|
|
0 commit comments