diff options
Diffstat (limited to 'common/vboot_hash.c')
-rw-r--r-- | common/vboot_hash.c | 89 |
1 files changed, 69 insertions, 20 deletions
diff --git a/common/vboot_hash.c b/common/vboot_hash.c index 0642e09e3c..0387040670 100644 --- a/common/vboot_hash.c +++ b/common/vboot_hash.c @@ -13,6 +13,7 @@ #include "host_command.h" #include "sha256.h" #include "shared_mem.h" +#include "stdbool.h" #include "system.h" #include "task.h" #include "timer.h" @@ -44,6 +45,8 @@ static uint32_t curr_pos; static const uint8_t *hash; /* Hash, or NULL if not valid */ static int want_abort; static int in_progress; +#define VBOOT_HASH_DEFERRED true +#define VBOOT_HASH_BLOCKING false static struct sha256_ctx ctx; @@ -109,6 +112,35 @@ static int read_and_hash_chunk(int offset, int size) #define SHA256_PRINT_SIZE 4 #endif +static void hash_next_chunk(size_t size) +{ +#ifdef CONFIG_MAPPED_STORAGE + flash_lock_mapped_storage(1); + SHA256_update(&ctx, (const uint8_t *)(CONFIG_MAPPED_STORAGE_BASE + + data_offset + curr_pos), size); + flash_lock_mapped_storage(0); +#else + if (read_and_hash_chunk(data_offset + curr_pos, size) != EC_SUCCESS) + return; +#endif +} + +static void vboot_hash_all_chunks(void) +{ + do { + size_t size = MIN(CHUNK_SIZE, data_size - curr_pos); + hash_next_chunk(size); + curr_pos += size; + } while (curr_pos < data_size); + + hash = SHA256_final(&ctx); + CPRINTS("hash done %ph", HEX_BUF(hash, SHA256_PRINT_SIZE)); + in_progress = 0; + clock_enable_module(MODULE_FAST_CPU, 0); + + return; +} + /** * Do next chunk of hashing work, if any. */ @@ -126,16 +158,7 @@ static void vboot_hash_next_chunk(void) /* Compute the next chunk of hash */ size = MIN(CHUNK_SIZE, data_size - curr_pos); - -#ifdef CONFIG_MAPPED_STORAGE - flash_lock_mapped_storage(1); - SHA256_update(&ctx, (const uint8_t *)(CONFIG_MAPPED_STORAGE_BASE + - data_offset + curr_pos), size); - flash_lock_mapped_storage(0); -#else - if (read_and_hash_chunk(data_offset + curr_pos, size) != EC_SUCCESS) - return; -#endif + hash_next_chunk(size); curr_pos += size; if (curr_pos >= data_size) { @@ -159,13 +182,23 @@ static void vboot_hash_next_chunk(void) } /** - * Start computing a hash of <size> bytes of data at flash offset <offset>. * * If nonce_size is non-zero, prefixes the <nonce> onto the data to be hashed. * Returns non-zero if error. */ +/** + * Start computing a hash of <size> bytes of data at flash offset <offset>. + * + * @param offset start address of data on flash to compute hash for. + * @param size size of data to compute hash for. + * @param nonce nonce to differentiate hash. + * @param nonce_size size of nonce. + * @param deferred True to hash progressively through deferred calls. + * False to hash with a blocking single call. + * @return ec_error_list. + */ static int vboot_hash_start(uint32_t offset, uint32_t size, - const uint8_t *nonce, int nonce_size) + const uint8_t *nonce, int nonce_size, bool deferred) { /* Fail if hash computation is already in progress */ if (in_progress) @@ -195,7 +228,10 @@ static int vboot_hash_start(uint32_t offset, uint32_t size, if (nonce_size) SHA256_update(&ctx, nonce, nonce_size); - hook_call_deferred(&vboot_hash_next_chunk_data, 0); + if (deferred) + hook_call_deferred(&vboot_hash_next_chunk_data, 0); + else + vboot_hash_all_chunks(); return EC_SUCCESS; } @@ -232,7 +268,9 @@ int vboot_hash_invalidate(int offset, int size) */ static uint32_t get_rw_size(void) { -#ifdef CONFIG_VBOOT_EFS +#ifdef CONFIG_VBOOT_EFS /* Only needed for EFS, which signs and verifies + * entire RW, thus not needed for EFS2, which + * verifies only the used image size. */ return CONFIG_RW_SIZE; #else return system_get_image_used(SYSTEM_IMAGE_RW); @@ -270,11 +308,19 @@ static void vboot_hash_init(void) { /* Start computing the hash of RW firmware */ vboot_hash_start(flash_get_rw_offset(system_get_active_copy()), - get_rw_size(), NULL, 0); + get_rw_size(), NULL, 0, VBOOT_HASH_DEFERRED); } } DECLARE_HOOK(HOOK_INIT, vboot_hash_init, HOOK_PRIO_INIT_VBOOT_HASH); +int vboot_get_rw_hash(const uint8_t **dst) +{ + int rv = vboot_hash_start(flash_get_rw_offset(system_get_active_copy()), + get_rw_size(), NULL, 0, VBOOT_HASH_BLOCKING); + *dst = hash; + return rv; +} + #ifdef CONFIG_SAVE_VBOOT_HASH static int vboot_hash_preserve_state(void) @@ -345,13 +391,14 @@ static int command_hash(int argc, char **argv) } else if (!strcasecmp(argv[1], "rw")) { return vboot_hash_start( get_offset(EC_VBOOT_HASH_OFFSET_ACTIVE), - get_rw_size(), NULL, 0); + get_rw_size(), + NULL, 0, VBOOT_HASH_DEFERRED); } else if (!strcasecmp(argv[1], "ro")) { return vboot_hash_start( CONFIG_EC_PROTECTED_STORAGE_OFF + CONFIG_RO_STORAGE_OFF, system_get_image_used(SYSTEM_IMAGE_RO), - NULL, 0); + NULL, 0, VBOOT_HASH_DEFERRED); } return EC_ERROR_PARAM2; } @@ -373,9 +420,10 @@ static int command_hash(int argc, char **argv) return vboot_hash_start(offset, size, (const uint8_t *)&nonce, - sizeof(nonce)); + sizeof(nonce), VBOOT_HASH_DEFERRED); } else - return vboot_hash_start(offset, size, NULL, 0); + return vboot_hash_start(offset, size, + NULL, 0, VBOOT_HASH_DEFERRED); } DECLARE_CONSOLE_COMMAND(hash, command_hash, "[abort | ro | rw] | [<offset> <size> [<nonce>]]", @@ -428,7 +476,8 @@ static int host_start_hash(const struct ec_params_vboot_hash *p) (offset == EC_VBOOT_HASH_OFFSET_UPDATE)) size = get_rw_size(); offset = get_offset(offset); - rv = vboot_hash_start(offset, size, p->nonce_data, p->nonce_size); + rv = vboot_hash_start(offset, size, p->nonce_data, p->nonce_size, + VBOOT_HASH_DEFERRED); if (rv == EC_SUCCESS) return EC_RES_SUCCESS; |