summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--common/build.mk1
-rw-r--r--common/main.c2
-rw-r--r--common/usb_pd_protocol.c2
-rw-r--r--common/vboot.c114
-rw-r--r--include/usb_pd.h7
-rw-r--r--include/vboot.h15
-rw-r--r--power/intel_x86.c19
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;