summaryrefslogtreecommitdiff
path: root/common/host_command.c
diff options
context:
space:
mode:
authorRandall Spangler <rspangler@chromium.org>2011-12-07 18:51:09 +0000
committerVincent Palatin <vpalatin@chromium.org>2011-12-07 19:10:02 +0000
commitbdf7da5b082f6d18dd27f1e5d8cca0b12154a28c (patch)
tree6f14312a6cc70d056efc2bede8728c0868266719 /common/host_command.c
parentabe5786058f4b60dc6d30e7d7c964aae850caa1f (diff)
downloadchrome-ec-bdf7da5b082f6d18dd27f1e5d8cca0b12154a28c.tar.gz
Initial sources import 1/3
source files mainly done by Randall. Signed-off-by: Randall Spangler <rspangler@chromium.org> Change-Id: Iaff83a842b17f3350fb6f2a3f1597ad4c29bd12a
Diffstat (limited to 'common/host_command.c')
-rw-r--r--common/host_command.c203
1 files changed, 203 insertions, 0 deletions
diff --git a/common/host_command.c b/common/host_command.c
new file mode 100644
index 0000000000..1f27196412
--- /dev/null
+++ b/common/host_command.c
@@ -0,0 +1,203 @@
+/* Copyright (c) 2011 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.
+ */
+
+/* Host command module for Chrome EC */
+
+#include "config.h"
+#include "console.h"
+#include "flash_commands.h"
+#include "host_command.h"
+#include "lpc.h"
+#include "lpc_commands.h"
+#include "system.h"
+#include "task.h"
+#include "uart.h"
+#include "registers.h"
+#include "util.h"
+
+static int host_command = 0;
+static uint8_t *host_data;
+
+/*****************************************************************************/
+/* Host commands */
+
+void host_command_received(int command)
+{
+ /* TODO: should warn if we already think we're in a command */
+
+ /* If this is the reboot command, reboot immediately. This gives
+ * the host processor a way to unwedge the EC even if it's busy with
+ * some other command. */
+ if (command == EC_LPC_COMMAND_REBOOT) {
+ system_reset(1);
+ /* Reset should never return; if it does, post an error */
+ lpc_send_host_response(EC_LPC_STATUS_ERROR);
+ return;
+ }
+
+ /* Save the command */
+ host_command = command;
+
+ /* Wake up the task to handle the command */
+ task_send_msg(TASK_ID_HOSTCMD, TASK_ID_HOSTCMD, 0);
+}
+
+
+static enum lpc_status HostCommandHello(uint8_t *data)
+{
+ struct lpc_params_hello *p = (struct lpc_params_hello *)data;
+ struct lpc_response_hello *r = (struct lpc_response_hello *)data;
+ uint32_t d = p->in_data;
+
+ uart_printf("[LPC Hello 0x%08x]\n", d);
+
+ /* TODO - remove this delay. For now, pretend command takes a long
+ * time, so we can see the busy bit set on the host side. */
+ {
+ volatile int i __attribute__((unused));
+ int j;
+ for (j = 0; j < 10000000; j++)
+ i = j;
+ }
+ uart_puts("[LPC sending hello back]\n");
+
+ r->out_data = d + 0x01020304;
+ return EC_LPC_STATUS_SUCCESS;
+}
+
+
+static enum lpc_status HostCommandGetVersion(uint8_t *data)
+{
+ struct lpc_response_get_version *r =
+ (struct lpc_response_get_version *)data;
+
+ uart_printf("[LPC GetVersion]\n");
+
+ strzcpy(r->version_string_ro, system_get_version(SYSTEM_IMAGE_RO),
+ sizeof(r->version_string_ro));
+ strzcpy(r->version_string_rw_a, system_get_version(SYSTEM_IMAGE_RW_A),
+ sizeof(r->version_string_rw_a));
+ strzcpy(r->version_string_rw_b, system_get_version(SYSTEM_IMAGE_RW_B),
+ sizeof(r->version_string_rw_b));
+
+ switch(system_get_image_copy()) {
+ case SYSTEM_IMAGE_RO:
+ r->current_image = EC_LPC_IMAGE_RO;
+ break;
+ case SYSTEM_IMAGE_RW_A:
+ r->current_image = EC_LPC_IMAGE_RW_A;
+ break;
+ case SYSTEM_IMAGE_RW_B:
+ r->current_image = EC_LPC_IMAGE_RW_B;
+ break;
+ default:
+ r->current_image = EC_LPC_IMAGE_UNKNOWN;
+ break;
+ }
+
+ return EC_LPC_STATUS_SUCCESS;
+}
+
+
+static enum lpc_status HostCommandReadTest(uint8_t *data)
+{
+ struct lpc_params_read_test *p = (struct lpc_params_read_test *)data;
+ struct lpc_response_read_test *r =
+ (struct lpc_response_read_test *)data;
+
+ int offset = p->offset;
+ int size = p->size / sizeof(uint32_t);
+ int i;
+
+ if (size > ARRAY_SIZE(r->data))
+ return EC_LPC_STATUS_ERROR;
+
+ for (i = 0; i < size; i++)
+ r->data[i] = offset + i;
+
+ return EC_LPC_STATUS_SUCCESS;
+}
+
+
+/* handle a LPC command */
+static void command_process(void)
+{
+ uart_printf("[hostcmd 0x%02x]\n", host_command);
+
+ /* TODO: might be smaller to make this a table, once we get a bunch
+ * of commands. */
+ switch (host_command) {
+ case EC_LPC_COMMAND_HELLO:
+ lpc_send_host_response(HostCommandHello(host_data));
+ return;
+ case EC_LPC_COMMAND_GET_VERSION:
+ lpc_send_host_response(HostCommandGetVersion(host_data));
+ return;
+ case EC_LPC_COMMAND_READ_TEST:
+ lpc_send_host_response(HostCommandReadTest(host_data));
+ return;
+ case EC_LPC_COMMAND_FLASH_INFO:
+ lpc_send_host_response(flash_command_get_info(host_data));
+ return;
+ case EC_LPC_COMMAND_FLASH_READ:
+ lpc_send_host_response(flash_command_read(host_data));
+ return;
+ case EC_LPC_COMMAND_FLASH_WRITE:
+ lpc_send_host_response(flash_command_write(host_data));
+ return;
+ case EC_LPC_COMMAND_FLASH_ERASE:
+ lpc_send_host_response(flash_command_erase(host_data));
+ return;
+ default:
+ lpc_send_host_response(EC_LPC_STATUS_INVALID_COMMAND);
+ }
+}
+
+/*****************************************************************************/
+/* Console commands */
+
+/* Command handler - prints EC version. */
+static int command_version(int argc, char **argv)
+{
+ uart_printf("RO version: %s\n",
+ system_get_version(SYSTEM_IMAGE_RO));
+ uart_printf("RW-A version: %s\n",
+ system_get_version(SYSTEM_IMAGE_RW_A));
+ uart_printf("RW-B version: %s\n",
+ system_get_version(SYSTEM_IMAGE_RW_B));
+ return EC_SUCCESS;
+}
+
+
+static const struct console_command console_commands[] = {
+ {"version", command_version},
+};
+
+static const struct console_group command_group = {
+ "Host commands", console_commands, ARRAY_SIZE(console_commands)
+};
+
+/*****************************************************************************/
+/* Initialization */
+
+int host_command_init(void)
+{
+ host_data = (uint8_t *)lpc_get_host_range();
+
+ console_register_commands(&command_group);
+ return EC_SUCCESS;
+}
+
+void host_command_task(void)
+{
+ host_command_init();
+
+ while (1) {
+ /* wait for the next command message */
+ task_wait_msg(-1);
+ /* process it */
+ command_process();
+ }
+}