Index: host/lib/crossystem.c |
diff --git a/host/lib/crossystem.c b/host/lib/crossystem.c |
index 277749b9bf2a91f22ea0509f46c7dee83d95bc54..5f94d711a002453f6f28010d37fcfd27a625700e 100644 |
--- a/host/lib/crossystem.c |
+++ b/host/lib/crossystem.c |
@@ -11,6 +11,7 @@ |
#include "crossystem.h" |
#include "utility.h" |
#include "vboot_common.h" |
+#include "vboot_nvstorage.h" |
/* ACPI constants from Chrome OS Main Processor Firmware Spec */ |
/* GPIO signal types */ |
@@ -22,6 +23,10 @@ |
#define CHSW_RECOVERY_EC_BOOT 0x00000004 |
#define CHSW_DEV_BOOT 0x00000020 |
#define CHSW_WP_BOOT 0x00000200 |
+/* CMOS reboot field bitflags */ |
+#define CMOSRF_RECOVERY 0x80 |
+#define CMOSRF_DEBUG_RESET 0x40 |
+#define CMOSRF_TRY_B 0x20 |
/* Base name for ACPI files */ |
#define ACPI_BASE_PATH "/sys/devices/platform/chromeos_acpi" |
@@ -34,6 +39,9 @@ |
#define GPIO_BASE_PATH "/sys/class/gpio" |
#define GPIO_EXPORT_PATH GPIO_BASE_PATH "/export" |
+/* Base name for NVRAM file */ |
+#define NVRAM_PATH "/dev/nvram" |
+ |
/* Read a string from a file. Passed the destination, dest size, and |
* filename to read. |
* |
@@ -161,12 +169,80 @@ int ReadGpio(int signal_type) { |
} |
+/* Read the CMOS reboot field in NVRAM. |
+ * |
+ * Returns 0 if the mask is clear in the field, 1 if set, or -1 if error. */ |
+int VbGetCmosRebootField(uint8_t mask) { |
+ FILE* f; |
+ int chnv, nvbyte; |
+ |
+ /* Get the byte offset from CHNV */ |
+ chnv = ReadFileInt(ACPI_CHNV_PATH); |
+ if (chnv == -1) |
+ return -1; |
+ |
+ f = fopen(NVRAM_PATH, "rb"); |
+ if (!f) |
+ return -1; |
+ |
+ if (0 != fseek(f, chnv, SEEK_SET) || EOF == (nvbyte = fgetc(f))) { |
+ fclose(f); |
+ return -1; |
+ } |
+ |
+ fclose(f); |
+ return (nvbyte & mask ? 1 : 0); |
+} |
+ |
+ |
+/* Write the CMOS reboot field in NVRAM. |
+ * |
+ * Sets (value=0) or clears (value!=0) the mask in the byte. |
+ * |
+ * Returns 0 if success, or -1 if error. */ |
+int VbSetCmosRebootField(uint8_t mask, int value) { |
+ FILE* f; |
+ int chnv, nvbyte; |
+ |
+ /* Get the byte offset from CHNV */ |
+ chnv = ReadFileInt(ACPI_CHNV_PATH); |
+ if (chnv == -1) |
+ return -1; |
+ |
+ f = fopen(NVRAM_PATH, "w+b"); |
+ if (!f) |
+ return -1; |
+ |
+ /* Read the current value */ |
+ if (0 != fseek(f, chnv, SEEK_SET) || EOF == (nvbyte = fgetc(f))) { |
+ fclose(f); |
+ return -1; |
+ } |
+ |
+ /* Set/clear the mask */ |
+ if (value) |
+ nvbyte |= mask; |
+ else |
+ nvbyte &= ~mask; |
+ |
+ /* Write the byte back */ |
+ if (0 != fseek(f, chnv, SEEK_SET) || EOF == (fputc(nvbyte, f))) { |
+ fclose(f); |
+ return -1; |
+ } |
+ |
+ /* Success */ |
+ fclose(f); |
+ return 0; |
+} |
+ |
/* Read a system property integer. |
* |
* Returns the property value, or -1 if error. */ |
int VbGetSystemPropertyInt(const char* name) { |
int value = -1; |
+ /* Switch positions */ |
if (!strcasecmp(name,"devsw_cur")) { |
value = ReadGpio(GPIO_SIGNAL_TYPE_DEV); |
} else if (!strcasecmp(name,"devsw_boot")) { |
@@ -186,6 +262,14 @@ int VbGetSystemPropertyInt(const char* name) { |
if (-1 != value && FwidStartsWith("Mario.")) |
value = 1 - value; /* Mario reports this backwards */ |
} |
+ /* NV storage values for older H2C BIOS */ |
+ else if (!strcasecmp(name,"recovery_request")) { |
+ value = VbGetCmosRebootField(CMOSRF_RECOVERY); |
+ } else if (!strcasecmp(name,"dbg_reset")) { |
+ value = VbGetCmosRebootField(CMOSRF_DEBUG_RESET); |
+ } else if (!strcasecmp(name,"fwb_tries")) { |
+ value = VbGetCmosRebootField(CMOSRF_TRY_B); |
+ } |
/* TODO: remaining properties from spec */ |
@@ -217,7 +301,15 @@ const char* VbGetSystemPropertyString(const char* name, char* dest, int size) { |
* Returns 0 if success, -1 if error. */ |
int VbSetSystemPropertyInt(const char* name, int value) { |
- /* TODO: support setting */ |
+ /* NV storage values for older H2C BIOS */ |
+ if (!strcasecmp(name,"recovery_request")) { |
+ return VbSetCmosRebootField(CMOSRF_RECOVERY, value); |
+ } else if (!strcasecmp(name,"dbg_reset")) { |
+ return VbSetCmosRebootField(CMOSRF_DEBUG_RESET, value); |
+ } else if (!strcasecmp(name,"fwb_tries")) { |
+ return VbSetCmosRebootField(CMOSRF_TRY_B, value); |
+ } |
+ |
return -1; |
} |