summaryrefslogtreecommitdiff
path: root/tests/vb2_nvstorage_tests.c
diff options
context:
space:
mode:
authorRandall Spangler <rspangler@chromium.org>2014-05-14 11:37:52 -0700
committerchrome-internal-fetch <chrome-internal-fetch@google.com>2014-06-05 23:14:27 +0000
commit3333e578497aafc4eb8c6e1e359f6e2b1dee633a (patch)
treef4c62ed293d9605559c09cb1b0607b4210a3d839 /tests/vb2_nvstorage_tests.c
parente166d04e797b605dd2f6784bc863a262c418c0c4 (diff)
downloadvboot-3333e578497aafc4eb8c6e1e359f6e2b1dee633a.tar.gz
vboot2: Add nvstorage and secdata functions
This is the second of several CLs adding a more memory- and code-efficient firmware verification library. BUG=chromium:370082 BRANCH=none TEST=make clean && COV=1 make Change-Id: I1dd571e7511bff18469707d5a2e90068e68e0d6f Signed-off-by: Randall Spangler <rspangler@chromium.org> Reviewed-on: https://chromium-review.googlesource.com/199841 Reviewed-by: Bill Richardson <wfrichar@chromium.org>
Diffstat (limited to 'tests/vb2_nvstorage_tests.c')
-rw-r--r--tests/vb2_nvstorage_tests.c192
1 files changed, 192 insertions, 0 deletions
diff --git a/tests/vb2_nvstorage_tests.c b/tests/vb2_nvstorage_tests.c
new file mode 100644
index 00000000..061f8691
--- /dev/null
+++ b/tests/vb2_nvstorage_tests.c
@@ -0,0 +1,192 @@
+/* Copyright (c) 2014 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.
+ *
+ * Tests for firmware NV storage library.
+ */
+
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "test_common.h"
+#include "vboot_common.h"
+
+#include "2api.h"
+#include "2common.h"
+#include "2misc.h"
+#include "2nvstorage.h"
+
+/* Single NV storage field to test */
+struct nv_field {
+ enum vb2_nv_param param; /* Parameter index */
+ uint32_t default_value; /* Expected default value */
+ uint32_t test_value; /* Value to test writing */
+ uint32_t test_value2; /* Second value to test writing */
+ char *desc; /* Field description */
+};
+
+/* Array of fields to test, terminated with a field with desc==NULL. */
+static struct nv_field nvfields[] = {
+ {VB2_NV_DEBUG_RESET_MODE, 0, 1, 0, "debug reset mode"},
+ {VB2_NV_TRY_NEXT, 0, 1, 0, "try next"},
+ {VB2_NV_TRY_COUNT, 0, 6, 15, "try B count"},
+ {VB2_NV_FW_TRIED, 0, 1, 0, "firmware tried"},
+ {VB2_NV_FW_RESULT, 0, 1, 2, "firmware result"},
+ {VB2_NV_RECOVERY_REQUEST, 0, 0x42, 0xED, "recovery request"},
+ {VB2_NV_RECOVERY_SUBCODE, 0, 0x56, 0xAC, "recovery subcode"},
+ {VB2_NV_LOCALIZATION_INDEX, 0, 0x69, 0xB0, "localization index"},
+ {VB2_NV_KERNEL_FIELD, 0, 0x12345678, 0xFEDCBA98, "kernel field"},
+ {VB2_NV_DEV_BOOT_USB, 0, 1, 0, "dev boot usb"},
+ {VB2_NV_DEV_BOOT_LEGACY, 0, 1, 0, "dev boot legacy"},
+ {VB2_NV_DEV_BOOT_SIGNED_ONLY, 0, 1, 0, "dev boot custom"},
+ {VB2_NV_DISABLE_DEV_REQUEST, 0, 1, 0, "disable dev request"},
+ {VB2_NV_CLEAR_TPM_OWNER_REQUEST, 0, 1, 0, "clear tpm owner request"},
+ {VB2_NV_CLEAR_TPM_OWNER_DONE, 0, 1, 0, "clear tpm owner done"},
+ {VB2_NV_OPROM_NEEDED, 0, 1, 0, "oprom needed"},
+ {0, 0, 0, 0, NULL}
+};
+
+static void test_changed(struct vb2_context *ctx, int changed, const char *why)
+{
+ if (changed)
+ TEST_NEQ(ctx->flags & VB2_CONTEXT_NVDATA_CHANGED, 0, why);
+ else
+ TEST_EQ(ctx->flags & VB2_CONTEXT_NVDATA_CHANGED, 0, why);
+};
+
+static void nv_storage_test(void)
+{
+ struct nv_field *vnf;
+ uint8_t goodcrc;
+ uint8_t workbuf[VB2_WORKBUF_RECOMMENDED_SIZE];
+ struct vb2_context c = {
+ .flags = 0,
+ .workbuf = workbuf,
+ .workbuf_size = sizeof(workbuf),
+ };
+ struct vb2_shared_data *sd = vb2_get_sd(&c);
+
+ memset(c.nvdata, 0xA6, sizeof(c.nvdata));
+ vb2_init_context(&c);
+
+ /* Init with invalid data should set defaults and regenerate CRC */
+ vb2_nv_init(&c);
+ TEST_EQ(c.nvdata[0], 0x70, "vb2_nv_init() reset header byte");
+ TEST_NEQ(c.nvdata[15], 0, "vb2_nv_init() CRC");
+ TEST_EQ(sd->status, VB2_SD_STATUS_NV_INIT | VB2_SD_STATUS_NV_REINIT,
+ "vb2_nv_init() status changed");
+ test_changed(&c, 1, "vb2_nv_init() reset changed");
+ goodcrc = c.nvdata[15];
+
+ /* Another init should not cause further changes */
+ c.flags = 0;
+ sd->status = 0;
+ vb2_nv_init(&c);
+ test_changed(&c, 0, "vb2_nv_init() didn't re-reset");
+ TEST_EQ(c.nvdata[15], goodcrc, "vb2_nv_init() CRC same");
+ TEST_EQ(sd->status, VB2_SD_STATUS_NV_INIT, "vb2_nv_init() status same");
+
+ /* Perturbing the header should force defaults */
+ c.nvdata[0] ^= 0x40;
+ vb2_nv_init(&c);
+ TEST_EQ(c.nvdata[0], 0x70, "vb2_nv_init() reset header byte again");
+ test_changed(&c, 1, "vb2_nv_init() corrupt changed");
+ TEST_EQ(c.nvdata[15], goodcrc, "vb2_nv_init() CRC same again");
+
+ /* So should perturbing some other byte */
+ TEST_EQ(c.nvdata[11], 0, "Kernel byte starts at 0");
+ c.nvdata[11] = 12;
+ vb2_nv_init(&c);
+ TEST_EQ(c.nvdata[11], 0, "vb2_nv_init() reset kernel byte");
+ test_changed(&c, 1, "vb2_nv_init() corrupt elsewhere changed");
+ TEST_EQ(c.nvdata[15], goodcrc, "vb2_nv_init() CRC same again");
+
+ /* Clear the kernel and firmware flags */
+ vb2_nv_init(&c);
+ TEST_EQ(vb2_nv_get(&c, VB2_NV_FIRMWARE_SETTINGS_RESET),
+ 1, "Firmware settings are reset");
+ vb2_nv_set(&c, VB2_NV_FIRMWARE_SETTINGS_RESET, 0);
+ TEST_EQ(vb2_nv_get(&c, VB2_NV_FIRMWARE_SETTINGS_RESET),
+ 0, "Firmware settings are clear");
+
+ TEST_EQ(vb2_nv_get(&c, VB2_NV_KERNEL_SETTINGS_RESET),
+ 1, "Kernel settings are reset");
+ vb2_nv_set(&c, VB2_NV_KERNEL_SETTINGS_RESET, 0);
+ TEST_EQ(vb2_nv_get(&c, VB2_NV_KERNEL_SETTINGS_RESET),
+ 0, "Kernel settings are clear");
+
+ TEST_EQ(c.nvdata[0], 0x40, "Header byte now just has the header bit");
+ /* That should have changed the CRC */
+ TEST_NEQ(c.nvdata[15], goodcrc,
+ "vb2_nv_init() CRC changed due to flags clear");
+
+ /* Test explicitly setting the reset flags again */
+ vb2_nv_init(&c);
+ vb2_nv_set(&c, VB2_NV_FIRMWARE_SETTINGS_RESET, 1);
+ TEST_EQ(vb2_nv_get(&c, VB2_NV_FIRMWARE_SETTINGS_RESET),
+ 1, "Firmware settings forced reset");
+ vb2_nv_set(&c, VB2_NV_FIRMWARE_SETTINGS_RESET, 0);
+
+ vb2_nv_set(&c, VB2_NV_KERNEL_SETTINGS_RESET, 1);
+ TEST_EQ(vb2_nv_get(&c, VB2_NV_KERNEL_SETTINGS_RESET),
+ 1, "Kernel settings forced reset");
+ vb2_nv_set(&c, VB2_NV_KERNEL_SETTINGS_RESET, 0);
+
+ /* Get/set an invalid field */
+ vb2_nv_init(&c);
+ vb2_nv_set(&c, -1, 1);
+ TEST_EQ(vb2_nv_get(&c, -1), 0, "Get invalid setting");
+
+ /* Test other fields */
+ vb2_nv_init(&c);
+ for (vnf = nvfields; vnf->desc; vnf++) {
+ TEST_EQ(vb2_nv_get(&c, vnf->param), vnf->default_value,
+ vnf->desc);
+ vb2_nv_set(&c, vnf->param, vnf->test_value);
+ TEST_EQ(vb2_nv_get(&c, vnf->param), vnf->test_value, vnf->desc);
+ vb2_nv_set(&c, vnf->param, vnf->test_value2);
+ TEST_EQ(vb2_nv_get(&c, vnf->param), vnf->test_value2,
+ vnf->desc);
+ }
+
+ /* None of those changes should have caused a reset to defaults */
+ vb2_nv_init(&c);
+ TEST_EQ(vb2_nv_get(&c, VB2_NV_FIRMWARE_SETTINGS_RESET),
+ 0, "Firmware settings are still clear");
+ TEST_EQ(vb2_nv_get(&c, VB2_NV_KERNEL_SETTINGS_RESET),
+ 0, "Kernel settings are still clear");
+
+ /* Writing identical settings doesn't cause the CRC to regenerate */
+ c.flags = 0;
+ vb2_nv_init(&c);
+ test_changed(&c, 0, "No regen CRC on open");
+ for (vnf = nvfields; vnf->desc; vnf++)
+ vb2_nv_set(&c, vnf->param, vnf->test_value2);
+ test_changed(&c, 0, "No regen CRC if data not changed");
+
+ /* Test out-of-range fields mapping to defaults or failing */
+ vb2_nv_init(&c);
+ vb2_nv_set(&c, VB2_NV_TRY_COUNT, 16);
+ TEST_EQ(vb2_nv_get(&c, VB2_NV_TRY_COUNT),
+ 15, "Try b count out of range");
+ vb2_nv_set(&c, VB2_NV_RECOVERY_REQUEST, 0x101);
+ TEST_EQ(vb2_nv_get(&c, VB2_NV_RECOVERY_REQUEST),
+ VB2_RECOVERY_LEGACY, "Recovery request out of range");
+ vb2_nv_set(&c, VB2_NV_LOCALIZATION_INDEX, 0x102);
+ TEST_EQ(vb2_nv_get(&c, VB2_NV_LOCALIZATION_INDEX),
+ 0, "Localization index out of range");
+
+ vb2_nv_set(&c, VB2_NV_FW_RESULT, VB2_FW_RESULT_UNKNOWN + 1);
+ vb2_nv_set(&c, VB2_NV_FW_RESULT, VB2_FW_RESULT_UNKNOWN + 100);
+ TEST_EQ(vb2_nv_get(&c, VB2_NV_FW_RESULT),
+ VB2_FW_RESULT_UNKNOWN, "Firmware result out of range");
+}
+
+int main(int argc, char* argv[])
+{
+ nv_storage_test();
+
+ return gTestSuccess ? 0 : 255;
+}