Detect and report VM environment in crossystem

Add "inside_vm" command to crossystem.
x86: If there is no HWID and mainfw_type is "nonchrome", report that the
host is a VM. If HWID is present, it's not a VM.
ARM: Detection not implemented and so far no ARM VMs exist, always
report that the system is not a VM

BUG=chromium:632303
TEST=emerge-cyan vboot_reference and test binary on cyan QEMU and HW
BRANCH=none

Change-Id: I18f5cb24b68e51f3097d9aafd9f0db0e610d322a
Reviewed-on: https://chromium-review.googlesource.com/367240
Commit-Ready: Nicolas Norvez <norvez@chromium.org>
Tested-by: Nicolas Norvez <norvez@chromium.org>
Reviewed-by: Randall Spangler <rspangler@chromium.org>
diff --git a/host/arch/arm/lib/crossystem_arch.c b/host/arch/arm/lib/crossystem_arch.c
index 309235d..ae1a029 100644
--- a/host/arch/arm/lib/crossystem_arch.c
+++ b/host/arch/arm/lib/crossystem_arch.c
@@ -401,11 +401,15 @@
     if (value != -1)
       return value;
     return VbGetVarGpio("write-protect-switch");
-  } else if (!strcasecmp(name, "recoverysw_ec_boot"))
+  } else if (!strcasecmp(name, "recoverysw_ec_boot")) {
     /* TODO: read correct value using ectool */
     return 0;
-  else
+  } else if (!strcasecmp(name, "inside_vm")) {
+    /* No ARM VMs currently. */
+    return 0;
+  } else {
     return -1;
+  }
 }
 
 const char* VbGetArchPropertyString(const char* name, char* dest,
diff --git a/host/arch/mips/lib/crossystem_arch.c b/host/arch/mips/lib/crossystem_arch.c
index 28a6b80..ed1c7ab 100644
--- a/host/arch/mips/lib/crossystem_arch.c
+++ b/host/arch/mips/lib/crossystem_arch.c
@@ -42,6 +42,8 @@
     return 0;
   } else if (!strcasecmp(name,"wpsw_boot")) {
     return 1;
+  } else if (!strcasecmp(name,"inside_vm")) {
+    return 0;
   }
   return -1;
 }
diff --git a/host/arch/x86/lib/crossystem_arch.c b/host/arch/x86/lib/crossystem_arch.c
index d7e89fe..e1ee4f8 100644
--- a/host/arch/x86/lib/crossystem_arch.c
+++ b/host/arch/x86/lib/crossystem_arch.c
@@ -803,6 +803,23 @@
       value = (int)fwupdate_value;
   }
 
+  /* Detect if the host is a VM. If there is no HWID and the firmware type
+   * is "nonchrome", then assume it is a VM. If HWID is present, it is a
+   * baremetal Chrome OS machine. Other cases are errors. */
+  if (!strcasecmp(name,"inside_vm")) {
+    char hwid[VB_MAX_STRING_PROPERTY];
+    if (!VbGetArchPropertyString("hwid", hwid, sizeof(hwid))) {
+      char fwtype_buf[VB_MAX_STRING_PROPERTY];
+      const char *fwtype = VbGetArchPropertyString("mainfw_type", fwtype_buf,
+                                                    sizeof(fwtype_buf));
+      if (fwtype && !strcasecmp(fwtype,"nonchrome")) {
+        value = 1;
+      }
+    } else {
+      value = 0;
+    }
+  }
+
   return value;
 }
 
diff --git a/utility/crossystem.c b/utility/crossystem.c
index c88a444..6278e30 100644
--- a/utility/crossystem.c
+++ b/utility/crossystem.c
@@ -69,6 +69,7 @@
   {"fw_prev_tried", IS_STRING, "Firmware tried on previous boot (vboot2)"},
   {"fw_prev_result", IS_STRING, "Firmware result of previous boot (vboot2)"},
   {"hwid", IS_STRING, "Hardware ID"},
+  {"inside_vm", 0, "Running in a VM?"},
   {"kern_nv", 0, "Non-volatile field for kernel use", "0x%08x"},
   {"kernkey_vfy", IS_STRING, "Type of verification done on kernel key block"},
   {"loc_idx", CAN_WRITE, "Localization index for firmware screens (writable)"},