mirror of
https://github.com/Telecominfraproject/OpenCellular.git
synced 2026-01-10 01:21:49 +00:00
Add nvstorage / crossystem support for new vboot2 fields
This allows testing vboot2. These fields are ignored by original vboot firmware. BUG=chromium:370082 BRANCH=none TEST=manual crossystem -> fw_tried=A, fw_result=unknown, fw_try_next=A crossystem fw_tried=B echo $? -> 1 crossystem -> fw_tried=A, fw_result=unknown, fw_try_next=A crossystem fw_try_next=B crossystem -> fw_tried=A, fw_result=unknown, fw_try_next=B crossystem fw_try_next=beats_me echo $? -> 1 crossystem -> fw_tried=A, fw_result=unknown, fw_try_next=B crossystem fw_try_next=A crossystem -> fw_tried=A, fw_result=unknown, fw_try_next=A crossystem fw_result=trying crossystem -> fw_tried=A, fw_result=trying, fw_try_next=A crossystem fw_result=bupkis echo $? -> 1 crossystem -> fw_tried=A, fw_result=trying, fw_try_next=A crossystem fw_result=success crossystem -> fw_tried=A, fw_result=success, fw_try_next=A crossystem fw_result=failure crossystem -> fw_tried=A, fw_result=failure, fw_try_next=A crossystem fw_result=unknown crossystem -> fw_tried=A, fw_result=unknown, fw_try_next=A crossystem -> fw_try_count = 0, fwb_tries = 0 crossystem fw_try_count=6 crossystem -> fw_try_count = 6, fwb_tries = 6 crossystem fwb_tries=0 crossystem -> fw_try_count = 0, fwb_tries = 0 Change-Id: I1532f3384f8c05de2a7ff3f35abcc35d18049491 Signed-off-by: Randall Spangler <rspangler@chromium.org> Reviewed-on: https://chromium-review.googlesource.com/205475
This commit is contained in:
committed by
chrome-internal-fetch
parent
d11086caf0
commit
9e1da78448
@@ -15,6 +15,11 @@
|
||||
* Constants for NV storage. We use this rather than structs and bitfields so
|
||||
* the data format is consistent across platforms and compilers. Total NV
|
||||
* storage size is VB2_NVDATA_SIZE = 16 bytes.
|
||||
*
|
||||
* These constants must match the equivalent constants in
|
||||
* lib/vboot_nvstorage.c. (We currently don't share a common header file
|
||||
* because we're tring to keep the two libs independent, and we hope to
|
||||
* deprecate that one.)
|
||||
*/
|
||||
|
||||
enum vb2_nv_offset {
|
||||
|
||||
@@ -45,8 +45,14 @@ typedef enum VbNvParam {
|
||||
/*
|
||||
* Number of times to try booting RW firmware slot B before slot A.
|
||||
* Valid range: 0-15.
|
||||
*
|
||||
* Vboot2: Number of times to try the firmware in VBNV_FW_TRY_NEXT.
|
||||
*
|
||||
* These refer to the same field, but have different enum values so
|
||||
* case statement don't complain about duplicates.
|
||||
*/
|
||||
VBNV_TRY_B_COUNT,
|
||||
VBNV_FW_TRY_COUNT,
|
||||
/*
|
||||
* Request recovery mode on next boot; see VBNB_RECOVERY_* below for
|
||||
* currently defined reason codes. 8-bit value.
|
||||
@@ -85,8 +91,33 @@ typedef enum VbNvParam {
|
||||
VBNV_RECOVERY_SUBCODE,
|
||||
/* Request that NVRAM be backed up at next boot if possible. */
|
||||
VBNV_BACKUP_NVRAM_REQUEST,
|
||||
|
||||
/* Vboot2: Firmware slot to try next. 0=A, 1=B */
|
||||
VBNV_FW_TRY_NEXT,
|
||||
/* Vboot2: Firmware slot tried this boot (0=A, 1=B) */
|
||||
VBNV_FW_TRIED,
|
||||
/* Vboot2: Result of trying that firmware (see vb2_fw_result) */
|
||||
VBNV_FW_RESULT,
|
||||
|
||||
|
||||
} VbNvParam;
|
||||
|
||||
/* Result of trying the firmware in VBNV_FW_TRIED */
|
||||
typedef enum VbFwResult {
|
||||
/* Unknown */
|
||||
VBNV_FW_RESULT_UNKNOWN = 0,
|
||||
|
||||
/* Trying a new slot, but haven't reached success/failure */
|
||||
VBNV_FW_RESULT_TRYING = 1,
|
||||
|
||||
/* Successfully booted to the OS */
|
||||
VBNV_FW_RESULT_SUCCESS = 2,
|
||||
|
||||
/* Known failure */
|
||||
VBNV_FW_RESULT_FAILURE = 3,
|
||||
|
||||
} VbFwResult;
|
||||
|
||||
/* Recovery reason codes for VBNV_RECOVERY_REQUEST */
|
||||
/* Recovery not requested. */
|
||||
#define VBNV_RECOVERY_NOT_REQUESTED 0x00
|
||||
|
||||
@@ -17,6 +17,10 @@
|
||||
/*
|
||||
* Constants for NV storage. We use this rather than structs and bitfields so
|
||||
* the data format is consistent across platforms and compilers.
|
||||
*
|
||||
* These constants must match the equivalent constants in 2lib/2nvstorage.c.
|
||||
* (We currently don't share a common header file because we're tring to keep
|
||||
* the two libs independent, and we hope to deprecate this one.)
|
||||
*/
|
||||
#define HEADER_OFFSET 0
|
||||
#define HEADER_MASK 0xC0
|
||||
@@ -45,6 +49,11 @@
|
||||
|
||||
#define RECOVERY_SUBCODE_OFFSET 6
|
||||
|
||||
#define BOOT2_OFFSET 7
|
||||
#define BOOT2_RESULT_MASK 0x03
|
||||
#define BOOT2_TRIED 0x04
|
||||
#define BOOT2_TRY_NEXT 0x08
|
||||
|
||||
#define KERNEL_FIELD_OFFSET 11
|
||||
#define CRC_OFFSET 15
|
||||
|
||||
@@ -103,6 +112,7 @@ int VbNvGet(VbNvContext *context, VbNvParam param, uint32_t *dest)
|
||||
return 0;
|
||||
|
||||
case VBNV_TRY_B_COUNT:
|
||||
case VBNV_FW_TRY_COUNT:
|
||||
*dest = raw[BOOT_OFFSET] & BOOT_TRY_B_COUNT_MASK;
|
||||
return 0;
|
||||
|
||||
@@ -159,6 +169,18 @@ int VbNvGet(VbNvContext *context, VbNvParam param, uint32_t *dest)
|
||||
*dest = (raw[BOOT_OFFSET] & BOOT_BACKUP_NVRAM ? 1 : 0);
|
||||
return 0;
|
||||
|
||||
case VBNV_FW_TRY_NEXT:
|
||||
*dest = (raw[BOOT2_OFFSET] & BOOT2_TRY_NEXT ? 1 : 0);
|
||||
return 0;
|
||||
|
||||
case VBNV_FW_TRIED:
|
||||
*dest = (raw[BOOT2_OFFSET] & BOOT2_TRIED ? 1 : 0);
|
||||
return 0;
|
||||
|
||||
case VBNV_FW_RESULT:
|
||||
*dest = raw[BOOT2_OFFSET] & BOOT2_RESULT_MASK;
|
||||
return 0;
|
||||
|
||||
default:
|
||||
return 1;
|
||||
}
|
||||
@@ -196,6 +218,7 @@ int VbNvSet(VbNvContext *context, VbNvParam param, uint32_t value)
|
||||
break;
|
||||
|
||||
case VBNV_TRY_B_COUNT:
|
||||
case VBNV_FW_TRY_COUNT:
|
||||
/* Clip to valid range. */
|
||||
if (value > BOOT_TRY_B_COUNT_MASK)
|
||||
value = BOOT_TRY_B_COUNT_MASK;
|
||||
@@ -289,6 +312,28 @@ int VbNvSet(VbNvContext *context, VbNvParam param, uint32_t value)
|
||||
raw[BOOT_OFFSET] &= ~BOOT_BACKUP_NVRAM;
|
||||
break;
|
||||
|
||||
case VBNV_FW_TRY_NEXT:
|
||||
if (value)
|
||||
raw[BOOT2_OFFSET] |= BOOT2_TRY_NEXT;
|
||||
else
|
||||
raw[BOOT2_OFFSET] &= ~BOOT2_TRY_NEXT;
|
||||
break;
|
||||
|
||||
case VBNV_FW_TRIED:
|
||||
if (value)
|
||||
raw[BOOT2_OFFSET] |= BOOT2_TRIED;
|
||||
else
|
||||
raw[BOOT2_OFFSET] &= ~BOOT2_TRIED;
|
||||
break;
|
||||
|
||||
case VBNV_FW_RESULT:
|
||||
/* Map out of range values to unknown */
|
||||
if (value > BOOT2_RESULT_MASK)
|
||||
value = VBNV_FW_RESULT_UNKNOWN;
|
||||
|
||||
raw[BOOT2_OFFSET] &= ~BOOT2_RESULT_MASK;
|
||||
raw[BOOT2_OFFSET] |= (uint8_t)value;
|
||||
break;
|
||||
|
||||
default:
|
||||
return 1;
|
||||
|
||||
@@ -60,6 +60,7 @@ typedef enum VbBuildOption {
|
||||
VB_BUILD_OPTION_NODEBUG
|
||||
} VbBuildOption;
|
||||
|
||||
static const char *fw_results[] = {"unknown", "trying", "success", "failure"};
|
||||
|
||||
/* Masks for kern_nv usage by kernel. */
|
||||
#define KERN_NV_FWUPDATE_TRIES_MASK 0x0000000F
|
||||
@@ -464,6 +465,8 @@ int VbGetSystemPropertyInt(const char* name) {
|
||||
value = VbGetNvStorage(VBNV_TRY_B_COUNT);
|
||||
} else if (!strcasecmp(name,"fw_vboot2")) {
|
||||
value = GetVdatInt(VDAT_INT_FW_BOOT2);
|
||||
} else if (!strcasecmp(name,"fw_try_count")) {
|
||||
value = VbGetNvStorage(VBNV_FW_TRY_COUNT);
|
||||
} else if (!strcasecmp(name,"fwupdate_tries")) {
|
||||
value = VbGetNvStorage(VBNV_KERNEL_FIELD);
|
||||
if (value != -1)
|
||||
@@ -547,6 +550,16 @@ const char* VbGetSystemPropertyString(const char* name, char* dest,
|
||||
return GetVdatString(dest, size, VDAT_STRING_LOAD_KERNEL_DEBUG);
|
||||
} else if (!strcasecmp(name, "ddr_type")) {
|
||||
return unknown_string;
|
||||
} else if (!strcasecmp(name, "fw_try_next")) {
|
||||
return VbGetNvStorage(VBNV_FW_TRY_NEXT) ? "B" : "A";
|
||||
} else if (!strcasecmp(name, "fw_tried")) {
|
||||
return VbGetNvStorage(VBNV_FW_TRIED) ? "B" : "A";
|
||||
} else if (!strcasecmp(name, "fw_result")) {
|
||||
int v = VbGetNvStorage(VBNV_FW_RESULT);
|
||||
if (v < ARRAY_SIZE(fw_results))
|
||||
return fw_results[v];
|
||||
else
|
||||
return "unknown";
|
||||
}
|
||||
|
||||
return NULL;
|
||||
@@ -578,6 +591,8 @@ int VbSetSystemPropertyInt(const char* name, int value) {
|
||||
return VbSetNvStorage(VBNV_CLEAR_TPM_OWNER_DONE, 0);
|
||||
} else if (!strcasecmp(name,"fwb_tries")) {
|
||||
return VbSetNvStorage(VBNV_TRY_B_COUNT, value);
|
||||
} else if (!strcasecmp(name,"fw_try_count")) {
|
||||
return VbSetNvStorage(VBNV_FW_TRY_COUNT, value);
|
||||
} else if (!strcasecmp(name,"oprom_needed")) {
|
||||
return VbSetNvStorage(VBNV_OPROM_NEEDED, value);
|
||||
} else if (!strcasecmp(name,"backup_nvram_request")) {
|
||||
@@ -614,5 +629,26 @@ int VbSetSystemPropertyInt(const char* name, int value) {
|
||||
|
||||
int VbSetSystemPropertyString(const char* name, const char* value) {
|
||||
/* Chain to architecture-dependent properties */
|
||||
return VbSetArchPropertyString(name, value);
|
||||
if (0 == VbSetArchPropertyString(name, value))
|
||||
return 0;
|
||||
|
||||
if (!strcasecmp(name, "fw_try_next")) {
|
||||
if (!strcasecmp(value, "A"))
|
||||
return VbSetNvStorage(VBNV_FW_TRY_NEXT, 0);
|
||||
else if (!strcasecmp(value, "B"))
|
||||
return VbSetNvStorage(VBNV_FW_TRY_NEXT, 1);
|
||||
else
|
||||
return -1;
|
||||
|
||||
} else if (!strcasecmp(name, "fw_result")) {
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(fw_results); i++) {
|
||||
if (!strcasecmp(value, fw_results[i]))
|
||||
return VbSetNvStorage(VBNV_FW_RESULT, i);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -37,6 +37,10 @@ static VbNvField nvfields[] = {
|
||||
{VBNV_CLEAR_TPM_OWNER_REQUEST, 0, 1, 0, "clear tpm owner request"},
|
||||
{VBNV_CLEAR_TPM_OWNER_DONE, 0, 1, 0, "clear tpm owner done"},
|
||||
{VBNV_OPROM_NEEDED, 0, 1, 0, "oprom needed"},
|
||||
{VBNV_FW_TRY_COUNT, 0, 8, 15, "try count"},
|
||||
{VBNV_FW_TRY_NEXT, 0, 1, 0, "try next"},
|
||||
{VBNV_FW_TRIED, 0, 1, 0, "firmware tried"},
|
||||
{VBNV_FW_RESULT, VBNV_FW_RESULT_UNKNOWN, 1, 2, "firmware result"},
|
||||
{0, 0, 0, 0, NULL}
|
||||
};
|
||||
|
||||
@@ -125,17 +129,22 @@ static void VbNvStorageTest(void) {
|
||||
|
||||
/* Test other fields */
|
||||
VbNvSetup(&c);
|
||||
/* Test all defaults first, since some fields alias onto others */
|
||||
for (vnf = nvfields; vnf->desc; vnf++) {
|
||||
TEST_EQ(VbNvGet(&c, vnf->param, &data), 0, vnf->desc);
|
||||
TEST_EQ(data, vnf->default_value, vnf->desc);
|
||||
printf("Testing field: %s\n", vnf->desc);
|
||||
TEST_EQ(VbNvGet(&c, vnf->param, &data), 0, " get");
|
||||
TEST_EQ(data, vnf->default_value, " default");
|
||||
}
|
||||
/* Now test get/set */
|
||||
for (vnf = nvfields; vnf->desc; vnf++) {
|
||||
printf("Testing field: %s\n", vnf->desc);
|
||||
TEST_EQ(VbNvSet(&c, vnf->param, vnf->test_value), 0, " set 1");
|
||||
TEST_EQ(VbNvGet(&c, vnf->param, &data), 0, " get 1");
|
||||
TEST_EQ(data, vnf->test_value, " value 1");
|
||||
|
||||
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);
|
||||
TEST_EQ(VbNvSet(&c, vnf->param, vnf->test_value2), 0, " set 2");
|
||||
TEST_EQ(VbNvGet(&c, vnf->param, &data), 0, " get 2");
|
||||
TEST_EQ(data, vnf->test_value2, " value 2");
|
||||
}
|
||||
VbNvTeardown(&c);
|
||||
|
||||
@@ -161,12 +170,19 @@ static void VbNvStorageTest(void) {
|
||||
VbNvSet(&c, VBNV_TRY_B_COUNT, 16);
|
||||
VbNvGet(&c, VBNV_TRY_B_COUNT, &data);
|
||||
TEST_EQ(data, 15, "Try b count out of range");
|
||||
VbNvSetup(&c);
|
||||
VbNvSet(&c, VBNV_FW_TRY_COUNT, 16);
|
||||
VbNvGet(&c, VBNV_FW_TRY_COUNT, &data);
|
||||
TEST_EQ(data, 15, "Try count out of range");
|
||||
VbNvSet(&c, VBNV_RECOVERY_REQUEST, 0x101);
|
||||
VbNvGet(&c, VBNV_RECOVERY_REQUEST, &data);
|
||||
TEST_EQ(data, VBNV_RECOVERY_LEGACY, "Recovery request out of range");
|
||||
VbNvSet(&c, VBNV_LOCALIZATION_INDEX, 0x102);
|
||||
VbNvGet(&c, VBNV_LOCALIZATION_INDEX, &data);
|
||||
TEST_EQ(data, 0, "Localization index out of range");
|
||||
VbNvSet(&c, VBNV_FW_RESULT, VBNV_FW_RESULT_UNKNOWN + 100);
|
||||
VbNvGet(&c, VBNV_FW_RESULT, &data);
|
||||
TEST_EQ(data, VBNV_FW_RESULT_UNKNOWN, "Firmware result out of range");
|
||||
VbNvTeardown(&c);
|
||||
}
|
||||
|
||||
|
||||
@@ -57,6 +57,12 @@ const Param sys_param_list[] = {
|
||||
{"fwid", IS_STRING, "Active firmware ID"},
|
||||
{"fwupdate_tries", CAN_WRITE,
|
||||
"Times to try OS firmware update (writable, inside kern_nv)"},
|
||||
{"fw_tried", IS_STRING, "Firmware tried this boot (vboot2)"},
|
||||
{"fw_try_count", CAN_WRITE, "Number of times to try fw_try_next (writable)"},
|
||||
{"fw_try_next", IS_STRING|CAN_WRITE,
|
||||
"Firmware to try next (vboot2,writable)"},
|
||||
{"fw_result", IS_STRING|CAN_WRITE,
|
||||
"Firmware result this boot (vboot2,writable)"},
|
||||
{"hwid", IS_STRING, "Hardware ID"},
|
||||
{"kern_nv", 0, "Non-volatile field for kernel use", "0x%08x"},
|
||||
{"kernkey_vfy", IS_STRING, "Type of verification done on kernel key block"},
|
||||
|
||||
Reference in New Issue
Block a user