mirror of
https://github.com/espressif/esp-idf.git
synced 2025-08-02 04:04:31 +02:00
Merge branch 'feature/parametrize_core_dump_check_v4.3' into 'release/v4.3'
coredump: core dump data check can now be parametrized (v4.3) See merge request espressif/esp-idf!13773
This commit is contained in:
@@ -48,6 +48,14 @@ menu "Core dump"
|
|||||||
depends on ESP_COREDUMP_DATA_FORMAT_ELF && IDF_TARGET_ESP32
|
depends on ESP_COREDUMP_DATA_FORMAT_ELF && IDF_TARGET_ESP32
|
||||||
endchoice
|
endchoice
|
||||||
|
|
||||||
|
config ESP_COREDUMP_CHECK_BOOT
|
||||||
|
bool "Check core dump data integrity on boot"
|
||||||
|
default y
|
||||||
|
depends on ESP_COREDUMP_ENABLE_TO_FLASH
|
||||||
|
help
|
||||||
|
When enabled, if any data are found on the flash core dump partition,
|
||||||
|
they will be checked by calculating their checksum.
|
||||||
|
|
||||||
config ESP_COREDUMP_ENABLE
|
config ESP_COREDUMP_ENABLE
|
||||||
bool
|
bool
|
||||||
default F
|
default F
|
||||||
|
@@ -78,6 +78,19 @@ void esp_core_dump_to_uart(panic_info_t *info);
|
|||||||
/*********************************** USER MODE API ************************************/
|
/*********************************** USER MODE API ************************************/
|
||||||
/**************************************************************************************/
|
/**************************************************************************************/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Check integrity of coredump data in flash.
|
||||||
|
* This function reads the coredump data while calculating their checksum. If it
|
||||||
|
* doesn't match the checksum written on flash, it means data are corrupted,
|
||||||
|
* an error will be returned. Else, ESP_OK is returned.
|
||||||
|
*
|
||||||
|
* @return `ESP_OK` if core dump is present and valid, `ESP_ERR_NOT_FOUND` if no core dump
|
||||||
|
* is stored in the partition, `ESP_ERR_INVALID_SIZE` or `ESP_ERR_INVALID_CRC`
|
||||||
|
* if the core dump is corrupted, other errors when unable to access flash, in that
|
||||||
|
* case please refer to \see esp_err_t
|
||||||
|
*/
|
||||||
|
esp_err_t esp_core_dump_image_check(void);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Retrieves address and size of coredump data in flash.
|
* @brief Retrieves address and size of coredump data in flash.
|
||||||
* This function is always available, even when core dump is disabled in menuconfig.
|
* This function is always available, even when core dump is disabled in menuconfig.
|
||||||
@@ -89,6 +102,15 @@ void esp_core_dump_to_uart(panic_info_t *info);
|
|||||||
*/
|
*/
|
||||||
esp_err_t esp_core_dump_image_get(size_t* out_addr, size_t *out_size);
|
esp_err_t esp_core_dump_image_get(size_t* out_addr, size_t *out_size);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Erases coredump data in flash. esp_core_dump_image_get() will then return
|
||||||
|
* ESP_ERR_NOT_FOUND. Can be used after a coredump has been transmitted successfully.
|
||||||
|
* This function is always available, even when core dump is disabled in menuconfig.
|
||||||
|
*
|
||||||
|
* @return ESP_OK on success, otherwise \see esp_err_t
|
||||||
|
*/
|
||||||
|
esp_err_t esp_core_dump_image_erase(void);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@@ -20,6 +20,8 @@
|
|||||||
#include "esp_flash_encrypt.h"
|
#include "esp_flash_encrypt.h"
|
||||||
#include "esp_rom_crc.h"
|
#include "esp_rom_crc.h"
|
||||||
|
|
||||||
|
#define BLANK_COREDUMP_SIZE 0xFFFFFFFF
|
||||||
|
|
||||||
const static DRAM_ATTR char TAG[] __attribute__((unused)) = "esp_core_dump_flash";
|
const static DRAM_ATTR char TAG[] __attribute__((unused)) = "esp_core_dump_flash";
|
||||||
|
|
||||||
#if CONFIG_ESP_COREDUMP_ENABLE_TO_FLASH
|
#if CONFIG_ESP_COREDUMP_ENABLE_TO_FLASH
|
||||||
@@ -57,6 +59,9 @@ static core_dump_flash_config_t s_core_flash_config;
|
|||||||
#define ESP_COREDUMP_FLASH_ERASE(_off_, _len_) esp_flash_erase_region(esp_flash_default_chip, _off_, _len_)
|
#define ESP_COREDUMP_FLASH_ERASE(_off_, _len_) esp_flash_erase_region(esp_flash_default_chip, _off_, _len_)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
esp_err_t esp_core_dump_image_check(void);
|
||||||
|
static esp_err_t esp_core_dump_partition_and_size_get(const esp_partition_t **partition, uint32_t* size);
|
||||||
|
|
||||||
static esp_err_t esp_core_dump_flash_custom_write(uint32_t address, const void *buffer, uint32_t length)
|
static esp_err_t esp_core_dump_flash_custom_write(uint32_t address, const void *buffer, uint32_t length)
|
||||||
{
|
{
|
||||||
esp_err_t err = ESP_OK;
|
esp_err_t err = ESP_OK;
|
||||||
@@ -70,8 +75,6 @@ static esp_err_t esp_core_dump_flash_custom_write(uint32_t address, const void *
|
|||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
esp_err_t esp_core_dump_image_get(size_t* out_addr, size_t *out_size);
|
|
||||||
|
|
||||||
static inline core_dump_crc_t esp_core_dump_calc_flash_config_crc(void)
|
static inline core_dump_crc_t esp_core_dump_calc_flash_config_crc(void)
|
||||||
{
|
{
|
||||||
return esp_rom_crc32_le(0, (uint8_t const *)&s_core_flash_config.partition, sizeof(s_core_flash_config.partition));
|
return esp_rom_crc32_le(0, (uint8_t const *)&s_core_flash_config.partition, sizeof(s_core_flash_config.partition));
|
||||||
@@ -302,6 +305,7 @@ static esp_err_t esp_core_dump_flash_write_end(core_dump_write_data_t* priv)
|
|||||||
}
|
}
|
||||||
wr_data->off += cs_len;
|
wr_data->off += cs_len;
|
||||||
ESP_COREDUMP_LOGI("Write end offset 0x%x, check sum length %d", wr_data->off, cs_len);
|
ESP_COREDUMP_LOGI("Write end offset 0x%x, check sum length %d", wr_data->off, cs_len);
|
||||||
|
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -341,19 +345,26 @@ void esp_core_dump_to_flash(panic_info_t *info)
|
|||||||
|
|
||||||
void esp_core_dump_init(void)
|
void esp_core_dump_init(void)
|
||||||
{
|
{
|
||||||
size_t core_data_sz = 0;
|
|
||||||
size_t core_data_addr = 0;
|
|
||||||
esp_core_dump_flash_init();
|
esp_core_dump_flash_init();
|
||||||
if (esp_core_dump_image_get(&core_data_addr, &core_data_sz) == ESP_OK && core_data_sz > 0) {
|
|
||||||
ESP_COREDUMP_LOGI("Found core dump %d bytes in flash @ 0x%x", core_data_sz, core_data_addr);
|
#if CONFIG_ESP_COREDUMP_CHECK_BOOT
|
||||||
|
const esp_partition_t *partition = 0;
|
||||||
|
uint32_t size = 0;
|
||||||
|
|
||||||
|
if (esp_core_dump_image_check() == ESP_OK
|
||||||
|
&& esp_core_dump_partition_and_size_get(&partition, &size) == ESP_OK) {
|
||||||
|
ESP_COREDUMP_LOGI("Found core dump %d bytes in flash @ 0x%x", size, partition->address);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
esp_err_t esp_core_dump_image_get(size_t* out_addr, size_t *out_size)
|
esp_err_t esp_core_dump_image_check(void)
|
||||||
{
|
{
|
||||||
esp_err_t err = ESP_OK;
|
esp_err_t err = ESP_OK;
|
||||||
|
const esp_partition_t *core_part = NULL;
|
||||||
core_dump_write_data_t wr_data = { 0 };
|
core_dump_write_data_t wr_data = { 0 };
|
||||||
uint32_t size = 0;
|
uint32_t size = 0;
|
||||||
|
uint32_t total_size = 0;
|
||||||
uint32_t offset = 0;
|
uint32_t offset = 0;
|
||||||
const uint32_t checksum_size = esp_core_dump_checksum_size();
|
const uint32_t checksum_size = esp_core_dump_checksum_size();
|
||||||
core_dump_checksum_bytes checksum_calc = NULL;
|
core_dump_checksum_bytes checksum_calc = NULL;
|
||||||
@@ -364,51 +375,15 @@ esp_err_t esp_core_dump_image_get(size_t* out_addr, size_t *out_size)
|
|||||||
/* Assert that we won't have any problems with our checksum size. */
|
/* Assert that we won't have any problems with our checksum size. */
|
||||||
ESP_COREDUMP_DEBUG_ASSERT(checksum_size <= COREDUMP_CHECKSUM_MAX_LEN);
|
ESP_COREDUMP_DEBUG_ASSERT(checksum_size <= COREDUMP_CHECKSUM_MAX_LEN);
|
||||||
|
|
||||||
/* Check the validity of the parameters. */
|
/* Retrieve the partition and size. */
|
||||||
if (out_addr == NULL || out_size == NULL) {
|
err = esp_core_dump_partition_and_size_get(&core_part, &total_size);
|
||||||
return ESP_ERR_INVALID_ARG;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Find the partition that could potentially contain a (previous) core dump. */
|
|
||||||
const esp_partition_t *core_part = esp_partition_find_first(ESP_PARTITION_TYPE_DATA,
|
|
||||||
ESP_PARTITION_SUBTYPE_DATA_COREDUMP,
|
|
||||||
NULL);
|
|
||||||
if (!core_part) {
|
|
||||||
ESP_LOGE(TAG, "No core dump partition found!");
|
|
||||||
return ESP_ERR_NOT_FOUND;
|
|
||||||
}
|
|
||||||
if (core_part->size < sizeof(uint32_t)) {
|
|
||||||
ESP_LOGE(TAG, "Too small core dump partition!");
|
|
||||||
return ESP_ERR_INVALID_SIZE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* The partition has been found, get its first uint32_t value, which
|
|
||||||
* describes the core dump file size. */
|
|
||||||
err = esp_partition_read(core_part, 0, &size, sizeof(uint32_t));
|
|
||||||
if (err != ESP_OK) {
|
|
||||||
ESP_LOGE(TAG, "Failed to read core dump data size (%d)!", err);
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Verify that the size read from the flash is not corrupted. */
|
|
||||||
if (size == 0xFFFFFFFF) {
|
|
||||||
ESP_LOGD(TAG, "Blank core dump partition!");
|
|
||||||
err = ESP_ERR_INVALID_SIZE;
|
|
||||||
} else if ((size < sizeof(uint32_t)) || (size > core_part->size)) {
|
|
||||||
ESP_LOGE(TAG, "Incorrect size of core dump image: %d", size);
|
|
||||||
err = ESP_ERR_INVALID_SIZE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (err != ESP_OK) {
|
if (err != ESP_OK) {
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Save the size read. */
|
|
||||||
*out_size = size;
|
|
||||||
|
|
||||||
/* The final checksum, from the image, doesn't take part into the checksum
|
/* The final checksum, from the image, doesn't take part into the checksum
|
||||||
* calculation, so subtract it from the bytes we are going to read. */
|
* calculation, so subtract it from the bytes we are going to read. */
|
||||||
size -= checksum_size ;
|
size = total_size - checksum_size ;
|
||||||
|
|
||||||
/* Initiate the checksum calculation for the coredump in the flash. */
|
/* Initiate the checksum calculation for the coredump in the flash. */
|
||||||
esp_core_dump_checksum_init(&wr_data.checksum_ctx);
|
esp_core_dump_checksum_init(&wr_data.checksum_ctx);
|
||||||
@@ -421,7 +396,7 @@ esp_err_t esp_core_dump_image_get(size_t* out_addr, size_t *out_size)
|
|||||||
/* Read the content of the flash. */
|
/* Read the content of the flash. */
|
||||||
err = esp_partition_read(core_part, offset, wr_data.cached_data, toread);
|
err = esp_partition_read(core_part, offset, wr_data.cached_data, toread);
|
||||||
if (err != ESP_OK) {
|
if (err != ESP_OK) {
|
||||||
ESP_LOGE(TAG, "Failed to read data from core dump (%d)!", err);
|
ESP_COREDUMP_LOGE("Failed to read data from core dump (%d)!", err);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -438,24 +413,136 @@ esp_err_t esp_core_dump_image_get(size_t* out_addr, size_t *out_size)
|
|||||||
|
|
||||||
/* Read the checksum from the flash and compare to the one just
|
/* Read the checksum from the flash and compare to the one just
|
||||||
* calculated. */
|
* calculated. */
|
||||||
err = esp_partition_read(core_part, *out_size - checksum_size, checksum_read, checksum_size);
|
err = esp_partition_read(core_part, total_size - checksum_size, checksum_read, checksum_size);
|
||||||
if (err != ESP_OK) {
|
if (err != ESP_OK) {
|
||||||
ESP_LOGE(TAG, "Failed to read checksum from core dump (%d)!", err);
|
ESP_COREDUMP_LOGE("Failed to read checksum from core dump (%d)!", err);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Compare the checksum read from the flash and the one just calculated. */
|
/* Compare the checksum read from the flash and the one just calculated. */
|
||||||
if (memcmp(checksum_calc, checksum_read, checksum_size) != 0) {
|
if (memcmp(checksum_calc, checksum_read, checksum_size) != 0) {
|
||||||
ESP_LOGE(TAG, "Core dump data check failed:");
|
ESP_COREDUMP_LOGE("Core dump data check failed:");
|
||||||
esp_core_dump_print_checksum("Calculated checksum", checksum_calc);
|
esp_core_dump_print_checksum("Calculated checksum", checksum_calc);
|
||||||
esp_core_dump_print_checksum("Image checksum", checksum_read);
|
esp_core_dump_print_checksum("Image checksum", checksum_read);
|
||||||
return ESP_ERR_INVALID_CRC;
|
return ESP_ERR_INVALID_CRC;
|
||||||
} else {
|
} else {
|
||||||
ESP_LOGI(TAG, "Core dump data checksum is correct");
|
ESP_COREDUMP_LOGI("Core dump data checksum is correct");
|
||||||
}
|
}
|
||||||
|
|
||||||
*out_addr = core_part->address;
|
|
||||||
return ESP_OK;
|
return ESP_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
esp_err_t esp_core_dump_image_erase(void)
|
||||||
|
{
|
||||||
|
/* Find the partition that could potentially contain a (previous) core dump. */
|
||||||
|
const esp_partition_t *core_part = esp_partition_find_first(ESP_PARTITION_TYPE_DATA,
|
||||||
|
ESP_PARTITION_SUBTYPE_DATA_COREDUMP,
|
||||||
|
NULL);
|
||||||
|
if (!core_part) {
|
||||||
|
ESP_LOGE(TAG, "No core dump partition found!");
|
||||||
|
return ESP_ERR_NOT_FOUND;
|
||||||
|
}
|
||||||
|
if (core_part->size < sizeof(uint32_t)) {
|
||||||
|
ESP_LOGE(TAG, "Too small core dump partition!");
|
||||||
|
return ESP_ERR_INVALID_SIZE;
|
||||||
|
}
|
||||||
|
|
||||||
|
esp_err_t err = ESP_OK;
|
||||||
|
err = esp_partition_erase_range(core_part, 0, core_part->size);
|
||||||
|
if (err != ESP_OK) {
|
||||||
|
ESP_LOGE(TAG, "Failed to erase core dump partition (%d)!", err);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Mark core dump as deleted by setting field size
|
||||||
|
const uint32_t blank_size = BLANK_COREDUMP_SIZE;
|
||||||
|
err = esp_partition_write(core_part, 0, &blank_size, sizeof(blank_size));
|
||||||
|
if (err != ESP_OK) {
|
||||||
|
ESP_LOGE(TAG, "Failed to write core dump partition size (%d)!", err);
|
||||||
|
}
|
||||||
|
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
static esp_err_t esp_core_dump_partition_and_size_get(const esp_partition_t **partition, uint32_t* size)
|
||||||
|
{
|
||||||
|
uint32_t core_size = 0;
|
||||||
|
const esp_partition_t *core_part = NULL;
|
||||||
|
|
||||||
|
/* Check the arguments, at least one should be provided. */
|
||||||
|
if (partition == NULL && size == NULL) {
|
||||||
|
return ESP_ERR_INVALID_ARG;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Find the partition that could potentially contain a (previous) core dump. */
|
||||||
|
core_part = esp_partition_find_first(ESP_PARTITION_TYPE_DATA,
|
||||||
|
ESP_PARTITION_SUBTYPE_DATA_COREDUMP,
|
||||||
|
NULL);
|
||||||
|
if (core_part == NULL) {
|
||||||
|
ESP_COREDUMP_LOGE("No core dump partition found!");
|
||||||
|
return ESP_ERR_NOT_FOUND;
|
||||||
|
}
|
||||||
|
if (core_part->size < sizeof(uint32_t)) {
|
||||||
|
ESP_COREDUMP_LOGE("Too small core dump partition!");
|
||||||
|
return ESP_ERR_INVALID_SIZE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* The partition has been found, get its first uint32_t value, which
|
||||||
|
* describes the core dump file size. */
|
||||||
|
esp_err_t err = esp_partition_read(core_part, 0, &core_size, sizeof(uint32_t));
|
||||||
|
if (err != ESP_OK) {
|
||||||
|
ESP_COREDUMP_LOGE("Failed to read core dump data size (%d)!", err);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Verify that the size read from the flash is not corrupted. */
|
||||||
|
if (core_size == 0xFFFFFFFF) {
|
||||||
|
ESP_COREDUMP_LOGD("Blank core dump partition!");
|
||||||
|
return ESP_ERR_INVALID_SIZE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((core_size < sizeof(uint32_t)) || (core_size > core_part->size)) {
|
||||||
|
ESP_COREDUMP_LOGE("Incorrect size of core dump image: %d", core_size);
|
||||||
|
return ESP_ERR_INVALID_SIZE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Return the values if needed. */
|
||||||
|
if (partition != NULL) {
|
||||||
|
*partition = core_part;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (size != NULL) {
|
||||||
|
*size = core_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ESP_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
esp_err_t esp_core_dump_image_get(size_t* out_addr, size_t *out_size)
|
||||||
|
{
|
||||||
|
esp_err_t err = ESP_OK;
|
||||||
|
uint32_t size = 0;
|
||||||
|
const esp_partition_t *core_part = NULL;
|
||||||
|
|
||||||
|
/* Check the validity of the parameters. */
|
||||||
|
if (out_addr == NULL || out_size == NULL) {
|
||||||
|
return ESP_ERR_INVALID_ARG;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Retrieve the partition and size. */
|
||||||
|
err = esp_core_dump_partition_and_size_get(&core_part, &size);
|
||||||
|
|
||||||
|
if (err != ESP_OK) {
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Save the address. */
|
||||||
|
*out_addr = core_part->address;
|
||||||
|
|
||||||
|
/* Save the size read. */
|
||||||
|
*out_size = size;
|
||||||
|
|
||||||
|
return ESP_OK;
|
||||||
|
}
|
||||||
|
Reference in New Issue
Block a user