diff options
author | Nicolas Boichat <drinkcat@chromium.org> | 2021-03-08 10:46:58 +0800 |
---|---|---|
committer | Commit Bot <commit-bot@chromium.org> | 2021-03-10 04:38:44 +0000 |
commit | 357ce5349a2e88bed9e9d773719e5119ac76ef49 (patch) | |
tree | e814f48733ce2dc4c503a8f64b1896abf5bb49cd | |
parent | 819adb4fa98f5d32a373ebd63e668b1c1bc5b121 (diff) | |
download | chrome-ec-357ce5349a2e88bed9e9d773719e5119ac76ef49.tar.gz |
util/ec_parse_panicinfo: Parse older structures
For devices on older FW branches, we need to be able to parse
panicinfo even if the size of the structures don't match.
Realign trailer (struct_size and magic) for that purpose.
Also, add WARNING/ERROR tags to messages so that we can
grep for those in a test.
Make a similar change in ectool (use the return value that
indicates the size).
BUG=b:182087232
TEST=make build/bds/util/ec_parse_panicinfo
TEST=build/bds/util/ec_parse_panicinfo < \
./upload_file_eccrash-857e3693bfce1e1f.eccrash
BRANCH=none
Change-Id: I97650aa3085e753b0a2256058402e33d11238f52
Signed-off-by: Nicolas Boichat <drinkcat@chromium.org>
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/2738577
Reviewed-by: Eric Yilun Lin <yllin@chromium.org>
-rw-r--r-- | util/ec_panicinfo.c | 61 | ||||
-rw-r--r-- | util/ec_panicinfo.h | 2 | ||||
-rw-r--r-- | util/ec_parse_panicinfo.c | 30 | ||||
-rw-r--r-- | util/ectool.c | 3 |
4 files changed, 75 insertions, 21 deletions
diff --git a/util/ec_panicinfo.c b/util/ec_panicinfo.c index b919cc6df7..ad6867fdc9 100644 --- a/util/ec_panicinfo.c +++ b/util/ec_panicinfo.c @@ -5,7 +5,9 @@ #include <stdint.h> #include <stdio.h> +#include <string.h> #include "compile_time_macros.h" + #include "ec_panicinfo.h" static void print_panic_reg(int regnum, const uint32_t *regs, int index) @@ -123,34 +125,67 @@ static int parse_panic_info_rv32i(const struct panic_data *pdata) return 0; } -int parse_panic_info(const struct panic_data *pdata) +int parse_panic_info(const char *data, size_t size) { + /* Size of the panic information "header". */ + const size_t header_size = 4; + /* Size of the panic information "trailer" (struct_size and magic). */ + const size_t trailer_size = sizeof(struct panic_data) - + offsetof(struct panic_data, struct_size); + + struct panic_data pdata = { 0 }; + size_t copy_size; + + if (size < (header_size + trailer_size)) { + fprintf(stderr, "ERROR: Panic data too short (%zd).\n", size); + return -1; + } + + if (size > sizeof(pdata)) { + fprintf(stderr, "WARNING: Panic data too large (%zd > %zd). " + "Following data may be incorrect!\n", + size, sizeof(pdata)); + copy_size = sizeof(pdata); + } else { + copy_size = size; + } + /* Copy the data into pdata, as the struct size may have changed. */ + memcpy(&pdata, data, copy_size); + /* Then copy the trailer in position. */ + memcpy((char *)&pdata + (sizeof(struct panic_data) - trailer_size), + data + (size - trailer_size), trailer_size); + /* * We only understand panic data with version <= 2. Warn the user * of higher versions. */ - if (pdata->struct_version > 2) - fprintf(stderr, - "Unknown panic data version (%d). " + if (pdata.struct_version > 2) + fprintf(stderr, "WARNING: Unknown panic data version (%d). " "Following data may be incorrect!\n", - pdata->struct_version); + pdata.struct_version); /* Validate magic number */ - if (pdata->magic != PANIC_DATA_MAGIC) + if (pdata.magic != PANIC_DATA_MAGIC) + fprintf(stderr, "WARNING: Incorrect panic magic (%d). " + "Following data may be incorrect!\n", + pdata.magic); + + if (pdata.struct_size != size) fprintf(stderr, - "Incorrect panic magic (%d). " + "WARNING: Panic struct size inconsistent (%u vs %zd). " "Following data may be incorrect!\n", - pdata->magic); + pdata.struct_size, size); - switch (pdata->arch) { + switch (pdata.arch) { case PANIC_ARCH_CORTEX_M: - return parse_panic_info_cm(pdata); + return parse_panic_info_cm(&pdata); case PANIC_ARCH_NDS32_N8: - return parse_panic_info_nds32(pdata); + return parse_panic_info_nds32(&pdata); case PANIC_ARCH_RISCV_RV32I: - return parse_panic_info_rv32i(pdata); + return parse_panic_info_rv32i(&pdata); default: - fprintf(stderr, "Unknown architecture (%d).\n", pdata->arch); + fprintf(stderr, "ERROR: Unknown architecture (%d).\n", + pdata.arch); break; } return -1; diff --git a/util/ec_panicinfo.h b/util/ec_panicinfo.h index f70c58e59f..c61cf797e6 100644 --- a/util/ec_panicinfo.h +++ b/util/ec_panicinfo.h @@ -14,6 +14,6 @@ * @param pdata Panic information to print * @return 0 if success or non-zero error code if error. */ -int parse_panic_info(const struct panic_data *pdata); +int parse_panic_info(const char *data, size_t size); #endif /* EC_PANICINFO_H */ diff --git a/util/ec_parse_panicinfo.c b/util/ec_parse_panicinfo.c index 5db8ed2e05..a3fefcf7b5 100644 --- a/util/ec_parse_panicinfo.c +++ b/util/ec_parse_panicinfo.c @@ -7,16 +7,36 @@ #include <stdint.h> #include <stdio.h> +#include "compile_time_macros.h" #include "ec_panicinfo.h" int main(int argc, char *argv[]) { - struct panic_data pdata; + /* + * panic_data size could change with time, as new architecture are + * added (or, less likely, removed). + */ + char pdata[4096]; + size_t size = 0; + size_t read; - if (fread(&pdata, sizeof(pdata), 1, stdin) != 1) { - fprintf(stderr, "Error reading panicinfo from stdin.\n"); - return 1; + BUILD_ASSERT(sizeof(pdata) > sizeof(struct panic_data)*2); + + while (1) { + read = fread(&pdata[size], 1, sizeof(pdata)-size, stdin); + if (read < 0) { + fprintf(stderr, "Cannot read panicinfo from stdin.\n"); + return 1; + } + if (read == 0) + break; + + size += read; + if (size == sizeof(pdata)) { + fprintf(stderr, "Too much panicinfo data in stdin.\n"); + return 1; + } } - return parse_panic_info(&pdata) ? 1 : 0; + return parse_panic_info(pdata, size) ? 1 : 0; } diff --git a/util/ectool.c b/util/ectool.c index a85166ebe7..459a7158b5 100644 --- a/util/ectool.c +++ b/util/ectool.c @@ -6448,7 +6448,6 @@ int cmd_keyboard_factory_test(int argc, char *argv[]) int cmd_panic_info(int argc, char *argv[]) { int rv; - struct panic_data *pdata = (struct panic_data *)ec_inbuf; rv = ec_command(EC_CMD_GET_PANIC_INFO, 0, NULL, 0, ec_inbuf, ec_max_insize); @@ -6460,7 +6459,7 @@ int cmd_panic_info(int argc, char *argv[]) return 0; } - return parse_panic_info(pdata); + return parse_panic_info(ec_inbuf, rv); } |