From 921e9b71258c318f364457d97a94d3fb9e1bbbfc Mon Sep 17 00:00:00 2001 From: Daisuke Nojiri Date: Wed, 12 Jul 2017 11:12:58 -0700 Subject: 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 Reviewed-on: https://chromium-review.googlesource.com/568699 Reviewed-by: Randall Spangler --- board/fizz/ec.tasklist | 4 +-- common/system.c | 8 ++---- common/vboot/vboot.c | 72 ++++++++++++++++++++++++++++++++++++++++---------- include/vboot.h | 11 -------- power/intel_x86.c | 15 ++++------- 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; -- cgit v1.2.1