summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBill Richardson <wfrichar@chromium.org>2012-05-22 11:00:36 -0700
committerBill Richardson <wfrichar@chromium.org>2012-05-22 14:22:13 -0700
commita7d62b4fd4b4cd9e290bbd1e9e2e479f9ab9455e (patch)
tree8a67e8760ce9dcd079bed3a245ebd5370a43636e
parent43e26da7940633bca4b6cfcb0ff8a541375506f9 (diff)
downloadchrome-ec-a7d62b4fd4b4cd9e290bbd1e9e2e479f9ab9455e.tar.gz
Add LPC command to handle vboot stuff.
This adds "ectool vboot", which works like so: # ./ectool vboot 0x06 image=A fake_dev=1 # ./ectool vboot 0 # ./ectool vboot 0x02 image=A fake_dev=0 # ./ectool vboot ff # ./ectool vboot 0x06 image=A fake_dev=1 You can set or unset the fake dev-switch, and see which firmware image the EC is running from. BUG=chrome-os-partner:8313 TEST=manual Boot the host, use crossystem to see the devsw_boot state. Change it with the ectool command, reboot, see that it's changed. Change-Id: Iaac40267338c6a07bc47b80e925e829bf1e1ae0c Signed-off-by: Bill Richardson <wfrichar@chromium.org>
-rw-r--r--common/vboot.c44
-rw-r--r--include/ec_commands.h27
-rw-r--r--include/vboot.h13
-rw-r--r--util/ectool.c76
4 files changed, 155 insertions, 5 deletions
diff --git a/common/vboot.c b/common/vboot.c
index c3825c11c9..89bcf73789 100644
--- a/common/vboot.c
+++ b/common/vboot.c
@@ -7,7 +7,9 @@
#include "console.h"
#include "cryptolib.h"
+#include "eoption.h"
#include "gpio.h"
+#include "host_command.h"
#include "keyboard_scan.h"
#include "system.h"
#include "timer.h"
@@ -197,3 +199,45 @@ bad:
CPRINTF("[FIXME: How to trigger recovery mode?]\n");
return EC_ERROR_UNKNOWN;
}
+
+/****************************************************************************/
+/* Host commands via LPC bus */
+/****************************************************************************/
+
+static int host_cmd_vboot(uint8_t *data, int *resp_size)
+{
+ struct ec_params_vboot_cmd *ptr =
+ (struct ec_params_vboot_cmd *)data;
+ uint8_t v;
+
+ switch (ptr->in.cmd) {
+ case VBOOT_CMD_GET_FLAGS:
+ v = VBOOT_FLAGS_IMAGE_MASK & system_get_image_copy();
+#ifdef CONFIG_FAKE_DEV_SWITCH
+ if (eoption_get_bool(EOPTION_BOOL_FAKE_DEV))
+ v |= VBOOT_FLAGS_FAKE_DEVMODE;
+#endif
+ ptr->out.get_flags.val = v;
+ *resp_size = sizeof(struct ec_params_vboot_cmd);
+ break;
+ case VBOOT_CMD_SET_FLAGS:
+ v = ptr->in.set_flags.val;
+#ifdef CONFIG_FAKE_DEV_SWITCH
+ if (v & VBOOT_FLAGS_FAKE_DEVMODE) {
+ eoption_set_bool(EOPTION_BOOL_FAKE_DEV, 1);
+ CPUTS("[Enabling fake dev-mode]\n");
+ } else {
+ eoption_set_bool(EOPTION_BOOL_FAKE_DEV, 0);
+ CPUTS("[Disabling fake dev-mode]\n");
+ }
+#endif
+ break;
+ default:
+ CPRINTF("[%T LB bad cmd 0x%x]\n", ptr->in.cmd);
+ return EC_RES_INVALID_PARAM;
+ }
+
+ return EC_RES_SUCCESS;
+}
+
+DECLARE_HOST_COMMAND(EC_CMD_VBOOT_CMD, host_cmd_vboot);
diff --git a/include/ec_commands.h b/include/ec_commands.h
index 91b5443e79..ea699f3d09 100644
--- a/include/ec_commands.h
+++ b/include/ec_commands.h
@@ -418,6 +418,33 @@ struct ec_params_lightbar_cmd {
} __attribute__ ((packed));
/*****************************************************************************/
+/* Verified boot commands. Details still evolving. */
+#define EC_CMD_VBOOT_CMD 0x29
+struct ec_params_vboot_cmd {
+ union {
+ union {
+ uint8_t cmd;
+ struct {
+ uint8_t cmd;
+ /* no inputs */
+ } get_flags;
+ struct {
+ uint8_t cmd;
+ uint8_t val;
+ } set_flags;
+ } in;
+ union {
+ struct {
+ uint8_t val;
+ } get_flags;
+ struct {
+ /* no outputs */
+ } set_flags;
+ } out;
+ };
+} __attribute__ ((packed));
+
+/*****************************************************************************/
/* USB charging control commands */
/* Set USB port charging mode */
diff --git a/include/vboot.h b/include/vboot.h
index 430c617a52..48d626c0c7 100644
--- a/include/vboot.h
+++ b/include/vboot.h
@@ -17,4 +17,17 @@ int vboot_pre_init(void);
/* Initializes the module. */
int vboot_init(void);
+/* These are the vboot commands available via LPC. */
+enum vboot_command {
+ VBOOT_CMD_GET_FLAGS,
+ VBOOT_CMD_SET_FLAGS,
+ VBOOT_NUM_CMDS,
+};
+
+/* These are the flags transferred across LPC. At the moment, only the devmode
+ flag can be set, and only because it's faked. Ultimately this functionality
+ will be moved elsewhere. */
+#define VBOOT_FLAGS_IMAGE_MASK 0x03 /* enum system_image_copy_t */
+#define VBOOT_FLAGS_FAKE_DEVMODE 0x04 /* fake dev-mode bit */
+
#endif /* __CROS_EC_VBOOT_H */
diff --git a/util/ectool.c b/util/ectool.c
index dd51dc62a9..98b85f22f4 100644
--- a/util/ectool.c
+++ b/util/ectool.c
@@ -12,8 +12,10 @@
#include <unistd.h>
#include "battery.h"
-#include "lightbar.h"
#include "ec_commands.h"
+#include "lightbar.h"
+#include "system.h"
+#include "vboot.h"
/* Handy tricks */
#define BUILD_ASSERT(cond) ((void)sizeof(char[1 - 2*!(cond)]))
@@ -54,10 +56,12 @@ const char help_str[] =
" Erases EC flash\n"
" hello\n"
" Checks for basic communication with EC\n"
- " lightbar reset\n"
- " Puts the lightbar into idle mode\n"
- " lightbar test [NUM]\n"
- " Cycles lights once. Optional argument does nothing.\n"
+ " lightbar [CMDS]\n"
+ " Various lightbar control commands\n"
+ " vboot get\n"
+ " Get vboot flags\n"
+ " vboot set VAL\n"
+ " Set vboot flags\n"
" pstoreinfo\n"
" Prints information on the EC host persistent storage\n"
" pstoreread <offset> <size> <outfile>\n"
@@ -1031,6 +1035,66 @@ static int cmd_lightbar(int argc, char **argv)
return lb_help(argv[0]);
}
+
+/* This needs to match the values defined in vboot.h. I'd like to
+ * define this in one and only one place, but I can't think of a good way to do
+ * that without adding bunch of complexity. This will do for now.
+ */
+static const struct {
+ uint8_t insize;
+ uint8_t outsize;
+} vb_command_paramcount[] = {
+ { sizeof(((struct ec_params_vboot_cmd *)0)->in.get_flags),
+ sizeof(((struct ec_params_vboot_cmd *)0)->out.get_flags) },
+ { sizeof(((struct ec_params_vboot_cmd *)0)->in.set_flags),
+ sizeof(((struct ec_params_vboot_cmd *)0)->out.set_flags) },
+};
+
+/* Note: depends on enum system_image_copy_t */
+static const char * const image_names[] = {"unknown", "RO", "A", "B"};
+
+static int cmd_vboot(int argc, char **argv)
+{
+ int r;
+ uint8_t v;
+ char *e;
+ struct ec_params_vboot_cmd param;
+
+ if (argc == 1) { /* no args = get */
+ param.in.cmd = VBOOT_CMD_GET_FLAGS;
+ r = ec_command(EC_CMD_VBOOT_CMD,
+ &param,
+ vb_command_paramcount[param.in.cmd].insize,
+ &param,
+ vb_command_paramcount[param.in.cmd].outsize);
+ if (r)
+ return r;
+
+ v = param.out.get_flags.val;
+ printf("0x%02x image=%s fake_dev=%d\n", v,
+ image_names[VBOOT_FLAGS_IMAGE_MASK & v],
+ VBOOT_FLAGS_FAKE_DEVMODE & v ? 1 : 0);
+ return 0;
+ }
+
+ /* else args => set values */
+
+ v = strtoul(argv[1], &e, 16) & 0xff;
+ if (e && *e) {
+ fprintf(stderr, "Bad value\n");
+ return -1;
+ }
+
+ param.in.cmd = VBOOT_CMD_SET_FLAGS;
+ param.in.set_flags.val = v;
+ r = ec_command(EC_CMD_VBOOT_CMD,
+ &param,
+ vb_command_paramcount[param.in.cmd].insize,
+ &param,
+ vb_command_paramcount[param.in.cmd].outsize);
+ return r;
+}
+
int cmd_usb_charge_set_mode(int argc, char *argv[])
{
struct ec_params_usb_charge_set_mode p;
@@ -1482,6 +1546,7 @@ const struct command commands[] = {
{"flashinfo", cmd_flash_info},
{"hello", cmd_hello},
{"lightbar", cmd_lightbar},
+ {"vboot", cmd_vboot},
{"pstoreinfo", cmd_pstore_info},
{"pstoreread", cmd_pstore_read},
{"pstorewrite", cmd_pstore_write},
@@ -1509,6 +1574,7 @@ int main(int argc, char *argv[])
const struct command *cmd;
BUILD_ASSERT(ARRAY_SIZE(lb_command_paramcount) == LIGHTBAR_NUM_CMDS);
+ BUILD_ASSERT(ARRAY_SIZE(vb_command_paramcount) == VBOOT_NUM_CMDS);
if (argc < 2 || !strcasecmp(argv[1], "-?") ||
!strcasecmp(argv[1], "help")) {