SMBIOS: Allow skipping default SMBIOS generation

The call to the `get_smbios_data` device operation is followed by
calls to unconditional default functions, which lacks flexibility.
Instead, have devices that implement `get_smbios_data` call these
default functions as needed.

Most `get_smbios_data` implementations are in mainboard code, and are
bound to the root device. The default functions only operate with PCI
devices because of the `dev->path.type != DEVICE_PATH_PCI` checks, so
calling these functions for non-PCI devices is unnecessary. QEMU also
implements `get_smbios_data` but binds it to the domain device, which
isn't PCI either.

Change-Id: Iefbf072b1203d04a98c9d26a30f22cfebe769eb4
Signed-off-by: Angel Pons <th3fanbus@gmail.com>
Reviewed-on: https://review.coreboot.org/c/coreboot/+/57366
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Nico Huber <nico.h@gmx.de>
Reviewed-by: Tim Wawrzynczak <twawrzynczak@chromium.org>
Reviewed-by: Felix Held <felix-coreboot@felixheld.de>
diff --git a/src/arch/x86/smbios.c b/src/arch/x86/smbios.c
index eebfd72..967883a 100644
--- a/src/arch/x86/smbios.c
+++ b/src/arch/x86/smbios.c
@@ -1213,6 +1213,16 @@
 				  dev->path.pci.devfn);
 }
 
+int get_smbios_data(struct device *dev, int *handle, unsigned long *current)
+{
+	int len = 0;
+
+	len += smbios_generate_type9_from_devtree(dev, handle, current);
+	len += smbios_generate_type41_from_devtree(dev, handle, current);
+
+	return len;
+}
+
 static int smbios_walk_device_tree(struct device *tree, int *handle, unsigned long *current)
 {
 	struct device *dev;
@@ -1222,9 +1232,9 @@
 		if (dev->enabled && dev->ops && dev->ops->get_smbios_data) {
 			printk(BIOS_INFO, "%s (%s)\n", dev_path(dev), dev_name(dev));
 			len += dev->ops->get_smbios_data(dev, handle, current);
+		} else {
+			len += get_smbios_data(dev, handle, current);
 		}
-		len += smbios_generate_type9_from_devtree(dev, handle, current);
-		len += smbios_generate_type41_from_devtree(dev, handle, current);
 	}
 	return len;
 }
diff --git a/src/drivers/ipmi/ipmi_kcs_ops.c b/src/drivers/ipmi/ipmi_kcs_ops.c
index 9d1cac8..ff18766 100644
--- a/src/drivers/ipmi/ipmi_kcs_ops.c
+++ b/src/drivers/ipmi/ipmi_kcs_ops.c
@@ -386,6 +386,8 @@
 		register_spacing,
 		0); // no IRQ
 
+	len += get_smbios_data(dev, handle, current);
+
 	return len;
 }
 #endif
diff --git a/src/drivers/wifi/generic/smbios.c b/src/drivers/wifi/generic/smbios.c
index 793349d..db22de9 100644
--- a/src/drivers/wifi/generic/smbios.c
+++ b/src/drivers/wifi/generic/smbios.c
@@ -9,6 +9,9 @@
 
 static int smbios_write_intel_wifi(struct device *dev, int *handle, unsigned long *current)
 {
+	if (dev->vendor != PCI_VENDOR_ID_INTEL)
+		return 0;
+
 	struct smbios_type_intel_wifi {
 		struct smbios_header header;
 		u8 str;
@@ -29,10 +32,9 @@
 
 int smbios_write_wifi_pcie(struct device *dev, int *handle, unsigned long *current)
 {
-	if (dev->vendor == PCI_VENDOR_ID_INTEL)
-		return smbios_write_intel_wifi(dev, handle, current);
-
-	return 0;
+	int len = smbios_write_intel_wifi(dev, handle, current);
+	len += get_smbios_data(dev, handle, current);
+	return len;
 }
 
 int smbios_write_wifi_cnvi(struct device *dev, int *handle, unsigned long *current)
diff --git a/src/include/smbios.h b/src/include/smbios.h
index 0f1386a..0b24c15 100644
--- a/src/include/smbios.h
+++ b/src/include/smbios.h
@@ -35,6 +35,9 @@
 			const char *name, u8 instance, u16 segment,
 			u8 bus, u8 device, u8 function, u8 device_type);
 
+struct device;
+int get_smbios_data(struct device *dev, int *handle, unsigned long *current);
+
 const char *smbios_system_manufacturer(void);
 const char *smbios_system_product_name(void);
 const char *smbios_system_serial_number(void);