summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRandall Spangler <rspangler@chromium.org>2011-02-25 09:50:54 -0800
committerRandall Spangler <rspangler@chromium.org>2011-02-25 09:50:54 -0800
commit0f8ffb11f5fe456aab4ef3a07ace0eb6c825dbd3 (patch)
tree7e3f739a4d89f21984be4ebe2a02507b262fe4c1
parent0ca76fcc0cb17104579b4b4de678952590eed953 (diff)
downloadvboot-0f8ffb11f5fe456aab4ef3a07ace0eb6c825dbd3.tar.gz
crossystem uses VbNvStorage
Change-Id: I3f158115c8514bda0b271674870d68717c4816e6 BUG=12282 TEST=manual crossystem fwb_tries=0 && crossystem fwb_tries This should print 0 on both BIOSes. crossystem fwb_tries=6 && crossystem fwb_tries This should print 1 on an older BIOS and 6 on a new BIOS (0050+) Then reboot and run crossystem mainfw_act This should print 'B', since fwb_tries was non-zero. Review URL: http://codereview.chromium.org/6576059
-rw-r--r--host/lib/crossystem.c125
1 files changed, 119 insertions, 6 deletions
diff --git a/host/lib/crossystem.c b/host/lib/crossystem.c
index 70f39ddb..9428ba52 100644
--- a/host/lib/crossystem.c
+++ b/host/lib/crossystem.c
@@ -63,6 +63,7 @@
#define ACPI_CHSW_PATH ACPI_BASE_PATH "/CHSW"
#define ACPI_FMAP_PATH ACPI_BASE_PATH "/FMAP"
#define ACPI_GPIO_PATH ACPI_BASE_PATH "/GPIO"
+#define ACPI_VBNV_PATH ACPI_BASE_PATH "/VBNV"
/* Base name for GPIO files */
#define GPIO_BASE_PATH "/sys/class/gpio"
@@ -276,6 +277,104 @@ int VbSetCmosRebootField(uint8_t mask, int value) {
return 0;
}
+
+/* Read an integer property from VbNvStorage.
+ *
+ * Returns the parameter value, or -1 if error. */
+int VbGetNvStorage(VbNvParam param) {
+ FILE* f;
+ VbNvContext vnc;
+ int offs;
+ uint32_t value;
+ int retval;
+
+ /* Get the byte offset from VBNV */
+ offs = ReadFileInt(ACPI_VBNV_PATH ".0");
+ if (offs == -1)
+ return -1;
+ if (VBNV_BLOCK_SIZE > ReadFileInt(ACPI_VBNV_PATH ".1"))
+ return -1; /* NV storage block is too small */
+
+ /* TODO: locking around NV access */
+ f = fopen(NVRAM_PATH, "rb");
+ if (!f)
+ return -1;
+
+ if (0 != fseek(f, offs, SEEK_SET) ||
+ 1 != fread(vnc.raw, VBNV_BLOCK_SIZE, 1, f)) {
+ fclose(f);
+ return -1;
+ }
+
+ fclose(f);
+
+ if (0 != VbNvSetup(&vnc))
+ return -1;
+ retval = VbNvGet(&vnc, param, &value);
+ if (0 != VbNvTeardown(&vnc))
+ return -1;
+ if (0 != retval)
+ return -1;
+
+ /* TODO: If vnc.raw_changed, attempt to reopen NVRAM for write and
+ * save the new defaults. If we're able to, log. */
+ /* TODO: release lock */
+
+ return (int)value;
+}
+
+
+/* Write an integer property to VbNvStorage.
+ *
+ * Returns 0 if success, -1 if error. */
+int VbSetNvStorage(VbNvParam param, int value) {
+ FILE* f;
+ VbNvContext vnc;
+ int offs;
+ int retval = -1;
+ int i;
+
+ /* Get the byte offset from VBNV */
+ offs = ReadFileInt(ACPI_VBNV_PATH ".0");
+ if (offs == -1)
+ return -1;
+ if (VBNV_BLOCK_SIZE > ReadFileInt(ACPI_VBNV_PATH ".1"))
+ return -1; /* NV storage block is too small */
+
+ /* TODO: locking around NV access */
+ f = fopen(NVRAM_PATH, "w+b");
+ if (!f)
+ return -1;
+
+ if (0 != fseek(f, offs, SEEK_SET) ||
+ 1 != fread(vnc.raw, VBNV_BLOCK_SIZE, 1, f)) {
+ goto VbSetNvCleanup;
+ }
+
+ if (0 != VbNvSetup(&vnc))
+ goto VbSetNvCleanup;
+ i = VbNvSet(&vnc, param, (uint32_t)value);
+ if (0 != VbNvTeardown(&vnc))
+ goto VbSetNvCleanup;
+ if (0 != i)
+ goto VbSetNvCleanup;
+
+ if (vnc.raw_changed) {
+ if (0 != fseek(f, offs, SEEK_SET) ||
+ 1 != fwrite(vnc.raw, VBNV_BLOCK_SIZE, 1, f))
+ goto VbSetNvCleanup;
+ }
+
+ /* Success */
+ retval = 0;
+
+VbSetNvCleanup:
+ fclose(f);
+ /* TODO: release lock */
+ return retval;
+}
+
+
/* Read the recovery reason. Returns the reason code or -1 if error. */
int VbGetRecoveryReason(void) {
int value;
@@ -385,13 +484,20 @@ int VbGetSystemPropertyInt(const char* name) {
} else if (!strcasecmp(name,"savedmem_size")) {
return (-1 == ReadFileInt(ACPI_CHSW_PATH) ? -1 : 0x00100000);
}
- /* NV storage values for older H2C BIOS */
+ /* 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")) {
- value = VbGetCmosRebootField(CMOSRF_RECOVERY);
+ value = VbGetNvStorage(VBNV_RECOVERY_REQUEST);
+ if (-1 == value)
+ value = VbGetCmosRebootField(CMOSRF_RECOVERY);
} else if (!strcasecmp(name,"dbg_reset")) {
- value = VbGetCmosRebootField(CMOSRF_DEBUG_RESET);
+ value = VbGetNvStorage(VBNV_DEBUG_RESET_MODE);
+ if (-1 == value)
+ value = VbGetCmosRebootField(CMOSRF_DEBUG_RESET);
} else if (!strcasecmp(name,"fwb_tries")) {
- value = VbGetCmosRebootField(CMOSRF_TRY_B);
+ value = VbGetNvStorage(VBNV_TRY_B_COUNT);
+ if (-1 == value)
+ value = VbGetCmosRebootField(CMOSRF_TRY_B);
}
/* Other parameters */
else if (!strcasecmp(name,"recovery_reason")) {
@@ -452,12 +558,19 @@ const char* VbGetSystemPropertyString(const char* name, char* dest, int size) {
* Returns 0 if success, -1 if error. */
int VbSetSystemPropertyInt(const char* name, int value) {
- /* NV storage values for older H2C BIOS */
+ /* NV storage values. If unable to get from NV storage, fall back to the
+ * CMOS reboot field used by older BIOS. */
if (!strcasecmp(name,"recovery_request")) {
+ if (0 == VbSetNvStorage(VBNV_RECOVERY_REQUEST, value))
+ return 0;
return VbSetCmosRebootField(CMOSRF_RECOVERY, value);
} else if (!strcasecmp(name,"dbg_reset")) {
- return VbSetCmosRebootField(CMOSRF_DEBUG_RESET, value);
+ if (0 == VbSetNvStorage(VBNV_DEBUG_RESET_MODE, value))
+ return 0;
+ return VbSetCmosRebootField(CMOSRF_DEBUG_RESET, value);
} else if (!strcasecmp(name,"fwb_tries")) {
+ if (0 == VbSetNvStorage(VBNV_TRY_B_COUNT, value))
+ return 0;
return VbSetCmosRebootField(CMOSRF_TRY_B, value);
}