Add Google ChromeOS vendor support
authorStefan Reinauer <reinauer@chromium.org>
Fri, 30 Mar 2012 19:01:06 +0000 (12:01 -0700)
committerStefan Reinauer <stefan.reinauer@coreboot.org>
Mon, 2 Apr 2012 16:39:31 +0000 (18:39 +0200)
Google's ChromeOS can be booted super fast and safely
using coreboot. This adds the ChromeOS specific code that
is required by all ChromeBooks to do this.

Change-Id: Ic03ff090a569a27acbd798ce1e5f89a34897a2f2
Signed-off-by: Stefan Reinauer <reinauer@google.com>
Reviewed-on: http://review.coreboot.org/817
Tested-by: build bot (Jenkins)
Reviewed-by: Ronald G. Minnich <rminnich@gmail.com>
12 files changed:
Makefile.inc
src/vendorcode/Makefile.inc
src/vendorcode/google/Makefile.inc [new file with mode: 0644]
src/vendorcode/google/chromeos/Kconfig
src/vendorcode/google/chromeos/Makefile.inc [new file with mode: 0644]
src/vendorcode/google/chromeos/acpi/gnvs.asl [new file with mode: 0644]
src/vendorcode/google/chromeos/chromeos.c [new file with mode: 0644]
src/vendorcode/google/chromeos/chromeos.h [new file with mode: 0644]
src/vendorcode/google/chromeos/gnvs.c [new file with mode: 0644]
src/vendorcode/google/chromeos/gnvs.h [new file with mode: 0644]
src/vendorcode/google/chromeos/vbnv.c [new file with mode: 0644]
src/vendorcode/google/chromeos/vboot.c

index b4855d0b6831802b68708973045d2612079db0f0..857ad1642b90759a6b41ac78619cbdf6712aa278 100644 (file)
@@ -43,6 +43,7 @@ subdirs-y += src/northbridge src/superio src/drivers src/cpu src/vendorcode
 subdirs-y += util/cbfstool util/sconfig
 subdirs-y += src/arch/$(ARCHDIR-y)
 subdirs-y += src/mainboard/$(MAINBOARDDIR)
+subdirs-y += src/vendorcode
 
 subdirs-$(CONFIG_ARCH_X86) += src/pc80
 
index 16c0d68497098c03ecd29dd3ef768ab67d0fd67c..e6d6bb13a03b77f01bd00cfde0d4cf7517f775a5 100644 (file)
@@ -1,2 +1,2 @@
 subdirs-y += amd
-
+subdirs-y += google
diff --git a/src/vendorcode/google/Makefile.inc b/src/vendorcode/google/Makefile.inc
new file mode 100644 (file)
index 0000000..20d40a8
--- /dev/null
@@ -0,0 +1,20 @@
+##
+## This file is part of the coreboot project.
+##
+## Copyright (C) 2011 The ChromiumOS Authors.  All rights reserved.
+##
+## 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.
+##
+## You should have received a copy of the GNU General Public License
+## along with this program; if not, write to the Free Software
+## Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+##
+
+subdirs-$(CONFIG_CHROMEOS) += chromeos
index f838b74804008be9b04065a17270456313933cfb..207431d0ec2cd744637b0c9ca0cf07ef2d4fbf29 100644 (file)
@@ -22,7 +22,34 @@ config CHROMEOS
        select TPM
        select CACHE_ROM
        help
-         Enable ChromeOS specific features
+         Enable ChromeOS specific features like the GPIO sub table in
+         the coreboot table. NOTE: Enabling this option on an unsupported
+         board will most likely break your build.
 
+config VBNV_OFFSET
+       hex
+       default 0x26
+       help
+         CMOS offset for VbNv data. This value must match cmos.layout
+         in the mainboard directory, minus 14 bytes for the RTC.
+
+config VBNV_SIZE
+       hex
+       default 0x10
+       help
+         CMOS storage size for VbNv data. This value must match cmos.layout
+         in the mainboard directory.
+
+config CHROMEOS_RAMOOPS
+       bool "Reserve space for Chrome OS ramoops"
+       default y
 
+config CHROMEOS_RAMOOPS_RAM_START
+       hex "Physical address of preserved RAM"
+       default 0x00f00000
+       depends on CHROMEOS_RAMOOPS
 
+config CHROMEOS_RAMOOPS_RAM_SIZE
+       hex "Size of preserved RAM"
+       default 0x00100000
+       depends on CHROMEOS_RAMOOPS
diff --git a/src/vendorcode/google/chromeos/Makefile.inc b/src/vendorcode/google/chromeos/Makefile.inc
new file mode 100644 (file)
index 0000000..c1b1cce
--- /dev/null
@@ -0,0 +1,25 @@
+##
+## This file is part of the coreboot project.
+##
+## Copyright (C) 2011 The ChromiumOS Authors.  All rights reserved.
+##
+## 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.
+##
+## You should have received a copy of the GNU General Public License
+## along with this program; if not, write to the Free Software
+## Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+##
+
+romstage-y += chromeos.c
+ramstage-y += chromeos.c
+romstage-y += vbnv.c
+ramstage-y += vbnv.c
+romstage-y += vboot.c
+ramstage-y += gnvs.c
diff --git a/src/vendorcode/google/chromeos/acpi/gnvs.asl b/src/vendorcode/google/chromeos/acpi/gnvs.asl
new file mode 100644 (file)
index 0000000..dc4a0bf
--- /dev/null
@@ -0,0 +1,37 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2011 The ChromiumOS Authors.  All rights reserved.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+/* This is the ChromeOS specific ACPI information needed by
+ * the mainboard's chromeos.asl
+ */
+
+VBT0,   32,    // 0x000 - Boot Reason
+VBT1,   32,    // 0x004 - Active Main Firmware
+VBT2,   32,    // 0x008 - Active EC Firmware
+VBT3,   16,    // 0x00c - CHSW
+VBT4, 2048,    // 0x00e - HWID
+VBT5,  512,    // 0x10e - FWID
+VBT6,  512,    // 0x14e - FRID
+VBT7,   32,    // 0x18e - active main firmware type
+VBT8,   32,    // 0x192 - Recovery Reason
+VBT9,   32,    // 0x196 - FMAP base address
+CHVD, 24576,   // 0x19a - VDAT space filled by verified boot
+VBTA,  32,     // 0xd9a - pointer to smbios FWID
+MEHH,  256,    // 0xd9e - Management Engine Hash
+               // 0xdbe
diff --git a/src/vendorcode/google/chromeos/chromeos.c b/src/vendorcode/google/chromeos/chromeos.c
new file mode 100644 (file)
index 0000000..c1c3b38
--- /dev/null
@@ -0,0 +1,37 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2011 The ChromiumOS Authors.  All rights reserved.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "chromeos.h"
+#include <arch/coreboot_tables.h>
+#include <console/console.h>
+
+int developer_mode_enabled(void)
+{
+       return get_developer_mode_switch();
+}
+
+int recovery_mode_enabled(void)
+{
+       /* TODO(reinauer): get information from VbInit.
+        * the recovery mode switch is not the only reason to go
+        * to recovery mode.
+        */
+       return get_recovery_mode_switch() || get_recovery_mode_from_vbnv();
+}
+
diff --git a/src/vendorcode/google/chromeos/chromeos.h b/src/vendorcode/google/chromeos/chromeos.h
new file mode 100644 (file)
index 0000000..ec0f3b7
--- /dev/null
@@ -0,0 +1,40 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2011 The ChromiumOS Authors.  All rights reserved.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef __CHROMEOS_H__
+#define __CHROMEOS_H__
+
+/* functions implemented per mainboard: */
+int get_developer_mode_switch(void);
+int get_recovery_mode_switch(void);
+#ifdef __PRE_RAM__
+void save_chromeos_gpios(void);
+#endif
+
+/* functions implemented in vbnv.c: */
+int get_recovery_mode_from_vbnv(void);
+
+/* functions implemented in chromeos.c: */
+int developer_mode_enabled(void);
+int recovery_mode_enabled(void);
+
+/* functions implemented in vboot.c */
+void init_chromeos(int bootmode);
+
+#endif
diff --git a/src/vendorcode/google/chromeos/gnvs.c b/src/vendorcode/google/chromeos/gnvs.c
new file mode 100644 (file)
index 0000000..8d0f9bb
--- /dev/null
@@ -0,0 +1,88 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2011 The ChromiumOS Authors.  All rights reserved.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <types.h>
+#include <cbfs.h>
+#include <console/console.h>
+#include "gnvs.h"
+
+chromeos_acpi_t *vboot_data;
+static u32 me_hash_saved[8];
+
+void chromeos_init_vboot(chromeos_acpi_t *chromeos)
+{
+       vboot_data = chromeos;
+
+       /* Copy saved ME hash into NVS */
+       memcpy(vboot_data->mehh, me_hash_saved, sizeof(vboot_data->mehh));
+}
+
+void chromeos_set_vboot_data_ptr(void *blob)
+{
+       /* This code has to be rewritten to pass the vboot table
+        * pointer through the coreboot table instead of the 
+        * FDT, since FDT support was rejected upstream. For now
+        * just make the code available for reference.
+        */
+#if 0 // CONFIG_ADD_FDT
+       int node_offset, addr_cell_len;
+       const u32 *cell;
+       uintptr_t table_addr = (uintptr_t)vboot_data;
+       u32 table_addr32;
+       u64 table_addr64;
+       void *table_ptr;
+
+       cell = fdt_getprop(blob, 0, "#address-cells", NULL);
+       if (cell && *cell == 2) {
+               addr_cell_len = 8;
+               table_addr64 = cpu_to_fdt64(table_addr);
+               table_ptr = &table_addr64;
+       } else {
+               addr_cell_len = 4;
+               table_addr32 = cpu_to_fdt32(table_addr);
+               table_ptr = &table_addr32;
+       }
+
+       node_offset = fdt_path_offset(blob, "/chromeos-config");
+       if (node_offset < 0) {
+               printk(BIOS_ERR,
+                       "Couldn't find /chromeos-config in the fdt.\n");
+               return;
+       }
+
+       if (fdt_setprop(blob, node_offset, "gnvs-vboot-table",
+                       table_ptr, addr_cell_len) < 0) {
+               printk(BIOS_ERR, "Couldn't set gnvs-vboot-table.\n");
+       }
+#else
+       printk(BIOS_ERR, "Can't set gnvs-vboot-table.\n");
+#endif
+}
+
+void chromeos_set_me_hash(u32 *hash, int len)
+{
+       if ((len*sizeof(u32)) > sizeof(vboot_data->mehh))
+               return;
+
+       /* Copy to NVS or save until it is ready */
+       if (vboot_data)
+               memcpy(vboot_data->mehh, hash, len*sizeof(u32));
+       else
+               memcpy(me_hash_saved, hash, len*sizeof(u32));
+}
diff --git a/src/vendorcode/google/chromeos/gnvs.h b/src/vendorcode/google/chromeos/gnvs.h
new file mode 100644 (file)
index 0000000..36922ba
--- /dev/null
@@ -0,0 +1,69 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2011 The ChromiumOS Authors.  All rights reserved.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef __VENDORCODE_GOOGLE_CHROMEOS_GNVS_H
+#define __VENDORCODE_GOOGLE_CHROMEOS_GNVS_H
+
+#define BOOT_REASON_OTHER      0
+#define BOOT_REASON_S3DIAG     9
+
+#define CHSW_RECOVERY_X86      (1 << 1)
+#define CHSW_RECOVERY_EC       (1 << 2)
+#define CHSW_DEVELOPER_SWITCH  (1 << 5)
+#define CHSW_FIRMWARE_WP_DIS   (1 << 9)
+
+#define ACTIVE_MAINFW_RECOVERY 0
+#define ACTIVE_MAINFW_RW_A     1
+#define ACTIVE_MAINFW_RW_B     2
+
+#define ACTIVE_MAINFW_TYPE_RECOVERY    0
+#define ACTIVE_MAINFW_TYPE_NORMAL      1
+#define ACTIVE_MAINFW_TYPE_DEVELOPER   2
+
+#define RECOVERY_REASON_NONE   0
+#define RECOVERY_REASON_ME     1
+// TODO(reinauer) other recovery reasons?
+
+#define ACTIVE_ECFW_RO         0
+#define ACTIVE_ECFW_RW         1
+
+typedef struct {
+       /* ChromeOS specific */
+       u32     vbt0;           // 00 boot reason
+       u32     vbt1;           // 04 active main firmware
+       u32     vbt2;           // 08 active ec firmware
+       u16     vbt3;           // 0c CHSW
+       u8      vbt4[256];      // 0e HWID
+       u8      vbt5[64];       // 10e FWID
+       u8      vbt6[64];       // 14e FRID - 275
+       u32     vbt7;           // 18e active main firmware type
+       u32     vbt8;           // 192 recovery reason
+       u32     vbt9;           // 196 fmap base address
+       u8      vdat[3072];     // 19a
+       u32     vbt10;          // d9a smbios bios version
+       u32     mehh[8];        // d9e management engine hash
+                               // dbe
+} __attribute__((packed)) chromeos_acpi_t;
+
+extern chromeos_acpi_t *vboot_data;
+void chromeos_init_vboot(chromeos_acpi_t *chromeos);
+void chromeos_set_vboot_data_ptr(void *);
+void chromeos_set_me_hash(u32*, int);
+
+#endif
diff --git a/src/vendorcode/google/chromeos/vbnv.c b/src/vendorcode/google/chromeos/vbnv.c
new file mode 100644 (file)
index 0000000..2129461
--- /dev/null
@@ -0,0 +1,109 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2011 The ChromiumOS Authors.  All rights reserved.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <types.h>
+#include <string.h>
+#include <console/console.h>
+#include <pc80/mc146818rtc.h>
+#include <cpu/x86/car.h>
+#include "chromeos.h"
+
+#define VBNV_BLOCK_SIZE 16     /* Size of NV storage block in bytes */
+
+/* Constants for NV storage.  We use this rather than structs and
+ * bitfields so the data format is consistent across platforms and
+ * compilers.
+ */
+#define HEADER_OFFSET                0
+#define HEADER_MASK                     0xC0
+#define HEADER_SIGNATURE                0x40
+#define HEADER_FIRMWARE_SETTINGS_RESET  0x20
+#define HEADER_KERNEL_SETTINGS_RESET    0x10
+
+#define BOOT_OFFSET                  1
+#define BOOT_DEBUG_RESET_MODE           0x80
+#define BOOT_TRY_B_COUNT_MASK           0x0F
+
+#define RECOVERY_OFFSET              2
+#define LOCALIZATION_OFFSET          3
+
+#define DEV_FLAGS_OFFSET             4
+#define DEV_BOOT_USB_MASK               0x01
+
+#define FIRMWARE_FLAGS_OFFSET        5
+#define FIRMWARE_TEST_ERR_FUNC_MASK     0x38
+#define FIRMWARE_TEST_ERR_FUNC_SHIFT    3
+#define FIRMWARE_TEST_ERR_NUM_MASK      0x07
+
+#define KERNEL_FIELD_OFFSET         11
+#define CRC_OFFSET                  15
+
+static int vbnv_initialized CAR_GLOBAL;
+uint8_t vbnv[CONFIG_VBNV_SIZE] CAR_GLOBAL;
+
+/* Return CRC-8 of the data, using x^8 + x^2 + x + 1 polynomial.  A
+ * table-based algorithm would be faster, but for only 15 bytes isn't
+ * worth the code size.
+ */
+
+static uint8_t crc8(const uint8_t * data, int len)
+{
+       unsigned crc = 0;
+       int i, j;
+
+       for (j = len; j; j--, data++) {
+               crc ^= (*data << 8);
+               for (i = 8; i; i--) {
+                       if (crc & 0x8000)
+                               crc ^= (0x1070 << 3);
+                       crc <<= 1;
+               }
+       }
+
+       return (uint8_t) (crc >> 8);
+}
+
+static void vbnv_setup(void)
+{
+       int i;
+
+       for (i = 0; i < CONFIG_VBNV_SIZE; i++)
+               vbnv[i] = cmos_read(CONFIG_VBNV_OFFSET + 14 + i);
+
+       /* Check data for consistency */
+       if ((HEADER_SIGNATURE != (vbnv[HEADER_OFFSET] & HEADER_MASK))
+           || (crc8(vbnv, CRC_OFFSET) != vbnv[CRC_OFFSET])) {
+
+               /* Data is inconsistent (bad CRC or header),
+                * so reset to defaults
+                */
+               memset(vbnv, 0, VBNV_BLOCK_SIZE);
+               vbnv[HEADER_OFFSET] =
+                   (HEADER_SIGNATURE | HEADER_FIRMWARE_SETTINGS_RESET |
+                    HEADER_KERNEL_SETTINGS_RESET);
+       }
+       vbnv_initialized = 1;
+}
+
+int get_recovery_mode_from_vbnv(void)
+{
+       if (!vbnv_initialized)
+               vbnv_setup();
+       return vbnv[RECOVERY_OFFSET];
+}
index e0a8c9b336fb67651c6a1e61536b9b9a0688366b..5bdb7a2b7a37548719384d4d404059076ec659fc 100644 (file)
 #include <console/console.h>
 #include <arch/acpi.h>
 #include <pc80/tpm.h>
+#include <reset.h>
 #include "chromeos.h"
 
 //#define EXTRA_LOGGING
+#define UBOOT_DOES_TPM_STARTUP
 
 #define TPM_LARGE_ENOUGH_COMMAND_SIZE 256      /* saves space in the firmware */
 
@@ -43,6 +45,12 @@ static const struct {
        { 0x0, 0xc1, 0x0, 0x0, 0x0, 0xc, 0x0, 0x0, 0x0, 0x99, 0x0, 0x2 }
 };
 
+static const struct {
+       u8 buffer[12];
+} tpm_startup_cmd = {
+       {0x0, 0xc1, 0x0, 0x0, 0x0, 0xc, 0x0, 0x0, 0x0, 0x99, 0x0, 0x1 }
+};
+
 static const struct {
        u8 buffer[10];
 } tpm_continueselftest_cmd = {
@@ -169,33 +177,60 @@ static u32 TlclSendReceive(const u8 * request, u8 * response, int max_length)
        return result;
 }
 
-void init_vboot(void)
+static void init_vboot(int bootmode)
 {
        u32 result;
        u8 response[TPM_LARGE_ENOUGH_COMMAND_SIZE];
 
-       printk(BIOS_DEBUG, "TPM: Init\n");
+#ifdef UBOOT_DOES_TPM_STARTUP
+       /* Doing TPM startup when we're not coming in on the S3 resume path
+        * saves us roughly 20ms in boot time only. This does not seem to
+        * be worth an API change to vboot_reference-firmware right now, so
+        * let's keep the code around, but just bail out early:
+        */
+       if (bootmode != 2)
+               return;
+#endif
+
+       printk(BIOS_DEBUG, "Verified boot TPM initialization.\n");
+
+       printk(BIOS_SPEW, "TPM: Init\n");
        if (tis_init())
                return;
 
-       printk(BIOS_DEBUG, "TPM: Open\n");
+       printk(BIOS_SPEW, "TPM: Open\n");
        if (tis_open())
                return;
 
-       printk(BIOS_DEBUG, "TPM: Resume\n");
 
-       result =
-           TlclSendReceive(tpm_resume_cmd.buffer, response, sizeof(response));
-
-       if (result == TPM_E_INVALID_POSTINIT) {
-               /* We're on a platform where the TPM maintains power in S3, so
-                * it's already initialized. */
-               printk(BIOS_DEBUG, "TPM: Already initialized.\n");
-               return;
+       if (bootmode == 2) {
+               /* S3 Resume */
+               printk(BIOS_SPEW, "TPM: Resume\n");
+               result = TlclSendReceive(tpm_resume_cmd.buffer,
+                                       response, sizeof(response));
+               if (result == TPM_E_INVALID_POSTINIT) {
+                       /* We're on a platform where the TPM maintains power
+                        * in S3, so it's already initialized.
+                        */
+                       printk(BIOS_DEBUG, "TPM: Already initialized.\n");
+                       return;
+               }
+       } else {
+               printk(BIOS_SPEW, "TPM: Startup\n");
+               result = TlclSendReceive(tpm_startup_cmd.buffer,
+                                       response, sizeof(response));
        }
+
        if (result == TPM_SUCCESS) {
-               printk(BIOS_DEBUG, "TPM: OK.\n");
+               printk(BIOS_SPEW, "TPM: OK.\n");
                return;
        }
-       // TODO(reinauer) hard reboot?
+
+       printk(BIOS_ERR, "TPM: Error code 0x%x. Hard reset!\n", result);
+       hard_reset();
+}
+
+void init_chromeos(int bootmode)
+{
+       init_vboot(bootmode);
 }