mirror of
https://github.com/espressif/esp-idf.git
synced 2025-07-31 19:24:33 +02:00
Merge branch 'bugfix/plain_coredump_encrypted_flash' into 'master'
coredump: fix plain coredump written on an encrypted flash Closes IDF-458 See merge request espressif/esp-idf!11166
This commit is contained in:
@@ -73,22 +73,29 @@ typedef esp_err_t (*esp_core_dump_flash_write_data_t)(void *priv, void * data, u
|
||||
|
||||
typedef uint32_t core_dump_crc_t;
|
||||
|
||||
/**
|
||||
* The following macro defines the size of the cache used to write the coredump
|
||||
* to the flash. When the flash is encrypted, the smallest data block we can
|
||||
* write to it is 16 bytes long. Thus, this macro MUST be a multiple of 16.
|
||||
*/
|
||||
#define COREDUMP_CACHE_SIZE 32
|
||||
|
||||
#if (COREDUMP_CACHE_SIZE % 16) != 0
|
||||
#error "Coredump cache size must be a multiple of 16"
|
||||
#endif
|
||||
|
||||
typedef struct _core_dump_write_data_t
|
||||
{
|
||||
// TODO: move flash related data to flash-specific code
|
||||
uint32_t off; // current offset in partition
|
||||
union
|
||||
{
|
||||
uint8_t data8[4];
|
||||
uint32_t data32;
|
||||
} cached_data;
|
||||
uint8_t cached_bytes;
|
||||
uint32_t off; // current offset in partition
|
||||
uint8_t cached_data[COREDUMP_CACHE_SIZE];
|
||||
uint8_t cached_bytes;
|
||||
#if CONFIG_ESP_COREDUMP_CHECKSUM_SHA256
|
||||
// TODO: move this to portable part of the code
|
||||
mbedtls_sha256_context ctx;
|
||||
char sha_output[COREDUMP_SHA256_LEN];
|
||||
char sha_output[COREDUMP_SHA256_LEN];
|
||||
#elif CONFIG_ESP_COREDUMP_CHECKSUM_CRC32
|
||||
core_dump_crc_t crc; // CRC of dumped data
|
||||
core_dump_crc_t crc; // CRC of dumped data
|
||||
#endif
|
||||
} core_dump_write_data_t;
|
||||
|
||||
|
@@ -16,6 +16,7 @@
|
||||
#include "esp_log.h"
|
||||
#include "esp_core_dump_priv.h"
|
||||
#include "esp_flash_internal.h"
|
||||
#include "esp_flash_encrypt.h"
|
||||
#include "esp_rom_crc.h"
|
||||
|
||||
const static DRAM_ATTR char TAG[] __attribute__((unused)) = "esp_core_dump_flash";
|
||||
@@ -24,33 +25,46 @@ const static DRAM_ATTR char TAG[] __attribute__((unused)) = "esp_core_dump_flash
|
||||
|
||||
typedef struct _core_dump_partition_t
|
||||
{
|
||||
// core dump partition start
|
||||
/* Core dump partition start. */
|
||||
uint32_t start;
|
||||
// core dump partition size
|
||||
/* Core dump partition size. */
|
||||
uint32_t size;
|
||||
} core_dump_partition_t;
|
||||
|
||||
typedef struct _core_dump_flash_config_t
|
||||
{
|
||||
// core dump partition config
|
||||
/* Core dump partition config. */
|
||||
core_dump_partition_t partition;
|
||||
// CRC of core dump partition config
|
||||
core_dump_crc_t partition_config_crc;
|
||||
/* CRC of core dump partition config. */
|
||||
core_dump_crc_t partition_config_crc;
|
||||
} core_dump_flash_config_t;
|
||||
|
||||
// core dump flash data
|
||||
/* Core dump flash data. */
|
||||
static core_dump_flash_config_t s_core_flash_config;
|
||||
|
||||
#ifdef CONFIG_SPI_FLASH_USE_LEGACY_IMPL
|
||||
#define ESP_COREDUMP_FLASH_WRITE(_off_, _data_, _len_) spi_flash_write(_off_, _data_, _len_)
|
||||
#define ESP_COREDUMP_FLASH_READ(_off_, _data_, _len_) spi_flash_read(_off_, _data_, _len_)
|
||||
#define ESP_COREDUMP_FLASH_ERASE(_off_, _len_) spi_flash_erase_range(_off_, _len_)
|
||||
#define ESP_COREDUMP_FLASH_WRITE(_off_, _data_, _len_) spi_flash_write(_off_, _data_, _len_)
|
||||
#define ESP_COREDUMP_FLASH_WRITE_ENCRYPTED(_off_, _data_, _len_) spi_flash_write_encrypted(_off_, _data_, _len_)
|
||||
#define ESP_COREDUMP_FLASH_ERASE(_off_, _len_) spi_flash_erase_range(_off_, _len_)
|
||||
#else
|
||||
#define ESP_COREDUMP_FLASH_WRITE(_off_, _data_, _len_) esp_flash_write(esp_flash_default_chip, _data_, _off_, _len_)
|
||||
#define ESP_COREDUMP_FLASH_READ(_off_, _data_, _len_) esp_flash_read(esp_flash_default_chip, _data_, _off_, _len_)
|
||||
#define ESP_COREDUMP_FLASH_ERASE(_off_, _len_) esp_flash_erase_region(esp_flash_default_chip, _off_, _len_)
|
||||
#define ESP_COREDUMP_FLASH_WRITE(_off_, _data_, _len_) esp_flash_write(esp_flash_default_chip, _data_, _off_, _len_)
|
||||
#define ESP_COREDUMP_FLASH_WRITE_ENCRYPTED(_off_, _data_, _len_) esp_flash_write_encrypted(esp_flash_default_chip, _off_, _data_, _len_)
|
||||
#define ESP_COREDUMP_FLASH_ERASE(_off_, _len_) esp_flash_erase_region(esp_flash_default_chip, _off_, _len_)
|
||||
#endif
|
||||
|
||||
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;
|
||||
|
||||
if (esp_flash_encryption_enabled()) {
|
||||
err = ESP_COREDUMP_FLASH_WRITE_ENCRYPTED(address, buffer, length);
|
||||
} else {
|
||||
err = ESP_COREDUMP_FLASH_WRITE(address, buffer, length);
|
||||
}
|
||||
|
||||
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)
|
||||
@@ -60,8 +74,9 @@ static inline core_dump_crc_t esp_core_dump_calc_flash_config_crc(void)
|
||||
|
||||
void esp_core_dump_flash_init(void)
|
||||
{
|
||||
const esp_partition_t *core_part;
|
||||
const esp_partition_t *core_part = NULL;
|
||||
|
||||
/* Look for the core dump partition on the flash. */
|
||||
ESP_COREDUMP_LOGI("Init core dump to flash");
|
||||
core_part = esp_partition_find_first(ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_DATA_COREDUMP, NULL);
|
||||
if (!core_part) {
|
||||
@@ -76,45 +91,79 @@ void esp_core_dump_flash_init(void)
|
||||
|
||||
static esp_err_t esp_core_dump_flash_write_data(void *priv, uint8_t *data, uint32_t data_size)
|
||||
{
|
||||
esp_err_t err;
|
||||
core_dump_write_data_t *wr_data = (core_dump_write_data_t *)priv;
|
||||
uint32_t written = 0, wr_sz;
|
||||
esp_err_t err = ESP_OK;
|
||||
uint32_t written = 0;
|
||||
uint32_t wr_sz = 0;
|
||||
|
||||
/* Make sure that the partition is large enough to hold the data. */
|
||||
assert((wr_data->off + data_size) < s_core_flash_config.partition.size);
|
||||
|
||||
if (wr_data->cached_bytes) {
|
||||
if ((sizeof(wr_data->cached_data)-wr_data->cached_bytes) > data_size)
|
||||
/* Some bytes are in the cache, let's continue filling the cache
|
||||
* with the data received as parameter. Let's calculate the maximum
|
||||
* amount of bytes we can still fill the cache with. */
|
||||
if ((COREDUMP_CACHE_SIZE - wr_data->cached_bytes) > data_size)
|
||||
wr_sz = data_size;
|
||||
else
|
||||
wr_sz = sizeof(wr_data->cached_data)-wr_data->cached_bytes;
|
||||
// append to data cache
|
||||
memcpy(&wr_data->cached_data.data8[wr_data->cached_bytes], data, wr_sz);
|
||||
wr_sz = COREDUMP_CACHE_SIZE - wr_data->cached_bytes;
|
||||
|
||||
/* Append wr_sz bytes from data parameter to the cache. */
|
||||
memcpy(&wr_data->cached_data[wr_data->cached_bytes], data, wr_sz);
|
||||
wr_data->cached_bytes += wr_sz;
|
||||
if (wr_data->cached_bytes == sizeof(wr_data->cached_data)) {
|
||||
err = ESP_COREDUMP_FLASH_WRITE(s_core_flash_config.partition.start + wr_data->off, &wr_data->cached_data, sizeof(wr_data->cached_data));
|
||||
|
||||
if (wr_data->cached_bytes == COREDUMP_CACHE_SIZE) {
|
||||
/* The cache is full, we can flush it to the flash. */
|
||||
err = esp_core_dump_flash_custom_write(s_core_flash_config.partition.start + wr_data->off,
|
||||
wr_data->cached_data,
|
||||
COREDUMP_CACHE_SIZE);
|
||||
if (err != ESP_OK) {
|
||||
ESP_COREDUMP_LOGE("Failed to write cached data to flash (%d)!", err);
|
||||
return err;
|
||||
}
|
||||
// update checksum according to padding
|
||||
esp_core_dump_checksum_update(wr_data, &wr_data->cached_data, sizeof(wr_data->cached_data));
|
||||
// reset data cache
|
||||
/* The offset of the next data that will be written onto the flash
|
||||
* can now be increased. */
|
||||
wr_data->off += COREDUMP_CACHE_SIZE;
|
||||
|
||||
/* Update checksum with the newly written data on the flash. */
|
||||
esp_core_dump_checksum_update(wr_data, &wr_data->cached_data, COREDUMP_CACHE_SIZE);
|
||||
|
||||
/* Reset cache from the next use. */
|
||||
wr_data->cached_bytes = 0;
|
||||
memset(&wr_data->cached_data, 0, sizeof(wr_data->cached_data));
|
||||
memset(wr_data->cached_data, 0, COREDUMP_CACHE_SIZE);
|
||||
}
|
||||
wr_data->off += sizeof(wr_data->cached_data);
|
||||
|
||||
written += wr_sz;
|
||||
data_size -= wr_sz;
|
||||
}
|
||||
|
||||
wr_sz = (data_size / sizeof(wr_data->cached_data)) * sizeof(wr_data->cached_data);
|
||||
/* Figure out how many bytes we can write onto the flash directly, without
|
||||
* using the cache. In our case the cache size is a multiple of the flash's
|
||||
* minimum writing block size, so we will use it for our calculation.
|
||||
* For example, if COREDUMP_CACHE_SIZE equals 32, here are interesting
|
||||
* values:
|
||||
* +---------+-----------------------+
|
||||
* | | data_size |
|
||||
* +---------+---+----+----+----+----+
|
||||
* | | 0 | 31 | 32 | 40 | 64 |
|
||||
* +---------+---+----+----+----+----+
|
||||
* | (blocks | 0 | 0 | 1 | 1 | 2) |
|
||||
* +---------+---+----+----+----+----+
|
||||
* | wr_sz | 0 | 0 | 32 | 32 | 64 |
|
||||
* +---------+---+----+----+----+----+
|
||||
*/
|
||||
wr_sz = (data_size / COREDUMP_CACHE_SIZE) * COREDUMP_CACHE_SIZE;
|
||||
if (wr_sz) {
|
||||
err = ESP_COREDUMP_FLASH_WRITE(s_core_flash_config.partition.start + wr_data->off, data + written, wr_sz);
|
||||
/* Write the contiguous amount of bytes to the flash,
|
||||
* without using the cache */
|
||||
err = esp_core_dump_flash_custom_write(s_core_flash_config.partition.start + wr_data->off, data + written, wr_sz);
|
||||
|
||||
if (err != ESP_OK) {
|
||||
ESP_COREDUMP_LOGE("Failed to write data to flash (%d)!", err);
|
||||
return err;
|
||||
}
|
||||
// update checksum of data written
|
||||
|
||||
/* Update the checksum with the newly written bytes */
|
||||
esp_core_dump_checksum_update(wr_data, data + written, wr_sz);
|
||||
wr_data->off += wr_sz;
|
||||
written += wr_sz;
|
||||
@@ -122,7 +171,9 @@ static esp_err_t esp_core_dump_flash_write_data(void *priv, uint8_t *data, uint3
|
||||
}
|
||||
|
||||
if (data_size > 0) {
|
||||
// append to data cache
|
||||
/* There still some bytes from the data parameter that need to be sent,
|
||||
* append it to cache in order to write them later. (i.e. when there
|
||||
* will be enough bytes to fill the cache) */
|
||||
memcpy(&wr_data->cached_data, data + written, data_size);
|
||||
wr_data->cached_bytes = data_size;
|
||||
}
|
||||
@@ -132,33 +183,53 @@ static esp_err_t esp_core_dump_flash_write_data(void *priv, uint8_t *data, uint3
|
||||
|
||||
static esp_err_t esp_core_dump_flash_write_prepare(void *priv, uint32_t *data_len)
|
||||
{
|
||||
esp_err_t err;
|
||||
uint32_t sec_num;
|
||||
core_dump_write_data_t *wr_data = (core_dump_write_data_t *)priv;
|
||||
uint32_t cs_len;
|
||||
esp_err_t err = ESP_OK;
|
||||
uint32_t sec_num = 0;
|
||||
uint32_t cs_len = 0;
|
||||
|
||||
/* Get the length, in bytes, of the checksum. */
|
||||
cs_len = esp_core_dump_checksum_finish(wr_data, NULL);
|
||||
|
||||
// check for available space in partition
|
||||
if ((*data_len + cs_len) > s_core_flash_config.partition.size) {
|
||||
/* At the end of the core dump file, a padding may be added, according to the
|
||||
* cache size. We must take that padding into account. */
|
||||
uint32_t padding = 0;
|
||||
const uint32_t modulo = *data_len % COREDUMP_CACHE_SIZE;
|
||||
if (modulo != 0) {
|
||||
/* The data length is not a multiple of the cache size,
|
||||
* so there will be a padding. */
|
||||
padding = COREDUMP_CACHE_SIZE - modulo;
|
||||
}
|
||||
|
||||
/* Now we can check whether we have enough space in our core dump parition
|
||||
* or not. */
|
||||
if ((*data_len + padding + cs_len) > s_core_flash_config.partition.size) {
|
||||
ESP_COREDUMP_LOGE("Not enough space to save core dump!");
|
||||
return ESP_ERR_NO_MEM;
|
||||
}
|
||||
// add space for checksum
|
||||
*data_len += cs_len;
|
||||
|
||||
/* We have enough space in the partition, add the padding and the checksum
|
||||
* in the core dump file calculation. */
|
||||
*data_len += padding + cs_len;
|
||||
|
||||
memset(wr_data, 0, sizeof(core_dump_write_data_t));
|
||||
|
||||
/* In order to erase the right amount of data in the flash, we have to
|
||||
* calculate how many SPI flash sectors will be needed by the core dump
|
||||
* file. */
|
||||
sec_num = *data_len / SPI_FLASH_SEC_SIZE;
|
||||
if (*data_len % SPI_FLASH_SEC_SIZE) {
|
||||
sec_num++;
|
||||
}
|
||||
|
||||
/* Erase the amount of sectors needed. */
|
||||
ESP_COREDUMP_LOGI("Erase flash %d bytes @ 0x%x", sec_num * SPI_FLASH_SEC_SIZE, s_core_flash_config.partition.start + 0);
|
||||
assert(sec_num * SPI_FLASH_SEC_SIZE <= s_core_flash_config.partition.size);
|
||||
err = ESP_COREDUMP_FLASH_ERASE(s_core_flash_config.partition.start + 0, sec_num * SPI_FLASH_SEC_SIZE);
|
||||
if (err != ESP_OK) {
|
||||
ESP_COREDUMP_LOGE("Failed to erase flash (%d)!", err);
|
||||
return err;
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
@@ -171,82 +242,90 @@ static esp_err_t esp_core_dump_flash_write_start(void *priv)
|
||||
|
||||
static esp_err_t esp_core_dump_flash_write_end(void *priv)
|
||||
{
|
||||
esp_err_t err;
|
||||
esp_err_t err = ESP_OK;
|
||||
void* checksum = NULL;
|
||||
uint32_t cs_len = 0;
|
||||
core_dump_write_data_t *wr_data = (core_dump_write_data_t *)priv;
|
||||
void* checksum;
|
||||
uint32_t cs_len = esp_core_dump_checksum_finish(wr_data, &checksum);
|
||||
|
||||
// flush cached bytes with zero padding
|
||||
/* Get the size, in bytes of the checksum. */
|
||||
cs_len = esp_core_dump_checksum_finish(wr_data, NULL);
|
||||
|
||||
/* Flush cached bytes, including the zero padding at the end (if any). */
|
||||
if (wr_data->cached_bytes) {
|
||||
err = ESP_COREDUMP_FLASH_WRITE(s_core_flash_config.partition.start + wr_data->off, &wr_data->cached_data, sizeof(wr_data->cached_data));
|
||||
err = esp_core_dump_flash_custom_write(s_core_flash_config.partition.start + wr_data->off,
|
||||
wr_data->cached_data,
|
||||
COREDUMP_CACHE_SIZE);
|
||||
|
||||
if (err != ESP_OK) {
|
||||
ESP_COREDUMP_LOGE("Failed to flush cached data to flash (%d)!", err);
|
||||
return err;
|
||||
}
|
||||
// update checksum according to padding
|
||||
esp_core_dump_checksum_update(wr_data, &wr_data->cached_data, sizeof(wr_data->cached_data));
|
||||
wr_data->off += sizeof(wr_data->cached_data);
|
||||
|
||||
/* Update the checksum with the data written, including the padding. */
|
||||
esp_core_dump_checksum_update(wr_data, wr_data->cached_data, COREDUMP_CACHE_SIZE);
|
||||
wr_data->off += COREDUMP_CACHE_SIZE;
|
||||
wr_data->cached_bytes = 0;
|
||||
}
|
||||
err = ESP_COREDUMP_FLASH_WRITE(s_core_flash_config.partition.start + wr_data->off, checksum, cs_len);
|
||||
|
||||
/* All data have been written to the flash, the cache is now empty, we can
|
||||
* terminate the checksum calculation. */
|
||||
esp_core_dump_checksum_finish(wr_data, &checksum);
|
||||
|
||||
/* Use the cache to write the checksum if its size doesn't match the requirements.
|
||||
* (e.g. its size is not a multiple of 32) */
|
||||
if (cs_len < COREDUMP_CACHE_SIZE) {
|
||||
/* Copy the checksum into the cache. */
|
||||
memcpy(wr_data->cached_data, checksum, cs_len);
|
||||
|
||||
/* Fill the rest of the cache with zeros. */
|
||||
memset(wr_data->cached_data + cs_len, 0, COREDUMP_CACHE_SIZE - cs_len);
|
||||
|
||||
/* Finally, write the checksum on the flash, using the cache. */
|
||||
err = esp_core_dump_flash_custom_write(s_core_flash_config.partition.start + wr_data->off,
|
||||
wr_data->cached_data,
|
||||
COREDUMP_CACHE_SIZE);
|
||||
} else {
|
||||
/* In that case, the length of the checksum must be a multiple of 16. */
|
||||
assert(cs_len % 16 == 0);
|
||||
err = esp_core_dump_flash_custom_write(s_core_flash_config.partition.start + wr_data->off, checksum, cs_len);
|
||||
}
|
||||
|
||||
if (err != ESP_OK) {
|
||||
ESP_COREDUMP_LOGE("Failed to flush cached data to flash (%d)!", err);
|
||||
return err;
|
||||
}
|
||||
wr_data->off += cs_len;
|
||||
ESP_COREDUMP_LOGI("Write end offset 0x%x, check sum length %d", wr_data->off, cs_len);
|
||||
#if LOG_LOCAL_LEVEL >= ESP_LOG_DEBUG
|
||||
union
|
||||
{
|
||||
uint8_t data8[sizeof(core_dump_header_t)];
|
||||
uint32_t data32[sizeof(core_dump_header_t)/sizeof(uint32_t)];
|
||||
} rom_data;
|
||||
err = ESP_COREDUMP_FLASH_READ(s_core_flash_config.partition.start + 0, &rom_data, sizeof(rom_data));
|
||||
if (err != ESP_OK) {
|
||||
ESP_COREDUMP_LOGE("Failed to read back coredump header (%d)!", err);
|
||||
return err;
|
||||
} else {
|
||||
ESP_COREDUMP_LOG_PROCESS("Core dump header words from flash:");
|
||||
for (uint32_t i = 0; i < sizeof(rom_data)/sizeof(uint32_t); i++) {
|
||||
ESP_COREDUMP_LOG_PROCESS("0x%x", rom_data.data32[i]);
|
||||
}
|
||||
}
|
||||
uint32_t crc;
|
||||
err = ESP_COREDUMP_FLASH_READ(s_core_flash_config.partition.start + wr_data->off - cs_len, &crc, sizeof(crc));
|
||||
if (err != ESP_OK) {
|
||||
ESP_COREDUMP_LOGE("Failed to read back checksum word (%d)!", err);
|
||||
return err;
|
||||
} else {
|
||||
ESP_COREDUMP_LOG_PROCESS("Checksum word from flash: 0x%x @ 0x%x", crc, wr_data->off - cs_len);
|
||||
}
|
||||
#endif
|
||||
return err;
|
||||
}
|
||||
|
||||
void esp_core_dump_to_flash(panic_info_t *info)
|
||||
{
|
||||
static core_dump_write_config_t wr_cfg;
|
||||
static core_dump_write_data_t wr_data;
|
||||
static core_dump_write_config_t wr_cfg = { 0 };
|
||||
static core_dump_write_data_t wr_data = { 0 };
|
||||
|
||||
/* Check core dump partition configuration. */
|
||||
core_dump_crc_t crc = esp_core_dump_calc_flash_config_crc();
|
||||
if (s_core_flash_config.partition_config_crc != crc) {
|
||||
ESP_COREDUMP_LOGE("Core dump flash config is corrupted! CRC=0x%x instead of 0x%x", crc, s_core_flash_config.partition_config_crc);
|
||||
return;
|
||||
}
|
||||
// check that partition can hold at least core dump data length
|
||||
|
||||
/* Make sure that the partition can at least data length. */
|
||||
if (s_core_flash_config.partition.start == 0 || s_core_flash_config.partition.size < sizeof(uint32_t)) {
|
||||
ESP_COREDUMP_LOGE("Invalid flash partition config!");
|
||||
return;
|
||||
}
|
||||
|
||||
// init non-OS flash access critical section
|
||||
/* Initialize non-OS flash access critical section. */
|
||||
spi_flash_guard_set(&g_flash_guard_no_os_ops);
|
||||
esp_flash_app_disable_protect(true);
|
||||
|
||||
memset(&wr_cfg, 0, sizeof(wr_cfg));
|
||||
/* Register the callbacks that will be called later by the generic part. */
|
||||
wr_cfg.prepare = esp_core_dump_flash_write_prepare;
|
||||
wr_cfg.start = esp_core_dump_flash_write_start;
|
||||
wr_cfg.end = esp_core_dump_flash_write_end;
|
||||
wr_cfg.write = (esp_core_dump_flash_write_data_t)esp_core_dump_flash_write_data;
|
||||
wr_cfg.write = (esp_core_dump_flash_write_data_t) esp_core_dump_flash_write_data;
|
||||
wr_cfg.priv = &wr_data;
|
||||
|
||||
ESP_COREDUMP_LOGI("Save core dump to flash...");
|
||||
@@ -267,14 +346,15 @@ void esp_core_dump_init(void)
|
||||
|
||||
esp_err_t esp_core_dump_image_get(size_t* out_addr, size_t *out_size)
|
||||
{
|
||||
esp_err_t err;
|
||||
const void *core_data;
|
||||
spi_flash_mmap_handle_t core_data_handle;
|
||||
spi_flash_mmap_handle_t core_data_handle = { 0 };
|
||||
esp_err_t err = ESP_OK;
|
||||
const void *core_data = NULL;
|
||||
|
||||
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);
|
||||
@@ -287,6 +367,8 @@ esp_err_t esp_core_dump_image_get(size_t* out_addr, size_t *out_size)
|
||||
return ESP_ERR_INVALID_SIZE;
|
||||
}
|
||||
|
||||
/* The partition has been found, map its first uint32_t value, which
|
||||
* describes the core dump file size. */
|
||||
err = esp_partition_mmap(core_part, 0, sizeof(uint32_t),
|
||||
SPI_FLASH_MMAP_DATA, &core_data, &core_data_handle);
|
||||
if (err != ESP_OK) {
|
||||
@@ -294,6 +376,7 @@ esp_err_t esp_core_dump_image_get(size_t* out_addr, size_t *out_size)
|
||||
return err;
|
||||
}
|
||||
|
||||
/* Extract the size and unmap the partition. */
|
||||
uint32_t *dw = (uint32_t *)core_data;
|
||||
*out_size = *dw;
|
||||
spi_flash_munmap(core_data_handle);
|
||||
@@ -305,19 +388,22 @@ esp_err_t esp_core_dump_image_get(size_t* out_addr, size_t *out_size)
|
||||
return ESP_ERR_INVALID_SIZE;
|
||||
}
|
||||
|
||||
// remap full core dump with CRC
|
||||
/* Remap the full core dump parition, including the final checksum. */
|
||||
err = esp_partition_mmap(core_part, 0, *out_size,
|
||||
SPI_FLASH_MMAP_DATA, &core_data, &core_data_handle);
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGE(TAG, "Failed to mmap core dump data (%d)!", err);
|
||||
return err;
|
||||
}
|
||||
// TODO: check CRC or SHA basing on the version of coredump image stored in flash
|
||||
|
||||
// TODO: check CRC or SHA basing on the version of core dump image stored in flash
|
||||
#if CONFIG_ESP_COREDUMP_CHECKSUM_CRC32
|
||||
uint32_t *crc = (uint32_t *)(((uint8_t *)core_data) + *out_size);
|
||||
crc--; // Point to CRC field
|
||||
/* Decrement crc to make it point onto our CRC checksum. */
|
||||
crc--;
|
||||
|
||||
// Calculate CRC over core dump data except for CRC field
|
||||
/* Calculate CRC checksum again over core dump data read from the flash,
|
||||
* excluding CRC field. */
|
||||
core_dump_crc_t cur_crc = esp_rom_crc32_le(0, (uint8_t const *)core_data, *out_size - sizeof(core_dump_crc_t));
|
||||
if (*crc != cur_crc) {
|
||||
ESP_LOGD(TAG, "Core dump CRC offset 0x%x, data size: %u",
|
||||
@@ -327,14 +413,21 @@ esp_err_t esp_core_dump_image_get(size_t* out_addr, size_t *out_size)
|
||||
return ESP_ERR_INVALID_CRC;
|
||||
}
|
||||
#elif CONFIG_ESP_COREDUMP_CHECKSUM_SHA256
|
||||
/* sha256_ptr will point to our checksum. */
|
||||
uint8_t* sha256_ptr = (uint8_t*)(((uint8_t *)core_data) + *out_size);
|
||||
sha256_ptr -= COREDUMP_SHA256_LEN;
|
||||
ESP_LOGD(TAG, "Core dump data offset, size: %d, %u!",
|
||||
(uint32_t)((uint32_t)sha256_ptr - (uint32_t)core_data), *out_size);
|
||||
|
||||
/* The following array will contain the SHA256 value of the core dump data
|
||||
* read from the flash. */
|
||||
unsigned char sha_output[COREDUMP_SHA256_LEN];
|
||||
mbedtls_sha256_context ctx;
|
||||
ESP_LOGI(TAG, "Calculate SHA256 for coredump:");
|
||||
(void)esp_core_dump_sha(&ctx, core_data, *out_size - COREDUMP_SHA256_LEN, sha_output);
|
||||
|
||||
/* Compare the two checksums, if they are different, the file on the flash
|
||||
* may be corrupted. */
|
||||
if (memcmp((uint8_t*)sha256_ptr, (uint8_t*)sha_output, COREDUMP_SHA256_LEN) != 0) {
|
||||
ESP_LOGE(TAG, "Core dump data SHA256 check failed:");
|
||||
esp_core_dump_print_sha256("Calculated SHA256", (uint8_t*)sha_output);
|
||||
|
Reference in New Issue
Block a user