#endif //CONFIG_SPI_FLASH_ENABLE_COUNTERS
static esp_err_t spi_flash_translate_rc(esp_rom_spiflash_result_t rc);
+static bool is_safe_write_address(size_t addr, size_t size);
const DRAM_ATTR spi_flash_guard_funcs_t g_flash_guard_default_ops = {
- .start = spi_flash_disable_interrupts_caches_and_other_cpu,
- .end = spi_flash_enable_interrupts_caches_and_other_cpu,
- .op_lock = spi_flash_op_lock,
- .op_unlock = spi_flash_op_unlock
+ .start = spi_flash_disable_interrupts_caches_and_other_cpu,
+ .end = spi_flash_enable_interrupts_caches_and_other_cpu,
+ .op_lock = spi_flash_op_lock,
+ .op_unlock = spi_flash_op_unlock,
+#if !CONFIG_SPI_FLASH_WRITING_DANGEROUS_REGIONS_ALLOWED
+ .is_safe_write_address = is_safe_write_address
+#endif
};
const DRAM_ATTR spi_flash_guard_funcs_t g_flash_guard_no_os_ops = {
- .start = spi_flash_disable_interrupts_caches_and_other_cpu_no_os,
- .end = spi_flash_enable_interrupts_caches_no_os,
- .op_lock = 0,
- .op_unlock = 0
+ .start = spi_flash_disable_interrupts_caches_and_other_cpu_no_os,
+ .end = spi_flash_enable_interrupts_caches_no_os,
+ .op_lock = 0,
+ .op_unlock = 0,
+#if !CONFIG_SPI_FLASH_WRITING_DANGEROUS_REGIONS_ALLOWED
+ .is_safe_write_address = 0
+#endif
};
static const spi_flash_guard_funcs_t *s_flash_guard_ops;
#define CHECK_WRITE_ADDRESS(ADDR, SIZE)
#else /* FAILS or ABORTS */
#define CHECK_WRITE_ADDRESS(ADDR, SIZE) do { \
- if (!is_safe_write_address(ADDR, SIZE)) { \
+ if (s_flash_guard_ops && s_flash_guard_ops->is_safe_write_address && !s_flash_guard_ops->is_safe_write_address(ADDR, SIZE)) { \
return ESP_ERR_INVALID_ARG; \
} \
} while(0)
* @brief SPI flash operation unlock function.
*/
typedef void (*spi_flash_op_unlock_func_t)(void);
+/**
+ * @brief Function to protect SPI flash critical regions corruption.
+ */
+typedef bool (*spi_flash_is_safe_write_address_t)(size_t addr, size_t size);
/**
* Structure holding SPI flash access critical sections management functions.
* - 'op_unlock' unlocks access to flash API internal data.
* These two functions are recursive and can be used around the outside of multiple calls to
* 'start' & 'end', in order to create atomic multi-part flash operations.
+ * 3) When CONFIG_SPI_FLASH_WRITING_DANGEROUS_REGIONS_ALLOWED is disabled, flash writing/erasing
+ * API checks for addresses provided by user to avoid corruption of critical flash regions
+ * (bootloader, partition table, running application etc.).
*
* Different versions of the guarding functions should be used depending on the context of
* execution (with or without functional OS). In normal conditions when flash API is called
* For example structure can be placed in DRAM and functions in IRAM sections.
*/
typedef struct {
- spi_flash_guard_start_func_t start; /**< critical section start function. */
- spi_flash_guard_end_func_t end; /**< critical section end function. */
- spi_flash_op_lock_func_t op_lock; /**< flash access API lock function.*/
- spi_flash_op_unlock_func_t op_unlock; /**< flash access API unlock function.*/
+ spi_flash_guard_start_func_t start; /**< critical section start function. */
+ spi_flash_guard_end_func_t end; /**< critical section end function. */
+ spi_flash_op_lock_func_t op_lock; /**< flash access API lock function.*/
+ spi_flash_op_unlock_func_t op_unlock; /**< flash access API unlock function.*/
+#if !CONFIG_SPI_FLASH_WRITING_DANGEROUS_REGIONS_ALLOWED
+ spi_flash_is_safe_write_address_t is_safe_write_address; /**< checks flash write addresses.*/
+#endif
} spi_flash_guard_funcs_t;
/**
*/
void spi_flash_guard_set(const spi_flash_guard_funcs_t* funcs);
-
/**
* @brief Get the guard functions used for flash access
*