From 437da71d0a9c7f397860efd02ddb03de9fd5b874 Mon Sep 17 00:00:00 2001 From: Angel Pons Date: Fri, 3 Sep 2021 16:51:40 +0200 Subject: SMBIOS/SCONFIG: Allow devtree-defined Type 41 entries Introduce the `smbios_dev_info` devicetree keyword to specify the instance ID and RefDes (Reference Designation) of onboard devices. Example syntax: device pci 1c.0 on # PCIe Port #1 device pci 00.0 on smbios_dev_info 6 end end device pci 1c.1 on # PCIe Port #2 device pci 00.0 on smbios_dev_info 42 "PCIe-PCI Time Machine" end end The `SMBIOS_TYPE41_PROVIDED_BY_DEVTREE` Kconfig option enables using this syntax to control the generated Type 41 entries. When this option is enabled, Type 41 entries are only autogenerated for devices with a defined instance ID. This avoids having to keep track of which instance IDs have been used for every device class. Using `smbios_dev_info` when `SMBIOS_TYPE41_PROVIDED_BY_DEVTREE` is not enabled will result in a build-time error, as the syntax is meaningless in this case. This is done with preprocessor guards around the Type 41 members in `struct device` and the code which uses the guarded members. Although the preprocessor usage isn't particularly elegant, adjusting the devicetree syntax and/or grammar depending on a Kconfig option is probably even worse. Change-Id: Iecca9ada6ee1000674cb5dd7afd5c309d8e1a64b Signed-off-by: Angel Pons Reviewed-on: https://review.coreboot.org/c/coreboot/+/57370 Tested-by: build bot (Jenkins) Reviewed-by: Tim Wawrzynczak Reviewed-by: Nico Huber --- src/Kconfig | 15 +++++++++++++++ src/arch/x86/smbios.c | 43 ++++++++++++++++++++++++++++++++++--------- src/include/device/device.h | 11 +++++++++++ 3 files changed, 60 insertions(+), 9 deletions(-) (limited to 'src') diff --git a/src/Kconfig b/src/Kconfig index be269b6195..e4ddf0cc70 100644 --- a/src/Kconfig +++ b/src/Kconfig @@ -785,6 +785,21 @@ config GENERATE_SMBIOS_TABLES If unsure, say Y. +config SMBIOS_TYPE41_PROVIDED_BY_DEVTREE + bool + depends on ARCH_X86 + help + If enabled, only generate SMBIOS Type 41 entries for PCI devices in + the devicetree for which Type 41 information is provided, e.g. with + the `smbios_dev_info` devicetree syntax. This is useful to manually + assign specific instance IDs to onboard devices irrespective of the + device traversal order. It is assumed that instance IDs for devices + of the same class are unique. + When disabled, coreboot autogenerates SMBIOS Type 41 entries for all + appropriate PCI devices in the devicetree. Instance IDs are assigned + successive numbers from a monotonically increasing counter, with one + counter for each device class. + config SMBIOS_PROVIDED_BY_MOBO bool default n diff --git a/src/arch/x86/smbios.c b/src/arch/x86/smbios.c index ea429713ae..c05f905892 100644 --- a/src/arch/x86/smbios.c +++ b/src/arch/x86/smbios.c @@ -1177,30 +1177,55 @@ static u8 smbios_get_device_type_from_dev(struct device *dev) } } -static int smbios_generate_type41_from_devtree(struct device *dev, int *handle, - unsigned long *current) +static bool smbios_get_type41_instance_id(struct device *dev, u8 device_type, u8 *instance_id) { +#if CONFIG(SMBIOS_TYPE41_PROVIDED_BY_DEVTREE) + *instance_id = dev->smbios_instance_id; + return dev->smbios_instance_id_valid; +#else static u8 type41_inst_cnt[SMBIOS_DEVICE_TYPE_COUNT + 1] = {}; + if (device_type == SMBIOS_DEVICE_TYPE_OTHER || + device_type == SMBIOS_DEVICE_TYPE_UNKNOWN) + return false; + + if (device_type > SMBIOS_DEVICE_TYPE_COUNT) + return false; + + *instance_id = type41_inst_cnt[device_type]++; + return true; +#endif +} + +static const char *smbios_get_type41_refdes(struct device *dev) +{ +#if CONFIG(SMBIOS_TYPE41_PROVIDED_BY_DEVTREE) + if (dev->smbios_refdes) + return dev->smbios_refdes; +#endif + return get_pci_subclass_name(dev); +} + +static int smbios_generate_type41_from_devtree(struct device *dev, int *handle, + unsigned long *current) +{ if (dev->path.type != DEVICE_PATH_PCI) return 0; if (!dev->on_mainboard) return 0; - u8 device_type = smbios_get_device_type_from_dev(dev); + const u8 device_type = smbios_get_device_type_from_dev(dev); - if (device_type == SMBIOS_DEVICE_TYPE_OTHER || - device_type == SMBIOS_DEVICE_TYPE_UNKNOWN) - return 0; + u8 instance_id; - if (device_type > SMBIOS_DEVICE_TYPE_COUNT) + if (!smbios_get_type41_instance_id(dev, device_type, &instance_id)) return 0; - const char *name = get_pci_subclass_name(dev); + const char *name = smbios_get_type41_refdes(dev); return smbios_write_type41(current, handle, name, // name - type41_inst_cnt[device_type]++, // inst + instance_id, // inst 0, // segment dev->bus->secondary, //bus PCI_SLOT(dev->path.pci.devfn), // device diff --git a/src/include/device/device.h b/src/include/device/device.h index 8610e0a4c6..237d836147 100644 --- a/src/include/device/device.h +++ b/src/include/device/device.h @@ -148,6 +148,17 @@ struct device { u8 smbios_slot_data_width; u8 smbios_slot_length; const char *smbios_slot_designation; + +#if CONFIG(SMBIOS_TYPE41_PROVIDED_BY_DEVTREE) + /* + * These fields are intentionally guarded so that attempts to use + * the corresponding devicetree syntax without selecting the Kconfig + * option result in build-time errors. Smaller size is a side effect. + */ + bool smbios_instance_id_valid; + u8 smbios_instance_id; + const char *smbios_refdes; +#endif #endif #endif DEVTREE_CONST void *chip_info; -- cgit v1.2.3