mirror of
https://github.com/espressif/esp-idf.git
synced 2025-07-31 19:24:33 +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
|
||||
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
|
||||
bool
|
||||
default F
|
||||
|
@@ -78,6 +78,19 @@ void esp_core_dump_to_uart(panic_info_t *info);
|
||||
/*********************************** 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.
|
||||
* 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);
|
||||
|
||||
/**
|
||||
* @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
|
||||
}
|
||||
#endif
|
||||
|
@@ -20,6 +20,8 @@
|
||||
#include "esp_flash_encrypt.h"
|
||||
#include "esp_rom_crc.h"
|
||||
|
||||
#define BLANK_COREDUMP_SIZE 0xFFFFFFFF
|
||||
|
||||
const static DRAM_ATTR char TAG[] __attribute__((unused)) = "esp_core_dump_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_)
|
||||
#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)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
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;
|
||||
ESP_COREDUMP_LOGI("Write end offset 0x%x, check sum length %d", wr_data->off, cs_len);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
@@ -341,19 +345,26 @@ void esp_core_dump_to_flash(panic_info_t *info)
|
||||
|
||||
void esp_core_dump_init(void)
|
||||
{
|
||||
size_t core_data_sz = 0;
|
||||
size_t core_data_addr = 0;
|
||||
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;
|
||||
const esp_partition_t *core_part = NULL;
|
||||
core_dump_write_data_t wr_data = { 0 };
|
||||
uint32_t size = 0;
|
||||
uint32_t total_size = 0;
|
||||
uint32_t offset = 0;
|
||||
const uint32_t checksum_size = esp_core_dump_checksum_size();
|
||||
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. */
|
||||
ESP_COREDUMP_DEBUG_ASSERT(checksum_size <= COREDUMP_CHECKSUM_MAX_LEN);
|
||||
|
||||
/* Check the validity of the parameters. */
|
||||
if (out_addr == NULL || out_size == NULL) {
|
||||
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;
|
||||
}
|
||||
|
||||
/* Retrieve the partition and size. */
|
||||
err = esp_core_dump_partition_and_size_get(&core_part, &total_size);
|
||||
if (err != ESP_OK) {
|
||||
return err;
|
||||
}
|
||||
|
||||
/* Save the size read. */
|
||||
*out_size = size;
|
||||
|
||||
/* 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. */
|
||||
size -= checksum_size ;
|
||||
size = total_size - checksum_size ;
|
||||
|
||||
/* Initiate the checksum calculation for the coredump in the flash. */
|
||||
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. */
|
||||
err = esp_partition_read(core_part, offset, wr_data.cached_data, toread);
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -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
|
||||
* 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) {
|
||||
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;
|
||||
}
|
||||
|
||||
/* Compare the checksum read from the flash and the one just calculated. */
|
||||
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("Image checksum", checksum_read);
|
||||
return ESP_ERR_INVALID_CRC;
|
||||
} 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;
|
||||
}
|
||||
|
||||
#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