Add an nvram flag to block the use of dev mode

Currently, this does nothing. It just sets a flag that nothing looks at.

Don't get all wound up - we haven't abandoned our principles. This will
eventually be used to allow enterprise-enrolled customers to prevent
unauthorized use of developer mode in the Chrome OS devices that THEY OWN.

This is not Google deciding to turn a feature off, it's allowing the OWNER
to control the use of the feature. In some situations, the owner can be held
liable for what others do with the owner's equipment. This will help the
owner avoid those situations while their device is out of their immediate
control.

BUG=none
BRANCH=ToT
TEST=manual

Set the flag with:

  crossystem block_devmode=1

Clear it with:

  crossystem block_devmode=0

Retrieve the value ("0" or "1") like so:

  val=$(crossystem block_devmode)
  echo "the flag is $val"

or just test it directly like so:

  if crossystem 'block_devmode?1' ; then
    echo "devmode is blocked"
  else
    echo "devmode is allowed"
  fi

It should be persistent across reboots.

Change-Id: I097f15b307e1c3a2a9db595e9495028a2eea6309
Signed-off-by: Bill Richardson <wfrichar@chromium.org>
Reviewed-on: https://chromium-review.googlesource.com/197771
Reviewed-by: Hung-Te Lin <hungte@chromium.org>
Reviewed-by: Randall Spangler <rspangler@chromium.org>
diff --git a/host/lib/crossystem.c b/host/lib/crossystem.c
index b496259..ba614cc 100644
--- a/host/lib/crossystem.c
+++ b/host/lib/crossystem.c
@@ -62,11 +62,12 @@
 
 /* Masks for kern_nv usage by kernel. */
 #define KERN_NV_FWUPDATE_TRIES_MASK 0x0000000F
+#define KERN_NV_BLOCK_DEVMODE_FLAG  0x00000010
 /* If you want to use the remaining currently-unused bits in kern_nv
  * for something kernel-y, define a new field (the way we did for
  * fwupdate_tries).  Don't just modify kern_nv directly, because that
  * makes it too easy to accidentally corrupt other sub-fields. */
-#define KERN_NV_CURRENTLY_UNUSED    0xFFFFFFF0
+#define KERN_NV_CURRENTLY_UNUSED    0xFFFFFFE0
 
 /* Return true if the FWID starts with the specified string. */
 int FwidStartsWith(const char *start) {
@@ -449,6 +450,12 @@
     value = VbGetNvStorage(VBNV_KERNEL_FIELD);
     if (value != -1)
       value &= KERN_NV_FWUPDATE_TRIES_MASK;
+  } else if (!strcasecmp(name,"block_devmode")) {
+    value = VbGetNvStorage(VBNV_KERNEL_FIELD);
+    if (value != -1) {
+      value &= KERN_NV_BLOCK_DEVMODE_FLAG;
+      value = !!value;
+    }
   } else if (!strcasecmp(name,"loc_idx")) {
     value = VbGetNvStorage(VBNV_LOCALIZATION_INDEX);
   } else if (!strcasecmp(name,"dev_boot_usb")) {
@@ -558,6 +565,14 @@
     kern_nv &= ~KERN_NV_FWUPDATE_TRIES_MASK;
     kern_nv |= (value & KERN_NV_FWUPDATE_TRIES_MASK);
     return VbSetNvStorage(VBNV_KERNEL_FIELD, kern_nv);
+  } else if (!strcasecmp(name,"block_devmode")) {
+    int kern_nv = VbGetNvStorage(VBNV_KERNEL_FIELD);
+    if (kern_nv == -1)
+      return -1;
+    kern_nv &= ~KERN_NV_BLOCK_DEVMODE_FLAG;
+    if (value)
+	kern_nv |= KERN_NV_BLOCK_DEVMODE_FLAG;
+    return VbSetNvStorage(VBNV_KERNEL_FIELD, kern_nv);
   } else if (!strcasecmp(name,"loc_idx")) {
     return VbSetNvStorage(VBNV_LOCALIZATION_INDEX, value);
   } else if (!strcasecmp(name,"dev_boot_usb")) {
diff --git a/utility/crossystem.c b/utility/crossystem.c
index 520f7fd..9a55d17 100644
--- a/utility/crossystem.c
+++ b/utility/crossystem.c
@@ -32,6 +32,7 @@
 /* List of parameters, terminated with a param with NULL name */
 const Param sys_param_list[] = {
   {"arch", IS_STRING, "Platform architecture"},
+  {"block_devmode", CAN_WRITE, "Block all use of developer mode"},
   {"clear_tpm_owner_request", CAN_WRITE, "Clear TPM owner on next boot"},
   {"clear_tpm_owner_done", CAN_WRITE, "Clear TPM owner done"},
   {"cros_debug", 0, "OS should allow debug features"},