[coreboot-gerrit] Patch set updated for coreboot: 4067c57 chromeos: Add a function to copy VPD WiFi calibration data to CBMEM

Patrick Georgi (pgeorgi@google.com) gerrit at coreboot.org
Fri Apr 10 13:17:15 CEST 2015


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

-gerrit

commit 4067c5703845b4879523be11c2ed13029329deaa
Author: Vadim Bendebury <vbendeb at 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 at chromium.org>
    Original-Reviewed-on: https://chromium-review.googlesource.com/225271
    Original-Reviewed-by: Aaron Durbin <adurbin at chromium.org>
    
    (cherry picked from commit 9fe185ae5fdc1a896bf892b498bff27a3462caeb)
    Signed-off-by: Aaron Durbin <adurbin at 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 fbd12fb..36997ed 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 vpd_mac.c
+ramstage-y += vpd_decode.c cros_vpd.c vpd_mac.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);
+	}
+}



More information about the coreboot-gerrit mailing list