diff options
author | Bill Richardson <wfrichar@chromium.org> | 2016-09-22 12:11:33 -0700 |
---|---|---|
committer | chrome-bot <chrome-bot@chromium.org> | 2016-09-24 16:22:19 -0700 |
commit | 9b7f0b7066d356faab7e61bfd920266b48d5a361 (patch) | |
tree | 5212061c174fbfc071aa626a370d53ea8a6af8db | |
parent | 2446e3bfc089c7e65e41c90809ea70e9d051be91 (diff) | |
download | chrome-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.c | 81 |
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: |