Crossystem should return at-boot switch positions from VbSharedData

This is more reliable than reading them through FDT/ACPI, since it reflects
the positions as shown to verified boot code.

Notes:
1. This affects ALL platforms with virtual dev switches (x86 AND arm)
2. The fix should have no effect on older platforms, but I haven't tested those.

BUG=chrome-os-partner:11805
TEST=manual

1. boot in normal mode.

devsw_boot             = 0                              # Developer switch position at boot
recovery_reason        = 0                              # Recovery mode reason for current boot
recoverysw_boot        = 0                              # Recovery switch position at boot
wpsw_boot              = 1                              # Firmware write protect hardware switch position at boot

2. boot in developer mode.

localhost ~ # crossystem
devsw_boot             = 1                              # Developer switch position at boot
recovery_reason        = 0                              # Recovery mode reason for current boot
recoverysw_boot        = 0                              # Recovery switch position at boot
wpsw_boot              = 1                              # Firmware write protect hardware switch position at boot

3. boot in developer-recovery mode using keyboard combo.

devsw_boot             = 1                              # Developer switch position at boot
recovery_reason        = 2                              # Recovery mode reason for current boot
recoverysw_boot        = 1                              # Recovery switch position at boot
wpsw_boot              = 1                              # Firmware write protect hardware switch position at boot

4. disable WP and reboot.  wpsw_boot should be 0.

Change-Id: If4156b5e14c6923c5b331c7e5feaabbffe1dad37
Reviewed-on: https://gerrit.chromium.org/gerrit/29199
Commit-Ready: Randall Spangler <rspangler@chromium.org>
Reviewed-by: Randall Spangler <rspangler@chromium.org>
Tested-by: Randall Spangler <rspangler@chromium.org>
diff --git a/host/lib/crossystem.c b/host/lib/crossystem.c
index 1515ecf..e120abc 100644
--- a/host/lib/crossystem.c
+++ b/host/lib/crossystem.c
@@ -34,6 +34,12 @@
 /* Fields that GetVdatInt() can get */
 typedef enum VdatIntField {
   VDAT_INT_FLAGS = 0,                /* Flags */
+  VDAT_INT_HEADER_VERSION,           /* Header version for VbSharedData */
+  VDAT_INT_DEVSW_BOOT,               /* Dev switch position at boot */
+  VDAT_INT_DEVSW_VIRTUAL,            /* Dev switch is virtual */
+  VDAT_INT_RECSW_BOOT,               /* Recovery switch position at boot */
+  VDAT_INT_WPSW_BOOT,                /* WP switch position at boot */
+
   VDAT_INT_FW_VERSION_TPM,           /* Current firmware version in TPM */
   VDAT_INT_KERNEL_VERSION_TPM,       /* Current kernel version in TPM */
   VDAT_INT_TRIED_FIRMWARE_B,         /* Tried firmware B due to fwb_tries */
@@ -322,15 +328,13 @@
   if (!sh)
     return -1;
 
+  /* Fields supported in version 1 */
   switch (field) {
     case VDAT_INT_FLAGS:
       value = (int)sh->flags;
       break;
-    case VDAT_INT_FW_VERSION_TPM:
-      value = (int)sh->fw_version_tpm;
-      break;
-    case VDAT_INT_KERNEL_VERSION_TPM:
-      value = (int)sh->kernel_version_tpm;
+    case VDAT_INT_HEADER_VERSION:
+      value = sh->struct_version;
       break;
     case VDAT_INT_TRIED_FIRMWARE_B:
       value = (sh->flags & VBSD_FWB_TRIED ? 1 : 0);
@@ -338,17 +342,47 @@
     case VDAT_INT_KERNEL_KEY_VERIFIED:
       value = (sh->flags & VBSD_KERNEL_KEY_VERIFIED ? 1 : 0);
       break;
-    case VDAT_INT_RECOVERY_REASON:
-      /* Field added in struct version 2 */
-      if (sh->struct_version >= 2)
-        value = sh->recovery_reason;
+    default:
       break;
   }
 
+  /* Fields added in struct version 2 */
+  if (sh->struct_version >= 2) {
+    switch(field) {
+      case VDAT_INT_DEVSW_BOOT:
+        value = (sh->flags & VBSD_BOOT_DEV_SWITCH_ON ? 1 : 0);
+        break;
+      case VDAT_INT_DEVSW_VIRTUAL:
+        value = (sh->flags & VBSD_HONOR_VIRT_DEV_SWITCH ? 1 : 0);
+        break;
+      case VDAT_INT_RECSW_BOOT:
+        value = (sh->flags & VBSD_BOOT_REC_SWITCH_ON ? 1 : 0);
+        break;
+      case VDAT_INT_WPSW_BOOT:
+        value = (sh->flags & VBSD_BOOT_FIRMWARE_WP_ENABLED ? 1 : 0);
+        break;
+      case VDAT_INT_FW_VERSION_TPM:
+        value = (int)sh->fw_version_tpm;
+        break;
+      case VDAT_INT_KERNEL_VERSION_TPM:
+        value = (int)sh->kernel_version_tpm;
+        break;
+      case VDAT_INT_RECOVERY_REASON:
+        value = sh->recovery_reason;
+        break;
+      default:
+        break;
+    }
+  }
+
   free(sh);
   return value;
 }
 
+/* Return version of VbSharedData struct or -1 if not found. */
+int VbSharedDataVersion(void) {
+  return GetVdatInt(VDAT_INT_HEADER_VERSION);
+}
 
 int VbGetSystemPropertyInt(const char* name) {
   int value = -1;
@@ -387,6 +421,14 @@
   /* Other parameters */
   else if (!strcasecmp(name,"cros_debug")) {
     value = VbGetCrosDebug();
+  } else if (!strcasecmp(name,"devsw_boot")) {
+    value = GetVdatInt(VDAT_INT_DEVSW_BOOT);
+  } else if (!strcasecmp(name,"devsw_virtual")) {
+    value = GetVdatInt(VDAT_INT_DEVSW_VIRTUAL);
+  } else if (!strcasecmp(name, "recoverysw_boot")) {
+    value = GetVdatInt(VDAT_INT_RECSW_BOOT);
+  } else if (!strcasecmp(name, "wpsw_boot")) {
+    value = GetVdatInt(VDAT_INT_WPSW_BOOT);
   } else if (!strcasecmp(name,"vdat_flags")) {
     value = GetVdatInt(VDAT_INT_FLAGS);
   } else if (!strcasecmp(name,"tpm_fwver")) {