summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBill Richardson <wfrichar@chromium.org>2016-09-22 12:11:33 -0700
committerchrome-bot <chrome-bot@chromium.org>2016-09-24 16:22:19 -0700
commit9b7f0b7066d356faab7e61bfd920266b48d5a361 (patch)
tree5212061c174fbfc071aa626a370d53ea8a6af8db
parent2446e3bfc089c7e65e41c90809ea70e9d051be91 (diff)
downloadchrome-ec-9b7f0b7066d356faab7e61bfd920266b48d5a361.tar.gz
Cr50: Unlock console quickly when battery is unplugged
The assumption is that removing the cover and disconnecting the battery is sufficiently obvious and time-consuming that it's not necessary to sit there poking the power button repeatedly. We still erase the NVMEM completely before unlocking, of course. BUG=chrome-os-partner:55322 BRANCH=none TEST=make buildall; test on Gru Toggle the Cr50 console with "lock on", then "lock off". Confirm that the 5-minute process only requires one poke when the battery cable is disconnected. Also confirm that both ways abort if you don't press the button at all. Change-Id: Iaa0f5eb102b914c95f3a34002438cbe80affcfb5 Signed-off-by: Bill Richardson <wfrichar@chromium.org> Reviewed-on: https://chromium-review.googlesource.com/388879 Reviewed-by: Randall Spangler <rspangler@chromium.org>
-rw-r--r--board/cr50/wp.c81
1 files changed, 56 insertions, 25 deletions
diff --git a/board/cr50/wp.c b/board/cr50/wp.c
index 8467370eb2..61873ce7d7 100644
--- a/board/cr50/wp.c
+++ b/board/cr50/wp.c
@@ -5,6 +5,7 @@
#include "common.h"
#include "console.h"
+#include "gpio.h"
#include "hooks.h"
#include "nvmem.h"
#include "registers.h"
@@ -52,15 +53,16 @@ int console_is_restricted(void)
/****************************************************************************/
/* Stuff for the unlock sequence */
-/* Total time to spend poking the power button */
-#define UNLOCK_TIME (10 * SECOND)
-/* Max time between pokes */
-#define UNLOCK_BEAT (2 * SECOND)
+/* Max time that can elapse between power button pokes */
+static int unlock_beat;
+/* When will we have poked the power button for long enough? */
static timestamp_t unlock_deadline;
+
+/* Are we expecting power button pokes? */
static int unlock_in_progress;
-/* Only invoked when the unlock sequence is done, either good or bad. */
+/* This is invoked only when the unlock sequence has ended */
static void unlock_sequence_is_over(void)
{
/* Disable the power button interrupt so we aren't bothered */
@@ -94,7 +96,7 @@ static void power_button_poked(void)
CPRINTS("poke: enough already", __func__);
} else {
/* Wait for the next poke */
- hook_call_deferred(&unlock_sequence_is_over_data, UNLOCK_BEAT);
+ hook_call_deferred(&unlock_sequence_is_over_data, unlock_beat);
CPRINTS("poke: not yet %.6ld", unlock_deadline);
}
@@ -103,12 +105,8 @@ static void power_button_poked(void)
DECLARE_IRQ(GC_IRQNUM_RBOX0_INTR_PWRB_IN_FED_INT, power_button_poked, 1);
-static int start_the_unlock_process(void)
+static void start_unlock_process(int total_poking_time, int max_poke_interval)
{
- /* Don't invoke more than one at a time */
- if (unlock_in_progress)
- return EC_ERROR_BUSY;
-
unlock_in_progress = 1;
/* Clear any leftover power button interrupts */
@@ -118,20 +116,18 @@ static int start_the_unlock_process(void)
GWRITE_FIELD(RBOX, INT_ENABLE, INTR_PWRB_IN_FED, 1);
task_enable_irq(GC_IRQNUM_RBOX0_INTR_PWRB_IN_FED_INT);
+ /* Must poke at least this often */
+ unlock_beat = max_poke_interval;
+
/* Keep poking until it's been long enough */
unlock_deadline = get_time();
- unlock_deadline.val += UNLOCK_TIME;
+ unlock_deadline.val += total_poking_time;
/* Stay awake while we're doing this, just in case. */
disable_sleep(SLEEP_MASK_FORCE_NO_DSLEEP);
/* Check progress after waiting long enough for one button press */
- hook_call_deferred(&unlock_sequence_is_over_data, UNLOCK_BEAT);
-
- CPRINTS("Unlock sequence starting. Continue until %.6ld",
- unlock_deadline);
-
- return EC_SUCCESS;
+ hook_call_deferred(&unlock_sequence_is_over_data, unlock_beat);
}
/****************************************************************************/
@@ -175,15 +171,50 @@ static int command_lock(int argc, char **argv)
/* Warn about the side effects of wiping nvmem */
ccputs(warning);
- /* Now the user has to sit there and poke the button */
- ccprintf("Start poking the power button in ");
- for (i = 10; i; i--) {
- ccprintf("%d ", i);
- sleep(1);
+ if (gpio_get_level(GPIO_BATT_PRES_L) == 1) {
+ /*
+ * If the battery cable has been disconnected, we only
+ * need to poke the power button once to prove physical
+ * presence.
+ */
+ ccprintf("Tap the power button once to confirm...\n\n");
+
+ /*
+ * We'll be satisified with the first press (so the
+ * unlock_deadine is now + 0us), but we're willing to
+ * wait for up to 10 seconds for that first press to
+ * happen. If we don't get one, the unlock will fail.
+ */
+ start_unlock_process(0, 10 * SECOND);
+
+ } else {
+ /*
+ * If the battery is present, the user has to sit there
+ * and poke the button repeatedly until enough time has
+ * elapsed.
+ */
+
+ ccprintf("Start poking the power button in ");
+ for (i = 10; i; i--) {
+ ccprintf("%d ", i);
+ sleep(1);
+ }
+ ccprintf("go!\n");
+
+ /*
+ * We won't be happy until we've poked the button for a
+ * good long while, but we'll only wait a short time
+ * between each press before deciding that the user has
+ * given up.
+ */
+ /* TODO(crbug.com/p/57408): Poke 5 mins, not 10 secs */
+ start_unlock_process(10 * SECOND, 2 * SECOND);
+
+ ccprintf("Unlock sequence starting."
+ " Continue until %.6ld\n", unlock_deadline);
}
- ccprintf("go!\n");
- return start_the_unlock_process();
+ return EC_SUCCESS;
}
out: