[PATCH v2] smbios: add support for type 9 system slot
Heinrich Schuchardt
xypron.glpk at gmx.de
Thu May 8 16:27:21 CEST 2025
Am 8. Mai 2025 16:10:33 MESZ schrieb Raymond Mao <raymond.mao at 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?
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.mao at 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 },
> };
More information about the U-Boot
mailing list