summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--board/cr50/board.c6
-rw-r--r--board/cr50/board.h6
-rw-r--r--board/cr50/power_button.c74
-rw-r--r--include/system.h3
4 files changed, 87 insertions, 2 deletions
diff --git a/board/cr50/board.c b/board/cr50/board.c
index 6843673662..defb033d52 100644
--- a/board/cr50/board.c
+++ b/board/cr50/board.c
@@ -1175,6 +1175,12 @@ void assert_ec_rst(void)
void deassert_ec_rst(void)
{
+ if (ec_rst_override()) {
+ ccprintf("EC un-reset blocked, try powercycle or Cr50 reboot."
+ "\n");
+ return;
+ }
+
wait_ec_rst(0);
if (uart_bitbang_is_enabled())
diff --git a/board/cr50/board.h b/board/cr50/board.h
index fea738f7d2..b9dc15e988 100644
--- a/board/cr50/board.h
+++ b/board/cr50/board.h
@@ -364,6 +364,12 @@ int ec_is_rx_allowed(void);
int servo_is_connected(void);
/*
+ * Returns nonzero value if EC reset line is taken over and should not be
+ * touched by the 'standard' EC reset functions.
+ */
+int ec_rst_override(void);
+
+/*
* Assert INT_AP_L to acknowledge AP that cr50 is ready for next TPM command.
* NOTE: must be called by ISR only.
*
diff --git a/board/cr50/power_button.c b/board/cr50/power_button.c
index 6aca820caf..6dab74d134 100644
--- a/board/cr50/power_button.c
+++ b/board/cr50/power_button.c
@@ -60,6 +60,71 @@ static void power_button_press_enable_interrupt(int enable)
#ifdef CONFIG_AP_RO_VERIFICATION
/*
+ * A hook used to keep the EC in reset, no matter what keys the user presses,
+ * the only way out is the Cr50 reboot, most likely through power cycle by
+ * battery cutoff.
+ *
+ * Cr50 console over SuzyQ would still be available in case the user has the
+ * cable and wants to see what happens with the system. The easiest way to see
+ * the system is in this state to run the 'flog' command and examine the flash
+ * log.
+ */
+static void keep_ec_in_reset(void);
+static bool ap_ro_verification_failed_;
+
+DECLARE_DEFERRED(keep_ec_in_reset);
+
+static void keep_ec_in_reset(void)
+{
+ if (!ap_ro_verification_failed_) {
+ enable_sleep(SLEEP_MASK_AP_RO_VERIFICATION);
+ return;
+ }
+
+ assert_ec_rst();
+ hook_call_deferred(&keep_ec_in_reset_data, 100 * MSEC);
+}
+
+static int ver_state_cmd(int argc, char **argv)
+{
+#ifdef CR50_DEV
+ int const max_args = 2;
+#else
+ int const max_args = 1;
+#endif
+
+ if (argc > max_args)
+ return EC_ERROR_PARAM_COUNT;
+#ifdef CR50_DEV
+ if (argc == max_args) {
+ if (strcasecmp(argv[1], "clear"))
+ return EC_ERROR_PARAM1;
+ if (ap_ro_verification_failed_) {
+ ap_ro_verification_failed_ = false;
+ deassert_ec_rst();
+ }
+ }
+#endif
+ ccprintf("%sAP RO verification failure detected\n",
+ ap_ro_verification_failed_ ? "" : "NO ");
+
+ return EC_SUCCESS;
+}
+DECLARE_SAFE_CONSOLE_COMMAND(ver_state, ver_state_cmd,
+#ifdef CR50_DEV
+ "[clear]",
+ "Display and/or clear AP RO validation state"
+#else
+ "", "Display AP RO validation state"
+#endif
+);
+
+int ec_rst_override(void)
+{
+ return ap_ro_verification_failed_;
+}
+
+/*
* Implement sequence detecting trigger for starting AP RO verification.
*
* 'RCTD' is short for 'RO check trigger detection'.
@@ -169,7 +234,14 @@ static int rctd_poll_handler(void)
CPRINTS("RO Validation triggered");
ap_ro_add_flash_event(APROF_CHECK_TRIGGERED);
- validate_ap_ro();
+
+ if (validate_ap_ro() == EC_ERROR_CRC) {
+ /* Validation failed, no go. */
+ ap_ro_verification_failed_ = true;
+ disable_sleep(SLEEP_MASK_AP_RO_VERIFICATION);
+ keep_ec_in_reset();
+ }
+
return 0;
}
diff --git a/include/system.h b/include/system.h
index 1df48cf28e..4862ad2dc0 100644
--- a/include/system.h
+++ b/include/system.h
@@ -425,7 +425,8 @@ enum {
SLEEP_MASK_USB_PD = BIT(5), /* USB PD device connected */
SLEEP_MASK_SPI = BIT(6), /* SPI communications ongoing */
SLEEP_MASK_I2C_SLAVE = BIT(7), /* I2C slave communication ongoing */
- SLEEP_MASK_FAN = BIT(8), /* Fan control loop ongoing */
+ SLEEP_MASK_AP_RO_VERIFICATION
+ = BIT(8), /* AP RO verification failure. */
SLEEP_MASK_USB_DEVICE = BIT(9), /* Generic USB device in use */
SLEEP_MASK_PWM = BIT(10), /* PWM output is enabled */
SLEEP_MASK_PHYSICAL_PRESENCE = BIT(11), /* Physical presence