diff options
author | Randall Spangler <rspangler@chromium.org> | 2012-08-09 15:17:24 -0700 |
---|---|---|
committer | Gerrit <chrome-bot@google.com> | 2012-08-09 17:40:38 -0700 |
commit | 6cd9e1124b2432f7b6d8693cc4bd170514cfd689 (patch) | |
tree | d418d284bd196d476426287c472dec8e5142ab43 /common/uart_buffering.c | |
parent | 371d06bbfdf56fad142539c9a72759e53d5bc26a (diff) | |
download | chrome-ec-6cd9e1124b2432f7b6d8693cc4bd170514cfd689.tar.gz |
Add ectool command to read snapshot of EC's console output
BUG=chrome-os-partner:12483
TEST=from root shell, 'ectool console', then on the ec console, type
'help list' a few times to generate lots of debug output, then repeat
'ectool console'. Then on EC console, 'syslock', and then 'ectool
console' should fail.
Change-Id: Ie1c74c7e35d6b8228615d20192fd90093977de64
Signed-off-by: Randall Spangler <rspangler@chromium.org>
Reviewed-on: https://gerrit.chromium.org/gerrit/29825
Reviewed-by: Bill Richardson <wfrichar@chromium.org>
Diffstat (limited to 'common/uart_buffering.c')
-rw-r--r-- | common/uart_buffering.c | 86 |
1 files changed, 85 insertions, 1 deletions
diff --git a/common/uart_buffering.c b/common/uart_buffering.c index 4e7accec66..1dd56aed60 100644 --- a/common/uart_buffering.c +++ b/common/uart_buffering.c @@ -9,7 +9,9 @@ #include "common.h" #include "console.h" +#include "host_command.h" #include "printf.h" +#include "system.h" #include "task.h" #include "uart.h" #include "util.h" @@ -39,7 +41,8 @@ #define CMD_HIST_NEXT(i) (((i) + 1) & (HISTORY_SIZE - 1)) #define CMD_HIST_PREV(i) (((i) - 1) & (HISTORY_SIZE - 1)) -/* Macro to calculate difference of pointers in the circular receive buffer. */ +/* Macros to calculate difference of pointers in the circular buffers. */ +#define TX_BUF_DIFF(i, j) (((i) - (j)) & (CONFIG_UART_TX_BUF_SIZE - 1)) #define RX_BUF_DIFF(i, j) (((i) - (j)) & (CONFIG_UART_RX_BUF_SIZE - 1)) /* ASCII control character; for example, CTRL('C') = ^C */ @@ -57,6 +60,8 @@ static volatile int rx_cur_buf_tail; static volatile int rx_cur_buf_head; static volatile int rx_cur_buf_ptr; static int last_rx_was_cr; +static int tx_snapshot_head; +static int tx_snapshot_tail; static enum { ESC_OUTSIDE, /* Not in escape code */ @@ -748,3 +753,82 @@ int uart_gets(char *dest, int size) /* Return the length we got */ return got; } + +/*****************************************************************************/ +/* Host commands */ + +static int host_command_console_snapshot(struct host_cmd_handler_args *args) +{ + /* + * Only allowed on unlocked system, since console output contains + * keystroke data. + */ + if (system_is_locked()) + return EC_ERROR_ACCESS_DENIED; + + /* Assume the whole circular buffer is full */ + tx_snapshot_head = tx_buf_head; + tx_snapshot_tail = TX_BUF_NEXT(tx_snapshot_head); + + /* + * Immediately skip any unused bytes. This doesn't always work, + * because a higher-priority task or interrupt handler can write to the + * buffer while we're scanning it. This is acceptable because this + * command is only for debugging, and the failure mode is a bit of + * garbage at the beginning of the saved output. The saved buffer + * could also be overwritten by the head coming completely back around + * before we finish. The alternative would be to make a full copy of + * the transmit buffer, but that requires a lot of RAM. + */ + while (tx_snapshot_tail != tx_snapshot_head) { + if (tx_buf[tx_snapshot_tail]) + break; + tx_snapshot_tail = TX_BUF_NEXT(tx_snapshot_tail); + } + + return EC_RES_SUCCESS; +} +DECLARE_HOST_COMMAND(EC_CMD_CONSOLE_SNAPSHOT, + host_command_console_snapshot, + EC_VER_MASK(0)); + +static int host_command_console_read(struct host_cmd_handler_args *args) +{ + char *dest = (char *)args->response; + + /* + * Only allowed on unlocked system, since console output contains + * keystroke data. + */ + if (system_is_locked()) + return EC_ERROR_ACCESS_DENIED; + + /* If no snapshot data, return empty response */ + if (tx_snapshot_head == tx_snapshot_tail) + return EC_RES_SUCCESS; + + /* Copy data to response */ + while (tx_snapshot_tail != tx_snapshot_head && + args->response_size < args->response_max - 1) { + + /* + * Copy only non-zero bytes, so that we don't copy unused + * bytes if the buffer hasn't completely rolled at boot. + */ + if (tx_buf[tx_snapshot_tail]) { + *(dest++) = tx_buf[tx_snapshot_tail]; + args->response_size++; + } + + tx_snapshot_tail = TX_BUF_NEXT(tx_snapshot_tail); + } + + /* Null-terminate */ + *(dest++) = '\0'; + args->response_size++; + + return EC_RES_SUCCESS; +} +DECLARE_HOST_COMMAND(EC_CMD_CONSOLE_READ, + host_command_console_read, + EC_VER_MASK(0)); |