summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVadim Bendebury <vbendeb@chromium.org>2020-04-09 18:52:56 -0700
committerCommit Bot <commit-bot@chromium.org>2020-04-13 22:05:53 +0000
commitadc20080797ae9958b5355ba743b6b97290bf07f (patch)
tree1db7da2fbbc9a5eff640761fe1f14e708b3587b7
parent9c87cc0a1a83c65939704fb933e737269cf6455d (diff)
downloadchrome-ec-adc20080797ae9958b5355ba743b6b97290bf07f.tar.gz
Implement sequence for detecting trigger for AP RO verification
When supported, the AP RO verification would be triggered by the operator pressing and keeping pressed the power button and then pressing and releasing a few times the refresh key. As proposed in this patch, to trigger the verification the operator must complete the sequence within 3 seconds by pressing the refresh key three times. The sequences is controlled by periodic polling. Enabling refresh key press interrupts was investigated, the issue is that the key generates plenty of interrupts due to dribbling, to the tune of a hundred each time it is pressed. It is much cheaper to just poll every 20 ms. The CONFIG_AP_RO_VERIFICATION config flag controls enabling of this feature. BUG=b:141191727 TEST=enabled the new feature and verified proper operation by both detecting the trigger and abandoning the sequence due to released power button or not enough times pressed refresh key. Signed-off-by: Vadim Bendebury <vbendeb@chromium.org> Change-Id: I55376a87009d6f8020358ad11db1e47d0b8393ed Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/2144944 Reviewed-by: Mary Ruthven <mruthven@chromium.org>
-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.
*/