diff options
author | Randall Spangler <rspangler@chromium.org> | 2012-09-12 13:48:07 -0700 |
---|---|---|
committer | Gerrit <chrome-bot@google.com> | 2012-09-12 15:42:25 -0700 |
commit | 88ff608ae261ceca193e7d5689dc67b1536ce3eb (patch) | |
tree | 11245c8dcbaf87f526e071a44ba50e2122412293 | |
parent | 0ac4bc36537ce3ee98a3ce3068a79919cd9804d3 (diff) | |
download | chrome-ec-88ff608ae261ceca193e7d5689dc67b1536ce3eb.tar.gz |
Add capability to auto-hash correct size for EC-RO or EC-RW
Otherwise the host needs to tell the EC how big this image is (which
it knows, but it's inconvenient for it to provide).
BUG=chrome-os-partner:13511
BRANCH=all
TEST=manual
1. ectool echash recalc ro -> prints hash of RO code (offset 0)
2. ectool echash recalc rw -> prints hash of RW code (offset non-zero)
In each case, size should be an exact number and not the size of the
whole RO or RW section. So for link, output should be something similar to:
localhost ~ # ectool echash recalc ro
Hashing EC-RO...
status: done
type: SHA-256
offset: 0x00000000
size: 0x00012a64
hash: 03a66c076d6dd4b4aa9ed6386713f45291f5143f9af2093003e632485899daf1
localhost ~ # ectool echash recalc rw
Hashing EC-RW...
status: done
type: SHA-256
offset: 0x00014000
size: 0x000123d1
hash: 0d6225e70f0b1e0419e987370371e00783f945827ef25915a8fb8549159dd2a4
Signed-off-by: Randall Spangler <rspangler@chromium.org>
3. At ec console, 'hash ro' or 'hash rw' should regenerate the same
hash values printed above.
Change-Id: I3f6085d29927b8cdf9dabc6930f0fdc7222bd8b5
Reviewed-on: https://gerrit.chromium.org/gerrit/33123
Tested-by: Randall Spangler <rspangler@chromium.org>
Reviewed-by: Simon Glass <sjg@chromium.org>
Commit-Ready: Randall Spangler <rspangler@chromium.org>
-rw-r--r-- | common/vboot_hash.c | 85 | ||||
-rw-r--r-- | include/ec_commands.h | 24 | ||||
-rw-r--r-- | util/ectool.c | 42 |
3 files changed, 102 insertions, 49 deletions
diff --git a/common/vboot_hash.c b/common/vboot_hash.c index 535f7f81c0..c80c174588 100644 --- a/common/vboot_hash.c +++ b/common/vboot_hash.c @@ -193,9 +193,21 @@ static int command_hash(int argc, char **argv) return EC_SUCCESS; } - if (argc == 2 && !strcasecmp(argv[1], "abort")) { - vboot_hash_abort(); - return EC_SUCCESS; + if (argc == 2) { + if (!strcasecmp(argv[1], "abort")) { + vboot_hash_abort(); + return EC_SUCCESS; + } else if (!strcasecmp(argv[1], "rw")) { + return vboot_hash_start( + CONFIG_FW_RW_OFF, + system_get_image_used(SYSTEM_IMAGE_RW), + NULL, 0); + } else if (!strcasecmp(argv[1], "ro")) { + return vboot_hash_start( + CONFIG_FW_RO_OFF, + system_get_image_used(SYSTEM_IMAGE_RO), + NULL, 0); + } } if (argc >= 3) { @@ -220,7 +232,7 @@ static int command_hash(int argc, char **argv) return vboot_hash_start(offset, size, NULL, 0); } DECLARE_CONSOLE_COMMAND(hash, command_hash, - "[abort] | [<offset> <size> [<nonce>]]", + "[abort | ro | rw] | [<offset> <size> [<nonce>]]", "Request hash recomputation", NULL); @@ -245,6 +257,42 @@ static void fill_response(struct ec_response_vboot_hash *r) r->status = EC_VBOOT_HASH_STATUS_NONE; } +/** + * Start computing a hash, with sanity checking on params. + * + * @return EC_RES_SUCCESS if success, or other result code on error. + */ +static int host_start_hash(const struct ec_params_vboot_hash *p) +{ + int offset = p->offset; + int size = p->size; + int rv; + + /* Sanity-check input params */ + if (p->hash_type != EC_VBOOT_HASH_TYPE_SHA256) + return EC_RES_INVALID_PARAM; + if (p->nonce_size > sizeof(p->nonce_data)) + return EC_RES_INVALID_PARAM; + + /* Handle special offset values */ + if (offset == EC_VBOOT_HASH_OFFSET_RO) { + offset = CONFIG_FW_RO_OFF; + size = system_get_image_used(SYSTEM_IMAGE_RO); + } else if (p->offset == EC_VBOOT_HASH_OFFSET_RW) { + offset = CONFIG_FW_RW_OFF; + size = system_get_image_used(SYSTEM_IMAGE_RW); + } + + rv = vboot_hash_start(offset, size, p->nonce_data, p->nonce_size); + + if (rv == EC_SUCCESS) + return EC_RES_SUCCESS; + else if (rv == EC_ERROR_INVAL) + return EC_RES_INVALID_PARAM; + else + return EC_RES_ERROR; +} + static int host_command_vboot_hash(struct host_cmd_handler_args *args) { const struct ec_params_vboot_hash *p = args->params; @@ -262,33 +310,12 @@ static int host_command_vboot_hash(struct host_cmd_handler_args *args) return EC_RES_SUCCESS; case EC_VBOOT_HASH_START: - if (p->hash_type != EC_VBOOT_HASH_TYPE_SHA256) - return EC_RES_INVALID_PARAM; - if (p->nonce_size > sizeof(p->nonce_data)) - return EC_RES_INVALID_PARAM; - - rv = vboot_hash_start(p->offset, p->size, p->nonce_data, - p->nonce_size); - - if (rv == EC_SUCCESS) - return EC_RES_SUCCESS; - else if (rv == EC_ERROR_INVAL) - return EC_RES_INVALID_PARAM; - else - return EC_RES_ERROR; + return host_start_hash(p); case EC_VBOOT_HASH_RECALC: - if (p->hash_type != EC_VBOOT_HASH_TYPE_SHA256) - return EC_RES_INVALID_PARAM; - if (p->nonce_size > sizeof(p->nonce_data)) - return EC_RES_INVALID_PARAM; - - rv = vboot_hash_start(p->offset, p->size, p->nonce_data, - p->nonce_size); - if (rv == EC_ERROR_INVAL) - return EC_RES_INVALID_PARAM; - else if (rv != EC_SUCCESS) - return EC_RES_ERROR; + rv = host_start_hash(p); + if (rv != EC_RES_SUCCESS) + return rv; /* Wait for hash to finish */ while (in_progress) diff --git a/include/ec_commands.h b/include/ec_commands.h index 4e3bd7082f..296b0d7ea9 100644 --- a/include/ec_commands.h +++ b/include/ec_commands.h @@ -712,22 +712,30 @@ struct ec_response_vboot_hash { } __packed; enum ec_vboot_hash_cmd { - EC_VBOOT_HASH_GET, /* Get current hash status */ - EC_VBOOT_HASH_ABORT, /* Abort calculating current hash */ - EC_VBOOT_HASH_START, /* Start computing a new hash */ - EC_VBOOT_HASH_RECALC, /* Synchronously compute a new hash */ + EC_VBOOT_HASH_GET = 0, /* Get current hash status */ + EC_VBOOT_HASH_ABORT = 1, /* Abort calculating current hash */ + EC_VBOOT_HASH_START = 2, /* Start computing a new hash */ + EC_VBOOT_HASH_RECALC = 3, /* Synchronously compute a new hash */ }; enum ec_vboot_hash_type { - EC_VBOOT_HASH_TYPE_SHA256, /* SHA-256 */ + EC_VBOOT_HASH_TYPE_SHA256 = 0, /* SHA-256 */ }; enum ec_vboot_hash_status { - EC_VBOOT_HASH_STATUS_NONE, /* No hash (not started, or aborted) */ - EC_VBOOT_HASH_STATUS_DONE, /* Finished computing a hash */ - EC_VBOOT_HASH_STATUS_BUSY, /* Busy computing a hash */ + EC_VBOOT_HASH_STATUS_NONE = 0, /* No hash (not started, or aborted) */ + EC_VBOOT_HASH_STATUS_DONE = 1, /* Finished computing a hash */ + EC_VBOOT_HASH_STATUS_BUSY = 2, /* Busy computing a hash */ }; +/* + * Special values for offset for EC_VBOOT_HASH_START and EC_VBOOT_HASH_RECALC. + * If one of these is specified, the EC will automatically update offset and + * size to the correct values for the specified image (RO or RW). + */ +#define EC_VBOOT_HASH_OFFSET_RO 0xfffffffe +#define EC_VBOOT_HASH_OFFSET_RW 0xfffffffd + /*****************************************************************************/ /* USB charging control commands */ diff --git a/util/ectool.c b/util/ectool.c index 90b0d558ee..4fbc6ce781 100644 --- a/util/ectool.c +++ b/util/ectool.c @@ -1990,6 +1990,10 @@ static int ec_hash_help(const char *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); + printf("\n" + "If <offset> is RO or RW, offset and size are computed\n" + "automatically for the EC-RO or EC-RW firmware image.\n"); + return 0; } @@ -2060,21 +2064,36 @@ int cmd_ec_hash(int argc, char *argv[]) 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"); + + if (argc < 3) { + fprintf(stderr, "Must specify offset\n"); return -1; } - p.size = strtol(argv[3], &e, 0); - if (e && *e) { - fprintf(stderr, "Bad size.\n"); + + if (!strcasecmp(argv[2], "ro")) { + p.offset = EC_VBOOT_HASH_OFFSET_RO; + p.size = 0; + printf("Hashing EC-RO...\n"); + } else if (!strcasecmp(argv[2], "rw")) { + p.offset = EC_VBOOT_HASH_OFFSET_RW; + p.size = 0; + printf("Hashing EC-RW...\n"); + } else if (argc < 4) { + fprintf(stderr, "Must specify size\n"); return -1; + } else { + 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; + } + printf("Hashing %d bytes at offset %d...\n", p.size, p.offset); } if (argc == 5) { @@ -2092,7 +2111,6 @@ int cmd_ec_hash(int argc, char *argv[]) } else p.nonce_size = 0; - printf("Hashing %d bytes at offset %d...\n", p.size, p.offset); rv = ec_command(EC_CMD_VBOOT_HASH, 0, &p, sizeof(p), &r, sizeof(r)); if (rv < 0) return rv; |