summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVadim Bendebury <vbendeb@chromium.org>2017-06-01 22:07:04 -0700
committerChromeOS Commit Bot <chromeos-commit-bot@chromium.org>2018-03-13 23:50:20 +0000
commit4c3282fe24b10423d28b80682dd1be22e1d881d0 (patch)
tree6d84a5164cc4538e322009e8e8d66857626e1f66
parent0215f0cf8513f7294d02da35b9d3134d10b9dcdd (diff)
downloadchrome-ec-4c3282fe24b10423d28b80682dd1be22e1d881d0.tar.gz
Cr50: usb_updater: add commands to get/set board id
This patch enhances the Cr50 usb_updater to allow to get and set Board ID value saved in the Cr50's INFO1 space using the earlier introduced dedicated vendor commands. Getting or Setting the board ID does not require establishing a connection with the Cr50, the new option is --board_id/-i. When specified without a parameter, the new option will cause the Board ID to be read. When specified with a parameter, the board ID value will be set. The parameter includes one or two values in a single string, the values separated by a colon. The first value is a 4 byte board ID, and the second value is the flags field. The default flags field is set to 0xff00. BRANCH=cr50 BUG=b:35587387,b:35587053 TEST=verified that it is possible to get and set the board ID value using usb_updater, both over USB and TPM. verified that it is not possible to set a new board ID value is the INFO1 space has been already programmed. verified that it is not possible to set a board ID value which would not allow the currently running image to start (even though there is no run time check yet). Original Change-Id: Ief175d8b2ef3177db13fa86f831914088d9447b0 Original Signed-off-by: Vadim Bendebury <vbendeb@chromium.org> Original Reviewed-on: https://chromium-review.googlesource.com/525096 Original Reviewed-by: Aseda Aboagye <aaboagye@chromium.org> Change-Id: I7bf66fe6c3ad3515d82444ba1ab956aca866acda Reviewed-on: https://chromium-review.googlesource.com/958717 Reviewed-by: Vadim Bendebury <vbendeb@chromium.org> Tested-by: Vadim Bendebury <vbendeb@chromium.org> Tested-by: Marco Chen <marcochen@chromium.org> Commit-Queue: Marco Chen <marcochen@chromium.org>
-rw-r--r--extra/usb_updater/usb_updater.c134
1 files changed, 131 insertions, 3 deletions
diff --git a/extra/usb_updater/usb_updater.c b/extra/usb_updater/usb_updater.c
index 340fc791be..1758bfab28 100644
--- a/extra/usb_updater/usb_updater.c
+++ b/extra/usb_updater/usb_updater.c
@@ -230,7 +230,7 @@ struct transfer_descriptor {
static uint32_t protocol_version;
static char *progname;
-static char *short_opts = "bcd:fhpsu";
+static char *short_opts = "bcd:fhipsu";
static const struct option long_opts[] = {
/* name hasarg *flag val */
{"binvers", 0, NULL, 'b'},
@@ -239,6 +239,7 @@ static const struct option long_opts[] = {
{"fwver", 0, NULL, 'f'},
{"help", 0, NULL, 'h'},
{"post_reset", 0, NULL, 'p'},
+ {"board_id", 2, NULL, 'i'},
{"systemdev", 0, NULL, 's'},
{"upstart", 0, NULL, 'u'},
{},
@@ -364,6 +365,8 @@ static void usage(int errs)
" -d,--device VID:PID USB device (default %04x:%04x)\n"
" -f,--fwver Report running firmware versions.\n"
" -h,--help Show this message\n"
+ " -i,--board_id [ID[:FLAGS]]\n"
+ " Get or set Info1 board ID fields\n"
" -p,--post_reset Request post reset after transfer\n"
" -s,--systemdev Use /dev/tpm0 (-d is ignored)\n"
" -u,--upstart "
@@ -1238,6 +1241,112 @@ static int show_headers_versions(const void *image)
return 0;
}
+struct board_id {
+ uint32_t type; /* Board type */
+ uint32_t type_inv; /* Board type (inverted) */
+ uint32_t flags; /* Flags */
+};
+
+enum board_id_action {
+ bid_none,
+ bid_get,
+ bid_set
+};
+
+/*
+ * The default flag value will allow to run images built for any hardware
+ * generation of a particular board ID.
+ */
+#define DEFAULT_BOARD_ID_FLAG 0xff00
+static int parse_bid(const char *opt,
+ struct board_id *bid,
+ enum board_id_action *bid_action)
+{
+ char *e;
+
+ if (!opt) {
+ *bid_action = bid_get;
+ return 1;
+ }
+
+ bid->type = (uint32_t)strtoul(opt, &e, 0);
+ *bid_action = bid_set; /* Ignored by caller on errors. */
+
+ if (!e || !*e) {
+ bid->flags = DEFAULT_BOARD_ID_FLAG;
+ return 1;
+ }
+
+ if (*e == ':') {
+ bid->flags = (uint32_t)strtoul(e + 1, &e, 0);
+ if (!e || !*e)
+ return 1;
+ }
+
+ return 0;
+}
+
+static void process_bid(struct transfer_descriptor *td,
+ enum board_id_action bid_action,
+ struct board_id *bid)
+{
+ size_t response_size;
+
+ if (bid_action == bid_get) {
+ struct board_id bid;
+
+ response_size = sizeof(bid);
+ send_vendor_command(td, VENDOR_CC_GET_BOARD_ID,
+ &bid, sizeof(bid),
+ &bid, &response_size);
+
+ if (response_size == sizeof(bid)) {
+ printf("Board ID space: %08x:%08x:%08x\n",
+ be32toh(bid.type), be32toh(bid.type_inv),
+ be32toh(bid.flags));
+ return;
+
+ }
+ fprintf(stderr, "Error reading board ID: response size %zd,"
+ " first byte %#02x\n", response_size,
+ response_size ? *(uint8_t *)&bid : -1);
+ exit(update_error);
+ }
+
+ if (bid_action == bid_set) {
+ /* Sending just two fields: type and flags. */
+ uint32_t command_body[2];
+ uint8_t response;
+
+ command_body[0] = htobe32(bid->type);
+ command_body[1] = htobe32(bid->flags);
+
+ response_size = sizeof(command_body);
+ send_vendor_command(td, VENDOR_CC_SET_BOARD_ID,
+ command_body, sizeof(command_body),
+ command_body, &response_size);
+
+ /*
+ * Speculative assignment: the response is expected to be one
+ * byte in size and be placed in the first byte of the buffer.
+ */
+ response = *((uint8_t *)command_body);
+
+ if (response_size == 1) {
+ if (!response)
+ return; /* Success! */
+
+ fprintf(stderr, "Error %d while setting board id\n",
+ response);
+ } else {
+ fprintf(stderr, "Unexpected response size %zd"
+ " while setting board id\n",
+ response_size);
+ }
+ exit(update_error);
+ }
+}
+
int main(int argc, char *argv[])
{
struct transfer_descriptor td;
@@ -1251,6 +1360,8 @@ int main(int argc, char *argv[])
int binary_vers = 0;
int show_fw_ver = 0;
int corrupt_inactive_rw = 0;
+ struct board_id bid;
+ enum board_id_action bid_action;
progname = strrchr(argv[0], '/');
if (progname)
@@ -1262,6 +1373,7 @@ int main(int argc, char *argv[])
memset(&td, 0, sizeof(td));
td.ep_type = usb_xfer;
+ bid_action = bid_none;
errorcnt = 0;
opterr = 0; /* quiet, you */
while ((i = getopt_long(argc, argv, short_opts, long_opts, 0)) != -1) {
@@ -1271,7 +1383,8 @@ int main(int argc, char *argv[])
break;
case 'd':
if (!parse_vidpid(optarg, &vid, &pid)) {
- printf("Invalid argument: \"%s\"\n", optarg);
+ printf("Invalid device argument: \"%s\"\n",
+ optarg);
errorcnt++;
}
break;
@@ -1284,6 +1397,18 @@ int main(int argc, char *argv[])
case 'h':
usage(errorcnt);
break;
+ case 'i':
+ if (!optarg && argv[optind] && argv[optind][0] != '-') {
+ /* optional argument present. */
+ optarg = argv[optind];
+ optind++;
+ }
+ if (!parse_bid(optarg, &bid, &bid_action)) {
+ printf("Invalid board id argument: \"%s\"\n",
+ optarg);
+ errorcnt++;
+ }
+ break;
case 's':
td.ep_type = dev_xfer;
break;
@@ -1316,7 +1441,7 @@ int main(int argc, char *argv[])
if (errorcnt)
usage(errorcnt);
- if (!show_fw_ver && !corrupt_inactive_rw) {
+ if (!show_fw_ver && !corrupt_inactive_rw && (bid_action == bid_none)) {
if (optind >= argc) {
fprintf(stderr,
"\nERROR: Missing required <binary image>\n\n");
@@ -1351,6 +1476,9 @@ int main(int argc, char *argv[])
}
}
+ if (bid_action != bid_none)
+ process_bid(&td, bid_action, &bid);
+
if (corrupt_inactive_rw)
invalidate_inactive_rw(&td);