summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMary Ruthven <mruthven@chromium.org>2022-02-23 11:04:07 -0600
committerCommit Bot <commit-bot@chromium.org>2022-03-01 05:09:35 +0000
commitbba90682d743dd6947751dcfd50871525c2224a2 (patch)
treebc3dd60d00cdabff1bbcb0ff8e017ac39a1ed6a1
parent8d39e763aca72c79049009865fe164f59b6c6035 (diff)
downloadchrome-ec-bba90682d743dd6947751dcfd50871525c2224a2.tar.gz
cr50: return the time since user_pres was asserted
Add a vendor command that returns the time since user_pres_l was asserted. This is only used for testing. Tracking user_pres_l needs to be enabled with a vendor command since DIOM4 may not be pulled up and may be pulled down on old boards. Enabling the vendor command survives deep sleep reset. It gets cleared after cr50 reset. Cr50 clears the user_pres_l status if tracking is disabled. BUG=b:219981194,b:208504127 TEST=manual # Verify it survives deep sleep sudo gsctool -y enable sudo gsctool -y ... user pres enabled # enter deep sleep sudo gsctool -y ... user pres enabled # Verify it doesn't survive cr50 reboot sudo gsctool -y enable sudo gsctool -y ... user pres enabled cr50 > reboot sudo gsctool -y ... user pres disabled # Check gsctool output after triggering DIOM4 pulse sudo gsctool -y enable # Trigger pulse and wait 5 seconds sudo gsctool -y ... user pres enabled last press: 5064331 Change-Id: Ib37980a5cd8d3378bf718e8e32a7d4152435a816 Signed-off-by: Mary Ruthven <mruthven@chromium.org> Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/3495863 Reviewed-by: Vadim Sukhomlinov <sukhomlinov@chromium.org>
-rw-r--r--board/cr50/board.c19
-rw-r--r--board/cr50/board.h6
-rw-r--r--board/cr50/build.mk1
-rw-r--r--board/cr50/gpio.inc14
-rw-r--r--board/cr50/scratch_reg1.h6
-rw-r--r--board/cr50/user_pres.c120
-rw-r--r--common/extension.c1
-rw-r--r--include/tpm_vendor_cmds.h14
8 files changed, 174 insertions, 7 deletions
diff --git a/board/cr50/board.c b/board/cr50/board.c
index 567ef45d27..b47bb4f611 100644
--- a/board/cr50/board.c
+++ b/board/cr50/board.c
@@ -189,6 +189,25 @@ int board_get_ccd_rec_lid_pin(void)
return board_properties & BOARD_CCD_REC_LID_PIN_MASK;
}
+int board_use_diom4(void)
+{
+ return !!(board_properties & BOARD_USE_DIOM4);
+}
+
+void board_write_prop(uint32_t flag, uint8_t enable)
+{
+ GWRITE_FIELD(PMU, LONG_LIFE_SCRATCH_WR_EN, REG1, 1);
+ /* Update board_properties and long life scratch. */
+ if (enable) {
+ board_properties |= flag;
+ GREG32(PMU, LONG_LIFE_SCRATCH1) |= flag;
+ } else {
+ board_properties &= ~flag;
+ GREG32(PMU, LONG_LIFE_SCRATCH1) &= ~flag;
+ }
+ /* Disable access to LONG_LIFE_SCRATCH1 reg */
+ GWRITE_FIELD(PMU, LONG_LIFE_SCRATCH_WR_EN, REG1, 0);
+}
/* Get header address of the backup RW copy. */
const struct SignedHeader *get_other_rw_addr(void)
diff --git a/board/cr50/board.h b/board/cr50/board.h
index a42df3038f..a0586256d8 100644
--- a/board/cr50/board.h
+++ b/board/cr50/board.h
@@ -294,6 +294,7 @@ void ec_detect_asserted(enum gpio_signal signal);
void servo_detect_asserted(enum gpio_signal signal);
void tpm_rst_deasserted(enum gpio_signal signal);
void tpm_rst_asserted(enum gpio_signal signal);
+void diom4_deasserted(enum gpio_signal signal);
void post_reboot_request(void);
@@ -361,6 +362,11 @@ int board_has_ec_cr50_comm_support(void);
int board_id_is_mismatched(void);
/* Allow for deep sleep to be enabled on AP shutdown */
int board_deep_sleep_allowed(void);
+/* The board uses DIOM4 for user_pres_l */
+int board_use_diom4(void);
+
+/* Set or clear a board property flag in long life scratch. */
+void board_write_prop(uint32_t flag, uint8_t enable);
void power_button_record(void);
diff --git a/board/cr50/build.mk b/board/cr50/build.mk
index f92a527ad8..d3e55093a9 100644
--- a/board/cr50/build.mk
+++ b/board/cr50/build.mk
@@ -113,6 +113,7 @@ board-${CONFIG_RDD} += rdd.o
board-${CONFIG_USB_SPI_V2} += usb_spi.o
board-${CONFIG_USB_I2C} += usb_i2c.o
board-y += recovery_button.o
+board-y += user_pres.o
fips-y=
fips-y += dcrypto/fips.o
diff --git a/board/cr50/gpio.inc b/board/cr50/gpio.inc
index 8fb67bd425..a89aae20b5 100644
--- a/board/cr50/gpio.inc
+++ b/board/cr50/gpio.inc
@@ -127,6 +127,12 @@ GPIO_INT(EC_PACKET_MODE_EN, PIN(1, 7), GPIO_INT_RISING, ec_comm_packet_mode_en)
GPIO_INT(EC_PACKET_MODE_DIS, PIN(1, 8), GPIO_INT_FALLING,
ec_comm_packet_mode_dis)
+/*
+ * Generic pulled up input used for physical presence indication on some
+ * devices.
+ */
+GPIO_INT(DIOM4, PIN(0, 3), GPIO_INT_RISING, diom4_deasserted)
+
/*****************************************************************************/
/* NON STANDARD INTERRUPT GPIOs - handlers defined and configured in board.c */
/*
@@ -172,12 +178,6 @@ GPIO(SPI_MOSI, PIN(0, 7), GPIO_INPUT | GPIO_PULL_DOWN)
GPIO(SPI_CLK, PIN(0, 8), GPIO_INPUT | GPIO_PULL_DOWN)
GPIO(SPI_CS_L, PIN(0, 9), GPIO_INPUT)
-/*
- * Generic pulled up input used for physical presence indication on some
- * devices.
- */
-GPIO(DIOM4, PIN(0, 3), GPIO_INPUT)
-
/* Used during *chip* factory process. */
GPIO(DIOB4, PIN(0, 10), GPIO_INPUT | GPIO_PULL_DOWN)
@@ -242,7 +242,7 @@ UNIMPLEMENTED(ENTERING_RW)
/* GPIOs - mark outputs as inputs too, to read back from the driven pad */
PINMUX(GPIO(INT_AP_L), A5, DIO_INPUT)
-PINMUX(GPIO(DIOM4), M4, DIO_INPUT | GPIO_PULL_UP)
+PINMUX(GPIO(DIOM4), M4, DIO_INPUT)
PINMUX(GPIO(EC_FLASH_SELECT), B2, DIO_INPUT)
PINMUX(GPIO(MONITOR_I2CP_SDA), A1, GPIO_INPUT)
diff --git a/board/cr50/scratch_reg1.h b/board/cr50/scratch_reg1.h
index b4cdd9c6d8..a7ad0c0b14 100644
--- a/board/cr50/scratch_reg1.h
+++ b/board/cr50/scratch_reg1.h
@@ -100,6 +100,11 @@
#define BOARD_CCD_REC_LID_PIN_DIOA12 (3 << BOARD_CCD_REC_LID_PIN_SHIFT)
/*
+ * The board supports USER_PRES on DIOM4.
+ */
+#define BOARD_USE_DIOM4 BIT(24)
+
+/*
* Indicates successful completion of FIPS power up
* tests earlier. Reduces wake up time after sleep.
* Stored in PWRDN_SCRATCH22 and use multiple bits to harden against
@@ -123,6 +128,7 @@
BOARD_PERIPH_CONFIG_I2C | \
BOARD_PERIPH_CONFIG_SPI | \
BOARD_USE_PLT_RESET | \
+ BOARD_USE_DIOM4 | \
BOARD_WP_DISABLE_DELAY)
#endif /* ! __EC_BOARD_CR50_SCRATCH_REG1_H */
diff --git a/board/cr50/user_pres.c b/board/cr50/user_pres.c
new file mode 100644
index 0000000000..218764657f
--- /dev/null
+++ b/board/cr50/user_pres.c
@@ -0,0 +1,120 @@
+/* Copyright 2022 The Chromium OS Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ *
+ * Track USER_PRES_L
+ */
+#include "extension.h"
+#include "gpio.h"
+#include "hooks.h"
+#include "registers.h"
+#include "scratch_reg1.h"
+#include "timer.h"
+
+static uint64_t last_press;
+static uint8_t asserted;
+
+/* Save the timestamp when DIOM4 is deasserted. */
+void diom4_deasserted(enum gpio_signal unused)
+{
+ if (!board_use_diom4())
+ return;
+
+ asserted = 1;
+ last_press = get_time().val;
+}
+
+void disable_user_pres(void)
+{
+ asserted = 0;
+ gpio_set_wakepin(GPIO_DIOM4, 0);
+ /* Disable the pullup and input on DIOM4 */
+ GWRITE_FIELD(PINMUX, DIOM4_CTL, PU, 0);
+ GWRITE_FIELD(PINMUX, DIOM4_CTL, IE, 0);
+ gpio_disable_interrupt(GPIO_DIOM4);
+}
+
+void enable_user_pres(void)
+{
+ /*
+ * The interrupt happens on the rising edge. Wake on the falling edge
+ * to ensure cr50 sees the rising edge interrupt.
+ */
+ gpio_set_wakepin(GPIO_DIOM4, GPIO_HIB_WAKE_FALLING);
+ /*
+ * Some boards don't have an external pull up. Add an internal one to
+ * make sure the signal isn't floating.
+ * Enable the pullup and input on DIOM4
+ */
+ GWRITE_FIELD(PINMUX, DIOM4_CTL, PU, 1);
+ GWRITE_FIELD(PINMUX, DIOM4_CTL, IE, 1);
+ /* Enable interrupts for user_pres_l detection */
+ gpio_enable_interrupt(GPIO_DIOM4);
+}
+
+/*
+ * Vendor command to for tracking USER_PRES_L
+ *
+ * This vendor command can be used to enable tracking USER_PRES_L on DIOM4 and
+ * get the time since DIOM4 was deasserted.
+ *
+ * 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_user_pres(enum vendor_cmd_cc code,
+ void *buf,
+ size_t input_size,
+ size_t *response_size)
+{
+ struct user_pres_response response;
+ uint8_t *buffer = buf;
+
+ *response_size = 0;
+
+ if (input_size == 1) {
+ uint8_t *cmd = buffer;
+
+ if (*cmd == USER_PRES_DISABLE) {
+ board_write_prop(BOARD_USE_DIOM4, 0);
+ disable_user_pres();
+ } else if (*cmd == USER_PRES_ENABLE) {
+ board_write_prop(BOARD_USE_DIOM4, 1);
+ enable_user_pres();
+ } else {
+ return VENDOR_RC_BOGUS_ARGS;
+ }
+ return VENDOR_RC_SUCCESS;
+ } else if (input_size) {
+ return VENDOR_RC_BOGUS_ARGS;
+ }
+ *response_size = sizeof(response);
+ response.state = board_use_diom4() ? USER_PRES_ENABLE :
+ USER_PRES_DISABLE;
+ if (board_use_diom4() && asserted) {
+ response.state |= USER_PRES_PRESSED;
+ response.last_press = get_time().val - last_press;
+ }
+ memcpy(buffer, &response, sizeof(response));
+
+ return VENDOR_RC_SUCCESS;
+}
+DECLARE_VENDOR_COMMAND(VENDOR_CC_USER_PRES, vc_user_pres);
+
+/**
+ * Setup DIOM4 interrupts if the board uses them.
+ */
+static void init_user_pres(void)
+{
+ if (!board_use_diom4()) {
+ disable_user_pres();
+ return;
+ }
+ enable_user_pres();
+}
+DECLARE_HOOK(HOOK_INIT, init_user_pres, HOOK_PRIO_DEFAULT);
diff --git a/common/extension.c b/common/extension.c
index 92e4798dce..d3dcae8217 100644
--- a/common/extension.c
+++ b/common/extension.c
@@ -37,6 +37,7 @@ uint32_t extension_route_command(struct vendor_cmd_params *p)
case VENDOR_CC_RESET_EC:
case VENDOR_CC_POP_LOG_ENTRY:
case VENDOR_CC_DS_DIS_TEMP:
+ case VENDOR_CC_USER_PRES:
#endif /* defined(CR50_DEV) */
case EXTENSION_POST_RESET: /* Always need to reset. */
case VENDOR_CC_CCD:
diff --git a/include/tpm_vendor_cmds.h b/include/tpm_vendor_cmds.h
index a59c81e10f..3ad5d79214 100644
--- a/include/tpm_vendor_cmds.h
+++ b/include/tpm_vendor_cmds.h
@@ -165,6 +165,8 @@ enum vendor_cmd_cc {
*/
VENDOR_CC_DS_DIS_TEMP = 59,
+ VENDOR_CC_USER_PRES = 60,
+
LAST_VENDOR_COMMAND = 65535,
};
@@ -224,6 +226,18 @@ enum wp_options {
WP_ENABLE
};
+/* VENDOR_CC_USER_PRES options. */
+enum user_pres_options {
+ USER_PRES_ENABLE = BIT(0),
+ USER_PRES_DISABLE = BIT(1),
+ USER_PRES_PRESSED = BIT(2)
+};
+/* Structure for VENDOR_CC_USER_PRES response */
+struct user_pres_response {
+ uint8_t state; /* The user presence state. ENABLE or DISABLE */
+ uint64_t last_press; /* Time since last press */
+} __packed;
+
/*
* The TPMv2 Spec mandates that vendor-specific command codes have bit 29 set,
* while bits 15-0 indicate the command. All other bits should be zero.