summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRandall Spangler <rspangler@chromium.org>2011-02-18 14:53:01 -0800
committerRandall Spangler <rspangler@chromium.org>2011-02-18 14:53:01 -0800
commite73302caae852485fdf180baa9a443b74f565dcc (patch)
tree44ce370ecc4e54b2596e13697f075612ef7744af
parent00b7d48f39c5e475fd3bc2f60cd987f164a0611e (diff)
downloadvboot-e73302caae852485fdf180baa9a443b74f565dcc.tar.gz
Add support for CHNV settings to crossystem.
crossystem can now be used in place of reboot_mode. BUG=12327 TEST=manual by comparing with the old reboot_mode utility crossystem recovery_request=1 reboot_mode crossystem dbg_reset=1 reboot_mode crossystem fwb_tries=1 reboot_mode crossystem recovery_request=0 reboot_mode crossystem dbg_reset=0 reboot_mode crossystem fwb_tries=0 reboot_mode Review URL: http://codereview.chromium.org/6538066 Change-Id: Ifde661d4621129d52e757654d85e386e65f90df5
-rw-r--r--host/lib/crossystem.c94
-rw-r--r--utility/crossystem_main.c5
2 files changed, 98 insertions, 1 deletions
diff --git a/host/lib/crossystem.c b/host/lib/crossystem.c
index 277749b9..5f94d711 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;
}
diff --git a/utility/crossystem_main.c b/utility/crossystem_main.c
index d6e0b8b6..7a1c1b51 100644
--- a/utility/crossystem_main.c
+++ b/utility/crossystem_main.c
@@ -32,6 +32,11 @@ const Param sys_param_list[] = {
{"hwid", 1, 0, "Hardware ID"},
{"fwid", 1, 0, "Active firmware ID"},
{"ro_fwid", 1, 0, "Read-only firmware ID"},
+ /* Writable integers */
+ {"recovery_request", 0, 1, "Recovery mode request (writable)"},
+ {"dbg_reset", 0, 1, "Debug reset mode request (writable)"},
+ {"fwb_tries", 0, 1, "Try firmware B count (writable)"},
+
/* Terminate with null name */
{NULL, 0, 0, NULL}
};