Hi Heinrich, On Thu, 8 May 2025 at 10:27, Heinrich Schuchardt <xypron.g...@gmx.de> wrote: > > Am 8. Mai 2025 16:10:33 MESZ schrieb Raymond Mao <raymond....@linaro.org>: > >Implement SMBIOS Type 9 (System Slot). > >SMBIOS library will look for a subnode "system-slot" under > >"smbios" to construct the data of Type 9. > >[1] is an example for the expected pattern of "system-slot". > > > > > The value of type 9 information comes with the information if a slot occupied. > > I can't see any code determining the actual usage. So what is the point of > this patch? > It loads properties from smbios-sysinfo subnode system-slot if any custom values exist, similarly as what we did for Type 1, 4, 7. If no properties exist under the system-slot subnode, as a fallback the library scans the entire device tree and converts the properties as possible, which is the default approach as I leave the system-slot node empty. Many of the Type 9 properties are vendor-specific so I expect a vendor to fill the system-slot subnode following the example in my commit message, while the fallback can still provide the basic Type 9 information.
Regards, Raymond > Best regards > > Heinrich > > > >If "system-slot" node does not exist, or any of its properties > >are missing, as a fallback, SMBIOS library will try to get the > >values by scanning the device tree. > > > >SMBIOS Type 9 support is under GENERATE_SMBIOS_TABLE_VERBOSE to > >avoid increasing rom size for those platforms which only require > >basic SMBIOS support. > > > >[1] Example of a "system-slot" node which contains two slots: > > system-slot { > > isa { > > socket-design = ""; > > slot-type = <SMBIOS_SYSSLOT_TYPE_ISA>; > > slot-data-bus-width = > > <SMBIOS_SYSSLOT_WIDTH_16BIT>; > > current-usage = <SMBIOS_SYSSLOT_USAGE_NA>; > > slot-length = <SMBIOS_SYSSLOT_LENG_SHORT>; > > slot-id = <0>; > > slot-characteristics-1 = <(SMBIOS_SYSSLOT_CHAR_5V | > > SMBIOS_SYSSLOT_CHAR_3_3V)>; > > slot-characteristics-2 = <SMBIOS_SYSSLOT_CHAR_ASYNCRM>; > > segment-group-number = <0>; > > bus-number = <0x80>; > > device-function-number = <0x10>; > > data-bus-width = <0>; > > peer-grouping-count = <0>; > > slot-information = <0>; > > slot-physical-width = <0>; > > slot-characteristics-1 = <(SMBIOS_SYSSLOT_CHAR_5V | > > SMBIOS_SYSSLOT_CHAR_3_3V)>; > > slot-characteristics-2 = <SMBIOS_SYSSLOT_CHAR_ASYNCRM>; > > segment-group-number = <0>; > > bus-number = <0x80>; > > device-function-number = <0x10>; > > data-bus-width = <0>; > > peer-grouping-count = <0>; > > slot-information = <0>; > > slot-physical-width = <0>; > > slot-pitch = <0>; > > slot-height = <0>; > > }; > > pcmcia { > > socket-design = ""; > > slot-type = <SMBIOS_SYSSLOT_TYPE_PCMCIA>; > > slot-data-bus-width = <SMBIOS_SYSSLOT_WIDTH_32BIT>; > > current-usage = <SMBIOS_SYSSLOT_USAGE_AVAILABLE>; > > slot-length = <SMBIOS_SYSSLOT_LENG_SHORT>; > > slot-id = <1>; > > slot-characteristics-1 = <(SMBIOS_SYSSLOT_CHAR_5V | > > SMBIOS_SYSSLOT_CHAR_3_3V)>; > > slot-characteristics-2 = <SMBIOS_SYSSLOT_CHAR_ASYNCRM>; > > segment-group-number = <1>; > > bus-number = <0xa0>; > > device-function-number = <0x40>; > > data-bus-width = <0>; > > peer-grouping-count = <0>; > > slot-information = <0>; > > slot-physical-width = <0>; > > slot-pitch = <0>; > > slot-height = <0>; > > }; > > }; > > > >Signed-off-by: Raymond Mao <raymond....@linaro.org> > >--- > >Changes in v2: > >- Reuse sysinfo_to_dt and convert_sysinfo_to_dt() for mapping SMBIOS > >properties to DT. > > > > arch/arm/dts/smbios_generic.dtsi | 3 + > > cmd/smbios.c | 114 +++++++++++++ > > include/smbios.h | 45 ++++++ > > include/smbios_def.h | 89 +++++++++++ > > lib/smbios.c | 267 ++++++++++++++++++++++++++++++- > > 5 files changed, 515 insertions(+), 3 deletions(-) > > > >diff --git a/arch/arm/dts/smbios_generic.dtsi > >b/arch/arm/dts/smbios_generic.dtsi > >index fc168317c9e..4463dade217 100644 > >--- a/arch/arm/dts/smbios_generic.dtsi > >+++ b/arch/arm/dts/smbios_generic.dtsi > >@@ -77,6 +77,9 @@ > > SMBIOS_CACHE_OP_WB)>; > > }; > > }; > >+ > >+ system-slot { > >+ }; > > }; > > }; > > }; > >diff --git a/cmd/smbios.c b/cmd/smbios.c > >index 562dd7959be..127e89ca914 100644 > >--- a/cmd/smbios.c > >+++ b/cmd/smbios.c > >@@ -119,6 +119,55 @@ static const struct str_lookup_table > >associativity_strings[] = { > > > > }; > > > >+static const struct str_lookup_table slot_type_strings[] = { > >+ { SMBIOS_SYSSLOT_TYPE_OTHER, "Other" }, > >+ { SMBIOS_SYSSLOT_TYPE_UNKNOWN, "Unknown" }, > >+ { SMBIOS_SYSSLOT_TYPE_ISA, "ISA" }, > >+ { SMBIOS_SYSSLOT_TYPE_PCI, "PCI" }, > >+ { SMBIOS_SYSSLOT_TYPE_PCMCIA, "PC Card (PCMCIA)" }, > >+ { SMBIOS_SYSSLOT_TYPE_PCIE, "PCI Express" }, > >+ { SMBIOS_SYSSLOT_TYPE_PCIEGEN2, "PCI Express Gen 2" }, > >+ { SMBIOS_SYSSLOT_TYPE_PCIEGEN3, "PCI Express Gen 3" }, > >+ { SMBIOS_SYSSLOT_TYPE_PCIEGEN3X16, "PCI Express Gen 3 x16" }, > >+ { SMBIOS_SYSSLOT_TYPE_PCIEGEN4, "PCI Express Gen 4" }, > >+ { SMBIOS_SYSSLOT_TYPE_PCIEGEN4X8, "PCI Express Gen 4 x8" }, > >+ { SMBIOS_SYSSLOT_TYPE_PCIEGEN4X16, "PCI Express Gen 4 x16" }, > >+}; > >+ > >+static const struct str_lookup_table slot_bus_width_strings[] = { > >+ { SMBIOS_SYSSLOT_WIDTH_OTHER, "Other" }, > >+ { SMBIOS_SYSSLOT_WIDTH_UNKNOWN, "Unknown" }, > >+ { SMBIOS_SYSSLOT_WIDTH_8BIT, "8 bit" }, > >+ { SMBIOS_SYSSLOT_WIDTH_16BIT, "16 bit" }, > >+ { SMBIOS_SYSSLOT_WIDTH_32BIT, "32 bit" }, > >+ { SMBIOS_SYSSLOT_WIDTH_64BIT, "64 bit" }, > >+ { SMBIOS_SYSSLOT_WIDTH_128BIT, "128 bit " }, > >+ { SMBIOS_SYSSLOT_WIDTH_1X, "1x or x1" }, > >+ { SMBIOS_SYSSLOT_WIDTH_2X, "2x or x2" }, > >+ { SMBIOS_SYSSLOT_WIDTH_4X, "4x or x4" }, > >+ { SMBIOS_SYSSLOT_WIDTH_8X, "8x or x8" }, > >+ { SMBIOS_SYSSLOT_WIDTH_12X, "12x or x12" }, > >+ { SMBIOS_SYSSLOT_WIDTH_16X, "16x or x16" }, > >+ { SMBIOS_SYSSLOT_WIDTH_32X, "32x or x32" }, > >+}; > >+ > >+static const struct str_lookup_table slot_usage_strings[] = { > >+ { SMBIOS_SYSSLOT_USAGE_OTHER, "Other" }, > >+ { SMBIOS_SYSSLOT_USAGE_UNKNOWN, "Unknown" }, > >+ { SMBIOS_SYSSLOT_USAGE_AVAILABLE, "Available" }, > >+ { SMBIOS_SYSSLOT_USAGE_INUSE, "In use" }, > >+ { SMBIOS_SYSSLOT_USAGE_NA, "Unavailable" }, > >+}; > >+ > >+static const struct str_lookup_table slot_length_strings[] = { > >+ { SMBIOS_SYSSLOT_LENG_OTHER, "Other" }, > >+ { SMBIOS_SYSSLOT_LENG_UNKNOWN, "Unknown" }, > >+ { SMBIOS_SYSSLOT_LENG_SHORT, "Short Length" }, > >+ { SMBIOS_SYSSLOT_LENG_LONG, "Long Length" }, > >+ { SMBIOS_SYSSLOT_LENG_2_5INDRV, "2.5 inch drive form factor" }, > >+ { SMBIOS_SYSSLOT_LENG_3_5INDRV, "3.5 inch drive form factor" }, > >+}; > >+ > > /** > > * smbios_get_string() - get SMBIOS string from table > > * > >@@ -403,6 +452,68 @@ static void smbios_print_type7(struct smbios_type7 > >*table) > > printf("\tInstalled Cache Size 2: 0x%08x\n", table->inst_size2.data); > > } > > > >+static void smbios_print_type9(struct smbios_type9 *table) > >+{ > >+ int i; > >+ u8 *addr = (u8 *)table + > >+ offsetof(struct smbios_type9, slot_information); > >+ > >+ printf("System Slots:\n"); > >+ smbios_print_str("Socket Designation", table, > >+ table->socket_design); > >+ smbios_print_lookup_str(slot_type_strings, > >+ table->slot_type, > >+ ARRAY_SIZE(slot_type_strings), > >+ "Slot Type"); > >+ smbios_print_lookup_str(slot_bus_width_strings, > >+ table->slot_data_bus_width, > >+ ARRAY_SIZE(slot_bus_width_strings), > >+ "Slot Data Bus Width"); > >+ smbios_print_lookup_str(slot_usage_strings, > >+ table->current_usage, > >+ ARRAY_SIZE(slot_usage_strings), > >+ "Current Usage"); > >+ smbios_print_lookup_str(slot_length_strings, > >+ table->slot_length, > >+ ARRAY_SIZE(slot_length_strings), > >+ "Slot Length"); > >+ printf("\tSlot ID: 0x%04x\n", table->slot_id); > >+ printf("\tSlot Characteristics 1: 0x%04x\n", > >+ table->slot_characteristics_1); > >+ printf("\tSlot Characteristics 2: 0x%04x\n", > >+ table->slot_characteristics_2); > >+ printf("\tSegment Group Number (Base): 0x%04x\n", > >+ table->segment_group_number); > >+ printf("\tBus Number (Base): 0x%04x\n", table->bus_number); > >+ printf("\tDevice/Function Number (Base): 0x%04x\n", > >+ table->device_function_number.data); > >+ printf("\tData Bus Width (Base): 0x%04x\n", > >+ table->electrical_bus_width); > >+ printf("\tPeer (S/B/D/F/Width) grouping count: 0x%04x\n", > >+ table->peer_grouping_count); > >+ printf("\tPeer (S/B/D/F/Width) groups:\n"); > >+ for (i = 0; i < table->peer_grouping_count; i++) { > >+ printf("\t\tPeer group[%03d]:\n", i); > >+ if (CONFIG_IS_ENABLED(HEXDUMP)) > >+ print_hex_dump("\t\t", DUMP_PREFIX_OFFSET, 16, 1, > >addr, > >+ SMBIOS_TYPE9_PGROUP_SIZE, false); > >+ addr += SMBIOS_TYPE9_PGROUP_SIZE; > >+ } > >+ printf("\n"); > >+ > >+ /* table->slot_information */ > >+ printf("\tSlot Information: 0x%04x\n", *addr); > >+ /* table->slot_physical_width */ > >+ addr += sizeof(table->slot_information); > >+ printf("\tSlot Physical Width: 0x%04x\n", *addr); > >+ /* table->slot_pitch */ > >+ addr += sizeof(table->slot_physical_width); > >+ printf("\tSlot Pitch: 0x%04x\n", *(u16 *)addr); > >+ /* table->slot_height */ > >+ addr += sizeof(table->slot_pitch); > >+ printf("\tSlot Height: 0x%04x\n", *addr); > >+} > >+ > > static void smbios_print_type127(struct smbios_type127 *table) > > { > > printf("End Of Table\n"); > >@@ -482,6 +593,9 @@ static int do_smbios(struct cmd_tbl *cmdtp, int flag, > >int argc, > > case SMBIOS_CACHE_INFORMATION: > > smbios_print_type7((struct smbios_type7 *)pos); > > break; > >+ case SMBIOS_SYSTEM_SLOTS: > >+ smbios_print_type9((struct smbios_type9 *)pos); > >+ break; > > case SMBIOS_END_OF_TABLE: > > smbios_print_type127((struct smbios_type127 *)pos); > > break; > >diff --git a/include/smbios.h b/include/smbios.h > >index b5fed57aba2..d885285ea41 100644 > >--- a/include/smbios.h > >+++ b/include/smbios.h > >@@ -264,6 +264,51 @@ struct __packed smbios_type7 { > > char eos[SMBIOS_STRUCT_EOS_BYTES]; > > }; > > > >+#define SMBIOS_TYPE9_PGROUP_SIZE 5 > >+ > >+struct pci_attr_lookup_table { > >+ const char *str; > >+ u8 slot_type; > >+ u8 data_bus_width; > >+ u8 slot_length; > >+ u8 chara1; > >+ u8 chara2; > >+}; > >+ > >+union dev_func_num { > >+ struct { > >+ u8 dev_num:5; > >+ u8 func_num:3; > >+ } fields; > >+ u8 data; > >+}; > >+ > >+struct __packed smbios_type9 { > >+ struct smbios_header hdr; > >+ u8 socket_design; > >+ u8 slot_type; > >+ u8 slot_data_bus_width; > >+ u8 current_usage; > >+ u8 slot_length; > >+ u16 slot_id; > >+ u8 slot_characteristics_1; > >+ u8 slot_characteristics_2; > >+ u16 segment_group_number; > >+ u8 bus_number; > >+ union dev_func_num device_function_number; > >+ u8 electrical_bus_width; > >+ u8 peer_grouping_count; > >+ /* > >+ * Dynamic bytes will be inserted here to store peer_groups. > >+ * length is equal to 'peer_grouping_count' * 5 > >+ */ > >+ u8 slot_information; > >+ u8 slot_physical_width; > >+ u16 slot_pitch; > >+ u8 slot_height; > >+ char eos[SMBIOS_STRUCT_EOS_BYTES]; > >+}; > >+ > > struct __packed smbios_type32 { > > u8 type; > > u8 length; > >diff --git a/include/smbios_def.h b/include/smbios_def.h > >index 81c5781217f..ef9cb02ed25 100644 > >--- a/include/smbios_def.h > >+++ b/include/smbios_def.h > >@@ -191,4 +191,93 @@ > > #define SMBIOS_CACHE_ASSOC_64WAY 13 > > #define SMBIOS_CACHE_ASSOC_20WAY 14 > > > >+/* > >+ * System Slot > >+ */ > >+ > >+/* Slot Type */ > >+#define SMBIOS_SYSSLOT_TYPE_OTHER 1 > >+#define SMBIOS_SYSSLOT_TYPE_UNKNOWN 2 > >+#define SMBIOS_SYSSLOT_TYPE_ISA 3 /* ISA */ > >+#define SMBIOS_SYSSLOT_TYPE_PCI 6 /* PCI */ > >+#define SMBIOS_SYSSLOT_TYPE_PCMCIA 7 /* PCMCIA */ > >+#define SMBIOS_SYSSLOT_TYPE_PCIE 0xa5 /* PCI Express */ > >+#define SMBIOS_SYSSLOT_TYPE_PCIEX1 0xa6 /* PCI Express x1 */ > >+#define SMBIOS_SYSSLOT_TYPE_PCIEX2 0xa7 /* PCI Express x2 */ > >+#define SMBIOS_SYSSLOT_TYPE_PCIEX4 0xa8 /* PCI Express x4 */ > >+#define SMBIOS_SYSSLOT_TYPE_PCIEX8 0xa9 /* PCI Express x8 */ > >+#define SMBIOS_SYSSLOT_TYPE_PCIEX16 0xaa /* PCI Express x16 */ > >+#define SMBIOS_SYSSLOT_TYPE_PCIEGEN2 0xab /* PCI Express Gen 2 */ > >+#define SMBIOS_SYSSLOT_TYPE_PCIEGEN2X1 0xac /* PCI Express Gen 2 > >x1 */ > >+#define SMBIOS_SYSSLOT_TYPE_PCIEGEN2X2 0xad /* PCI Express Gen 2 > >x2 */ > >+#define SMBIOS_SYSSLOT_TYPE_PCIEGEN2X4 0xae /* PCI Express Gen 2 > >x4 */ > >+#define SMBIOS_SYSSLOT_TYPE_PCIEGEN2X8 0xaf /* PCI Express Gen 2 > >x8 */ > >+#define SMBIOS_SYSSLOT_TYPE_PCIEGEN2X16 0xb0 /* PCI Express Gen 2 > >x16 */ > >+#define SMBIOS_SYSSLOT_TYPE_PCIEGEN3 0xb1 /* PCI Express Gen 3 */ > >+#define SMBIOS_SYSSLOT_TYPE_PCIEGEN3X1 0xb2 /* PCI Express Gen 3 > >x1 */ > >+#define SMBIOS_SYSSLOT_TYPE_PCIEGEN3X2 0xb3 /* PCI Express Gen 3 > >x2 */ > >+#define SMBIOS_SYSSLOT_TYPE_PCIEGEN3X4 0xb4 /* PCI Express Gen 3 > >x4 */ > >+#define SMBIOS_SYSSLOT_TYPE_PCIEGEN3X8 0xb5 /* PCI Express Gen 3 > >x8 */ > >+#define SMBIOS_SYSSLOT_TYPE_PCIEGEN3X16 0xb6 /* PCI Express Gen 3 > >x16 */ > >+#define SMBIOS_SYSSLOT_TYPE_PCIEGEN4 0xb8 /* PCI Express Gen 4 */ > >+#define SMBIOS_SYSSLOT_TYPE_PCIEGEN4X1 0xb9 /* PCI Express Gen 4 > >x1 */ > >+#define SMBIOS_SYSSLOT_TYPE_PCIEGEN4X2 0xba /* PCI Express Gen 4 > >x2 */ > >+#define SMBIOS_SYSSLOT_TYPE_PCIEGEN4X4 0xbb /* PCI Express Gen 4 > >x4 */ > >+#define SMBIOS_SYSSLOT_TYPE_PCIEGEN4X8 0xbc /* PCI Express Gen 4 > >x8 */ > >+#define SMBIOS_SYSSLOT_TYPE_PCIEGEN4X16 0xbd /* PCI Express Gen 4 > >x16 */ > >+ > >+/* Slot Data Bus Width */ > >+#define SMBIOS_SYSSLOT_WIDTH_OTHER 1 > >+#define SMBIOS_SYSSLOT_WIDTH_UNKNOWN 2 > >+#define SMBIOS_SYSSLOT_WIDTH_8BIT 3 > >+#define SMBIOS_SYSSLOT_WIDTH_16BIT 4 > >+#define SMBIOS_SYSSLOT_WIDTH_32BIT 5 > >+#define SMBIOS_SYSSLOT_WIDTH_64BIT 6 > >+#define SMBIOS_SYSSLOT_WIDTH_128BIT 7 > >+#define SMBIOS_SYSSLOT_WIDTH_1X 8 > >+#define SMBIOS_SYSSLOT_WIDTH_2X 9 > >+#define SMBIOS_SYSSLOT_WIDTH_4X 10 > >+#define SMBIOS_SYSSLOT_WIDTH_8X 11 > >+#define SMBIOS_SYSSLOT_WIDTH_12X 12 > >+#define SMBIOS_SYSSLOT_WIDTH_16X 13 > >+#define SMBIOS_SYSSLOT_WIDTH_32X 14 > >+ > >+/* Current Usage */ > >+#define SMBIOS_SYSSLOT_USAGE_OTHER 1 > >+#define SMBIOS_SYSSLOT_USAGE_UNKNOWN 2 > >+#define SMBIOS_SYSSLOT_USAGE_AVAILABLE 3 > >+#define SMBIOS_SYSSLOT_USAGE_INUSE 4 > >+#define SMBIOS_SYSSLOT_USAGE_NA 5 > >+ > >+/* Slot Length */ > >+#define SMBIOS_SYSSLOT_LENG_OTHER 1 > >+#define SMBIOS_SYSSLOT_LENG_UNKNOWN 2 > >+#define SMBIOS_SYSSLOT_LENG_SHORT 3 > >+#define SMBIOS_SYSSLOT_LENG_LONG 4 > >+#define SMBIOS_SYSSLOT_LENG_2_5INDRV 5 > >+#define SMBIOS_SYSSLOT_LENG_3_5INDRV 6 > >+ > >+/* Slot Characteristics 1 */ > >+#define SMBIOS_SYSSLOT_CHAR_UND 1 /* BIT(0) */ > >+#define SMBIOS_SYSSLOT_CHAR_5V 2 /* BIT(1) */ > >+#define SMBIOS_SYSSLOT_CHAR_3_3V 4 /* BIT(2) */ > >+#define SMBIOS_SYSSLOT_CHAR_SHARED 8 /* BIT(3) */ > >+#define SMBIOS_SYSSLOT_CHAR_PCCARD16 16 /* BIT(4) */ > >+#define SMBIOS_SYSSLOT_CHAR_PCCARDBUS 32 /* BIT(5) */ > >+#define SMBIOS_SYSSLOT_CHAR_PCCARDZV 64 /* BIT(6) */ > >+#define SMBIOS_SYSSLOT_CHAR_PCCARDMRR 0x80 /* BIT(7) */ > >+ > >+/* Slot Characteristics 2 */ > >+#define SMBIOS_SYSSLOT_CHAR_PCIPME 1 /* BIT(0) */ > >+#define SMBIOS_SYSSLOT_CHAR_HOTPLUG 2 /* BIT(1) */ > >+#define SMBIOS_SYSSLOT_CHAR_PCISMB 4 /* BIT(2) */ > >+#define SMBIOS_SYSSLOT_CHAR_PCIBIF 8 /* BIT(3) */ > >+#define SMBIOS_SYSSLOT_CHAR_ASYNCRM 16 /* BIT(4) */ > >+#define SMBIOS_SYSSLOT_CHAR_FBCXL1 32 /* BIT(5) */ > >+#define SMBIOS_SYSSLOT_CHAR_FBCXL2 64 /* BIT(6) */ > >+#define SMBIOS_SYSSLOT_CHAR_FBCXL3 0x80 /* BIT(7) */ > >+ > >+/* Slot segment group number */ > >+#define SMBIOS_SYSSLOT_SGGNUM_UND 0 > >+ > > #endif /* _SMBIOS_DEF_H_ */ > >diff --git a/lib/smbios.c b/lib/smbios.c > >index 7c9701a57f9..55350d00067 100644 > >--- a/lib/smbios.c > >+++ b/lib/smbios.c > >@@ -66,11 +66,47 @@ struct map_sysinfo { > > > > static const struct map_sysinfo sysinfo_to_dt[] = { > > { .si_node = "system", .si_str = "product", .dt_str = "model", 2 }, > >- { .si_node = "system", .si_str = "manufacturer", .dt_str = > >"compatible", 1 }, > >- { .si_node = "baseboard", .si_str = "product", .dt_str = "model", 2 }, > >- { .si_node = "baseboard", .si_str = "manufacturer", .dt_str = > >"compatible", 1 }, > >+ { .si_node = "system", .si_str = "manufacturer", > >+ .dt_str = "compatible", 1 }, > >+ { .si_node = "baseboard", .si_str = "product", > >+ .dt_str = "model", 2 }, > >+ { .si_node = "baseboard", .si_str = "manufacturer", > >+ .dt_str = "compatible", 1 }, > >+ { .si_node = "system-slot", .si_str = "slot-type", > >+ .dt_str = "device_type", 0}, > >+ { .si_node = "system-slot", .si_str = "segment-group-number", > >+ .dt_str = "linux,pci-domain", 0}, > > }; > > > >+#if IS_ENABLED(CONFIG_GENERATE_SMBIOS_TABLE_VERBOSE) > >+static const struct pci_attr_lookup_table pci_attr[] = { > >+ { "pci-host-ecam-generic", SMBIOS_SYSSLOT_TYPE_PCIE, > >+ SMBIOS_SYSSLOT_WIDTH_8X, SMBIOS_SYSSLOT_LENG_LONG, > >+ SMBIOS_SYSSLOT_CHAR_3_3V, SMBIOS_SYSSLOT_CHAR_PCIPME }, > >+ { "pci-host-cam-generic", SMBIOS_SYSSLOT_TYPE_PCI, > >+ SMBIOS_SYSSLOT_WIDTH_32BIT, SMBIOS_SYSSLOT_LENG_SHORT, > >+ SMBIOS_SYSSLOT_CHAR_5V | SMBIOS_SYSSLOT_CHAR_3_3V, > >+ SMBIOS_SYSSLOT_CHAR_PCIPME }, > >+ { "pci-host-thunder-ecam", SMBIOS_SYSSLOT_TYPE_PCIEGEN3, > >+ SMBIOS_SYSSLOT_WIDTH_8X, SMBIOS_SYSSLOT_LENG_LONG, > >+ SMBIOS_SYSSLOT_CHAR_3_3V, > >+ SMBIOS_SYSSLOT_CHAR_PCIPME | SMBIOS_SYSSLOT_CHAR_HOTPLUG }, > >+ { "pci-host-octeontx-ecam", SMBIOS_SYSSLOT_TYPE_PCIEGEN3X16, > >+ SMBIOS_SYSSLOT_WIDTH_16X, SMBIOS_SYSSLOT_LENG_LONG, > >+ SMBIOS_SYSSLOT_CHAR_3_3V, > >+ SMBIOS_SYSSLOT_CHAR_PCIPME | SMBIOS_SYSSLOT_CHAR_HOTPLUG }, > >+ { "pci-host-thunder-pem", SMBIOS_SYSSLOT_TYPE_PCIEGEN4X8, > >+ SMBIOS_SYSSLOT_WIDTH_8X, SMBIOS_SYSSLOT_LENG_LONG, > >+ SMBIOS_SYSSLOT_CHAR_3_3V, > >+ SMBIOS_SYSSLOT_CHAR_PCIPME | SMBIOS_SYSSLOT_CHAR_HOTPLUG }, > >+ { "pci-host-octeontx2-pem", SMBIOS_SYSSLOT_TYPE_PCIEGEN4X16, > >+ SMBIOS_SYSSLOT_WIDTH_16X, SMBIOS_SYSSLOT_LENG_LONG, > >+ SMBIOS_SYSSLOT_CHAR_3_3V, > >+ SMBIOS_SYSSLOT_CHAR_PCIPME | SMBIOS_SYSSLOT_CHAR_HOTPLUG | > >+ SMBIOS_SYSSLOT_CHAR_PCIBIF }, > >+}; > >+#endif > >+ > > /** > > * struct smbios_ctx - context for writing SMBIOS tables > > * > >@@ -222,6 +258,7 @@ static int smbios_get_val_si(struct smbios_ctx * > >__maybe_unused ctx, > > { > > #if IS_ENABLED(CONFIG_GENERATE_SMBIOS_TABLE_VERBOSE) > > int val; > >+ const struct map_sysinfo *nprop; > > > > if (!ctx->dev) > > return val_def; > >@@ -240,6 +277,11 @@ static int smbios_get_val_si(struct smbios_ctx * > >__maybe_unused ctx, > > */ > > if (!ofnode_read_u32(ofnode_root(), prop, &val)) > > return val; > >+ > >+ /* If the node is still missing, try with the mapping values */ > >+ nprop = convert_sysinfo_to_dt(ctx->subnode_name, prop); > >+ if (!ofnode_read_u32(ofnode_root(), nprop->dt_str, &val)) > >+ return val; > > #endif > > return val_def; > > } > >@@ -856,6 +898,222 @@ static int smbios_write_type7(ulong *current, int > >handle, > > return len; > > } > > > >+static void smbios_lookup_pci_attr(struct smbios_ctx *ctx, > >+ struct smbios_type9 *t) > >+{ > >+ const char *compatible; > >+ u32 addr_cells, size_cells, total_cells; > >+ const fdt32_t *reg; > >+ int reglen; > >+ int i; > >+ > >+ /* default attributes */ > >+ t->slot_type = SMBIOS_SYSSLOT_TYPE_PCI; > >+ t->slot_data_bus_width = SMBIOS_SYSSLOT_WIDTH_UNKNOWN; > >+ t->slot_characteristics_1 = SMBIOS_SYSSLOT_CHAR_UND; > >+ t->current_usage = SMBIOS_SYSSLOT_USAGE_UNKNOWN; > >+ t->slot_length = SMBIOS_SYSSLOT_LENG_UNKNOWN; > >+ t->segment_group_number = smbios_get_val_si(ctx, > >"segment-group-number", > >+ SYSID_NONE, > >+ > >SMBIOS_SYSSLOT_SGGNUM_UND); > >+ > >+ /* > >+ * Get #address-cells and #size-cells dynamically > >+ * Default 3 for #address-cells and 2 for #size-cells > >+ */ > >+ addr_cells = ofnode_read_u32_default(ctx->node, "#address-cells", 3); > >+ size_cells = ofnode_read_u32_default(ctx->node, "#size-cells", 2); > >+ total_cells = addr_cells + size_cells; > >+ > >+ /* Read property 'reg' from the node */ > >+ reg = ofnode_read_prop(ctx->node, "reg", ®len); > >+ if (reg && reglen > addr_cells * sizeof(*reg)) { > >+ /* First address-cell: Bus Number */ > >+ if (addr_cells >= 1) > >+ t->bus_number = fdt32_to_cpu(reg[0]); > >+ /* Second address-cell: Device/Function */ > >+ if (addr_cells >= 2) > >+ t->device_function_number.data = fdt32_to_cpu(reg[1]); > >+ /* > >+ * Third address-cell 'Register Offset' and the following > >+ * size-cell bytes are not useful for SMBIOS type 9, just > >+ * ignore them. > >+ */ > >+ /* > >+ * As neither PCI IRQ Routing Table ($PIRQ) nor FDT > >+ * property to represent a Slot ID, try to derive a > >+ * Slot ID programmatically. > >+ */ > >+ t->slot_id = t->device_function_number.fields.dev_num | > >+ (t->bus_number << 5); > >+ } > >+ > >+ /* Read 'compatible' property */ > >+ compatible = ofnode_read_string(ctx->node, "compatible"); > >+ if (!compatible) > >+ return; > >+ > >+ for (i = 0; i < ARRAY_SIZE(pci_attr); i++) { > >+ if (strstr(compatible, pci_attr[i].str)) { > >+ t->slot_type = pci_attr[i].slot_type; > >+ t->slot_data_bus_width = pci_attr[i].data_bus_width; > >+ t->slot_length = pci_attr[i].slot_length; > >+ t->slot_characteristics_1 = pci_attr[i].chara1; > >+ t->slot_characteristics_2 = pci_attr[i].chara2; > >+ /* mark it as in-use arbitrarily */ > >+ t->current_usage = SMBIOS_SYSSLOT_USAGE_INUSE; > >+ return; > >+ } > >+ } > >+} > >+ > >+static void smbios_write_type9_fields(struct smbios_ctx *ctx, > >+ struct smbios_type9 *t) > >+{ > >+ t->slot_type = smbios_get_val_si(ctx, "slot-type", SYSID_NONE, > >+ SMBIOS_SYSSLOT_TYPE_UNKNOWN); > >+ t->slot_data_bus_width = > >+ smbios_get_val_si(ctx, "data-bus-width", > >+ SYSID_NONE, SMBIOS_SYSSLOT_WIDTH_UNKNOWN); > >+ t->current_usage = smbios_get_val_si(ctx, "current-usage", SYSID_NONE, > >+ SMBIOS_SYSSLOT_USAGE_UNKNOWN); > >+ t->slot_length = smbios_get_val_si(ctx, "slot-length", SYSID_NONE, > >+ SMBIOS_SYSSLOT_LENG_UNKNOWN); > >+ t->slot_id = smbios_get_val_si(ctx, "slot-id", SYSID_NONE, 0); > >+ t->slot_characteristics_1 = > >+ smbios_get_val_si(ctx, "slot-characteristics-1", SYSID_NONE, > >+ SMBIOS_SYSSLOT_CHAR_UND); > >+ t->slot_characteristics_2 = smbios_get_val_si(ctx, > >+ > >"slot-characteristics-2", > >+ SYSID_NONE, 0); > >+ t->segment_group_number = smbios_get_val_si(ctx, > >"segment-group-number", > >+ SYSID_NONE, 0); > >+ t->bus_number = smbios_get_val_si(ctx, "bus-number", SYSID_NONE, 0); > >+ t->device_function_number.data = > >+ smbios_get_val_si(ctx, "device-function-number", SYSID_NONE, > >0); > >+} > >+ > >+static int smbios_write_type9_1slot(ulong *current, int handle, > >+ struct smbios_ctx *ctx, u8 devtype) > >+{ > >+ struct smbios_type9 *t; > >+ int len = sizeof(*t); > >+ u8 pgroups_cnt; > >+ u8 *eos_addr; > >+ size_t pgroups_size; > >+ void *wp; > >+ > >+ pgroups_cnt = smbios_get_val_si(ctx, "peer-grouping-count", > >+ SYSID_NONE, 0); > >+ pgroups_size = pgroups_cnt * SMBIOS_TYPE9_PGROUP_SIZE; > >+ > >+ /* > >+ * reserve the space for the dynamic bytes of peer_groups. > >+ * TODO: > >+ * peer_groups = <peer_grouping_count> * SMBIOS_TYPE9_PGROUP_SIZE > >+ */ > >+ len += pgroups_size; > >+ > >+ t = map_sysmem(*current, len); > >+ memset(t, 0, len); > >+ > >+ fill_smbios_header(t, SMBIOS_SYSTEM_SLOTS, len, handle); > >+ > >+ /* eos is at the end of the structure */ > >+ eos_addr = (u8 *)t + len - sizeof(t->eos); > >+ smbios_set_eos(ctx, eos_addr); > >+ > >+ /* Write the general fields */ > >+ t->peer_grouping_count = pgroups_cnt; > >+ t->socket_design = smbios_add_prop_si(ctx, "socket-design", > >SYSID_NONE, > >+ NULL); > >+ t->electrical_bus_width = smbios_get_val_si(ctx, "data-bus-width", > >+ SYSID_NONE, 0); > >+ > >+ /* skip the reserved peer groups and write the following fields from > >eos */ > >+ /* t->slot_height */ > >+ wp = eos_addr - sizeof(t->slot_height); > >+ *((u8 *)wp) = smbios_get_val_si(ctx, "slot-height", SYSID_NONE, 0); > >+ /* t->slot_pitch */ > >+ wp -= sizeof(t->slot_pitch); > >+ *((u16 *)wp) = smbios_get_val_si(ctx, "slot-pitch", SYSID_NONE, 0); > >+ /* t->slot_physical_width */ > >+ wp -= sizeof(t->slot_physical_width); > >+ *((u8 *)wp) = smbios_get_val_si(ctx, "slot-physical-width", > >SYSID_NONE, 0); > >+ /* t->slot_information */ > >+ wp -= sizeof(t->slot_information); > >+ *((u8 *)wp) = smbios_get_val_si(ctx, "slot-information", SYSID_NONE, > >0); > >+ > >+ /* For PCI, some fields can be extracted from FDT node */ > >+ if (devtype == SMBIOS_SYSSLOT_TYPE_PCI) > >+ /* Populate PCI attributes from existing PCI properties */ > >+ smbios_lookup_pci_attr(ctx, t); > >+ else if (devtype == SMBIOS_SYSSLOT_TYPE_UNKNOWN) { > >+ /* Properties that expected in smbios subnode 'system-slot' */ > >+ smbios_write_type9_fields(ctx, t); > >+ } > >+ len = t->hdr.length + smbios_string_table_len(ctx); > >+ *current += len; > >+ unmap_sysmem(t); > >+ > >+ return len; > >+} > >+ > >+static int smbios_write_type9(ulong *current, int handle, > >+ struct smbios_ctx *ctx) > >+{ > >+ int len = 0; > >+ struct smbios_ctx ctx_bak; > >+ ofnode child; > >+ const struct map_sysinfo *prop; > >+ > >+ /* TODO: Get system slot information via pci subsystem */ > >+ if (!IS_ENABLED(CONFIG_OF_CONTROL)) > >+ return 0; /* Error, return 0-length */ > >+ > >+ memcpy(&ctx_bak, ctx, sizeof(ctx_bak)); > >+ > >+ /* write the properties if any subnode exists under 'system-slot' */ > >+ for (child = ofnode_first_subnode(ctx->node); ofnode_valid(child); > >+ child = ofnode_next_subnode(child)) { > >+ ctx->node = child; > >+ len += smbios_write_type9_1slot(current, handle++, ctx, > >+ SMBIOS_SYSSLOT_TYPE_UNKNOWN); > >+ memcpy(ctx, &ctx_bak, sizeof(*ctx)); > >+ } > >+ > >+ if (len) > >+ return len; > >+ > >+ /* if no subnode of 'system-slot', try scan the entire FDT */ > >+ prop = convert_sysinfo_to_dt(ctx->subnode_name, "slot-type"); > >+ for (child = ofnode_first_subnode(ofnode_root()); ofnode_valid(child); > >+ child = ofnode_next_subnode(child)) { > >+ const char *dev_type_str; > >+ u8 dev_type = SMBIOS_SYSSLOT_TYPE_UNKNOWN; > >+ > >+ dev_type_str = ofnode_read_string(child, prop->dt_str); > >+ if (!dev_type_str) > >+ continue; > >+ > >+ if (!strcmp(dev_type_str, "pci")) > >+ dev_type = SMBIOS_SYSSLOT_TYPE_PCI; > >+ else if (!strcmp(dev_type_str, "isa")) > >+ dev_type = SMBIOS_SYSSLOT_TYPE_ISA; > >+ else if (!strcmp(dev_type_str, "pcmcia")) > >+ dev_type = SMBIOS_SYSSLOT_TYPE_PCMCIA; > >+ else > >+ continue; > >+ > >+ ctx->node = child; > >+ len += smbios_write_type9_1slot(current, handle++, ctx, > >+ dev_type); > >+ memcpy(ctx, &ctx_bak, sizeof(*ctx)); > >+ } > >+ > >+ return len; > >+} > >+ > > #endif /* #if IS_ENABLED(CONFIG_GENERATE_SMBIOS_TABLE_VERBOSE) */ > > > > static int smbios_write_type32(ulong *current, int handle, > >@@ -902,6 +1160,9 @@ static struct smbios_write_method smbios_write_funcs[] > >= { > > { smbios_write_type7, "cache", }, > > #endif > > { smbios_write_type4, "processor"}, > >+#if IS_ENABLED(CONFIG_GENERATE_SMBIOS_TABLE_VERBOSE) > >+ { smbios_write_type9, "system-slot"}, > >+#endif > > { smbios_write_type32, }, > > { smbios_write_type127 }, > > }; >