diff options
Diffstat (limited to 'src/arch/x86/smbios.c')
-rw-r--r-- | src/arch/x86/smbios.c | 71 |
1 files changed, 71 insertions, 0 deletions
diff --git a/src/arch/x86/smbios.c b/src/arch/x86/smbios.c index 310a870da6..bf627f280f 100644 --- a/src/arch/x86/smbios.c +++ b/src/arch/x86/smbios.c @@ -30,6 +30,9 @@ #include <memory_info.h> #include <spd.h> #include <cbmem.h> +#include <device/pci_ids.h> +#include <device/pci_def.h> +#include <device/pci.h> #if CONFIG(CHROMEOS) #include <vendorcode/google/chromeos/gnvs.h> #endif @@ -50,6 +53,41 @@ static u8 smbios_checksum(u8 *p, u32 length) return -ret; } +/* Get the device type 41 from the dev struct */ +static u8 smbios_get_device_type_from_dev(struct device *dev) +{ + u16 pci_basesubclass = (dev->class >> 8) & 0xFFFF; + + switch (pci_basesubclass) { + case PCI_CLASS_NOT_DEFINED: + return SMBIOS_DEVICE_TYPE_OTHER; + case PCI_CLASS_DISPLAY_VGA: + case PCI_CLASS_DISPLAY_XGA: + case PCI_CLASS_DISPLAY_3D: + case PCI_CLASS_DISPLAY_OTHER: + return SMBIOS_DEVICE_TYPE_VIDEO; + case PCI_CLASS_STORAGE_SCSI: + return SMBIOS_DEVICE_TYPE_SCSI; + case PCI_CLASS_NETWORK_ETHERNET: + return SMBIOS_DEVICE_TYPE_ETHERNET; + case PCI_CLASS_NETWORK_TOKEN_RING: + return SMBIOS_DEVICE_TYPE_TOKEN_RING; + case PCI_CLASS_MULTIMEDIA_VIDEO: + case PCI_CLASS_MULTIMEDIA_AUDIO: + case PCI_CLASS_MULTIMEDIA_PHONE: + case PCI_CLASS_MULTIMEDIA_OTHER: + return SMBIOS_DEVICE_TYPE_SOUND; + case PCI_CLASS_STORAGE_ATA: + return SMBIOS_DEVICE_TYPE_PATA; + case PCI_CLASS_STORAGE_SATA: + return SMBIOS_DEVICE_TYPE_SATA; + case PCI_CLASS_STORAGE_SAS: + return SMBIOS_DEVICE_TYPE_SAS; + default: + return SMBIOS_DEVICE_TYPE_UNKNOWN; + } +} + int smbios_add_string(u8 *start, const char *str) { @@ -999,6 +1037,38 @@ static int smbios_write_type127(unsigned long *current, int handle) return len; } +/* Generate Type41 entries from devicetree */ +static int smbios_walk_device_tree_type41(struct device *dev, int *handle, + unsigned long *current) +{ + static u8 type41_inst_cnt[SMBIOS_DEVICE_TYPE_COUNT + 1] = {}; + + 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); + + if (device_type == SMBIOS_DEVICE_TYPE_OTHER || + device_type == SMBIOS_DEVICE_TYPE_UNKNOWN) + return 0; + + if (device_type > SMBIOS_DEVICE_TYPE_COUNT) + return 0; + + const char *name = get_pci_subclass_name(dev); + + return smbios_write_type41(current, handle, + name, // name + type41_inst_cnt[device_type]++, // inst + 0, // segment + dev->bus->secondary, //bus + PCI_SLOT(dev->path.pci.devfn), // device + PCI_FUNC(dev->path.pci.devfn), // func + device_type); +} + /* Generate Type9 entries from devicetree */ static int smbios_walk_device_tree_type9(struct device *dev, int *handle, unsigned long *current) @@ -1062,6 +1132,7 @@ static int smbios_walk_device_tree(struct device *tree, int *handle, len += dev->ops->get_smbios_data(dev, handle, current); } len += smbios_walk_device_tree_type9(dev, handle, current); + len += smbios_walk_device_tree_type41(dev, handle, current); } return len; } |