Aaron Durbin (adurbin(a)google.com) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/9435
-gerrit
commit 147adcb722265ccc1771cd66e7457560aea4a278
Author: Vadim Bendebury <vbendeb(a)chromium.org>
Date: Thu Oct 23 16:02:51 2014 -0700
chromeos: Add a function to copy VPD WiFi calibration data to CBMEM
This patch adds functions looking in the VPD for WiFi calibration
data, and if found, copying the calibration blobs into CBMEM.
Two possible key names templates are used: wifi_base64_calibrationX
and wifi_calibrationX, where X is replaced by the WiFi interface
number. Up to four interfaces can be provisioned.
The calibration data will be retrieved from CBMEM by the bootloader
and placed into the device tree before starting the kernel.
The structure of the WiFi calibration data CBMEM entry is defined
locally: it is a concatenation of the blob names and their contents.
Each blob is padded as necessary to make sure that the size divisible
by four.
To make sure that the exactly required amount of memory is allocated
for the CBMEM entry, the function first scans the VPD, caching the
information about the available blobs and calculating their combined
size.
Then the required size CBMEM entry is allocates and the blobs are
copied into it.
BRANCH=storm
BUG=chrome-os-partner:32611
TEST=when this function is called, and the VPD includes calibration
data blobs, the WIFI entry shows up in the list of CBMEM entries
reported by coreboot.
Original-Change-Id: Ibe02dc36ff6254e3b9ad0a5bd2696ca29e1b2be3
Original-Signed-off-by: Vadim Bendebury <vbendeb(a)chromium.org>
Original-Reviewed-on: https://chromium-review.googlesource.com/225271
Original-Reviewed-by: Aaron Durbin <adurbin(a)chromium.org>
(cherry picked from commit 9fe185ae5fdc1a896bf892b498bff27a3462caeb)
Signed-off-by: Aaron Durbin <adurbin(a)chromium.org>
Change-Id: Ia60f0c5c84decf9854426c4f0cb88f8ccee69046
---
src/vendorcode/google/chromeos/Makefile.inc | 2 +-
src/vendorcode/google/chromeos/chromeos.h | 2 +
src/vendorcode/google/chromeos/vpd_calibration.c | 197 +++++++++++++++++++++++
3 files changed, 200 insertions(+), 1 deletion(-)
diff --git a/src/vendorcode/google/chromeos/Makefile.inc b/src/vendorcode/google/chromeos/Makefile.inc
index c325bcc..027f4aa 100644
--- a/src/vendorcode/google/chromeos/Makefile.inc
+++ b/src/vendorcode/google/chromeos/Makefile.inc
@@ -29,7 +29,7 @@ ramstage-y += fmap.c
ramstage-$(CONFIG_CHROMEOS_RAMOOPS) += ramoops.c
smm-y += fmap.c
romstage-y += vpd_decode.c cros_vpd.c
-ramstage-y += vpd_decode.c cros_vpd.c
+ramstage-y += vpd_decode.c cros_vpd.c vpd_calibration.c
ifeq ($(MOCK_TPM),1)
CFLAGS_common += -DMOCK_TPM=1
diff --git a/src/vendorcode/google/chromeos/chromeos.h b/src/vendorcode/google/chromeos/chromeos.h
index 5ba5457..13a4fe3 100644
--- a/src/vendorcode/google/chromeos/chromeos.h
+++ b/src/vendorcode/google/chromeos/chromeos.h
@@ -83,4 +83,6 @@ static inline void chromeos_ram_oops_init(chromeos_acpi_t *chromeos) {}
static inline void chromeos_reserve_ram_oops(struct device *dev, int idx) {}
#endif /* CONFIG_CHROMEOS_RAMOOPS */
+void cbmem_add_vpd_calibration_data(void);
+
#endif /* __CHROMEOS_H__ */
diff --git a/src/vendorcode/google/chromeos/vpd_calibration.c b/src/vendorcode/google/chromeos/vpd_calibration.c
new file mode 100644
index 0000000..3bfd843
--- /dev/null
+++ b/src/vendorcode/google/chromeos/vpd_calibration.c
@@ -0,0 +1,197 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright 2014 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.
+ *
+ * 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 <cbmem.h>
+#include <console/console.h>
+#include <string.h>
+
+#include <vendorcode/google/chromeos/chromeos.h>
+#include <vendorcode/google/chromeos/cros_vpd.h>
+
+/*
+ * This file provides functions looking in the VPD for WiFi calibration data,
+ * and if found, copying the calibration blobs into CBMEM.
+ *
+ * Per interface calibration data is stored in the VPD in opaque blobs. The
+ * keys of the blobs follow one of two possible patterns:
+ * "wifi_base64_calibration<N>" or "wifi_calibration<N>", where <N> is the
+ * interface number.
+ *
+ * This function accommodates up to 4 interfaces. All calibration blobs found
+ * in the VPD are packed into a single CBMEM entry as describe by the
+ * structures below:
+ */
+
+/* This structure describes a single calibration data blob */
+struct calibration_blob {
+ uint32_t blob_size; /* Total size. rounded up to fall on a 4 byte
+ boundary. */
+ uint32_t key_size; /* Size of the name of this entry, \0 included. */
+ uint32_t value_size; /* Size of the value of this entry */
+ /* Zero terminated name(key) goes here, immediately followed by value */
+};
+
+/*
+ * This is the structure of the CBMEM entry containing WiFi calibration blobs.
+ * It starts with the total size (header size included) followed by an
+ * arbitrary number of concatenated 4 byte aligned calibration blobs.
+ */
+struct calibration_entry {
+ uint32_t size;
+ struct calibration_blob entries[0]; /* A varialble size container. */
+};
+
+
+#define MAX_WIFI_INTERFACE_COUNT 4
+
+/*
+ * Structure of the cache to keep information about calibration blobs present
+ * in the VPD, one cache entry per VPD blob.
+ *
+ * Maintaing the cache allows to scan the VPD once, determine the CBMEM entry
+ * memory requirements, then allocate as much room as necessary and fill it
+ * up.
+ */
+struct vpd_blob_cache_t {
+ /* The longest name template must fit with an extra character. */
+ char key_name[40];
+ const void *value_pointer;
+ unsigned blob_size;
+ unsigned key_size;
+ unsigned value_size;
+};
+
+static const char * const templates[] = {
+ "wifi_base64_calibrationX",
+ "wifi_calibrationX"
+};
+
+/*
+ * Scan the VPD for WiFi calibration data, checking for all possible key names
+ * and caching discovered blobs.
+ *
+ * Return the sum of sizes of all blobs, as stored in CBMEM.
+ */
+static size_t fill_up_entries_cache(struct vpd_blob_cache_t *cache,
+ size_t max_entries, size_t *filled_entries)
+{
+ int i;
+ int cbmem_entry_size = 0;
+ size_t used_entries = 0;
+
+
+ for (i = 0;
+ (i < ARRAY_SIZE(templates)) && (used_entries < max_entries);
+ i++) {
+ int j;
+ const int index_location = strlen(templates[i]) - 1;
+ const int key_length = index_location + 2;
+
+ if (key_length > sizeof(cache->key_name))
+ continue;
+
+ for (j = 0; j < MAX_WIFI_INTERFACE_COUNT; j++) {
+ const void *payload;
+ int payload_size;
+
+ strcpy(cache->key_name, templates[i]);
+ cache->key_name[index_location] = j + '0';
+
+ payload = cros_vpd_find(cache->key_name, &payload_size);
+ if (!payload)
+ continue;
+
+ cache->value_pointer = payload;
+ cache->key_size = key_length;
+ cache->value_size = payload_size;
+ cache->blob_size =
+ ALIGN(sizeof(struct calibration_blob) +
+ cache->key_size +
+ cache->value_size, 4);
+ cbmem_entry_size += cache->blob_size;
+
+ used_entries++;
+ if (used_entries == max_entries)
+ break;
+
+ cache++;
+ }
+ }
+
+ *filled_entries = used_entries;
+ return cbmem_entry_size;
+}
+
+void cbmem_add_vpd_calibration_data(void)
+{
+ size_t cbmem_entry_size, filled_entries;
+ struct calibration_entry *cbmem_entry;
+ struct calibration_blob *cal_blob;
+ int i;
+ /*
+ * Allocate one more cache entry than max required, to make sure that
+ * the last entry can be identified by the key size of zero.
+ */
+ struct vpd_blob_cache_t vpd_blob_cache[ARRAY_SIZE(templates) *
+ MAX_WIFI_INTERFACE_COUNT];
+
+ cbmem_entry_size = fill_up_entries_cache(vpd_blob_cache,
+ ARRAY_SIZE(vpd_blob_cache),
+ &filled_entries);
+
+ if (!cbmem_entry_size)
+ return; /* No calibration data found in the VPD. */
+
+ cbmem_entry_size += sizeof(struct calibration_entry);
+ cbmem_entry = cbmem_add(CBMEM_ID_WIFI_CALIBRATION, cbmem_entry_size);
+ if (!cbmem_entry) {
+ printk(BIOS_ERR, "%s: no room in cbmem to add %zd bytes\n",
+ __func__, cbmem_entry_size);
+ return;
+ }
+
+ cbmem_entry->size = cbmem_entry_size;
+
+ /* Copy cached data into the CBMEM entry. */
+ cal_blob = cbmem_entry->entries;
+
+ for (i = 0; i < filled_entries; i++) {
+ /* Use this as a pointer to the current cache entry. */
+ struct vpd_blob_cache_t *cache = vpd_blob_cache + i;
+ char *pointer;
+
+ cal_blob->blob_size = cache->blob_size;
+ cal_blob->key_size = cache->key_size;
+ cal_blob->value_size = cache->value_size;
+
+ /* copy the key */
+ pointer = (char *)(cal_blob + 1);
+ memcpy(pointer, cache->key_name, cache->key_size);
+
+ /* and the value */
+ pointer += cache->key_size;
+ memcpy(pointer, cache->value_pointer, cache->value_size);
+
+ printk(BIOS_INFO, "%s: added %s to CBMEM\n",
+ __func__, cache->key_name);
+
+ cal_blob = (struct calibration_blob *)
+ ((char *)cal_blob + cal_blob->blob_size);
+ }
+}
Aaron Durbin (adurbin(a)google.com) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/9435
-gerrit
commit dc557047f86f0a4e22bba6702f6f41b3661e5950
Author: Vadim Bendebury <vbendeb(a)chromium.org>
Date: Thu Oct 23 16:02:51 2014 -0700
chromeos: Add a function to copy VPD WiFi calibration data to CBMEM
This patch adds functions looking in the VPD for WiFi calibration
data, and if found, copying the calibration blobs into CBMEM.
Two possible key names templates are used: wifi_base64_calibrationX
and wifi_calibrationX, where X is replaced by the WiFi interface
number. Up to four interfaces can be provisioned.
The calibration data will be retrieved from CBMEM by the bootloader
and placed into the device tree before starting the kernel.
The structure of the WiFi calibration data CBMEM entry is defined
locally: it is a concatenation of the blob names and their contents.
Each blob is padded as necessary to make sure that the size divisible
by four.
To make sure that the exactly required amount of memory is allocated
for the CBMEM entry, the function first scans the VPD, caching the
information about the available blobs and calculating their combined
size.
Then the required size CBMEM entry is allocates and the blobs are
copied into it.
BRANCH=storm
BUG=chrome-os-partner:32611
TEST=when this function is called, and the VPD includes calibration
data blobs, the WIFI entry shows up in the list of CBMEM entries
reported by coreboot.
Original-Change-Id: Ibe02dc36ff6254e3b9ad0a5bd2696ca29e1b2be3
Original-Signed-off-by: Vadim Bendebury <vbendeb(a)chromium.org>
Original-Reviewed-on: https://chromium-review.googlesource.com/225271
Original-Reviewed-by: Aaron Durbin <adurbin(a)chromium.org>
(cherry picked from commit 9fe185ae5fdc1a896bf892b498bff27a3462caeb)
Signed-off-by: Aaron Durbin <adurbin(a)chromium.org>
Change-Id: Ia60f0c5c84decf9854426c4f0cb88f8ccee69046
---
src/vendorcode/google/chromeos/Makefile.inc | 2 +-
src/vendorcode/google/chromeos/chromeos.h | 2 +
src/vendorcode/google/chromeos/vpd_calibration.c | 197 +++++++++++++++++++++++
3 files changed, 200 insertions(+), 1 deletion(-)
diff --git a/src/vendorcode/google/chromeos/Makefile.inc b/src/vendorcode/google/chromeos/Makefile.inc
index c325bcc..027f4aa 100644
--- a/src/vendorcode/google/chromeos/Makefile.inc
+++ b/src/vendorcode/google/chromeos/Makefile.inc
@@ -29,7 +29,7 @@ ramstage-y += fmap.c
ramstage-$(CONFIG_CHROMEOS_RAMOOPS) += ramoops.c
smm-y += fmap.c
romstage-y += vpd_decode.c cros_vpd.c
-ramstage-y += vpd_decode.c cros_vpd.c
+ramstage-y += vpd_decode.c cros_vpd.c vpd_calibration.c
ifeq ($(MOCK_TPM),1)
CFLAGS_common += -DMOCK_TPM=1
diff --git a/src/vendorcode/google/chromeos/chromeos.h b/src/vendorcode/google/chromeos/chromeos.h
index 5ba5457..13a4fe3 100644
--- a/src/vendorcode/google/chromeos/chromeos.h
+++ b/src/vendorcode/google/chromeos/chromeos.h
@@ -83,4 +83,6 @@ static inline void chromeos_ram_oops_init(chromeos_acpi_t *chromeos) {}
static inline void chromeos_reserve_ram_oops(struct device *dev, int idx) {}
#endif /* CONFIG_CHROMEOS_RAMOOPS */
+void cbmem_add_vpd_calibration_data(void);
+
#endif /* __CHROMEOS_H__ */
diff --git a/src/vendorcode/google/chromeos/vpd_calibration.c b/src/vendorcode/google/chromeos/vpd_calibration.c
new file mode 100644
index 0000000..1bccf5a
--- /dev/null
+++ b/src/vendorcode/google/chromeos/vpd_calibration.c
@@ -0,0 +1,197 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright 2014 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.
+ *
+ * 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 <cbmem.h>
+#include <console/console.h>
+#include <string.h>
+
+#include <vendorcode/google/chromeos/chromeos.h>
+#include <vendorcode/google/chromeos/cros_vpd.h>
+
+/*
+ * This file provides functions looking in the VPD for WiFi calibration data,
+ * and if found, copying the calibration blobs into CBMEM.
+ *
+ * Per interface calibration data is stored in the VPD in opaque blobs. The
+ * keys of the blobs follow one of two possible patterns:
+ * "wifi_base64_calibration<N>" or "wifi_calibration<N>", where <N> is the
+ * interface number.
+ *
+ * This function accommodates up to 4 interfaces. All calibration blobs found
+ * in the VPD are packed into a single CBMEM entry as describe by the
+ * structures below:
+ */
+
+/* This structure describes a single calibration data blob */
+struct calibration_blob {
+ uint32_t blob_size; /* Total size. rounded up to fall on a 4 byte
+ boundary. */
+ uint32_t key_size; /* Size of the name of this entry, \0 included. */
+ uint32_t value_size; /* Size of the value of this entry */
+ /* Zero terminated name(key) goes here, immediately followed by value */
+};
+
+/*
+ * This is the structure of the CBMEM entry containing WiFi calibration blobs.
+ * It starts with the total size (header size included) followed by an
+ * arbitrary number of concatenated 4 byte aligned calibration blobs.
+ */
+struct calibration_entry {
+ uint32_t size;
+ struct calibration_blob entries[0]; /* A varialble size container. */
+};
+
+
+#define MAX_WIFI_INTERFACE_COUNT 4
+
+/*
+ * Structure of the cache to keep information about calibration blobs present
+ * in the VPD, one cache entry per VPD blob.
+ *
+ * Maintaing the cache allows to scan the VPD once, determine the CBMEM entry
+ * memory requirements, then allocate as much room as necessary and fill it
+ * up.
+ */
+struct vpd_blob_cache_t {
+ /* The longest name template must fit with an extra character. */
+ char key_name[40];
+ const void *value_pointer;
+ unsigned blob_size;
+ unsigned key_size;
+ unsigned value_size;
+};
+
+static const char * const templates[] = {
+ "wifi_base64_calibrationX",
+ "wifi_calibrationX"
+};
+
+/*
+ * Scan the VPD for WiFi calibration data, checking for all possible key names
+ * and caching discovered blobs.
+ *
+ * Return the sum of sizes of all blobs, as stored in CBMEM.
+ */
+static size_t fill_up_entries_cache(struct vpd_blob_cache_t *cache,
+ size_t max_entries, size_t *filled_entries)
+{
+ int i;
+ int cbmem_entry_size = 0;
+ size_t used_entries = 0;
+
+
+ for (i = 0;
+ (i < ARRAY_SIZE(templates)) && (used_entries < max_entries);
+ i++) {
+ int j;
+ const int index_location = strlen(templates[i]) - 1;
+ const int key_length = index_location + 2;
+
+ if (key_length > sizeof(cache->key_name))
+ continue;
+
+ for (j = 0; j < MAX_WIFI_INTERFACE_COUNT; j++) {
+ const void *payload;
+ int payload_size;
+
+ strcpy(cache->key_name, templates[i]);
+ cache->key_name[index_location] = j + '0';
+
+ payload = cros_vpd_find(cache->key_name, &payload_size);
+ if (!payload)
+ continue;
+
+ cache->value_pointer = payload;
+ cache->key_size = key_length;
+ cache->value_size = payload_size;
+ cache->blob_size =
+ ALIGN(sizeof(struct calibration_blob) +
+ cache->key_size +
+ cache->value_size, 4);
+ cbmem_entry_size += cache->blob_size;
+
+ used_entries++;
+ if (used_entries == max_entries)
+ break;
+
+ cache++;
+ }
+ }
+
+ *filled_entries = used_entries;
+ return cbmem_entry_size;
+}
+
+void cbmem_add_vpd_calibration_data(void)
+{
+ size_t cbmem_entry_size, filled_entries;
+ struct calibration_entry *cbmem_entry;
+ struct calibration_blob *cal_blob;
+ int i;
+ /*
+ * Allocate one more cache entry than max required, to make sure that
+ * the last entry can be identified by the key size of zero.
+ */
+ struct vpd_blob_cache_t vpd_blob_cache[ARRAY_SIZE(templates) *
+ MAX_WIFI_INTERFACE_COUNT];
+
+ cbmem_entry_size = fill_up_entries_cache(vpd_blob_cache,
+ ARRAY_SIZE(vpd_blob_cache),
+ &filled_entries);
+
+ if (!cbmem_entry_size)
+ return; /* No calibration data found in the VPD. */
+
+ cbmem_entry_size += sizeof(struct calibration_entry);
+ cbmem_entry = cbmem_add(CBMEM_ID_WIFI_CALIBRATION, cbmem_entry_size);
+ if (!cbmem_entry) {
+ printk(BIOS_ERR, "%s: no room in cbmem table to add %d bytes\n",
+ __func__, cbmem_entry_size);
+ return;
+ }
+
+ cbmem_entry->size = cbmem_entry_size;
+
+ /* Copy cached data into the CBMEM entry. */
+ cal_blob = cbmem_entry->entries;
+
+ for (i = 0; i < filled_entries; i++) {
+ /* Use this as a pointer to the current cache entry. */
+ struct vpd_blob_cache_t *cache = vpd_blob_cache + i;
+ char *pointer;
+
+ cal_blob->blob_size = cache->blob_size;
+ cal_blob->key_size = cache->key_size;
+ cal_blob->value_size = cache->value_size;
+
+ /* copy the key */
+ pointer = (char *)(cal_blob + 1);
+ memcpy(pointer, cache->key_name, cache->key_size);
+
+ /* and the value */
+ pointer += cache->key_size;
+ memcpy(pointer, cache->value_pointer, cache->value_size);
+
+ printk(BIOS_INFO, "%s: added %s to CBMEM\n",
+ __func__, cache->key_name);
+
+ cal_blob = (struct calibration_blob *)
+ ((char *)cal_blob + cal_blob->blob_size);
+ }
+}
Aaron Durbin (adurbin(a)google.com) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/9434
-gerrit
commit b531d904c6546aa2adc361ef03490085e08c63e0
Author: Vadim Bendebury <vbendeb(a)chromium.org>
Date: Wed Oct 22 17:39:24 2014 -0700
chromeos: add another VPD access API
The new API allows to find VPD objects in the VPD cache. There is no
need for the caller to allocate or free the per object memory.
The existing API (cros_vpd_gets) now uses the new function as well.
BRANCH=storm
BUG=chrome-os-partner:32611
TEST=verified that MAC addresses still show up in the device tree on
the booted storm device
Original-Change-Id: I6c0b11bb844d6235930124d642da632319142d88
Original-Signed-off-by: Vadim Bendebury <vbendeb(a)chromium.org>
Original-Reviewed-on: https://chromium-review.googlesource.com/225258
Original-Reviewed-by: Hung-Te Lin <hungte(a)chromium.org>
(cherry picked from commit 99a34344448a5521cee8ad3918aefb1fde28417d)
Signed-off-by: Aaron Durbin <adurbin(a)chromium.org>
Change-Id: Ia1da362b12389a18a784ac3c8195127e91bb8d00
---
src/vendorcode/google/chromeos/cros_vpd.c | 26 +++++++++++++++++++++-----
src/vendorcode/google/chromeos/cros_vpd.h | 16 ++++++++++++++++
2 files changed, 37 insertions(+), 5 deletions(-)
diff --git a/src/vendorcode/google/chromeos/cros_vpd.c b/src/vendorcode/google/chromeos/cros_vpd.c
index df2b5bf..c0e4830 100644
--- a/src/vendorcode/google/chromeos/cros_vpd.c
+++ b/src/vendorcode/google/chromeos/cros_vpd.c
@@ -99,7 +99,7 @@ static int vpd_gets_callback(const uint8_t *key, int32_t key_len,
return VPD_FAIL;
}
-char *cros_vpd_gets(const char *key, char *buffer, int size)
+const void *cros_vpd_find(const char *key, int *size)
{
uint8_t *vpd_address = NULL;
int32_t vpd_size = 0;
@@ -121,10 +121,26 @@ char *cros_vpd_gets(const char *key, char *buffer, int size)
if (!arg.matched)
return NULL;
- if (size < arg.value_len + 1)
- size = arg.value_len + 1;
- memcpy(buffer, arg.value, size - 1);
- buffer[size - 1] = '\0';
+ *size = arg.value_len;
+ return arg.value;
+}
+
+char *cros_vpd_gets(const char *key, char *buffer, int size)
+{
+ const void *string_address;
+ int string_size;
+
+ string_address = cros_vpd_find(key, &string_size);
+
+ if (!string_address)
+ return NULL;
+
+ if (size > (string_size + 1)) {
+ strcpy(buffer, string_address);
+ } else {
+ memcpy(buffer, string_address, size - 1);
+ buffer[size - 1] = '\0';
+ }
return buffer;
}
diff --git a/src/vendorcode/google/chromeos/cros_vpd.h b/src/vendorcode/google/chromeos/cros_vpd.h
index 674dbf6..19658c2 100644
--- a/src/vendorcode/google/chromeos/cros_vpd.h
+++ b/src/vendorcode/google/chromeos/cros_vpd.h
@@ -18,4 +18,20 @@
*/
char *cros_vpd_gets(const char *key, char *buffer, int size);
+/*
+ * Find VPD value by key.
+ *
+ * Searches for a VPD entry in the VPD cache. If found, places the size of the
+ * entry into '*size' and returns the pointer to the entry data.
+ *
+ * This function presumes that VPD is cached in DRAM (which is the case in the
+ * current implementation) and as such returns the pointer into the cache. The
+ * user is not supposed to modify the data, and does not have to free the
+ * memory.
+ *
+ * Returns NULL if key is not found.
+ */
+
+const void *cros_vpd_find(const char *key, int *size);
+
#endif /* __CROS_VPD_H__ */
Aaron Durbin (adurbin(a)google.com) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/9433
-gerrit
commit 2921d44f895a1a2db8be2c5b8725533f348d658e
Author: Daisuke Nojiri <dnojiri(a)chromium.org>
Date: Fri Oct 10 10:51:06 2014 -0700
vboot: move vboot files to designated directory
This moves vboot1 and vboot2 files to their designated directory. Common
code stays in vendorcode/google/chromeos.
BUG=none
BRANCH=none
TEST=built cosmos, veyron_pinky, rush_ryu, nyan_blaze, samus, parrot,
lumpy, daisy_spring, and storm.
Signed-off-by: Daisuke Nojiri <dnojiri(a)chromium.org>
Original-Change-Id: Ia9fb41ba30930b79b222269acfade7ef44b23626
Original-Reviewed-on: https://chromium-review.googlesource.com/222874
Original-Reviewed-by: Daisuke Nojiri <dnojiri(a)chromium.org>
Original-Commit-Queue: Daisuke Nojiri <dnojiri(a)chromium.org>
Original-Tested-by: Daisuke Nojiri <dnojiri(a)chromium.org>
(cherry picked from commit cbfef9ad40776d890e2149b9db788fe0b387d210)
Signed-off-by: Aaron Durbin <adurbin(a)chromium.org>
Change-Id: Ia73696accfd93cc14ca83516fa77f87331faef51
---
src/mainboard/google/nyan_blaze/romstage.c | 2 +-
src/mainboard/google/veyron_pinky/romstage.c | 2 +-
src/soc/nvidia/tegra124/include/soc/memlayout.ld | 2 +-
.../tegra132/include/soc/memlayout_vboot2.ld | 2 +-
src/soc/rockchip/rk3288/include/soc/memlayout.ld | 2 +-
src/vendorcode/google/chromeos/Kconfig | 47 +--
src/vendorcode/google/chromeos/Makefile.inc | 101 +----
src/vendorcode/google/chromeos/antirollback.c | 329 ----------------
src/vendorcode/google/chromeos/chromeos.c | 183 +--------
src/vendorcode/google/chromeos/chromeos.h | 99 +----
src/vendorcode/google/chromeos/memlayout.h | 47 ---
src/vendorcode/google/chromeos/symbols.h | 32 --
src/vendorcode/google/chromeos/vboot1/Kconfig | 34 ++
src/vendorcode/google/chromeos/vboot1/Makefile.inc | 74 ++++
.../google/chromeos/vboot1/vboot_loader.c | 416 +++++++++++++++++++++
.../google/chromeos/vboot1/vboot_wrapper.c | 266 +++++++++++++
src/vendorcode/google/chromeos/vboot2/Kconfig | 43 +++
src/vendorcode/google/chromeos/vboot2/Makefile.inc | 60 +++
.../google/chromeos/vboot2/antirollback.c | 329 ++++++++++++++++
src/vendorcode/google/chromeos/vboot2/common.c | 70 ++++
src/vendorcode/google/chromeos/vboot2/memlayout.h | 47 +++
src/vendorcode/google/chromeos/vboot2/misc.h | 72 ++++
src/vendorcode/google/chromeos/vboot2/symbols.h | 32 ++
.../google/chromeos/vboot2/vboot_handoff.c | 175 +++++++++
src/vendorcode/google/chromeos/vboot2/verstage.c | 252 +++++++++++++
src/vendorcode/google/chromeos/vboot2/verstage.ld | 58 +++
src/vendorcode/google/chromeos/vboot2/verstub.c | 97 +++++
src/vendorcode/google/chromeos/vboot_common.c | 122 ++++++
src/vendorcode/google/chromeos/vboot_common.h | 55 +++
src/vendorcode/google/chromeos/vboot_handoff.c | 174 ---------
src/vendorcode/google/chromeos/vboot_handoff.h | 11 +
src/vendorcode/google/chromeos/vboot_loader.c | 416 ---------------------
src/vendorcode/google/chromeos/vboot_wrapper.c | 266 -------------
src/vendorcode/google/chromeos/verstage.c | 251 -------------
src/vendorcode/google/chromeos/verstage.ld | 58 ---
src/vendorcode/google/chromeos/verstub.c | 96 -----
36 files changed, 2243 insertions(+), 2079 deletions(-)
diff --git a/src/mainboard/google/nyan_blaze/romstage.c b/src/mainboard/google/nyan_blaze/romstage.c
index 034a929..c9510d6 100644
--- a/src/mainboard/google/nyan_blaze/romstage.c
+++ b/src/mainboard/google/nyan_blaze/romstage.c
@@ -96,7 +96,7 @@ static void __attribute__((noinline)) romstage(void)
early_mainboard_init();
#if CONFIG_VBOOT2_VERIFY_FIRMWARE
- entry = vboot_load_ramstage();
+ entry = vboot2_load_ramstage();
#else
early_mainboard_init();
vboot_verify_firmware(romstage_handoff_find_or_add());
diff --git a/src/mainboard/google/veyron_pinky/romstage.c b/src/mainboard/google/veyron_pinky/romstage.c
index 38166ed..b050228 100644
--- a/src/mainboard/google/veyron_pinky/romstage.c
+++ b/src/mainboard/google/veyron_pinky/romstage.c
@@ -117,7 +117,7 @@ void main(void)
#endif
#if IS_ENABLED(CONFIG_VBOOT_VERIFY_FIRMWARE)
- void *entry = vboot_load_ramstage();
+ void *entry = vboot2_load_ramstage();
if (entry != NULL)
stage_exit(entry);
#endif
diff --git a/src/soc/nvidia/tegra124/include/soc/memlayout.ld b/src/soc/nvidia/tegra124/include/soc/memlayout.ld
index 0d9e772..c8db5c5 100644
--- a/src/soc/nvidia/tegra124/include/soc/memlayout.ld
+++ b/src/soc/nvidia/tegra124/include/soc/memlayout.ld
@@ -18,7 +18,7 @@
*/
#include <memlayout.h>
-#include <vendorcode/google/chromeos/memlayout.h>
+#include <vendorcode/google/chromeos/vboot2/memlayout.h>
#include <arch/header.ld>
diff --git a/src/soc/nvidia/tegra132/include/soc/memlayout_vboot2.ld b/src/soc/nvidia/tegra132/include/soc/memlayout_vboot2.ld
index 8743268..1709392 100644
--- a/src/soc/nvidia/tegra132/include/soc/memlayout_vboot2.ld
+++ b/src/soc/nvidia/tegra132/include/soc/memlayout_vboot2.ld
@@ -18,7 +18,7 @@
*/
#include <memlayout.h>
-#include <vendorcode/google/chromeos/memlayout.h>
+#include <vendorcode/google/chromeos/vboot2/memlayout.h>
#include <arch/header.ld>
diff --git a/src/soc/rockchip/rk3288/include/soc/memlayout.ld b/src/soc/rockchip/rk3288/include/soc/memlayout.ld
index 2ddb6a6..922e2f8 100644
--- a/src/soc/rockchip/rk3288/include/soc/memlayout.ld
+++ b/src/soc/rockchip/rk3288/include/soc/memlayout.ld
@@ -18,7 +18,7 @@
*/
#include <memlayout.h>
-#include <vendorcode/google/chromeos/memlayout.h>
+#include <vendorcode/google/chromeos/vboot2/memlayout.h>
#include <arch/header.ld>
diff --git a/src/vendorcode/google/chromeos/Kconfig b/src/vendorcode/google/chromeos/Kconfig
index 8826a14..62a415b 100644
--- a/src/vendorcode/google/chromeos/Kconfig
+++ b/src/vendorcode/google/chromeos/Kconfig
@@ -94,22 +94,6 @@ config FLASHMAP_OFFSET
help
Offset of flash map in firmware image
-config VBOOT_VERIFY_FIRMWARE
- bool "Verify firmware with vboot."
- default n
- select RELOCATABLE_MODULES
- help
- Enabling VBOOT_VERIFY_FIRMWARE will use vboot to verify the ramstage
- and boot loader.
-
-config VBOOT2_VERIFY_FIRMWARE
- bool "Firmware Verification with vboot2"
- default n
- depends on CHROMEOS && HAVE_HARD_RESET
- help
- Enabling VBOOT2_VERIFY_FIRMWARE will use vboot2 to verify the romstage
- and boot loader.
-
config EC_SOFTWARE_SYNC
bool "Enable EC software sync"
default n
@@ -141,16 +125,6 @@ config VIRTUAL_DEV_SWITCH
help
Whether this platform has a virtual developer switch.
-config RETURN_FROM_VERSTAGE
- bool "return from verstage"
- default n
- depends on VBOOT2_VERIFY_FIRMWARE
- help
- If this is set, the verstage returns back to the bootblock instead of
- exits to the romstage so that the verstage space can be reused by the
- romstage. Useful if a ram space is too small to fit both the verstage
- and the romstage.
-
# These VBOOT_X_INDEX are the position of X in FW_MAIN_A/B region. The index
# table is created by cros_bundle_firmware at build time based on the positions
# of the blobs listed in fmap.dts and stored at the top of FW_MAIN_A/B region.
@@ -164,14 +138,6 @@ config VBOOT_BOOT_LOADER_INDEX
This is the index of the bootloader component in the verified
firmware block.
-config VBOOT_ROMSTAGE_INDEX
- hex
- default 2
- depends on VBOOT2_VERIFY_FIRMWARE
- help
- This is the index of the romstage component in the verified
- firmware block.
-
config VBOOT_RAMSTAGE_INDEX
hex "Ramstage component index"
default 1
@@ -180,14 +146,6 @@ config VBOOT_RAMSTAGE_INDEX
This is the index of the ramstage component in the verified
firmware block.
-config VBOOT_REFCODE_INDEX
- hex "Reference code firmware index"
- default 1
- depends on VBOOT_VERIFY_FIRMWARE
- help
- This is the index of the reference code component in the verified
- firmware block.
-
config NO_TPM_RESUME
bool
default n
@@ -196,5 +154,8 @@ config NO_TPM_RESUME
boards, booting Windows will break if the TPM resume command
is sent during an S3 resume.
-endif
+source src/vendorcode/google/chromeos/vboot1/Kconfig
+source src/vendorcode/google/chromeos/vboot2/Kconfig
+
+endif # CHROMEOS
endmenu
diff --git a/src/vendorcode/google/chromeos/Makefile.inc b/src/vendorcode/google/chromeos/Makefile.inc
index f43a87e..c325bcc 100644
--- a/src/vendorcode/google/chromeos/Makefile.inc
+++ b/src/vendorcode/google/chromeos/Makefile.inc
@@ -37,101 +37,8 @@ else
CFLAGS_common += -DMOCK_TPM=0
endif
-ifeq ($(CONFIG_VBOOT_VERIFY_FIRMWARE),y)
-romstage-y += vboot_helper.c
-ramstage-y += vboot_helper.c
-romstage-y += vboot_loader.c
-rmodules_$(ARCH-romstage-y)-y += vboot_wrapper.c
-
-ifneq ($(CONFIG_SPI_FLASH_MEMORY_MAPPED),y)
-VBOOT_MAKEFLAGS = REGION_READ=1
-endif
-
-VB_LIB = $(obj)/external/vboot_reference/vboot_fw.a
-# Currently, vboot comes into picture only during the romstage, thus
-# is compiled for being used in romstage only. Since, we are splitting
-# up all components in one of the three stages of coreboot, vboot seems
-# most logical to fall under the romstage. Thus, all references to arch
-# and other compiler stuff for vboot is using the romstage arch.
-VB_FIRMWARE_ARCH := $(ARCHDIR-$(ARCH-romstage-y))
-VB_SOURCE := vboot_reference
-
-# Add the vboot include paths.
-CPPFLAGS_common += -I$(VB_SOURCE)/firmware/include
-
-VBOOT_STUB_ELF = $(obj)/vendorcode/google/chromeos/vbootstub.elf
-VBOOT_STUB = $(VBOOT_STUB_ELF).rmod
-
-# Dependency for the vboot rmodules. Ordering matters.
-VBOOT_STUB_DEPS += $(obj)/vendorcode/google/chromeos/vboot_wrapper.rmodules_$(ARCH-romstage-y).o
-VBOOT_STUB_DEPS += $(obj)/lib/memcmp.rmodules_$(ARCH-romstage-y).o
-VBOOT_STUB_DEPS += $(obj)/arch/x86/lib/memset.rmodules_$(ARCH-romstage-y).o
-VBOOT_STUB_DEPS += $(obj)/arch/x86/lib/memcpy.rmodules_$(ARCH-romstage-y).o
-VBOOT_STUB_DEPS += $(VB_LIB)
-# Remove the '-include' option since that will break vboot's build and ensure
-# vboot_reference can get to coreboot's include files.
-VBOOT_CFLAGS += $(patsubst -I%,-I$(top)/%,$(filter-out -include $(src)/include/kconfig.h, $(CFLAGS_romstage) $(CPPFLAGS_romstage)))
-VBOOT_CFLAGS += -DVBOOT_DEBUG
-VBOOT_CFLAGS += $(rmodules_$(ARCH-ROMSTAGE-y)-c-ccopts)
-
-# Link the vbootstub module with a 64KiB-byte heap.
-$(eval $(call rmodule_link,$(VBOOT_STUB_ELF), $(VBOOT_STUB_DEPS), 0x10000,$(ARCH-romstage-y)))
-
-# Build vboot library without the default includes from coreboot proper.
-$(VB_LIB):
- @printf " MAKE $(subst $(obj)/,,$(@))\n"
- $(Q)$(MAKE) -C $(VB_SOURCE) \
- CC="$(CC_romstage)" \
- CFLAGS="$(VBOOT_CFLAGS)" \
- $(VBOOT_MAKEFLAGS) \
- FIRMWARE_ARCH=$(VB_FIRMWARE_ARCH) \
- BUILD=$(top)/$(dir $(VB_LIB)) \
- V=$(V) \
- fwlib
-
-endif
-
-ifeq ($(CONFIG_VBOOT2_VERIFY_FIRMWARE),y)
VB_SOURCE := vboot_reference
-CPPFLAGS_common += -I$(VB_SOURCE)/firmware/2lib/include
-CPPFLAGS_common += -I$(VB_SOURCE)/firmware/include
-
-verstage-generic-ccopts += -D__PRE_RAM__ -D__VERSTAGE__
-
-ifeq ($(CONFIG_RETURN_FROM_VERSTAGE),y)
-bootblock-y += verstub.c chromeos.c
-else
-verstage-y += verstub.c
-endif
-verstage-y += verstage.c fmap.c chromeos.c
-verstage-y += antirollback.c
-verstage-$(CONFIG_CHROMEOS_VBNV_CMOS) += vbnv_cmos.c
-verstage-$(CONFIG_CHROMEOS_VBNV_EC) += vbnv_ec.c
-verstage-$(CONFIG_CHROMEOS_VBNV_FLASH) += vbnv_flash.c
-romstage-y += vboot_handoff.c
-
-verstage-y += verstage.ld
-
-VB_FIRMWARE_ARCH := $(ARCHDIR-$(ARCH-VERSTAGE-y))
-VB2_LIB = $(obj)/external/vboot_reference/vboot_fw2.a
-VBOOT_CFLAGS += $(patsubst -I%,-I$(top)/%,$(filter-out -include $(src)/include/kconfig.h, $(CFLAGS_verstage) $(CPPFLAGS_verstage)))
-VBOOT_CFLAGS += $(verstage-c-ccopts)
-VBOOT_CFLAGS += -include $(top)/src/include/kconfig.h -Wno-missing-prototypes
-VBOOT_CFLAGS += -DVBOOT_DEBUG
-
-$(VB2_LIB): $(obj)/config.h
- @printf " MAKE $(subst $(obj)/,,$(@))\n"
- $(Q)$(MAKE) -C $(VB_SOURCE) \
- CC="$(CC_verstage)" \
- CFLAGS="$(VBOOT_CFLAGS)" VBOOT2="y" \
- FIRMWARE_ARCH=$(VB_FIRMWARE_ARCH) \
- BUILD=$(top)/$(dir $(VB2_LIB)) \
- V=$(V) \
- fwlib2
-
-VERSTAGE_ELF = $(objcbfs)/verstage.elf
-cbfs-files-y += $(call strip_quotes,$(CONFIG_CBFS_PREFIX))/verstage
-fallback/verstage-file = $(VERSTAGE_ELF)
-fallback/verstage-type = stage
-fallback/verstage-compression = none
-endif # CONFIG_VBOOT2_VERIFY_FIRMWARE
+subdirs-$(CONFIG_VBOOT_VERIFY_FIRMWARE) += vboot1
+subdirs-$(CONFIG_VBOOT2_VERIFY_FIRMWARE) += vboot2
+INCLUDES += -I$(VB_SOURCE)/firmware/2lib/include
+INCLUDES += -I$(VB_SOURCE)/firmware/include
diff --git a/src/vendorcode/google/chromeos/antirollback.c b/src/vendorcode/google/chromeos/antirollback.c
deleted file mode 100644
index bb547b5..0000000
--- a/src/vendorcode/google/chromeos/antirollback.c
+++ /dev/null
@@ -1,329 +0,0 @@
-/* Copyright (c) 2013 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.
- *
- * Functions for querying, manipulating and locking rollback indices
- * stored in the TPM NVRAM.
- */
-
-#include <2api.h>
-#include <2sysincludes.h>
-#include <antirollback.h>
-#include <tpm_lite/tlcl.h>
-#include <tpm_lite/tss_constants.h>
-
-#ifndef offsetof
-#define offsetof(A,B) __builtin_offsetof(A,B)
-#endif
-
-#ifdef FOR_TEST
-#include <stdio.h>
-#define VBDEBUG(format, args...) printf(format, ## args)
-#else
-#include <console/console.h>
-#define VBDEBUG(format, args...) \
- printk(BIOS_INFO, "%s():%d: " format, __func__, __LINE__, ## args)
-#endif
-
-#define RETURN_ON_FAILURE(tpm_cmd) do { \
- uint32_t result_; \
- if ((result_ = (tpm_cmd)) != TPM_SUCCESS) { \
- VBDEBUG("Antirollback: %08x returned by " #tpm_cmd \
- "\n", (int)result_); \
- return result_; \
- } \
- } while (0)
-
-uint32_t tpm_clear_and_reenable(void)
-{
- VBDEBUG("TPM: Clear and re-enable\n");
- RETURN_ON_FAILURE(tlcl_force_clear());
- RETURN_ON_FAILURE(tlcl_set_enable());
- RETURN_ON_FAILURE(tlcl_set_deactivated(0));
-
- return TPM_SUCCESS;
-}
-
-uint32_t safe_write(uint32_t index, const void *data, uint32_t length)
-{
- uint32_t result = tlcl_write(index, data, length);
- if (result == TPM_E_MAXNVWRITES) {
- RETURN_ON_FAILURE(tpm_clear_and_reenable());
- return tlcl_write(index, data, length);
- } else {
- return result;
- }
-}
-
-uint32_t safe_define_space(uint32_t index, uint32_t perm, uint32_t size)
-{
- uint32_t result = tlcl_define_space(index, perm, size);
- if (result == TPM_E_MAXNVWRITES) {
- RETURN_ON_FAILURE(tpm_clear_and_reenable());
- return tlcl_define_space(index, perm, size);
- } else {
- return result;
- }
-}
-
-static uint32_t read_space_firmware(struct vb2_context *ctx)
-{
- int attempts = 3;
-
- while (attempts--) {
- RETURN_ON_FAILURE(tlcl_read(FIRMWARE_NV_INDEX, ctx->secdata,
- VB2_SECDATA_SIZE));
-
- if (vb2api_secdata_check(ctx) == VB2_SUCCESS)
- return TPM_SUCCESS;
-
- VBDEBUG("TPM: %s() - bad CRC\n", __func__);
- }
-
- VBDEBUG("TPM: %s() - too many bad CRCs, giving up\n", __func__);
- return TPM_E_CORRUPTED_STATE;
-}
-
-static uint32_t write_secdata(uint32_t index,
- const uint8_t *secdata,
- uint32_t len)
-{
- uint8_t sd[32];
- uint32_t rv;
- int attempts = 3;
-
- if (len > sizeof(sd)) {
- VBDEBUG("TPM: %s() - data is too large\n", __func__);
- return TPM_E_WRITE_FAILURE;
- }
-
- while (attempts--) {
- rv = safe_write(index, secdata, len);
- /* Can't write, not gonna try again */
- if (rv != TPM_SUCCESS)
- return rv;
-
- /* Read it back to be sure it got the right values. */
- rv = tlcl_read(index, sd, len);
- if (rv == TPM_SUCCESS && memcmp(secdata, sd, len) == 0)
- return rv;
-
- VBDEBUG("TPM: %s() failed. trying again\n", __func__);
- /* Try writing it again. Maybe it was garbled on the way out. */
- }
-
- VBDEBUG("TPM: %s() - too many failures, giving up\n", __func__);
-
- return TPM_E_CORRUPTED_STATE;
-}
-
-uint32_t factory_initialize_tpm(struct vb2_context *ctx)
-{
- TPM_PERMANENT_FLAGS pflags;
- uint32_t result;
- /* this is derived from rollback_index.h of vboot_reference. see struct
- * RollbackSpaceKernel for details. */
- static const uint8_t secdata_kernel[] = {
- 0x02,
- 0x4C, 0x57, 0x52, 0x47,
- 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00,
- 0xE8,
- };
-
- VBDEBUG("TPM: factory initialization\n");
-
- /*
- * Do a full test. This only happens the first time the device is
- * turned on in the factory, so performance is not an issue. This is
- * almost certainly not necessary, but it gives us more confidence
- * about some code paths below that are difficult to
- * test---specifically the ones that set lifetime flags, and are only
- * executed once per physical TPM.
- */
- result = tlcl_self_test_full();
- if (result != TPM_SUCCESS)
- return result;
-
- result = tlcl_get_permanent_flags(&pflags);
- if (result != TPM_SUCCESS)
- return result;
-
- /*
- * TPM may come from the factory without physical presence finalized.
- * Fix if necessary.
- */
- VBDEBUG("TPM: physicalPresenceLifetimeLock=%d\n",
- pflags.physicalPresenceLifetimeLock);
- if (!pflags.physicalPresenceLifetimeLock) {
- VBDEBUG("TPM: Finalizing physical presence\n");
- RETURN_ON_FAILURE(tlcl_finalize_physical_presence());
- }
-
- /*
- * The TPM will not enforce the NV authorization restrictions until the
- * execution of a TPM_NV_DefineSpace with the handle of
- * TPM_NV_INDEX_LOCK. Here we create that space if it doesn't already
- * exist. */
- VBDEBUG("TPM: nvLocked=%d\n", pflags.nvLocked);
- if (!pflags.nvLocked) {
- VBDEBUG("TPM: Enabling NV locking\n");
- RETURN_ON_FAILURE(tlcl_set_nv_locked());
- }
-
- /* Clear TPM owner, in case the TPM is already owned for some reason. */
- VBDEBUG("TPM: Clearing owner\n");
- RETURN_ON_FAILURE(tpm_clear_and_reenable());
-
- /* Define the backup space. No need to initialize it, though. */
- RETURN_ON_FAILURE(safe_define_space(BACKUP_NV_INDEX,
- TPM_NV_PER_PPWRITE,
- VB2_NVDATA_SIZE));
-
- /* Define and initialize the kernel space */
- RETURN_ON_FAILURE(safe_define_space(KERNEL_NV_INDEX,
- TPM_NV_PER_PPWRITE,
- sizeof(secdata_kernel)));
- RETURN_ON_FAILURE(write_secdata(KERNEL_NV_INDEX,
- secdata_kernel,
- sizeof(secdata_kernel)));
-
- /* Defines and sets vb2 secdata space */
- vb2api_secdata_create(ctx);
- RETURN_ON_FAILURE(safe_define_space(FIRMWARE_NV_INDEX,
- TPM_NV_PER_GLOBALLOCK |
- TPM_NV_PER_PPWRITE,
- VB2_SECDATA_SIZE));
- RETURN_ON_FAILURE(write_secdata(FIRMWARE_NV_INDEX,
- ctx->secdata,
- VB2_SECDATA_SIZE));
-
- VBDEBUG("TPM: factory initialization successful\n");
-
- return TPM_SUCCESS;
-}
-
-/*
- * SetupTPM starts the TPM and establishes the root of trust for the
- * anti-rollback mechanism. SetupTPM can fail for three reasons. 1 A bug. 2 a
- * TPM hardware failure. 3 An unexpected TPM state due to some attack. In
- * general we cannot easily distinguish the kind of failure, so our strategy is
- * to reboot in recovery mode in all cases. The recovery mode calls SetupTPM
- * again, which executes (almost) the same sequence of operations. There is a
- * good chance that, if recovery mode was entered because of a TPM failure, the
- * failure will repeat itself. (In general this is impossible to guarantee
- * because we have no way of creating the exact TPM initial state at the
- * previous boot.) In recovery mode, we ignore the failure and continue, thus
- * giving the recovery kernel a chance to fix things (that's why we don't set
- * bGlobalLock). The choice is between a knowingly insecure device and a
- * bricked device.
- *
- * As a side note, observe that we go through considerable hoops to avoid using
- * the STCLEAR permissions for the index spaces. We do this to avoid writing
- * to the TPM flashram at every reboot or wake-up, because of concerns about
- * the durability of the NVRAM.
- */
-uint32_t setup_tpm(struct vb2_context *ctx)
-{
- uint8_t disable;
- uint8_t deactivated;
- uint32_t result;
-
- RETURN_ON_FAILURE(tlcl_lib_init());
-
-#ifdef TEGRA_SOFT_REBOOT_WORKAROUND
- result = tlcl_startup();
- if (result == TPM_E_INVALID_POSTINIT) {
- /*
- * Some prototype hardware doesn't reset the TPM on a CPU
- * reset. We do a hard reset to get around this.
- */
- VBDEBUG("TPM: soft reset detected\n", result);
- return TPM_E_MUST_REBOOT;
- } else if (result != TPM_SUCCESS) {
- VBDEBUG("TPM: tlcl_startup returned %08x\n", result);
- return result;
- }
-#else
- RETURN_ON_FAILURE(tlcl_startup());
-#endif
-
- /*
- * Some TPMs start the self test automatically at power on. In that case
- * we don't need to call ContinueSelfTest. On some (other) TPMs,
- * continue_self_test may block. In that case, we definitely don't want
- * to call it here. For TPMs in the intersection of these two sets, we
- * are screwed. (In other words: TPMs that require manually starting the
- * self-test AND block will have poor performance until we split
- * tlcl_send_receive() into send() and receive(), and have a state
- * machine to control setup.)
- *
- * This comment is likely to become obsolete in the near future, so
- * don't trust it. It may have not been updated.
- */
-#ifdef TPM_MANUAL_SELFTEST
-#ifdef TPM_BLOCKING_CONTINUESELFTEST
-#warning "lousy TPM!"
-#endif
- RETURN_ON_FAILURE(tlcl_continue_self_test());
-#endif
- result = tlcl_assert_physical_presence();
- if (result != TPM_SUCCESS) {
- /*
- * It is possible that the TPM was delivered with the physical
- * presence command disabled. This tries enabling it, then
- * tries asserting PP again.
- */
- RETURN_ON_FAILURE(tlcl_physical_presence_cmd_enable());
- RETURN_ON_FAILURE(tlcl_assert_physical_presence());
- }
-
- /* Check that the TPM is enabled and activated. */
- RETURN_ON_FAILURE(tlcl_get_flags(&disable, &deactivated, NULL));
- if (disable || deactivated) {
- VBDEBUG("TPM: disabled (%d) or deactivated (%d). Fixing...\n",
- disable, deactivated);
- RETURN_ON_FAILURE(tlcl_set_enable());
- RETURN_ON_FAILURE(tlcl_set_deactivated(0));
- VBDEBUG("TPM: Must reboot to re-enable\n");
- return TPM_E_MUST_REBOOT;
- }
-
- VBDEBUG("TPM: SetupTPM() succeeded\n");
- return TPM_SUCCESS;
-}
-
-uint32_t antirollback_read_space_firmware(struct vb2_context *ctx)
-{
- uint32_t rv;
-
- rv = setup_tpm(ctx);
- if (rv)
- return rv;
-
- /* Read the firmware space. */
- rv = read_space_firmware(ctx);
- if (rv == TPM_E_BADINDEX) {
- /*
- * This seems the first time we've run. Initialize the TPM.
- */
- VBDEBUG("TPM: Not initialized yet.\n");
- RETURN_ON_FAILURE(factory_initialize_tpm(ctx));
- } else if (rv != TPM_SUCCESS) {
- VBDEBUG("TPM: Firmware space in a bad state; giving up.\n");
- //RETURN_ON_FAILURE(factory_initialize_tpm(ctx));
- return TPM_E_CORRUPTED_STATE;
- }
-
- return TPM_SUCCESS;
-}
-
-uint32_t antirollback_write_space_firmware(struct vb2_context *ctx)
-{
- return write_secdata(FIRMWARE_NV_INDEX, ctx->secdata, VB2_SECDATA_SIZE);
-}
-
-uint32_t antirollback_lock_space_firmware()
-{
- return tlcl_set_global_lock();
-}
diff --git a/src/vendorcode/google/chromeos/chromeos.c b/src/vendorcode/google/chromeos/chromeos.c
index c4d651a..437e128 100644
--- a/src/vendorcode/google/chromeos/chromeos.c
+++ b/src/vendorcode/google/chromeos/chromeos.c
@@ -20,18 +20,11 @@
#include <stddef.h>
#include <string.h>
#include "chromeos.h"
-#if CONFIG_VBOOT_VERIFY_FIRMWARE || CONFIG_VBOOT2_VERIFY_FIRMWARE
-#include "fmap.h"
-#include "symbols.h"
-#include "vboot_handoff.h"
-#include <reset.h>
-#endif
#include <boot/coreboot_tables.h>
#include <cbfs.h>
#include <cbmem.h>
#include <console/console.h>
-#if CONFIG_VBOOT_VERIFY_FIRMWARE
static int vboot_enable_developer(void)
{
struct vboot_handoff *vbho;
@@ -58,10 +51,18 @@ static int vboot_enable_recovery(void)
return !!(vbho->init_params.out_flags & VB_INIT_OUT_ENABLE_RECOVERY);
}
-#else
-static inline int vboot_enable_developer(void) { return 0; }
-static inline int vboot_enable_recovery(void) { return 0; }
-#endif
+
+int vboot_skip_display_init(void)
+{
+ struct vboot_handoff *vbho;
+
+ vbho = cbmem_find(CBMEM_ID_VBOOT_HANDOFF);
+
+ if (vbho == NULL)
+ return 0;
+
+ return !(vbho->init_params.out_flags & VB_INIT_OUT_ENABLE_DISPLAY);
+}
int developer_mode_enabled(void)
{
@@ -92,22 +93,6 @@ int __attribute__((weak)) clear_recovery_mode_switch(void)
return 0;
}
-int vboot_skip_display_init(void)
-{
-#if CONFIG_VBOOT_VERIFY_FIRMWARE
- struct vboot_handoff *vbho;
-
- vbho = cbmem_find(CBMEM_ID_VBOOT_HANDOFF);
-
- if (vbho == NULL)
- return 0;
-
- return !(vbho->init_params.out_flags & VB_INIT_OUT_ENABLE_DISPLAY);
-#else
- return 0;
-#endif
-}
-
#ifdef __ROMSTAGE__
void __attribute__((weak)) save_chromeos_gpios(void)
{
@@ -120,147 +105,3 @@ int __attribute((weak)) vboot_get_sw_write_protect(void)
return 0;
}
#endif
-
-#if CONFIG_VBOOT_VERIFY_FIRMWARE || CONFIG_VBOOT2_VERIFY_FIRMWARE
-void vboot_locate_region(const char *name, struct vboot_region *region)
-{
- region->size = find_fmap_entry(name, (void **)®ion->offset_addr);
-}
-
-void *vboot_get_region(uintptr_t offset_addr, size_t size, void *dest)
-{
- if (IS_ENABLED(CONFIG_SPI_FLASH_MEMORY_MAPPED)) {
- if (dest != NULL)
- return memcpy(dest, (void *)offset_addr, size);
- else
- return (void *)offset_addr;
- } else {
- struct cbfs_media default_media, *media = &default_media;
- void *cache;
-
- init_default_cbfs_media(media);
- media->open(media);
- if (dest != NULL) {
- cache = dest;
- if (media->read(media, dest, offset_addr, size) != size)
- cache = NULL;
- } else {
- cache = media->map(media, offset_addr, size);
- if (cache == CBFS_MEDIA_INVALID_MAP_ADDRESS)
- cache = NULL;
- }
- media->close(media);
- return cache;
- }
-}
-
-int vboot_get_handoff_info(void **addr, uint32_t *size)
-{
- struct vboot_handoff *vboot_handoff;
-
- vboot_handoff = cbmem_find(CBMEM_ID_VBOOT_HANDOFF);
-
- if (vboot_handoff == NULL)
- return -1;
-
- *addr = vboot_handoff;
- *size = sizeof(*vboot_handoff);
- return 0;
-}
-
-/* This will leak a mapping of a fw region */
-struct vboot_components *vboot_locate_components(struct vboot_region *region)
-{
- size_t req_size;
- struct vboot_components *vbc;
-
- req_size = sizeof(*vbc);
- req_size += sizeof(struct vboot_component_entry) *
- MAX_PARSED_FW_COMPONENTS;
-
- vbc = vboot_get_region(region->offset_addr, req_size, NULL);
- if (vbc && vbc->num_components > MAX_PARSED_FW_COMPONENTS)
- vbc = NULL;
-
- return vbc;
-}
-
-void *vboot_get_payload(int *len)
-{
- struct vboot_handoff *vboot_handoff;
- struct firmware_component *fwc;
-
- vboot_handoff = cbmem_find(CBMEM_ID_VBOOT_HANDOFF);
-
- if (vboot_handoff == NULL)
- return NULL;
-
- if (CONFIG_VBOOT_BOOT_LOADER_INDEX >= MAX_PARSED_FW_COMPONENTS) {
- printk(BIOS_ERR, "Invalid boot loader index: %d\n",
- CONFIG_VBOOT_BOOT_LOADER_INDEX);
- return NULL;
- }
-
- fwc = &vboot_handoff->components[CONFIG_VBOOT_BOOT_LOADER_INDEX];
-
- /* If payload size is zero fall back to cbfs path. */
- if (fwc->size == 0)
- return NULL;
-
- if (len != NULL)
- *len = fwc->size;
-
- printk(BIOS_DEBUG, "Booting 0x%x byte verified payload at 0x%08x.\n",
- fwc->size, fwc->address);
-
- /* This will leak a mapping. */
- return vboot_get_region(fwc->address, fwc->size, NULL);
-}
-#endif
-
-#if CONFIG_VBOOT2_VERIFY_FIRMWARE
-void *vboot_load_stage(int stage_index,
- struct vboot_region *fw_main,
- struct vboot_components *fw_info)
-{
- struct cbfs_media default_media, *media = &default_media;
- uintptr_t fc_addr;
- uint32_t fc_size;
- void *entry;
-
- if (stage_index >= fw_info->num_components) {
- printk(BIOS_INFO, "invalid stage index\n");
- return NULL;
- }
-
- fc_addr = fw_main->offset_addr + fw_info->entries[stage_index].offset;
- fc_size = fw_info->entries[stage_index].size;
- if (fc_size == 0 ||
- fc_addr + fc_size > fw_main->offset_addr + fw_main->size) {
- printk(BIOS_INFO, "invalid stage address or size\n");
- return NULL;
- }
-
- init_default_cbfs_media(media);
-
- /* we're making cbfs access offset outside of the region managed by
- * cbfs. this works because cbfs_load_stage_by_offset does not check
- * the offset. */
- entry = cbfs_load_stage_by_offset(media, fc_addr);
- if (entry == (void *)-1)
- entry = NULL;
- return entry;
-}
-
-struct vb2_working_data * const vboot_get_working_data(void)
-{
- return (struct vb2_working_data *)_vboot2_work;
-}
-
-void vboot_reboot(void)
-{
- hard_reset();
- die("failed to reboot");
-}
-
-#endif
diff --git a/src/vendorcode/google/chromeos/chromeos.h b/src/vendorcode/google/chromeos/chromeos.h
index ed6c75b..5ba5457 100644
--- a/src/vendorcode/google/chromeos/chromeos.h
+++ b/src/vendorcode/google/chromeos/chromeos.h
@@ -23,6 +23,8 @@
#include <stddef.h>
#include <stdint.h>
#include <bootmode.h>
+#include "vboot_common.h"
+#include "vboot2/misc.h"
/*for mainboard use only*/
void setup_chromeos_gpios(void);
@@ -47,54 +49,14 @@ static inline void elog_add_boot_reason(void) { return; }
struct romstage_handoff;
-/* TODO(shawnn): Remove these CONFIGs and define default weak functions
- * that can be overridden in the platform / MB code. */
#if CONFIG_VBOOT_VERIFY_FIRMWARE || CONFIG_VBOOT2_VERIFY_FIRMWARE
-struct vboot_region {
- uintptr_t offset_addr;
- int32_t size;
-};
-
-/*
- * The vboot handoff structure keeps track of a maximum number of firmware
- * components in the verfieid RW area of flash. This is not a restriction on
- * the number of components packed in a firmware block. It's only the maximum
- * number of parsed firmware components (address and size) included in the
- * handoff structure.
- */
-#define MAX_PARSED_FW_COMPONENTS 5
-
-/* The FW areas consist of multiple components. At the beginning of
- * each area is the number of total compoments as well as the size and
- * offset for each component. One needs to caculate the total size of the
- * signed firmware region based off of the embedded metadata. */
-struct vboot_component_entry {
- uint32_t offset;
- uint32_t size;
-} __attribute__((packed));
-
-struct vboot_components {
- uint32_t num_components;
- struct vboot_component_entry entries[0];
-} __attribute__((packed));
-
-void vboot_locate_region(const char *name, struct vboot_region *region);
-
-struct vboot_components *vboot_locate_components(struct vboot_region *region);
-
-/*
- * This is a dual purpose routine. If dest is non-NULL the region at
- * offset_addr will be read into the area pointed to by dest. If dest
- * is NULL,the region will be mapped to a memory location. NULL is
- * returned on error else the location of the requested region.
- */
-void *vboot_get_region(uintptr_t offset_addr, size_t size, void *dest);
/* Returns 0 on success < 0 on error. */
int vboot_get_handoff_info(void **addr, uint32_t *size);
int vboot_enable_developer(void);
int vboot_enable_recovery(void);
int vboot_skip_display_init(void);
-#else
+void *vboot_get_payload(int *len);
+#else /* CONFIG_VBOOT_VERIFY_FIRMWARE || CONFIG_VBOOT2_VERIFY_FIRMWARE */
static inline void vboot_verify_firmware(struct romstage_handoff *h) {}
static inline void *vboot_get_payload(int *len) { return NULL; }
static inline int vboot_get_handoff_info(void **addr, uint32_t *size)
@@ -121,55 +83,4 @@ static inline void chromeos_ram_oops_init(chromeos_acpi_t *chromeos) {}
static inline void chromeos_reserve_ram_oops(struct device *dev, int idx) {}
#endif /* CONFIG_CHROMEOS_RAMOOPS */
-void vboot2_verify_firmware(void);
-
-#if CONFIG_VBOOT2_VERIFY_FIRMWARE
-void *vboot_load_ramstage(void);
-void verstage_main(void);
-void *vboot_load_stage(int stage_index,
- struct vboot_region *fw_main,
- struct vboot_components *fw_info);
-void vboot_reboot(void);
-
-/*
- * this is placed at the start of the vboot work buffer. selected_region is used
- * for the verstage to return the location of the selected slot. buffer is used
- * by the vboot2 core. Keep the struct cpu architecture agnostic as it crosses
- * stage boundaries.
- */
-struct vb2_working_data {
- uint32_t selected_region_offset;
- uint32_t selected_region_size;
- uint64_t buffer_size;
- uint64_t buffer;
-};
-
-struct vb2_working_data * const vboot_get_working_data(void);
-
-static inline void vb2_get_selected_region(struct vb2_working_data *wd,
- struct vboot_region *region)
-{
- region->offset_addr = wd->selected_region_offset;
- region->size = wd->selected_region_size;
-}
-
-static inline void vb2_set_selected_region(struct vb2_working_data *wd,
- struct vboot_region *region)
-{
- wd->selected_region_offset = region->offset_addr;
- wd->selected_region_size = region->size;
-}
-
-static inline int vboot_is_slot_selected(struct vb2_working_data *wd)
-{
- return wd->selected_region_size > 0;
-}
-
-static inline int vboot_is_readonly_path(struct vb2_working_data *wd)
-{
- return wd->selected_region_size == 0;
-}
-
-#endif /* CONFIG_VBOOT2_VERIFY_FIRMWARE */
-
-#endif
+#endif /* __CHROMEOS_H__ */
diff --git a/src/vendorcode/google/chromeos/memlayout.h b/src/vendorcode/google/chromeos/memlayout.h
deleted file mode 100644
index 468f746..0000000
--- a/src/vendorcode/google/chromeos/memlayout.h
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * This file is part of the coreboot project.
- *
- * Copyright 2014 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.
- *
- * 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 file contains macro definitions for memlayout.ld linker scripts. */
-
-#ifndef __CHROMEOS_MEMLAYOUT_H
-#define __CHROMEOS_MEMLAYOUT_H
-
-#define VBOOT2_WORK(addr, size) \
- REGION(vboot2_work, addr, size, 4) \
- _ = ASSERT(size >= 16K, "vboot2 work buffer must be at least 16K!");
-
-#ifdef __VERSTAGE__
- #define VERSTAGE(addr, sz) \
- SET_COUNTER(VERSTAGE, addr) \
- _ = ASSERT(_everstage - _verstage <= sz, \
- STR(Verstage exceeded its allotted size! (sz))); \
- INCLUDE "vendorcode/google/chromeos/verstage.verstage.ld"
-#else
- #define VERSTAGE(addr, sz) \
- SET_COUNTER(VERSTAGE, addr) \
- . += sz;
-#endif
-
-#ifdef __VERSTAGE__
- #define OVERLAP_VERSTAGE_ROMSTAGE(addr, size) VERSTAGE(addr, size)
-#else
- #define OVERLAP_VERSTAGE_ROMSTAGE(addr, size) ROMSTAGE(addr, size)
-#endif
-
-#endif /* __CHROMEOS_MEMLAYOUT_H */
diff --git a/src/vendorcode/google/chromeos/symbols.h b/src/vendorcode/google/chromeos/symbols.h
deleted file mode 100644
index 21169f0..0000000
--- a/src/vendorcode/google/chromeos/symbols.h
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * This file is part of the coreboot project.
- *
- * Copyright 2014 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.
- *
- * 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_SYMBOLS_H
-#define __CHROMEOS_SYMBOLS_H
-
-extern u8 _vboot2_work[];
-extern u8 _evboot2_work[];
-#define _vboot2_work_size (_evboot2_work - _vboot2_work)
-
-/* Careful: _e<stage> and _<stage>_size only defined for the current stage! */
-extern u8 _verstage[];
-extern u8 _everstage[];
-#define _verstage_size (_everstage - _verstage)
-
-#endif /* __CHROMEOS_SYMBOLS_H */
diff --git a/src/vendorcode/google/chromeos/vboot1/Kconfig b/src/vendorcode/google/chromeos/vboot1/Kconfig
new file mode 100644
index 0000000..0102869
--- /dev/null
+++ b/src/vendorcode/google/chromeos/vboot1/Kconfig
@@ -0,0 +1,34 @@
+## This file is part of the coreboot project.
+##
+## Copyright (C) 2014 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
+##
+
+config VBOOT_VERIFY_FIRMWARE
+ bool "Verify firmware with vboot."
+ default n
+ depends on CHROMEOS
+ select RELOCATABLE_MODULES
+ help
+ Enabling VBOOT_VERIFY_FIRMWARE will use vboot to verify the ramstage
+ and boot loader.
+
+config VBOOT_REFCODE_INDEX
+ hex "Reference code firmware index"
+ default 1
+ depends on VBOOT_VERIFY_FIRMWARE
+ help
+ This is the index of the reference code component in the verified
+ firmware block.
diff --git a/src/vendorcode/google/chromeos/vboot1/Makefile.inc b/src/vendorcode/google/chromeos/vboot1/Makefile.inc
new file mode 100644
index 0000000..a2d42b4
--- /dev/null
+++ b/src/vendorcode/google/chromeos/vboot1/Makefile.inc
@@ -0,0 +1,74 @@
+##
+## This file is part of the coreboot project.
+##
+## Copyright (C) 2014 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
+##
+
+ramstage-y += ../vboot_common.c
+romstage-y += vboot_loader.c ../vboot_common.c
+rmodules_$(ARCH-ROMSTAGE-y)-y += vboot_wrapper.c ../vboot_common.c
+
+ifneq ($(CONFIG_SPI_FLASH_MEMORY_MAPPED),y)
+VBOOT_MAKEFLAGS = REGION_READ=1
+endif
+
+VB_LIB = $(obj)/external/vboot_reference/vboot_fw.a
+# Currently, vboot comes into picture only during the romstage, thus
+# is compiled for being used in romstage only. Since, we are splitting
+# up all components in one of the three stages of coreboot, vboot seems
+# most logical to fall under the romstage. Thus, all references to arch
+# and other compiler stuff for vboot is using the romstage arch.
+VB_FIRMWARE_ARCH := $(ARCHDIR-$(ARCH-ROMSTAGE-y))
+
+VBOOT_STUB_ELF = $(obj)/vendorcode/google/chromeos/vboot1/vbootstub.elf
+VBOOT_STUB = $(VBOOT_STUB_ELF).rmod
+
+# Dependency for the vboot rmodules. Ordering matters.
+VBOOT_STUB_DEPS += $(obj)/vendorcode/google/chromeos/vboot1/vboot_wrapper.rmodules_$(ARCH-ROMSTAGE-y).o
+VBOOT_STUB_DEPS += $(obj)/lib/memcmp.rmodules_$(ARCH-ROMSTAGE-y).o
+ifeq ($(CONFIG_ARCH_ROMSTAGE_X86_32),y)
+VBOOT_STUB_DEPS += $(obj)/arch/x86/lib/memset.rmodules_$(ARCH-ROMSTAGE-y).o
+VBOOT_STUB_DEPS += $(obj)/arch/x86/lib/memcpy.rmodules_$(ARCH-ROMSTAGE-y).o
+endif
+ifeq ($(CONFIG_ARCH_ROMSTAGE_ARM),y)
+VBOOT_STUB_DEPS += $(obj)/arch/arm/memset.rmodules_$(ARCH-ROMSTAGE-y).o
+VBOOT_STUB_DEPS += $(obj)/arch/arm/memcpy.rmodules_$(ARCH-ROMSTAGE-y).o
+endif
+ifeq ($(CONFIG_ARCH_ROMSTAGE_ARM64),y)
+VBOOT_STUB_DEPS += $(obj)/lib/memset.rmodules.o
+VBOOT_STUB_DEPS += $(obj)/lib/memcpy.rmodules.o
+endif
+VBOOT_STUB_DEPS += $(VB_LIB)
+# Remove the '-include' option since that will break vboot's build and ensure
+# vboot_reference can get to coreboot's include files.
+VBOOT_CFLAGS += $(patsubst -I%,-I$(top)/%,$(filter-out -include $(src)/include/kconfig.h, $(CFLAGS_romstage)))
+VBOOT_CFLAGS += -DVBOOT_DEBUG
+VBOOT_CFLAGS += $(rmodules_$(ARCH-ROMSTAGE-y)-c-ccopts)
+
+# Link the vbootstub module with a 64KiB-byte heap.
+$(eval $(call rmodule_link,$(VBOOT_STUB_ELF), $(VBOOT_STUB_DEPS), 0x10000,$(ARCH-ROMSTAGE-y)))
+
+# Build vboot library without the default includes from coreboot proper.
+$(VB_LIB):
+ @printf " MAKE $(subst $(obj)/,,$(@))\n"
+ $(Q)FIRMWARE_ARCH=$(VB_FIRMWARE_ARCH) \
+ CC="$(CC_romstage)" \
+ CFLAGS="$(VBOOT_CFLAGS)" \
+ $(MAKE) -C $(VB_SOURCE) \
+ $(VBOOT_MAKEFLAGS) \
+ BUILD=$(top)/$(dir $(VB_LIB)) \
+ V=$(V) \
+ fwlib
diff --git a/src/vendorcode/google/chromeos/vboot1/vboot_loader.c b/src/vendorcode/google/chromeos/vboot1/vboot_loader.c
new file mode 100644
index 0000000..0353a3a
--- /dev/null
+++ b/src/vendorcode/google/chromeos/vboot1/vboot_loader.c
@@ -0,0 +1,416 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2013 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.
+ *
+ * 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 <arch/stages.h>
+#include <stdint.h>
+#include <stddef.h>
+#include <string.h>
+#include <cbfs.h>
+#include <cbmem.h>
+#include <console/console.h>
+#include <console/vtxprintf.h>
+#include <program_loading.h>
+#include <tpm.h>
+#include <reset.h>
+#include <romstage_handoff.h>
+#include <rmodule.h>
+#include <string.h>
+#include <stdlib.h>
+#include <timestamp.h>
+#include "../chromeos.h"
+#include "../vboot_context.h"
+#include "../vboot_handoff.h"
+
+#define TEMP_CBMEM_ID_VBOOT 0xffffffff
+#define TEMP_CBMEM_ID_VBLOCKS 0xfffffffe
+
+static void vboot_run_stub(struct vboot_context *context)
+{
+ struct rmod_stage_load rmod_stage = {
+ .cbmem_id = TEMP_CBMEM_ID_VBOOT,
+ .name = CONFIG_CBFS_PREFIX "/vboot",
+ };
+ void (*entry)(struct vboot_context *context);
+
+ if (rmodule_stage_load_from_cbfs(&rmod_stage)) {
+ printk(BIOS_DEBUG, "Could not load vboot stub.\n");
+ goto out;
+ }
+
+ entry = rmod_stage.entry;
+
+ /* Call stub. */
+ entry(context);
+
+out:
+ /* Tear down the region no longer needed. */
+ if (rmod_stage.cbmem_entry != NULL)
+ cbmem_entry_remove(rmod_stage.cbmem_entry);
+}
+
+/* Helper routines for the vboot stub. */
+static void log_msg(const char *fmt, va_list args)
+{
+ do_vtxprintf(fmt, args);
+}
+
+static void fatal_error(void)
+{
+ printk(BIOS_ERR, "vboot encountered fatal error. Resetting.\n");
+ hard_reset();
+}
+
+static int fw_region_size(struct vboot_region *r)
+{
+ struct vboot_components *fw_info;
+ int32_t size;
+ int i;
+
+ fw_info = vboot_locate_components(r);
+ if (fw_info == NULL)
+ return -1;
+
+ if (fw_info->num_components > MAX_PARSED_FW_COMPONENTS)
+ return -1;
+
+ size = sizeof(*fw_info);
+ size += sizeof(struct vboot_component_entry) * fw_info->num_components;
+
+ for (i = 0; i < fw_info->num_components; i++)
+ size += ALIGN(fw_info->entries[i].size, sizeof(uint32_t));
+
+ /* Check that size of comopnents does not exceed the region's size. */
+ if (size > r->size)
+ return -1;
+
+ /* Update region with the correct size. */
+ r->size = size;
+
+ return 0;
+}
+
+static int vboot_fill_params(struct vboot_context *ctx)
+{
+ VbCommonParams *cparams;
+ VbSelectFirmwareParams *fparams;
+
+ if (fw_region_size(&ctx->fw_a))
+ return -1;
+
+ if (fw_region_size(&ctx->fw_b))
+ return -1;
+
+ cparams = ctx->cparams;
+ fparams = ctx->fparams;
+
+ cparams->gbb_size = ctx->gbb.size;
+ fparams->verification_size_A = ctx->vblock_a.size;
+ fparams->verification_size_B = ctx->vblock_b.size;
+
+ if (IS_ENABLED(CONFIG_SPI_FLASH_MEMORY_MAPPED)) {
+ /* Get memory-mapped pointers to the regions. */
+ cparams->gbb_data = vboot_get_region(ctx->gbb.offset_addr,
+ ctx->gbb.size, NULL);
+ fparams->verification_block_A =
+ vboot_get_region(ctx->vblock_a.offset_addr,
+ ctx->vblock_a.size, NULL);
+ fparams->verification_block_B =
+ vboot_get_region(ctx->vblock_b.offset_addr,
+ ctx->vblock_b.size, NULL);
+ } else {
+ /*
+ * Copy the vblock info into a buffer in cbmem. The gbb will
+ * be read using VbExRegionRead().
+ */
+ char *dest;
+ size_t vblck_sz;
+
+ vblck_sz = ctx->vblock_a.size + ctx->vblock_b.size;
+ ctx->vblocks = cbmem_entry_add(TEMP_CBMEM_ID_VBLOCKS, vblck_sz);
+ if (ctx->vblocks == NULL)
+ return -1;
+ dest = cbmem_entry_start(ctx->vblocks);
+ if (vboot_get_region(ctx->vblock_a.offset_addr,
+ ctx->vblock_a.size, dest) == NULL)
+ return -1;
+ fparams->verification_block_A = (void *)dest;
+ dest += ctx->vblock_a.size;
+ if (vboot_get_region(ctx->vblock_b.offset_addr,
+ ctx->vblock_b.size, dest) == NULL)
+ return -1;
+ fparams->verification_block_B = (void *)dest;
+ }
+
+ return 0;
+}
+
+static void fill_handoff(struct vboot_context *context)
+{
+ struct vboot_components *fw_info;
+ struct vboot_region *region;
+ int i;
+
+ /* Fix up the handoff structure. */
+ context->handoff->selected_firmware =
+ context->fparams->selected_firmware;
+
+ /* Parse out the components for downstream consumption. */
+ if (context->handoff->selected_firmware == VB_SELECT_FIRMWARE_A)
+ region = &context->fw_a;
+ else if (context->handoff->selected_firmware == VB_SELECT_FIRMWARE_B)
+ region = &context->fw_b;
+ else
+ return;
+
+ fw_info = vboot_locate_components(region);
+ if (fw_info == NULL)
+ return;
+
+ for (i = 0; i < fw_info->num_components; i++) {
+ context->handoff->components[i].address =
+ region->offset_addr + fw_info->entries[i].offset;
+ context->handoff->components[i].size = fw_info->entries[i].size;
+ }
+}
+
+static void vboot_clean_up(struct vboot_context *context)
+{
+ if (context->vblocks != NULL)
+ cbmem_entry_remove(context->vblocks);
+}
+
+static void reset(void)
+{
+ hard_reset();
+}
+
+static void vboot_invoke_wrapper(struct vboot_handoff *vboot_handoff)
+{
+ VbCommonParams cparams;
+ VbSelectFirmwareParams fparams;
+ struct vboot_context context;
+ uint32_t *iflags;
+
+ vboot_handoff->selected_firmware = VB_SELECT_FIRMWARE_READONLY;
+
+ memset(&cparams, 0, sizeof(cparams));
+ memset(&fparams, 0, sizeof(fparams));
+ memset(&context, 0, sizeof(context));
+
+ iflags = &vboot_handoff->init_params.flags;
+ if (get_developer_mode_switch())
+ *iflags |= VB_INIT_FLAG_DEV_SWITCH_ON;
+ if (get_recovery_mode_switch()) {
+ clear_recovery_mode_switch();
+ *iflags |= VB_INIT_FLAG_REC_BUTTON_PRESSED;
+ }
+ if (get_write_protect_state())
+ *iflags |= VB_INIT_FLAG_WP_ENABLED;
+ if (vboot_get_sw_write_protect())
+ *iflags |= VB_INIT_FLAG_SW_WP_ENABLED;
+ if (CONFIG_VIRTUAL_DEV_SWITCH)
+ *iflags |= VB_INIT_FLAG_VIRTUAL_DEV_SWITCH;
+ if (CONFIG_EC_SOFTWARE_SYNC) {
+ *iflags |= VB_INIT_FLAG_EC_SOFTWARE_SYNC;
+ *iflags |= VB_INIT_FLAG_VIRTUAL_REC_SWITCH;
+ }
+ if (CONFIG_VBOOT_EC_SLOW_UPDATE)
+ *iflags |= VB_INIT_FLAG_EC_SLOW_UPDATE;
+ if (CONFIG_VBOOT_OPROM_MATTERS) {
+ *iflags |= VB_INIT_FLAG_OPROM_MATTERS;
+ /* Will load VGA option rom during this boot */
+ if (developer_mode_enabled() || recovery_mode_enabled() ||
+ vboot_wants_oprom()) {
+ *iflags |= VB_INIT_FLAG_OPROM_LOADED;
+ }
+ }
+
+ context.handoff = vboot_handoff;
+ context.cparams = &cparams;
+ context.fparams = &fparams;
+
+ cparams.shared_data_blob = &vboot_handoff->shared_data[0];
+ cparams.shared_data_size = VB_SHARED_DATA_MIN_SIZE;
+ cparams.caller_context = &context;
+
+ vboot_locate_region("GBB", &context.gbb);
+ vboot_locate_region("VBLOCK_A", &context.vblock_a);
+ vboot_locate_region("VBLOCK_B", &context.vblock_b);
+ vboot_locate_region("FW_MAIN_A", &context.fw_a);
+ vboot_locate_region("FW_MAIN_B", &context.fw_b);
+
+ /* Check all fmap entries. */
+ if (context.fw_a.size < 0 || context.fw_b.size < 0 ||
+ context.vblock_a.size < 0 || context.vblock_b.size < 0 ||
+ context.gbb.size < 0) {
+ printk(BIOS_DEBUG, "Not all fmap entries found for vboot.\n");
+ return;
+ }
+
+ /* Fill in vboot parameters. */
+ if (vboot_fill_params(&context)) {
+ vboot_clean_up(&context);
+ return;
+ }
+
+ /* Initialize callbacks. */
+ context.read_vbnv = &read_vbnv;
+ context.save_vbnv = &save_vbnv;
+ context.tis_init = &tis_init;
+ context.tis_open = &tis_open;
+ context.tis_close = &tis_close;
+ context.tis_sendrecv = &tis_sendrecv;
+ context.log_msg = &log_msg;
+ context.fatal_error = &fatal_error;
+ context.get_region = &vboot_get_region;
+ context.reset = &reset;
+
+ vboot_run_stub(&context);
+
+ fill_handoff(&context);
+
+ vboot_clean_up(&context);
+}
+
+#if CONFIG_RELOCATABLE_RAMSTAGE
+static void *vboot_load_ramstage(uint32_t cbmem_id, const char *name,
+ const struct cbmem_entry **cbmem_entry)
+{
+ struct vboot_handoff *vboot_handoff;
+ struct cbfs_stage *stage;
+ const struct firmware_component *fwc;
+ struct rmod_stage_load rmod_load = {
+ .cbmem_id = cbmem_id,
+ .name = name,
+ };
+
+ timestamp_add_now(TS_START_VBOOT);
+
+ vboot_handoff = cbmem_add(CBMEM_ID_VBOOT_HANDOFF,
+ sizeof(*vboot_handoff));
+
+ if (vboot_handoff == NULL) {
+ printk(BIOS_DEBUG, "Could not add vboot_handoff structure.\n");
+ return NULL;
+ }
+
+ memset(vboot_handoff, 0, sizeof(*vboot_handoff));
+
+ vboot_invoke_wrapper(vboot_handoff);
+
+ timestamp_add_now(TS_END_VBOOT);
+
+ /* Take RO firmware path since no RW area was selected. */
+ if (vboot_handoff->selected_firmware != VB_SELECT_FIRMWARE_A &&
+ vboot_handoff->selected_firmware != VB_SELECT_FIRMWARE_B) {
+ printk(BIOS_DEBUG, "No RW firmware selected: 0x%08x\n",
+ vboot_handoff->selected_firmware);
+ return NULL;
+ }
+
+ if (CONFIG_VBOOT_RAMSTAGE_INDEX >= MAX_PARSED_FW_COMPONENTS) {
+ printk(BIOS_ERR, "Invalid ramstage index: %d\n",
+ CONFIG_VBOOT_RAMSTAGE_INDEX);
+ return NULL;
+ }
+
+ /* Check for invalid address. */
+ fwc = &vboot_handoff->components[CONFIG_VBOOT_RAMSTAGE_INDEX];
+ if (fwc->address == 0) {
+ printk(BIOS_DEBUG, "RW ramstage image address invalid.\n");
+ return NULL;
+ }
+
+ printk(BIOS_DEBUG, "RW ramstage image at 0x%08x, 0x%08x bytes.\n",
+ fwc->address, fwc->size);
+
+ stage = (void *)fwc->address;
+
+ if (rmodule_stage_load(&rmod_load, stage)) {
+ vboot_handoff->selected_firmware = VB_SELECT_FIRMWARE_READONLY;
+ printk(BIOS_DEBUG, "Could not load ramstage region.\n");
+ return NULL;
+ }
+
+ *cbmem_entry = rmod_load.cbmem_entry;
+
+ return rmod_load.entry;
+}
+#else /* CONFIG_RELOCATABLE_RAMSTAGE */
+static void vboot_load_ramstage(struct vboot_handoff *vboot_handoff,
+ struct romstage_handoff *handoff)
+{
+ struct cbfs_stage *stage;
+ const struct firmware_component *fwc;
+
+ if (CONFIG_VBOOT_RAMSTAGE_INDEX >= MAX_PARSED_FW_COMPONENTS) {
+ printk(BIOS_ERR, "Invalid ramstage index: %d\n",
+ CONFIG_VBOOT_RAMSTAGE_INDEX);
+ return;
+ }
+
+ /* Check for invalid address. */
+ fwc = &vboot_handoff->components[CONFIG_VBOOT_RAMSTAGE_INDEX];
+ if (fwc->address == 0) {
+ printk(BIOS_DEBUG, "RW ramstage image address invalid.\n");
+ return;
+ }
+
+ printk(BIOS_DEBUG, "RW ramstage image at 0x%08x, 0x%08x bytes.\n",
+ fwc->address, fwc->size);
+
+ /* This will leak a mapping. */
+ stage = vboot_get_region(fwc->address, fwc->size, NULL);
+
+ if (stage == NULL) {
+ printk(BIOS_DEBUG, "Unable to get RW ramstage region.\n");
+ return;
+ }
+
+ timestamp_add_now(TS_START_COPYRAM);
+
+ /* Stages rely the below clearing so that the bss is initialized. */
+ memset((void *) (uintptr_t) stage->load, 0, stage->memlen);
+
+ if (cbfs_decompress(stage->compression,
+ ((unsigned char *) stage) +
+ sizeof(struct cbfs_stage),
+ (void *) (uintptr_t) stage->load,
+ stage->len))
+ return;
+
+ timestamp_add_now(TS_END_COPYRAM);
+
+#if CONFIG_ARCH_X86
+ __asm__ volatile (
+ "movl $0, %%ebp\n"
+ "jmp *%%edi\n"
+ :: "D"(stage->entry)
+ );
+#elif CONFIG_ARCH_ARM
+ stage_exit((void *)(uintptr_t)stage->entry);
+#endif
+}
+#endif /* CONFIG_RELOCATABLE_RAMSTAGE */
+
+
+const struct ramstage_loader_ops vboot_ramstage_loader = {
+ .name = "VBOOT",
+ .load = vboot_load_ramstage,
+};
diff --git a/src/vendorcode/google/chromeos/vboot1/vboot_wrapper.c b/src/vendorcode/google/chromeos/vboot1/vboot_wrapper.c
new file mode 100644
index 0000000..5b9dbbb
--- /dev/null
+++ b/src/vendorcode/google/chromeos/vboot1/vboot_wrapper.c
@@ -0,0 +1,266 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2013 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.
+ *
+ * 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 <console/vtxprintf.h>
+#if CONFIG_ARCH_X86
+#include <cpu/x86/tsc.h>
+#else
+#include <timer.h>
+#endif
+#include <rmodule.h>
+#include <stdlib.h>
+#include <string.h>
+#include "../vboot_context.h"
+#include "../vboot_handoff.h"
+
+/* Keep a global context pointer around for the callbacks to use. */
+static struct vboot_context *gcontext;
+
+static void vboot_wrapper(void *arg)
+{
+ VbError_t res;
+ struct vboot_context *context;
+
+ context = arg;
+ gcontext = context;
+
+ VbExDebug("Calling VbInit()\n");
+ res = VbInit(context->cparams, &context->handoff->init_params);
+ VbExDebug("VbInit() returned 0x%08x\n", res);
+
+ if (res != VBERROR_SUCCESS) {
+ if(res == VBERROR_TPM_REBOOT_REQUIRED) {
+ VbExDebug("TPM Reboot Required. Proceeding reboot.\n");
+ gcontext->reset();
+ }
+ return;
+ }
+
+ VbExDebug("Calling VbSelectFirmware()\n");
+ res = VbSelectFirmware(context->cparams, context->fparams);
+ VbExDebug("VbSelectFirmware() returned 0x%08x\n", res);
+
+ if (res != VBERROR_SUCCESS)
+ return;
+}
+
+void VbExError(const char *format, ...)
+{
+ va_list args;
+
+ va_start(args, format);
+ gcontext->log_msg(format, args);
+ va_end(args);
+
+ gcontext->fatal_error();
+}
+
+void VbExDebug(const char *format, ...)
+{
+ va_list args;
+
+ va_start(args, format);
+ gcontext->log_msg(format, args);
+ va_end(args);
+}
+
+uint64_t VbExGetTimer(void)
+{
+#if CONFIG_ARCH_X86
+ return rdtscll();
+#else
+ struct mono_time mt;
+ timer_monotonic_get(&mt);
+ return mt.microseconds;
+#endif
+}
+
+VbError_t VbExNvStorageRead(uint8_t *buf)
+{
+ gcontext->read_vbnv(buf);
+ return VBERROR_SUCCESS;
+}
+
+VbError_t VbExNvStorageWrite(const uint8_t *buf)
+{
+ gcontext->save_vbnv(buf);
+ return VBERROR_SUCCESS;
+}
+
+extern char _heap[];
+extern char _eheap[];
+static char *heap_current;
+static int heap_size;
+
+void *VbExMalloc(size_t size)
+{
+ void *ptr;
+
+ if (heap_current == NULL) {
+ heap_current = &_heap[0];
+ heap_size = &_eheap[0] - &_heap[0];
+ VbExDebug("vboot heap: %p 0x%08x bytes\n",
+ heap_current, heap_size);
+ }
+
+ if (heap_size < size) {
+ VbExError("vboot heap request cannot be fulfilled. "
+ "0x%08x available, 0x%08x requested\n",
+ heap_size, size);
+ }
+
+ ptr = heap_current;
+ heap_size -= size;
+ heap_current += size;
+
+ return ptr;
+}
+
+void VbExFree(void *ptr)
+{
+ /* Leak all memory. */
+}
+
+/* vboot doesn't expose these through the vboot_api.h, but they are needed.
+ * coreboot requires declarations so provide them to avoid compiler errors. */
+int Memcmp(const void *src1, const void *src2, size_t n);
+void *Memcpy(void *dest, const void *src, uint64_t n);
+void *Memset(void *dest, const uint8_t c, uint64_t n);
+
+int Memcmp(const void *src1, const void *src2, size_t n)
+{
+ return memcmp(src1, src2, n);
+}
+
+void *Memcpy(void *dest, const void *src, uint64_t n)
+{
+ return memcpy(dest, src, n);
+}
+
+void *Memset(void *dest, const uint8_t c, uint64_t n)
+{
+ return memset(dest, c, n);
+}
+
+static inline size_t get_hash_block_size(size_t requested_size)
+{
+ if (!IS_ENABLED(CONFIG_SPI_FLASH_MEMORY_MAPPED)) {
+ const size_t block_size = 64 * 1024;
+ if (requested_size > block_size)
+ return block_size;
+ }
+ return requested_size;
+}
+
+VbError_t VbExHashFirmwareBody(VbCommonParams *cparams, uint32_t firmware_index)
+{
+ uint8_t *data;
+ struct vboot_region *region;
+ struct vboot_context *ctx;
+ size_t data_size;
+ uintptr_t offset_addr;
+
+ ctx = cparams->caller_context;
+
+ switch (firmware_index) {
+ case VB_SELECT_FIRMWARE_A:
+ region = &ctx->fw_a;
+ break;
+ case VB_SELECT_FIRMWARE_B:
+ region = &ctx->fw_b;
+ break;
+ default:
+ return VBERROR_UNKNOWN;
+ }
+
+ data_size = region->size;
+ offset_addr = region->offset_addr;
+ while (data_size) {
+ size_t block_size;
+
+ block_size = get_hash_block_size(data_size);
+ data = ctx->get_region(offset_addr, block_size, NULL);
+ if (data == NULL)
+ return VBERROR_UNKNOWN;
+ VbUpdateFirmwareBodyHash(cparams, data, block_size);
+
+ data_size -= block_size;
+ offset_addr += block_size;
+ }
+
+ return VBERROR_SUCCESS;
+}
+
+VbError_t VbExTpmInit(void)
+{
+ if (gcontext->tis_init())
+ return VBERROR_UNKNOWN;
+ return VbExTpmOpen();
+}
+
+VbError_t VbExTpmClose(void)
+{
+ if (gcontext->tis_close())
+ return VBERROR_UNKNOWN;
+ return VBERROR_SUCCESS;
+}
+
+VbError_t VbExTpmOpen(void)
+{
+ if (gcontext->tis_open())
+ return VBERROR_UNKNOWN;
+ return VBERROR_SUCCESS;
+}
+
+VbError_t VbExTpmSendReceive(const uint8_t *request, uint32_t request_length,
+ uint8_t *response, uint32_t *response_length)
+{
+ size_t len = *response_length;
+ if (gcontext->tis_sendrecv(request, request_length, response, &len))
+ return VBERROR_UNKNOWN;
+ /* check 64->32bit overflow and (re)check response buffer overflow */
+ if (len > *response_length)
+ return VBERROR_UNKNOWN;
+ *response_length = len;
+ return VBERROR_SUCCESS;
+}
+
+#if !CONFIG_SPI_FLASH_MEMORY_MAPPED
+VbError_t VbExRegionRead(VbCommonParams *cparams,
+ enum vb_firmware_region region, uint32_t offset,
+ uint32_t size, void *buf)
+{
+ struct vboot_context *ctx;
+ VbExDebug("VbExRegionRead: offset=%x size=%x, buf=%p\n",
+ offset, size, buf);
+ ctx = cparams->caller_context;
+
+ if (region == VB_REGION_GBB) {
+ if (offset + size > cparams->gbb_size)
+ return VBERROR_REGION_READ_INVALID;
+ offset += ctx->gbb.offset_addr;
+ if (ctx->get_region(offset, size, buf) == NULL)
+ return VBERROR_REGION_READ_INVALID;
+ return VBERROR_SUCCESS;
+ }
+
+ return VBERROR_UNSUPPORTED_REGION;
+}
+#endif /* CONFIG_SPI_FLASH_MEMORY_MAPPED */
+
+RMODULE_ENTRY(vboot_wrapper);
diff --git a/src/vendorcode/google/chromeos/vboot2/Kconfig b/src/vendorcode/google/chromeos/vboot2/Kconfig
new file mode 100644
index 0000000..20d2f1f
--- /dev/null
+++ b/src/vendorcode/google/chromeos/vboot2/Kconfig
@@ -0,0 +1,43 @@
+## This file is part of the coreboot project.
+##
+## Copyright (C) 2014 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
+##
+
+config VBOOT2_VERIFY_FIRMWARE
+ bool "Firmware Verification with vboot2"
+ default n
+ depends on CHROMEOS && HAVE_HARD_RESET
+ help
+ Enabling VBOOT2_VERIFY_FIRMWARE will use vboot2 to verify the romstage
+ and boot loader.
+
+config RETURN_FROM_VERSTAGE
+ bool "return from verstage"
+ default n
+ depends on VBOOT2_VERIFY_FIRMWARE
+ help
+ If this is set, the verstage returns back to the bootblock instead of
+ exits to the romstage so that the verstage space can be reused by the
+ romstage. Useful if a ram space is too small to fit both the verstage
+ and the romstage.
+
+config VBOOT_ROMSTAGE_INDEX
+ hex
+ default 2
+ depends on VBOOT2_VERIFY_FIRMWARE
+ help
+ This is the index of the romstage component in the verified
+ firmware block.
diff --git a/src/vendorcode/google/chromeos/vboot2/Makefile.inc b/src/vendorcode/google/chromeos/vboot2/Makefile.inc
new file mode 100644
index 0000000..8dcba9c
--- /dev/null
+++ b/src/vendorcode/google/chromeos/vboot2/Makefile.inc
@@ -0,0 +1,60 @@
+##
+## This file is part of the coreboot project.
+##
+## Copyright (C) 2014 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
+##
+
+verstage-generic-ccopts += -D__PRE_RAM__ -D__VERSTAGE__
+
+ramstage-y += ../vboot_common.c
+romstage-y += ../vboot_common.c
+
+ifeq ($(CONFIG_RETURN_FROM_VERSTAGE),y)
+bootblock-y += common.c verstub.c ../chromeos.c ../vboot_common.c
+else
+verstage-y += verstub.c
+endif
+verstage-y += verstage.c ../fmap.c ../chromeos.c ../vboot_common.c
+verstage-y += antirollback.c common.c
+verstage-$(CONFIG_CHROMEOS_VBNV_CMOS) += ../vbnv_cmos.c
+verstage-$(CONFIG_CHROMEOS_VBNV_EC) += ../vbnv_ec.c
+verstage-$(CONFIG_CHROMEOS_VBNV_FLASH) += ../vbnv_flash.c
+romstage-y += vboot_handoff.c common.c
+
+verstage-y += verstage.ld
+
+VB_FIRMWARE_ARCH := $(ARCHDIR-$(ARCH-VERSTAGE-y))
+VB2_LIB = $(obj)/external/vboot_reference/vboot_fw2.a
+VBOOT_CFLAGS += $(patsubst -I%,-I$(top)/%,$(filter-out -include $(src)/include/kconfig.h, $(CFLAGS_verstage)))
+VBOOT_CFLAGS += $(verstage-c-ccopts)
+VBOOT_CFLAGS += -include $(top)/src/include/kconfig.h -Wno-missing-prototypes
+VBOOT_CFLAGS += -DVBOOT_DEBUG
+
+$(VB2_LIB): | $$(generic-deps)
+ @printf " MAKE $(subst $(obj)/,,$(@))\n"
+ $(Q)FIRMWARE_ARCH=$(VB_FIRMWARE_ARCH) \
+ CC="$(CC_verstage)" \
+ CFLAGS="$(VBOOT_CFLAGS)" VBOOT2="y" \
+ $(MAKE) -C $(VB_SOURCE) \
+ BUILD=$(top)/$(dir $(VB2_LIB)) \
+ V=$(V) \
+ fwlib2
+
+VERSTAGE_ELF = $(objcbfs)/verstage.elf
+cbfs-files-y += $(call strip_quotes,$(CONFIG_CBFS_PREFIX))/verstage
+fallback/verstage-file = $(VERSTAGE_ELF)
+fallback/verstage-type = stage
+fallback/verstage-compression = none
\ No newline at end of file
diff --git a/src/vendorcode/google/chromeos/vboot2/antirollback.c b/src/vendorcode/google/chromeos/vboot2/antirollback.c
new file mode 100644
index 0000000..bb547b5
--- /dev/null
+++ b/src/vendorcode/google/chromeos/vboot2/antirollback.c
@@ -0,0 +1,329 @@
+/* Copyright (c) 2013 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.
+ *
+ * Functions for querying, manipulating and locking rollback indices
+ * stored in the TPM NVRAM.
+ */
+
+#include <2api.h>
+#include <2sysincludes.h>
+#include <antirollback.h>
+#include <tpm_lite/tlcl.h>
+#include <tpm_lite/tss_constants.h>
+
+#ifndef offsetof
+#define offsetof(A,B) __builtin_offsetof(A,B)
+#endif
+
+#ifdef FOR_TEST
+#include <stdio.h>
+#define VBDEBUG(format, args...) printf(format, ## args)
+#else
+#include <console/console.h>
+#define VBDEBUG(format, args...) \
+ printk(BIOS_INFO, "%s():%d: " format, __func__, __LINE__, ## args)
+#endif
+
+#define RETURN_ON_FAILURE(tpm_cmd) do { \
+ uint32_t result_; \
+ if ((result_ = (tpm_cmd)) != TPM_SUCCESS) { \
+ VBDEBUG("Antirollback: %08x returned by " #tpm_cmd \
+ "\n", (int)result_); \
+ return result_; \
+ } \
+ } while (0)
+
+uint32_t tpm_clear_and_reenable(void)
+{
+ VBDEBUG("TPM: Clear and re-enable\n");
+ RETURN_ON_FAILURE(tlcl_force_clear());
+ RETURN_ON_FAILURE(tlcl_set_enable());
+ RETURN_ON_FAILURE(tlcl_set_deactivated(0));
+
+ return TPM_SUCCESS;
+}
+
+uint32_t safe_write(uint32_t index, const void *data, uint32_t length)
+{
+ uint32_t result = tlcl_write(index, data, length);
+ if (result == TPM_E_MAXNVWRITES) {
+ RETURN_ON_FAILURE(tpm_clear_and_reenable());
+ return tlcl_write(index, data, length);
+ } else {
+ return result;
+ }
+}
+
+uint32_t safe_define_space(uint32_t index, uint32_t perm, uint32_t size)
+{
+ uint32_t result = tlcl_define_space(index, perm, size);
+ if (result == TPM_E_MAXNVWRITES) {
+ RETURN_ON_FAILURE(tpm_clear_and_reenable());
+ return tlcl_define_space(index, perm, size);
+ } else {
+ return result;
+ }
+}
+
+static uint32_t read_space_firmware(struct vb2_context *ctx)
+{
+ int attempts = 3;
+
+ while (attempts--) {
+ RETURN_ON_FAILURE(tlcl_read(FIRMWARE_NV_INDEX, ctx->secdata,
+ VB2_SECDATA_SIZE));
+
+ if (vb2api_secdata_check(ctx) == VB2_SUCCESS)
+ return TPM_SUCCESS;
+
+ VBDEBUG("TPM: %s() - bad CRC\n", __func__);
+ }
+
+ VBDEBUG("TPM: %s() - too many bad CRCs, giving up\n", __func__);
+ return TPM_E_CORRUPTED_STATE;
+}
+
+static uint32_t write_secdata(uint32_t index,
+ const uint8_t *secdata,
+ uint32_t len)
+{
+ uint8_t sd[32];
+ uint32_t rv;
+ int attempts = 3;
+
+ if (len > sizeof(sd)) {
+ VBDEBUG("TPM: %s() - data is too large\n", __func__);
+ return TPM_E_WRITE_FAILURE;
+ }
+
+ while (attempts--) {
+ rv = safe_write(index, secdata, len);
+ /* Can't write, not gonna try again */
+ if (rv != TPM_SUCCESS)
+ return rv;
+
+ /* Read it back to be sure it got the right values. */
+ rv = tlcl_read(index, sd, len);
+ if (rv == TPM_SUCCESS && memcmp(secdata, sd, len) == 0)
+ return rv;
+
+ VBDEBUG("TPM: %s() failed. trying again\n", __func__);
+ /* Try writing it again. Maybe it was garbled on the way out. */
+ }
+
+ VBDEBUG("TPM: %s() - too many failures, giving up\n", __func__);
+
+ return TPM_E_CORRUPTED_STATE;
+}
+
+uint32_t factory_initialize_tpm(struct vb2_context *ctx)
+{
+ TPM_PERMANENT_FLAGS pflags;
+ uint32_t result;
+ /* this is derived from rollback_index.h of vboot_reference. see struct
+ * RollbackSpaceKernel for details. */
+ static const uint8_t secdata_kernel[] = {
+ 0x02,
+ 0x4C, 0x57, 0x52, 0x47,
+ 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00,
+ 0xE8,
+ };
+
+ VBDEBUG("TPM: factory initialization\n");
+
+ /*
+ * Do a full test. This only happens the first time the device is
+ * turned on in the factory, so performance is not an issue. This is
+ * almost certainly not necessary, but it gives us more confidence
+ * about some code paths below that are difficult to
+ * test---specifically the ones that set lifetime flags, and are only
+ * executed once per physical TPM.
+ */
+ result = tlcl_self_test_full();
+ if (result != TPM_SUCCESS)
+ return result;
+
+ result = tlcl_get_permanent_flags(&pflags);
+ if (result != TPM_SUCCESS)
+ return result;
+
+ /*
+ * TPM may come from the factory without physical presence finalized.
+ * Fix if necessary.
+ */
+ VBDEBUG("TPM: physicalPresenceLifetimeLock=%d\n",
+ pflags.physicalPresenceLifetimeLock);
+ if (!pflags.physicalPresenceLifetimeLock) {
+ VBDEBUG("TPM: Finalizing physical presence\n");
+ RETURN_ON_FAILURE(tlcl_finalize_physical_presence());
+ }
+
+ /*
+ * The TPM will not enforce the NV authorization restrictions until the
+ * execution of a TPM_NV_DefineSpace with the handle of
+ * TPM_NV_INDEX_LOCK. Here we create that space if it doesn't already
+ * exist. */
+ VBDEBUG("TPM: nvLocked=%d\n", pflags.nvLocked);
+ if (!pflags.nvLocked) {
+ VBDEBUG("TPM: Enabling NV locking\n");
+ RETURN_ON_FAILURE(tlcl_set_nv_locked());
+ }
+
+ /* Clear TPM owner, in case the TPM is already owned for some reason. */
+ VBDEBUG("TPM: Clearing owner\n");
+ RETURN_ON_FAILURE(tpm_clear_and_reenable());
+
+ /* Define the backup space. No need to initialize it, though. */
+ RETURN_ON_FAILURE(safe_define_space(BACKUP_NV_INDEX,
+ TPM_NV_PER_PPWRITE,
+ VB2_NVDATA_SIZE));
+
+ /* Define and initialize the kernel space */
+ RETURN_ON_FAILURE(safe_define_space(KERNEL_NV_INDEX,
+ TPM_NV_PER_PPWRITE,
+ sizeof(secdata_kernel)));
+ RETURN_ON_FAILURE(write_secdata(KERNEL_NV_INDEX,
+ secdata_kernel,
+ sizeof(secdata_kernel)));
+
+ /* Defines and sets vb2 secdata space */
+ vb2api_secdata_create(ctx);
+ RETURN_ON_FAILURE(safe_define_space(FIRMWARE_NV_INDEX,
+ TPM_NV_PER_GLOBALLOCK |
+ TPM_NV_PER_PPWRITE,
+ VB2_SECDATA_SIZE));
+ RETURN_ON_FAILURE(write_secdata(FIRMWARE_NV_INDEX,
+ ctx->secdata,
+ VB2_SECDATA_SIZE));
+
+ VBDEBUG("TPM: factory initialization successful\n");
+
+ return TPM_SUCCESS;
+}
+
+/*
+ * SetupTPM starts the TPM and establishes the root of trust for the
+ * anti-rollback mechanism. SetupTPM can fail for three reasons. 1 A bug. 2 a
+ * TPM hardware failure. 3 An unexpected TPM state due to some attack. In
+ * general we cannot easily distinguish the kind of failure, so our strategy is
+ * to reboot in recovery mode in all cases. The recovery mode calls SetupTPM
+ * again, which executes (almost) the same sequence of operations. There is a
+ * good chance that, if recovery mode was entered because of a TPM failure, the
+ * failure will repeat itself. (In general this is impossible to guarantee
+ * because we have no way of creating the exact TPM initial state at the
+ * previous boot.) In recovery mode, we ignore the failure and continue, thus
+ * giving the recovery kernel a chance to fix things (that's why we don't set
+ * bGlobalLock). The choice is between a knowingly insecure device and a
+ * bricked device.
+ *
+ * As a side note, observe that we go through considerable hoops to avoid using
+ * the STCLEAR permissions for the index spaces. We do this to avoid writing
+ * to the TPM flashram at every reboot or wake-up, because of concerns about
+ * the durability of the NVRAM.
+ */
+uint32_t setup_tpm(struct vb2_context *ctx)
+{
+ uint8_t disable;
+ uint8_t deactivated;
+ uint32_t result;
+
+ RETURN_ON_FAILURE(tlcl_lib_init());
+
+#ifdef TEGRA_SOFT_REBOOT_WORKAROUND
+ result = tlcl_startup();
+ if (result == TPM_E_INVALID_POSTINIT) {
+ /*
+ * Some prototype hardware doesn't reset the TPM on a CPU
+ * reset. We do a hard reset to get around this.
+ */
+ VBDEBUG("TPM: soft reset detected\n", result);
+ return TPM_E_MUST_REBOOT;
+ } else if (result != TPM_SUCCESS) {
+ VBDEBUG("TPM: tlcl_startup returned %08x\n", result);
+ return result;
+ }
+#else
+ RETURN_ON_FAILURE(tlcl_startup());
+#endif
+
+ /*
+ * Some TPMs start the self test automatically at power on. In that case
+ * we don't need to call ContinueSelfTest. On some (other) TPMs,
+ * continue_self_test may block. In that case, we definitely don't want
+ * to call it here. For TPMs in the intersection of these two sets, we
+ * are screwed. (In other words: TPMs that require manually starting the
+ * self-test AND block will have poor performance until we split
+ * tlcl_send_receive() into send() and receive(), and have a state
+ * machine to control setup.)
+ *
+ * This comment is likely to become obsolete in the near future, so
+ * don't trust it. It may have not been updated.
+ */
+#ifdef TPM_MANUAL_SELFTEST
+#ifdef TPM_BLOCKING_CONTINUESELFTEST
+#warning "lousy TPM!"
+#endif
+ RETURN_ON_FAILURE(tlcl_continue_self_test());
+#endif
+ result = tlcl_assert_physical_presence();
+ if (result != TPM_SUCCESS) {
+ /*
+ * It is possible that the TPM was delivered with the physical
+ * presence command disabled. This tries enabling it, then
+ * tries asserting PP again.
+ */
+ RETURN_ON_FAILURE(tlcl_physical_presence_cmd_enable());
+ RETURN_ON_FAILURE(tlcl_assert_physical_presence());
+ }
+
+ /* Check that the TPM is enabled and activated. */
+ RETURN_ON_FAILURE(tlcl_get_flags(&disable, &deactivated, NULL));
+ if (disable || deactivated) {
+ VBDEBUG("TPM: disabled (%d) or deactivated (%d). Fixing...\n",
+ disable, deactivated);
+ RETURN_ON_FAILURE(tlcl_set_enable());
+ RETURN_ON_FAILURE(tlcl_set_deactivated(0));
+ VBDEBUG("TPM: Must reboot to re-enable\n");
+ return TPM_E_MUST_REBOOT;
+ }
+
+ VBDEBUG("TPM: SetupTPM() succeeded\n");
+ return TPM_SUCCESS;
+}
+
+uint32_t antirollback_read_space_firmware(struct vb2_context *ctx)
+{
+ uint32_t rv;
+
+ rv = setup_tpm(ctx);
+ if (rv)
+ return rv;
+
+ /* Read the firmware space. */
+ rv = read_space_firmware(ctx);
+ if (rv == TPM_E_BADINDEX) {
+ /*
+ * This seems the first time we've run. Initialize the TPM.
+ */
+ VBDEBUG("TPM: Not initialized yet.\n");
+ RETURN_ON_FAILURE(factory_initialize_tpm(ctx));
+ } else if (rv != TPM_SUCCESS) {
+ VBDEBUG("TPM: Firmware space in a bad state; giving up.\n");
+ //RETURN_ON_FAILURE(factory_initialize_tpm(ctx));
+ return TPM_E_CORRUPTED_STATE;
+ }
+
+ return TPM_SUCCESS;
+}
+
+uint32_t antirollback_write_space_firmware(struct vb2_context *ctx)
+{
+ return write_secdata(FIRMWARE_NV_INDEX, ctx->secdata, VB2_SECDATA_SIZE);
+}
+
+uint32_t antirollback_lock_space_firmware()
+{
+ return tlcl_set_global_lock();
+}
diff --git a/src/vendorcode/google/chromeos/vboot2/common.c b/src/vendorcode/google/chromeos/vboot2/common.c
new file mode 100644
index 0000000..178e8b5
--- /dev/null
+++ b/src/vendorcode/google/chromeos/vboot2/common.c
@@ -0,0 +1,70 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2014 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 <cbfs.h>
+#include <console/console.h>
+#include <reset.h>
+#include "../chromeos.h"
+#include "../vboot_handoff.h"
+#include "misc.h"
+#include "symbols.h"
+
+void *vboot_load_stage(int stage_index,
+ struct vboot_region *fw_main,
+ struct vboot_components *fw_info)
+{
+ struct cbfs_media default_media, *media = &default_media;
+ uintptr_t fc_addr;
+ uint32_t fc_size;
+ void *entry;
+
+ if (stage_index >= fw_info->num_components) {
+ printk(BIOS_INFO, "invalid stage index\n");
+ return NULL;
+ }
+
+ fc_addr = fw_main->offset_addr + fw_info->entries[stage_index].offset;
+ fc_size = fw_info->entries[stage_index].size;
+ if (fc_size == 0 ||
+ fc_addr + fc_size > fw_main->offset_addr + fw_main->size) {
+ printk(BIOS_INFO, "invalid stage address or size\n");
+ return NULL;
+ }
+
+ init_default_cbfs_media(media);
+
+ /* we're making cbfs access offset outside of the region managed by
+ * cbfs. this works because cbfs_load_stage_by_offset does not check
+ * the offset. */
+ entry = cbfs_load_stage_by_offset(media, fc_addr);
+ if (entry == (void *)-1)
+ entry = NULL;
+ return entry;
+}
+
+struct vb2_working_data * const vboot_get_working_data(void)
+{
+ return (struct vb2_working_data *)_vboot2_work;
+}
+
+void vboot_reboot(void)
+{
+ hard_reset();
+ die("failed to reboot");
+}
diff --git a/src/vendorcode/google/chromeos/vboot2/memlayout.h b/src/vendorcode/google/chromeos/vboot2/memlayout.h
new file mode 100644
index 0000000..9e19200
--- /dev/null
+++ b/src/vendorcode/google/chromeos/vboot2/memlayout.h
@@ -0,0 +1,47 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright 2014 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.
+ *
+ * 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 file contains macro definitions for memlayout.ld linker scripts. */
+
+#ifndef __CHROMEOS_VBOOT2_MEMLAYOUT_H
+#define __CHROMEOS_VBOOT2_MEMLAYOUT_H
+
+#define VBOOT2_WORK(addr, size) \
+ REGION(vboot2_work, addr, size, 4) \
+ _ = ASSERT(size >= 16K, "vboot2 work buffer must be at least 16K!");
+
+#ifdef __VERSTAGE__
+ #define VERSTAGE(addr, sz) \
+ SET_COUNTER(VERSTAGE, addr) \
+ _ = ASSERT(_everstage - _verstage <= sz, \
+ STR(Verstage exceeded its allotted size! (sz))); \
+ INCLUDE "vendorcode/google/chromeos/vboot2/verstage.verstage.ld"
+#else
+ #define VERSTAGE(addr, sz) \
+ SET_COUNTER(VERSTAGE, addr) \
+ . += sz;
+#endif
+
+#ifdef __VERSTAGE__
+ #define OVERLAP_VERSTAGE_ROMSTAGE(addr, size) VERSTAGE(addr, size)
+#else
+ #define OVERLAP_VERSTAGE_ROMSTAGE(addr, size) ROMSTAGE(addr, size)
+#endif
+
+#endif /* __CHROMEOS_VBOOT2_MEMLAYOUT_H */
diff --git a/src/vendorcode/google/chromeos/vboot2/misc.h b/src/vendorcode/google/chromeos/vboot2/misc.h
new file mode 100644
index 0000000..cae302b
--- /dev/null
+++ b/src/vendorcode/google/chromeos/vboot2/misc.h
@@ -0,0 +1,72 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2014 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_VBOOT2_MISC_H__
+#define __CHROMEOS_VBOOT2_MISC_H__
+
+#include "../vboot_common.h"
+
+void vboot2_verify_firmware(void);
+void *vboot2_load_ramstage(void);
+void verstage_main(void);
+void *vboot_load_stage(int stage_index,
+ struct vboot_region *fw_main,
+ struct vboot_components *fw_info);
+void vboot_reboot(void);
+
+/*
+ * this is placed at the start of the vboot work buffer. selected_region is used
+ * for the verstage to return the location of the selected slot. buffer is used
+ * by the vboot2 core. Keep the struct cpu architecture agnostic as it crosses
+ * stage boundaries.
+ */
+struct vb2_working_data {
+ uint32_t selected_region_offset;
+ uint32_t selected_region_size;
+ uint64_t buffer_size;
+ uint64_t buffer;
+};
+
+struct vb2_working_data * const vboot_get_working_data(void);
+
+static inline void vb2_get_selected_region(struct vb2_working_data *wd,
+ struct vboot_region *region)
+{
+ region->offset_addr = wd->selected_region_offset;
+ region->size = wd->selected_region_size;
+}
+
+static inline void vb2_set_selected_region(struct vb2_working_data *wd,
+ struct vboot_region *region)
+{
+ wd->selected_region_offset = region->offset_addr;
+ wd->selected_region_size = region->size;
+}
+
+static inline int vboot_is_slot_selected(struct vb2_working_data *wd)
+{
+ return wd->selected_region_size > 0;
+}
+
+static inline int vboot_is_readonly_path(struct vb2_working_data *wd)
+{
+ return wd->selected_region_size == 0;
+}
+
+#endif /* __CHROMEOS_VBOOT2_MISC_H__ */
diff --git a/src/vendorcode/google/chromeos/vboot2/symbols.h b/src/vendorcode/google/chromeos/vboot2/symbols.h
new file mode 100644
index 0000000..fda7114
--- /dev/null
+++ b/src/vendorcode/google/chromeos/vboot2/symbols.h
@@ -0,0 +1,32 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright 2014 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.
+ *
+ * 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_VBOOT2_SYMBOLS_H
+#define __CHROMEOS_VBOOT2_SYMBOLS_H
+
+extern u8 _vboot2_work[];
+extern u8 _evboot2_work[];
+#define _vboot2_work_size (_evboot2_work - _vboot2_work)
+
+/* Careful: _e<stage> and _<stage>_size only defined for the current stage! */
+extern u8 _verstage[];
+extern u8 _everstage[];
+#define _verstage_size (_everstage - _verstage)
+
+#endif /* __CHROMEOS_VBOOT2_SYMBOLS_H */
diff --git a/src/vendorcode/google/chromeos/vboot2/vboot_handoff.c b/src/vendorcode/google/chromeos/vboot2/vboot_handoff.c
new file mode 100644
index 0000000..a8573d0
--- /dev/null
+++ b/src/vendorcode/google/chromeos/vboot2/vboot_handoff.c
@@ -0,0 +1,175 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2013 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.
+ *
+ * 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 <2recovery_reasons.h>
+#include <2struct.h>
+#include <arch/stages.h>
+#include <assert.h>
+#include <stdint.h>
+#include <stddef.h>
+#include <string.h>
+#include <cbfs.h>
+#include <cbmem.h>
+#include <console/console.h>
+#include <console/vtxprintf.h>
+#include <stdlib.h>
+#include <timestamp.h>
+#include <vboot_struct.h>
+#include "../chromeos.h"
+#include "../fmap.h"
+#include "../vboot_handoff.h"
+#include "misc.h"
+
+static void *load_ramstage(struct vboot_handoff *vboot_handoff,
+ struct vboot_region *fw_main)
+{
+ struct vboot_components *fw_info;
+ int i;
+
+ fw_info = vboot_locate_components(fw_main);
+ if (fw_info == NULL)
+ die("failed to locate firmware components\n");
+
+ /* these offset & size are used to load a rw boot loader */
+ for (i = 0; i < fw_info->num_components; i++) {
+ vboot_handoff->components[i].address =
+ fw_main->offset_addr + fw_info->entries[i].offset;
+ vboot_handoff->components[i].size = fw_info->entries[i].size;
+ }
+
+ return vboot_load_stage(CONFIG_VBOOT_RAMSTAGE_INDEX, fw_main, fw_info);
+}
+
+/**
+ * Sets vboot_handoff based on the information in vb2_shared_data
+ *
+ * TODO: Read wp switch to set VBSD_BOOT_FIRMWARE_WP_ENABLED
+ */
+static void fill_vboot_handoff(struct vboot_handoff *vboot_handoff,
+ struct vb2_shared_data *vb2_sd)
+{
+ VbSharedDataHeader *vb_sd =
+ (VbSharedDataHeader *)vboot_handoff->shared_data;
+ uint32_t *oflags = &vboot_handoff->init_params.out_flags;
+
+ vb_sd->flags |= VBSD_BOOT_FIRMWARE_VBOOT2;
+
+ vboot_handoff->selected_firmware = vb2_sd->fw_slot;
+
+ vb_sd->firmware_index = vb2_sd->fw_slot;
+
+ vb_sd->magic = VB_SHARED_DATA_MAGIC;
+ vb_sd->struct_version = VB_SHARED_DATA_VERSION;
+ vb_sd->struct_size = sizeof(VbSharedDataHeader);
+ vb_sd->data_size = VB_SHARED_DATA_MIN_SIZE;
+ vb_sd->data_used = sizeof(VbSharedDataHeader);
+
+ if (vb2_sd->recovery_reason) {
+ vb_sd->firmware_index = 0xFF;
+ if (vb2_sd->recovery_reason == VB2_RECOVERY_RO_MANUAL)
+ vb_sd->flags |= VBSD_BOOT_REC_SWITCH_ON;
+ *oflags |= VB_INIT_OUT_ENABLE_RECOVERY;
+ *oflags |= VB_INIT_OUT_CLEAR_RAM;
+ *oflags |= VB_INIT_OUT_ENABLE_DISPLAY;
+ *oflags |= VB_INIT_OUT_ENABLE_USB_STORAGE;
+ }
+ if (vb2_sd->flags & VB2_SD_DEV_MODE_ENABLED) {
+ *oflags |= VB_INIT_OUT_ENABLE_DEVELOPER;
+ *oflags |= VB_INIT_OUT_CLEAR_RAM;
+ *oflags |= VB_INIT_OUT_ENABLE_DISPLAY;
+ *oflags |= VB_INIT_OUT_ENABLE_USB_STORAGE;
+ vb_sd->flags |= VBSD_BOOT_DEV_SWITCH_ON;
+ vb_sd->flags |= VBSD_LF_DEV_SWITCH_ON;
+ }
+ /* TODO: Set these in depthcharge */
+ if (CONFIG_VIRTUAL_DEV_SWITCH)
+ vb_sd->flags |= VBSD_HONOR_VIRT_DEV_SWITCH;
+ if (CONFIG_EC_SOFTWARE_SYNC) {
+ vb_sd->flags |= VBSD_EC_SOFTWARE_SYNC;
+ vb_sd->flags |= VBSD_BOOT_REC_SWITCH_VIRTUAL;
+ }
+ /* In vboot1, VBSD_FWB_TRIED is
+ * set only if B is booted as explicitly requested. Therefore, if B is
+ * booted because A was found bad, the flag should not be set. It's
+ * better not to touch it if we can only ambiguously control it. */
+ /* if (vb2_sd->fw_slot)
+ vb_sd->flags |= VBSD_FWB_TRIED; */
+
+ /* copy kernel subkey if it's found */
+ if (vb2_sd->workbuf_preamble_size) {
+ struct vb2_fw_preamble *fp;
+ uintptr_t dst, src;
+ printk(BIOS_INFO, "Copying FW preamble\n");
+ fp = (struct vb2_fw_preamble *)((uintptr_t)vb2_sd +
+ vb2_sd->workbuf_preamble_offset);
+ src = (uintptr_t)&fp->kernel_subkey +
+ fp->kernel_subkey.key_offset;
+ dst = (uintptr_t)vb_sd + sizeof(VbSharedDataHeader);
+ assert(dst + fp->kernel_subkey.key_size <=
+ (uintptr_t)vboot_handoff + sizeof(*vboot_handoff));
+ memcpy((void *)dst, (void *)src,
+ fp->kernel_subkey.key_size);
+ vb_sd->data_used += fp->kernel_subkey.key_size;
+ vb_sd->kernel_subkey.key_offset =
+ dst - (uintptr_t)&vb_sd->kernel_subkey;
+ vb_sd->kernel_subkey.key_size = fp->kernel_subkey.key_size;
+ vb_sd->kernel_subkey.algorithm = fp->kernel_subkey.algorithm;
+ vb_sd->kernel_subkey.key_version =
+ fp->kernel_subkey.key_version;
+ }
+
+ vb_sd->recovery_reason = vb2_sd->recovery_reason;
+}
+
+/**
+ * Load ramstage and return the entry point
+ */
+void *vboot2_load_ramstage(void)
+{
+ struct vboot_handoff *vh;
+ struct vb2_shared_data *sd;
+ struct vboot_region fw_main;
+ struct vb2_working_data *wd = vboot_get_working_data();
+
+ sd = (struct vb2_shared_data *)(uintptr_t)wd->buffer;
+ sd->workbuf_hash_offset = 0;
+ sd->workbuf_hash_size = 0;
+
+ printk(BIOS_INFO, "creating vboot_handoff structure\n");
+ vh = cbmem_add(CBMEM_ID_VBOOT_HANDOFF, sizeof(*vh));
+ if (vh == NULL)
+ /* we don't need to failover gracefully here because this
+ * shouldn't happen with the image that has passed QA. */
+ die("failed to allocate vboot_handoff structure\n");
+
+ memset(vh, 0, sizeof(*vh));
+
+ /* needed until we finish transtion to vboot2 for kernel verification */
+ fill_vboot_handoff(vh, sd);
+
+ if (vboot_is_readonly_path(wd))
+ /* we're on recovery path. continue to ro-ramstage. */
+ return NULL;
+
+ printk(BIOS_INFO,
+ "loading ramstage from Slot %c\n", sd->fw_slot ? 'B' : 'A');
+ vb2_get_selected_region(wd, &fw_main);
+
+ return load_ramstage(vh, &fw_main);
+}
diff --git a/src/vendorcode/google/chromeos/vboot2/verstage.c b/src/vendorcode/google/chromeos/vboot2/verstage.c
new file mode 100644
index 0000000..572e161
--- /dev/null
+++ b/src/vendorcode/google/chromeos/vboot2/verstage.c
@@ -0,0 +1,252 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright 2014 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.
+ *
+ * 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 <2api.h>
+#include <2struct.h>
+#include <antirollback.h>
+#include <console/console.h>
+#include <console/vtxprintf.h>
+#include <string.h>
+
+#include "../chromeos.h"
+#include "misc.h"
+
+#define TODO_BLOCK_SIZE 1024
+
+static int is_slot_a(struct vb2_context *ctx)
+{
+ return !(ctx->flags & VB2_CONTEXT_FW_SLOT_B);
+}
+
+/* exports */
+
+void vb2ex_printf(const char *func, const char *fmt, ...)
+{
+ va_list args;
+
+ printk(BIOS_INFO, "VB2:%s() ", func);
+ va_start(args, fmt);
+ vprintk(BIOS_INFO, fmt, args);
+ va_end(args);
+
+ return;
+}
+
+int vb2ex_tpm_clear_owner(struct vb2_context *ctx)
+{
+ uint32_t rv;
+ printk(BIOS_INFO, "Clearing TPM owner\n");
+ rv = tpm_clear_and_reenable();
+ if (rv)
+ return VB2_ERROR_EX_TPM_CLEAR_OWNER;
+ return VB2_SUCCESS;
+}
+
+int vb2ex_read_resource(struct vb2_context *ctx,
+ enum vb2_resource_index index,
+ uint32_t offset,
+ void *buf,
+ uint32_t size)
+{
+ struct vboot_region region;
+
+ switch (index) {
+ case VB2_RES_GBB:
+ vboot_locate_region("GBB", ®ion);
+ break;
+ case VB2_RES_FW_VBLOCK:
+ if (is_slot_a(ctx))
+ vboot_locate_region("VBLOCK_A", ®ion);
+ else
+ vboot_locate_region("VBLOCK_B", ®ion);
+ break;
+ default:
+ return VB2_ERROR_EX_READ_RESOURCE_INDEX;
+ }
+
+ if (offset + size > region.size)
+ return VB2_ERROR_EX_READ_RESOURCE_SIZE;
+
+ if (vboot_get_region(region.offset_addr + offset, size, buf) == NULL)
+ return VB2_ERROR_UNKNOWN;
+
+ return VB2_SUCCESS;
+}
+
+static int hash_body(struct vb2_context *ctx, struct vboot_region *fw_main)
+{
+ uint32_t expected_size;
+ MAYBE_STATIC uint8_t block[TODO_BLOCK_SIZE];
+ size_t block_size = sizeof(block);
+ uintptr_t offset;
+ int rv;
+
+ expected_size = fw_main->size;
+ offset = fw_main->offset_addr;
+
+ /* Start the body hash */
+ rv = vb2api_init_hash(ctx, VB2_HASH_TAG_FW_BODY, &expected_size);
+ if (rv)
+ return rv;
+
+ /* Extend over the body */
+ while (expected_size) {
+ void *b;
+ if (block_size > expected_size)
+ block_size = expected_size;
+
+ b = vboot_get_region(offset, block_size, block);
+ if (b == NULL)
+ return VB2_ERROR_UNKNOWN;
+ rv = vb2api_extend_hash(ctx, b, block_size);
+ if (rv)
+ return rv;
+
+ expected_size -= block_size;
+ offset += block_size;
+ }
+
+ /* Check the result */
+ rv = vb2api_check_hash(ctx);
+ if (rv)
+ return rv;
+
+ return VB2_SUCCESS;
+}
+
+static int locate_firmware(struct vb2_context *ctx,
+ struct vboot_region *fw_main)
+{
+ if (is_slot_a(ctx))
+ vboot_locate_region("FW_MAIN_A", fw_main);
+ else
+ vboot_locate_region("FW_MAIN_B", fw_main);
+
+ if (fw_main->size < 0)
+ return 1;
+
+ return 0;
+}
+
+/**
+ * Save non-volatile and/or secure data if needed.
+ */
+static void save_if_needed(struct vb2_context *ctx)
+{
+ if (ctx->flags & VB2_CONTEXT_NVDATA_CHANGED) {
+ printk(BIOS_INFO, "Saving nvdata\n");
+ save_vbnv(ctx->nvdata);
+ ctx->flags &= ~VB2_CONTEXT_NVDATA_CHANGED;
+ }
+ if (ctx->flags & VB2_CONTEXT_SECDATA_CHANGED) {
+ printk(BIOS_INFO, "Saving secdata\n");
+ antirollback_write_space_firmware(ctx);
+ ctx->flags &= ~VB2_CONTEXT_SECDATA_CHANGED;
+ }
+}
+
+/**
+ * Verify and select the firmware in the RW image
+ *
+ * TODO: Avoid loading a stage twice (once in hash_body & again in load_stage).
+ * when per-stage verification is ready.
+ */
+#if CONFIG_RETURN_FROM_VERSTAGE
+void main(void)
+#else
+void verstage_main(void)
+#endif /* CONFIG_RETURN_FROM_VERSTAGE */
+{
+ struct vb2_context ctx;
+ struct vboot_region fw_main;
+ struct vb2_working_data *wd = vboot_get_working_data();
+ int rv;
+
+ /* Set up context and work buffer */
+ memset(&ctx, 0, sizeof(ctx));
+ ctx.workbuf = (uint8_t *)(uintptr_t)wd->buffer;
+ ctx.workbuf_size = wd->buffer_size;
+
+ /* Read nvdata from a non-volatile storage */
+ read_vbnv(ctx.nvdata);
+
+ /* Read secdata from TPM. Initialize TPM if secdata not found. We don't
+ * check the return value here because vb2api_fw_phase1 will catch
+ * invalid secdata and tell us what to do (=reboot). */
+ antirollback_read_space_firmware(&ctx);
+
+ if (get_developer_mode_switch())
+ ctx.flags |= VB2_CONTEXT_FORCE_DEVELOPER_MODE;
+ if (get_recovery_mode_switch()) {
+ clear_recovery_mode_switch();
+ ctx.flags |= VB2_CONTEXT_FORCE_RECOVERY_MODE;
+ }
+
+ /* Do early init */
+ printk(BIOS_INFO, "Phase 1\n");
+ rv = vb2api_fw_phase1(&ctx);
+ if (rv) {
+ printk(BIOS_INFO, "Recovery requested (%x)\n", rv);
+ /* If we need recovery mode, leave firmware selection now */
+ save_if_needed(&ctx);
+ return;
+ }
+
+ /* Determine which firmware slot to boot */
+ printk(BIOS_INFO, "Phase 2\n");
+ rv = vb2api_fw_phase2(&ctx);
+ if (rv) {
+ printk(BIOS_INFO, "Reboot requested (%x)\n", rv);
+ save_if_needed(&ctx);
+ vboot_reboot();
+ }
+
+ /* Try that slot */
+ printk(BIOS_INFO, "Phase 3\n");
+ rv = vb2api_fw_phase3(&ctx);
+ if (rv) {
+ printk(BIOS_INFO, "Reboot requested (%x)\n", rv);
+ save_if_needed(&ctx);
+ vboot_reboot();
+ }
+
+ printk(BIOS_INFO, "Phase 4\n");
+ rv = locate_firmware(&ctx, &fw_main);
+ if (rv)
+ die("Failed to read FMAP to locate firmware");
+
+ rv = hash_body(&ctx, &fw_main);
+ save_if_needed(&ctx);
+ if (rv) {
+ printk(BIOS_INFO, "Reboot requested (%x)\n", rv);
+ vboot_reboot();
+ }
+
+ /* Lock TPM */
+ rv = antirollback_lock_space_firmware();
+ if (rv) {
+ printk(BIOS_INFO, "Failed to lock TPM (%x)\n", rv);
+ vb2api_fail(&ctx, VB2_RECOVERY_RO_TPM_L_ERROR, 0);
+ save_if_needed(&ctx);
+ vboot_reboot();
+ }
+
+ printk(BIOS_INFO, "Slot %c is selected\n", is_slot_a(&ctx) ? 'A' : 'B');
+ vb2_set_selected_region(wd, &fw_main);
+}
diff --git a/src/vendorcode/google/chromeos/vboot2/verstage.ld b/src/vendorcode/google/chromeos/vboot2/verstage.ld
new file mode 100644
index 0000000..c7fd646
--- /dev/null
+++ b/src/vendorcode/google/chromeos/vboot2/verstage.ld
@@ -0,0 +1,58 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright 2014 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.
+ *
+ * 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 file is included inside a SECTIONS block */
+
+.text . : {
+ _program = .;
+ _verstage = .;
+ *(.text._start);
+ *(.text.stage_entry);
+ *(.text);
+ *(.text.*);
+} : to_load
+
+.data . : {
+ *(.rodata);
+ *(.rodata.*);
+ *(.data);
+ *(.data.*);
+ . = ALIGN(8);
+}
+
+.bss . : {
+ . = ALIGN(8);
+ _bss = .;
+ *(.bss)
+ *(.bss.*)
+ *(.sbss)
+ *(.sbss.*)
+ _ebss = .;
+ _everstage = .;
+ _eprogram = .;
+}
+
+/* Discard the sections we don't need/want */
+/DISCARD/ : {
+ *(.comment)
+ *(.note)
+ *(.comment.*)
+ *(.note.*)
+ *(.eh_frame);
+}
diff --git a/src/vendorcode/google/chromeos/vboot2/verstub.c b/src/vendorcode/google/chromeos/vboot2/verstub.c
new file mode 100644
index 0000000..e8faa07
--- /dev/null
+++ b/src/vendorcode/google/chromeos/vboot2/verstub.c
@@ -0,0 +1,97 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright 2014 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.
+ *
+ * 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 <arch/stages.h>
+#include <cbfs.h>
+#include <console/console.h>
+#include <string.h>
+#include "../chromeos.h"
+#include "misc.h"
+#include "symbols.h"
+
+static struct vb2_working_data *init_vb2_working_data(void)
+{
+ struct vb2_working_data *wd;
+
+ wd = vboot_get_working_data();
+ memset(wd, 0, _vboot2_work_size);
+ /* 8-byte alignment for ARMv7 */
+ wd->buffer = ALIGN_UP((uintptr_t)&wd[1], 8);
+ wd->buffer_size = _vboot2_work_size + (uintptr_t)wd
+ - (uintptr_t)wd->buffer;
+
+ return wd;
+}
+
+/**
+ * Verify a slot and jump to the next stage
+ *
+ * This could be either part of the (1) bootblock or the (2) verstage, depending
+ * on CONFIG_RETURN_FROM_VERSTAGE.
+ *
+ * 1) It jumps to the verstage and comes back, then, loads the romstage over the
+ * verstage space and exits to it. (note the cbfs cache is trashed on return
+ * from the verstage.)
+ *
+ * 2) We're already in the verstage. Verify firmware, then load the romstage and
+ * exits to it.
+ */
+void vboot2_verify_firmware(void)
+{
+ void *entry;
+ struct vb2_working_data *wd;
+
+ wd = init_vb2_working_data();
+
+#if CONFIG_RETURN_FROM_VERSTAGE
+ /* load verstage from RO */
+ entry = cbfs_load_stage(CBFS_DEFAULT_MEDIA,
+ CONFIG_CBFS_PREFIX "/verstage");
+ if (entry == (void *)-1)
+ die("failed to load verstage");
+
+ /* verify and select a slot */
+ stage_exit(entry);
+#else
+ verstage_main();
+#endif /* CONFIG_RETURN_FROM_VERSTAGE */
+
+ /* jump to the selected slot */
+ entry = NULL;
+ if (vboot_is_slot_selected(wd)) {
+ /* RW A or B */
+ struct vboot_region fw_main;
+ struct vboot_components *fw_info;
+ vb2_get_selected_region(wd, &fw_main);
+ fw_info = vboot_locate_components(&fw_main);
+ if (fw_info == NULL)
+ die("failed to locate firmware components\n");
+ entry = vboot_load_stage(CONFIG_VBOOT_ROMSTAGE_INDEX,
+ &fw_main, fw_info);
+ } else if (vboot_is_readonly_path(wd)) {
+ /* RO */
+ entry = cbfs_load_stage(CBFS_DEFAULT_MEDIA,
+ CONFIG_CBFS_PREFIX "/romstage");
+ }
+
+ if (entry != NULL && entry != (void *)-1)
+ stage_exit(entry);
+
+ die("failed to exit from stage\n");
+}
diff --git a/src/vendorcode/google/chromeos/vboot_common.c b/src/vendorcode/google/chromeos/vboot_common.c
new file mode 100644
index 0000000..b2893d9
--- /dev/null
+++ b/src/vendorcode/google/chromeos/vboot_common.c
@@ -0,0 +1,122 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2014 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 <stddef.h>
+#include <string.h>
+#include <boot/coreboot_tables.h>
+#include <cbfs.h>
+#include <cbmem.h>
+#include <console/console.h>
+#include "chromeos.h"
+#include "vboot_common.h"
+
+void vboot_locate_region(const char *name, struct vboot_region *region)
+{
+ region->size = find_fmap_entry(name, (void **)®ion->offset_addr);
+}
+
+void *vboot_get_region(uintptr_t offset_addr, size_t size, void *dest)
+{
+ if (IS_ENABLED(CONFIG_SPI_FLASH_MEMORY_MAPPED)) {
+ if (dest != NULL)
+ return memcpy(dest, (void *)offset_addr, size);
+ else
+ return (void *)offset_addr;
+ } else {
+ struct cbfs_media default_media, *media = &default_media;
+ void *cache;
+
+ init_default_cbfs_media(media);
+ media->open(media);
+ if (dest != NULL) {
+ cache = dest;
+ if (media->read(media, dest, offset_addr, size) != size)
+ cache = NULL;
+ } else {
+ cache = media->map(media, offset_addr, size);
+ if (cache == CBFS_MEDIA_INVALID_MAP_ADDRESS)
+ cache = NULL;
+ }
+ media->close(media);
+ return cache;
+ }
+}
+
+int vboot_get_handoff_info(void **addr, uint32_t *size)
+{
+ struct vboot_handoff *vboot_handoff;
+
+ vboot_handoff = cbmem_find(CBMEM_ID_VBOOT_HANDOFF);
+
+ if (vboot_handoff == NULL)
+ return -1;
+
+ *addr = vboot_handoff;
+ *size = sizeof(*vboot_handoff);
+ return 0;
+}
+
+/* This will leak a mapping of a fw region */
+struct vboot_components *vboot_locate_components(struct vboot_region *region)
+{
+ size_t req_size;
+ struct vboot_components *vbc;
+
+ req_size = sizeof(*vbc);
+ req_size += sizeof(struct vboot_component_entry) *
+ MAX_PARSED_FW_COMPONENTS;
+
+ vbc = vboot_get_region(region->offset_addr, req_size, NULL);
+ if (vbc && vbc->num_components > MAX_PARSED_FW_COMPONENTS)
+ vbc = NULL;
+
+ return vbc;
+}
+
+void *vboot_get_payload(int *len)
+{
+ struct vboot_handoff *vboot_handoff;
+ struct firmware_component *fwc;
+
+ vboot_handoff = cbmem_find(CBMEM_ID_VBOOT_HANDOFF);
+
+ if (vboot_handoff == NULL)
+ return NULL;
+
+ if (CONFIG_VBOOT_BOOT_LOADER_INDEX >= MAX_PARSED_FW_COMPONENTS) {
+ printk(BIOS_ERR, "Invalid boot loader index: %d\n",
+ CONFIG_VBOOT_BOOT_LOADER_INDEX);
+ return NULL;
+ }
+
+ fwc = &vboot_handoff->components[CONFIG_VBOOT_BOOT_LOADER_INDEX];
+
+ /* If payload size is zero fall back to cbfs path. */
+ if (fwc->size == 0)
+ return NULL;
+
+ if (len != NULL)
+ *len = fwc->size;
+
+ printk(BIOS_DEBUG, "Booting 0x%x byte verified payload at 0x%08x.\n",
+ fwc->size, fwc->address);
+
+ /* This will leak a mapping. */
+ return vboot_get_region(fwc->address, fwc->size, NULL);
+}
diff --git a/src/vendorcode/google/chromeos/vboot_common.h b/src/vendorcode/google/chromeos/vboot_common.h
new file mode 100644
index 0000000..c6c9b50
--- /dev/null
+++ b/src/vendorcode/google/chromeos/vboot_common.h
@@ -0,0 +1,55 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2014 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.
+ *
+ * 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 VBOOT_COMMON_H
+#define VBOOT_COMMON_H
+
+#include <stdint.h>
+
+struct vboot_region {
+ uintptr_t offset_addr;
+ int32_t size;
+};
+
+/* The FW areas consist of multiple components. At the beginning of
+ * each area is the number of total compoments as well as the size and
+ * offset for each component. One needs to caculate the total size of the
+ * signed firmware region based off of the embedded metadata. */
+struct vboot_component_entry {
+ uint32_t offset;
+ uint32_t size;
+} __attribute__((packed));
+
+struct vboot_components {
+ uint32_t num_components;
+ struct vboot_component_entry entries[0];
+} __attribute__((packed));
+
+void vboot_locate_region(const char *name, struct vboot_region *region);
+
+struct vboot_components *vboot_locate_components(struct vboot_region *region);
+
+/*
+ * This is a dual purpose routine. If dest is non-NULL the region at
+ * offset_addr will be read into the area pointed to by dest. If dest
+ * is NULL,the region will be mapped to a memory location. NULL is
+ * returned on error else the location of the requested region.
+ */
+void *vboot_get_region(uintptr_t offset_addr, size_t size, void *dest);
+
+#endif /* VBOOT_COMMON_H */
diff --git a/src/vendorcode/google/chromeos/vboot_handoff.c b/src/vendorcode/google/chromeos/vboot_handoff.c
deleted file mode 100644
index f929a59..0000000
--- a/src/vendorcode/google/chromeos/vboot_handoff.c
+++ /dev/null
@@ -1,174 +0,0 @@
-/*
- * This file is part of the coreboot project.
- *
- * Copyright (C) 2013 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.
- *
- * 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 <2recovery_reasons.h>
-#include <2struct.h>
-#include <arch/stages.h>
-#include <assert.h>
-#include <stdint.h>
-#include <stddef.h>
-#include <string.h>
-#include <cbfs.h>
-#include <cbmem.h>
-#include <console/console.h>
-#include <console/vtxprintf.h>
-#include <stdlib.h>
-#include <timestamp.h>
-#include "chromeos.h"
-#include "fmap.h"
-#include "vboot_handoff.h"
-#include <vboot_struct.h>
-
-static void *load_ramstage(struct vboot_handoff *vboot_handoff,
- struct vboot_region *fw_main)
-{
- struct vboot_components *fw_info;
- int i;
-
- fw_info = vboot_locate_components(fw_main);
- if (fw_info == NULL)
- die("failed to locate firmware components\n");
-
- /* these offset & size are used to load a rw boot loader */
- for (i = 0; i < fw_info->num_components; i++) {
- vboot_handoff->components[i].address =
- fw_main->offset_addr + fw_info->entries[i].offset;
- vboot_handoff->components[i].size = fw_info->entries[i].size;
- }
-
- return vboot_load_stage(CONFIG_VBOOT_RAMSTAGE_INDEX, fw_main, fw_info);
-}
-
-/**
- * Sets vboot_handoff based on the information in vb2_shared_data
- *
- * TODO: Read wp switch to set VBSD_BOOT_FIRMWARE_WP_ENABLED
- */
-static void fill_vboot_handoff(struct vboot_handoff *vboot_handoff,
- struct vb2_shared_data *vb2_sd)
-{
- VbSharedDataHeader *vb_sd =
- (VbSharedDataHeader *)vboot_handoff->shared_data;
- uint32_t *oflags = &vboot_handoff->init_params.out_flags;
-
- vb_sd->flags |= VBSD_BOOT_FIRMWARE_VBOOT2;
-
- vboot_handoff->selected_firmware = vb2_sd->fw_slot;
-
- vb_sd->firmware_index = vb2_sd->fw_slot;
-
- vb_sd->magic = VB_SHARED_DATA_MAGIC;
- vb_sd->struct_version = VB_SHARED_DATA_VERSION;
- vb_sd->struct_size = sizeof(VbSharedDataHeader);
- vb_sd->data_size = VB_SHARED_DATA_MIN_SIZE;
- vb_sd->data_used = sizeof(VbSharedDataHeader);
-
- if (vb2_sd->recovery_reason) {
- vb_sd->firmware_index = 0xFF;
- if (vb2_sd->recovery_reason == VB2_RECOVERY_RO_MANUAL)
- vb_sd->flags |= VBSD_BOOT_REC_SWITCH_ON;
- *oflags |= VB_INIT_OUT_ENABLE_RECOVERY;
- *oflags |= VB_INIT_OUT_CLEAR_RAM;
- *oflags |= VB_INIT_OUT_ENABLE_DISPLAY;
- *oflags |= VB_INIT_OUT_ENABLE_USB_STORAGE;
- }
- if (vb2_sd->flags & VB2_SD_DEV_MODE_ENABLED) {
- *oflags |= VB_INIT_OUT_ENABLE_DEVELOPER;
- *oflags |= VB_INIT_OUT_CLEAR_RAM;
- *oflags |= VB_INIT_OUT_ENABLE_DISPLAY;
- *oflags |= VB_INIT_OUT_ENABLE_USB_STORAGE;
- vb_sd->flags |= VBSD_BOOT_DEV_SWITCH_ON;
- vb_sd->flags |= VBSD_LF_DEV_SWITCH_ON;
- }
- /* TODO: Set these in depthcharge */
- if (CONFIG_VIRTUAL_DEV_SWITCH)
- vb_sd->flags |= VBSD_HONOR_VIRT_DEV_SWITCH;
- if (CONFIG_EC_SOFTWARE_SYNC) {
- vb_sd->flags |= VBSD_EC_SOFTWARE_SYNC;
- vb_sd->flags |= VBSD_BOOT_REC_SWITCH_VIRTUAL;
- }
- /* In vboot1, VBSD_FWB_TRIED is
- * set only if B is booted as explicitly requested. Therefore, if B is
- * booted because A was found bad, the flag should not be set. It's
- * better not to touch it if we can only ambiguously control it. */
- /* if (vb2_sd->fw_slot)
- vb_sd->flags |= VBSD_FWB_TRIED; */
-
- /* copy kernel subkey if it's found */
- if (vb2_sd->workbuf_preamble_size) {
- struct vb2_fw_preamble *fp;
- uintptr_t dst, src;
- printk(BIOS_INFO, "Copying FW preamble\n");
- fp = (struct vb2_fw_preamble *)( (uintptr_t)vb2_sd +
- vb2_sd->workbuf_preamble_offset);
- src = (uintptr_t)&fp->kernel_subkey +
- fp->kernel_subkey.key_offset;
- dst = (uintptr_t)vb_sd + sizeof(VbSharedDataHeader);
- assert(dst + fp->kernel_subkey.key_size <=
- (uintptr_t)vboot_handoff + sizeof(*vboot_handoff));
- memcpy((void *)dst, (void *)src,
- fp->kernel_subkey.key_size);
- vb_sd->data_used += fp->kernel_subkey.key_size;
- vb_sd->kernel_subkey.key_offset =
- dst - (uintptr_t)&vb_sd->kernel_subkey;
- vb_sd->kernel_subkey.key_size = fp->kernel_subkey.key_size;
- vb_sd->kernel_subkey.algorithm = fp->kernel_subkey.algorithm;
- vb_sd->kernel_subkey.key_version =
- fp->kernel_subkey.key_version;
- }
-
- vb_sd->recovery_reason = vb2_sd->recovery_reason;
-}
-
-/**
- * Load ramstage and return the entry point
- */
-void *vboot_load_ramstage(void)
-{
- struct vboot_handoff *vh;
- struct vb2_shared_data *sd;
- struct vboot_region fw_main;
- struct vb2_working_data *wd = vboot_get_working_data();
-
- sd = (struct vb2_shared_data *)(uintptr_t)wd->buffer;
- sd->workbuf_hash_offset = 0;
- sd->workbuf_hash_size = 0;
-
- printk(BIOS_INFO, "creating vboot_handoff structure\n");
- vh = cbmem_add(CBMEM_ID_VBOOT_HANDOFF, sizeof(*vh));
- if (vh == NULL)
- /* we don't need to failover gracefully here because this
- * shouldn't happen with the image that has passed QA. */
- die("failed to allocate vboot_handoff structure\n");
-
- memset(vh, 0, sizeof(*vh));
-
- /* needed until we finish transtion to vboot2 for kernel verification */
- fill_vboot_handoff(vh, sd);
-
- if (vboot_is_readonly_path(wd))
- /* we're on recovery path. continue to ro-ramstage. */
- return NULL;
-
- printk(BIOS_INFO,
- "loading ramstage from Slot %c\n", sd->fw_slot ? 'B' : 'A');
- vb2_get_selected_region(wd, &fw_main);
-
- return load_ramstage(vh, &fw_main);
-}
diff --git a/src/vendorcode/google/chromeos/vboot_handoff.h b/src/vendorcode/google/chromeos/vboot_handoff.h
index b001743..e6b2d69 100644
--- a/src/vendorcode/google/chromeos/vboot_handoff.h
+++ b/src/vendorcode/google/chromeos/vboot_handoff.h
@@ -19,9 +19,20 @@
#ifndef VBOOT_HANDOFF_H
#define VBOOT_HANDOFF_H
+
#include <vboot_api.h>
#include <vboot_struct.h>
#include "chromeos.h"
+#include "vboot_common.h"
+
+/*
+ * The vboot handoff structure keeps track of a maximum number of firmware
+ * components in the verfieid RW area of flash. This is not a restriction on
+ * the number of components packed in a firmware block. It's only the maximum
+ * number of parsed firmware components (address and size) included in the
+ * handoff structure.
+ */
+#define MAX_PARSED_FW_COMPONENTS 5
struct firmware_component {
uint32_t address;
diff --git a/src/vendorcode/google/chromeos/vboot_loader.c b/src/vendorcode/google/chromeos/vboot_loader.c
deleted file mode 100644
index d13608c..0000000
--- a/src/vendorcode/google/chromeos/vboot_loader.c
+++ /dev/null
@@ -1,416 +0,0 @@
-/*
- * This file is part of the coreboot project.
- *
- * Copyright (C) 2013 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.
- *
- * 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 <arch/stages.h>
-#include <stdint.h>
-#include <stddef.h>
-#include <string.h>
-#include <cbfs.h>
-#include <cbmem.h>
-#include <console/console.h>
-#include <console/vtxprintf.h>
-#include <program_loading.h>
-#include <tpm.h>
-#include <reset.h>
-#include <romstage_handoff.h>
-#include <rmodule.h>
-#include <string.h>
-#include <stdlib.h>
-#include <timestamp.h>
-#include "chromeos.h"
-#include "vboot_context.h"
-#include "vboot_handoff.h"
-
-#define TEMP_CBMEM_ID_VBOOT 0xffffffff
-#define TEMP_CBMEM_ID_VBLOCKS 0xfffffffe
-
-static void vboot_run_stub(struct vboot_context *context)
-{
- struct rmod_stage_load rmod_stage = {
- .cbmem_id = TEMP_CBMEM_ID_VBOOT,
- .name = CONFIG_CBFS_PREFIX "/vboot",
- };
- void (*entry)(struct vboot_context *context);
-
- if (rmodule_stage_load_from_cbfs(&rmod_stage)) {
- printk(BIOS_DEBUG, "Could not load vboot stub.\n");
- goto out;
- }
-
- entry = rmod_stage.entry;
-
- /* Call stub. */
- entry(context);
-
-out:
- /* Tear down the region no longer needed. */
- if (rmod_stage.cbmem_entry != NULL)
- cbmem_entry_remove(rmod_stage.cbmem_entry);
-}
-
-/* Helper routines for the vboot stub. */
-static void log_msg(const char *fmt, va_list args)
-{
- do_vtxprintf(fmt, args);
-}
-
-static void fatal_error(void)
-{
- printk(BIOS_ERR, "vboot encountered fatal error. Resetting.\n");
- hard_reset();
-}
-
-static int fw_region_size(struct vboot_region *r)
-{
- struct vboot_components *fw_info;
- int32_t size;
- int i;
-
- fw_info = vboot_locate_components(r);
- if (fw_info == NULL)
- return -1;
-
- if (fw_info->num_components > MAX_PARSED_FW_COMPONENTS)
- return -1;
-
- size = sizeof(*fw_info);
- size += sizeof(struct vboot_component_entry) * fw_info->num_components;
-
- for (i = 0; i < fw_info->num_components; i++)
- size += ALIGN(fw_info->entries[i].size, sizeof(uint32_t));
-
- /* Check that size of comopnents does not exceed the region's size. */
- if (size > r->size)
- return -1;
-
- /* Update region with the correct size. */
- r->size = size;
-
- return 0;
-}
-
-static int vboot_fill_params(struct vboot_context *ctx)
-{
- VbCommonParams *cparams;
- VbSelectFirmwareParams *fparams;
-
- if (fw_region_size(&ctx->fw_a))
- return -1;
-
- if (fw_region_size(&ctx->fw_b))
- return -1;
-
- cparams = ctx->cparams;
- fparams = ctx->fparams;
-
- cparams->gbb_size = ctx->gbb.size;
- fparams->verification_size_A = ctx->vblock_a.size;
- fparams->verification_size_B = ctx->vblock_b.size;
-
- if (IS_ENABLED(CONFIG_SPI_FLASH_MEMORY_MAPPED)) {
- /* Get memory-mapped pointers to the regions. */
- cparams->gbb_data = vboot_get_region(ctx->gbb.offset_addr,
- ctx->gbb.size, NULL);
- fparams->verification_block_A =
- vboot_get_region(ctx->vblock_a.offset_addr,
- ctx->vblock_a.size, NULL);
- fparams->verification_block_B =
- vboot_get_region(ctx->vblock_b.offset_addr,
- ctx->vblock_b.size, NULL);
- } else {
- /*
- * Copy the vblock info into a buffer in cbmem. The gbb will
- * be read using VbExRegionRead().
- */
- char *dest;
- size_t vblck_sz;
-
- vblck_sz = ctx->vblock_a.size + ctx->vblock_b.size;
- ctx->vblocks = cbmem_entry_add(TEMP_CBMEM_ID_VBLOCKS, vblck_sz);
- if (ctx->vblocks == NULL)
- return -1;
- dest = cbmem_entry_start(ctx->vblocks);
- if (vboot_get_region(ctx->vblock_a.offset_addr,
- ctx->vblock_a.size, dest) == NULL)
- return -1;
- fparams->verification_block_A = (void *)dest;
- dest += ctx->vblock_a.size;
- if (vboot_get_region(ctx->vblock_b.offset_addr,
- ctx->vblock_b.size, dest) == NULL)
- return -1;
- fparams->verification_block_B = (void *)dest;
- }
-
- return 0;
-}
-
-static void fill_handoff(struct vboot_context *context)
-{
- struct vboot_components *fw_info;
- struct vboot_region *region;
- int i;
-
- /* Fix up the handoff structure. */
- context->handoff->selected_firmware =
- context->fparams->selected_firmware;
-
- /* Parse out the components for downstream consumption. */
- if (context->handoff->selected_firmware == VB_SELECT_FIRMWARE_A)
- region = &context->fw_a;
- else if (context->handoff->selected_firmware == VB_SELECT_FIRMWARE_B)
- region = &context->fw_b;
- else
- return;
-
- fw_info = vboot_locate_components(region);
- if (fw_info == NULL)
- return;
-
- for (i = 0; i < fw_info->num_components; i++) {
- context->handoff->components[i].address =
- region->offset_addr + fw_info->entries[i].offset;
- context->handoff->components[i].size = fw_info->entries[i].size;
- }
-}
-
-static void vboot_clean_up(struct vboot_context *context)
-{
- if (context->vblocks != NULL)
- cbmem_entry_remove(context->vblocks);
-}
-
-static void reset(void)
-{
- hard_reset();
-}
-
-static void vboot_invoke_wrapper(struct vboot_handoff *vboot_handoff)
-{
- VbCommonParams cparams;
- VbSelectFirmwareParams fparams;
- struct vboot_context context;
- uint32_t *iflags;
-
- vboot_handoff->selected_firmware = VB_SELECT_FIRMWARE_READONLY;
-
- memset(&cparams, 0, sizeof(cparams));
- memset(&fparams, 0, sizeof(fparams));
- memset(&context, 0, sizeof(context));
-
- iflags = &vboot_handoff->init_params.flags;
- if (get_developer_mode_switch())
- *iflags |= VB_INIT_FLAG_DEV_SWITCH_ON;
- if (get_recovery_mode_switch()) {
- clear_recovery_mode_switch();
- *iflags |= VB_INIT_FLAG_REC_BUTTON_PRESSED;
- }
- if (get_write_protect_state())
- *iflags |= VB_INIT_FLAG_WP_ENABLED;
- if (vboot_get_sw_write_protect())
- *iflags |= VB_INIT_FLAG_SW_WP_ENABLED;
- if (CONFIG_VIRTUAL_DEV_SWITCH)
- *iflags |= VB_INIT_FLAG_VIRTUAL_DEV_SWITCH;
- if (CONFIG_EC_SOFTWARE_SYNC) {
- *iflags |= VB_INIT_FLAG_EC_SOFTWARE_SYNC;
- *iflags |= VB_INIT_FLAG_VIRTUAL_REC_SWITCH;
- }
- if (CONFIG_VBOOT_EC_SLOW_UPDATE)
- *iflags |= VB_INIT_FLAG_EC_SLOW_UPDATE;
- if (CONFIG_VBOOT_OPROM_MATTERS) {
- *iflags |= VB_INIT_FLAG_OPROM_MATTERS;
- /* Will load VGA option rom during this boot */
- if (developer_mode_enabled() || recovery_mode_enabled() ||
- vboot_wants_oprom()) {
- *iflags |= VB_INIT_FLAG_OPROM_LOADED;
- }
- }
-
- context.handoff = vboot_handoff;
- context.cparams = &cparams;
- context.fparams = &fparams;
-
- cparams.shared_data_blob = &vboot_handoff->shared_data[0];
- cparams.shared_data_size = VB_SHARED_DATA_MIN_SIZE;
- cparams.caller_context = &context;
-
- vboot_locate_region("GBB", &context.gbb);
- vboot_locate_region("VBLOCK_A", &context.vblock_a);
- vboot_locate_region("VBLOCK_B", &context.vblock_b);
- vboot_locate_region("FW_MAIN_A", &context.fw_a);
- vboot_locate_region("FW_MAIN_B", &context.fw_b);
-
- /* Check all fmap entries. */
- if (context.fw_a.size < 0 || context.fw_b.size < 0 ||
- context.vblock_a.size < 0 || context.vblock_b.size < 0 ||
- context.gbb.size < 0) {
- printk(BIOS_DEBUG, "Not all fmap entries found for vboot.\n");
- return;
- }
-
- /* Fill in vboot parameters. */
- if (vboot_fill_params(&context)) {
- vboot_clean_up(&context);
- return;
- }
-
- /* Initialize callbacks. */
- context.read_vbnv = &read_vbnv;
- context.save_vbnv = &save_vbnv;
- context.tis_init = &tis_init;
- context.tis_open = &tis_open;
- context.tis_close = &tis_close;
- context.tis_sendrecv = &tis_sendrecv;
- context.log_msg = &log_msg;
- context.fatal_error = &fatal_error;
- context.get_region = &vboot_get_region;
- context.reset = &reset;
-
- vboot_run_stub(&context);
-
- fill_handoff(&context);
-
- vboot_clean_up(&context);
-}
-
-#if CONFIG_RELOCATABLE_RAMSTAGE
-static void *vboot_load_ramstage(uint32_t cbmem_id, const char *name,
- const struct cbmem_entry **cbmem_entry)
-{
- struct vboot_handoff *vboot_handoff;
- struct cbfs_stage *stage;
- const struct firmware_component *fwc;
- struct rmod_stage_load rmod_load = {
- .cbmem_id = cbmem_id,
- .name = name,
- };
-
- timestamp_add_now(TS_START_VBOOT);
-
- vboot_handoff = cbmem_add(CBMEM_ID_VBOOT_HANDOFF,
- sizeof(*vboot_handoff));
-
- if (vboot_handoff == NULL) {
- printk(BIOS_DEBUG, "Could not add vboot_handoff structure.\n");
- return NULL;
- }
-
- memset(vboot_handoff, 0, sizeof(*vboot_handoff));
-
- vboot_invoke_wrapper(vboot_handoff);
-
- timestamp_add_now(TS_END_VBOOT);
-
- /* Take RO firmware path since no RW area was selected. */
- if (vboot_handoff->selected_firmware != VB_SELECT_FIRMWARE_A &&
- vboot_handoff->selected_firmware != VB_SELECT_FIRMWARE_B) {
- printk(BIOS_DEBUG, "No RW firmware selected: 0x%08x\n",
- vboot_handoff->selected_firmware);
- return NULL;
- }
-
- if (CONFIG_VBOOT_RAMSTAGE_INDEX >= MAX_PARSED_FW_COMPONENTS) {
- printk(BIOS_ERR, "Invalid ramstage index: %d\n",
- CONFIG_VBOOT_RAMSTAGE_INDEX);
- return NULL;
- }
-
- /* Check for invalid address. */
- fwc = &vboot_handoff->components[CONFIG_VBOOT_RAMSTAGE_INDEX];
- if (fwc->address == 0) {
- printk(BIOS_DEBUG, "RW ramstage image address invalid.\n");
- return NULL;
- }
-
- printk(BIOS_DEBUG, "RW ramstage image at 0x%08x, 0x%08x bytes.\n",
- fwc->address, fwc->size);
-
- stage = (void *)fwc->address;
-
- if (rmodule_stage_load(&rmod_load, stage)) {
- vboot_handoff->selected_firmware = VB_SELECT_FIRMWARE_READONLY;
- printk(BIOS_DEBUG, "Could not load ramstage region.\n");
- return NULL;
- }
-
- *cbmem_entry = rmod_load.cbmem_entry;
-
- return rmod_load.entry;
-}
-#else /* CONFIG_RELOCATABLE_RAMSTAGE */
-static void vboot_load_ramstage(struct vboot_handoff *vboot_handoff,
- struct romstage_handoff *handoff)
-{
- struct cbfs_stage *stage;
- const struct firmware_component *fwc;
-
- if (CONFIG_VBOOT_RAMSTAGE_INDEX >= MAX_PARSED_FW_COMPONENTS) {
- printk(BIOS_ERR, "Invalid ramstage index: %d\n",
- CONFIG_VBOOT_RAMSTAGE_INDEX);
- return;
- }
-
- /* Check for invalid address. */
- fwc = &vboot_handoff->components[CONFIG_VBOOT_RAMSTAGE_INDEX];
- if (fwc->address == 0) {
- printk(BIOS_DEBUG, "RW ramstage image address invalid.\n");
- return;
- }
-
- printk(BIOS_DEBUG, "RW ramstage image at 0x%08x, 0x%08x bytes.\n",
- fwc->address, fwc->size);
-
- /* This will leak a mapping. */
- stage = vboot_get_region(fwc->address, fwc->size, NULL);
-
- if (stage == NULL) {
- printk(BIOS_DEBUG, "Unable to get RW ramstage region.\n");
- return;
- }
-
- timestamp_add_now(TS_START_COPYRAM);
-
- /* Stages rely the below clearing so that the bss is initialized. */
- memset((void *) (uintptr_t) stage->load, 0, stage->memlen);
-
- if (cbfs_decompress(stage->compression,
- ((unsigned char *) stage) +
- sizeof(struct cbfs_stage),
- (void *) (uintptr_t) stage->load,
- stage->len))
- return;
-
- timestamp_add_now(TS_END_COPYRAM);
-
-#if CONFIG_ARCH_X86
- __asm__ volatile (
- "movl $0, %%ebp\n"
- "jmp *%%edi\n"
- :: "D"(stage->entry)
- );
-#elif CONFIG_ARCH_ARM
- stage_exit((void *)(uintptr_t)stage->entry);
-#endif
-}
-#endif /* CONFIG_RELOCATABLE_RAMSTAGE */
-
-
-const struct ramstage_loader_ops vboot_ramstage_loader = {
- .name = "VBOOT",
- .load = vboot_load_ramstage,
-};
diff --git a/src/vendorcode/google/chromeos/vboot_wrapper.c b/src/vendorcode/google/chromeos/vboot_wrapper.c
deleted file mode 100644
index dd6065c..0000000
--- a/src/vendorcode/google/chromeos/vboot_wrapper.c
+++ /dev/null
@@ -1,266 +0,0 @@
-/*
- * This file is part of the coreboot project.
- *
- * Copyright (C) 2013 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.
- *
- * 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 <console/vtxprintf.h>
-#if CONFIG_ARCH_X86
-#include <cpu/x86/tsc.h>
-#else
-#include <timer.h>
-#endif
-#include <rmodule.h>
-#include <stdlib.h>
-#include <string.h>
-#include "vboot_context.h"
-#include "vboot_handoff.h"
-
-/* Keep a global context pointer around for the callbacks to use. */
-static struct vboot_context *gcontext;
-
-static void vboot_wrapper(void *arg)
-{
- VbError_t res;
- struct vboot_context *context;
-
- context = arg;
- gcontext = context;
-
- VbExDebug("Calling VbInit()\n");
- res = VbInit(context->cparams, &context->handoff->init_params);
- VbExDebug("VbInit() returned 0x%08x\n", res);
-
- if (res != VBERROR_SUCCESS) {
- if(res == VBERROR_TPM_REBOOT_REQUIRED) {
- VbExDebug("TPM Reboot Required. Proceeding reboot.\n");
- gcontext->reset();
- }
- return;
- }
-
- VbExDebug("Calling VbSelectFirmware()\n");
- res = VbSelectFirmware(context->cparams, context->fparams);
- VbExDebug("VbSelectFirmware() returned 0x%08x\n", res);
-
- if (res != VBERROR_SUCCESS)
- return;
-}
-
-void VbExError(const char *format, ...)
-{
- va_list args;
-
- va_start(args, format);
- gcontext->log_msg(format, args);
- va_end(args);
-
- gcontext->fatal_error();
-}
-
-void VbExDebug(const char *format, ...)
-{
- va_list args;
-
- va_start(args, format);
- gcontext->log_msg(format, args);
- va_end(args);
-}
-
-uint64_t VbExGetTimer(void)
-{
-#if CONFIG_ARCH_X86
- return rdtscll();
-#else
- struct mono_time mt;
- timer_monotonic_get(&mt);
- return mt.microseconds;
-#endif
-}
-
-VbError_t VbExNvStorageRead(uint8_t *buf)
-{
- gcontext->read_vbnv(buf);
- return VBERROR_SUCCESS;
-}
-
-VbError_t VbExNvStorageWrite(const uint8_t *buf)
-{
- gcontext->save_vbnv(buf);
- return VBERROR_SUCCESS;
-}
-
-extern char _heap[];
-extern char _eheap[];
-static char *heap_current;
-static int heap_size;
-
-void *VbExMalloc(size_t size)
-{
- void *ptr;
-
- if (heap_current == NULL) {
- heap_current = &_heap[0];
- heap_size = &_eheap[0] - &_heap[0];
- VbExDebug("vboot heap: %p 0x%08x bytes\n",
- heap_current, heap_size);
- }
-
- if (heap_size < size) {
- VbExError("vboot heap request cannot be fulfilled. "
- "0x%08x available, 0x%08x requested\n",
- heap_size, size);
- }
-
- ptr = heap_current;
- heap_size -= size;
- heap_current += size;
-
- return ptr;
-}
-
-void VbExFree(void *ptr)
-{
- /* Leak all memory. */
-}
-
-/* vboot doesn't expose these through the vboot_api.h, but they are needed.
- * coreboot requires declarations so provide them to avoid compiler errors. */
-int Memcmp(const void *src1, const void *src2, size_t n);
-void *Memcpy(void *dest, const void *src, uint64_t n);
-void *Memset(void *dest, const uint8_t c, uint64_t n);
-
-int Memcmp(const void *src1, const void *src2, size_t n)
-{
- return memcmp(src1, src2, n);
-}
-
-void *Memcpy(void *dest, const void *src, uint64_t n)
-{
- return memcpy(dest, src, n);
-}
-
-void *Memset(void *dest, const uint8_t c, uint64_t n)
-{
- return memset(dest, c, n);
-}
-
-static inline size_t get_hash_block_size(size_t requested_size)
-{
- if (!IS_ENABLED(CONFIG_SPI_FLASH_MEMORY_MAPPED)) {
- const size_t block_size = 64 * 1024;
- if (requested_size > block_size)
- return block_size;
- }
- return requested_size;
-}
-
-VbError_t VbExHashFirmwareBody(VbCommonParams *cparams, uint32_t firmware_index)
-{
- uint8_t *data;
- struct vboot_region *region;
- struct vboot_context *ctx;
- size_t data_size;
- uintptr_t offset_addr;
-
- ctx = cparams->caller_context;
-
- switch (firmware_index) {
- case VB_SELECT_FIRMWARE_A:
- region = &ctx->fw_a;
- break;
- case VB_SELECT_FIRMWARE_B:
- region = &ctx->fw_b;
- break;
- default:
- return VBERROR_UNKNOWN;
- }
-
- data_size = region->size;
- offset_addr = region->offset_addr;
- while (data_size) {
- size_t block_size;
-
- block_size = get_hash_block_size(data_size);
- data = ctx->get_region(offset_addr, block_size, NULL);
- if (data == NULL)
- return VBERROR_UNKNOWN;
- VbUpdateFirmwareBodyHash(cparams, data, block_size);
-
- data_size -= block_size;
- offset_addr += block_size;
- }
-
- return VBERROR_SUCCESS;
-}
-
-VbError_t VbExTpmInit(void)
-{
- if (gcontext->tis_init())
- return VBERROR_UNKNOWN;
- return VbExTpmOpen();
-}
-
-VbError_t VbExTpmClose(void)
-{
- if (gcontext->tis_close())
- return VBERROR_UNKNOWN;
- return VBERROR_SUCCESS;
-}
-
-VbError_t VbExTpmOpen(void)
-{
- if (gcontext->tis_open())
- return VBERROR_UNKNOWN;
- return VBERROR_SUCCESS;
-}
-
-VbError_t VbExTpmSendReceive(const uint8_t *request, uint32_t request_length,
- uint8_t *response, uint32_t *response_length)
-{
- size_t len = *response_length;
- if (gcontext->tis_sendrecv(request, request_length, response, &len))
- return VBERROR_UNKNOWN;
- /* check 64->32bit overflow and (re)check response buffer overflow */
- if (len > *response_length)
- return VBERROR_UNKNOWN;
- *response_length = len;
- return VBERROR_SUCCESS;
-}
-
-#if !CONFIG_SPI_FLASH_MEMORY_MAPPED
-VbError_t VbExRegionRead(VbCommonParams *cparams,
- enum vb_firmware_region region, uint32_t offset,
- uint32_t size, void *buf)
-{
- struct vboot_context *ctx;
- VbExDebug("VbExRegionRead: offset=%x size=%x, buf=%p\n",
- offset, size, buf);
- ctx = cparams->caller_context;
-
- if (region == VB_REGION_GBB) {
- if (offset + size > cparams->gbb_size)
- return VBERROR_REGION_READ_INVALID;
- offset += ctx->gbb.offset_addr;
- if (ctx->get_region(offset, size, buf) == NULL)
- return VBERROR_REGION_READ_INVALID;
- return VBERROR_SUCCESS;
- }
-
- return VBERROR_UNSUPPORTED_REGION;
-}
-#endif /* CONFIG_SPI_FLASH_MEMORY_MAPPED */
-
-RMODULE_ENTRY(vboot_wrapper);
diff --git a/src/vendorcode/google/chromeos/verstage.c b/src/vendorcode/google/chromeos/verstage.c
deleted file mode 100644
index 1b42bb6..0000000
--- a/src/vendorcode/google/chromeos/verstage.c
+++ /dev/null
@@ -1,251 +0,0 @@
-/*
- * This file is part of the coreboot project.
- *
- * Copyright 2014 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.
- *
- * 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 <2api.h>
-#include <2struct.h>
-#include <antirollback.h>
-#include <console/console.h>
-#include <console/vtxprintf.h>
-#include <string.h>
-
-#include "chromeos.h"
-
-#define TODO_BLOCK_SIZE 1024
-
-static int is_slot_a(struct vb2_context *ctx)
-{
- return !(ctx->flags & VB2_CONTEXT_FW_SLOT_B);
-}
-
-/* exports */
-
-void vb2ex_printf(const char *func, const char *fmt, ...)
-{
- va_list args;
-
- printk(BIOS_INFO, "VB2:%s() ", func);
- va_start(args, fmt);
- vprintk(BIOS_INFO, fmt, args);
- va_end(args);
-
- return;
-}
-
-int vb2ex_tpm_clear_owner(struct vb2_context *ctx)
-{
- uint32_t rv;
- printk(BIOS_INFO, "Clearing TPM owner\n");
- rv = tpm_clear_and_reenable();
- if (rv)
- return VB2_ERROR_EX_TPM_CLEAR_OWNER;
- return VB2_SUCCESS;
-}
-
-int vb2ex_read_resource(struct vb2_context *ctx,
- enum vb2_resource_index index,
- uint32_t offset,
- void *buf,
- uint32_t size)
-{
- struct vboot_region region;
-
- switch (index) {
- case VB2_RES_GBB:
- vboot_locate_region("GBB", ®ion);
- break;
- case VB2_RES_FW_VBLOCK:
- if (is_slot_a(ctx))
- vboot_locate_region("VBLOCK_A", ®ion);
- else
- vboot_locate_region("VBLOCK_B", ®ion);
- break;
- default:
- return VB2_ERROR_EX_READ_RESOURCE_INDEX;
- }
-
- if (offset + size > region.size)
- return VB2_ERROR_EX_READ_RESOURCE_SIZE;
-
- if (vboot_get_region(region.offset_addr + offset, size, buf) == NULL)
- return VB2_ERROR_UNKNOWN;
-
- return VB2_SUCCESS;
-}
-
-static int hash_body(struct vb2_context *ctx, struct vboot_region *fw_main)
-{
- uint32_t expected_size;
- MAYBE_STATIC uint8_t block[TODO_BLOCK_SIZE];
- size_t block_size = sizeof(block);
- uintptr_t offset;
- int rv;
-
- expected_size = fw_main->size;
- offset = fw_main->offset_addr;
-
- /* Start the body hash */
- rv = vb2api_init_hash(ctx, VB2_HASH_TAG_FW_BODY, &expected_size);
- if (rv)
- return rv;
-
- /* Extend over the body */
- while (expected_size) {
- void *b;
- if (block_size > expected_size)
- block_size = expected_size;
-
- b = vboot_get_region(offset, block_size, block);
- if (b == NULL)
- return VB2_ERROR_UNKNOWN;
- rv = vb2api_extend_hash(ctx, b, block_size);
- if (rv)
- return rv;
-
- expected_size -= block_size;
- offset += block_size;
- }
-
- /* Check the result */
- rv = vb2api_check_hash(ctx);
- if (rv)
- return rv;
-
- return VB2_SUCCESS;
-}
-
-static int locate_firmware(struct vb2_context *ctx,
- struct vboot_region *fw_main)
-{
- if (is_slot_a(ctx))
- vboot_locate_region("FW_MAIN_A", fw_main);
- else
- vboot_locate_region("FW_MAIN_B", fw_main);
-
- if (fw_main->size < 0)
- return 1;
-
- return 0;
-}
-
-/**
- * Save non-volatile and/or secure data if needed.
- */
-static void save_if_needed(struct vb2_context *ctx)
-{
- if (ctx->flags & VB2_CONTEXT_NVDATA_CHANGED) {
- printk(BIOS_INFO, "Saving nvdata\n");
- save_vbnv(ctx->nvdata);
- ctx->flags &= ~VB2_CONTEXT_NVDATA_CHANGED;
- }
- if (ctx->flags & VB2_CONTEXT_SECDATA_CHANGED) {
- printk(BIOS_INFO, "Saving secdata\n");
- antirollback_write_space_firmware(ctx);
- ctx->flags &= ~VB2_CONTEXT_SECDATA_CHANGED;
- }
-}
-
-/**
- * Verify and select the firmware in the RW image
- *
- * TODO: Avoid loading a stage twice (once in hash_body & again in load_stage).
- * when per-stage verification is ready.
- */
-#if CONFIG_RETURN_FROM_VERSTAGE
-void main(void)
-#else
-void verstage_main(void)
-#endif /* CONFIG_RETURN_FROM_VERSTAGE */
-{
- struct vb2_context ctx;
- struct vboot_region fw_main;
- struct vb2_working_data *wd = vboot_get_working_data();
- int rv;
-
- /* Set up context and work buffer */
- memset(&ctx, 0, sizeof(ctx));
- ctx.workbuf = (uint8_t *)(uintptr_t)wd->buffer;
- ctx.workbuf_size = wd->buffer_size;
-
- /* Read nvdata from a non-volatile storage */
- read_vbnv(ctx.nvdata);
-
- /* Read secdata from TPM. Initialize TPM if secdata not found. We don't
- * check the return value here because vb2api_fw_phase1 will catch
- * invalid secdata and tell us what to do (=reboot). */
- antirollback_read_space_firmware(&ctx);
-
- if (get_developer_mode_switch())
- ctx.flags |= VB2_CONTEXT_FORCE_DEVELOPER_MODE;
- if (get_recovery_mode_switch()) {
- clear_recovery_mode_switch();
- ctx.flags |= VB2_CONTEXT_FORCE_RECOVERY_MODE;
- }
-
- /* Do early init */
- printk(BIOS_INFO, "Phase 1\n");
- rv = vb2api_fw_phase1(&ctx);
- if (rv) {
- printk(BIOS_INFO, "Recovery requested (%x)\n", rv);
- /* If we need recovery mode, leave firmware selection now */
- save_if_needed(&ctx);
- return;
- }
-
- /* Determine which firmware slot to boot */
- printk(BIOS_INFO, "Phase 2\n");
- rv = vb2api_fw_phase2(&ctx);
- if (rv) {
- printk(BIOS_INFO, "Reboot requested (%x)\n", rv);
- save_if_needed(&ctx);
- vboot_reboot();
- }
-
- /* Try that slot */
- printk(BIOS_INFO, "Phase 3\n");
- rv = vb2api_fw_phase3(&ctx);
- if (rv) {
- printk(BIOS_INFO, "Reboot requested (%x)\n", rv);
- save_if_needed(&ctx);
- vboot_reboot();
- }
-
- printk(BIOS_INFO, "Phase 4\n");
- rv = locate_firmware(&ctx, &fw_main);
- if (rv)
- die("Failed to read FMAP to locate firmware");
-
- rv = hash_body(&ctx, &fw_main);
- save_if_needed(&ctx);
- if (rv) {
- printk(BIOS_INFO, "Reboot requested (%x)\n", rv);
- vboot_reboot();
- }
-
- /* Lock TPM */
- rv = antirollback_lock_space_firmware();
- if (rv) {
- printk(BIOS_INFO, "Failed to lock TPM (%x)\n", rv);
- vb2api_fail(&ctx, VB2_RECOVERY_RO_TPM_L_ERROR, 0);
- save_if_needed(&ctx);
- vboot_reboot();
- }
-
- printk(BIOS_INFO, "Slot %c is selected\n", is_slot_a(&ctx) ? 'A' : 'B');
- vb2_set_selected_region(wd, &fw_main);
-}
diff --git a/src/vendorcode/google/chromeos/verstage.ld b/src/vendorcode/google/chromeos/verstage.ld
deleted file mode 100644
index c7fd646..0000000
--- a/src/vendorcode/google/chromeos/verstage.ld
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * This file is part of the coreboot project.
- *
- * Copyright 2014 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.
- *
- * 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 file is included inside a SECTIONS block */
-
-.text . : {
- _program = .;
- _verstage = .;
- *(.text._start);
- *(.text.stage_entry);
- *(.text);
- *(.text.*);
-} : to_load
-
-.data . : {
- *(.rodata);
- *(.rodata.*);
- *(.data);
- *(.data.*);
- . = ALIGN(8);
-}
-
-.bss . : {
- . = ALIGN(8);
- _bss = .;
- *(.bss)
- *(.bss.*)
- *(.sbss)
- *(.sbss.*)
- _ebss = .;
- _everstage = .;
- _eprogram = .;
-}
-
-/* Discard the sections we don't need/want */
-/DISCARD/ : {
- *(.comment)
- *(.note)
- *(.comment.*)
- *(.note.*)
- *(.eh_frame);
-}
diff --git a/src/vendorcode/google/chromeos/verstub.c b/src/vendorcode/google/chromeos/verstub.c
deleted file mode 100644
index eb91c22..0000000
--- a/src/vendorcode/google/chromeos/verstub.c
+++ /dev/null
@@ -1,96 +0,0 @@
-/*
- * This file is part of the coreboot project.
- *
- * Copyright 2014 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.
- *
- * 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 <arch/stages.h>
-#include <cbfs.h>
-#include <console/console.h>
-#include <string.h>
-#include "chromeos.h"
-#include "symbols.h"
-
-static struct vb2_working_data *init_vb2_working_data(void)
-{
- struct vb2_working_data *wd;
-
- wd = vboot_get_working_data();
- memset(wd, 0, _vboot2_work_size);
- /* 8-byte alignment for ARMv7 */
- wd->buffer = ALIGN_UP((uintptr_t)&wd[1], 8);
- wd->buffer_size = _vboot2_work_size + (uintptr_t)wd
- - (uintptr_t)wd->buffer;
-
- return wd;
-}
-
-/**
- * Verify a slot and jump to the next stage
- *
- * This could be either part of the (1) bootblock or the (2) verstage, depending
- * on CONFIG_RETURN_FROM_VERSTAGE.
- *
- * 1) It jumps to the verstage and comes back, then, loads the romstage over the
- * verstage space and exits to it. (note the cbfs cache is trashed on return
- * from the verstage.)
- *
- * 2) We're already in the verstage. Verify firmware, then load the romstage and
- * exits to it.
- */
-void vboot2_verify_firmware(void)
-{
- void *entry;
- struct vb2_working_data *wd;
-
- wd = init_vb2_working_data();
-
-#if CONFIG_RETURN_FROM_VERSTAGE
- /* load verstage from RO */
- entry = cbfs_load_stage(CBFS_DEFAULT_MEDIA,
- CONFIG_CBFS_PREFIX "/verstage");
- if (entry == (void *)-1)
- die("failed to load verstage");
-
- /* verify and select a slot */
- stage_exit(entry);
-#else
- verstage_main();
-#endif /* CONFIG_RETURN_FROM_VERSTAGE */
-
- /* jump to the selected slot */
- entry = NULL;
- if (vboot_is_slot_selected(wd)) {
- /* RW A or B */
- struct vboot_region fw_main;
- struct vboot_components *fw_info;
- vb2_get_selected_region(wd, &fw_main);
- fw_info = vboot_locate_components(&fw_main);
- if (fw_info == NULL)
- die("failed to locate firmware components\n");
- entry = vboot_load_stage(CONFIG_VBOOT_ROMSTAGE_INDEX,
- &fw_main, fw_info);
- } else if (vboot_is_readonly_path(wd)) {
- /* RO */
- entry = cbfs_load_stage(CBFS_DEFAULT_MEDIA,
- CONFIG_CBFS_PREFIX "/romstage");
- }
-
- if (entry != NULL && entry != (void *)-1)
- stage_exit(entry);
-
- die("failed to exit from stage\n");
-}
Aaron Durbin (adurbin(a)google.com) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/9171
-gerrit
commit 6ae7f3b6ac39134cf923306d1b9637662500e2f6
Author: Aaron Durbin <adurbin(a)chromium.org>
Date: Sun Mar 29 00:05:18 2015 -0500
fmap: add region based fmap API
Instead of being pointer based use the region infrastrucutre.
Additionally, this removes the need for arch-specific compilation
paths.
Change-Id: I436533a4f4a272837794ee00c90280602745edac
Signed-off-by: Aaron Durbin <adurbin(a)chromium.org>
---
src/Kconfig | 9 +++
src/include/fmap.h | 35 ++++++++++
src/lib/Makefile.inc | 4 ++
src/lib/fmap.c | 121 +++++++++++++++++++++++++++++++++
src/vendorcode/google/chromeos/Kconfig | 8 ---
5 files changed, 169 insertions(+), 8 deletions(-)
diff --git a/src/Kconfig b/src/Kconfig
index cc87aec..d91258f 100644
--- a/src/Kconfig
+++ b/src/Kconfig
@@ -219,6 +219,15 @@ config CACHE_RELOCATED_RAMSTAGE_OUTSIDE_CBMEM
The relocated ramstage is saved in an area specified by the
by the board and/or chipset.
+config FLASHMAP_OFFSET
+ hex "Flash Map Offset"
+ default 0x00670000 if NORTHBRIDGE_INTEL_SANDYBRIDGE
+ default 0x00610000 if NORTHBRIDGE_INTEL_IVYBRIDGE
+ default CBFS_SIZE if !ARCH_X86
+ default 0
+ help
+ Offset of flash map in firmware image
+
choice
prompt "Bootblock behaviour"
default BOOTBLOCK_SIMPLE
diff --git a/src/include/fmap.h b/src/include/fmap.h
new file mode 100644
index 0000000..e575bbf
--- /dev/null
+++ b/src/include/fmap.h
@@ -0,0 +1,35 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright 2015 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.
+ *
+ * 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.
+ */
+
+#ifndef _FMAP_H_
+#define _FMAP_H_
+
+#include <region.h>
+
+/* Locate the named area in the fmap and fill in a region device representing
+ * that area. The region is a sub-region of the readonly boot media. Return
+ * 0 on success, < 0 on error. */
+int fmap_locate_area_as_rdev(const char *name, struct region_device *area);
+
+/* Locate the named area in the fmap and fill in a region with the
+ * offset and size of that area within the boot media. Return 0 on success,
+ * < 0 on error. */
+int fmap_locate_area(const char *name, struct region *r);
+
+#endif
diff --git a/src/lib/Makefile.inc b/src/lib/Makefile.inc
index cb09dbf..e60df66 100644
--- a/src/lib/Makefile.inc
+++ b/src/lib/Makefile.inc
@@ -28,11 +28,13 @@ bootblock-y += memchr.c
bootblock-y += memcmp.c
bootblock-y += mem_pool.c
bootblock-y += region.c
+bootblock-y += fmap.c
verstage-y += prog_ops.c
verstage-y += delay.c
verstage-y += cbfs.c
verstage-y += cbfs_boot_props.c
+verstage-y += fmap.c
verstage-y += memcmp.c
verstage-y += region.c
verstage-$(CONFIG_CONSOLE_CBMEM) += cbmem_console.c
@@ -48,6 +50,7 @@ $(foreach arch,$(ARCH_SUPPORTED),\
$(eval rmodules_$(arch)-y += memcmp.c) \
$(eval rmodules_$(arch)-y += rmodule.ld))
+romstage-y += fmap.c
romstage-$(CONFIG_I2C_TPM) += delay.c
romstage-y += cbfs.c
romstage-y += cbfs_boot_props.c
@@ -73,6 +76,7 @@ ramstage-y += hardwaremain.c
ramstage-y += selfboot.c
ramstage-y += coreboot_table.c
ramstage-y += bootmem.c
+ramstage-y += fmap.c
ramstage-y += memchr.c
ramstage-y += memcmp.c
ramstage-y += malloc.c
diff --git a/src/lib/fmap.c b/src/lib/fmap.c
new file mode 100644
index 0000000..c0cbca1
--- /dev/null
+++ b/src/lib/fmap.c
@@ -0,0 +1,121 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright 2012-2015 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.
+ *
+ * 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.
+ */
+
+#include <boot_device.h>
+#include <console/console.h>
+#include <fmap.h>
+#include <fmap_serialized.h>
+#include <stddef.h>
+#include <string.h>
+
+/*
+ * See http://code.google.com/p/flashmap/ for more information on FMAP.
+ */
+
+static int find_fmap_directory(struct region_device *fmrd)
+{
+ const struct region_device *boot;
+ struct fmap *fmap;
+ size_t fmap_size;
+ size_t offset = CONFIG_FLASHMAP_OFFSET;
+
+ boot = boot_device_ro();
+
+ if (boot == NULL)
+ return -1;
+
+ fmap_size = sizeof(struct fmap);
+
+ fmap = rdev_mmap(boot, offset, fmap_size);
+
+ if (fmap == NULL)
+ return -1;
+
+ if (memcmp(fmap->signature, FMAP_SIGNATURE, sizeof(fmap->signature))) {
+ printk(BIOS_DEBUG, "No FMAP found at %zx offset.\n", offset);
+ rdev_munmap(boot, fmap);
+ return -1;
+ }
+
+ printk(BIOS_DEBUG, "FMAP: Found \"%s\" version %d.%d at %zx.\n",
+ fmap->name, fmap->ver_major, fmap->ver_minor, offset);
+ printk(BIOS_DEBUG, "FMAP: base = %llx size = %x #areas = %d\n",
+ (long long)fmap->base, fmap->size, fmap->nareas);
+
+ fmap_size += fmap->nareas * sizeof(struct fmap_area);
+
+ rdev_munmap(boot, fmap);
+
+ return rdev_chain(fmrd, boot, offset, fmap_size);
+}
+
+int fmap_locate_area_as_rdev(const char *name, struct region_device *area)
+{
+ const struct region_device *boot;
+ struct region ar;
+
+ boot = boot_device_ro();
+
+ if (fmap_locate_area(name, &ar))
+ return -1;
+
+ return rdev_chain(area, boot, ar.offset, ar.size);
+}
+
+int fmap_locate_area(const char *name, struct region *ar)
+{
+ struct region_device fmrd;
+ size_t offset;
+
+ if (find_fmap_directory(&fmrd))
+ return -1;
+
+ /* Start reading the areas just after fmap header. */
+ offset = sizeof(struct fmap);
+
+ while (1) {
+ struct fmap_area *area;
+
+ area = rdev_mmap(&fmrd, offset, sizeof(*area));
+
+ if (area == NULL)
+ return -1;
+
+ if (strcmp((const char *)area->name, name)) {
+ rdev_munmap(&fmrd, area);
+ offset += sizeof(struct fmap_area);
+ continue;
+ }
+
+ printk(BIOS_DEBUG, "FMAP: area %s found\n", name);
+ printk(BIOS_DEBUG, "FMAP: offset: %x\n", area->offset);
+ printk(BIOS_DEBUG, "FMAP: size: %d bytes\n", area->size);
+
+ ar->offset = area->offset;
+ ar->size = area->size;
+
+ rdev_munmap(&fmrd, area);
+
+ return 0;
+ }
+
+ printk(BIOS_DEBUG, "FMAP: area %s not found\n", name);
+
+ return -1;
+}
diff --git a/src/vendorcode/google/chromeos/Kconfig b/src/vendorcode/google/chromeos/Kconfig
index 8826a14..4259ad9 100644
--- a/src/vendorcode/google/chromeos/Kconfig
+++ b/src/vendorcode/google/chromeos/Kconfig
@@ -86,14 +86,6 @@ config CHROMEOS_RAMOOPS_RAM_SIZE
default 0x00100000
depends on CHROMEOS_RAMOOPS
-config FLASHMAP_OFFSET
- hex "Flash Map Offset"
- default 0x00670000 if NORTHBRIDGE_INTEL_SANDYBRIDGE
- default 0x00610000 if NORTHBRIDGE_INTEL_IVYBRIDGE
- default 0
- help
- Offset of flash map in firmware image
-
config VBOOT_VERIFY_FIRMWARE
bool "Verify firmware with vboot."
default n
Aaron Durbin (adurbin(a)google.com) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/9170
-gerrit
commit 1a315ee6fe6ff50b1bc4ebcd700e1407e3951391
Author: Aaron Durbin <adurbin(a)chromium.org>
Date: Sat Mar 28 23:56:22 2015 -0500
fmap: create fmap_serialized.h header
Create a header for the fmap serialized data
layout to allow for easier use from non-chromeos
code.
Change-Id: Ie36e9ff9cb554234ec394b921f029eeed6845aee
Signed-off-by: Aaron Durbin <adurbin(a)chromium.org>
---
src/include/fmap_serialized.h | 73 +++++++++++++++++++++++++++++++++++
src/vendorcode/google/chromeos/fmap.h | 40 +------------------
2 files changed, 74 insertions(+), 39 deletions(-)
diff --git a/src/include/fmap_serialized.h b/src/include/fmap_serialized.h
new file mode 100644
index 0000000..3585f0b
--- /dev/null
+++ b/src/include/fmap_serialized.h
@@ -0,0 +1,73 @@
+/*
+ * Copyright 2010, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Alternatively, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") version 2 as published by the Free
+ * Software Foundation.
+ */
+
+#ifndef FLASHMAP_SERIALIZED_H__
+#define FLASHMAP_SERIALIZED_H__
+
+#include <stdint.h>
+
+#define FMAP_SIGNATURE "__FMAP__"
+#define FMAP_VER_MAJOR 1 /* this header's FMAP minor version */
+#define FMAP_VER_MINOR 1 /* this header's FMAP minor version */
+#define FMAP_STRLEN 32 /* maximum length for strings, */
+ /* including null-terminator */
+
+enum fmap_flags {
+ FMAP_AREA_STATIC = 1 << 0,
+ FMAP_AREA_COMPRESSED = 1 << 1,
+ FMAP_AREA_RO = 1 << 2,
+};
+
+/* Mapping of volatile and static regions in firmware binary */
+struct fmap_area {
+ uint32_t offset; /* offset relative to base */
+ uint32_t size; /* size in bytes */
+ uint8_t name[FMAP_STRLEN]; /* descriptive name */
+ uint16_t flags; /* flags for this area */
+} __attribute__((packed));
+
+struct fmap {
+ uint8_t signature[8]; /* "__FMAP__" (0x5F5F464D41505F5F) */
+ uint8_t ver_major; /* major version */
+ uint8_t ver_minor; /* minor version */
+ uint64_t base; /* address of the firmware binary */
+ uint32_t size; /* size of firmware binary in bytes */
+ uint8_t name[FMAP_STRLEN]; /* name of this firmware binary */
+ uint16_t nareas; /* number of areas described by
+ fmap_areas[] below */
+ struct fmap_area areas[];
+} __attribute__((packed));
+
+#endif /* FLASHMAP_SERIALIZED_H__ */
diff --git a/src/vendorcode/google/chromeos/fmap.h b/src/vendorcode/google/chromeos/fmap.h
index a3d2abd..db61b74 100644
--- a/src/vendorcode/google/chromeos/fmap.h
+++ b/src/vendorcode/google/chromeos/fmap.h
@@ -36,44 +36,6 @@
#ifndef FLASHMAP_LIB_FMAP_H__
#define FLASHMAP_LIB_FMAP_H__
-#include <stdint.h>
+#include <fmap_serialized.h>
-#define FMAP_SIGNATURE "__FMAP__"
-#define FMAP_VER_MAJOR 1 /* this header's FMAP minor version */
-#define FMAP_VER_MINOR 1 /* this header's FMAP minor version */
-#define FMAP_STRLEN 32 /* maximum length for strings, */
- /* including null-terminator */
-
-enum fmap_flags {
- FMAP_AREA_STATIC = 1 << 0,
- FMAP_AREA_COMPRESSED = 1 << 1,
- FMAP_AREA_RO = 1 << 2,
-};
-
-/* Mapping of volatile and static regions in firmware binary */
-struct fmap_area {
- uint32_t offset; /* offset relative to base */
- uint32_t size; /* size in bytes */
- uint8_t name[FMAP_STRLEN]; /* descriptive name */
- uint16_t flags; /* flags for this area */
-} __attribute__((packed));
-
-struct fmap {
- uint8_t signature[8]; /* "__FMAP__" (0x5F5F464D41505F5F) */
- uint8_t ver_major; /* major version */
- uint8_t ver_minor; /* minor version */
- uint64_t base; /* address of the firmware binary */
- uint32_t size; /* size of firmware binary in bytes */
- uint8_t name[FMAP_STRLEN]; /* name of this firmware binary */
- uint16_t nareas; /* number of areas described by
- fmap_areas[] below */
- struct fmap_area areas[];
-} __attribute__((packed));
-
-
-/* coreboot specific function prototypes */
-const struct fmap *fmap_find(void);
-const struct fmap_area *find_fmap_area(const struct fmap *fmap,
- const char name[]);
-int find_fmap_entry(const char name[], void **pointer);
#endif /* FLASHMAP_LIB_FMAP_H__*/