summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--board/cr50/factory_mode.c42
-rw-r--r--common/ccd_config.c5
-rw-r--r--include/ccd_config.h9
-rw-r--r--include/tpm_vendor_cmds.h8
4 files changed, 64 insertions, 0 deletions
diff --git a/board/cr50/factory_mode.c b/board/cr50/factory_mode.c
index c8a5dd2cdd..22d028d4ee 100644
--- a/board/cr50/factory_mode.c
+++ b/board/cr50/factory_mode.c
@@ -5,6 +5,8 @@
#include "board_id.h"
#include "console.h"
+#include "ccd_config.h"
+#include "extension.h"
#include "system.h"
#define CPRINTS(format, args...) cprints(CC_CCD, format, ## args)
@@ -75,3 +77,43 @@ int board_is_first_factory_boot(void)
return (!(system_get_reset_flags() & RESET_FLAG_HIBERNATE) &&
inactive_image_is_guc_image() && board_id_is_erased());
}
+
+/*
+ * Vendor command for ccd factory reset.
+ *
+ * This vendor command can be used to enable ccd and disable write protect with
+ * a factory reset. A factory reset is automatically done during the first
+ * factory boot, but this vendor command can be used to do a factory reset at
+ * any time. Before calling factory reset, cr50 will make sure it is safe to do
+ * so. Cr50 checks batt_is_present to make sure the user has physical access to
+ * the device. Cr50 also checks ccd isn't disabled by the FWMP or ccd password.
+ *
+ * checks:
+ * - batt_is_present - Factory reset can only be done if HW write protect is
+ * removed.
+ * - FWMP disables ccd - If FWMP has disabled ccd, then we can't bypass it with
+ * a factory reset.
+ * - CCD password is set - If there is a password, someone will have to use that
+ * to open ccd and enable ccd manually. A factory reset cannot be
+ * used to get around the password.
+ */
+static enum vendor_cmd_rc vc_factory_reset(enum vendor_cmd_cc code,
+ void *buf,
+ size_t input_size,
+ size_t *response_size)
+{
+ *response_size = 0;
+
+ if (input_size)
+ return VENDOR_RC_BOGUS_ARGS;
+
+ if (board_battery_is_present() || !board_fwmp_allows_unlock() ||
+ ccd_has_password())
+ return VENDOR_RC_NOT_ALLOWED;
+
+ CPRINTF("factory reset\n");
+ enable_ccd_factory_mode();
+
+ return VENDOR_RC_SUCCESS;
+}
+DECLARE_VENDOR_COMMAND(VENDOR_CC_RESET_FACTORY, vc_factory_reset);
diff --git a/common/ccd_config.c b/common/ccd_config.c
index c356d0a04e..a3d419356c 100644
--- a/common/ccd_config.c
+++ b/common/ccd_config.c
@@ -581,6 +581,11 @@ static void ccd_testlab_toggle(void)
/******************************************************************************/
/* External interface */
+int ccd_has_password(void)
+{
+ return raw_has_password();
+}
+
void ccd_config_init(enum ccd_state state)
{
/* Set initial state, after making sure it's a valid one */
diff --git a/include/ccd_config.h b/include/ccd_config.h
index 7153449883..240feb5240 100644
--- a/include/ccd_config.h
+++ b/include/ccd_config.h
@@ -276,6 +276,15 @@ int ccd_reset_config(unsigned int flags);
void ccd_tpm_reset_callback(void);
/**
+ * Return True if the ccd password is set. It is possible that a pending ccd
+ * change would set or clear the password, but we don't think this is a big
+ * issue or risk for now.
+ *
+ * @return 1 if password is set, 0 if it's not
+ */
+int ccd_has_password(void);
+
+/**
* Enter CCD factory mode. This will clear the TPM and do a hard reboot after
* updating the ccd config.
*/
diff --git a/include/tpm_vendor_cmds.h b/include/tpm_vendor_cmds.h
index 58bb669d4a..b6b32c3ef7 100644
--- a/include/tpm_vendor_cmds.h
+++ b/include/tpm_vendor_cmds.h
@@ -55,6 +55,14 @@ enum vendor_cmd_cc {
VENDOR_CC_GET_ALERTS_DATA = 35,
VENDOR_CC_SPI_HASH = 36,
VENDOR_CC_PINWEAVER = 37,
+ /*
+ * Check the factory reset settings. If they're all set correctly, do a
+ * factory reset to enable ccd factory mode. All capabilities will be
+ * set to Always and write protect will be permanently disabled. This
+ * mode can't be reset unless VENDOR_CC_DISABLE_FACTORY is called or
+ * the 'ccd reset' console command is run.
+ */
+ VENDOR_CC_RESET_FACTORY = 38,
LAST_VENDOR_COMMAND = 65535,
};