diff options
author | Nicolas Boichat <drinkcat@google.com> | 2016-09-01 14:35:48 +0800 |
---|---|---|
committer | chrome-bot <chrome-bot@chromium.org> | 2016-09-06 22:02:27 -0700 |
commit | 107cb0df63efb527a470553b0a4e6f1f1ab17eb6 (patch) | |
tree | 53d3db1cfb60445ef0da82df66ea81989f0e0497 /util | |
parent | 03a3f864796d02196de8419b3c12c78f425b946c (diff) | |
download | chrome-ec-107cb0df63efb527a470553b0a4e6f1f1ab17eb6.tar.gz |
util: Add ec_parse_panicinfo tool to parse binary panicinfo
To be able to parse binary panicinfo from feedback reports, we need
a host tool:
- Move panicinfo generic parsing functions to a separate C file
- Create a new host utility to parse panicinfo
BRANCH=none
BUG=chromium:643062
TEST=base64 -d | ec_parse_panicinfo
Change-Id: Idd8560a2894f270d0ab3a9f654c333135759e57f
Reviewed-on: https://chromium-review.googlesource.com/379639
Commit-Ready: Nicolas Boichat <drinkcat@chromium.org>
Tested-by: Nicolas Boichat <drinkcat@chromium.org>
Reviewed-by: Randall Spangler <rspangler@chromium.org>
Diffstat (limited to 'util')
-rw-r--r-- | util/build.mk | 7 | ||||
-rw-r--r-- | util/ec_panicinfo.c | 125 | ||||
-rw-r--r-- | util/ec_panicinfo.h | 19 | ||||
-rw-r--r-- | util/ec_parse_panicinfo.c | 22 | ||||
-rw-r--r-- | util/ectool.c | 110 |
5 files changed, 173 insertions, 110 deletions
diff --git a/util/build.mk b/util/build.mk index 4b382f1156..89772f9746 100644 --- a/util/build.mk +++ b/util/build.mk @@ -6,7 +6,8 @@ # Host tools build # -host-util-bin=ectool lbplay stm32mon ec_sb_firmware_update lbcc +host-util-bin=ectool lbplay stm32mon ec_sb_firmware_update lbcc \ + ec_parse_panicinfo build-util-bin=ec_uartd iteflash ifeq ($(CHIP),npcx) build-util-bin+=ecst @@ -15,7 +16,9 @@ endif comm-objs=$(util-lock-objs:%=lock/%) comm-host.o comm-dev.o comm-objs+=comm-lpc.o comm-i2c.o misc_util.o -ectool-objs=ectool.o ectool_keyscan.o ec_flash.o $(comm-objs) +ectool-objs=ectool.o ectool_keyscan.o ec_flash.o ec_panicinfo.o $(comm-objs) ec_sb_firmware_update-objs=ec_sb_firmware_update.o $(comm-objs) misc_util.o ec_sb_firmware_update-objs+=powerd_lock.o lbplay-objs=lbplay.o $(comm-objs) + +ec_parse_panicinfo-objs=ec_parse_panicinfo.o ec_panicinfo.o diff --git a/util/ec_panicinfo.c b/util/ec_panicinfo.c new file mode 100644 index 0000000000..47de4b2a4c --- /dev/null +++ b/util/ec_panicinfo.c @@ -0,0 +1,125 @@ +/* Copyright 2016 The Chromium OS Authors. All rights reserved. + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include <stdint.h> +#include <stdio.h> +#include "ec_panicinfo.h" + +static void print_panic_reg(int regnum, const uint32_t *regs, int index) +{ + static const char * const regname[] = { + "r0 ", "r1 ", "r2 ", "r3 ", "r4 ", + "r5 ", "r6 ", "r7 ", "r8 ", "r9 ", + "r10", "r11", "r12", "sp ", "lr ", + "pc "}; + + printf("%s:", regname[regnum]); + if (regs) + printf("%08x", regs[index]); + else + printf(" "); + printf((regnum & 3) == 3 ? "\n" : " "); +} + +static int parse_panic_info_cm(const struct panic_data *pdata) +{ + const uint32_t *lregs = pdata->cm.regs; + const uint32_t *sregs = NULL; + enum { + ORIG_UNKNOWN = 0, + ORIG_PROCESS, + ORIG_HANDLER + } origin = ORIG_UNKNOWN; + int i; + const char *panic_origins[3] = {"", "PROCESS", "HANDLER"}; + + printf("Saved panic data:%s\n", + (pdata->flags & PANIC_DATA_FLAG_OLD_HOSTCMD ? "" : " (NEW)")); + + if (pdata->struct_version == 2) + origin = ((lregs[11] & 0xf) == 1 || (lregs[11] & 0xf) == 9) ? + ORIG_HANDLER : ORIG_PROCESS; + + /* + * In pdata struct, 'regs', which is allocated before 'frame', has + * one less elements in version 1. Therefore, if the data is from + * version 1, shift 'sregs' by one element to align with 'frame' in + * version 1. + */ + if (pdata->flags & PANIC_DATA_FLAG_FRAME_VALID) + sregs = pdata->cm.frame - (pdata->struct_version == 1 ? 1 : 0); + + printf("=== %s EXCEPTION: %02x ====== xPSR: %08x ===\n", + panic_origins[origin], + lregs[1] & 0xff, sregs ? sregs[7] : -1); + for (i = 0; i < 4; ++i) + print_panic_reg(i, sregs, i); + for (i = 4; i < 10; ++i) + print_panic_reg(i, lregs, i - 1); + print_panic_reg(10, lregs, 9); + print_panic_reg(11, lregs, 10); + print_panic_reg(12, sregs, 4); + print_panic_reg(13, lregs, origin == ORIG_HANDLER ? 2 : 0); + print_panic_reg(14, sregs, 5); + print_panic_reg(15, sregs, 6); + + return 0; +} + +static int parse_panic_info_nds32(const struct panic_data *pdata) +{ + const uint32_t *regs = pdata->nds_n8.regs; + uint32_t itype = pdata->nds_n8.itype; + uint32_t ipc = pdata->nds_n8.ipc; + uint32_t ipsw = pdata->nds_n8.ipsw; + + printf("Saved panic data:%s\n", + (pdata->flags & PANIC_DATA_FLAG_OLD_HOSTCMD ? "" : " (NEW)")); + + printf("=== EXCEP: ITYPE=%x ===\n", itype); + printf("R0 %08x R1 %08x R2 %08x R3 %08x\n", + regs[0], regs[1], regs[2], regs[3]); + printf("R4 %08x R5 %08x R6 %08x R7 %08x\n", + regs[4], regs[5], regs[6], regs[7]); + printf("R8 %08x R9 %08x R10 %08x R15 %08x\n", + regs[8], regs[9], regs[10], regs[11]); + printf("FP %08x GP %08x LP %08x SP %08x\n", + regs[12], regs[13], regs[14], regs[15]); + printf("IPC %08x IPSW %05x\n", ipc, ipsw); + printf("SWID of ITYPE: %x\n", ((itype >> 16) & 0x7fff)); + + return 0; +} + +int parse_panic_info(const struct panic_data *pdata) +{ + /* + * 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). " + "Following data may be incorrect!\n", + pdata->struct_version); + + /* Validate magic number */ + if (pdata->magic != PANIC_DATA_MAGIC) + fprintf(stderr, + "Incorrect panic magic (%d). " + "Following data may be incorrect!\n", + pdata->magic); + + switch (pdata->arch) { + case PANIC_ARCH_CORTEX_M: + return parse_panic_info_cm(pdata); + case PANIC_ARCH_NDS32_N8: + return parse_panic_info_nds32(pdata); + default: + fprintf(stderr, "Unknown architecture (%d).\n", pdata->arch); + break; + } + return -1; +} diff --git a/util/ec_panicinfo.h b/util/ec_panicinfo.h new file mode 100644 index 0000000000..f70c58e59f --- /dev/null +++ b/util/ec_panicinfo.h @@ -0,0 +1,19 @@ +/* Copyright 2016 The Chromium OS Authors. All rights reserved. + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifndef EC_PANICINFO_H +#define EC_PANICINFO_H + +#include "panic.h" + +/** + * Prints panic information to stdout. + * + * @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); + +#endif /* EC_PANICINFO_H */ diff --git a/util/ec_parse_panicinfo.c b/util/ec_parse_panicinfo.c new file mode 100644 index 0000000000..5db8ed2e05 --- /dev/null +++ b/util/ec_parse_panicinfo.c @@ -0,0 +1,22 @@ +/* Copyright 2016 The Chromium OS Authors. All rights reserved. + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + * + * Standalone utility to parse EC panicinfo. + */ + +#include <stdint.h> +#include <stdio.h> +#include "ec_panicinfo.h" + +int main(int argc, char *argv[]) +{ + struct panic_data pdata; + + if (fread(&pdata, sizeof(pdata), 1, stdin) != 1) { + fprintf(stderr, "Error reading panicinfo from stdin.\n"); + return 1; + } + + return parse_panic_info(&pdata) ? 1 : 0; +} diff --git a/util/ectool.c b/util/ectool.c index 57660597bb..b8e5415c22 100644 --- a/util/ectool.c +++ b/util/ectool.c @@ -17,6 +17,7 @@ #include "battery.h" #include "comm-host.h" #include "compile_time_macros.h" +#include "ec_panicinfo.h" #include "ec_flash.h" #include "ectool.h" #include "lightbar.h" @@ -4420,94 +4421,6 @@ int cmd_keyboard_factory_test(int argc, char *argv[]) return 0; } -static void print_panic_reg(int regnum, const uint32_t *regs, int index) -{ - static const char * const regname[] = { - "r0 ", "r1 ", "r2 ", "r3 ", "r4 ", - "r5 ", "r6 ", "r7 ", "r8 ", "r9 ", - "r10", "r11", "r12", "sp ", "lr ", - "pc "}; - - printf("%s:", regname[regnum]); - if (regs) - printf("%08x", regs[index]); - else - printf(" "); - printf((regnum & 3) == 3 ? "\n" : " "); -} - -int cmd_panic_info_cm(int argc, char *argv[]) -{ - struct panic_data *pdata = (struct panic_data *)ec_inbuf; - const uint32_t *lregs = pdata->cm.regs; - const uint32_t *sregs = NULL; - enum { - ORIG_UNKNOWN = 0, - ORIG_PROCESS, - ORIG_HANDLER - } origin = ORIG_UNKNOWN; - int i; - const char *panic_origins[3] = {"", "PROCESS", "HANDLER"}; - - printf("Saved panic data:%s\n", - (pdata->flags & PANIC_DATA_FLAG_OLD_HOSTCMD ? "" : " (NEW)")); - - if (pdata->struct_version == 2) - origin = ((lregs[11] & 0xf) == 1 || (lregs[11] & 0xf) == 9) ? - ORIG_HANDLER : ORIG_PROCESS; - - /* - * In pdata struct, 'regs', which is allocated before 'frame', has - * one less elements in version 1. Therefore, if the data is from - * version 1, shift 'sregs' by one element to align with 'frame' in - * version 1. - */ - if (pdata->flags & PANIC_DATA_FLAG_FRAME_VALID) - sregs = pdata->cm.frame - (pdata->struct_version == 1 ? 1 : 0); - - printf("=== %s EXCEPTION: %02x ====== xPSR: %08x ===\n", - panic_origins[origin], - lregs[1] & 0xff, sregs ? sregs[7] : -1); - for (i = 0; i < 4; ++i) - print_panic_reg(i, sregs, i); - for (i = 4; i < 10; ++i) - print_panic_reg(i, lregs, i - 1); - print_panic_reg(10, lregs, 9); - print_panic_reg(11, lregs, 10); - print_panic_reg(12, sregs, 4); - print_panic_reg(13, lregs, origin == ORIG_HANDLER ? 2 : 0); - print_panic_reg(14, sregs, 5); - print_panic_reg(15, sregs, 6); - - return 0; -} - -int cmd_panic_info_nds32(int argc, char *argv[]) -{ - struct panic_data *pdata = (struct panic_data *)ec_inbuf; - const uint32_t *regs = pdata->nds_n8.regs; - uint32_t itype = pdata->nds_n8.itype; - uint32_t ipc = pdata->nds_n8.ipc; - uint32_t ipsw = pdata->nds_n8.ipsw; - - printf("Saved panic data:%s\n", - (pdata->flags & PANIC_DATA_FLAG_OLD_HOSTCMD ? "" : " (NEW)")); - - printf("=== EXCEP: ITYPE=%x ===\n", itype); - printf("R0 %08x R1 %08x R2 %08x R3 %08x\n", - regs[0], regs[1], regs[2], regs[3]); - printf("R4 %08x R5 %08x R6 %08x R7 %08x\n", - regs[4], regs[5], regs[6], regs[7]); - printf("R8 %08x R9 %08x R10 %08x R15 %08x\n", - regs[8], regs[9], regs[10], regs[11]); - printf("FP %08x GP %08x LP %08x SP %08x\n", - regs[12], regs[13], regs[14], regs[15]); - printf("IPC %08x IPSW %05x\n", ipc, ipsw); - printf("SWID of ITYPE: %x\n", ((itype >> 16) & 0x7fff)); - - return 0; -} - int cmd_panic_info(int argc, char *argv[]) { int rv; @@ -4523,26 +4436,7 @@ int cmd_panic_info(int argc, char *argv[]) return 0; } - /* - * 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). " - "Following data may be incorrect!\n", - pdata->struct_version); - - switch (pdata->arch) { - case PANIC_ARCH_CORTEX_M: - return cmd_panic_info_cm(argc, argv); - case PANIC_ARCH_NDS32_N8: - return cmd_panic_info_nds32(argc, argv); - default: - fprintf(stderr, "Unknown architecture (%d).\n", pdata->arch); - break; - } - return -1; + return parse_panic_info(pdata); } |