summaryrefslogtreecommitdiff
path: root/test
diff options
context:
space:
mode:
authorVadim Bendebury <vbendeb@chromium.org>2019-04-29 17:25:45 -0700
committerchrome-bot <chrome-bot@chromium.org>2019-05-01 11:02:59 -0700
commit13089909211c5289c46d22a3cb7fb9b06efcd917 (patch)
treeb77aedebccc921f8f07b86c2dbcadea4ef13315d /test
parent262ded1e01a374537e56160811bdad5763b311a5 (diff)
downloadchrome-ec-13089909211c5289c46d22a3cb7fb9b06efcd917.tar.gz
nvmem: fix delimiter creation during setvar()
The (key, value) objects should not be treated differently from TPM objects when initializing NVMEM from some inconsistent state. Saving of a modified (key, value) object should include the 'incomplete delimiter' phase when the new value has been already saved, but the old value has not yet been eliminated. Added tests verifying various failure modes. BRANCH=cr50, cr50-mp BUG=b:69907320, b:129710256 TEST='make run-nvmem' succeeds Change-Id: Ia53b6cfa2edd59fef28ace6978d752ca3cfbb2aa Signed-off-by: Vadim Bendebury <vbendeb@chromium.org> Reviewed-on: https://chromium-review.googlesource.com/1590043 Reviewed-by: Andrey Pronin <apronin@chromium.org>
Diffstat (limited to 'test')
-rw-r--r--test/nvmem.c106
-rw-r--r--test/nvmem_test.h4
2 files changed, 104 insertions, 6 deletions
diff --git a/test/nvmem.c b/test/nvmem.c
index dc5cde1eee..a7e339ebf1 100644
--- a/test/nvmem.c
+++ b/test/nvmem.c
@@ -1330,15 +1330,110 @@ static int test_tpm_nvmem_modify_evictable_objects(void)
return EC_SUCCESS;
}
+static int test_nvmem_tuple_updates(void)
+{
+ size_t i;
+ const char *modified_var1 = "var one after";
+ const struct tuple *t;
+
+ const struct {
+ uint8_t *key;
+ uint8_t *value;
+ } kv_pairs[] = {
+ /* Use # as the delimiter to allow \0 in keys/values. */
+ {"key0", "var zero before"},
+ {"key1", "var one before"}
+ };
+
+ TEST_ASSERT(post_init_from_scratch(0xff) == EC_SUCCESS);
+
+ /* Save vars in the nvmem. */
+ for (i = 0; i < ARRAY_SIZE(kv_pairs); i++)
+ TEST_ASSERT(setvar(kv_pairs[i].key, strlen(kv_pairs[i].key),
+ kv_pairs[i].value,
+ strlen(kv_pairs[i].value)) == EC_SUCCESS);
+
+ TEST_ASSERT(nvmem_init() == EC_SUCCESS);
+ /* Verify the vars are still there. */
+ for (i = 0; i < ARRAY_SIZE(kv_pairs); i++) {
+ const struct tuple *t;
+
+ t = getvar(kv_pairs[i].key, strlen(kv_pairs[i].key));
+ TEST_ASSERT(t);
+ TEST_ASSERT(t->val_len == strlen(kv_pairs[i].value));
+ TEST_ASSERT(!memcmp(t->data_ + strlen(kv_pairs[i].key),
+ kv_pairs[i].value, t->val_len));
+ freevar(t);
+ }
+
+ /*
+ * Now, let's try updating variable 'key1' introducing various failure
+ * modes.
+ */
+ failure_mode = TEST_FAIL_SAVING_VAR;
+ TEST_ASSERT(setvar(kv_pairs[1].key, strlen(kv_pairs[1].key),
+ modified_var1, strlen(modified_var1)) == EC_SUCCESS);
+ TEST_ASSERT(nvmem_init() == EC_SUCCESS);
+ /* No change should be seen. */
+ for (i = 0; i < ARRAY_SIZE(kv_pairs); i++) {
+ t = getvar(kv_pairs[i].key, strlen(kv_pairs[i].key));
+ TEST_ASSERT(t);
+ TEST_ASSERT(t->val_len == strlen(kv_pairs[i].value));
+ TEST_ASSERT(!memcmp(t->data_ + strlen(kv_pairs[i].key),
+ kv_pairs[i].value, t->val_len));
+ freevar(t);
+ }
+ failure_mode = TEST_FAIL_FINALIZING_VAR;
+ TEST_ASSERT(setvar(kv_pairs[1].key, strlen(kv_pairs[1].key),
+ modified_var1, strlen(modified_var1)) == EC_SUCCESS);
+ failure_mode = TEST_NO_FAILURE;
+ TEST_ASSERT(nvmem_init() == EC_SUCCESS);
+
+ /* First variable should be still unchanged. */
+ t = getvar(kv_pairs[0].key, strlen(kv_pairs[0].key));
+ TEST_ASSERT(t);
+ TEST_ASSERT(t->val_len == strlen(kv_pairs[0].value));
+ TEST_ASSERT(!memcmp(t->data_ + strlen(kv_pairs[0].key),
+ kv_pairs[0].value, t->val_len));
+ freevar(t);
+
+ /* Second variable should be updated. */
+ t = getvar(kv_pairs[1].key, strlen(kv_pairs[1].key));
+ TEST_ASSERT(t);
+ TEST_ASSERT(t->val_len == strlen(modified_var1));
+ TEST_ASSERT(!memcmp(t->data_ + strlen(kv_pairs[1].key), modified_var1,
+ t->val_len));
+ freevar(t);
+
+ /* A corrupted attempt to update second variable. */
+ failure_mode = TEST_FAIL_FINALIZING_VAR;
+ TEST_ASSERT(setvar(kv_pairs[1].key, strlen(kv_pairs[1].key),
+ kv_pairs[1].value, strlen(kv_pairs[1].value))
+ == EC_SUCCESS);
+ failure_mode = TEST_NO_FAILURE;
+ TEST_ASSERT(nvmem_init() == EC_SUCCESS);
+
+ /* Is there an instance of the second variable still in the flash. */
+ t = getvar(kv_pairs[1].key, strlen(kv_pairs[1].key));
+ TEST_ASSERT(t);
+ freevar(t);
+
+ /* Delete the remaining instance of the variable. */
+ TEST_ASSERT(setvar(kv_pairs[1].key, strlen(kv_pairs[1].key),
+ NULL, 0) == EC_SUCCESS);
+
+ /* Verify that it is indeed deleted before and after re-init. */
+ TEST_ASSERT(!getvar(kv_pairs[1].key, strlen(kv_pairs[1].key)));
+ TEST_ASSERT(nvmem_init() == EC_SUCCESS);
+ TEST_ASSERT(!getvar(kv_pairs[1].key, strlen(kv_pairs[1].key)));
+
+ return EC_SUCCESS;
+}
+
void run_test(void)
{
run_test_setup();
- if (0) {
- RUN_TEST(test_nvmem_incomplete_transaction);
- test_print_result();
- return;
- }
RUN_TEST(test_migration);
RUN_TEST(test_corrupt_nvmem);
RUN_TEST(test_fully_erased_nvmem);
@@ -1351,6 +1446,7 @@ void run_test(void)
RUN_TEST(test_tpm_nvmem_modify_reserved_objects);
RUN_TEST(test_tpm_nvmem_modify_evictable_objects);
RUN_TEST(test_nvmem_incomplete_transaction);
+ RUN_TEST(test_nvmem_tuple_updates);
failure_mode = TEST_NO_FAILURE; /* In case the above test failed. */
RUN_TEST(test_nvmem_interrupted_compaction);
failure_mode = TEST_NO_FAILURE; /* In case the above test failed. */
diff --git a/test/nvmem_test.h b/test/nvmem_test.h
index f8f166dc5e..9e050582ac 100644
--- a/test/nvmem_test.h
+++ b/test/nvmem_test.h
@@ -17,7 +17,9 @@ enum test_failure_mode {
TEST_NO_FAILURE,
TEST_FAIL_WHEN_SAVING,
TEST_FAIL_WHEN_INVALIDATING,
- TEST_FAIL_WHEN_COMPACTING
+ TEST_FAIL_WHEN_COMPACTING,
+ TEST_FAIL_SAVING_VAR,
+ TEST_FAIL_FINALIZING_VAR
};
extern enum test_failure_mode failure_mode;