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 <th3fanbus@gmail.com>
Reviewed-on: https://review.coreboot.org/c/coreboot/+/57370
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Tim Wawrzynczak <twawrzynczak@chromium.org>
Reviewed-by: Nico Huber <nico.h@gmx.de>
diff --git a/util/sconfig/main.c b/util/sconfig/main.c
index 685da9d..1de98d4 100644
--- a/util/sconfig/main.c
+++ b/util/sconfig/main.c
@@ -1023,6 +1023,25 @@
 	dev->smbios_slot_designation = designation;
 }
 
+void add_smbios_dev_info(struct bus *bus, long instance_id, const char *refdes)
+{
+	struct device *dev = bus->dev;
+
+	if (dev->bustype != PCI && dev->bustype != DOMAIN) {
+		printf("ERROR: 'dev_info' only allowed for PCI devices\n");
+		exit(1);
+	}
+
+	if (instance_id < 0 || instance_id > UINT8_MAX) {
+		printf("ERROR: SMBIOS dev info instance ID '%ld' out of range\n", instance_id);
+		exit(1);
+	}
+
+	dev->smbios_instance_id_valid = 1;
+	dev->smbios_instance_id = (unsigned int)instance_id;
+	dev->smbios_refdes = refdes;
+}
+
 void add_pci_subsystem_ids(struct bus *bus, int vendor, int device,
 			   int inherit)
 {
@@ -1135,6 +1154,14 @@
 		fprintf(fil, "\t.smbios_slot_length = %s,\n",
 			ptr->smbios_slot_length);
 
+	/* Fill in SMBIOS type41 fields */
+	if (ptr->smbios_instance_id_valid) {
+		fprintf(fil, "\t.smbios_instance_id_valid = true,\n");
+		fprintf(fil, "\t.smbios_instance_id = %u,\n", ptr->smbios_instance_id);
+		if (ptr->smbios_refdes)
+			fprintf(fil, "\t.smbios_refdes = \"%s\",\n", ptr->smbios_refdes);
+	}
+
 	fprintf(fil, "#endif\n");
 	fprintf(fil, "#endif\n");
 }