summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRandall Spangler <rspangler@chromium.org>2011-02-25 12:06:26 -0800
committerRandall Spangler <rspangler@chromium.org>2011-02-25 12:06:26 -0800
commit172602829dc0d79ed65d7ed81225389f090b981f (patch)
tree83253d5ac03d77e816ba676dc233a36f37dba543
parent0f8ffb11f5fe456aab4ef3a07ace0eb6c825dbd3 (diff)
downloadvboot-172602829dc0d79ed65d7ed81225389f090b981f.tar.gz
Add NV storage fields for firmware flags
1) Did firmware attempt RW slot B before slot A? 2) Did firmware check the kernel keyblock signature, or just its hash? Added crossystem support as well. BUG=chrome-os-partner:1657 TEST=make && make runtests Review URL: http://codereview.chromium.org/6597011 Change-Id: I0d743ae87cedd938ba988170793717d3fdbd8ce9
-rw-r--r--firmware/include/vboot_nvstorage.h7
-rw-r--r--firmware/lib/vboot_nvstorage.c40
-rw-r--r--host/lib/crossystem.c13
-rw-r--r--tests/vboot_nvstorage_test.c100
-rw-r--r--utility/crossystem_main.c2
5 files changed, 93 insertions, 69 deletions
diff --git a/firmware/include/vboot_nvstorage.h b/firmware/include/vboot_nvstorage.h
index 31bc539e..4b92e7f8 100644
--- a/firmware/include/vboot_nvstorage.h
+++ b/firmware/include/vboot_nvstorage.h
@@ -47,6 +47,13 @@ typedef enum VbNvParam {
VBNV_LOCALIZATION_INDEX,
/* Field reserved for kernel/user-mode use; 32-bit value. */
VBNV_KERNEL_FIELD,
+ /* Firmware checked RW slot B before slot A on the current boot because
+ * VBNV_TRY_B_COUNT was non-zero at that time. 0=no; 1=yes. */
+ VBNV_FW_USED_TRY_B,
+ /* Firmware verified the kernel key block signature using the key stored
+ * in the firmware. 0=no, just used the key block hash; 1=yes, used the
+ * key block signature. */
+ VBNV_FW_VERIFIED_KERNEL_KEY,
} VbNvParam;
diff --git a/firmware/lib/vboot_nvstorage.c b/firmware/lib/vboot_nvstorage.c
index 6e8c1c79..ec6e55de 100644
--- a/firmware/lib/vboot_nvstorage.c
+++ b/firmware/lib/vboot_nvstorage.c
@@ -14,17 +14,22 @@
* bitfields so the data format is consistent across platforms and
* compilers. */
#define HEADER_OFFSET 0
-#define HEADER_MASK 0xC0
-#define HEADER_SIGNATURE 0x40
-#define HEADER_FIRMWARE_SETTINGS_RESET 0x20
-#define HEADER_KERNEL_SETTINGS_RESET 0x10
+#define HEADER_MASK 0xC0
+#define HEADER_SIGNATURE 0x40
+#define HEADER_FIRMWARE_SETTINGS_RESET 0x20
+#define HEADER_KERNEL_SETTINGS_RESET 0x10
#define BOOT_OFFSET 1
-#define BOOT_DEBUG_RESET_MODE 0x80
-#define BOOT_TRY_B_COUNT 0x0F
+#define BOOT_DEBUG_RESET_MODE 0x80
+#define BOOT_TRY_B_COUNT 0x0F
#define RECOVERY_OFFSET 2
#define LOCALIZATION_OFFSET 3
+
+#define FIRMWARE_FLAGS_OFFSET 5
+#define FIRMWARE_FW_USED_TRY_B 0x80
+#define FIRMWARE_FW_VERIFIED_KERNEL_KEY 0x40
+
#define KERNEL_FIELD_OFFSET 11
#define CRC_OFFSET 15
@@ -120,6 +125,15 @@ int VbNvGet(VbNvContext* context, VbNvParam param, uint32_t* dest) {
| (raw[KERNEL_FIELD_OFFSET + 3] << 24));
return 0;
+ case VBNV_FW_USED_TRY_B:
+ *dest = (raw[FIRMWARE_FLAGS_OFFSET] & FIRMWARE_FW_USED_TRY_B ? 1 : 0);
+ return 0;
+
+ case VBNV_FW_VERIFIED_KERNEL_KEY:
+ *dest = (raw[FIRMWARE_FLAGS_OFFSET] & FIRMWARE_FW_VERIFIED_KERNEL_KEY ?
+ 1 : 0);
+ return 0;
+
default:
return 1;
}
@@ -187,6 +201,20 @@ int VbNvSet(VbNvContext* context, VbNvParam param, uint32_t value) {
raw[KERNEL_FIELD_OFFSET + 3] = (uint8_t)(value >> 24);
break;
+ case VBNV_FW_USED_TRY_B:
+ if (value)
+ raw[FIRMWARE_FLAGS_OFFSET] |= FIRMWARE_FW_USED_TRY_B;
+ else
+ raw[FIRMWARE_FLAGS_OFFSET] &= ~FIRMWARE_FW_USED_TRY_B;
+ break;
+
+ case VBNV_FW_VERIFIED_KERNEL_KEY:
+ if (value)
+ raw[FIRMWARE_FLAGS_OFFSET] |= FIRMWARE_FW_VERIFIED_KERNEL_KEY;
+ else
+ raw[FIRMWARE_FLAGS_OFFSET] &= ~FIRMWARE_FW_VERIFIED_KERNEL_KEY;
+ break;
+
default:
return 1;
}
diff --git a/host/lib/crossystem.c b/host/lib/crossystem.c
index 9428ba52..da9d80b5 100644
--- a/host/lib/crossystem.c
+++ b/host/lib/crossystem.c
@@ -484,6 +484,10 @@ int VbGetSystemPropertyInt(const char* name) {
} else if (!strcasecmp(name,"savedmem_size")) {
return (-1 == ReadFileInt(ACPI_CHSW_PATH) ? -1 : 0x00100000);
}
+ /* NV storage values with no defaults for older BIOS. */
+ else if (!strcasecmp(name,"tried_fwb")) {
+ value = VbGetNvStorage(VBNV_FW_USED_TRY_B);
+ }
/* NV storage values. If unable to get from NV storage, fall back to the
* CMOS reboot field used by older BIOS. */
else if (!strcasecmp(name,"recovery_request")) {
@@ -548,6 +552,15 @@ const char* VbGetSystemPropertyString(const char* name, char* dest, int size) {
default:
return NULL;
}
+ } else if (!strcasecmp(name,"kernkey_vfy")) {
+ switch(VbGetNvStorage(VBNV_FW_VERIFIED_KERNEL_KEY)) {
+ case 0:
+ return "hash";
+ case 1:
+ return "sig";
+ default:
+ return NULL;
+ }
} else
return NULL;
}
diff --git a/tests/vboot_nvstorage_test.c b/tests/vboot_nvstorage_test.c
index d5807c87..b3753713 100644
--- a/tests/vboot_nvstorage_test.c
+++ b/tests/vboot_nvstorage_test.c
@@ -2,7 +2,7 @@
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*
- * Tests for firmware image library.
+ * Tests for firmware NV storage library.
*/
#include <stdio.h>
@@ -13,9 +13,30 @@
#include "vboot_common.h"
#include "vboot_nvstorage.h"
+/* Single NV storage field to test */
+typedef struct VbNvField {
+ VbNvParam 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 */
+} VbNvField;
+
+/* Array of fields to test, terminated with a field with desc==NULL. */
+static VbNvField nvfields[] = {
+ {VBNV_DEBUG_RESET_MODE, 0, 1, 0, "debug reset mode"},
+ {VBNV_TRY_B_COUNT, 0, 6, 15, "try B count"},
+ {VBNV_RECOVERY_REQUEST, 0, 0x42, 0xED, "recovery request"},
+ {VBNV_LOCALIZATION_INDEX, 0, 0x69, 0xB0, "localization index"},
+ {VBNV_KERNEL_FIELD, 0, 0x12345678, 0xFEDCBA98, "kernel field"},
+ {VBNV_FW_USED_TRY_B, 0, 1, 0, "firmware used try B"},
+ {VBNV_FW_VERIFIED_KERNEL_KEY, 0, 1, 0, "firmware verified kernel key"},
+ {0, 0, 0, 0, NULL}
+};
static void VbNvStorageTest(void) {
+ VbNvField* vnf;
VbNvContext c;
uint8_t goodcrc;
uint32_t data;
@@ -77,65 +98,20 @@ static void VbNvStorageTest(void) {
/* That should have changed the CRC */
TEST_NEQ(c.raw[15], goodcrc, "VbNvTeardown() CRC changed due to flags clear");
- /* Test debug reset mode field */
+ /* Test other fields */
VbNvSetup(&c);
- TEST_EQ(VbNvGet(&c, VBNV_DEBUG_RESET_MODE, &data), 0,
- "Get debug reset mode");
- TEST_EQ(data, 0, "Debug reset mode default");
- TEST_EQ(VbNvSet(&c, VBNV_DEBUG_RESET_MODE, 1), 0,
- "Set debug reset mode");
- VbNvGet(&c, VBNV_DEBUG_RESET_MODE, &data);
- TEST_EQ(data, 1, "Debug reset mode set");
- VbNvTeardown(&c);
-
- /* Test try B count */
- VbNvSetup(&c);
- TEST_EQ(VbNvGet(&c, VBNV_TRY_B_COUNT, &data), 0, "Get try b count");
- TEST_EQ(data, 0, "Try b count default");
- TEST_EQ(VbNvSet(&c, VBNV_TRY_B_COUNT, 6), 0, "Set try b count");
- VbNvGet(&c, VBNV_TRY_B_COUNT, &data);
- TEST_EQ(data, 6, "Try b count set");
- VbNvSet(&c, VBNV_TRY_B_COUNT, 15);
- VbNvGet(&c, VBNV_TRY_B_COUNT, &data);
- TEST_EQ(data, 15, "Try b count set 2");
- VbNvTeardown(&c);
-
- /* Test recovery request */
- VbNvSetup(&c);
- TEST_EQ(VbNvGet(&c, VBNV_RECOVERY_REQUEST, &data), 0, "Get recovery request");
- TEST_EQ(data, 0, "Default recovery request");
- TEST_EQ(VbNvSet(&c, VBNV_RECOVERY_REQUEST, 0x42), 0, "Set recovery request");
- VbNvGet(&c, VBNV_RECOVERY_REQUEST, &data);
- TEST_EQ(data, 0x42, "Set recovery request");
- VbNvSet(&c, VBNV_RECOVERY_REQUEST, 0xED);
- VbNvGet(&c, VBNV_RECOVERY_REQUEST, &data);
- TEST_EQ(data, 0xED, "Set recovery request 2");
- VbNvTeardown(&c);
-
- /* Test localization index */
- VbNvSetup(&c);
- TEST_EQ(VbNvGet(&c, VBNV_LOCALIZATION_INDEX, &data), 0,
- "Get localization index");
- TEST_EQ(data, 0, "Default localization index");
- TEST_EQ(VbNvSet(&c, VBNV_LOCALIZATION_INDEX, 0x69), 0,
- "Set localization index");
- VbNvGet(&c, VBNV_LOCALIZATION_INDEX, &data);
- TEST_EQ(data, 0x69, "Set localization index");
- VbNvSet(&c, VBNV_LOCALIZATION_INDEX, 0xB0);
- VbNvGet(&c, VBNV_LOCALIZATION_INDEX, &data);
- TEST_EQ(data, 0xB0, "Set localization index 2");
- VbNvTeardown(&c);
-
- /* Test kernel field */
- VbNvSetup(&c);
- TEST_EQ(VbNvGet(&c, VBNV_KERNEL_FIELD, &data), 0, "Get kernel field");
- TEST_EQ(data, 0, "Default kernel field");
- TEST_EQ(VbNvSet(&c, VBNV_KERNEL_FIELD, 0x12345678), 0, "Set kernel field");
- VbNvGet(&c, VBNV_KERNEL_FIELD, &data);
- TEST_EQ(data, 0x12345678, "Set kernel field");
- VbNvSet(&c, VBNV_KERNEL_FIELD, 0xFEDCBA98);
- VbNvGet(&c, VBNV_KERNEL_FIELD, &data);
- TEST_EQ(data, 0xFEDCBA98, "Set kernel field 2");
+ for (vnf = nvfields; vnf->desc; vnf++) {
+ TEST_EQ(VbNvGet(&c, vnf->param, &data), 0, vnf->desc);
+ TEST_EQ(data, vnf->default_value, vnf->desc);
+
+ TEST_EQ(VbNvSet(&c, vnf->param, vnf->test_value), 0, vnf->desc);
+ TEST_EQ(VbNvGet(&c, vnf->param, &data), 0, vnf->desc);
+ TEST_EQ(data, vnf->test_value, vnf->desc);
+
+ TEST_EQ(VbNvSet(&c, vnf->param, vnf->test_value2), 0, vnf->desc);
+ TEST_EQ(VbNvGet(&c, vnf->param, &data), 0, vnf->desc);
+ TEST_EQ(data, vnf->test_value2, vnf->desc);
+ }
VbNvTeardown(&c);
/* None of those changes should have caused a reset to defaults */
@@ -149,10 +125,8 @@ static void VbNvStorageTest(void) {
/* Verify writing identical settings doesn't cause the CRC to regenerate */
VbNvSetup(&c);
TEST_EQ(c.regenerate_crc, 0, "No regen CRC on open");
- VbNvSet(&c, VBNV_DEBUG_RESET_MODE, 1);
- VbNvSet(&c, VBNV_RECOVERY_REQUEST, 0xED);
- VbNvSet(&c, VBNV_LOCALIZATION_INDEX, 0xB0);
- VbNvSet(&c, VBNV_KERNEL_FIELD, 0xFEDCBA98);
+ for (vnf = nvfields; vnf->desc; vnf++)
+ TEST_EQ(VbNvSet(&c, vnf->param, vnf->test_value2), 0, vnf->desc);
TEST_EQ(c.regenerate_crc, 0, "No regen CRC if data not changed");
VbNvTeardown(&c);
TEST_EQ(c.raw_changed, 0, "No raw change if data not changed");
diff --git a/utility/crossystem_main.c b/utility/crossystem_main.c
index 07c14e45..5352b4d7 100644
--- a/utility/crossystem_main.c
+++ b/utility/crossystem_main.c
@@ -33,6 +33,7 @@ const Param sys_param_list[] = {
{"savedmem_base", 0, 0, "RAM debug data area physical address", "0x%08x"},
{"savedmem_size", 0, 0, "RAM debug data area size in bytes"},
{"fmap_base", 0, 0, "Main firmware flashmap physical address", "0x%08x"},
+ {"tried_fwb", 0, 0, "Tried firmware B before A this boot"},
/* Read-only strings */
{"hwid", 1, 0, "Hardware ID"},
{"fwid", 1, 0, "Active firmware ID"},
@@ -40,6 +41,7 @@ const Param sys_param_list[] = {
{"mainfw_act", 1, 0, "Active main firmware"},
{"mainfw_type", 1, 0, "Active main firmware type"},
{"ecfw_act", 1, 0, "Active EC firmware"},
+ {"kernkey_vfy", 1, 0, "Type of verification done on kernel key block"},
/* Writable integers */
{"recovery_request", 0, 1, "Recovery mode request (writable)"},
{"dbg_reset", 0, 1, "Debug reset mode request (writable)"},