debug: coredump: flash backend: add query/command to get raw data

Add a new coredump query and command type to retrieve the raw data
stored to the flash backend

Signed-off-by: Pieter De Gendt <pieter.degendt@basalte.be>
This commit is contained in:
Pieter De Gendt 2021-10-04 13:56:28 +02:00 committed by Fabio Baltieri
commit a727b8aaac
2 changed files with 156 additions and 1 deletions

View file

@ -7,6 +7,9 @@
#ifndef ZEPHYR_INCLUDE_DEBUG_COREDUMP_H_
#define ZEPHYR_INCLUDE_DEBUG_COREDUMP_H_
#include <stddef.h>
#include <sys/types.h>
/* Query ID */
enum coredump_query_id {
/*
@ -24,6 +27,14 @@ enum coredump_query_id {
*/
COREDUMP_QUERY_HAS_STORED_DUMP,
/*
* Returns coredump raw size from backend.
* 0 if none.
* -ENOTSUP if this query is not supported.
* Otherwise, error code from backend.
*/
COREDUMP_QUERY_GET_STORED_DUMP_SIZE,
COREDUMP_QUERY_MAX
};
@ -55,9 +66,41 @@ enum coredump_cmd_id {
*/
COREDUMP_CMD_ERASE_STORED_DUMP,
/*
* Copy the raw stored coredump.
*
* Returns copied size if successful
* 0 if stored coredump is not found
* -ENOTSUP if this command is not supported.
* Otherwise, error code from backend.
*/
COREDUMP_CMD_COPY_STORED_DUMP,
/*
* Invalidate the stored coredump. This is faster than
* erasing the whole partition.
*
* Returns 0 if successful.
* -ENOTSUP if this command is not supported.
* Otherwise, error code from backend.
*/
COREDUMP_CMD_INVALIDATE_STORED_DUMP,
COREDUMP_CMD_MAX
};
/* Coredump copy command argument definition */
struct coredump_cmd_copy_arg {
/* Copy offset */
off_t offset;
/* Copy destination buffer */
uint8_t *buffer;
/* Copy length */
size_t length;
};
#ifdef CONFIG_DEBUG_COREDUMP
#include <zephyr/toolchain.h>

View file

@ -42,6 +42,7 @@ LOG_MODULE_REGISTER(coredump, CONFIG_KERNEL_LOG_LEVEL);
#define FLASH_WRITE_SIZE DT_PROP(FLASH_CONTROLLER, write_block_size)
#define FLASH_BUF_SIZE FLASH_WRITE_SIZE
#define FLASH_ERASE_SIZE DT_PROP(FLASH_CONTROLLER, erase_block_size)
#define FLASH_PARTITION FLASH_AREA_ID(coredump_partition)
@ -273,7 +274,100 @@ out:
}
/**
* @brief Erase the stored coredump from flash partition.
* @brief Get the stored coredump in flash partition.
*
* This reads the stored coredump data and copies the raw data
* to the destination buffer.
*
* If the destination buffer is NULL, the offset and length are
* ignored and the entire dump size is returned.
*
* @param off offset of partition to begin reading
* @param dst buffer to read data into (can be NULL)
* @param len number of bytes to read
* @return dump size if successful; 0 if stored coredump is not found
* or is not valid; error otherwise
*/
static int get_stored_dump(off_t off, uint8_t *dst, size_t len)
{
int ret;
struct flash_hdr_t hdr;
ret = partition_open();
if (ret != 0) {
goto out;
}
/* Read header */
ret = data_read(0, (uint8_t *)&hdr, sizeof(hdr), NULL, NULL);
if (ret != 0) {
goto out;
}
/* Verify header signature */
if ((hdr.id[0] != 'C') && (hdr.id[1] != 'D')) {
ret = 0;
goto out;
}
/* Error encountered while dumping, so non-existent */
if (hdr.error != 0) {
ret = 0;
goto out;
}
/* Return the dump size if no destination buffer available */
if (!dst) {
ret = (int)hdr.size;
goto out;
}
/* Offset larger than dump size */
if (off >= hdr.size) {
ret = 0;
goto out;
}
/* Start reading the data, skip write-aligned header */
off += ROUND_UP(sizeof(struct flash_hdr_t), FLASH_WRITE_SIZE);
ret = data_read(off, dst, len, NULL, NULL);
if (ret == 0) {
ret = (int)len;
}
out:
partition_close();
return ret;
}
/**
* @brief Erase the stored coredump header from flash partition.
*
* This erases the stored coredump header from the flash partition,
* invalidating the coredump data.
*
* @return 0 if successful; error otherwise
*/
static int erase_coredump_header(void)
{
int ret;
ret = partition_open();
if (ret == 0) {
/* Erase header block */
ret = flash_area_erase(backend_ctx.flash_area, 0,
ROUND_UP(sizeof(struct flash_hdr_t),
FLASH_ERASE_SIZE));
}
partition_close();
return ret;
}
/**
* @brief Erase the stored coredump in flash partition.
*
* This erases the stored coredump data from the flash partition.
*
@ -458,6 +552,9 @@ static int coredump_flash_backend_query(enum coredump_query_id query_id,
case COREDUMP_QUERY_HAS_STORED_DUMP:
ret = process_stored_dump(cb_calc_buf_checksum, NULL);
break;
case COREDUMP_QUERY_GET_STORED_DUMP_SIZE:
ret = get_stored_dump(0, NULL, 0);
break;
default:
ret = -ENOTSUP;
break;
@ -489,6 +586,21 @@ static int coredump_flash_backend_cmd(enum coredump_cmd_id cmd_id,
case COREDUMP_CMD_ERASE_STORED_DUMP:
ret = erase_flash_partition();
break;
case COREDUMP_CMD_COPY_STORED_DUMP:
if (arg) {
struct coredump_cmd_copy_arg *copy_arg
= (struct coredump_cmd_copy_arg *)arg;
ret = get_stored_dump(copy_arg->offset,
copy_arg->buffer,
copy_arg->length);
} else {
ret = -EINVAL;
}
break;
case COREDUMP_CMD_INVALIDATE_STORED_DUMP:
ret = erase_coredump_header();
break;
default:
ret = -ENOTSUP;
break;