Philipp Deppenwiese has submitted this change and it was merged. ( https://review.coreboot.org/25046 )
Change subject: drivers/vpd: Add VPD support ......................................................................
drivers/vpd: Add VPD support
VPD reference: https://chromium.googlesource.com/chromiumos/platform/vpd/+/master/README.md
Copy ChromeOS VPD driver to add support for VPD without CROMEOS. Possible use case: * Storing calibration data * Storing MAC address * Storing serial * Storing boot options
+ Now it's possible to define the VPD space by choosing one of the following enums: VPD_ANY, VPD_RW, VPD_RO. + CHROMEOS selects now VPD as part of it. + VPD is implemented as driver.
Change-Id: Id9263bd39bf25d024e93daa57053fefcb1adc53a Signed-off-by: Patrick Rudolph patrick.rudolph@9elements.com Reviewed-on: https://review.coreboot.org/25046 Reviewed-by: David Hendricks david.hendricks@gmail.com Tested-by: build bot (Jenkins) no-reply@coreboot.org --- A src/drivers/vpd/Kconfig A src/drivers/vpd/Makefile.inc A src/drivers/vpd/lib_vpd.c R src/drivers/vpd/lib_vpd.h R src/drivers/vpd/vpd.c R src/drivers/vpd/vpd.h R src/drivers/vpd/vpd_tables.h M src/mainboard/google/reef/variants/snappy/mainboard.c M src/vendorcode/google/chromeos/Kconfig M src/vendorcode/google/chromeos/Makefile.inc M src/vendorcode/google/chromeos/sar.c M src/vendorcode/google/chromeos/vpd_calibration.c D src/vendorcode/google/chromeos/vpd_decode.c M src/vendorcode/google/chromeos/vpd_mac.c M src/vendorcode/google/chromeos/vpd_serialno.c M src/vendorcode/google/chromeos/wrdd.c 16 files changed, 206 insertions(+), 140 deletions(-)
Approvals: build bot (Jenkins): Verified David Hendricks: Looks good to me, approved
diff --git a/src/drivers/vpd/Kconfig b/src/drivers/vpd/Kconfig new file mode 100644 index 0000000..335b907 --- /dev/null +++ b/src/drivers/vpd/Kconfig @@ -0,0 +1,28 @@ +## +## This file is part of the coreboot project. +## +## Copyright (C) 2012 The Chromium OS 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. +## + +config VPD + bool "Support for Vital Product Data tables" + default n + help + Enable support for flash based vital product data. + +if VPD + +config VPD_DEBUG + bool "Enable VPD debug output" + default n + +endif diff --git a/src/drivers/vpd/Makefile.inc b/src/drivers/vpd/Makefile.inc new file mode 100644 index 0000000..91c069d --- /dev/null +++ b/src/drivers/vpd/Makefile.inc @@ -0,0 +1,2 @@ +romstage-$(CONFIG_VPD) += lib_vpd.c +ramstage-$(CONFIG_VPD) += vpd.c lib_vpd.c diff --git a/src/drivers/vpd/lib_vpd.c b/src/drivers/vpd/lib_vpd.c new file mode 100644 index 0000000..0744a71 --- /dev/null +++ b/src/drivers/vpd/lib_vpd.c @@ -0,0 +1,113 @@ +/* + * Copyright (c) 2014 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. + * + */ +#include <assert.h> +#include "lib_vpd.h" + +/* Given an encoded string, this functions decodes the length field which varies + * from 1 byte to many bytes. + * + * The in points the actual byte going to be decoded. The *length returns + * the decoded length field. The number of consumed bytes will be stroed in + * decoded_len. + * + * Returns VPD_FAIL if more bit is 1, but actually reaches the end of string. + */ +int decodeLen(const int32_t max_len, + const uint8_t *in, + int32_t *length, + int32_t *decoded_len) +{ + uint8_t more; + int i = 0; + + assert(length); + assert(decoded_len); + + *length = 0; + do { + if (i >= max_len) + return VPD_FAIL; + + more = in[i] & 0x80; + *length <<= 7; + *length |= in[i] & 0x7f; + ++i; + } while (more); + + *decoded_len = i; + + return VPD_OK; +} + +/* Given the encoded string, this function invokes callback with extracted + * (key, value). The *consumed will be plused the number of bytes consumed in + * this function. + * + * The input_buf points to the first byte of the input buffer. + * + * The *consumed starts from 0, which is actually the next byte to be decoded. + * It can be non-zero to be used in multiple calls. + * + * If one entry is successfully decoded, sends it to callback and returns the + * result. + */ +int decodeVpdString(const int32_t max_len, + const uint8_t *input_buf, + int32_t *consumed, + VpdDecodeCallback callback, + void *callback_arg) +{ + int type; + int32_t key_len, value_len; + int32_t decoded_len; + const uint8_t *key, *value; + + /* type */ + if (*consumed >= max_len) + return VPD_FAIL; + + type = input_buf[*consumed]; + switch (type) { + case VPD_TYPE_INFO: + case VPD_TYPE_STRING: + (*consumed)++; + /* key */ + if (VPD_OK != decodeLen(max_len - *consumed, + &input_buf[*consumed], &key_len, + &decoded_len) || + *consumed + decoded_len >= max_len) { + return VPD_FAIL; + } + + *consumed += decoded_len; + key = &input_buf[*consumed]; + *consumed += key_len; + + /* value */ + if (VPD_OK != decodeLen(max_len - *consumed, + &input_buf[*consumed], + &value_len, &decoded_len) || + *consumed + decoded_len > max_len) { + return VPD_FAIL; + } + *consumed += decoded_len; + value = &input_buf[*consumed]; + *consumed += value_len; + + if (type == VPD_TYPE_STRING) + return callback(key, key_len, value, value_len, + callback_arg); + + return VPD_OK; + + default: + return VPD_FAIL; + break; + } + + return VPD_OK; +} diff --git a/src/vendorcode/google/chromeos/lib_vpd.h b/src/drivers/vpd/lib_vpd.h similarity index 93% rename from src/vendorcode/google/chromeos/lib_vpd.h rename to src/drivers/vpd/lib_vpd.h index e08cb3a..7a7566b 100644 --- a/src/vendorcode/google/chromeos/lib_vpd.h +++ b/src/drivers/vpd/lib_vpd.h @@ -11,25 +11,25 @@ #include <inttypes.h>
enum { - VPD_OK = 0, - VPD_FAIL, + VPD_OK = 0, + VPD_FAIL, };
enum { - VPD_TYPE_TERMINATOR = 0, - VPD_TYPE_STRING, - VPD_TYPE_INFO = 0xfe, - VPD_TYPE_IMPLICIT_TERMINATOR = 0xff, + VPD_TYPE_TERMINATOR = 0, + VPD_TYPE_STRING, + VPD_TYPE_INFO = 0xfe, + VPD_TYPE_IMPLICIT_TERMINATOR = 0xff, };
enum { - VPD_AS_LONG_AS = -1, + VPD_AS_LONG_AS = -1, };
enum { /* export_type */ - VPD_EXPORT_KEY_VALUE = 1, - VPD_EXPORT_VALUE, - VPD_EXPORT_AS_PARAMETER, + VPD_EXPORT_KEY_VALUE = 1, + VPD_EXPORT_VALUE, + VPD_EXPORT_AS_PARAMETER, };
/* Callback for decodeVpdString to invoke. */ @@ -39,15 +39,15 @@
/* Container data types */ struct StringPair { - uint8_t *key; - uint8_t *value; - int pad_len; - int filter_out; /* TRUE means not exported. */ - struct StringPair *next; + uint8_t *key; + uint8_t *value; + int pad_len; + int filter_out; /* TRUE means not exported. */ + struct StringPair *next; };
struct PairContainer { - struct StringPair *first; + struct StringPair *first; };
diff --git a/src/vendorcode/google/chromeos/cros_vpd.c b/src/drivers/vpd/vpd.c similarity index 89% rename from src/vendorcode/google/chromeos/cros_vpd.c rename to src/drivers/vpd/vpd.c index d0e2cc1..e620b58 100644 --- a/src/vendorcode/google/chromeos/cros_vpd.c +++ b/src/drivers/vpd/vpd.c @@ -5,14 +5,13 @@ */
#include <console/console.h> - #include <cbmem.h> #include <fmap.h> #include <stdlib.h> #include <string.h> #include <timestamp.h>
-#include "cros_vpd.h" +#include "vpd.h" #include "lib_vpd.h" #include "vpd_tables.h"
@@ -178,7 +177,7 @@ return VPD_FAIL; }
-const void *cros_vpd_find(const char *key, int *size) +const void *vpd_find(const char *key, int *size, enum vpd_region region) { struct vpd_gets_arg arg = {0}; int consumed = 0; @@ -191,10 +190,18 @@ arg.key = (const uint8_t *)key; arg.key_len = strlen(key);
- while (VPD_OK == decodeVpdString(vpd->ro_size, vpd->blob, &consumed, - vpd_gets_callback, &arg)) { + if (region == VPD_ANY || region == VPD_RO) + while (VPD_OK == decodeVpdString(vpd->ro_size, vpd->blob, + &consumed, vpd_gets_callback, &arg)) { /* Iterate until found or no more entries. */ - } + } + + if (!arg.matched && region != VPD_RO) + while (VPD_OK == decodeVpdString(vpd->rw_size, + vpd->blob + vpd->ro_size, &consumed, + vpd_gets_callback, &arg)) { + /* Iterate until found or no more entries. */ + }
if (!arg.matched) return NULL; @@ -203,12 +210,12 @@ return arg.value; }
-char *cros_vpd_gets(const char *key, char *buffer, int size) +char *vpd_gets(const char *key, char *buffer, int size, enum vpd_region region) { const void *string_address; int string_size;
- string_address = cros_vpd_find(key, &string_size); + string_address = vpd_find(key, &string_size, region);
if (!string_address) return NULL; diff --git a/src/vendorcode/google/chromeos/cros_vpd.h b/src/drivers/vpd/vpd.h similarity index 76% rename from src/vendorcode/google/chromeos/cros_vpd.h rename to src/drivers/vpd/vpd.h index 1fa56a4..6009b8b 100644 --- a/src/vendorcode/google/chromeos/cros_vpd.h +++ b/src/drivers/vpd/vpd.h @@ -4,12 +4,14 @@ * found in the LICENSE file. */
-#ifndef __CROS_VPD_H__ -#define __CROS_VPD_H__ +#ifndef __VPD_H__ +#define __VPD_H__
-#define CROS_VPD_REGION_NAME "region" -#define CROS_VPD_WIFI_SAR_NAME "wifi_sar" - +enum vpd_region { + VPD_ANY = 0, + VPD_RO = 1, + VPD_RW = 2 +}; /* * Reads VPD string value by key. * @@ -19,7 +21,7 @@ * * Returns NULL if key is not found, otherwise buffer. */ -char *cros_vpd_gets(const char *key, char *buffer, int size); +char *vpd_gets(const char *key, char *buffer, int size, enum vpd_region region);
/* * Find VPD value by key. @@ -35,6 +37,6 @@ * Returns NULL if key is not found. */
-const void *cros_vpd_find(const char *key, int *size); +const void *vpd_find(const char *key, int *size, enum vpd_region region);
-#endif /* __CROS_VPD_H__ */ +#endif /* __VPD_H__ */ diff --git a/src/vendorcode/google/chromeos/vpd_tables.h b/src/drivers/vpd/vpd_tables.h similarity index 100% rename from src/vendorcode/google/chromeos/vpd_tables.h rename to src/drivers/vpd/vpd_tables.h diff --git a/src/mainboard/google/reef/variants/snappy/mainboard.c b/src/mainboard/google/reef/variants/snappy/mainboard.c index a625c60..73de67e 100644 --- a/src/mainboard/google/reef/variants/snappy/mainboard.c +++ b/src/mainboard/google/reef/variants/snappy/mainboard.c @@ -16,7 +16,7 @@ #include <string.h> #include <baseboard/variants.h> #include <ec/google/chromeec/ec.h> -#include <vendorcode/google/chromeos/cros_vpd.h> +#include <drivers/vpd/vpd.h> #include <soc/cpu.h> #include <soc/intel/apollolake/chip.h>
@@ -59,7 +59,7 @@ if (!IS_ENABLED(CONFIG_CHROMEOS)) return board_sku_num;
- if (!cros_vpd_gets(vpd_skuid, vpd_buffer, ARRAY_SIZE(vpd_buffer))) + if (!vpd_gets(vpd_skuid, vpd_buffer, ARRAY_SIZE(vpd_buffer), VPD_ANY)) return board_sku_num;
vpd_len = strlen(vpd_buffer); diff --git a/src/vendorcode/google/chromeos/Kconfig b/src/vendorcode/google/chromeos/Kconfig index 4f1fad9..1dd726f 100644 --- a/src/vendorcode/google/chromeos/Kconfig +++ b/src/vendorcode/google/chromeos/Kconfig @@ -24,6 +24,7 @@ select ELOG if BOOT_DEVICE_SUPPORTS_WRITES select COLLECT_TIMESTAMPS select VBOOT + select VPD help Enable ChromeOS specific features like the GPIO sub table in the coreboot table. NOTE: Enabling this option on an unsupported diff --git a/src/vendorcode/google/chromeos/Makefile.inc b/src/vendorcode/google/chromeos/Makefile.inc index e833e0d..ecd82b7 100644 --- a/src/vendorcode/google/chromeos/Makefile.inc +++ b/src/vendorcode/google/chromeos/Makefile.inc @@ -17,8 +17,7 @@ ramstage-$(CONFIG_HAVE_ACPI_TABLES) += gnvs.c ramstage-$(CONFIG_HAVE_ACPI_TABLES) += acpi.c ramstage-$(CONFIG_CHROMEOS_RAMOOPS) += ramoops.c -romstage-y += vpd_decode.c -ramstage-y += vpd_decode.c cros_vpd.c vpd_mac.c vpd_serialno.c vpd_calibration.c +ramstage-y += vpd_mac.c vpd_serialno.c vpd_calibration.c ramstage-$(CONFIG_CHROMEOS_DISABLE_PLATFORM_HIERARCHY_ON_RESUME) += tpm2.c ramstage-$(CONFIG_HAVE_REGULATORY_DOMAIN) += wrdd.c ramstage-$(CONFIG_USE_SAR) += sar.c diff --git a/src/vendorcode/google/chromeos/sar.c b/src/vendorcode/google/chromeos/sar.c index fc72dc1..6799f12 100644 --- a/src/vendorcode/google/chromeos/sar.c +++ b/src/vendorcode/google/chromeos/sar.c @@ -19,9 +19,10 @@ #include <types.h> #include <string.h> #include <sar.h> -#include "cros_vpd.h" +#include <drivers/vpd/vpd.h>
#define WIFI_SAR_CBFS_FILENAME "wifi_sar_defaults.hex" +#define CROS_VPD_WIFI_SAR_NAME "wifi_sar"
static int load_sar_file_from_cbfs(void *buf, size_t buffer_size) { @@ -55,7 +56,7 @@ int get_wifi_sar_limits(struct wifi_sar_limits *sar_limits) { const char *wifi_sar_limit_key = CROS_VPD_WIFI_SAR_NAME; - /* cros_vpd_gets() reads in one less than size characters from the VPD + /* vpd_gets() reads in one less than size characters from the VPD * with a terminating null byte ('\0') stored as the last character into * the buffer, thus the increasing by 1 for buffer_size. */ const size_t buffer_size = (sizeof(struct wifi_sar_limits) / @@ -79,8 +80,8 @@ }
/* Try to read the SAR limit entry from VPD */ - if (!cros_vpd_gets(wifi_sar_limit_key, wifi_sar_limit_str, - buffer_size)) { + if (!vpd_gets(wifi_sar_limit_key, wifi_sar_limit_str, + buffer_size, VPD_ANY)) { printk(BIOS_ERR, "Error: Could not locate '%s' in VPD.\n", wifi_sar_limit_key);
diff --git a/src/vendorcode/google/chromeos/vpd_calibration.c b/src/vendorcode/google/chromeos/vpd_calibration.c index 697ff95..7f9910b 100644 --- a/src/vendorcode/google/chromeos/vpd_calibration.c +++ b/src/vendorcode/google/chromeos/vpd_calibration.c @@ -19,7 +19,7 @@ #include <string.h>
#include <vendorcode/google/chromeos/chromeos.h> -#include <vendorcode/google/chromeos/cros_vpd.h> +#include <drivers/vpd/vpd.h>
/* * This file provides functions looking in the VPD for WiFi calibration data, @@ -112,7 +112,7 @@ strcpy(cache->key_name, templates[i]); cache->key_name[index_location] = j + '0';
- payload = cros_vpd_find(cache->key_name, &payload_size); + payload = vpd_find(cache->key_name, &payload_size, VPD_ANY); if (!payload) continue;
diff --git a/src/vendorcode/google/chromeos/vpd_decode.c b/src/vendorcode/google/chromeos/vpd_decode.c deleted file mode 100644 index 545fd81..0000000 --- a/src/vendorcode/google/chromeos/vpd_decode.c +++ /dev/null @@ -1,89 +0,0 @@ -/* - * Copyright (c) 2014 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. - * - */ -#include <assert.h> -#include "lib_vpd.h" - -int decodeLen( - const int32_t max_len, - const uint8_t *in, - int32_t *length, - int32_t *decoded_len) { - uint8_t more; - int i = 0; - - assert(length); - assert(decoded_len); - - *length = 0; - do { - if (i >= max_len) return VPD_FAIL; - more = in[i] & 0x80; - *length <<= 7; - *length |= in[i] & 0x7f; - ++i; - } while (more); - - *decoded_len = i; - - return VPD_OK; -} - -/* Sequentially decodes type, key, and value. - */ -int decodeVpdString( - const int32_t max_len, - const uint8_t *input_buf, - int32_t *consumed, - VpdDecodeCallback callback, - void *callback_arg) { - int type; - int32_t key_len, value_len; - int32_t decoded_len; - const uint8_t *key, *value; - - /* type */ - if (*consumed >= max_len) - return VPD_FAIL; - - type = input_buf[*consumed]; - switch (type) { - case VPD_TYPE_INFO: - case VPD_TYPE_STRING: - (*consumed)++; - - /* key */ - if (VPD_OK != decodeLen(max_len - *consumed, &input_buf[*consumed], - &key_len, &decoded_len) || - *consumed + decoded_len >= max_len) { - return VPD_FAIL; - } - - *consumed += decoded_len; - key = &input_buf[*consumed]; - *consumed += key_len; - - /* value */ - if (VPD_OK != decodeLen(max_len - *consumed, &input_buf[*consumed], - &value_len, &decoded_len) || - *consumed + decoded_len > max_len) { - return VPD_FAIL; - } - *consumed += decoded_len; - value = &input_buf[*consumed]; - *consumed += value_len; - - if (type == VPD_TYPE_STRING) - return callback(key, key_len, value, value_len, callback_arg); - - return VPD_OK; - - default: - return VPD_FAIL; - break; - } - return VPD_OK; -} diff --git a/src/vendorcode/google/chromeos/vpd_mac.c b/src/vendorcode/google/chromeos/vpd_mac.c index 0619974..e3ef04b 100644 --- a/src/vendorcode/google/chromeos/vpd_mac.c +++ b/src/vendorcode/google/chromeos/vpd_mac.c @@ -17,7 +17,7 @@ #include <console/console.h> #include <string.h>
-#include <vendorcode/google/chromeos/cros_vpd.h> +#include <drivers/vpd/vpd.h>
/* * Decode string representation of the MAC address (a string of 12 hex @@ -84,8 +84,8 @@ * If there are no more MAC addresses of this template * in the VPD - move on. */ - if (!cros_vpd_gets(mac_addr_key, mac_addr_str, - sizeof(mac_addr_str))) + if (!vpd_gets(mac_addr_key, mac_addr_str, + sizeof(mac_addr_str), VPD_ANY)) break;
if (!macs) { diff --git a/src/vendorcode/google/chromeos/vpd_serialno.c b/src/vendorcode/google/chromeos/vpd_serialno.c index e9a771e..8cae5d6 100644 --- a/src/vendorcode/google/chromeos/vpd_serialno.c +++ b/src/vendorcode/google/chromeos/vpd_serialno.c @@ -18,7 +18,7 @@ #include <assert.h> #include <string.h>
-#include <vendorcode/google/chromeos/cros_vpd.h> +#include <drivers/vpd/vpd.h>
void lb_table_add_serialno_from_vpd(struct lb_header *header) { @@ -27,8 +27,8 @@ char serialno[32]; size_t len;
- if (!cros_vpd_gets(serialno_key, serialno, - sizeof(serialno))) { + if (!vpd_gets(serialno_key, serialno, + sizeof(serialno), VPD_ANY)) { printk(BIOS_ERR, "no serial number in vpd\n"); return; } diff --git a/src/vendorcode/google/chromeos/wrdd.c b/src/vendorcode/google/chromeos/wrdd.c index ad80992..093e6cd 100644 --- a/src/vendorcode/google/chromeos/wrdd.c +++ b/src/vendorcode/google/chromeos/wrdd.c @@ -18,7 +18,9 @@ #include <types.h> #include <string.h> #include <wrdd.h> -#include "cros_vpd.h" +#include <drivers/vpd/vpd.h> + +#define CROS_VPD_REGION_NAME "region"
/* * wrdd_domain_value is ISO 3166-2 @@ -59,8 +61,8 @@ char *separator;
/* If not found for any reason fall backto the default value */ - if (!cros_vpd_gets(wrdd_domain_key, wrdd_domain_code, - ARRAY_SIZE(wrdd_domain_code))) { + if (!vpd_gets(wrdd_domain_key, wrdd_domain_code, + ARRAY_SIZE(wrdd_domain_code), VPD_ANY)) { printk(BIOS_DEBUG, "Error: Could not locate '%s' in VPD\n", wrdd_domain_key); return WRDD_DEFAULT_REGULATORY_DOMAIN;