summaryrefslogtreecommitdiff
path: root/util/ectool.c
diff options
context:
space:
mode:
authorRandall Spangler <rspangler@chromium.org>2012-06-22 12:56:56 -0700
committerGerrit <chrome-bot@google.com>2012-06-25 15:37:42 -0700
commit900c0215b4f47551c850259ef7c716285c46e8b5 (patch)
treed467eb3c50b9a3def174db18b7dc6dcfb110ab43 /util/ectool.c
parentaab92d552d7274f00e624bc8bc74ec41d3101b6d (diff)
downloadchrome-ec-900c0215b4f47551c850259ef7c716285c46e8b5.tar.gz
Add hash support
EC computes a SHA-256 hash of its RW code on boot. Also adds host and console commands to tell the EC to recompute the hash, or hash a different section of flash memory. BUG=chrome-os-partner:10777 TEST=manual 1) ectool echash -> should match what the EC precomputed 2a) ectool echash recalc 0 0x10000 5 2b) on EC console, 'hash 0 0x10000 5' 2c) results should agree 3a) on ec console, 'hash 0 0x3e000' then quickly 'hash abort' 3b) ectool echash -> status should be unavailable 4) ectool echash start 0 0x3e000 6 && ectool echash && ectool echash abort && sleep 2 && ectool echash status should be busy, then unavailable Signed-off-by: Randall Spangler <rspangler@chromium.org> Change-Id: I6806d7b4d4dca3a74f476092551b4dba875d558e Reviewed-on: https://gerrit.chromium.org/gerrit/26023
Diffstat (limited to 'util/ectool.c')
-rw-r--r--util/ectool.c123
1 files changed, 123 insertions, 0 deletions
diff --git a/util/ectool.c b/util/ectool.c
index f608d952cb..4fb953b1fe 100644
--- a/util/ectool.c
+++ b/util/ectool.c
@@ -36,6 +36,8 @@ const char help_str[] =
" Prints battery info\n"
" chipinfo\n"
" Prints chip info\n"
+ " echash [CMDS]\n"
+ " Various EC hash commands\n"
" eventclear <mask>\n"
" Clears EC host events flags where mask has bits set\n"
" eventget\n"
@@ -1565,6 +1567,126 @@ int cmd_chipinfo(int argc, char *argv[])
return 0;
}
+
+static int ec_hash_help(const char *cmd)
+{
+ printf("Usage:\n");
+ printf(" %s - get last hash\n", cmd);
+ printf(" %s abort - abort hashing\n", cmd);
+ printf(" %s start [<offset> <size> [<nonce>]] - start hashing\n", cmd);
+ printf(" %s recalc [<offset> <size> [<nonce>]] - sync rehash\n", cmd);
+ return 0;
+}
+
+
+static int ec_hash_print(const struct ec_response_vboot_hash *r)
+{
+ int i;
+
+ if (r->status == EC_VBOOT_HASH_STATUS_BUSY) {
+ printf("status: busy\n");
+ return 0;
+ } else if (r->status == EC_VBOOT_HASH_STATUS_NONE) {
+ printf("status: unavailable\n");
+ return 0;
+ } else if (r->status != EC_VBOOT_HASH_STATUS_DONE) {
+ printf("status: %d\n", r->status);
+ return 0;
+ }
+
+ printf("status: done\n");
+ if (r->hash_type == EC_VBOOT_HASH_TYPE_SHA256)
+ printf("type: SHA-256\n");
+ else
+ printf("type: %d\n", r->hash_type);
+
+ printf("offset: 0x%08x\n", r->offset);
+ printf("size: 0x%08x\n", r->size);
+
+ printf("hash: ");
+ for (i = 0; i < r->digest_size; i++)
+ printf("%02x", r->hash_digest[i]);
+ printf("\n");
+ return 0;
+}
+
+
+int cmd_ec_hash(int argc, char *argv[])
+{
+ struct ec_params_vboot_hash p;
+ struct ec_response_vboot_hash r;
+ char *e;
+
+ if (argc < 2) {
+ /* Get hash status */
+ p.cmd = EC_VBOOT_HASH_GET;
+ if (ec_command(EC_CMD_VBOOT_HASH, &p, sizeof(p), &r, sizeof(r)))
+ return -1;
+
+ return ec_hash_print(&r);
+ }
+
+ if (argc == 2 && !strcasecmp(argv[1], "abort")) {
+ /* Abort hash calculation */
+ p.cmd = EC_VBOOT_HASH_ABORT;
+ if (ec_command(EC_CMD_VBOOT_HASH, &p, sizeof(p), &r, sizeof(r)))
+ return -1;
+ return 0;
+ }
+
+ /* The only other commands are start and recalc */
+ if (!strcasecmp(argv[1], "start"))
+ p.cmd = EC_VBOOT_HASH_START;
+ else if (!strcasecmp(argv[1], "recalc"))
+ p.cmd = EC_VBOOT_HASH_RECALC;
+ else
+ return ec_hash_help(argv[0]);
+
+ if (argc < 4) {
+ fprintf(stderr, "Must specify offset and size\n");
+ return -1;
+ }
+
+ p.hash_type = EC_VBOOT_HASH_TYPE_SHA256;
+ p.offset = strtol(argv[2], &e, 0);
+ if (e && *e) {
+ fprintf(stderr, "Bad offset.\n");
+ return -1;
+ }
+ p.size = strtol(argv[3], &e, 0);
+ if (e && *e) {
+ fprintf(stderr, "Bad size.\n");
+ return -1;
+ }
+
+ if (argc == 5) {
+ /*
+ * Technically nonce can be any binary data up to 64 bytes,
+ * but this command only supports a 32-bit value.
+ */
+ uint32_t nonce = strtol(argv[4], &e, 0);
+ if (e && *e) {
+ fprintf(stderr, "Bad nonce integer.\n");
+ return -1;
+ }
+ memcpy(p.nonce_data, &nonce, sizeof(nonce));
+ p.nonce_size = sizeof(nonce);
+ } else
+ p.nonce_size = 0;
+
+ printf("Hashing %d bytes at offset %d...\n", p.size, p.offset);
+ if (ec_command(EC_CMD_VBOOT_HASH, &p, sizeof(p), &r, sizeof(r)))
+ return -1;
+
+ /* Start command doesn't wait for hashing to finish */
+ if (p.cmd == EC_VBOOT_HASH_START)
+ return 0;
+
+ /* Recalc command does wait around, so a result is ready now */
+ return ec_hash_print(&r);
+}
+
+
struct command {
const char *name;
int (*handler)(int argc, char *argv[]);
@@ -1576,6 +1698,7 @@ const struct command commands[] = {
{"backlight", cmd_lcd_backlight},
{"battery", cmd_battery},
{"chipinfo", cmd_chipinfo},
+ {"echash", cmd_ec_hash},
{"eventclear", cmd_host_event_clear},
{"eventget", cmd_host_event_get_raw},
{"eventgetscimask", cmd_host_event_get_sci_mask},