diff options
author | Bill Richardson <wfrichar@chromium.org> | 2012-05-22 11:00:36 -0700 |
---|---|---|
committer | Bill Richardson <wfrichar@chromium.org> | 2012-05-22 14:22:13 -0700 |
commit | a7d62b4fd4b4cd9e290bbd1e9e2e479f9ab9455e (patch) | |
tree | 8a67e8760ce9dcd079bed3a245ebd5370a43636e | |
parent | 43e26da7940633bca4b6cfcb0ff8a541375506f9 (diff) | |
download | chrome-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.c | 44 | ||||
-rw-r--r-- | include/ec_commands.h | 27 | ||||
-rw-r--r-- | include/vboot.h | 13 | ||||
-rw-r--r-- | util/ectool.c | 76 |
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, + ¶m, + vb_command_paramcount[param.in.cmd].insize, + ¶m, + 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, + ¶m, + vb_command_paramcount[param.in.cmd].insize, + ¶m, + 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")) { |