diff --git a/components/espcoredump/Kconfig b/components/espcoredump/Kconfig index 83811c76cd..9134413832 100644 --- a/components/espcoredump/Kconfig +++ b/components/espcoredump/Kconfig @@ -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 diff --git a/components/espcoredump/include/esp_core_dump.h b/components/espcoredump/include/esp_core_dump.h index 818c0a3519..7854d4a51d 100644 --- a/components/espcoredump/include/esp_core_dump.h +++ b/components/espcoredump/include/esp_core_dump.h @@ -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. diff --git a/components/espcoredump/src/core_dump_flash.c b/components/espcoredump/src/core_dump_flash.c index 33412d61fc..55b8383c67 100644 --- a/components/espcoredump/src/core_dump_flash.c +++ b/components/espcoredump/src/core_dump_flash.c @@ -59,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; @@ -72,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)); @@ -304,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; } @@ -343,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; @@ -366,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 == BLANK_COREDUMP_SIZE) { - ESP_LOGD(TAG, "Coredump not found, blank core dump partition!"); - err = ESP_ERR_NOT_FOUND; - } 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); @@ -423,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; } @@ -440,23 +413,22 @@ 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; } @@ -493,3 +465,84 @@ esp_err_t esp_core_dump_image_erase(void) 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; +}