Merge branch 'coredump_refactoring' into 'master'

Coredump refactoring

See merge request espressif/esp-idf!29268
This commit is contained in:
Erhan Kurubas 2024-03-07 21:23:39 +08:00
commit 4462a2040f
15 changed files with 307 additions and 352 deletions

View File

@ -376,14 +376,8 @@ void esp_panic_handler(panic_info_t *info)
} else {
disable_all_wdts();
s_dumping_core = true;
#if CONFIG_ESP_COREDUMP_ENABLE_TO_FLASH
esp_core_dump_to_flash(info);
#endif
#if CONFIG_ESP_COREDUMP_ENABLE_TO_UART && !CONFIG_ESP_SYSTEM_PANIC_SILENT_REBOOT
esp_core_dump_to_uart(info);
#endif
esp_core_dump_write(info);
s_dumping_core = false;
esp_panic_handler_reconfigure_wdts(1000);
}
#endif /* CONFIG_ESP_COREDUMP_ENABLE */

View File

@ -106,9 +106,9 @@ menu "Core dump"
int "Reserved stack size"
depends on ESP_COREDUMP_ENABLE
range 0 4096 if !ESP_COREDUMP_USE_STACK_SIZE
range 1280 4096 if ESP_COREDUMP_USE_STACK_SIZE
range 1792 4096 if ESP_COREDUMP_USE_STACK_SIZE
default 0 if !ESP_COREDUMP_USE_STACK_SIZE
default 1280 if ESP_COREDUMP_USE_STACK_SIZE
default 1792 if ESP_COREDUMP_USE_STACK_SIZE
help
Size of the memory to be reserved for core dump stack. If 0 core dump process will run on
the stack of crashed task/ISR, otherwise special stack will be allocated.

View File

@ -47,51 +47,49 @@ typedef struct {
*/
void esp_core_dump_init(void);
/**
* @brief Saves core dump to flash.
*
* The structure of data stored in flash is as follows:
*
* | TOTAL_LEN | VERSION | TASKS_NUM | TCB_SIZE |
* | TCB_ADDR_1 | STACK_TOP_1 | STACK_END_1 | TCB_1 | STACK_1 |
* . . . .
* . . . .
* | TCB_ADDR_N | STACK_TOP_N | STACK_END_N | TCB_N | STACK_N |
* | CHECKSUM |
*
* Core dump in flash consists of header and data for every task in the system at the moment of crash.
* For flash data integrity, a checksum is used at the end of core the dump data.
* The structure of core dump data is described below in details.
* 1) Core dump starts with header:
* 1.1) TOTAL_LEN is total length of core dump data in flash including the checksum. Size is 4 bytes.
* 1.2) VERSION field keeps 4 byte version of core dump.
* 1.2) TASKS_NUM is the number of tasks for which data are stored. Size is 4 bytes.
* 1.3) TCB_SIZE is the size of task's TCB structure. Size is 4 bytes.
* 2) Core dump header is followed by the data for every task in the system.
* Task data are started with task header:
* 2.1) TCB_ADDR is the address of TCB in memory. Size is 4 bytes.
* 2.2) STACK_TOP is the top of task's stack (address of the topmost stack item). Size is 4 bytes.
* 2.2) STACK_END is the end of task's stack (address from which task's stack starts). Size is 4 bytes.
* 3) Task header is followed by TCB data. Size is TCB_SIZE bytes.
* 4) Task's stack is placed after TCB data. Size is (STACK_END - STACK_TOP) bytes.
* 5) The checksum is placed at the end of the data.
*/
void esp_core_dump_to_flash(panic_info_t *info);
/**
* @brief Print base64-encoded core dump to UART.
*
* The structure of core dump data is the same as for data stored in flash (@see esp_core_dump_to_flash) with some notes:
* 1) The checksum is not present in core dump printed to UART.
* 2) Since checksum is omitted TOTAL_LEN does not include its size.
* 3) Printed base64 data are surrounded with special messages to help user recognize the start and end of actual data.
*/
void esp_core_dump_to_uart(panic_info_t *info);
/**************************************************************************************/
/*********************************** USER MODE API ************************************/
/**************************************************************************************/
/**
* Core dump file consists of header and data (in binary or ELF format) for every task in the system at the moment of crash.
* For the data integrity, a checksum is used at the end of core the dump data.
* The structure of core dump file is described below in details.
* 1) Core dump starts with header:
* 1.1) TOTAL_LEN is total length of core dump data in flash including the checksum. Size is 4 bytes.
* 1.2) VERSION field keeps 4 byte version of core dump.
* 1.2) TASKS_NUM is the number of tasks for which data are stored. Size is 4 bytes. Unused in ELF format
* 1.3) TCB_SIZE is the size of task's TCB structure. Size is 4 bytes. Unused in ELF format
* 1.4) MEM_SEG_NUM is the number of memory segment. Size is 4 bytes. Unused in ELF format
* 1.5) CHIP_REV is the revision of the chip. Size is 4 bytes.
* 2) Core dump header is followed by the data for every task in the system. Data part is differs for the binary
* and elf formats.
* 2.1) The core dump file uses a subset of the ELF structures to store the crash information.
* Loadable ELF segments and ELF notes (ELF.PT_NOTE) used with a special name and type (CORE, NT_PRSTATUS type)
* 2.2) In Binary format task data are started with the task header:
* 2.2.1) TCB_ADDR is the address of TCB in memory. Size is 4 bytes.
* 2.2.2) STACK_TOP is the top of task's stack (address of the topmost stack item). Size is 4 bytes.
* 2.2.3) STACK_END is the end of task's stack (address from which task's stack starts). Size is 4 bytes.
* 2.2.4) Task header is followed by TCB data. Size is TCB_SIZE bytes.
* 2.2.5) Task's stack is placed after TCB data. Size is (STACK_END - STACK_TOP) bytes.
* 2.3) The checksum is placed at the end of the data.
* 3) The structure of the uart data is the same as the data stored in flash
* 3.1) Uart data is printed in base64 format surrounded with special messages to help user recognize the start and
* end of actual data.
*
* For more information about the implementation please check api-guides/core_dump_internals.rst
*
*/
/**
* @brief Print/store coredump data to the selected destination uart or flash.
*
* @param info Pointer to the panic information. It contains the execution frame.
*
* @return ESP_OK on success, otherwise \see esp_err_t
*/
void esp_core_dump_write(panic_info_t *info);
/**
* @brief Check integrity of coredump data in flash.
* This function reads the coredump data while calculating their checksum. If it

View File

@ -1,22 +0,0 @@
/*
* SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef ESP_CORE_DUMP_BINARY_H_
#define ESP_CORE_DUMP_BINARY_H_
#include "esp_core_dump_types.h"
/**
* @brief Initiate the binary core dump generation.
*
* @param info Exception frame info generated when the panic occured.
* @param write_cfg Structure containing the callbacks that will be called to
* write the generated core dump file.
*
* @return ESP_OK on success, otherwise \see esp_err_t.
*/
esp_err_t esp_core_dump_write_binary(core_dump_write_config_t *write_cfg);
#endif

View File

@ -55,31 +55,31 @@ uint32_t esp_core_dump_elf_version(void);
/**
* @brief Initialize checksum calculation for the given context.
*
* @param wr_data Core dump checksum context to fill.
* @param ctx Core dump checksum context to fill.
*/
void esp_core_dump_checksum_init(void ** wr_data);
void esp_core_dump_checksum_init(void *ctx);
/**
* @brief Update checksum calculation by integrating the given data in the context.
*
* @param wr_data Core dump checksum context.
* @param ctx Core dump checksum context.
* @param data Pointer to the data to integrate in the checksum calculation.
* This is usually the new data to write (or already written) on
* the flash.
*/
void esp_core_dump_checksum_update(void* wr_data, void* data, size_t data_len);
void esp_core_dump_checksum_update(void *ctx, void *data, size_t data_len);
/**
* @brief Terminate and return checksum calculated for the given context.
*
* @param wr_data Core dump checksum context.
* @param ctx Core dump checksum context.
* @param chs_ptr Pointer used to return the checksum calculated. It can be
* NULL, in this case, it will be ignored but the correct size
* of the checksum will be returned.
*
* @return The size, in bytes, of the checksum.
*/
uint32_t esp_core_dump_checksum_finish(void* wr_data, core_dump_checksum_bytes* chs_ptr);
uint32_t esp_core_dump_checksum_finish(void *ctx, core_dump_checksum_bytes *chs_ptr);
/**
* @brief Return the size of the checksums.

View File

@ -1,22 +0,0 @@
/*
* SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef ESP_CORE_DUMP_ELF_H_
#define ESP_CORE_DUMP_ELF_H_
#include "esp_core_dump_types.h"
/**
* @brief Initiate the ELF core dump generation.
*
* @param info Exception frame info generated when the panic occured.
* @param write_cfg Structre containing the callbacks that will be called to
* write the generated core dump data.
*
* @return ESP_OK on success, otherwise \see esp_err_t.
*/
esp_err_t esp_core_dump_write_elf(core_dump_write_config_t *write_cfg);
#endif

View File

@ -91,6 +91,46 @@ bool esp_core_dump_in_isr_context(void);
*/
uint32_t esp_core_dump_get_user_ram_size(void);
/**
* @brief Prints write start info string according to destination.
*/
void esp_core_dump_print_write_start(void);
/**
* @brief Prints write end info string according to destination.
*/
void esp_core_dump_print_write_end(void);
/**
* @brief Initializes the flash/UART hardware for data storage.
*/
esp_err_t esp_core_dump_write_init(void);
/**
* @brief Prepares the flash/UART for data storage
*/
esp_err_t esp_core_dump_write_prepare(core_dump_write_data_t *wr_data, uint32_t *data_len);
/**
* @brief Initiates the beginning of data writing.
*/
esp_err_t esp_core_dump_write_start(core_dump_write_data_t *wr_data);
/**
* @brief Writes a data chunk to the flash/UART
*/
esp_err_t esp_core_dump_write_data(core_dump_write_data_t *wr_data, void *data, uint32_t data_len);
/**
* @brief Finalizes the data writing process
*/
esp_err_t esp_core_dump_write_end(core_dump_write_data_t *wr_data);
/**
* @brief Stores the core dump in either binary or ELF format.
*/
esp_err_t esp_core_dump_store(void);
/**
* @brief Get TCB length, in bytes.
*

View File

@ -91,6 +91,39 @@ extern "C" {
#error "Coredump cache size must be a multiple of 16"
#endif
typedef uint32_t core_dump_crc_t;
#if CONFIG_ESP_COREDUMP_CHECKSUM_CRC32
typedef struct {
core_dump_crc_t crc;
uint32_t total_bytes_checksum; /* Number of bytes used to calculate the checksum */
} core_dump_crc_ctx_t;
typedef core_dump_crc_ctx_t checksum_ctx_t;
#else
#if CONFIG_IDF_TARGET_ESP32
#include "mbedtls/sha256.h" /* mbedtls_sha256_context */
typedef mbedtls_sha256_context sha256_ctx_t;
#else
#include "hal/sha_types.h" /* SHA_CTX */
typedef SHA_CTX sha256_ctx_t;
#endif
#define COREDUMP_SHA256_LEN 32
typedef struct {
sha256_ctx_t ctx;
uint8_t result[COREDUMP_SHA256_LEN];
uint32_t total_bytes_checksum; /* Number of bytes used to calculate the checksum */
} core_dump_sha_ctx_t;
typedef core_dump_sha_ctx_t checksum_ctx_t;
#endif
/**
* @brief Chip ID associated to this implementation.
*/
@ -100,39 +133,9 @@ typedef struct _core_dump_write_data_t {
uint32_t off; /*!< Current offset of data being written */
uint8_t cached_data[COREDUMP_CACHE_SIZE]; /*!< Cache used to write to flash */
uint8_t cached_bytes; /*!< Number of bytes filled in the cached */
void *checksum_ctx; /*!< Checksum context */
checksum_ctx_t checksum_ctx; /*!< Checksum context */
} core_dump_write_data_t;
/**
* @brief Types below define the signatures of the callbacks that are used
* to output a core dump. The destination of the dump is implementation
* dependant.
*/
typedef esp_err_t (*esp_core_dump_write_prepare_t)(core_dump_write_data_t* priv, uint32_t *data_len);
typedef esp_err_t (*esp_core_dump_write_start_t)(core_dump_write_data_t* priv);
typedef esp_err_t (*esp_core_dump_write_end_t)(core_dump_write_data_t* priv);
typedef esp_err_t (*esp_core_dump_flash_write_data_t)(core_dump_write_data_t* priv,
void * data,
uint32_t data_len);
/**
* @brief Core dump emitter control structure.
* This structure contains the functions that are called in order to write
* the core dump to the destination (UART or flash).
* The function are called in this order:
* - prepare
* - start
* - write called once or more
* - end
*/
typedef struct _core_dump_write_config_t {
esp_core_dump_write_prepare_t prepare; /*!< Function called for sanity checks */
esp_core_dump_write_start_t start; /*!< Function called at the beginning of data writing */
esp_core_dump_flash_write_data_t write; /*!< Function called to write data chunk */
esp_core_dump_write_end_t end; /*!< Function called once all data have been written */
core_dump_write_data_t* priv; /*!< Private context to pass to every function of this structure */
} core_dump_write_config_t;
/**
* @brief Core dump data header
* This header predecesses the actual core dump data (ELF or binary). */
@ -168,16 +171,6 @@ typedef struct _core_dump_mem_seg_header_t {
uint32_t size; /*!< Memory region size */
} core_dump_mem_seg_header_t;
/**
* @brief Core dump flash init function
*/
void esp_core_dump_flash_init(void);
/**
* @brief Common core dump write function
*/
void esp_core_dump_write(panic_info_t *info, core_dump_write_config_t *write_cfg);
#ifdef __cplusplus
}
#endif

View File

@ -7,7 +7,6 @@
#include <stdint.h>
#include <stdbool.h>
#include "sdkconfig.h"
#include "core_dump_binary.h"
#include "esp_core_dump_port.h"
#include "esp_core_dump_common.h"
#include "hal/efuse_hal.h"
@ -16,8 +15,9 @@
const static char TAG[] __attribute__((unused)) = "esp_core_dump_binary";
static esp_err_t esp_core_dump_save_task(core_dump_write_config_t *write_cfg,
core_dump_task_header_t *task)
esp_err_t esp_core_dump_store(void) __attribute__((alias("esp_core_dump_write_binary")));
static esp_err_t esp_core_dump_save_task(core_dump_write_data_t *write_data, core_dump_task_header_t *task)
{
esp_err_t err = ESP_FAIL;
uint32_t stk_vaddr = 0;
@ -27,19 +27,19 @@ static esp_err_t esp_core_dump_save_task(core_dump_write_config_t *write_cfg,
stk_len = esp_core_dump_get_memory_len(stk_vaddr, stk_vaddr + stk_len);
// Save memory segment header
err = write_cfg->write(write_cfg->priv, (void*)task, sizeof(core_dump_task_header_t));
err = esp_core_dump_write_data(write_data, task, sizeof(core_dump_task_header_t));
if (err != ESP_OK) {
ESP_COREDUMP_LOGE("Failed to write task header, error=%d!", err);
return err;
}
// Save TCB block
err = write_cfg->write(write_cfg->priv, task->tcb_addr, esp_core_dump_get_tcb_len());
err = esp_core_dump_write_data(write_data, task->tcb_addr, esp_core_dump_get_tcb_len());
if (err != ESP_OK) {
ESP_COREDUMP_LOGE("Failed to write TCB, error=%d!", err);
return err;
}
// Save task stack
err = write_cfg->write(write_cfg->priv, (void*)stk_paddr, stk_len);
err = esp_core_dump_write_data(write_data, (void *)stk_paddr, stk_len);
if (err != ESP_OK) {
ESP_COREDUMP_LOGE("Failed to write stack for task (TCB:%x), stack_start=%x, error=%d!",
task->tcb_addr,
@ -48,12 +48,12 @@ static esp_err_t esp_core_dump_save_task(core_dump_write_config_t *write_cfg,
return err;
}
ESP_COREDUMP_LOG_PROCESS("Task (TCB:%x) dump is saved.",
task->tcb_addr);
ESP_COREDUMP_LOG_PROCESS("Task (TCB:%x) dump is saved.", task->tcb_addr);
return ESP_OK;
}
static esp_err_t esp_core_dump_save_mem_segment(core_dump_write_config_t* write_cfg,
static esp_err_t esp_core_dump_save_mem_segment(core_dump_write_data_t* write_data,
core_dump_mem_seg_header_t* seg)
{
esp_err_t err = ESP_FAIL;
@ -63,14 +63,14 @@ static esp_err_t esp_core_dump_save_mem_segment(core_dump_write_config_t* write_
seg->start, seg->size);
return ESP_FAIL;
}
// Save TCB address, stack base and stack top addr
err = write_cfg->write(write_cfg->priv, (void*)seg, sizeof(core_dump_mem_seg_header_t));
// Save TCB address, stack base and stack top addrq
err = esp_core_dump_write_data(write_data, seg, sizeof(core_dump_mem_seg_header_t));
if (err != ESP_OK) {
ESP_COREDUMP_LOGE("Failed to write memory segment header, error=%d!", err);
return err;
}
// Save memory contents
err = write_cfg->write(write_cfg->priv, (void*)seg->start, seg->size);
err = esp_core_dump_write_data(write_data, (void *)seg->start, seg->size);
if (err != ESP_OK) {
ESP_COREDUMP_LOGE("Failed to write memory segment, (%x, %lu), error=%d!",
seg->start, seg->size, err);
@ -81,18 +81,24 @@ static esp_err_t esp_core_dump_save_mem_segment(core_dump_write_config_t* write_
return ESP_OK;
}
esp_err_t esp_core_dump_write_binary(core_dump_write_config_t *write_cfg)
static esp_err_t esp_core_dump_write_binary(void)
{
esp_err_t err = ESP_OK;
uint32_t tcb_sz = esp_core_dump_get_tcb_len();
uint32_t data_len = 0;
uint32_t bad_tasks_num = 0;
core_dump_write_data_t write_data = { 0 };
core_dump_header_t hdr = { 0 };
core_dump_task_header_t task_hdr = { 0 };
core_dump_mem_seg_header_t mem_seg = { 0 };
TaskIterator_t task_iter;
void *cur_task = NULL;
esp_err_t err = esp_core_dump_write_init();
if (err != ESP_OK) {
ESP_COREDUMP_LOGE("Binary write init failed!");
return ESP_FAIL;
}
// Verifies all tasks in the snapshot
esp_core_dump_reset_tasks_snapshots_iter();
esp_core_dump_task_iterator_init(&task_iter);
@ -161,21 +167,17 @@ esp_err_t esp_core_dump_write_binary(core_dump_write_config_t *write_cfg)
ESP_COREDUMP_LOG_PROCESS("Core dump length=%lu, tasks processed: %d, broken tasks: %d",
data_len, hdr.tasks_num, bad_tasks_num);
// Prepare write
if (write_cfg->prepare) {
err = write_cfg->prepare(write_cfg->priv, &data_len);
if (err != ESP_OK) {
ESP_COREDUMP_LOGE("Failed to prepare core dump, error=%d!", err);
return err;
}
err = esp_core_dump_write_prepare(&write_data, &data_len);
if (err != ESP_OK) {
ESP_COREDUMP_LOGE("Failed to prepare core dump, error=%d!", err);
return err;
}
// Write start
if (write_cfg->start) {
err = write_cfg->start(write_cfg->priv);
if (err != ESP_OK) {
ESP_COREDUMP_LOGE("Failed to start core dump, error=%d!", err);
return err;
}
err = esp_core_dump_write_start(&write_data);
if (err != ESP_OK) {
ESP_COREDUMP_LOGE("Failed to start core dump, error=%d!", err);
return err;
}
// Write header
@ -183,7 +185,7 @@ esp_err_t esp_core_dump_write_binary(core_dump_write_config_t *write_cfg)
hdr.version = COREDUMP_VERSION_BIN_CURRENT;
hdr.tcb_sz = tcb_sz;
hdr.chip_rev = efuse_hal_chip_revision();
err = write_cfg->write(write_cfg->priv, &hdr, sizeof(core_dump_header_t));
err = esp_core_dump_write_data(&write_data, &hdr, sizeof(core_dump_header_t));
if (err != ESP_OK) {
ESP_COREDUMP_LOGE("Failed to write core dump header error=%d!", err);
return err;
@ -194,7 +196,7 @@ esp_err_t esp_core_dump_write_binary(core_dump_write_config_t *write_cfg)
// Write first crashed task data first (not always first task in the snapshot)
ESP_COREDUMP_LOGD("Save first crashed task %x", cur_task);
if (esp_core_dump_get_task_snapshot(cur_task, &task_hdr, NULL)) {
err = esp_core_dump_save_task(write_cfg, &task_hdr);
err = esp_core_dump_save_task(&write_data, &task_hdr);
if (err != ESP_OK) {
ESP_COREDUMP_LOGE("Failed to save first crashed task %x, error=%d!",
task_hdr.tcb_addr, err);
@ -213,7 +215,7 @@ esp_err_t esp_core_dump_write_binary(core_dump_write_config_t *write_cfg)
}
ESP_COREDUMP_LOGD("Save task %x (TCB:%x, stack:%x..%x)",
task_iter.pxTaskHandle, task_hdr.tcb_addr, task_hdr.stack_start, task_hdr.stack_end);
err = esp_core_dump_save_task(write_cfg, &task_hdr);
err = esp_core_dump_save_task(&write_data, &task_hdr);
if (err != ESP_OK) {
ESP_COREDUMP_LOGE("Failed to save core dump task %x, error=%d!",
task_hdr.tcb_addr, err);
@ -232,7 +234,7 @@ esp_err_t esp_core_dump_write_binary(core_dump_write_config_t *write_cfg)
if (mem_seg.size > 0) {
ESP_COREDUMP_LOG_PROCESS("Save interrupted task stack %lu bytes @ %x",
mem_seg.size, mem_seg.start);
err = esp_core_dump_save_mem_segment(write_cfg, &mem_seg);
err = esp_core_dump_save_mem_segment(&write_data, &mem_seg);
if (err != ESP_OK) {
ESP_COREDUMP_LOGE("Failed to save interrupted task stack, error=%d!", err);
return err;
@ -256,7 +258,7 @@ esp_err_t esp_core_dump_write_binary(core_dump_write_config_t *write_cfg)
mem_seg.size = esp_core_dump_get_memory_len(start, start + data_sz);;
ESP_COREDUMP_LOG_PROCESS("Save user memory region %lu bytes @ %x",
mem_seg.size, mem_seg.start);
err = esp_core_dump_save_mem_segment(write_cfg, &mem_seg);
err = esp_core_dump_save_mem_segment(&write_data, &mem_seg);
if (err != ESP_OK) {
ESP_COREDUMP_LOGE("Failed to save user memory region, error=%d!", err);
return err;
@ -266,13 +268,12 @@ esp_err_t esp_core_dump_write_binary(core_dump_write_config_t *write_cfg)
}
// Write end
if (write_cfg->end) {
err = write_cfg->end(write_cfg->priv);
if (err != ESP_OK) {
ESP_COREDUMP_LOGE("Failed to end core dump error=%d!", err);
return err;
}
err = esp_core_dump_write_end(&write_data);
if (err != ESP_OK) {
ESP_COREDUMP_LOGE("Failed to end core dump error=%d!", err);
return err;
}
if (bad_tasks_num) {
ESP_COREDUMP_LOGE("Found %d broken tasks!", bad_tasks_num);
}

View File

@ -12,8 +12,6 @@
#include "esp_rom_sys.h"
#include "esp_core_dump_port.h"
#include "esp_core_dump_common.h"
#include "core_dump_elf.h"
#include "core_dump_binary.h"
const static char TAG[] __attribute__((unused)) = "esp_core_dump_common";
@ -142,26 +140,19 @@ FORCE_INLINE_ATTR void esp_core_dump_report_stack_usage(void)
static void* s_exc_frame = NULL;
inline void esp_core_dump_write(panic_info_t *info, core_dump_write_config_t *write_cfg)
inline static void esp_core_dump_write_internal(panic_info_t *info)
{
#ifndef CONFIG_ESP_COREDUMP_ENABLE_TO_NONE
esp_err_t err = ESP_ERR_NOT_SUPPORTED;
s_exc_frame = (void*) info->frame;
bool isr_context = esp_core_dump_in_isr_context();
s_exc_frame = (void *)info->frame;
esp_core_dump_setup_stack();
esp_core_dump_port_init(info, isr_context);
#if CONFIG_ESP_COREDUMP_DATA_FORMAT_BIN
err = esp_core_dump_write_binary(write_cfg);
#elif CONFIG_ESP_COREDUMP_DATA_FORMAT_ELF
err = esp_core_dump_write_elf(write_cfg);
#endif
esp_err_t err = esp_core_dump_store();
if (err != ESP_OK) {
ESP_COREDUMP_LOGE("Core dump write binary failed with error=%d", err);
ESP_COREDUMP_LOGE("Core dump write failed with error=%d", err);
}
esp_core_dump_report_stack_usage();
#endif
}
void __attribute__((weak)) esp_core_dump_init(void)
@ -311,4 +302,15 @@ inline bool esp_core_dump_in_isr_context(void)
#endif // CONFIG_ESP_TASK_WDT_EN
}
void esp_core_dump_write(panic_info_t *info)
{
#if CONFIG_ESP_COREDUMP_ENABLE_TO_UART && CONFIG_ESP_SYSTEM_PANIC_SILENT_REBOOT
return;
#endif
esp_core_dump_print_write_start();
esp_core_dump_write_internal(info);
esp_core_dump_print_write_end();
}
#endif

View File

@ -13,16 +13,7 @@
const static char TAG[] __attribute__((unused)) = "esp_core_dump_crc";
typedef uint32_t core_dump_crc_t;
typedef struct {
core_dump_crc_t crc;
uint32_t total_bytes_checksum; /* Number of bytes used to calculate the checksum */
} core_dump_crc_ctx_t;
static core_dump_crc_ctx_t s_core_dump_crc_ctx = { 0 };
void esp_core_dump_checksum_init(core_dump_checksum_ctx *out_ctx) __attribute__((alias("core_dump_crc_init")));
void esp_core_dump_checksum_init(core_dump_checksum_ctx cks_ctx) __attribute__((alias("core_dump_crc_init")));
void esp_core_dump_checksum_update(core_dump_checksum_ctx cks_ctx, void* data, size_t data_len) __attribute__((alias("core_dump_crc_update")));
uint32_t esp_core_dump_checksum_finish(core_dump_checksum_ctx cks_ctx, core_dump_checksum_bytes* chs_ptr) __attribute__((alias("core_dump_crc_finish")));
void esp_core_dump_print_checksum(const char* msg, core_dump_checksum_bytes checksum) __attribute__((alias("core_dump_crc_print")));
@ -49,12 +40,12 @@ static uint32_t core_dump_crc_version(void)
return COREDUMP_VERSION_ELF_CRC32;
}
static void core_dump_crc_init(core_dump_checksum_ctx *out_ctx)
static void core_dump_crc_init(core_dump_checksum_ctx cks_ctx)
{
if (out_ctx) {
s_core_dump_crc_ctx.crc = 0;
s_core_dump_crc_ctx.total_bytes_checksum = 0;
*out_ctx = &s_core_dump_crc_ctx;
if (cks_ctx) {
core_dump_crc_ctx_t *crc_ctx = cks_ctx;
crc_ctx->crc = 0;
crc_ctx->total_bytes_checksum = 0;
}
}

View File

@ -9,7 +9,6 @@
#include "esp_flash_encrypt.h"
#include "sdkconfig.h"
#include "core_dump_checksum.h"
#include "core_dump_elf.h"
#include "esp_core_dump_port.h"
#include "esp_core_dump_port_impl.h"
#include "esp_core_dump_common.h"
@ -79,7 +78,7 @@ typedef struct _core_dump_elf_t {
uint16_t elf_stage;
uint32_t elf_next_data_offset;
uint16_t segs_count;
core_dump_write_config_t * write_cfg;
core_dump_write_data_t write_data;
uint32_t note_data_size; /* can be used where static storage needed */
} core_dump_elf_t;
@ -98,6 +97,8 @@ typedef struct {
#endif
#define ALIGN_UP(x, a) (((x) + (a) - 1) & ~((a) - 1))
esp_err_t esp_core_dump_store(void) __attribute__((alias("esp_core_dump_write_elf")));
// Builds elf header and check all data offsets
static int elf_write_file_header(core_dump_elf_t *self, uint32_t seg_count)
{
@ -130,7 +131,7 @@ static int elf_write_file_header(core_dump_elf_t *self, uint32_t seg_count)
elf_hdr.e_shnum = 0; // initial section counter is 0
elf_hdr.e_shstrndx = SHN_UNDEF; // do not use string table
// write built elf header into elf image
esp_err_t err = self->write_cfg->write(self->write_cfg->priv, (void*)&elf_hdr, sizeof(elf_hdr));
esp_err_t err = esp_core_dump_write_data(&self->write_data, &elf_hdr, sizeof(elf_hdr));
ELF_CHECK_ERR((err == ESP_OK), ELF_PROC_ERR_WRITE_FAIL,
"Write ELF header failure (%d)", err);
ESP_COREDUMP_LOG_PROCESS("Add file header %u bytes", sizeof(elf_hdr));
@ -146,7 +147,7 @@ static int elf_write_segment_header(core_dump_elf_t *self, elf_phdr* phdr)
phdr->p_offset = self->elf_next_data_offset;
// set segment data information and write it into image
esp_err_t err = self->write_cfg->write(self->write_cfg->priv, (void*)phdr, sizeof(elf_phdr));
esp_err_t err = esp_core_dump_write_data(&self->write_data, phdr, sizeof(elf_phdr));
ELF_CHECK_ERR((err == ESP_OK), ELF_PROC_ERR_WRITE_FAIL,
"Write ELF segment header failure (%d)", err);
ESP_COREDUMP_LOG_PROCESS("Add segment header %u bytes: type %d, sz %u, off = 0x%x",
@ -187,7 +188,7 @@ static int elf_add_segment(core_dump_elf_t *self,
(uint32_t)data_len, self->elf_next_data_offset);
// write segment data only when write function is set and phdr = NULL
// write data into segment
err = self->write_cfg->write(self->write_cfg->priv, data, (uint32_t)data_len);
err = esp_core_dump_write_data(&self->write_data, data, (uint32_t)data_len);
ELF_CHECK_ERR((err == ESP_OK), ELF_PROC_ERR_WRITE_FAIL,
"Write ELF segment data failure (%d)", err);
self->elf_next_data_offset += data_len;
@ -206,11 +207,11 @@ static int elf_write_note_header(core_dump_elf_t *self,
note_hdr.n_descsz = data_sz;
note_hdr.n_type = type;
// write note header
esp_err_t err = self->write_cfg->write(self->write_cfg->priv, &note_hdr, sizeof(note_hdr));
esp_err_t err = esp_core_dump_write_data(&self->write_data, &note_hdr, sizeof(note_hdr));
ELF_CHECK_ERR((err == ESP_OK), ELF_PROC_ERR_WRITE_FAIL,
"Write ELF note header failure (%d)", err);
// write note name
err = self->write_cfg->write(self->write_cfg->priv, name_buffer, name_len);
err = esp_core_dump_write_data(&self->write_data, name_buffer, name_len);
ELF_CHECK_ERR((err == ESP_OK), ELF_PROC_ERR_WRITE_FAIL,
"Write ELF note name failure (%d)", err);
@ -242,13 +243,13 @@ static int elf_write_note(core_dump_elf_t *self,
// note data must be aligned in memory. we write aligned byte structures and panic details in strings,
// which might not be aligned by default. Therefore, we need to verify alignment and add padding if necessary.
err = self->write_cfg->write(self->write_cfg->priv, data, data_sz);
err = esp_core_dump_write_data(&self->write_data, data, data_sz);
if (err == ESP_OK) {
int pad_size = data_len - data_sz;
if (pad_size != 0) {
uint8_t pad_bytes[3] = {0};
ESP_COREDUMP_LOG_PROCESS("Core dump note data needs %d bytes padding", pad_size);
err = self->write_cfg->write(self->write_cfg->priv, pad_bytes, pad_size);
err = esp_core_dump_write_data(&self->write_data, pad_bytes, pad_size);
}
}
@ -529,7 +530,7 @@ static void elf_write_core_dump_note_cb(void *opaque, const char *data)
param->total_size += data_len;
if (!param->size_only) {
esp_err_t err = self->write_cfg->write(self->write_cfg->priv, (void *)data, data_len);
esp_err_t err = esp_core_dump_write_data(&self->write_data, (void *)data, data_len);
if (err != ESP_OK) {
param->total_size = 0;
}
@ -567,7 +568,7 @@ static int elf_add_wdt_panic_details(core_dump_elf_t *self)
uint8_t pad_bytes[3] = {0};
uint32_t pad_size = 4 - mod;
ESP_COREDUMP_LOG_PROCESS("Core dump note needs %d bytes padding", pad_size);
err = self->write_cfg->write(self->write_cfg->priv, pad_bytes, pad_size);
err = esp_core_dump_write_data(&self->write_data, pad_bytes, pad_size);
ELF_CHECK_ERR((err == ESP_OK), ELF_PROC_ERR_WRITE_FAIL, "Write ELF note padding failure (%d)", err);
}
}
@ -668,17 +669,18 @@ static int esp_core_dump_do_write_elf_pass(core_dump_elf_t *self)
return tot_len;
}
esp_err_t esp_core_dump_write_elf(core_dump_write_config_t *write_cfg)
static esp_err_t esp_core_dump_write_elf(void)
{
static core_dump_elf_t self = { 0 };
static core_dump_header_t dump_hdr = { 0 };
esp_err_t err = ESP_OK;
core_dump_elf_t self = { 0 };
core_dump_header_t dump_hdr = { 0 };
int tot_len = sizeof(dump_hdr);
int write_len = sizeof(dump_hdr);
ELF_CHECK_ERR((write_cfg), ESP_ERR_INVALID_ARG, "Invalid input data.");
self.write_cfg = write_cfg;
esp_err_t err = esp_core_dump_write_init();
if (err != ESP_OK) {
ESP_COREDUMP_LOGE("Elf write init failed!");
return ESP_FAIL;
}
// On first pass (do not write actual data), but calculate data length needed to allocate memory
self.elf_stage = ELF_STAGE_CALC_SPACE;
@ -692,21 +694,17 @@ esp_err_t esp_core_dump_write_elf(core_dump_write_config_t *write_cfg)
ESP_COREDUMP_LOG_PROCESS("============== Data size = %d bytes ============", tot_len);
// Prepare write elf
if (write_cfg->prepare) {
err = write_cfg->prepare(write_cfg->priv, (uint32_t*)&tot_len);
if (err != ESP_OK) {
ESP_COREDUMP_LOGE("Failed to prepare core dump storage (%d)!", err);
return err;
}
err = esp_core_dump_write_prepare(&self.write_data, (uint32_t*)&tot_len);
if (err != ESP_OK) {
ESP_COREDUMP_LOGE("Failed to prepare core dump storage (%d)!", err);
return err;
}
// Write start
if (write_cfg->start) {
err = write_cfg->start(write_cfg->priv);
if (err != ESP_OK) {
ESP_COREDUMP_LOGE("Failed to start core dump (%d)!", err);
return err;
}
err = esp_core_dump_write_start(&self.write_data);
if (err != ESP_OK) {
ESP_COREDUMP_LOGE("Failed to start core dump (%d)!", err);
return err;
}
// Write core dump header
@ -716,9 +714,7 @@ esp_err_t esp_core_dump_write_elf(core_dump_write_config_t *write_cfg)
dump_hdr.tcb_sz = 0; // unused in ELF format
dump_hdr.mem_segs_num = 0; // unused in ELF format
dump_hdr.chip_rev = efuse_hal_chip_revision();
err = write_cfg->write(write_cfg->priv,
(void*)&dump_hdr,
sizeof(core_dump_header_t));
err = esp_core_dump_write_data(&self.write_data, &dump_hdr, sizeof(core_dump_header_t));
if (err != ESP_OK) {
ESP_COREDUMP_LOGE("Failed to write core dump header (%d)!", err);
return err;
@ -745,13 +741,11 @@ esp_err_t esp_core_dump_write_elf(core_dump_write_config_t *write_cfg)
ESP_COREDUMP_LOG_PROCESS("=========== Data written size = %d bytes ==========", write_len);
// Write end, update checksum
if (write_cfg->end) {
err = write_cfg->end(write_cfg->priv);
if (err != ESP_OK) {
ESP_COREDUMP_LOGE("Failed to end core dump (%d)!", err);
return err;
}
err = esp_core_dump_write_end(&self.write_data);
if (err != ESP_OK) {
ESP_COREDUMP_LOGE("Failed to end core dump (%d)!", err);
}
return err;
}

View File

@ -32,8 +32,6 @@ typedef struct _core_dump_partition_t {
#endif
} core_dump_partition_t;
typedef uint32_t core_dump_crc_t;
typedef struct _core_dump_flash_config_t {
/* Core dump partition config. */
core_dump_partition_t partition;
@ -44,6 +42,14 @@ typedef struct _core_dump_flash_config_t {
/* Core dump flash data. */
static core_dump_flash_config_t s_core_flash_config;
void esp_core_dump_print_write_start(void) __attribute__((alias("esp_core_dump_flash_print_write_start")));
void esp_core_dump_print_write_end(void) __attribute__((alias("esp_core_dump_flash_print_write_end")));
esp_err_t esp_core_dump_write_init(void) __attribute__((alias("esp_core_dump_flash_hw_init")));
esp_err_t esp_core_dump_write_prepare(core_dump_write_data_t *wr_data, uint32_t *data_len) __attribute__((alias("esp_core_dump_flash_write_prepare")));
esp_err_t esp_core_dump_write_start(core_dump_write_data_t *wr_data) __attribute__((alias("esp_core_dump_flash_write_start")));
esp_err_t esp_core_dump_write_end(core_dump_write_data_t *wr_data) __attribute__((alias("esp_core_dump_flash_write_end")));
esp_err_t esp_core_dump_write_data(core_dump_write_data_t *wr_data, void *data, uint32_t data_len) __attribute__((alias("esp_core_dump_flash_write_data")));
#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_)
@ -51,6 +57,16 @@ static core_dump_flash_config_t s_core_flash_config;
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 void esp_core_dump_flash_print_write_start(void)
{
ESP_COREDUMP_LOGI("Save core dump to flash...");
}
static void esp_core_dump_flash_print_write_end(void)
{
ESP_COREDUMP_LOGI("Core dump has been saved to flash.");
}
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;
@ -69,7 +85,35 @@ 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));
}
void esp_core_dump_flash_init(void)
static esp_err_t esp_core_dump_flash_hw_init(void)
{
/* 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 ESP_FAIL;
}
/* Make sure that the partition can at least hold the 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 ESP_FAIL;
}
#if CONFIG_ESP_COREDUMP_FLASH_NO_OVERWRITE
if (!s_core_flash_config.partition.empty) {
ESP_COREDUMP_LOGW("Core dump already exists in flash, will not overwrite it with a new core dump");
return ESP_FAIL;
}
#endif
/* Initialize non-OS flash access critical section. */
spi_flash_guard_set(&g_flash_guard_no_os_ops);
esp_flash_app_disable_protect(true);
return ESP_OK;
}
static void esp_core_dump_partition_init(void)
{
const esp_partition_t *core_part = NULL;
@ -103,9 +147,8 @@ void esp_core_dump_flash_init(void)
}
}
static esp_err_t esp_core_dump_flash_write_data(core_dump_write_data_t* priv, uint8_t* data, uint32_t data_size)
static esp_err_t esp_core_dump_flash_write_data(core_dump_write_data_t* wr_data, uint8_t* data, uint32_t data_size)
{
core_dump_write_data_t *wr_data = (core_dump_write_data_t *)priv;
esp_err_t err = ESP_OK;
uint32_t written = 0;
uint32_t wr_sz = 0;
@ -141,7 +184,7 @@ static esp_err_t esp_core_dump_flash_write_data(core_dump_write_data_t* priv, ui
wr_data->off += COREDUMP_CACHE_SIZE;
/* Update checksum with the newly written data on the flash. */
esp_core_dump_checksum_update(wr_data->checksum_ctx, &wr_data->cached_data, COREDUMP_CACHE_SIZE);
esp_core_dump_checksum_update(&wr_data->checksum_ctx, &wr_data->cached_data, COREDUMP_CACHE_SIZE);
/* Reset cache from the next use. */
wr_data->cached_bytes = 0;
@ -179,7 +222,7 @@ static esp_err_t esp_core_dump_flash_write_data(core_dump_write_data_t* priv, ui
}
/* Update the checksum with the newly written bytes */
esp_core_dump_checksum_update(wr_data->checksum_ctx, data + written, wr_sz);
esp_core_dump_checksum_update(&wr_data->checksum_ctx, data + written, wr_sz);
wr_data->off += wr_sz;
written += wr_sz;
data_size -= wr_sz;
@ -196,9 +239,8 @@ static esp_err_t esp_core_dump_flash_write_data(core_dump_write_data_t* priv, ui
return ESP_OK;
}
static esp_err_t esp_core_dump_flash_write_prepare(core_dump_write_data_t *priv, uint32_t *data_len)
static esp_err_t esp_core_dump_flash_write_prepare(core_dump_write_data_t *wr_data, uint32_t *data_len)
{
core_dump_write_data_t *wr_data = (core_dump_write_data_t *)priv;
esp_err_t err = ESP_OK;
uint32_t sec_num = 0;
uint32_t cs_len = 0;
@ -248,19 +290,17 @@ static esp_err_t esp_core_dump_flash_write_prepare(core_dump_write_data_t *priv,
return err;
}
static esp_err_t esp_core_dump_flash_write_start(core_dump_write_data_t* priv)
static esp_err_t esp_core_dump_flash_write_start(core_dump_write_data_t *wr_data)
{
core_dump_write_data_t *wr_data = (core_dump_write_data_t *)priv;
esp_core_dump_checksum_init(&wr_data->checksum_ctx);
return ESP_OK;
}
static esp_err_t esp_core_dump_flash_write_end(core_dump_write_data_t* priv)
static esp_err_t esp_core_dump_flash_write_end(core_dump_write_data_t *wr_data)
{
esp_err_t err = ESP_OK;
core_dump_checksum_bytes checksum = NULL;
uint32_t cs_len = 0;
core_dump_write_data_t *wr_data = (core_dump_write_data_t *)priv;
/* Get the size, in bytes of the checksum. */
cs_len = esp_core_dump_checksum_size();
@ -277,14 +317,14 @@ static esp_err_t esp_core_dump_flash_write_end(core_dump_write_data_t* priv)
}
/* Update the checksum with the data written, including the padding. */
esp_core_dump_checksum_update(wr_data->checksum_ctx, wr_data->cached_data, COREDUMP_CACHE_SIZE);
esp_core_dump_checksum_update(&wr_data->checksum_ctx, wr_data->cached_data, COREDUMP_CACHE_SIZE);
wr_data->off += COREDUMP_CACHE_SIZE;
wr_data->cached_bytes = 0;
}
/* 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_ctx, &checksum);
esp_core_dump_checksum_finish(&wr_data->checksum_ctx, &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) */
@ -315,50 +355,9 @@ static esp_err_t esp_core_dump_flash_write_end(core_dump_write_data_t* priv)
return err;
}
void esp_core_dump_to_flash(panic_info_t *info)
{
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;
}
/* Make sure that the partition can at least hold the 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;
}
#if CONFIG_ESP_COREDUMP_FLASH_NO_OVERWRITE
if (!s_core_flash_config.partition.empty) {
ESP_COREDUMP_LOGW("Core dump already exists in flash, will not overwrite it with a new core dump");
return;
}
#endif
/* Initialize non-OS flash access critical section. */
spi_flash_guard_set(&g_flash_guard_no_os_ops);
esp_flash_app_disable_protect(true);
/* 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.priv = &wr_data;
ESP_COREDUMP_LOGI("Save core dump to flash...");
esp_core_dump_write(info, &wr_cfg);
ESP_COREDUMP_LOGI("Core dump has been saved to flash.");
}
void esp_core_dump_init(void)
{
esp_core_dump_flash_init();
esp_core_dump_partition_init();
#if CONFIG_ESP_COREDUMP_CHECK_BOOT
const esp_partition_t *partition = 0;
@ -414,7 +413,7 @@ esp_err_t esp_core_dump_image_check(void)
}
/* Update the checksum according to what was just read. */
esp_core_dump_checksum_update(wr_data.checksum_ctx, wr_data.cached_data, toread);
esp_core_dump_checksum_update(&wr_data.checksum_ctx, wr_data.cached_data, toread);
/* Move the offset forward and decrease the remaining size. */
offset += toread;
@ -422,7 +421,7 @@ esp_err_t esp_core_dump_image_check(void)
}
/* The coredump has been totally read, finish the checksum calculation. */
esp_core_dump_checksum_finish(wr_data.checksum_ctx, &checksum_calc);
esp_core_dump_checksum_finish(&wr_data.checksum_ctx, &checksum_calc);
/* Read the checksum from the flash and compare to the one just
* calculated. */

View File

@ -10,29 +10,10 @@
#include <string.h>
#include "esp_core_dump_types.h"
#if CONFIG_IDF_TARGET_ESP32
#include "mbedtls/sha256.h" /* mbedtls_sha256_context */
#else
#include "hal/sha_types.h" /* SHA_CTX */
#endif
const static char TAG[] __attribute__((unused)) = "esp_core_dump_sha";
#define COREDUMP_SHA256_LEN 32
typedef struct {
#if CONFIG_IDF_TARGET_ESP32
mbedtls_sha256_context ctx;
#else
SHA_CTX ctx;
#endif
uint8_t result[COREDUMP_SHA256_LEN];
uint32_t total_bytes_checksum; /* Number of bytes used to calculate the checksum */
} core_dump_sha_ctx_t;
static core_dump_sha_ctx_t s_core_dump_sha_ctx = { 0 };
void esp_core_dump_checksum_init(core_dump_checksum_ctx *cks_ctx) __attribute__((alias("core_dump_sha_init")));
void esp_core_dump_checksum_init(core_dump_checksum_ctx cks_ctx) __attribute__((alias("core_dump_sha_init")));
void esp_core_dump_checksum_update(core_dump_checksum_ctx cks_ctx, void* data, size_t data_len) __attribute__((alias("core_dump_sha_update")));
uint32_t esp_core_dump_checksum_finish(core_dump_checksum_ctx cks_ctx, core_dump_checksum_bytes* chs_ptr) __attribute__((alias("core_dump_sha_finish")));
void esp_core_dump_print_checksum(const char* msg, core_dump_checksum_bytes checksum) __attribute__((alias("core_dump_sha256_print")));
@ -107,12 +88,12 @@ static uint32_t core_dump_sha_version(void)
return COREDUMP_VERSION_ELF_SHA256;
}
static void core_dump_sha_init(core_dump_checksum_ctx *out_ctx)
static void core_dump_sha_init(core_dump_checksum_ctx cks_ctx)
{
if (out_ctx) {
core_dump_sha256_start(&s_core_dump_sha_ctx);
s_core_dump_sha_ctx.total_bytes_checksum = 0;
*out_ctx = &s_core_dump_sha_ctx;
if (cks_ctx) {
core_dump_sha_ctx_t *sha_ctx = cks_ctx;
core_dump_sha256_start(sha_ctx);
sha_ctx->total_bytes_checksum = 0;
}
}

View File

@ -17,6 +17,14 @@ const static char TAG[] __attribute__((unused)) = "esp_core_dump_uart";
#if CONFIG_ESP_COREDUMP_ENABLE_TO_UART
void esp_core_dump_print_write_start(void) __attribute__((alias("esp_core_dump_uart_print_write_start")));
void esp_core_dump_print_write_end(void) __attribute__((alias("esp_core_dump_uart_print_write_end")));
esp_err_t esp_core_dump_write_init(void) __attribute__((alias("esp_core_dump_uart_hw_init")));
esp_err_t esp_core_dump_write_prepare(core_dump_write_data_t *wr_data, uint32_t *data_len) __attribute__((alias("esp_core_dump_uart_write_prepare")));
esp_err_t esp_core_dump_write_start(core_dump_write_data_t *wr_data) __attribute__((alias("esp_core_dump_uart_write_start")));
esp_err_t esp_core_dump_write_end(core_dump_write_data_t *wr_data) __attribute__((alias("esp_core_dump_uart_write_end")));
esp_err_t esp_core_dump_write_data(core_dump_write_data_t *wr_data, void *data, uint32_t data_len) __attribute__((alias("esp_core_dump_uart_write_data")));
/* This function exists on every board, thus, we don't need to specify
* explicitly the header for each board. */
int esp_clk_cpu_freq(void);
@ -47,32 +55,40 @@ static void esp_core_dump_b64_encode(const uint8_t *src, uint32_t src_len, uint8
dst[j++] = '\0';
}
static esp_err_t esp_core_dump_uart_write_start(core_dump_write_data_t *priv)
static void esp_core_dump_uart_print_write_start(void)
{
ESP_COREDUMP_LOGI("Print core dump to uart...");
}
static void esp_core_dump_uart_print_write_end(void)
{
ESP_COREDUMP_LOGI("Core dump has been written to uart.");
}
static esp_err_t esp_core_dump_uart_write_start(core_dump_write_data_t *wr_data)
{
esp_err_t err = ESP_OK;
core_dump_write_data_t *wr_data = (core_dump_write_data_t *)priv;
ESP_COREDUMP_ASSERT(priv != NULL);
ESP_COREDUMP_ASSERT(wr_data != NULL);
esp_core_dump_checksum_init(&wr_data->checksum_ctx);
ESP_COREDUMP_PRINT("================= CORE DUMP START =================\r\n");
return err;
}
static esp_err_t esp_core_dump_uart_write_prepare(core_dump_write_data_t *priv, uint32_t *data_len)
static esp_err_t esp_core_dump_uart_write_prepare(core_dump_write_data_t *wr_data, uint32_t *data_len)
{
ESP_COREDUMP_ASSERT(data_len != NULL);
*data_len += esp_core_dump_checksum_size();
return ESP_OK;
}
static esp_err_t esp_core_dump_uart_write_end(core_dump_write_data_t *priv)
static esp_err_t esp_core_dump_uart_write_end(core_dump_write_data_t *wr_data)
{
esp_err_t err = ESP_OK;
char buf[64 + 4] = { 0 };
core_dump_checksum_bytes cs_addr = NULL;
core_dump_write_data_t *wr_data = (core_dump_write_data_t *)priv;
if (wr_data) {
size_t cs_len = esp_core_dump_checksum_finish(wr_data->checksum_ctx, &cs_addr);
size_t cs_len = esp_core_dump_checksum_finish(&wr_data->checksum_ctx, &cs_addr);
wr_data->off += cs_len;
esp_core_dump_b64_encode((const uint8_t *)cs_addr, cs_len, (uint8_t*)&buf[0]);
ESP_COREDUMP_PRINT("%s\r\n", buf);
@ -86,13 +102,12 @@ static esp_err_t esp_core_dump_uart_write_end(core_dump_write_data_t *priv)
return err;
}
static esp_err_t esp_core_dump_uart_write_data(core_dump_write_data_t *priv, void * data, uint32_t data_len)
static esp_err_t esp_core_dump_uart_write_data(core_dump_write_data_t *wr_data, void * data, uint32_t data_len)
{
esp_err_t err = ESP_OK;
char buf[64 + 4] = { 0 };
char *addr = data;
char *end = addr + data_len;
core_dump_write_data_t *wr_data = (core_dump_write_data_t *)priv;
ESP_COREDUMP_ASSERT(data != NULL);
@ -111,7 +126,7 @@ static esp_err_t esp_core_dump_uart_write_data(core_dump_write_data_t *priv, voi
if (wr_data) {
wr_data->off += data_len;
esp_core_dump_checksum_update(wr_data->checksum_ctx, data, data_len);
esp_core_dump_checksum_update(&wr_data->checksum_ctx, data, data_len);
}
return err;
}
@ -126,16 +141,8 @@ static int esp_core_dump_uart_get_char(void)
return i;
}
void esp_core_dump_to_uart(panic_info_t *info)
static esp_err_t esp_core_dump_uart_hw_init(void)
{
core_dump_write_data_t wr_data = { 0 };
core_dump_write_config_t wr_cfg = {
.prepare = esp_core_dump_uart_write_prepare,
.start = esp_core_dump_uart_write_start,
.end = esp_core_dump_uart_write_end,
.write = esp_core_dump_uart_write_data,
.priv = (void*) &wr_data
};
uint32_t tm_end = 0;
uint32_t tm_cur = 0;
int ch = 0;
@ -162,9 +169,8 @@ void esp_core_dump_to_uart(panic_info_t *info)
}
ch = esp_core_dump_uart_get_char();
}
ESP_COREDUMP_LOGI("Print core dump to uart...");
esp_core_dump_write(info, &wr_cfg);
ESP_COREDUMP_LOGI("Core dump has been written to uart.");
return ESP_OK;
}
void esp_core_dump_init(void)