summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVadim Bendebury <vbendeb@chromium.org>2018-01-10 19:05:17 -0800
committerchrome-bot <chrome-bot@chromium.org>2018-01-12 03:27:10 -0800
commita41c59598de1d335af76e6bc4b1178720154d48c (patch)
tree87529c5a36c37e3afbe633aaa71475ec5318850b
parentd99e680b3ce01db9561739862d4e584820060db7 (diff)
downloadchrome-ec-a41c59598de1d335af76e6bc4b1178720154d48c.tar.gz
gsctool: add options to control ccd
The user needs to be able to unlock/open/lock CCD in addition to setting the CCD password. This patch adds command line options for these three CCD subcommands. They all are communicated to the TPM using the same vendor command. 'open' and 'unlock' subcommands could require the user to enter the password. This is indicated by the appropriate vendor command return code. If return code of 'open' or 'unlock' subcommand indicates the need for physical presence, the utility starts polling the Cr50 prompting the user to press the power button when the chip expects it. Some input parameters sanity checks are added to make sure that the user does not request mutually exclusive actions. BRANCH=none BUG=b:62537474 TEST=verified that CCD can be unlocked and opend with and without password, with and without PP required. Change-Id: Iea229a220e9f3d2f5d07cebdaebcb9b297939310 Signed-off-by: Vadim Bendebury <vbendeb@chromium.org> Reviewed-on: https://chromium-review.googlesource.com/861209 Reviewed-by: Randall Spangler <rspangler@chromium.org>
-rw-r--r--extra/usb_updater/gsctool.c143
1 files changed, 133 insertions, 10 deletions
diff --git a/extra/usb_updater/gsctool.c b/extra/usb_updater/gsctool.c
index 986708255e..de26319271 100644
--- a/extra/usb_updater/gsctool.c
+++ b/extra/usb_updater/gsctool.c
@@ -239,12 +239,15 @@ struct transfer_descriptor {
static uint32_t protocol_version;
static char *progname;
-static char *short_opts = "abcd:fhiPprstu";
+static char *short_opts = "abcd:fhikoPprstUu";
static const struct option long_opts[] = {
/* name hasarg *flag val */
{"any", 0, NULL, 'a'},
{"binvers", 0, NULL, 'b'},
{"board_id", 2, NULL, 'i'},
+ {"ccd_lock", 0, NULL, 'k'},
+ {"ccd_open", 0, NULL, 'o'},
+ {"ccd_unlock", 0, NULL, 'U'},
{"corrupt", 0, NULL, 'c'},
{"device", 1, NULL, 'd'},
{"fwver", 0, NULL, 'f'},
@@ -512,6 +515,10 @@ static int tpm_send_pkt(struct transfer_descriptor *td, unsigned int digest,
memcpy(&rv, &((struct upgrade_pkt *)outbuf)->ordinal, sizeof(rv));
rv = be32toh(rv);
+ /* Clear out vendor command return value offset.*/
+ if ((rv & VENDOR_RC_ERR) == VENDOR_RC_ERR)
+ rv &= ~VENDOR_RC_ERR;
+
return rv;
}
@@ -549,9 +556,11 @@ static void usage(int errs)
" Get or set Info1 board ID fields\n"
" ID could be 32 bit hex or 4 "
"character string.\n"
+ " -k,--ccd_lock Lock CCD\n"
+ " -o,--ccd_open Start CCD open sequence\n"
" -P,--password <password>\n"
" Set or clear CCD password. Use\n"
- " 'clear' to clear it.\n"
+ " 'clear:<cur password>' to clear it.\n"
" -p,--post_reset Request post reset after transfer\n"
" -r,--rma_auth [[auth_code|\"disable\"]\n"
" Request RMA challenge, process "
@@ -559,6 +568,7 @@ static void usage(int errs)
" -s,--systemdev Use /dev/tpm0 (-d is ignored)\n"
" -t,--trunks_send Use `trunks_send --raw' "
"(-d is ignored)\n"
+ " -U,--ccd_unlock Start CCD unlock sequence\n"
" -u,--upstart "
"Upstart mode (strict header checks)\n"
"\n", progname, VID, PID);
@@ -1614,6 +1624,94 @@ static void process_password(struct transfer_descriptor *td)
exit(update_error);
}
+static void process_ccd_state(struct transfer_descriptor *td, int ccd_unlock,
+ int ccd_open, int ccd_lock)
+{
+ uint8_t payload;
+ uint8_t response;
+ uint8_t prev_response;
+ size_t response_size;
+ int rv;
+
+ if (ccd_unlock)
+ payload = CCDV_UNLOCK;
+ else if (ccd_open)
+ payload = CCDV_OPEN;
+ else
+ payload = CCDV_LOCK;
+
+ response_size = sizeof(response);
+ rv = send_vendor_command(td, VENDOR_CC_CCD,
+ &payload, sizeof(payload),
+ &response, &response_size);
+
+ /*
+ * If password is required - try sending the same subcommand
+ * accompanied by user password.
+ */
+ if (rv == VENDOR_RC_PASSWORD_REQUIRED)
+ rv = common_process_password(td, payload);
+
+ if (rv == VENDOR_RC_SUCCESS)
+ return;
+
+ if (rv != VENDOR_RC_IN_PROGRESS) {
+ fprintf(stderr, "Error: rv %d, response %d\n",
+ rv, response_size ? response : 0);
+ exit(update_error);
+ }
+
+ /*
+ * Physical presence process started, poll for the state the user
+ * asked for. Only two subcommands would return 'IN_PROGRESS'.
+ */
+ if (ccd_unlock)
+ payload = CCDV_PP_POLL_UNLOCK;
+ else
+ payload = CCDV_PP_POLL_OPEN;
+
+ prev_response = ~0; /* Guaranteed invalid value. */
+ while (1) {
+ response_size = sizeof(response);
+ rv = send_vendor_command(td, VENDOR_CC_CCD,
+ &payload, sizeof(payload),
+ &response, &response_size);
+
+ if (((rv != VENDOR_RC_SUCCESS) && (rv != VENDOR_RC_IN_PROGRESS))
+ || (response_size != 1)) {
+ fprintf(stderr, "Error: rv %d, response %d\n",
+ rv, response_size ? response : 0);
+ exit(update_error);
+ }
+
+ if (response == CCD_PP_DONE) {
+ printf("PP Done!\n");
+ return;
+ }
+
+ if (response == CCD_PP_CLOSED) {
+ fprintf(stderr,
+ "Error: Physical presence check timeout!\n");
+ exit(update_error);
+ }
+
+
+ if (response == CCD_PP_AWAITING_PRESS) {
+ printf("Press PP button now!\n");
+ } else if (response == CCD_PP_BETWEEN_PRESSES) {
+ if (prev_response != response)
+ printf("Another press will be required!\n");
+ } else {
+ fprintf(stderr, "Error: unknown poll result %d\n",
+ response);
+ exit(update_error);
+ }
+ prev_response = response;
+
+ usleep(500 * 1000); /* Poll every half a second. */
+ }
+}
+
static void process_bid(struct transfer_descriptor *td,
enum board_id_action bid_action,
struct board_id *bid)
@@ -1760,6 +1858,9 @@ int main(int argc, char *argv[])
struct board_id bid;
enum board_id_action bid_action;
int password = 0;
+ int ccd_open = 0;
+ int ccd_unlock = 0;
+ int ccd_lock = 0;
int try_all_transfer = 0;
const char *exclusive_opt_error =
"Options -a, -s and -t are mutually exclusive\n";
@@ -1821,6 +1922,18 @@ int main(int argc, char *argv[])
errorcnt++;
}
break;
+ case 'k':
+ ccd_lock = 1;
+ break;
+ case 'o':
+ ccd_open = 1;
+ break;
+ case 'p':
+ td.post_reset = 1;
+ break;
+ case 'P':
+ password = 1;
+ break;
case 'r':
rma = 1;
@@ -1846,11 +1959,8 @@ int main(int argc, char *argv[])
}
td.ep_type = ts_xfer;
break;
- case 'p':
- td.post_reset = 1;
- break;
- case 'P':
- password = 1;
+ case 'U':
+ ccd_unlock = 1;
break;
case 'u':
td.upstart_mode = 1;
@@ -1881,11 +1991,14 @@ int main(int argc, char *argv[])
if (errorcnt)
usage(errorcnt);
- if (!show_fw_ver &&
+ if ((bid_action == bid_none) &&
+ !ccd_lock &&
+ !ccd_open &&
+ !ccd_unlock &&
!corrupt_inactive_rw &&
- (bid_action == bid_none) &&
+ !password &&
!rma &&
- !password) {
+ !show_fw_ver) {
if (optind >= argc) {
fprintf(stderr,
"\nERROR: Missing required <binary image>\n\n");
@@ -1910,6 +2023,13 @@ int main(int argc, char *argv[])
printf("Ignoring binary image %s\n", argv[optind]);
}
+ if (((bid_action != bid_none) + !!rma + !!password +
+ !!ccd_open + !!ccd_unlock + !!ccd_lock) > 2) {
+ fprintf(stderr, "ERROR: options -i, -k, -o, -P, -r, and -u "
+ "are mutually exclusive\n");
+ exit(update_error);
+ }
+
if (td.ep_type == usb_xfer) {
usb_findit(vid, pid, &td.uep);
} else if (td.ep_type == dev_xfer) {
@@ -1923,6 +2043,9 @@ int main(int argc, char *argv[])
}
}
+ if (ccd_unlock || ccd_open || ccd_lock)
+ process_ccd_state(&td, ccd_unlock, ccd_open, ccd_lock);
+
if (password)
process_password(&td);