From d7303404a59a296fad9085db23fa18fe97f0f5c3 Mon Sep 17 00:00:00 2001 From: Aseda Aboagye Date: Mon, 13 Feb 2017 10:57:26 -0800 Subject: cr50: Make sure TPM wipe only clears TPM data. Previously, wiping the TPM would wipe all of NvMem, however, it really should only clear the TPM's NvMem space. This commit adds a function to clear a given NvMem user's space and makes the TPM only clear its space. BUG=chrome-os-partner:61597 BRANCH=None TEST=Add code for using nvmem vars, create a test variable, add a user to snappy, unlock the console, verify that the user is no longer present on the system and the test nvmem var still exists. TEST=make -j buildall Change-Id: Ic98baa5166a1ef9ae76e910b1b9ab100300e947f Signed-off-by: Aseda Aboagye Reviewed-on: https://chromium-review.googlesource.com/445803 Commit-Ready: Aseda Aboagye Tested-by: Aseda Aboagye Reviewed-by: Vadim Bendebury --- common/nvmem.c | 27 ++++++++++++------- common/tpm_registers.c | 4 +-- include/nvmem.h | 11 ++++---- test/nvmem.c | 72 ++++++++++++++++++++++++++++++++------------------ 4 files changed, 70 insertions(+), 44 deletions(-) diff --git a/common/nvmem.c b/common/nvmem.c index 7ffde9d977..cb4abc3287 100644 --- a/common/nvmem.c +++ b/common/nvmem.c @@ -358,34 +358,41 @@ static int nvmem_get_partition_off(int user, uint32_t offset, return EC_SUCCESS; } -int nvmem_setup(void) +int nvmem_erase_user_data(enum nvmem_users user) { int part; int ret; + uint32_t user_offset, user_size; - CPRINTS("Configuring NVMEM Flash Partition"); + if (user >= NVMEM_NUM_USERS) + return EC_ERROR_INVAL; - part = nvmem_act_partition; - nvmem_act_partition = 0; + CPRINTS("Erasing NVMEM Flash Partition user: %d", user); ret = EC_SUCCESS; + /* Find offset within cache. */ + user_offset = nvmem_user_start_offset[user]; + user_size = nvmem_user_sizes[user]; + for (part = 0; part < NVMEM_NUM_PARTITIONS; part++) { int rv; - memset(nvmem_cache, 0xff, NVMEM_PARTITION_SIZE); + /* Lock the cache buffer. */ + nvmem_lock_cache(); + /* Erase the user's data. */ + memset(nvmem_cache + user_offset, 0xFF, user_size); + /* * Make sure the contents change between runs of - * nvmem_save() so that both flash partitions are + * nvmem_save() so that all flash partitions are * written with empty contents and different * generation numbers. */ ((struct nvmem_partition *)nvmem_cache)->tag.generation = part; - /* Lock the cache buffer (unlocked by nvmem_save() */ - nvmem_lock_cache(); - rv = nvmem_save(); - /* Even if one partition saving failed, let's keep going. */ + /* Make a best effort to clear each partition. */ + rv = nvmem_save(); if (rv != EC_SUCCESS) ret = rv; } diff --git a/common/tpm_registers.c b/common/tpm_registers.c index c2728522ae..cac79c725d 100644 --- a/common/tpm_registers.c +++ b/common/tpm_registers.c @@ -727,8 +727,8 @@ static void tpm_reset_now(int wipe_first) cprints(CC_TASK, "%s: force EC off", __func__); assert_ec_rst(); - /* Now wipe nvmem */ - wipe_result = nvmem_setup(); + /* Now wipe the TPM's nvmem */ + wipe_result = nvmem_erase_user_data(NVMEM_TPM); } else { wipe_result = EC_SUCCESS; } diff --git a/include/nvmem.h b/include/nvmem.h index 87de8b9cae..e9fae3d11d 100644 --- a/include/nvmem.h +++ b/include/nvmem.h @@ -174,14 +174,13 @@ int nvmem_move(uint32_t src_offset, uint32_t dest_offset, uint32_t size, int nvmem_commit(void); /* - * Reinitialzse all NvMem partitions + * Clear out a user's data across all partitions. * - * This function should be called when NvMem needs to be wiped out. - * - * @return EC_SUCCESS if flash operations are successful. - * EC_ERROR_UNKNOWN otherwise. + * @param user: The user who's data should be cleared. + * @return EC_SUCCESS if the user's data across all partitions was + * cleared. Error othrwise. */ -int nvmem_setup(void); +int nvmem_erase_user_data(enum nvmem_users user); /* * Temporarily stopping NVMEM commits could be beneficial. One use case is diff --git a/test/nvmem.c b/test/nvmem.c index b70c4732f4..d09bf8752a 100644 --- a/test/nvmem.c +++ b/test/nvmem.c @@ -175,41 +175,61 @@ static int test_configured_nvmem(void) return nvmem_init(); } -/* Verify that nvmem_setup indeed reinitializes the entire NVMEM. */ -static int test_nvmem_setup(void) +/* Verify that nvmem_erase_user_data only erases the given user's data. */ +static int test_nvmem_erase_user_data(void) { uint32_t write_value; uint32_t read_value; + int i; nvmem_init(); - write_value = 1; - - /* Make sure both partitions have data in them. */ - nvmem_write(0, sizeof(write_value), &write_value, NVMEM_USER_0); - nvmem_commit(); - read_value = ~write_value; - nvmem_read(0, sizeof(read_value), &read_value, NVMEM_USER_0); - TEST_ASSERT(read_value == write_value); + /* Make sure all partitions have data in them. */ + for (i = 0; i < NVMEM_NUM_PARTITIONS; i++) { + write_value = i; + nvmem_write(0, sizeof(write_value), &write_value, NVMEM_USER_0); + write_value = 2; + nvmem_write(0, sizeof(write_value), &write_value, NVMEM_USER_1); + write_value = 3; + nvmem_write(0, sizeof(write_value), &write_value, NVMEM_USER_2); + nvmem_commit(); + } - nvmem_write(0, sizeof(write_value), &write_value, NVMEM_USER_0); - nvmem_commit(); + /* Check that the writes took place. */ read_value = ~write_value; nvmem_read(0, sizeof(read_value), &read_value, NVMEM_USER_0); - TEST_ASSERT(read_value == write_value); + TEST_ASSERT(read_value == i-1); + nvmem_read(0, sizeof(read_value), &read_value, NVMEM_USER_1); + TEST_ASSERT(read_value == 2); + nvmem_read(0, sizeof(read_value), &read_value, NVMEM_USER_2); + TEST_ASSERT(read_value == 3); - /* nvmem_setup() is supposed to erase both partitions. */ - nvmem_setup(); - - nvmem_read(0, sizeof(read_value), &read_value, NVMEM_USER_0); - TEST_ASSERT(read_value == 0xffffffff); - - /* Switch active partition. */ - nvmem_write(0, sizeof(write_value), &write_value, NVMEM_USER_0); - nvmem_commit(); - - nvmem_read(0, sizeof(read_value), &read_value, NVMEM_USER_0); - TEST_ASSERT(read_value != 0xffffffff); + /* + * nvmem_erase_user_data() is supposed to erase the user's data across + * all partitions. + */ + nvmem_erase_user_data(NVMEM_USER_0); + + for (i = 0; i < NVMEM_NUM_PARTITIONS; i++) { + /* Make sure USER 0's data is (still) gone. */ + nvmem_read(0, sizeof(read_value), &read_value, NVMEM_USER_0); + TEST_ASSERT(read_value == 0xffffffff); + + /* Make sure the other users' data has been untouched. */ + nvmem_read(0, sizeof(read_value), &read_value, NVMEM_USER_1); + TEST_ASSERT(read_value == 2); + + /* + * The active partition changes when the contents of the cache + * changes. Therefore, in order to examine all the paritions, + * we'll keep modifying one of the user's data. + */ + nvmem_read(0, sizeof(read_value), &read_value, NVMEM_USER_2); + TEST_ASSERT(read_value == (3+i)); + write_value = 4 + i; + nvmem_write(0, sizeof(write_value), &write_value, NVMEM_USER_2); + nvmem_commit(); + } return EC_SUCCESS; } @@ -689,7 +709,7 @@ void run_test(void) RUN_TEST(test_move); RUN_TEST(test_is_different); RUN_TEST(test_lock); - RUN_TEST(test_nvmem_setup); + RUN_TEST(test_nvmem_erase_user_data); RUN_TEST(test_nvmem_save); test_print_result(); } -- cgit v1.2.1