[coreboot-gerrit] Patch set updated for coreboot: vendorcode/google/chromeos: Cache VPD data into CBMEM

Patrick Georgi (pgeorgi@google.com) gerrit at coreboot.org
Thu Nov 19 16:12:14 CET 2015


Patrick Georgi (pgeorgi at google.com) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/12453

-gerrit

commit c10419b9980a20c3279658ad257e762946a4ed4f
Author: Hung-Te Lin <hungte at chromium.org>
Date:   Mon Jul 13 15:49:57 2015 +0800

    vendorcode/google/chromeos: Cache VPD data into CBMEM
    
    There are few drawbacks reading VPD from SPI flash in user land, including
    "lack of firmware level authority" and "slow reading speed".
    
    Since for many platforms we are already reading VPD in firmware (for
    example MAC and serial number), caching the VPD data in CBMEM should
    will speed up and simplify user land VPD processing without adding
    performance cost.
    
    A new CBMEM ID is added: CBMEM_ID_VPD, referring to a structure containing
    raw Google VPD 2.0 structure and can be found by the new LB_TAG_VPD in
    Coreboot tables.
    
    BRANCH=smaug
    BUG=chrome-os-partner:39945
    TEST=emerge-smaug coreboot chromeos-bootimage # and boots successfully.
    
    [pg: lots of changes to make it work with what happened in upstream
    since 2013]
    
    Change-Id: If8629ac002d52abed7b480d3d06298665613edbf
    Signed-off-by: Patrick Georgi <pgeorgi at chromium.org>
    Original-Commit-Id: 117a9e88912860a22d250ff0e53a7d40237ddd45
    Original-Change-Id: Ic79f424a6e3edfb6c5d168b9661d61a56fab295f
    Original-Signed-off-by: Hung-Te Lin <hungte at chromium.org>
    Original-Reviewed-on: https://chromium-review.googlesource.com/285031
    Original-Reviewed-by: Aaron Durbin <adurbin at chromium.org>
---
 src/commonlib/include/commonlib/cbmem_id.h        |   2 +
 src/commonlib/include/commonlib/coreboot_tables.h |   1 +
 src/lib/coreboot_table.c                          |   1 +
 src/vendorcode/google/chromeos/cros_vpd.c         | 146 ++++++++++++++++------
 4 files changed, 111 insertions(+), 39 deletions(-)

diff --git a/src/commonlib/include/commonlib/cbmem_id.h b/src/commonlib/include/commonlib/cbmem_id.h
index 580d5ea..44ab31e 100644
--- a/src/commonlib/include/commonlib/cbmem_id.h
+++ b/src/commonlib/include/commonlib/cbmem_id.h
@@ -62,6 +62,7 @@
 #define CBMEM_ID_VBOOT_HANDOFF	0x780074f0
 #define CBMEM_ID_VBOOT_SEL_REG	0x780074f1
 #define CBMEM_ID_VBOOT_WORKBUF	0x78007343
+#define CBMEM_ID_VPD		0x56504420
 #define CBMEM_ID_WIFI_CALIBRATION 0x57494649
 
 #define CBMEM_ID_TO_NAME_TABLE				 \
@@ -105,5 +106,6 @@
 	{ CBMEM_ID_VBOOT_HANDOFF,	"VBOOT      " }, \
 	{ CBMEM_ID_VBOOT_SEL_REG,	"VBOOT SEL  " }, \
 	{ CBMEM_ID_VBOOT_WORKBUF,	"VBOOT WORK " }, \
+	{ CBMEM_ID_VPD,			"VPD        " }, \
 	{ CBMEM_ID_WIFI_CALIBRATION,	"WIFI CLBR  " },
 #endif /* _CBMEM_ID_H_ */
diff --git a/src/commonlib/include/commonlib/coreboot_tables.h b/src/commonlib/include/commonlib/coreboot_tables.h
index 5e0c87c..32c388b 100644
--- a/src/commonlib/include/commonlib/coreboot_tables.h
+++ b/src/commonlib/include/commonlib/coreboot_tables.h
@@ -245,6 +245,7 @@ void lb_ramoops(struct lb_header *header);
 #define LB_TAG_MRC_CACHE	0x0018
 #define LB_TAG_ACPI_GNVS	0x0024
 #define LB_TAG_WIFI_CALIBRATION	0x0027
+#define LB_TAG_VPD		0x002c
 struct lb_cbmem_ref {
 	uint32_t tag;
 	uint32_t size;
diff --git a/src/lib/coreboot_table.c b/src/lib/coreboot_table.c
index 258a4a5..2226f5e 100644
--- a/src/lib/coreboot_table.c
+++ b/src/lib/coreboot_table.c
@@ -285,6 +285,7 @@ static void add_cbmem_pointers(struct lb_header *header)
 		{CBMEM_ID_TIMESTAMP, LB_TAG_TIMESTAMPS},
 		{CBMEM_ID_CONSOLE, LB_TAG_CBMEM_CONSOLE},
 		{CBMEM_ID_ACPI_GNVS, LB_TAG_ACPI_GNVS},
+		{CBMEM_ID_VPD, LB_TAG_VPD},
 		{CBMEM_ID_WIFI_CALIBRATION, LB_TAG_WIFI_CALIBRATION}
 	};
 	int i;
diff --git a/src/vendorcode/google/chromeos/cros_vpd.c b/src/vendorcode/google/chromeos/cros_vpd.c
index f9aec88..72f1219 100644
--- a/src/vendorcode/google/chromeos/cros_vpd.c
+++ b/src/vendorcode/google/chromeos/cros_vpd.c
@@ -6,6 +6,7 @@
 
 #include <console/console.h>
 
+#include <cbmem.h>
 #include <fmap.h>
 #include <stdlib.h>
 #include <string.h>
@@ -17,6 +18,8 @@
 /* Currently we only support Google VPD 2.0, which has a fixed offset. */
 enum {
 	GOOGLE_VPD_2_0_OFFSET = 0x600,
+	CROSVPD_CBMEM_MAGIC = 0x43524f53,
+	CROSVPD_CBMEM_VERSION = 0x0001,
 };
 
 struct vpd_gets_arg {
@@ -26,56 +29,121 @@ struct vpd_gets_arg {
 	int matched;
 };
 
-static int cros_vpd_load(uint8_t **vpd_address, int32_t *vpd_size)
+struct vpd_cbmem {
+	uint32_t magic;
+	uint32_t version;
+	uint32_t ro_size;
+	uint32_t rw_size;
+	uint8_t blob[0];
+	/* The blob contains both RO and RW data. It starts with RO (0 ..
+	 * ro_size) and then RW (ro_size .. ro_size+rw_size).
+	 */
+};
+
+/* returns the size of data in a VPD 2.0 formatted fmap region, or 0 */
+static int32_t get_vpd_size(const char *fmap_name, int32_t *base)
 {
-	MAYBE_STATIC int cached = 0;
-	MAYBE_STATIC uint8_t *cached_address = NULL;
-	MAYBE_STATIC int32_t cached_size = 0;
-	MAYBE_STATIC int result = -1;
 	struct google_vpd_info info;
-	int32_t base;
 	struct region_device vpd;
+	int32_t size;
 
-	if (cached) {
-		*vpd_address = cached_address;
-		*vpd_size = cached_size;
-		return result;
-	}
-
-	cached = 1;
-	if (fmap_locate_area_as_rdev("RO_VPD", &vpd)) {
-		printk(BIOS_ERR, "%s: No RO_VPD FMAP section.\n", __func__);
-		return result;
+	if (fmap_locate_area_as_rdev(fmap_name, &vpd)) {
+		printk(BIOS_ERR, "%s: No %s FMAP section.\n", __func__,
+			fmap_name);
+		return 0;
 	}
 
-	base = 0;
-	cached_size = region_device_sz(&vpd);
+	size = region_device_sz(&vpd);
 
-	if ((cached_size < GOOGLE_VPD_2_0_OFFSET + sizeof(info)) ||
+	if ((size < GOOGLE_VPD_2_0_OFFSET + sizeof(info)) ||
 	    rdev_chain(&vpd, &vpd, GOOGLE_VPD_2_0_OFFSET,
-			cached_size - GOOGLE_VPD_2_0_OFFSET)) {
+			size - GOOGLE_VPD_2_0_OFFSET)) {
 		printk(BIOS_ERR, "%s: Too small (%d) for Google VPD 2.0.\n",
-		       __func__, cached_size);
-		return result;
+		       __func__, size);
+		return 0;
 	}
 
 	/* Try if we can find a google_vpd_info, otherwise read whole VPD. */
-	if (rdev_readat(&vpd, &info, base, sizeof(info)) == sizeof(info) &&
+	if (rdev_readat(&vpd, &info, *base, sizeof(info)) == sizeof(info) &&
 	    memcmp(info.header.magic, VPD_INFO_MAGIC, sizeof(info.header.magic))
-	    == 0 && cached_size >= info.size + sizeof(info)) {
-		base += sizeof(info);
-		cached_size = info.size;
+	    == 0 && size >= info.size + sizeof(info)) {
+		*base += sizeof(info);
+		size = info.size;
+	} else {
+		size -= GOOGLE_VPD_2_0_OFFSET;
+	}
+
+	return size;
+}
+
+static void cbmem_add_cros_vpd(int is_recovery)
+{
+	struct region_device vpd;
+	struct vpd_cbmem *cbmem;
+	int32_t ro_vpd_base = 0, rw_vpd_base = 0;
+	int32_t ro_vpd_size, rw_vpd_size;
+
+	ro_vpd_size = get_vpd_size("RO_VPD", &ro_vpd_base);
+	rw_vpd_size = get_vpd_size("RW_VPD", &rw_vpd_base);
+
+	/* no VPD at all? nothing to do then */
+	if ((ro_vpd_size == 0) && (rw_vpd_size == 0))
+		return;
+
+	cbmem = cbmem_add(CBMEM_ID_VPD, sizeof(*cbmem) + ro_vpd_size +
+		rw_vpd_size);
+	if (!cbmem) {
+		printk(BIOS_ERR, "%s: Failed to allocate CBMEM (%zu+%zu).\n",
+			__func__, ro_vpd_size, rw_vpd_size);
+		return;
 	}
 
-	cached_address = rdev_mmap(&vpd, base, cached_size);
-	if (cached_address) {
-		*vpd_address = cached_address;
-		*vpd_size = cached_size;
-		printk(BIOS_DEBUG, "%s: Got VPD: %#x+%#x\n", __func__, base,
-		       cached_size);
-		result = 0;
+	cbmem->magic = CROSVPD_CBMEM_MAGIC;
+	cbmem->version = CROSVPD_CBMEM_VERSION;
+	cbmem->ro_size = 0;
+	cbmem->rw_size = 0;
+
+	if (ro_vpd_size) {
+		if (fmap_locate_area_as_rdev("RO_VPD", &vpd)) {
+			/* shouldn't happen, but let's be extra defensive */
+			printk(BIOS_ERR, "%s: No RO_VPD FMAP section.\n",
+				__func__);
+			return;
+		}
+		rdev_chain(&vpd, &vpd, GOOGLE_VPD_2_0_OFFSET,
+			region_device_sz(&vpd) - GOOGLE_VPD_2_0_OFFSET);
+
+
+		if (rdev_readat(&vpd, cbmem->blob, ro_vpd_base, ro_vpd_size) ==
+			ro_vpd_size) {
+			cbmem->ro_size = ro_vpd_size;
+		} else {
+			printk(BIOS_ERR,
+				"%s: Reading RO_VPD FMAP section failed.\n",
+				__func__);
+			ro_vpd_size = 0;
+		}
+	}
+
+	if (rw_vpd_size) {
+		if (fmap_locate_area_as_rdev("RW_VPD", &vpd)) {
+			/* shouldn't happen, but let's be extra defensive */
+			printk(BIOS_ERR, "%s: No RW_VPD FMAP section.\n",
+				__func__);
+			return;
+		}
+		rdev_chain(&vpd, &vpd, GOOGLE_VPD_2_0_OFFSET,
+			region_device_sz(&vpd) - GOOGLE_VPD_2_0_OFFSET);
+
+		if (rdev_readat(&vpd, cbmem->blob + ro_vpd_size, rw_vpd_base,
+			rw_vpd_size) == rw_vpd_size) {
+			cbmem->rw_size = rw_vpd_size;
+		} else {
+			printk(BIOS_ERR,
+				"%s: Reading RW_VPD FMAP section failed.\n",
+				__func__);
+		}
 	}
-	return result;
 }
 
 static int vpd_gets_callback(const uint8_t *key, int32_t key_len,
@@ -97,19 +165,18 @@ static int vpd_gets_callback(const uint8_t *key, int32_t key_len,
 
 const void *cros_vpd_find(const char *key, int *size)
 {
-	uint8_t *vpd_address = NULL;
-	int32_t vpd_size = 0;
 	struct vpd_gets_arg arg = {0};
 	int consumed = 0;
+	const struct vpd_cbmem *vpd;
 
-	if (cros_vpd_load(&vpd_address, &vpd_size) != 0) {
+	vpd = cbmem_find(CBMEM_ID_VPD);
+	if (!vpd || !vpd->ro_size)
 		return NULL;
-	}
 
 	arg.key = (const uint8_t *)key;
 	arg.key_len = strlen(key);
 
-	while (VPD_OK == decodeVpdString(vpd_size, vpd_address, &consumed,
+	while (VPD_OK == decodeVpdString(vpd->ro_size, vpd->blob, &consumed,
 					 vpd_gets_callback, &arg)) {
 		/* Iterate until found or no more entries. */
 	}
@@ -141,3 +208,4 @@ char *cros_vpd_gets(const char *key, char *buffer, int size)
 	return buffer;
 }
 
+RAMSTAGE_CBMEM_INIT_HOOK(cbmem_add_cros_vpd)



More information about the coreboot-gerrit mailing list