aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVadim Bendebury <vbendeb@chromium.org>2017-03-22 16:16:34 -0700
committerAaron Durbin <adurbin@chromium.org>2017-05-05 23:24:20 +0200
commitb9126fe46cb7432b9d9d1f4ca8b557e50e303380 (patch)
tree5e6905ba730f62bb6e9ecf3462ad262ce74a2fef
parentc623aa055d590501e14669277bfa3ba46c5ec22b (diff)
cr50: check if the new image needs to be enabled and act on it
The AP sends the Cr50 a request to enable the new firmware image. If the new Cr50 image was found and enabled, the AP expects the Cr50 to reset the device in 1 second. While waiting for the Cr50 to reset, the AP logs a newly defined event and optionally shuts down the system. By default the x86 systems power off as shutting those systems down is not board specific. BRANCH=gru,reef BUG=b:35580805 TEST=built a reef image, observed that in case cr50 image is updated, after the next reboot the AP stops booting before loading depthcharge, reports upcoming reset and waits for it. Once the system is booted after that, the new event can be found in the log: localhost ~ # mosys eventlog list ... 7 | 2017-03-23 18:42:12 | Chrome OS Developer Mode 8 | 2017-03-23 18:42:13 | Unknown | 0xac 9 | 2017-03-23 18:42:21 | System boot | 46 ... Change-Id: I45fd6058c03f32ff8edccd56ca2aa5359d9b21b1 Signed-off-by: Vadim Bendebury <vbendeb@chromium.org> Signed-off-by: Aaron Durbin <adurbin@chromium.org> Reviewed-on: https://review.coreboot.org/18946 Tested-by: build bot (Jenkins) <no-reply@coreboot.org> Reviewed-by: Furquan Shaikh <furquan@google.com>
-rw-r--r--src/Kconfig6
-rw-r--r--src/include/elog.h4
-rw-r--r--src/vendorcode/google/chromeos/Makefile.inc1
-rw-r--r--src/vendorcode/google/chromeos/cr50_enable_update.c71
4 files changed, 82 insertions, 0 deletions
diff --git a/src/Kconfig b/src/Kconfig
index 49f8672ff2..ffaf7eb25e 100644
--- a/src/Kconfig
+++ b/src/Kconfig
@@ -406,11 +406,17 @@ config TPM2
If unsure, say N.
+config POWER_OFF_ON_CR50_UPDATE
+ bool
+ help
+ Power off machine while waiting for CR50 update to take effect.
+
config MAINBOARD_HAS_TPM_CR50
bool
default y if MAINBOARD_HAS_SPI_TPM_CR50 || MAINBOARD_HAS_I2C_TPM_CR50
default n
select MAINBOARD_HAS_TPM2
+ select POWER_OFF_ON_CR50_UPDATE if ARCH_X86
config HEAP_SIZE
hex
diff --git a/src/include/elog.h b/src/include/elog.h
index f532ddab70..964e04099d 100644
--- a/src/include/elog.h
+++ b/src/include/elog.h
@@ -122,6 +122,7 @@
#define ELOG_WAKE_SOURCE_GPIO 0x04
#define ELOG_WAKE_SOURCE_SMBUS 0x05
#define ELOG_WAKE_SOURCE_PWRBTN 0x06
+
struct elog_event_data_wake {
u8 source;
u32 instance;
@@ -174,6 +175,9 @@ struct elog_event_mem_cache_update {
/* CPU Thermal Trip */
#define ELOG_TYPE_THERM_TRIP 0xab
+/* Cr50 */
+#define ELOG_TYPE_CR50_UPDATE 0xac
+
#if CONFIG_ELOG
/* Eventlog backing storage must be initialized before calling elog_init(). */
extern int elog_init(void);
diff --git a/src/vendorcode/google/chromeos/Makefile.inc b/src/vendorcode/google/chromeos/Makefile.inc
index 22352ef243..9d87f6eae3 100644
--- a/src/vendorcode/google/chromeos/Makefile.inc
+++ b/src/vendorcode/google/chromeos/Makefile.inc
@@ -22,6 +22,7 @@ ramstage-y += vpd_decode.c cros_vpd.c vpd_mac.c vpd_serialno.c vpd_calibration.c
ramstage-$(CONFIG_CHROMEOS_DISABLE_PLATFORM_HIERARCHY_ON_RESUME) += tpm2.c
ramstage-$(CONFIG_HAVE_REGULATORY_DOMAIN) += wrdd.c
ramstage-$(CONFIG_USE_SAR) += sar.c
+ramstage-$(CONFIG_MAINBOARD_HAS_TPM_CR50) += cr50_enable_update.c
ifeq ($(CONFIG_ARCH_MIPS),)
bootblock-y += watchdog.c
ramstage-y += watchdog.c
diff --git a/src/vendorcode/google/chromeos/cr50_enable_update.c b/src/vendorcode/google/chromeos/cr50_enable_update.c
new file mode 100644
index 0000000000..e962f194cd
--- /dev/null
+++ b/src/vendorcode/google/chromeos/cr50_enable_update.c
@@ -0,0 +1,71 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright 2017 Google Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <bootstate.h>
+#include <console/console.h>
+#include <ec/google/chromeec/ec.h>
+#include <elog.h>
+#include <halt.h>
+#include <tpm_lite/tlcl.h>
+#include <vb2_api.h>
+#include <vboot/vboot_common.h>
+
+static void enable_update(void *unused)
+{
+ int ret;
+ uint8_t num_restored_headers;
+
+ /* Nothing to do on recovery mode. */
+ if (vboot_recovery_mode_enabled())
+ return;
+
+ ret = tlcl_lib_init();
+
+ if (ret != VB2_SUCCESS) {
+ printk(BIOS_ERR, "tlcl_lib_init() failed for CR50 update: %x\n",
+ ret);
+ return;
+ }
+
+ /* Reboot in 1000 ms if necessary. */
+ ret = tlcl_cr50_enable_update(1000, &num_restored_headers);
+
+ if (ret != TPM_SUCCESS) {
+ printk(BIOS_ERR, "Attempt to enable CR50 update failed: %x\n",
+ ret);
+ return;
+ }
+
+ /* If no headers were restored there is no reset forthcoming. */
+ if (!num_restored_headers)
+ return;
+
+ elog_add_event(ELOG_TYPE_CR50_UPDATE);
+
+ /* clear current post code avoid chatty eventlog on subsequent boot*/
+ post_code(0);
+
+ printk(BIOS_INFO, "Waiting for CR50 reset to pick up update.\n");
+
+ if (IS_ENABLED(CONFIG_POWER_OFF_ON_CR50_UPDATE)) {
+ if (IS_ENABLED(CONFIG_EC_GOOGLE_CHROMEEC))
+ google_chromeec_reboot(0, EC_REBOOT_HIBERNATE,
+ EC_REBOOT_FLAG_ON_AP_SHUTDOWN);
+ poweroff();
+ }
+ halt();
+}
+BOOT_STATE_INIT_ENTRY(BS_PAYLOAD_LOAD, BS_ON_ENTRY, enable_update, NULL);
+