diff options
-rw-r--r-- | common/build.mk | 1 | ||||
-rw-r--r-- | common/main.c | 2 | ||||
-rw-r--r-- | common/usb_pd_protocol.c | 2 | ||||
-rw-r--r-- | common/vboot.c | 114 | ||||
-rw-r--r-- | include/usb_pd.h | 7 | ||||
-rw-r--r-- | include/vboot.h | 15 | ||||
-rw-r--r-- | power/intel_x86.c | 19 |
7 files changed, 158 insertions, 2 deletions
diff --git a/common/build.mk b/common/build.mk index 981654e761..0b339272c5 100644 --- a/common/build.mk +++ b/common/build.mk @@ -105,6 +105,7 @@ common-$(CONFIG_USB_POWER_DELIVERY)+=usb_pd_protocol.o usb_pd_policy.o common-$(CONFIG_USB_PD_LOGGING)+=pd_log.o common-$(CONFIG_USB_PD_TCPC)+=usb_pd_tcpc.o common-$(CONFIG_USB_UPDATE)+=usb_update.o update_fw.o +common-$(CONFIG_VBOOT_EC)+=vboot.o common-$(CONFIG_VBOOT_HASH)+=sha256.o vboot_hash.o common-$(CONFIG_VSTORE)+=vstore.o common-$(CONFIG_WIRELESS)+=wireless.o diff --git a/common/main.c b/common/main.c index c1f4bbdce6..a05f5808b0 100644 --- a/common/main.c +++ b/common/main.c @@ -162,6 +162,7 @@ test_mockable __keep int main(void) button_init(); #endif +#ifndef CONFIG_VBOOT_EC #if defined(CONFIG_RWSIG) && !defined(HAS_TASK_RWSIG) /* * Check the RW firmware signature and jump to it if it is good. @@ -184,6 +185,7 @@ test_mockable __keep int main(void) } } #endif +#endif /* !CONFIG_VBOOT_EC */ /* * Print the init time. Not completely accurate because it can't take diff --git a/common/usb_pd_protocol.c b/common/usb_pd_protocol.c index d3cfa0da73..8db80304e7 100644 --- a/common/usb_pd_protocol.c +++ b/common/usb_pd_protocol.c @@ -201,7 +201,7 @@ BUILD_ASSERT(ARRAY_SIZE(pd_state_names) == PD_STATE_COUNT); static struct ec_params_usb_pd_rw_hash_entry rw_hash_table[RW_HASH_ENTRIES]; #endif -static inline int pd_comm_is_enabled(int port) +int pd_comm_is_enabled(int port) { #ifdef CONFIG_COMMON_RUNTIME return pd_comm_enabled[port]; diff --git a/common/vboot.c b/common/vboot.c new file mode 100644 index 0000000000..b298a1d427 --- /dev/null +++ b/common/vboot.c @@ -0,0 +1,114 @@ +/* Copyright 2017 The Chromium OS Authors. All rights reserved. + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* + * Implementation of EC's boot verification + */ + +#include "battery.h" +#include "charge_manager.h" +#include "chipset.h" +#include "console.h" +#include "host_command.h" +#include "rwsig.h" +#include "system.h" +#include "usb_pd.h" +#include "vboot.h" + +#define CPRINTS(format, args...) cprints(CC_VBOOT, format, ## args) + +enum vboot_ec_slot { + VBOOT_EC_SLOT_A, + VBOOT_EC_SLOT_B, +}; + +static int has_matrix_keyboard(void) +{ + return 0; +} + +static int is_vboot_ec_supported(void) +{ + return 0; +} + +static int is_low_power_ap_boot_supported(void) +{ + return 0; +} + +static int verify_slot(int slot) +{ + /* TODO: Handle slot A and B */ + CPRINTS("Verifying S%d", slot); + return rwsig_check_signature(); +} + +static int verify_rw(void) +{ + uint8_t slot = VBOOT_EC_SLOT_A; + + /* 1. Read BBRAM to decide which slot to verify */ + /* 2. Verify the slot */ + return verify_slot(slot); +} + +/* Request more power: charging battery or more powerful AC adapter */ +static void request_power(void) +{ + /* TODO: Blink LED */ +} + +static void request_recovery(void) +{ + /* TODO: Blink LED */ +} + +static int is_manual_recovery(void) +{ + return host_get_events() & EC_HOST_EVENT_KEYBOARD_RECOVERY; +} + +void vboot_ec(void) +{ + 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(); + return; + } + + if (pd_comm_is_enabled(port)) + /* Normal RW boot or unlocked RO boot. + * Hoping enough power will be supplied after PD negotiation. */ + return; + + /* PD communication is disabled. Probably this is RO image */ + CPRINTS("PD comm disabled"); + + if (is_manual_recovery()) { + if (battery_is_present() || has_matrix_keyboard()) { + request_power(); + return; + } + CPRINTS("Enable C%d PD communication", 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()) { + request_power(); + return; + } + + if (verify_rw()) + /* Jump (and reboot) */ + rwsig_jump_now(); + + /* Failed to verify RW. Need recovery. */ + request_recovery(); +} diff --git a/include/usb_pd.h b/include/usb_pd.h index 8eb53c93c3..0fdf7e19fa 100644 --- a/include/usb_pd.h +++ b/include/usb_pd.h @@ -1495,6 +1495,13 @@ void pd_hw_init_rx(int port); int pd_analyze_rx(int port, uint32_t *payload); /** + * Check if PD communication is enabled + * + * @return true if it's enabled or false otherwise + */ +int pd_comm_is_enabled(int port); + +/** * Get connected state * * @param port USB-C port number diff --git a/include/vboot.h b/include/vboot.h new file mode 100644 index 0000000000..ba13328544 --- /dev/null +++ b/include/vboot.h @@ -0,0 +1,15 @@ +/* Copyright 2017 The Chromium OS Authors. All rights reserved. + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/** + * 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_ec(void); diff --git a/power/intel_x86.c b/power/intel_x86.c index f4b5251d00..cb3dc93e0e 100644 --- a/power/intel_x86.c +++ b/power/intel_x86.c @@ -20,6 +20,7 @@ #include "system.h" #include "task.h" #include "util.h" +#include "vboot.h" #include "wireless.h" /* Chipset specific header files */ @@ -180,7 +181,6 @@ enum power_state power_chipset_init(void) enum power_state common_intel_x86_power_handle_state(enum power_state state) { - switch (state) { case POWER_G3: break; @@ -270,6 +270,23 @@ enum power_state common_intel_x86_power_handle_state(enum power_state state) return POWER_G3; } +#ifdef CONFIG_VBOOT_EC + /* + * We have to test power readiness here (instead of S5->S3) + * 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_ec(); + 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; |