diff options
author | Randall Spangler <rspangler@chromium.org> | 2011-02-25 12:06:26 -0800 |
---|---|---|
committer | Randall Spangler <rspangler@chromium.org> | 2011-02-25 12:06:26 -0800 |
commit | 172602829dc0d79ed65d7ed81225389f090b981f (patch) | |
tree | 83253d5ac03d77e816ba676dc233a36f37dba543 | |
parent | 0f8ffb11f5fe456aab4ef3a07ace0eb6c825dbd3 (diff) | |
download | vboot-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.h | 7 | ||||
-rw-r--r-- | firmware/lib/vboot_nvstorage.c | 40 | ||||
-rw-r--r-- | host/lib/crossystem.c | 13 | ||||
-rw-r--r-- | tests/vboot_nvstorage_test.c | 100 | ||||
-rw-r--r-- | utility/crossystem_main.c | 2 |
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)"}, |