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>
This commit is contained in:
Bill Richardson
2012-05-22 11:00:36 -07:00
parent 43e26da794
commit a7d62b4fd4
4 changed files with 155 additions and 5 deletions

View File

@@ -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);

View File

@@ -417,6 +417,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 */

View File

@@ -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 */

View File

@@ -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")) {