summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--board/cr50/power_button.c111
-rw-r--r--include/config.h3
2 files changed, 114 insertions, 0 deletions
diff --git a/board/cr50/power_button.c b/board/cr50/power_button.c
index 5f46a4d0a6..a7d3634a00 100644
--- a/board/cr50/power_button.c
+++ b/board/cr50/power_button.c
@@ -56,10 +56,121 @@ static void power_button_press_enable_interrupt(int enable)
}
}
+#ifdef CONFIG_AP_RO_VERIFICATION
+
+/*
+ * Implement sequence detecting trigger for starting AP RO verification.
+ *
+ * 'RCTD' is short for 'RO check trigger detection'.
+ *
+ * Start the detection sequence each time power button is pressed. While it is
+ * kept pressed, count number of presses of the refresh key. If the refresh
+ * key is pressed PRESS_COUNT times within RCTD_CUTOFF_TIME, consider the RO
+ * verification process triggered.
+ *
+ * If power button is released before the refresh key is pressed the required
+ * number of times, or the cutoff time expires, stop the sequence until the
+ * next power button press.
+ */
+static void rctd_poll(void);
+DECLARE_DEFERRED(rctd_poll);
+
+#define RCTD_CUTOFF_TIME (3 * SECOND)
+#define RCTD_POLL_INTERVAL (20 * MSEC) /* Poll buttons this often.*/
+#define DEBOUNCE_COUNT 2 /* Keyboard keys are pretty noisy, need debouncing. */
+#define PRESS_COUNT 3
+
+/*
+ * Lower 32 bit of the timestamp when the sequence started. Is zero if the
+ * sequence is not running.
+ */
+static uint32_t rctd_start_time;
+
+/*
+ * rctd_poll_handler - periodically check states of power button and refresh
+ * key.
+ *
+ * Returns non-zero value if the polling needs to continue, or zero, if the
+ * polling should stop.
+ */
+static int rctd_poll_handler(void)
+{
+ uint32_t dior_state;
+ uint8_t ref_curr_state;
+ static uint8_t ref_press_count;
+ static uint8_t ref_last_state;
+ static uint8_t ref_debounced_state;
+ static uint8_t ref_debounce_counter;
+
+ /*
+ * H1 DIORx pins provide current state of both the power button and
+ * escape key.
+ */
+ dior_state = GREG32(RBOX, CHECK_INPUT);
+ ref_curr_state = !!(dior_state & GC_RBOX_CHECK_INPUT_KEY0_IN_MASK);
+
+ if (rctd_start_time == 0) {
+ /* Start the new sequence. */
+ rctd_start_time = get_time().le.lo;
+ ref_debounced_state = ref_last_state = ref_curr_state;
+ ref_debounce_counter = DEBOUNCE_COUNT;
+ ref_press_count = 0;
+ } else {
+ /* Have this been running longer than the timeout? */
+ if ((get_time().le.lo - rctd_start_time) > RCTD_CUTOFF_TIME) {
+ CPRINTS("Timeout, no RO check triggered");
+ return 0;
+ }
+ }
+
+
+ if ((dior_state & GC_RBOX_CHECK_INPUT_PWRB_IN_MASK) != 0) {
+ CPRINTS("Power button released, RO Check Detection stopped");
+ return 0;
+ }
+
+ if (ref_curr_state != ref_debounced_state) {
+ ref_debounced_state = ref_curr_state;
+ ref_debounce_counter = 0;
+ return 1;
+ }
+
+ if (ref_debounce_counter >= DEBOUNCE_COUNT)
+ return 1;
+
+ if (++ref_debounce_counter != DEBOUNCE_COUNT)
+ return 1;
+
+ ref_last_state = ref_debounced_state;
+ if (!ref_last_state)
+ return 1;
+
+ CPRINTS("Esc press registered");
+ if (++ref_press_count != PRESS_COUNT)
+ return 1;
+
+ CPRINTS("RO Validation triggered");
+ return 0;
+}
+
+static void rctd_poll(void)
+{
+ if (rctd_poll_handler())
+ hook_call_deferred(&rctd_poll_data, RCTD_POLL_INTERVAL);
+ else
+ rctd_start_time = 0;
+}
+#endif
+
static void power_button_handler(void)
{
CPRINTS("power button pressed");
+#ifdef CONFIG_AP_RO_VERIFICATION
+ if (rctd_start_time == 0)
+ hook_call_deferred(&rctd_poll_data, 0);
+#endif
+
if (physical_detect_press() != EC_SUCCESS) {
/* Not consumed by physical detect */
#ifdef CONFIG_U2F
diff --git a/include/config.h b/include/config.h
index 5e556b7224..c2dbc278e0 100644
--- a/include/config.h
+++ b/include/config.h
@@ -1414,6 +1414,9 @@
/* Trigger building the image with all format strings extracted. */
#undef CONFIG_EXTRACT_PRINTF_STRINGS
+/* Include AP RO verification support. */
+#undef CONFIG_AP_RO_VERIFICATION
+
/*
* Enable EC-CR50 communication (a.k.a. EC-EFS2). This is for CR50 config only.
*/