summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaisuke Nojiri <dnojiri@chromium.org>2017-07-12 11:12:58 -0700
committerchrome-bot <chrome-bot@chromium.org>2017-07-14 04:01:45 -0700
commit921e9b71258c318f364457d97a94d3fb9e1bbbfc (patch)
tree1ff1afcf36153e7884fb6c0086c7dc063564a9a8
parenta53d2f5949942899cdb5d7b43f5ecc3820f0627e (diff)
downloadchrome-ec-921e9b71258c318f364457d97a94d3fb9e1bbbfc.tar.gz
vboot: Jump to RW early
This change makes EC run vboot in the HOOK task. The vboot routine requires battery and charger info. It waits in a deferred call loop until the charge manager is initialized. BUG=b:63586051 BRANCH=none TEST=Verify the following cases: A. Hardware reboot (type-c/BJ) 1. Unplug AC in S0 then plug in AC: BOOT/BOOT 2. Unplug AC in S5 then plug in AC: S5/S5 3. Unplug AC after A.2 then plug in AC: S5/S5 4. Press PB in S5: BOOT/BOOT B. Software reboot (type-c/BJ) 1. Run EC reboot command in S0: BOOT/BOOT 2. Run EC reboot command in S5: BOOT/BOOT 3. Run EC reboot ap-off command in S0: S5/S5 4. Run EC reboot ap-off command in S5: S5/S5 5. Run host reboot command: BOOT/BOOT 6. Run host shutdown command: S5/S5 C. Recovery tests 1. Press RB and PB in S0: FAIL(*1)/PASS 2. Press RB and PB in S5: FAIL(*1)/PASS(*2) 3. Unplug AC in S0 then press RB and plug in AC: PASS/PASS 4. Unplug AC in S5 then press RB and plug in AC: PASS(*2)/PASS(*2) *1: b:63668669 *2: b:63669512. Requires one more PB press. Change-Id: I28f37fdad7f83d0d44570b9003e8c6a4b83b832f Signed-off-by: Daisuke Nojiri <dnojiri@chromium.org> Reviewed-on: https://chromium-review.googlesource.com/568699 Reviewed-by: Randall Spangler <rspangler@chromium.org>
-rw-r--r--board/fizz/ec.tasklist4
-rw-r--r--common/system.c8
-rw-r--r--common/vboot/vboot.c72
-rw-r--r--include/vboot.h11
-rw-r--r--power/intel_x86.c15
5 files changed, 67 insertions, 43 deletions
diff --git a/board/fizz/ec.tasklist b/board/fizz/ec.tasklist
index 82a214f38d..b60ae990a7 100644
--- a/board/fizz/ec.tasklist
+++ b/board/fizz/ec.tasklist
@@ -21,9 +21,9 @@
*/
#define CONFIG_TASK_LIST \
- TASK_ALWAYS(HOOKS, hook_task, NULL, LARGER_TASK_STACK_SIZE) \
+ TASK_ALWAYS(HOOKS, hook_task, NULL, 2048) \
/* Larger stack for RW verification (i.e. sha256, rsa) */ \
- TASK_NOTEST(CHIPSET, chipset_task, NULL, 2048) \
+ TASK_NOTEST(CHIPSET, chipset_task, NULL, TASK_STACK_SIZE) \
TASK_NOTEST(PDCMD, pd_command_task, NULL, TASK_STACK_SIZE) \
TASK_ALWAYS(HOSTCMD, host_command_task, NULL, LARGER_TASK_STACK_SIZE) \
TASK_ALWAYS(CONSOLE, console_task, NULL, LARGER_TASK_STACK_SIZE) \
diff --git a/common/system.c b/common/system.c
index 66e7be5192..1f9a2062c1 100644
--- a/common/system.c
+++ b/common/system.c
@@ -983,13 +983,9 @@ static int command_sysjump(int argc, char **argv)
/* Handle named images */
if (!strcasecmp(argv[1], "RO"))
return system_run_image_copy(SYSTEM_IMAGE_RO);
- else if (!strcasecmp(argv[1], "RW") || !strcasecmp(argv[1], "A")) {
- /*
- * TODO(crosbug.com/p/11149): remove "A" once all scripts are
- * updated to use "RW".
- */
+ else if (!strcasecmp(argv[1], "RW") || !strcasecmp(argv[1], "A"))
return system_run_image_copy(SYSTEM_IMAGE_RW);
- } else if (!strcasecmp(argv[1], "B")) {
+ else if (!strcasecmp(argv[1], "B")) {
#ifdef CONFIG_RW_B
return system_run_image_copy(SYSTEM_IMAGE_RW_B);
#else
diff --git a/common/vboot/vboot.c b/common/vboot/vboot.c
index 27c57b27c2..27a47fd125 100644
--- a/common/vboot/vboot.c
+++ b/common/vboot/vboot.c
@@ -11,6 +11,7 @@
#include "charge_manager.h"
#include "chipset.h"
#include "console.h"
+#include "hooks.h"
#include "host_command.h"
#include "rsa.h"
#include "rwsig.h"
@@ -21,8 +22,8 @@
#include "vboot.h"
#include "vb21_struct.h"
-#define CPRINTS(format, args...) cprints(CC_VBOOT, format, ## args)
-#define CPRINTF(format, args...) cprintf(CC_VBOOT, format, ## args)
+#define CPRINTS(format, args...) cprints(CC_VBOOT,"VB " format, ## args)
+#define CPRINTF(format, args...) cprintf(CC_VBOOT,"VB " format, ## args)
enum vboot_ec_slot {
VBOOT_EC_SLOT_A,
@@ -145,48 +146,89 @@ static int verify_and_jump(void)
static void request_power(void)
{
/* TODO: Blink LED */
+ CPRINTS("%s", __func__);
}
static void request_recovery(void)
{
/* TODO: Blink LED */
+ CPRINTS("%s", __func__);
}
static int is_manual_recovery(void)
{
- return host_get_events() & EC_HOST_EVENT_KEYBOARD_RECOVERY;
+ return host_is_event_set(EC_HOST_EVENT_KEYBOARD_RECOVERY);
}
-void vboot_main(void)
+static void vboot_main(void);
+DECLARE_DEFERRED(vboot_main);
+static void vboot_main(void)
{
+ const int check_charge_manager_frequency_usec = 10 * MSEC;
int port = charge_manager_get_active_charge_port();
- if (port >= CONFIG_USB_PD_PORT_COUNT) {
- /* AC is not type-c. No chance to boot. */
- request_power();
+ if (port == CHARGE_PORT_NONE) {
+ /* We loop here until charge manager is ready */
+ hook_call_deferred(&vboot_main_data,
+ check_charge_manager_frequency_usec);
+ return;
+ }
+
+ CPRINTS("Checking power");
+
+ if (system_can_boot_ap()) {
+ /*
+ * We are here for the two cases:
+ * 1. Booting on RO with a barrel jack adapter. We can continue
+ * to boot AP with EC-RO. We'll jump later in softsync.
+ * 2. Booting on RW with a type-c charger. PD negotiation is
+ * done and we can boot AP.
+ */
+ CPRINTS("Got enough power");
return;
}
- if (pd_comm_is_enabled(port))
- /* Normal RW boot or unlocked RO boot.
- * Hoping enough power will be supplied after PD negotiation. */
+ if (system_get_image_copy() != SYSTEM_IMAGE_RO || !system_is_locked()) {
+ /*
+ * If we're here, it means PD negotiation was attempted but
+ * we didn't get enough power to boot AP. This happens on RW
+ * or unlocked RO.
+ *
+ * This could be caused by a weak type-c charger. If that's
+ * the case, users need to plug a better charger. We could
+ * also be here because PD negotiation is still taking place.
+ * If so, we'll briefly show request power sign but it will
+ * be immediately corrected.
+ */
+ request_power();
return;
+ }
- /* PD communication is disabled. Probably this is RO image */
- CPRINTS("PD comm disabled");
+ CPRINTS("Booting RO on weak battery/charger");
if (is_manual_recovery()) {
+ CPRINTS("Manual recovery requested");
if (battery_is_present() || has_matrix_keyboard()) {
request_power();
return;
}
- CPRINTS("Enable C%d PD communication", port);
+ /* We don't request_power because we don't want to assume all
+ * devices support a non type-c charger. We open up a security
+ * hole by allowing EC-RO to do PD negotiation but attackers
+ * don't gain meaningful advantage on devices without a matrix
+ * keyboard */
+ CPRINTS("Enable C%d PD comm", port);
pd_comm_enable(port, 1);
/* TODO: Inform PD task and make it negotiate */
return;
}
- if (!is_vboot_ec_supported() && !is_low_power_ap_boot_supported()) {
+ if (!is_vboot_ec_supported()) {
+ if (is_low_power_ap_boot_supported())
+ /* If a device supports this feature, AP's boot power
+ * threshold should be set low. That will let EC-RO
+ * boot AP and softsync take care of RW verification. */
+ return;
request_power();
return;
}
@@ -197,3 +239,5 @@ void vboot_main(void)
/* Failed to jump. Need recovery. */
request_recovery();
}
+
+DECLARE_HOOK(HOOK_INIT, vboot_main, HOOK_PRIO_DEFAULT);
diff --git a/include/vboot.h b/include/vboot.h
index 14f7a8f13c..b9f03c6423 100644
--- a/include/vboot.h
+++ b/include/vboot.h
@@ -46,14 +46,3 @@ int vboot_is_padding_valid(const uint8_t *data, uint32_t start, uint32_t end);
*/
int vboot_verify(const uint8_t *data, int len,
const struct rsa_public_key *key, const uint8_t *sig);
-
-/**
- * Verify RW image and jump to it
- *
- * Calling this API results in one of the followings:
- * 1. Returns, expecting PD will provide enough power after negotiation
- * 2. Jumps to RW (no return)
- * 3. Returns, requesting more power
- * 4. Returns, requesting recovery
- */
-void vboot_main(void);
diff --git a/power/intel_x86.c b/power/intel_x86.c
index 90a8682d7c..954ec5d29a 100644
--- a/power/intel_x86.c
+++ b/power/intel_x86.c
@@ -278,16 +278,11 @@ enum power_state common_intel_x86_power_handle_state(enum power_state state)
* because when entering S5, EC enables EC_ROP_SLP_SUS pin
* which causes (short-powered) system to brown out.
*/
- {
- if (!system_can_boot_ap()) {
- vboot_main();
- while (!system_can_boot_ap())
- /* LED blinks as HOOK_TICK events trigger.
- * We can print percent & power as they
- * improve. */
- msleep(200);
- }
- }
+ while (!system_can_boot_ap())
+ /* LED blinks as HOOK_TICK events trigger.
+ * We can print percent & power as they
+ * improve. */
+ msleep(200);
#endif
power_s5_up = 1;
return POWER_S5;