summaryrefslogtreecommitdiff
path: root/util
diff options
context:
space:
mode:
authorJonathan Brandmeyer <jbrandmeyer@chromium.org>2018-07-16 15:02:22 -0600
committerchrome-bot <chrome-bot@chromium.org>2018-07-26 04:07:41 -0700
commitdda2f778befed39e449d96b471b94d489ed23d60 (patch)
treefc0db938c092a609fbf47e9758d8f0113e5b0cce /util
parent48113728b689870e6aeda6534d36eeffd3b738b3 (diff)
downloadchrome-ec-dda2f778befed39e449d96b471b94d489ed23d60.tar.gz
reset: Log the reason for AP resets.
Provides a new EC host command 'uptime info' which gathers up some information which may be useful for debugging spurious resets on the AP (was the EC reset recently? Why was the EC reset? If the EC reset the AP, why did it do so?, etc.). Provide ectool support for the same. Example results of `ectool uptimeinfo`: ``` localhost ~ # ectool uptimeinfo EC uptime: 475.368 seconds AP resets since EC boot: 2 Most recent AP reset causes: 315.903: reset: console command 363.507: reset: keyboard warm reboot EC reset flags at last EC boot: reset-pin | sysjump ``` BRANCH=none TEST=Perform some `apreset` commands from the EC console and observe their side-effects via the `ectool uptimeinfo` command on the AP side. Test sequences include no-resets through 5 resets, observing that the ring buffer handling was correct. BUG=b:110788201, b:79529789 Signed-off-by: Jonathan Brandmeyer <jbrandmeyer@chromium.org> Change-Id: I0bf29d69de471c64f905ee8aa070b15b4f34f2ba Reviewed-on: https://chromium-review.googlesource.com/1139028 Commit-Ready: Jonathan Brandmeyer <jbrandmeyer@chromium.org> Tested-by: Jonathan Brandmeyer <jbrandmeyer@chromium.org> Reviewed-by: Jett Rink <jettrink@chromium.org>
Diffstat (limited to 'util')
-rw-r--r--util/ectool.c124
1 files changed, 124 insertions, 0 deletions
diff --git a/util/ectool.c b/util/ectool.c
index f1de218278..cf28ccca08 100644
--- a/util/ectool.c
+++ b/util/ectool.c
@@ -17,6 +17,7 @@
#include "anx74xx.h"
#include "battery.h"
#include "comm-host.h"
+#include "chipset.h"
#include "compile_time_macros.h"
#include "cros_ec_dev.h"
#include "ec_panicinfo.h"
@@ -256,6 +257,9 @@ const char help_str[] =
" Get/set TMP006 calibration\n"
" tmp006raw <tmp006_index>\n"
" Get raw TMP006 data\n"
+ " uptimeinfo\n"
+ " Get info about how long the EC has been running and the most\n"
+ " recent AP resets\n"
" usbchargemode <port> <mode>\n"
" Set USB charging mode\n"
" usbmux <mux>\n"
@@ -622,6 +626,125 @@ int cmd_cmdversions(int argc, char *argv[])
return 0;
}
+/*
+ * Convert a reset cause ID to human-readable string, providing total coverage
+ * of the 'cause' space. The returned string points to static storage and must
+ * not be free()ed.
+ */
+static const char *reset_cause_to_str(uint16_t cause)
+{
+ static const char * const reset_causes[] = {
+ "(reset unknown)",
+ "reset: board custom",
+ "reset: ap hang detected",
+ "reset: console command",
+ "reset: keyboard sysreset",
+ "reset: keyboard warm reboot",
+ "reset: debug warm reboot",
+ "reset: at AP's request",
+ "reset: during EC initialization",
+ };
+ BUILD_ASSERT(ARRAY_SIZE(reset_causes) == CHIPSET_RESET_COUNT);
+
+ static const char * const shutdown_causes[] = {
+ "shutdown: power failure",
+ "shutdown: during EC initialization",
+ "shutdown: board custom",
+ "shutdown: battery voltage startup inhibit",
+ "shutdown: power wait asserted",
+ "shutdown: critical battery",
+ "shutdown: by console command",
+ "shutdown: entering G3",
+ "shutdown: thermal",
+ "shutdown: power button",
+ };
+ BUILD_ASSERT(ARRAY_SIZE(shutdown_causes) ==
+ CHIPSET_SHUTDOWN_COUNT - CHIPSET_SHUTDOWN_BEGIN);
+
+ if (cause < CHIPSET_RESET_COUNT)
+ return reset_causes[cause];
+
+ if (cause < CHIPSET_SHUTDOWN_BEGIN)
+ return "(reset unknown)";
+
+ if (cause < CHIPSET_SHUTDOWN_COUNT)
+ return shutdown_causes[cause - CHIPSET_SHUTDOWN_BEGIN];
+
+ return "(shutdown unknown)";
+}
+
+int cmd_uptimeinfo(int argc, char *argv[])
+{
+ static const char * const reset_flag_strings[] = {
+ "other",
+ "reset-pin",
+ "brownout",
+ "power-on",
+ "watchdog",
+ "soft",
+ "hibernate",
+ "rtc-alarm",
+ "wake-pin",
+ "low-battery",
+ "sysjump",
+ "hard",
+ "ap-off",
+ "preserved",
+ "usb-resume",
+ "rdd",
+ "rbox",
+ "security"
+ };
+
+ struct ec_response_uptime_info r;
+ int rv;
+ int i;
+ int flag_count;
+ uint32_t flag;
+
+ if (argc != 1) {
+ fprintf(stderr, "uptimeinfo takes no arguments");
+ return -1;
+ }
+
+ rv = ec_command(EC_CMD_GET_UPTIME_INFO, 0, NULL, 0, &r, sizeof(r));
+ if (rv < 0) {
+ fprintf(stderr, "ERROR: EC_CMD_GET_UPTIME_INFO failed; %d\n",
+ rv);
+ return rv;
+ }
+
+ printf("EC uptime: %d.%03d seconds\n",
+ r.time_since_ec_boot_ms / 1000,
+ r.time_since_ec_boot_ms % 1000);
+
+ printf("AP resets since EC boot: %d\n", r.ap_resets_since_ec_boot);
+
+ printf("Most recent AP reset causes:\n");
+ for (i = 0; i != ARRAY_SIZE(r.recent_ap_reset); ++i) {
+ if (r.recent_ap_reset[i].reset_time_ms == 0)
+ continue;
+
+ printf("\t%d.%03d: %s\n",
+ r.recent_ap_reset[i].reset_time_ms / 1000,
+ r.recent_ap_reset[i].reset_time_ms % 1000,
+ reset_cause_to_str(r.recent_ap_reset[i].reset_cause));
+ }
+
+ printf("EC reset flags at last EC boot: ");
+ flag_count = 0;
+ for (flag = 0; flag != ARRAY_SIZE(reset_flag_strings); ++flag) {
+ if ((r.ec_reset_flags & (1 << flag)) != 0) {
+ if (flag_count)
+ printf(" | ");
+ printf(reset_flag_strings[flag]);
+ flag_count++;
+ }
+ }
+ printf("\n");
+ return 0;
+}
+
int cmd_version(int argc, char *argv[])
{
struct ec_response_get_version r;
@@ -8115,6 +8238,7 @@ const struct command commands[] = {
{"tpframeget", cmd_tp_frame_get},
{"tmp006cal", cmd_tmp006cal},
{"tmp006raw", cmd_tmp006raw},
+ {"uptimeinfo", cmd_uptimeinfo},
{"usbchargemode", cmd_usb_charge_set_mode},
{"usbmux", cmd_usb_mux},
{"usbpd", cmd_usb_pd},