summaryrefslogtreecommitdiff
path: root/common/vboot_hash.c
diff options
context:
space:
mode:
Diffstat (limited to 'common/vboot_hash.c')
-rw-r--r--common/vboot_hash.c50
1 files changed, 42 insertions, 8 deletions
diff --git a/common/vboot_hash.c b/common/vboot_hash.c
index 8174455fa5..68b9876522 100644
--- a/common/vboot_hash.c
+++ b/common/vboot_hash.c
@@ -80,11 +80,17 @@ static int vboot_hash_start(uint32_t offset, uint32_t size,
return EC_SUCCESS;
}
-/* Abort hash currently in progress, if any. */
+/* Abort hash currently in progress, and invalidate any completed hash. */
static void vboot_hash_abort(void)
{
- if (in_progress)
+ if (in_progress) {
want_abort = 1;
+ } else {
+ CPRINTF("[%T hash abort]\n");
+ want_abort = 0;
+ data_size = 0;
+ hash = NULL;
+ }
}
static void vboot_hash_init(void)
@@ -112,6 +118,26 @@ static void vboot_hash_init(void)
}
}
+int vboot_hash_invalidate(int offset, int size)
+{
+ /* Don't invalidate if passed an invalid region */
+ if (offset < 0 || size <= 0 || offset + size < 0)
+ return 0;
+
+ /* Don't invalidate if hash is already invalid */
+ if (!hash)
+ return 0;
+
+ /* No overlap if passed region is off either end of hashed region */
+ if (offset + size <= data_offset || offset >= data_offset + data_size)
+ return 0;
+
+ /* Invalidate the hash */
+ CPRINTF("[%T hash invalidated 0x%08x 0x%08x]\n", offset, size);
+ vboot_hash_abort();
+ return 1;
+}
+
void vboot_hash_task(void)
{
vboot_hash_init();
@@ -122,10 +148,8 @@ void vboot_hash_task(void)
task_wait_event(-1);
} else if (want_abort) {
/* Abort hash computation currently in progress */
- CPRINTF("[%T hash abort]\n");
- data_size = 0;
- want_abort = 0;
in_progress = 0;
+ vboot_hash_abort();
} else {
/* Compute the next chunk of hash */
int size = MIN(CHUNK_SIZE, data_size - curr_pos);
@@ -136,10 +160,16 @@ void vboot_hash_task(void)
size);
curr_pos += size;
if (curr_pos >= data_size) {
+ /* Store the final hash */
hash = SHA256_final(&ctx);
CPRINTF("[%T hash done %.*h]\n",
SHA256_DIGEST_SIZE, hash);
+
in_progress = 0;
+
+ /* Handle receiving abort during finalize */
+ if (want_abort)
+ vboot_hash_abort();
}
/*
@@ -189,10 +219,14 @@ static int command_hash(int argc, char **argv)
ccprintf("Offset: 0x%08x\n", data_offset);
ccprintf("Size: 0x%08x (%d)\n", data_size, data_size);
ccprintf("Digest: ");
- if (in_progress)
+ if (want_abort)
+ ccprintf("(aborting)\n");
+ else if (in_progress)
ccprintf("(in progress)\n");
- else
+ else if (hash)
ccprintf("%.*h\n", SHA256_DIGEST_SIZE, hash);
+ else
+ ccprintf("(invalid)\n");
return EC_SUCCESS;
}
@@ -248,7 +282,7 @@ static void fill_response(struct ec_response_vboot_hash *r)
{
if (in_progress)
r->status = EC_VBOOT_HASH_STATUS_BUSY;
- else if (hash) {
+ else if (hash && !want_abort) {
r->status = EC_VBOOT_HASH_STATUS_DONE;
r->hash_type = EC_VBOOT_HASH_TYPE_SHA256;
r->digest_size = SHA256_DIGEST_SIZE;