summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTodd Broch <tbroch@chromium.org>2014-12-17 18:35:59 -0800
committerChromeOS Commit Bot <chromeos-commit-bot@chromium.org>2015-01-30 03:28:20 +0000
commit25bf61ea3c3d5ad667f5eb804f0c85d0330d56f8 (patch)
tree34d09f8c67c4ad73ff42013d4507f22fb3817252
parentd5ee7f958bbc0d986768dcdaf3b8f4b598d0b1a7 (diff)
downloadchrome-ec-25bf61ea3c3d5ad667f5eb804f0c85d0330d56f8.tar.gz
ectool: Add enter_gfu to support PD flashing.
Flashing PD devices works through ectool but only when device has already entered GFU alternate mode. This CL adds ability to force that entry for devices with default policy engine does not already do that. Signed-off-by: Todd Broch <tbroch@chromium.org> BRANCH=samus BUG=chrome-os-partner:33947 TEST=manual, 1. On hoho flash RW successfully ectool --name cros_pd flashpd 4 1 hoho.ec.RW.bin Original-Change-Id: Idd320cf91644f0c1bff87767ab20049d86aa86c6 Reviewed-on: https://chromium-review.googlesource.com/236959 Reviewed-by: Alec Berg <alecaberg@chromium.org> Tested-by: Todd Broch <tbroch@chromium.org> (cherry picked from commit 94515d9ee25c76c7813addff38599636d916931d) Signed-off-by: Alec Berg <alecaberg@chromium.org> Reviewed-on: https://chromium-review.googlesource.com/241431 (cherry picked from commit a7a826c391ec20e4d9068318fcac053ed0c63cce) Signed-off-by: Todd Broch <tbroch@chromium.org> Change-Id: I4cf96ca1f2286935e33fe8405bae118eff1af222 Reviewed-on: https://chromium-review.googlesource.com/244226 Reviewed-by: Alec Berg <alecaberg@chromium.org> Tested-by: Todd Broch <tbroch@chromium.org> Commit-Queue: Todd Broch <tbroch@chromium.org>
-rw-r--r--util/ectool.c143
1 files changed, 122 insertions, 21 deletions
diff --git a/util/ectool.c b/util/ectool.c
index e78ef5d65f..28c2258af1 100644
--- a/util/ectool.c
+++ b/util/ectool.c
@@ -98,7 +98,7 @@ const char help_str[] =
" Erases EC flash\n"
" flashinfo\n"
" Prints information on the EC flash\n"
- " flashpd\n"
+ " flashpd <dev_id> <port> <filename>\n"
" Flash commands over PD\n"
" flashprotect [now] [enable | disable]\n"
" Prints or sets EC flash protection state\n"
@@ -836,10 +836,86 @@ int cmd_rw_hash_pd(int argc, char *argv[])
return rv;
}
+/**
+ * determine if in GFU mode or not.
+ *
+ * NOTE, Sends HOST commands that modify ec_outbuf contents.
+ *
+ * @opos return value of GFU mode object position or zero if not found
+ * @port port number to query
+ * @return 1 if in GFU mode, 0 if not, -1 if error
+ */
+static int in_gfu_mode(int *opos, int port)
+{
+ int i;
+ struct ec_params_usb_pd_get_mode_request *p =
+ (struct ec_params_usb_pd_get_mode_request *)ec_outbuf;
+ struct ec_params_usb_pd_get_mode_response *r =
+ (struct ec_params_usb_pd_get_mode_response *)ec_inbuf;
+ p->port = port;
+ p->svid_idx = 0;
+ do {
+ ec_command(EC_CMD_USB_PD_GET_AMODE, 0, p, sizeof(*p),
+ ec_inbuf, ec_max_insize);
+ if (!r->svid || (r->svid == USB_VID_GOOGLE))
+ break;
+ p->svid_idx++;
+ } while (p->svid_idx < SVID_DISCOVERY_MAX);
+
+ if (r->svid != USB_VID_GOOGLE) {
+ fprintf(stderr, "Google VID not returned\n");
+ return -1;
+ }
+
+ *opos = 0; /* invalid ... must be 1 thru 6 */
+ for (i = 0; i < PDO_MODES; i++) {
+ if (r->vdo[i] == MODE_GOOGLE_FU) {
+ *opos = i + 1;
+ break;
+ }
+ }
+
+ return r->active && ((r->idx + 1) == *opos);
+}
+
+/**
+ * Enter GFU mode.
+ *
+ * NOTE, Sends HOST commands that modify ec_outbuf contents.
+ *
+ * @port port number to enter GFU on.
+ * @return 1 if entered GFU mode, 0 if not, -1 if error
+ */
+static int enter_gfu_mode(int port)
+{
+ int opos;
+ struct ec_params_usb_pd_set_mode_request *p =
+ (struct ec_params_usb_pd_set_mode_request *)ec_outbuf;
+ int gfu_mode = in_gfu_mode(&opos, port);
+
+ if (gfu_mode < 0) {
+ fprintf(stderr, "Failed to query GFU mode support\n");
+ return 0;
+ } else if (!gfu_mode) {
+ if (!opos) {
+ fprintf(stderr, "Invalid object position %d\n", opos);
+ return 0;
+ }
+ p->port = port;
+ p->svid = USB_VID_GOOGLE;
+ p->opos = opos;
+
+ ec_command(EC_CMD_USB_PD_SET_AMODE, 0, p, sizeof(*p),
+ NULL, 0);
+ usleep(500000); /* sleep to allow time for set mode */
+ gfu_mode = in_gfu_mode(&opos, port);
+ }
+ return gfu_mode;
+}
int cmd_pd_device_info(int argc, char *argv[])
{
- int i, rv;
+ int i, rv, port;
char *e;
struct ec_params_usb_pd_info_request *p =
(struct ec_params_usb_pd_info_request *)ec_outbuf;
@@ -852,22 +928,41 @@ int cmd_pd_device_info(int argc, char *argv[])
return -1;
}
- p->port = strtol(argv[1], &e, 0);
+ port = strtol(argv[1], &e, 0);
if (e && *e) {
fprintf(stderr, "Bad port\n");
return -1;
}
+ r1 = (struct ec_params_usb_pd_discovery_entry *)ec_inbuf;
+ rv = ec_command(EC_CMD_USB_PD_DISCOVERY, 0, p, sizeof(*p),
+ ec_inbuf, ec_max_insize);
+ if (rv < 0)
+ return rv;
+
+ if (!r1->vid)
+ printf("Port:%d has no discovered device\n", port);
+ else {
+ printf("Port:%d ptype:%d vid:0x%04x pid:0x%04x\n", port,
+ r1->ptype, r1->vid, r1->pid);
+ }
+
+ if (enter_gfu_mode(port) != 1) {
+ fprintf(stderr, "Failed to enter GFU mode\n");
+ return -1;
+ }
+
+ p->port = port;
rv = ec_command(EC_CMD_USB_PD_DEV_INFO, 0, p, sizeof(*p),
ec_inbuf, ec_max_insize);
if (rv < 0)
return rv;
if (!r0->dev_id)
- printf("Port:%d has no valid device\n", p->port);
+ printf("Port:%d has no valid device\n", port);
else {
uint8_t *rwp = r0->dev_rw_hash;
- printf("Port:%d DevId:%d.%d Hash:", p->port,
+ printf("Port:%d DevId:%d.%d Hash:", port,
HW_DEV_ID_MAJ(r0->dev_id), HW_DEV_ID_MIN(r0->dev_id));
for (i = 0; i < 5; i++) {
printf(" 0x%02x%02x%02x%02x", rwp[3], rwp[2], rwp[1],
@@ -877,19 +972,6 @@ int cmd_pd_device_info(int argc, char *argv[])
printf(" CurImg:%s\n", image_names[r0->current_image]);
}
- r1 = (struct ec_params_usb_pd_discovery_entry *)ec_inbuf;
- rv = ec_command(EC_CMD_USB_PD_DISCOVERY, 0, p, sizeof(*p),
- ec_inbuf, ec_max_insize);
- if (rv < 0)
- return rv;
-
- if (!r1->vid)
- printf("Port:%d has no discovered device\n", p->port);
- else {
- printf("Port:%d ptype:%d vid:0x%04x pid:0x%04x\n", p->port,
- r1->ptype, r1->vid, r1->pid);
- }
-
return rv;
}
@@ -897,7 +979,7 @@ int cmd_flash_pd(int argc, char *argv[])
{
struct ec_params_usb_pd_fw_update *p =
(struct ec_params_usb_pd_fw_update *)ec_outbuf;
- int i;
+ int i, dev_id, port;
int rv, fsize, step = 96;
char *e;
char *buf;
@@ -909,18 +991,23 @@ int cmd_flash_pd(int argc, char *argv[])
return -1;
}
- p->dev_id = strtol(argv[1], &e, 0);
+ dev_id = strtol(argv[1], &e, 0);
if (e && *e) {
fprintf(stderr, "Bad device ID\n");
return -1;
}
- p->port = strtol(argv[2], &e, 0);
+ port = strtol(argv[2], &e, 0);
if (e && *e) {
fprintf(stderr, "Bad port\n");
return -1;
}
+ if (enter_gfu_mode(port) != 1) {
+ fprintf(stderr, "Failed to enter GFU mode\n");
+ return -1;
+ }
+
/* Read the input file */
buf = read_file(argv[3], &fsize);
if (!buf)
@@ -928,6 +1015,8 @@ int cmd_flash_pd(int argc, char *argv[])
/* Erase the current RW RSA signature */
fprintf(stderr, "Erasing expected RW hash\n");
+ p->dev_id = dev_id;
+ p->port = port;
p->cmd = USB_PD_FW_ERASE_SIG;
p->size = 0;
rv = ec_command(EC_CMD_USB_PD_FW_UPDATE, 0,
@@ -938,6 +1027,8 @@ int cmd_flash_pd(int argc, char *argv[])
/* Reboot */
fprintf(stderr, "Rebooting\n");
+ p->dev_id = dev_id;
+ p->port = port;
p->cmd = USB_PD_FW_REBOOT;
p->size = 0;
rv = ec_command(EC_CMD_USB_PD_FW_UPDATE, 0,
@@ -948,8 +1039,16 @@ int cmd_flash_pd(int argc, char *argv[])
usleep(3000000); /* 3sec to reboot and get CC line idle */
+ /* re-enter GFU after reboot */
+ if (enter_gfu_mode(port) != 1) {
+ fprintf(stderr, "Failed to enter GFU mode\n");
+ goto pd_flash_error;
+ }
+
/* Erase RW flash */
fprintf(stderr, "Erasing RW flash\n");
+ p->dev_id = dev_id;
+ p->port = port;
p->cmd = USB_PD_FW_FLASH_ERASE;
p->size = 0;
rv = ec_command(EC_CMD_USB_PD_FW_UPDATE, 0,
@@ -963,6 +1062,8 @@ int cmd_flash_pd(int argc, char *argv[])
/* Write RW flash */
fprintf(stderr, "Writing RW flash\n");
+ p->dev_id = dev_id;
+ p->port = port;
p->cmd = USB_PD_FW_FLASH_WRITE;
p->size = step;