jonzhang@fb.com has uploaded this change for review. ( https://review.coreboot.org/c/coreboot/+/34501 )
Change subject: Get HyperThreading setting from RW_VPD for FSP UPD ......................................................................
Get HyperThreading setting from RW_VPD for FSP UPD
Summary: This patch adds a library function in vpd_decode.h which is available in romstage, and thus can be used to customize FSP UPD setting.
Fetch key named as "HyperThreading" from RW_VPD which is a VPD partition. If there is a valid value, use the value to set FSP UPD HyperThreading variable.
If RW_VPD is not found, or if "HyperThreading" key does not exist, or if the value of "HyperThreading" key is neither '1' nor '0', default value is used.
BDW-DE SOC code is updated to use this function, if VPD is configured.
Test Plan: * Build an OCP MonoLake coreboot image, run following command to initialize RW_VPD and insert HyperThreading key: vpd -f build/coreboot.rom -O -i RW_VPD -s 'HyperThreading=0' * Flash the image to MonoLake, boot and observe following message in boot log: Detected 16 CPU threads
If RW_VPD partition does not exist, or if HyperThreading key/value pair does not exist, the boot log has: Detected 32 CPU threads
Signed-off-by: Jonathan Zhang jonzhang@fb.com Change-Id: Ice6ffe3f7a14c7f09637c5dcfc47e551a57f42f1 --- M src/drivers/vpd/vpd_decode.c M src/drivers/vpd/vpd_decode.h M src/soc/intel/fsp_broadwell_de/fsp/chipset_fsp_util.c 3 files changed, 105 insertions(+), 0 deletions(-)
git pull ssh://review.coreboot.org:29418/coreboot refs/changes/01/34501/1
diff --git a/src/drivers/vpd/vpd_decode.c b/src/drivers/vpd/vpd_decode.c index 527c508..4638971 100644 --- a/src/drivers/vpd/vpd_decode.c +++ b/src/drivers/vpd/vpd_decode.c @@ -6,6 +6,8 @@ * This is a copy from upstream: * https://chromium.googlesource.com/chromiumos/platform/vpd/+/master/lib/vpd_d... */ +#include <device/mmio.h> +#include <string.h> #include "vpd_decode.h"
static int vpd_decode_len( @@ -95,3 +97,63 @@
return VPD_DECODE_OK; } + +/** + * search: Find first instance of string in a given region + * @param p string to find + * @param a start address of region to search + * @param lengthp length of string to search for + * @param lengtha length of region to search in + * @return offset offset from start address a where string was found. + * If string not found, return lengtha. + */ +static uintptr_t search(char *p, u8 *a, unsigned int lengthp, + unsigned int lengtha) +{ + int i, j; + + /* Searching */ + for (j = 0; j <= lengtha - lengthp; j++) { + for (i = 0; i < lengthp && p[i] == a[i + j]; i++) + ; + if (i >= lengthp) + return j; + } + return (uintptr_t)lengtha; +} + +/* + * Fetch HyperThreading key/value from a VPD partition, eg. RW_VPD. + * + * If a key with matching name is found, and if the value is + * either '1' or '0', the return value is set to true, + * and *hyper_threading is set accordingly. + * Otherwise, the return value is set to false. + * + * search_address points to the VPD parition memory address. + * search_length is the siae of such VPD partition. + */ +bool get_hyper_threading(u8 *hyper_threading, + void *search_address, size_t search_length) +{ + char key[] = "HyperThreading"; + uintptr_t offset; + + offset = search(key, search_address, strlen(key), search_length); + if (offset == search_length) { + return false; + } + + /* move to value field, and bypass the byte holding length of value */ + /* The size of key field is sizeof(key) - 1 */ + offset += sizeof(key); + *hyper_threading = read8(search_address + offset); + if (*hyper_threading == '1') + *hyper_threading = 1; + else if (*hyper_threading == '0') + *hyper_threading = 0; + else + return false; + + return true; +} diff --git a/src/drivers/vpd/vpd_decode.h b/src/drivers/vpd/vpd_decode.h index 5d595f3..25de12d 100644 --- a/src/drivers/vpd/vpd_decode.h +++ b/src/drivers/vpd/vpd_decode.h @@ -48,4 +48,18 @@ const u32 max_len, const u8 *input_buf, u32 *consumed, vpd_decode_callback callback, void *callback_arg);
+/* + * Fetch HyperThreading key/value from a VPD partition, eg. RW_VPD. + * + * If a key with matching name is found, and if the value is + * either '1' or '0', the return value is set to true, + * and *hyper_threading is set accordingly. + * Otherwise, the return value is set to false. + * + * search_address points to the VPD parition memory address. + * search_length is the siae of such VPD partition. + */ +bool get_hyper_threading(u8 *hyper_threading, + void *search_address, size_t search_length); + #endif /* __VPD_DECODE_H */ diff --git a/src/soc/intel/fsp_broadwell_de/fsp/chipset_fsp_util.c b/src/soc/intel/fsp_broadwell_de/fsp/chipset_fsp_util.c index edb313e..c5b2874 100644 --- a/src/soc/intel/fsp_broadwell_de/fsp/chipset_fsp_util.c +++ b/src/soc/intel/fsp_broadwell_de/fsp/chipset_fsp_util.c @@ -22,7 +22,9 @@ #include <cbmem.h> #include <device/device.h> #include <device/pci_def.h> +#include <device/mmio.h> #include <drivers/intel/fsp1_0/fsp_util.h> +#include <drivers/vpd/vpd_decode.h> #include <soc/pci_devs.h> #include <soc/romstage.h> #include <fsp.h> @@ -48,6 +50,11 @@ */ static void ConfigureDefaultUpdData(UPD_DATA_REGION *UpdData) { + struct region_device rdev; + void *search_address = NULL; + size_t search_length = -1; + u8 hyper_threading; + /* * Serial Port */ @@ -121,6 +128,28 @@ UpdData->Ehci2Enable = 1; else UpdData->Ehci2Enable = 0; + + /* + * If RW_VPD VPD partition exists, search key/value pairs + * to see if there are relevant FSP UPD variable setting(s). + * If so, use such setting(s) to customize FSP behavior. + */ + if (CONFIG(VPD)) { + if (!fmap_locate_area_as_rdev("RW_VPD", &rdev)) { + search_address = rdev_mmap_full(&rdev); + if (search_address != NULL) { + search_length = region_device_sz(&rdev); + /* + * If there is a valid value for HyperThreading key in RW_VPD, + * use the value to customize FSP UPD HyperThreading variable. + */ + if (get_hyper_threading(&hyper_threading, search_address, + search_length) == true) { + UpdData->HyperThreading = hyper_threading; + } + } + } + } }
/* Set up the Broadwell-DE specific structures for the call into the FSP */