summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--common/flash_common.c9
-rw-r--r--common/vboot_hash.c50
-rw-r--r--include/vboot_hash.h23
3 files changed, 74 insertions, 8 deletions
diff --git a/common/flash_common.c b/common/flash_common.c
index 6afa4adc6e..11cb8150f3 100644
--- a/common/flash_common.c
+++ b/common/flash_common.c
@@ -13,6 +13,7 @@
#include "shared_mem.h"
#include "system.h"
#include "util.h"
+#include "vboot_hash.h"
int flash_dataptr(int offset, int size_req, int align, char **ptrp)
{
@@ -48,6 +49,10 @@ int flash_write(int offset, int size, const char *data)
if (flash_dataptr(offset, size, CONFIG_FLASH_WRITE_SIZE, NULL) < 0)
return EC_ERROR_INVAL; /* Invalid range */
+#ifdef CONFIG_TASK_VBOOTHASH
+ vboot_hash_invalidate(offset, size);
+#endif
+
return flash_physical_write(offset, size, data);
}
@@ -56,6 +61,10 @@ int flash_erase(int offset, int size)
if (flash_dataptr(offset, size, CONFIG_FLASH_ERASE_SIZE, NULL) < 0)
return EC_ERROR_INVAL; /* Invalid range */
+#ifdef CONFIG_TASK_VBOOTHASH
+ vboot_hash_invalidate(offset, size);
+#endif
+
return flash_physical_erase(offset, size);
}
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;
diff --git a/include/vboot_hash.h b/include/vboot_hash.h
new file mode 100644
index 0000000000..002282b346
--- /dev/null
+++ b/include/vboot_hash.h
@@ -0,0 +1,23 @@
+/* Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+/* Verified boot hashing memory module for Chrome EC */
+
+#ifndef __CROS_EC_VBOOT_HASH_H
+#define __CROS_EC_VBOOT_HASH_H
+
+#include "common.h"
+
+/**
+ * Invalidate the hash if the hashed data overlaps the specified region.
+ *
+ * @param offset Region start offset in flash
+ * @param size Size of region in bytes
+ *
+ * @return non-zero if the region overlapped the hashed region.
+ */
+int vboot_hash_invalidate(int offset, int size);
+
+#endif /* __CROS_EC_VBOOT_HASH_H */