diff options
Diffstat (limited to 'common/vboot_hash.c')
-rw-r--r-- | common/vboot_hash.c | 50 |
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; |