depthcharge: add functions to improve dev mode switch security

Add VbExKeyboardReadWithFlags() and VbExGetSwitches()
and read the recovery button state directly from hardware.
Also pass the VB_INIT_FLAG_VIRTUAL_REC_SWITCH at init
as appropriate.

These changes make it possible for vboot to avoid some
dangerous opportunistic exploits that could put the device
in developer mode without the owner intending to do so.

BUG=chrome-os-partner:21729
TEST=compiles
BRANCH=none
CQ-DEPEND=CL:182241,CL:182946,CL:182357

Change-Id: Ied1e59684517c0125be029f575be282fdb2db8a3
Reviewed-on: https://chromium-review.googlesource.com/183052
Reviewed-by: Luigi Semenzato <semenzato@chromium.org>
Commit-Queue: Luigi Semenzato <semenzato@chromium.org>
Tested-by: Luigi Semenzato <semenzato@chromium.org>
diff --git a/board/beltino/defconfig b/board/beltino/defconfig
index 2b09f1e..44d1d7d 100644
--- a/board/beltino/defconfig
+++ b/board/beltino/defconfig
@@ -9,6 +9,7 @@
 
 # Vboot
 CONFIG_OPROM_MATTERS=y
+CONFIG_PHYSICAL_REC_SWITCH=y
 CONFIG_RO_NORMAL_SUPPORT=y
 CONFIG_VIRTUAL_DEV_SWITCH=y
 
diff --git a/board/panther/defconfig b/board/panther/defconfig
index 5944658..d85652b 100644
--- a/board/panther/defconfig
+++ b/board/panther/defconfig
@@ -9,6 +9,7 @@
 
 # Vboot
 CONFIG_OPROM_MATTERS=y
+CONFIG_PHYSICAL_REC_SWITCH=y
 CONFIG_RO_NORMAL_SUPPORT=y
 CONFIG_VIRTUAL_DEV_SWITCH=y
 
diff --git a/src/board/panther/board.c b/src/board/panther/board.c
index d9c6d69..f8997a7 100644
--- a/src/board/panther/board.c
+++ b/src/board/panther/board.c
@@ -42,6 +42,12 @@
 	if (sysinfo_install_flags())
 		return 1;
 
+	// Read the current value of the recovery button instead of the
+	// value passed by coreboot.
+	LpPchGpio *rec_gpio = new_lp_pch_gpio_input(12);
+	if (flag_replace(FLAG_RECSW, new_gpio_not(&rec_gpio->ops)))
+		return 1;
+
 	MemMappedFlash *flash = new_mem_mapped_flash(0xff800000, 0x800000);
 	if (!flash || flash_set_ops(&flash->ops))
 		return 1;
diff --git a/src/vboot/Kconfig b/src/vboot/Kconfig
index 9225a52..3ee3d5d 100644
--- a/src/vboot/Kconfig
+++ b/src/vboot/Kconfig
@@ -29,6 +29,12 @@
 	help
 	  Whether this platform has a virtual developer switch.
 
+config PHYSICAL_REC_SWITCH
+	bool "Physical recovery switch is present"
+	default n
+	help
+	  Informs vboot that a physical recovery switch is present
+
 config OPROM_MATTERS
 	bool "Video option ROM matters"
 	default n
diff --git a/src/vboot/callbacks/Makefile.inc b/src/vboot/callbacks/Makefile.inc
index 158e167..919caed 100644
--- a/src/vboot/callbacks/Makefile.inc
+++ b/src/vboot/callbacks/Makefile.inc
@@ -28,6 +28,7 @@
 depthcharge-$(CONFIG_NV_STORAGE_CMOS) += nvstorage_cmos.c
 depthcharge-$(CONFIG_NV_STORAGE_DISK) += nvstorage_disk.c
 depthcharge-$(CONFIG_NV_STORAGE_CROS_EC) += nvstorage_cros_ec.c
+depthcharge-y += switches.c
 depthcharge-y += time.c
 depthcharge-y += tpm.c
 
diff --git a/src/vboot/callbacks/keyboard.c b/src/vboot/callbacks/keyboard.c
index d54f35d..20c23ee 100644
--- a/src/vboot/callbacks/keyboard.c
+++ b/src/vboot/callbacks/keyboard.c
@@ -61,3 +61,17 @@
 		return ch;
 	}
 }
+
+uint32_t VbExKeyboardReadWithFlags(uint32_t *flags_ptr)
+{
+	uint32_t c = VbExKeyboardRead();
+	if (flags_ptr) {
+		*flags_ptr = 0;
+		// USB keyboards definitely cannot be trusted (assuming they
+		// are even keyboards).  There are other devices that also
+		// cannot be trusted, but this is the best we can do for now.
+		if (last_key_input_type() != CONSOLE_INPUT_TYPE_USB)
+			*flags_ptr |= VB_KEY_FLAG_TRUSTED_KEYBOARD;
+	}
+	return c;
+}
diff --git a/src/vboot/callbacks/switches.c b/src/vboot/callbacks/switches.c
new file mode 100644
index 0000000..e07ae88
--- /dev/null
+++ b/src/vboot/callbacks/switches.c
@@ -0,0 +1,48 @@
+/*
+ * Copyright 2014 Google Inc.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but without any warranty; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <libpayload.h>
+#include <vboot_api.h>
+#include <vboot/util/flag.h>
+
+/*
+ * Return the state of the switches specified in request_mask.
+ * TODO(semenzato): find a better interface than the INIT_FLAGS.
+ */
+uint32_t VbExGetSwitches(uint32_t request_mask)
+{
+	uint32_t result = 0;
+
+	if ((request_mask & VB_INIT_FLAG_DEV_SWITCH_ON) &&
+            flag_fetch(FLAG_DEVSW))
+		result |= VB_INIT_FLAG_DEV_SWITCH_ON;
+
+	if ((request_mask & VB_INIT_FLAG_REC_BUTTON_PRESSED) &&
+	    flag_fetch(FLAG_RECSW))
+		result |= VB_INIT_FLAG_REC_BUTTON_PRESSED;
+
+	if ((request_mask & VB_INIT_FLAG_WP_ENABLED) &&
+	    flag_fetch(FLAG_WPSW))
+		result |= VB_INIT_FLAG_WP_ENABLED;
+
+	return result;
+}
diff --git a/src/vboot/stages.c b/src/vboot/stages.c
index 20366b3..f4c4039 100644
--- a/src/vboot/stages.c
+++ b/src/vboot/stages.c
@@ -78,6 +78,8 @@
 		iparams.flags |= VB_INIT_FLAG_VIRTUAL_DEV_SWITCH;
 	if (CONFIG_EC_SOFTWARE_SYNC)
 		iparams.flags |= VB_INIT_FLAG_EC_SOFTWARE_SYNC;
+        if (!CONFIG_PHYSICAL_REC_SWITCH)
+                iparams.flags |= VB_INIT_FLAG_VIRTUAL_REC_SWITCH;
 
 	printf("Calling VbInit().\n");
 	VbError_t res = VbInit(&cparams, &iparams);