summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRandall Spangler <rspangler@chromium.org>2012-08-27 15:31:13 -0700
committerGerrit <chrome-bot@google.com>2012-08-28 14:05:08 -0700
commitac26b57735e57647544f2838d0548c1b7263c284 (patch)
tree643f82465e3e336c0ac37220baf312e436100e1b
parent73e439dc87767e92f45ff78641449c796caa6ef8 (diff)
downloadchrome-ec-ac26b57735e57647544f2838d0548c1b7263c284.tar.gz
Copy host command params out of LPC space during checksumming
This prevents the host from rewriting them during the checksum operation. BUG=chrome-os-partner:13202 TEST='ectool version' should still work BRANCH=link Change-Id: Ib44f45b027c0a54ba40f70052728ba427dc71849 Signed-off-by: Randall Spangler <rspangler@chromium.org> Reviewed-on: https://gerrit.chromium.org/gerrit/31511 Reviewed-by: Simon Glass <sjg@chromium.org>
-rw-r--r--chip/lm4/lpc.c33
-rw-r--r--include/host_command.h1
2 files changed, 23 insertions, 11 deletions
diff --git a/chip/lm4/lpc.c b/chip/lm4/lpc.c
index c098a5f571..74c31ebd97 100644
--- a/chip/lm4/lpc.c
+++ b/chip/lm4/lpc.c
@@ -35,6 +35,7 @@ static uint8_t acpi_mem_test; /* Test byte in ACPI memory space */
static uint32_t host_events; /* Currently pending SCI/SMI events */
static uint32_t event_mask[3]; /* Event masks for each type */
static struct host_cmd_handler_args host_cmd_args;
+static uint8_t params_copy[EC_HOST_PARAM_SIZE];
static int init_done;
static uint8_t * const cmd_params = (uint8_t *)LPC_POOL_CMD_DATA +
@@ -143,14 +144,13 @@ static void lpc_send_response(struct host_cmd_handler_args *args)
size = 0;
}
- /* TODO(sjg@chromium.org): put flags in args? */
- if (lpc_host_args->flags & EC_HOST_ARGS_FLAG_FROM_HOST) {
+ if (args->flags & EC_HOST_ARGS_FLAG_FROM_HOST) {
/* New-style response */
int csum;
int i;
lpc_host_args->flags =
- (lpc_host_args->flags & ~EC_HOST_ARGS_FLAG_FROM_HOST) |
+ (args->flags & ~EC_HOST_ARGS_FLAG_FROM_HOST) |
EC_HOST_ARGS_FLAG_TO_HOST;
lpc_host_args->data_size = size;
@@ -456,15 +456,16 @@ static void handle_host_command(int cmd)
host_cmd_args.command = cmd;
host_cmd_args.result = EC_RES_SUCCESS;
host_cmd_args.send_response = lpc_send_response;
+ host_cmd_args.flags = lpc_host_args->flags;
/* See if we have an old or new style command */
- if (lpc_host_args->flags & EC_HOST_ARGS_FLAG_FROM_HOST) {
+ if (host_cmd_args.flags & EC_HOST_ARGS_FLAG_FROM_HOST) {
/* New style command */
int size = lpc_host_args->data_size;
int csum, i;
host_cmd_args.version = lpc_host_args->command_version;
- host_cmd_args.params = cmd_params;
+ host_cmd_args.params = params_copy;
host_cmd_args.params_size = size;
host_cmd_args.response = cmd_params;
host_cmd_args.response_max = EC_HOST_PARAM_SIZE;
@@ -474,14 +475,24 @@ static void handle_host_command(int cmd)
if (size > EC_HOST_PARAM_SIZE) {
host_cmd_args.result = EC_RES_INVALID_PARAM;
} else {
- /* Verify checksum */
+ const uint8_t *src = cmd_params;
+ uint8_t *copy = params_copy;
+
+ /*
+ * Verify checksum and copy params out of LPC space.
+ * This ensures the data acted on by the host command
+ * handler can't be changed by host writes after the
+ * checksum is verified.
+ */
csum = host_cmd_args.command +
- lpc_host_args->flags +
- lpc_host_args->command_version +
- lpc_host_args->data_size;
+ host_cmd_args.flags +
+ host_cmd_args.version +
+ host_cmd_args.params_size;
- for (i = 0; i < size; i++)
- csum += cmd_params[i];
+ for (i = 0; i < size; i++) {
+ csum += *src;
+ *(copy++) = *(src++);
+ }
if ((uint8_t)csum != lpc_host_args->checksum)
host_cmd_args.result = EC_RES_INVALID_CHECKSUM;
diff --git a/include/host_command.h b/include/host_command.h
index 6218d17ebc..3afca62908 100644
--- a/include/host_command.h
+++ b/include/host_command.h
@@ -21,6 +21,7 @@ struct host_cmd_handler_args {
void (*send_response)(struct host_cmd_handler_args *args);
uint8_t command; /* Command (e.g., EC_CMD_FLASH_GET_INFO) */
uint8_t version; /* Version of command (0-31) */
+ uint8_t flags; /* Flags (EC_HOST_ARGS_FLAG_*) */
uint8_t params_size; /* Size of input parameters in bytes */
uint8_t i2c_old_response; /* (for I2C) send an old-style response */
const void *params; /* Input parameters */