diff --git a/arch/arm/dts/smbios_generic.dtsi b/arch/arm/dts/smbios_generic.dtsi index fc168317c9e..fe16037fc20 100644 --- a/arch/arm/dts/smbios_generic.dtsi +++ b/arch/arm/dts/smbios_generic.dtsi @@ -77,6 +77,18 @@ SMBIOS_CACHE_OP_WB)>; }; }; + + system-slot { + }; + + memory-array { + }; + + memory-device { + }; + + memory-array-mapped-address { + }; }; }; }; diff --git a/cmd/smbios.c b/cmd/smbios.c index ed419f19028..3fafa46d0a5 100644 --- a/cmd/smbios.c +++ b/cmd/smbios.c @@ -119,6 +119,149 @@ 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" }, +}; + +static const struct str_lookup_table ma_location_strings[] = { + { SMBIOS_MA_LOCATION_OTHER, "Other" }, + { SMBIOS_MA_LOCATION_UNKNOWN, "Unknown" }, + { SMBIOS_MA_LOCATION_MOTHERBOARD, "System board or motherboard" }, +}; + +static const struct str_lookup_table ma_use_strings[] = { + { SMBIOS_MA_USE_OTHER, "Other" }, + { SMBIOS_MA_USE_UNKNOWN, "Unknown" }, + { SMBIOS_MA_USE_SYSTEM, "System memory" }, + { SMBIOS_MA_USE_VIDEO, "Video memory" }, + { SMBIOS_MA_USE_FLASH, "Flash memory" }, + { SMBIOS_MA_USE_NVRAM, "Non-volatile RAM" }, + { SMBIOS_MA_USE_CACHE, "Cache memory" }, +}; + +static const struct str_lookup_table ma_err_corr_strings[] = { + { SMBIOS_MA_ERRCORR_OTHER, "Other" }, + { SMBIOS_MA_ERRCORR_UNKNOWN, "Unknown" }, + { SMBIOS_MA_ERRCORR_NONE, "None" }, + { SMBIOS_MA_ERRCORR_PARITY, "Parity" }, + { SMBIOS_MA_ERRCORR_SBITECC, "Single-bit ECC" }, + { SMBIOS_MA_ERRCORR_MBITECC, "Multi-bit ECC" }, + { SMBIOS_MA_ERRCORR_CRC, "CRC" }, +}; + +static const struct str_lookup_table md_form_factor_strings[] = { + { SMBIOS_MD_FF_OTHER, "Other" }, + { SMBIOS_MD_FF_UNKNOWN, "Unknown" }, + { SMBIOS_MD_FF_SIMM, "SIMM" }, + { SMBIOS_MD_FF_SIP, "SIP" }, + { SMBIOS_MD_FF_CHIP, "Chip" }, + { SMBIOS_MD_FF_DIP, "DIP" }, + { SMBIOS_MD_FF_ZIP, "ZIP" }, + { SMBIOS_MD_FF_PROPCARD, "Proprietary Card" }, + { SMBIOS_MD_FF_DIMM, "DIMM" }, + { SMBIOS_MD_FF_TSOP, "TSOP" }, + { SMBIOS_MD_FF_ROC, "Row of chips" }, + { SMBIOS_MD_FF_RIMM, "RIMM" }, + { SMBIOS_MD_FF_SODIMM, "SODIMM" }, + { SMBIOS_MD_FF_SRIMM, "SRIMM" }, + { SMBIOS_MD_FF_FBDIMM, "FB-DIMM" }, + { SMBIOS_MD_FF_DIE, "Die" }, +}; + +static const struct str_lookup_table md_type_strings[] = { + { SMBIOS_MD_TYPE_OTHER, "Other" }, + { SMBIOS_MD_TYPE_UNKNOWN, "Unknown" }, + { SMBIOS_MD_TYPE_DRAM, "DRAM" }, + { SMBIOS_MD_TYPE_EDRAM, "EDRAM" }, + { SMBIOS_MD_TYPE_VRAM, "VRAM" }, + { SMBIOS_MD_TYPE_SRAM, "SRAM" }, + { SMBIOS_MD_TYPE_RAM, "RAM" }, + { SMBIOS_MD_TYPE_ROM, "ROM" }, + { SMBIOS_MD_TYPE_FLASH, "FLASH" }, + { SMBIOS_MD_TYPE_EEPROM, "EEPROM" }, + { SMBIOS_MD_TYPE_FEPROM, "FEPROM" }, + { SMBIOS_MD_TYPE_EPROM, "EPROM" }, + { SMBIOS_MD_TYPE_CDRAM, "CDRAM" }, + { SMBIOS_MD_TYPE_3DRAM, "3DRAM" }, + { SMBIOS_MD_TYPE_SDRAM, "SDRAM" }, + { SMBIOS_MD_TYPE_SGRAM, "SGRAM" }, + { SMBIOS_MD_TYPE_RDRAM, "RDRAM" }, + { SMBIOS_MD_TYPE_DDR, "DDR" }, + { SMBIOS_MD_TYPE_DDR2, "DDR2" }, + { SMBIOS_MD_TYPE_DDR2FBD, "DDR2 FB-DIMM" }, + { SMBIOS_MD_TYPE_RSVD1, "Reserved" }, + { SMBIOS_MD_TYPE_RSVD2, "Reserved" }, + { SMBIOS_MD_TYPE_DSVD3, "Reserved" }, + { SMBIOS_MD_TYPE_DDR3, "DDR3" }, + { SMBIOS_MD_TYPE_FBD2, "FBD2" }, + { SMBIOS_MD_TYPE_DDR4, "DDR4" }, + { SMBIOS_MD_TYPE_LPDDR, "LPDDR" }, + { SMBIOS_MD_TYPE_LPDDR2, "LPDDR2" }, + { SMBIOS_MD_TYPE_LPDDR3, "LPDDR3" }, + { SMBIOS_MD_TYPE_LPDDR4, "LPDDR4" }, + { SMBIOS_MD_TYPE_LNVD, "Logical non-volatile device" }, + { SMBIOS_MD_TYPE_HBM, "HBM" }, + { SMBIOS_MD_TYPE_HBM2, "HBM2" }, + { SMBIOS_MD_TYPE_DDR5, "DDR5" }, + { SMBIOS_MD_TYPE_LPDDR5, "LPDDR5" }, + { SMBIOS_MD_TYPE_HBM3, "HBM3" }, +}; + +static const struct str_lookup_table md_tech_strings[] = { + { SMBIOS_MD_TECH_OTHER, "Other" }, + { SMBIOS_MD_TECH_UNKNOWN, "Unknown" }, + { SMBIOS_MD_TECH_DRAM, "DRAM" }, + { SMBIOS_MD_TECH_NVDIMMN, "NVDIMM-N" }, + { SMBIOS_MD_TECH_NVDIMMF, "NVDIMM-F" }, + { SMBIOS_MD_TECH_NVDIMMP, "NVDIMM-P" }, + { SMBIOS_MD_TECH_OPTANE, "Intel Optane persistent memory" }, +}; + /** * smbios_get_string() - get SMBIOS string from table * @@ -205,6 +348,8 @@ static void smbios_print_type0(struct smbios_type0 *table) printf("\tBIOS ROM Size: 0x%02x\n", table->bios_rom_size); printf("\tBIOS Characteristics: 0x%016llx\n", table->bios_characteristics); + if (table->hdr.length < SMBIOS_TYPE0_LENGTH_V24) + return; printf("\tBIOS Characteristics Extension Byte 1: 0x%02x\n", table->bios_characteristics_ext1); printf("\tBIOS Characteristics Extension Byte 2: 0x%02x\n", @@ -217,6 +362,8 @@ static void smbios_print_type0(struct smbios_type0 *table) table->ec_major_release); printf("\tEmbedded Controller Firmware Minor Release: 0x%02x\n", table->ec_minor_release); + if (table->hdr.length < SMBIOS_TYPE0_LENGTH_V31) + return; printf("\tExtended BIOS ROM Size: 0x%04x\n", table->extended_bios_rom_size); } @@ -228,17 +375,16 @@ static void smbios_print_type1(struct smbios_type1 *table) smbios_print_str("Product Name", table, table->product_name); smbios_print_str("Version", table, table->version); smbios_print_str("Serial Number", table, table->serial_number); - if (table->hdr.length >= SMBIOS_TYPE1_LENGTH_V21) { - printf("\tUUID: %pUl\n", table->uuid); - smbios_print_lookup_str(wakeup_type_strings, - table->wakeup_type, - ARRAY_SIZE(wakeup_type_strings), - "Wake-up Type"); - } - if (table->hdr.length >= SMBIOS_TYPE1_LENGTH_V24) { - smbios_print_str("SKU Number", table, table->sku_number); - smbios_print_str("Family", table, table->family); - } + if (table->hdr.length < SMBIOS_TYPE1_LENGTH_V21) + return; + printf("\tUUID: %pUl\n", table->uuid); + smbios_print_lookup_str(wakeup_type_strings, table->wakeup_type, + ARRAY_SIZE(wakeup_type_strings), + "Wake-up Type"); + if (table->hdr.length < SMBIOS_TYPE1_LENGTH_V24) + return; + smbios_print_str("SKU Number", table, table->sku_number); + smbios_print_str("Family", table, table->family); } static void smbios_print_type2(struct smbios_type2 *table) @@ -358,21 +504,31 @@ static void smbios_print_type4(struct smbios_type4 *table) printf("\tL1 Cache Handle: 0x%04x\n", table->l1_cache_handle); printf("\tL2 Cache Handle: 0x%04x\n", table->l2_cache_handle); printf("\tL3 Cache Handle: 0x%04x\n", table->l3_cache_handle); + if (table->hdr.length < SMBIOS_TYPE4_LENGTH_V23) + return; smbios_print_str("Serial Number", table, table->serial_number); smbios_print_str("Asset Tag", table, table->asset_tag); smbios_print_str("Part Number", table, table->part_number); + if (table->hdr.length < SMBIOS_TYPE4_LENGTH_V25) + return; printf("\tCore Count: 0x%02x\n", table->core_count); printf("\tCore Enabled: 0x%02x\n", table->core_enabled); printf("\tThread Count: 0x%02x\n", table->thread_count); printf("\tProcessor Characteristics: 0x%04x\n", table->processor_characteristics); + if (table->hdr.length < SMBIOS_TYPE4_LENGTH_V26) + return; smbios_print_lookup_str(processor_family_strings, table->processor_family2, ARRAY_SIZE(processor_family_strings), "Processor Family 2"); + if (table->hdr.length < SMBIOS_TYPE4_LENGTH_V30) + return; printf("\tCore Count 2: 0x%04x\n", table->core_count2); printf("\tCore Enabled 2: 0x%04x\n", table->core_enabled2); printf("\tThread Count 2: 0x%04x\n", table->thread_count2); + if (table->hdr.length < SMBIOS_TYPE4_LENGTH_V36) + return; printf("\tThread Enabled: 0x%04x\n", table->thread_enabled); } @@ -386,6 +542,8 @@ static void smbios_print_type7(struct smbios_type7 *table) printf("\tInstalled Size: 0x%04x\n", table->inst_size.data); printf("\tSupported SRAM Type: 0x%04x\n", table->supp_sram_type.data); printf("\tCurrent SRAM Type: 0x%04x\n", table->curr_sram_type.data); + if (table->hdr.length < SMBIOS_TYPE7_LENGTH_V21) + return; printf("\tCache Speed: 0x%02x\n", table->speed); smbios_print_lookup_str(err_corr_type_strings, table->err_corr_type, @@ -399,10 +557,183 @@ static void smbios_print_type7(struct smbios_type7 *table) table->associativity, ARRAY_SIZE(associativity_strings), "Associativity"); + if (table->hdr.length < SMBIOS_TYPE7_LENGTH_V31) + return; printf("\tMaximum Cache Size 2: 0x%08x\n", table->max_size2.data); 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); + if (table->hdr.length < SMBIOS_TYPE9_LENGTH_V21) + return; + printf("\tSlot Characteristics 2: 0x%04x\n", + table->slot_characteristics_2); + if (table->hdr.length < SMBIOS_TYPE9_LENGTH_V26) + return; + 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_type16(struct smbios_type16 *table) +{ + printf("Physical Memory Array:\n"); + if (table->hdr.length < SMBIOS_TYPE16_LENGTH_V21) + return; + smbios_print_lookup_str(ma_location_strings, table->location, + ARRAY_SIZE(ma_location_strings), "Location"); + smbios_print_lookup_str(ma_use_strings, table->use, + ARRAY_SIZE(ma_use_strings), "Use"); + smbios_print_lookup_str(ma_err_corr_strings, table->mem_err_corr, + ARRAY_SIZE(ma_err_corr_strings), + "Memory Error Correction"); + printf("\tMaximum Capacity: 0x%08x\n", table->max_cap); + printf("\tMemory Error Information Handle: 0x%04x\n", + table->mem_err_info_hdl); + printf("\tNumber of Memory Devices: 0x%04x\n", table->num_of_mem_dev); + if (table->hdr.length < SMBIOS_TYPE16_LENGTH_V27) + return; + printf("\tExtended Maximum Capacity: 0x%016llx\n", table->ext_max_cap); +} + +static void smbios_print_type17(struct smbios_type17 *table) +{ + printf("Memory Device:\n"); + if (table->hdr.length < SMBIOS_TYPE17_LENGTH_V21) + return; + printf("\tPhysical Memory Array Handle: 0x%04x\n", + table->phy_mem_array_hdl); + printf("\tMemory Error Information Handle: 0x%04x\n", + table->mem_err_info_hdl); + printf("\tTotal Width: 0x%04x\n", table->total_width); + printf("\tData Width: 0x%04x\n", table->data_width); + printf("\tSize: 0x%04x\n", table->size); + smbios_print_lookup_str(md_form_factor_strings, table->form_factor, + ARRAY_SIZE(md_form_factor_strings), + "Form Factor"); + printf("\tDevice Set: 0x%04x\n", table->dev_set); + smbios_print_str("Device Locator", table, table->dev_locator); + smbios_print_str("Bank Locator", table, table->bank_locator); + smbios_print_lookup_str(md_type_strings, table->mem_type, + ARRAY_SIZE(md_type_strings), "Memory Type"); + printf("\tType Detail: 0x%04x\n", table->type_detail); + if (table->hdr.length < SMBIOS_TYPE17_LENGTH_V23) + return; + printf("\tSpeed: 0x%04x\n", table->speed); + smbios_print_str("Manufacturer", table, table->manufacturer); + smbios_print_str("Serial Number", table, table->serial_number); + smbios_print_str("Asset Tag", table, table->asset_tag); + smbios_print_str("Part Number", table, table->part_number); + if (table->hdr.length < SMBIOS_TYPE17_LENGTH_V26) + return; + printf("\tAttributes: 0x%04x\n", table->attributes); + if (table->hdr.length < SMBIOS_TYPE17_LENGTH_V27) + return; + printf("\tExtended Size: 0x%08x\n", table->ext_size); + printf("\tConfigured Memory Speed: 0x%04x\n", table->config_mem_speed); + if (table->hdr.length < SMBIOS_TYPE17_LENGTH_V28) + return; + printf("\tMinimum voltage: 0x%04x\n", table->min_voltage); + printf("\tMaximum voltage: 0x%04x\n", table->max_voltage); + printf("\tConfigured voltage: 0x%04x\n", table->config_voltage); + if (table->hdr.length < SMBIOS_TYPE17_LENGTH_V32) + return; + smbios_print_lookup_str(md_tech_strings, table->mem_tech, + ARRAY_SIZE(md_tech_strings), + "Memory Technology"); + printf("\tMemory Operating Mode Capability: 0x%04x\n", + table->mem_op_mode_cap); + smbios_print_str("Firmware Version", table, table->fw_ver); + printf("\tModule Manufacturer ID: 0x%04x\n", table->module_man_id); + printf("\tModule Product ID: 0x%04x\n", table->module_prod_id); + printf("\tMemory Subsystem Controller Manufacturer ID: 0x%04x\n", + table->mem_subsys_con_man_id); + printf("\tMemory Subsystem Controller Product ID: 0x%04x\n", + table->mem_subsys_con_prod_id); + printf("\tNon-volatile Size: 0x%016llx\n", table->nonvolatile_size); + printf("\tVolatile Size: 0x%016llx\n", table->volatile_size); + printf("\tCache Size: 0x%016llx\n", table->cache_size); + printf("\tLogical Size: 0x%016llx\n", table->logical_size); + if (table->hdr.length < SMBIOS_TYPE17_LENGTH_V33) + return; + printf("\tExtended Speed: 0x%04x\n", table->ext_speed); + printf("\tExtended Configured Memory Speed: 0x%04x\n", + table->ext_config_mem_speed); + printf("\tPMIC0 Manufacturer ID: 0x%04x\n", table->pmic0_man_id); + printf("\tPMIC0 Revision Number: 0x%04x\n", table->pmic0_rev_num); + printf("\tRCD Manufacturer ID: 0x%04x\n", table->rcd_man_id); + printf("\tRCD Revision Number: 0x%04x\n", table->rcd_rev_num); +} + +static void smbios_print_type19(struct smbios_type19 *table) +{ + printf("Memory Array Mapped Address:\n"); + if (table->hdr.length < SMBIOS_TYPE19_LENGTH_V21) + return; + printf("\tStarting Address: 0x%08x\n", table->start_addr); + printf("\tEnding Address: 0x%08x\n", table->end_addr); + printf("\tMemory Array Handle: 0x%04x\n", table->mem_array_hdl); + printf("\tPartition Width: 0x%04x\n", table->partition_wid); + if (table->hdr.length < SMBIOS_TYPE19_LENGTH_V27) + return; + printf("\tExtended Starting Address: 0x%016llx\n", table->ext_start_addr); + printf("\tExtended Ending Address: 0x%016llx\n", table->ext_end_addr); +} + static void smbios_print_type127(struct smbios_type127 *table) { printf("End Of Table\n"); @@ -482,6 +813,18 @@ 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_PHYS_MEMORY_ARRAY: + smbios_print_type16((struct smbios_type16 *)pos); + break; + case SMBIOS_MEMORY_DEVICE: + smbios_print_type17((struct smbios_type17 *)pos); + break; + case SMBIOS_MEMORY_ARRAY_MAPPED_ADDRESS: + smbios_print_type19((struct smbios_type19 *)pos); + break; case SMBIOS_END_OF_TABLE: smbios_print_type127((struct smbios_type127 *)pos); break; diff --git a/drivers/sysinfo/smbios.c b/drivers/sysinfo/smbios.c index 99104274f72..ff5873c940e 100644 --- a/drivers/sysinfo/smbios.c +++ b/drivers/sysinfo/smbios.c @@ -24,6 +24,7 @@ struct sysinfo_plat_priv { struct smbios_type7 t7[SYSINFO_CACHE_LVL_MAX]; u16 cache_handles[SYSINFO_CACHE_LVL_MAX]; u8 cache_level; + u16 marray_handles[SYSINFO_MEM_HANDLE_MAX]; }; static void smbios_cache_info_dump(struct smbios_type7 *cache_info) @@ -165,6 +166,10 @@ static int sysinfo_plat_get_data(struct udevice *dev, int id, void **buf, *buf = &priv->cache_handles[0]; *size = sizeof(priv->cache_handles); break; + case SYSID_SM_MEMARRAY_HANDLE: + *buf = &priv->marray_handles[0]; + *size = sizeof(priv->marray_handles); + break; default: return -EOPNOTSUPP; } diff --git a/include/smbios.h b/include/smbios.h index f2f7483bce5..39090d3ba18 100644 --- a/include/smbios.h +++ b/include/smbios.h @@ -110,10 +110,42 @@ struct __packed smbios_type0 { char eos[SMBIOS_STRUCT_EOS_BYTES]; }; +#define SMBIOS_TYPE0_LENGTH_V24 0x18 +#define SMBIOS_TYPE0_LENGTH_V31 0x1a + #define SMBIOS_TYPE1_LENGTH_V20 0x08 #define SMBIOS_TYPE1_LENGTH_V21 0x19 #define SMBIOS_TYPE1_LENGTH_V24 0x1b +#define SMBIOS_TYPE4_LENGTH_V20 0x1a +#define SMBIOS_TYPE4_LENGTH_V23 0x23 +#define SMBIOS_TYPE4_LENGTH_V25 0x28 +#define SMBIOS_TYPE4_LENGTH_V26 0x2a +#define SMBIOS_TYPE4_LENGTH_V30 0x30 +#define SMBIOS_TYPE4_LENGTH_V36 0x32 + +#define SMBIOS_TYPE7_LENGTH_V20 0x0f +#define SMBIOS_TYPE7_LENGTH_V21 0x13 +#define SMBIOS_TYPE7_LENGTH_V31 0x1b + +#define SMBIOS_TYPE9_LENGTH_V20 0x0c +#define SMBIOS_TYPE9_LENGTH_V21 0x0d +#define SMBIOS_TYPE9_LENGTH_V26 0x11 + +#define SMBIOS_TYPE16_LENGTH_V21 0x0f +#define SMBIOS_TYPE16_LENGTH_V27 0x17 + +#define SMBIOS_TYPE17_LENGTH_V21 0x15 +#define SMBIOS_TYPE17_LENGTH_V23 0x1b +#define SMBIOS_TYPE17_LENGTH_V26 0x1c +#define SMBIOS_TYPE17_LENGTH_V27 0x22 +#define SMBIOS_TYPE17_LENGTH_V28 0x28 +#define SMBIOS_TYPE17_LENGTH_V32 0x54 +#define SMBIOS_TYPE17_LENGTH_V33 0x5c + +#define SMBIOS_TYPE19_LENGTH_V21 0x0f +#define SMBIOS_TYPE19_LENGTH_V27 0x1f + struct __packed smbios_type1 { struct smbios_header hdr; u8 manufacturer; @@ -264,6 +296,125 @@ 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]; +}; + +enum { + SMBIOS_MEM_NONE = 0, + SMBIOS_MEM_CUSTOM = 1, + SMBIOS_MEM_FDT_MEM_NODE = 2, + SMBIOS_MEM_FDT_MEMCON_NODE = 3 +}; + +struct __packed smbios_type16 { + struct smbios_header hdr; + u8 location; + u8 use; + u8 mem_err_corr; + u32 max_cap; + u16 mem_err_info_hdl; + u16 num_of_mem_dev; + u64 ext_max_cap; + char eos[SMBIOS_STRUCT_EOS_BYTES]; +}; + +struct __packed smbios_type17 { + struct smbios_header hdr; + u16 phy_mem_array_hdl; + u16 mem_err_info_hdl; + u16 total_width; + u16 data_width; + u16 size; + u8 form_factor; + u8 dev_set; + u8 dev_locator; + u8 bank_locator; + u8 mem_type; + u16 type_detail; + u16 speed; + u8 manufacturer; + u8 serial_number; + u8 asset_tag; + u8 part_number; + u8 attributes; + u32 ext_size; + u16 config_mem_speed; + u16 min_voltage; + u16 max_voltage; + u16 config_voltage; + u8 mem_tech; + u16 mem_op_mode_cap; + u8 fw_ver; + u16 module_man_id; + u16 module_prod_id; + u16 mem_subsys_con_man_id; + u16 mem_subsys_con_prod_id; + u64 nonvolatile_size; + u64 volatile_size; + u64 cache_size; + u64 logical_size; + u32 ext_speed; + u32 ext_config_mem_speed; + u16 pmic0_man_id; + u16 pmic0_rev_num; + u16 rcd_man_id; + u16 rcd_rev_num; + char eos[SMBIOS_STRUCT_EOS_BYTES]; +}; + +struct __packed smbios_type19 { + struct smbios_header hdr; + u32 start_addr; + u32 end_addr; + u16 mem_array_hdl; + u8 partition_wid; + u64 ext_start_addr; + u64 ext_end_addr; + 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..ae50e1a808e 100644 --- a/include/smbios_def.h +++ b/include/smbios_def.h @@ -191,4 +191,254 @@ #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 + +/* Physical Memory Array */ + +/* Location */ +#define SMBIOS_MA_LOCATION_OTHER 1 +#define SMBIOS_MA_LOCATION_UNKNOWN 2 +#define SMBIOS_MA_LOCATION_MOTHERBOARD 3 + +/* Use */ +#define SMBIOS_MA_USE_OTHER 1 +#define SMBIOS_MA_USE_UNKNOWN 2 +#define SMBIOS_MA_USE_SYSTEM 3 +#define SMBIOS_MA_USE_VIDEO 4 +#define SMBIOS_MA_USE_FLASH 5 +#define SMBIOS_MA_USE_NVRAM 6 +#define SMBIOS_MA_USE_CACHE 7 + +/* Error Correction Type */ +#define SMBIOS_MA_ERRCORR_OTHER 1 +#define SMBIOS_MA_ERRCORR_UNKNOWN 2 +#define SMBIOS_MA_ERRCORR_NONE 3 +#define SMBIOS_MA_ERRCORR_PARITY 4 +#define SMBIOS_MA_ERRCORR_SBITECC 5 +#define SMBIOS_MA_ERRCORR_MBITECC 6 +#define SMBIOS_MA_ERRCORR_CRC 7 + +/* Error Information Handle */ +#define SMBIOS_MA_ERRINFO_NONE 0xFFFE +#define SMBIOS_MA_ERRINFO_NOERR 0xFFFF + +/* Memory Device */ + +/* Size */ + +#define SMBIOS_MD_SIZE_UNKNOWN 0xFFFF +#define SMBIOS_MD_SIZE_EXT 0x7FFF + +/* Form Factor */ +#define SMBIOS_MD_FF_OTHER 1 +#define SMBIOS_MD_FF_UNKNOWN 2 +#define SMBIOS_MD_FF_SIMM 3 +#define SMBIOS_MD_FF_SIP 4 +#define SMBIOS_MD_FF_CHIP 5 +#define SMBIOS_MD_FF_DIP 6 +#define SMBIOS_MD_FF_ZIP 7 +#define SMBIOS_MD_FF_PROPCARD 8 +#define SMBIOS_MD_FF_DIMM 9 +#define SMBIOS_MD_FF_TSOP 10 +#define SMBIOS_MD_FF_ROC 11 +#define SMBIOS_MD_FF_RIMM 12 +#define SMBIOS_MD_FF_SODIMM 13 +#define SMBIOS_MD_FF_SRIMM 14 +#define SMBIOS_MD_FF_FBDIMM 15 +#define SMBIOS_MD_FF_DIE 16 + +/* Device set */ +#define SMBIOS_MD_DEVSET_NONE 0 +#define SMBIOS_MD_DEVSET_UNKNOWN 0xFF + +/* Speed */ +#define SMBIOS_MD_SPEED_UNKNOWN 0 +#define SMBIOS_MD_SPEED_EXT 0xFFFF + +/* Attributes */ +#define SMBIOS_MD_ATTR_RANK_UNKNOWN 0 + +/* Configured Memory Speed */ +#define SMBIOS_MD_CONFSPEED_UNKNOWN 0 +#define SMBIOS_MD_CONFSPEED_EXT 0xFFFF + +/* Voltage */ +#define SMBIOS_MD_VOLTAGE_UNKNOWN 0 + +/* Type */ +#define SMBIOS_MD_TYPE_OTHER 1 +#define SMBIOS_MD_TYPE_UNKNOWN 2 +#define SMBIOS_MD_TYPE_DRAM 3 +#define SMBIOS_MD_TYPE_EDRAM 4 +#define SMBIOS_MD_TYPE_VRAM 5 +#define SMBIOS_MD_TYPE_SRAM 6 +#define SMBIOS_MD_TYPE_RAM 7 +#define SMBIOS_MD_TYPE_ROM 8 +#define SMBIOS_MD_TYPE_FLASH 9 +#define SMBIOS_MD_TYPE_EEPROM 10 +#define SMBIOS_MD_TYPE_FEPROM 11 +#define SMBIOS_MD_TYPE_EPROM 12 +#define SMBIOS_MD_TYPE_CDRAM 13 +#define SMBIOS_MD_TYPE_3DRAM 14 +#define SMBIOS_MD_TYPE_SDRAM 15 +#define SMBIOS_MD_TYPE_SGRAM 16 +#define SMBIOS_MD_TYPE_RDRAM 17 +#define SMBIOS_MD_TYPE_DDR 18 +#define SMBIOS_MD_TYPE_DDR2 19 +#define SMBIOS_MD_TYPE_DDR2FBD 20 +#define SMBIOS_MD_TYPE_RSVD1 21 +#define SMBIOS_MD_TYPE_RSVD2 22 +#define SMBIOS_MD_TYPE_DSVD3 23 +#define SMBIOS_MD_TYPE_DDR3 24 +#define SMBIOS_MD_TYPE_FBD2 25 +#define SMBIOS_MD_TYPE_DDR4 26 +#define SMBIOS_MD_TYPE_LPDDR 27 +#define SMBIOS_MD_TYPE_LPDDR2 28 +#define SMBIOS_MD_TYPE_LPDDR3 29 +#define SMBIOS_MD_TYPE_LPDDR4 30 +#define SMBIOS_MD_TYPE_LNVD 31 +#define SMBIOS_MD_TYPE_HBM 32 +#define SMBIOS_MD_TYPE_HBM2 33 +#define SMBIOS_MD_TYPE_DDR5 34 +#define SMBIOS_MD_TYPE_LPDDR5 35 +#define SMBIOS_MD_TYPE_HBM3 36 + +/* Type Detail */ +#define SMBIOS_MD_TD_RSVD 1 /* BIT(0), set to 0 */ +#define SMBIOS_MD_TD_OTHER 2 /* BIT(1) */ +#define SMBIOS_MD_TD_UNKNOWN 4 /* BIT(2) */ +#define SMBIOS_MD_TD_FP 8 /* BIT(3) */ +#define SMBIOS_MD_TD_SC 0x10 /* BIT(4) */ +#define SMBIOS_MD_TD_PS 0x20 /* BIT(5) */ +#define SMBIOS_MD_TD_RAMBUS 0x40 /* BIT(6) */ +#define SMBIOS_MD_TD_SYNC 0x80 /* BIT(7) */ +#define SMBIOS_MD_TD_CMOS 0x100 /* BIT(8) */ +#define SMBIOS_MD_TD_EDO 0x200 /* BIT(9) */ +#define SMBIOS_MD_TD_WINDRAM 0x400 /* BIT(10) */ +#define SMBIOS_MD_TD_CACHEDRAM 0x800 /* BIT(11) */ +#define SMBIOS_MD_TD_NV 0x1000 /* BIT(12) */ +#define SMBIOS_MD_TD_RGSTD 0x2000 /* BIT(13) */ +#define SMBIOS_MD_TD_UNRGSTD 0x4000 /* BIT(14) */ +#define SMBIOS_MD_TD_LRDIMM 0x8000 /* BIT(15) */ + +/* Technology */ +#define SMBIOS_MD_TECH_OTHER 1 +#define SMBIOS_MD_TECH_UNKNOWN 2 +#define SMBIOS_MD_TECH_DRAM 3 +#define SMBIOS_MD_TECH_NVDIMMN 4 +#define SMBIOS_MD_TECH_NVDIMMF 5 +#define SMBIOS_MD_TECH_NVDIMMP 6 +#define SMBIOS_MD_TECH_OPTANE 7 + +/* Operating Mode Capability */ +#define SMBIOS_MD_OPMC_RSVD 1 /* BIT(0), set to 0 */ +#define SMBIOS_MD_OPMC_OTHER 2 /* BIT(1) */ +#define SMBIOS_MD_OPMC_UNKNOWN 4 /* BIT(2) */ +#define SMBIOS_MD_OPMC_VM 8 /* BIT(3) */ +#define SMBIOS_MD_OPMC_BYTEAPM 0x10 /* BIT(4) */ +#define SMBIOS_MD_OPMC_BLKAPM 0x20 /* BIT(5) */ +/* Bit 6:15 Reserved, set to 0 */ + +/* Non-volatile / Volatile / Cache / Logical portion Size */ +#define SMBIOS_MD_PORT_SIZE_NONE 0 +#define SMBIOS_MD_PORT_SIZE_UNKNOWN_HI 0xFFFFFFFF +#define SMBIOS_MD_PORT_SIZE_UNKNOWN_LO 0xFFFFFFFF +#define SMBIOS_MS_PORT_SIZE_UNKNOWN 0xFFFFFFFFFFFFFFFF + +/* Error Information Handle */ +#define SMBIOS_MD_ERRINFO_NONE 0xFFFE +#define SMBIOS_MD_ERRINFO_NOERR 0xFFFF + +/* Memory Array Mapped Address */ + +/* Partition Width */ +#define SMBIOS_MAMA_PW_DEF 1 /* not partitioned */ + #endif /* _SMBIOS_DEF_H_ */ diff --git a/include/sysinfo.h b/include/sysinfo.h index e87cf969fcd..54eb64a204a 100644 --- a/include/sysinfo.h +++ b/include/sysinfo.h @@ -12,6 +12,7 @@ struct udevice; #define SYSINFO_CACHE_LVL_MAX 3 +#define SYSINFO_MEM_HANDLE_MAX 8 /* * This uclass encapsulates hardware methods to gather information about a @@ -149,6 +150,9 @@ enum sysinfo_id { SYSID_SM_CACHE_INFO_END = SYSID_SM_CACHE_INST_SIZE2 + SYSINFO_CACHE_LVL_MAX - 1, + /* Memory Array (Type 16) */ + SYSID_SM_MEMARRAY_HANDLE, + /* For show_board_info() */ SYSID_BOARD_MODEL, SYSID_BOARD_MANUFACTURER, diff --git a/lib/smbios.c b/lib/smbios.c index b8c2846277a..d5f18c8bd69 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 * @@ -95,6 +131,18 @@ struct smbios_ctx { char *last_str; }; +typedef int (*smbios_write_subnode)(ulong *current, int handle, + struct smbios_ctx *ctx, int idx, + int type); + +typedef int (*smbios_write_memnode)(ulong *current, int handle, + struct smbios_ctx *ctx, int idx, + int type); + +typedef int (*smbios_write_memctrlnode)(ulong *current, int handle, + struct smbios_ctx *ctx, int idx, + u64 base, u64 sz); + /** * Function prototype to write a specific type of SMBIOS structure * @@ -103,7 +151,7 @@ struct smbios_ctx { * @ctx: context for writing the tables * Return: size of the structure */ -typedef int (*smbios_write_type)(ulong *addr, int handle, +typedef int (*smbios_write_type)(ulong *addr, int *handle, struct smbios_ctx *ctx); /** @@ -222,6 +270,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,10 +289,58 @@ 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; } +#if IS_ENABLED(CONFIG_GENERATE_SMBIOS_TABLE_VERBOSE) +static u64 smbios_get_u64_si(struct smbios_ctx * __maybe_unused ctx, + const char * __maybe_unused prop, + int __maybe_unused sysinfo_id, u64 val_def) +{ + size_t len; + void *data; + const fdt32_t *prop_val; + int prop_len; + u64 val = 0; + + if (!ctx->dev) + return val_def; + + if (!sysinfo_get_data(ctx->dev, sysinfo_id, &data, &len)) + return *((u64 *)data); + + if (!IS_ENABLED(CONFIG_OF_CONTROL) || !prop || !ofnode_valid(ctx->node)) + return val_def; + + prop_val = ofnode_read_prop(ctx->node, prop, &prop_len); + if (!prop_val || prop_len < sizeof(fdt32_t) || + prop_len % sizeof(fdt32_t)) { + /* + * If the node or property is not valid fallback and try the root + */ + prop_val = ofnode_read_prop(ofnode_root(), prop, &prop_len); + if (!prop_val || prop_len < sizeof(fdt32_t) || + prop_len % sizeof(fdt32_t)) + return val_def; + } + + /* 64-bit: or 32-bit */ + if (prop_len >= sizeof(fdt32_t) * 2) { + val = ((u64)fdt32_to_cpu(prop_val[0]) << 32) | + fdt32_to_cpu(prop_val[1]); + } else { + val = fdt32_to_cpu(prop_val[0]); + } + return val; +} +#endif + /** * smbios_add_prop_si() - Add a property from the devicetree or sysinfo * @@ -364,7 +461,7 @@ static int smbios_string_table_len(const struct smbios_ctx *ctx) return (ctx->next_ptr + 1) - ctx->eos; } -static int smbios_write_type0(ulong *current, int handle, +static int smbios_write_type0(ulong *current, int *handle, struct smbios_ctx *ctx) { struct smbios_type0 *t; @@ -372,7 +469,7 @@ static int smbios_write_type0(ulong *current, int handle, t = map_sysmem(*current, len); memset(t, 0, len); - fill_smbios_header(t, SMBIOS_BIOS_INFORMATION, len, handle); + fill_smbios_header(t, SMBIOS_BIOS_INFORMATION, len, *handle); smbios_set_eos(ctx, t->eos); t->vendor = smbios_add_prop_si(ctx, NULL, SYSID_SM_BIOS_VENDOR, "U-Boot"); @@ -423,7 +520,7 @@ static int smbios_write_type0(ulong *current, int handle, return len; } -static int smbios_write_type1(ulong *current, int handle, +static int smbios_write_type1(ulong *current, int *handle, struct smbios_ctx *ctx) { struct smbios_type1 *t; @@ -434,7 +531,7 @@ static int smbios_write_type1(ulong *current, int handle, t = map_sysmem(*current, len); memset(t, 0, len); - fill_smbios_header(t, SMBIOS_SYSTEM_INFORMATION, len, handle); + fill_smbios_header(t, SMBIOS_SYSTEM_INFORMATION, len, *handle); smbios_set_eos(ctx, t->eos); t->manufacturer = smbios_add_prop_si(ctx, "manufacturer", @@ -471,7 +568,7 @@ static int smbios_write_type1(ulong *current, int handle, return len; } -static int smbios_write_type2(ulong *current, int handle, +static int smbios_write_type2(ulong *current, int *handle, struct smbios_ctx *ctx) { struct smbios_type2 *t; @@ -485,7 +582,7 @@ static int smbios_write_type2(ulong *current, int handle, */ t = map_sysmem(*current, len); memset(t, 0, len); - fill_smbios_header(t, SMBIOS_BOARD_INFORMATION, len, handle); + fill_smbios_header(t, SMBIOS_BOARD_INFORMATION, len, *handle); /* eos is at the end of the structure */ eos_addr = (u8 *)t + len - sizeof(t->eos); @@ -519,7 +616,7 @@ static int smbios_write_type2(ulong *current, int handle, * t->number_contained_objects = ; */ - t->chassis_handle = handle + 1; + t->chassis_handle = *handle + 1; len = t->hdr.length + smbios_string_table_len(ctx); *current += len; @@ -528,7 +625,7 @@ static int smbios_write_type2(ulong *current, int handle, return len; } -static int smbios_write_type3(ulong *current, int handle, +static int smbios_write_type3(ulong *current, int *handle, struct smbios_ctx *ctx) { struct smbios_type3 *t; @@ -548,7 +645,7 @@ static int smbios_write_type3(ulong *current, int handle, t = map_sysmem(*current, len); memset(t, 0, len); - fill_smbios_header(t, SMBIOS_SYSTEM_ENCLOSURE, len, handle); + fill_smbios_header(t, SMBIOS_SYSTEM_ENCLOSURE, len, *handle); #if IS_ENABLED(CONFIG_GENERATE_SMBIOS_TABLE_VERBOSE) elem_addr = (u8 *)t + offsetof(struct smbios_type3, sku_number); sku_num_addr = elem_addr + elem_size; @@ -669,7 +766,7 @@ static void smbios_write_type4_dm(struct smbios_type4 *t, #endif } -static int smbios_write_type4(ulong *current, int handle, +static int smbios_write_type4(ulong *current, int *handle, struct smbios_ctx *ctx) { struct smbios_type4 *t; @@ -679,7 +776,7 @@ static int smbios_write_type4(ulong *current, int handle, t = map_sysmem(*current, len); memset(t, 0, len); - fill_smbios_header(t, SMBIOS_PROCESSOR_INFORMATION, len, handle); + fill_smbios_header(t, SMBIOS_PROCESSOR_INFORMATION, len, *handle); smbios_set_eos(ctx, t->eos); t->socket_design = smbios_add_prop_si(ctx, "socket-design", SYSID_SM_PROCESSOR_SOCKET, NULL); @@ -828,13 +925,14 @@ static int smbios_write_type7_1level(ulong *current, int handle, return len; } -static int smbios_write_type7(ulong *current, int handle, +static int smbios_write_type7(ulong *current, int *handle, struct smbios_ctx *ctx) { int len = 0; int i, level; ofnode parent = ctx->node; struct smbios_ctx ctx_bak; + int hdl_base = *handle; memcpy(&ctx_bak, ctx, sizeof(ctx_bak)); @@ -850,15 +948,1017 @@ static int smbios_write_type7(ulong *current, int handle, return 0; ctx->subnode_name = buf; ctx->node = ofnode_find_subnode(parent, ctx->subnode_name); - len += smbios_write_type7_1level(current, handle++, ctx, i); + *handle = hdl_base + i; + len += smbios_write_type7_1level(current, *handle, ctx, i); memcpy(ctx, &ctx_bak, sizeof(*ctx)); } + + return len; +} + +static int smbios_scan_subnodes(ulong *current, struct smbios_ctx *ctx, + int *handle, smbios_write_subnode cb, int type) +{ + ofnode child; + int i; + int hdl_base = *handle; + int len = 0; + struct smbios_ctx ctx_bak; + + memcpy(&ctx_bak, ctx, sizeof(ctx_bak)); + + for (i = 0, child = ofnode_first_subnode(ctx->node); + ofnode_valid(child); child = ofnode_next_subnode(child), i++) { + ctx->node = child; + *handle = hdl_base + i; + len += cb(current, *handle, ctx, i, type); + memcpy(ctx, &ctx_bak, sizeof(*ctx)); + } + + 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, + int __maybe_unused idx, int 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 = * 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_scan_slot_type(ulong *current, int *handle, + struct smbios_ctx *ctx) +{ + int i = 0; + struct smbios_ctx ctx_bak; + ofnode child; + const struct map_sysinfo *prop; + int hdl_base = *handle; + int len = 0; + + memcpy(&ctx_bak, ctx, sizeof(ctx_bak)); + 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; + + *handle = hdl_base + i; + ctx->node = child; + len += smbios_write_type9_1slot(current, *handle, ctx, 0, + dev_type); + memcpy(ctx, &ctx_bak, sizeof(*ctx)); + i++; + } + + return len; +} + +static int smbios_write_type9(ulong *current, int *handle, + struct smbios_ctx *ctx) +{ + int len; + + /* TODO: Get system slot information via pci subsystem */ + if (!IS_ENABLED(CONFIG_OF_CONTROL)) + return 0; /* Error, return 0-length */ + + len = smbios_scan_subnodes(current, ctx, handle, + smbios_write_type9_1slot, + SMBIOS_SYSSLOT_TYPE_UNKNOWN); + if (len) + return len; + + /* if no subnode under 'system-slot', try scan the entire FDT */ + len = smbios_scan_slot_type(current, handle, ctx); + + return len; +} + +static u64 smbios_pop_size_from_memory_node(ofnode node) +{ + const fdt32_t *reg; + int len; + u64 size_bytes; + + /* Read property 'reg' from the node */ + reg = ofnode_read_prop(node, "reg", &len); + if (!reg || len < sizeof(fdt32_t) * 4 || len % sizeof(fdt32_t)) + return 0; + + /* Combine hi/lo for size (typically 64-bit) */ + size_bytes = ((u64)fdt32_to_cpu(reg[2]) << 32) | fdt32_to_cpu(reg[3]); + + return size_bytes; +} + +static int +smbios_write_type16_sum_memory_nodes(ulong *current, int handle, + struct smbios_ctx *ctx, u16 cnt, u64 size) +{ + struct smbios_type16 *t; + int len = sizeof(*t); + u8 *eos_addr; + void *hdl; + size_t hdl_size; + + t = map_sysmem(*current, len); + memset(t, 0, len); + + fill_smbios_header(t, SMBIOS_PHYS_MEMORY_ARRAY, len, handle); + + /* eos is at the end of the structure */ + eos_addr = (u8 *)t + len - sizeof(t->eos); + smbios_set_eos(ctx, eos_addr); + + /* default attributes */ + t->location = SMBIOS_MA_LOCATION_MOTHERBOARD; + t->use = SMBIOS_MA_USE_SYSTEM; + t->mem_err_corr = SMBIOS_MA_ERRCORR_UNKNOWN; + t->mem_err_info_hdl = SMBIOS_MA_ERRINFO_NONE; + t->num_of_mem_dev = cnt; + + /* Use extended field */ + t->max_cap = cpu_to_le32(0x80000000); + t->ext_max_cap = cpu_to_le64(size >> 10); /* In KB */ + + /* Save the memory array handles */ + if (!sysinfo_get_data(ctx->dev, SYSID_SM_MEMARRAY_HANDLE, &hdl, + &hdl_size) && + hdl_size == SYSINFO_MEM_HANDLE_MAX * sizeof(u16)) + *((u16 *)hdl) = handle; + + len = t->hdr.length + smbios_string_table_len(ctx); + *current += len; + unmap_sysmem(t); + + return len; +} + +static void +smbios_pop_type16_from_memcontroller_node(ofnode node, struct smbios_type16 *t) +{ + ofnode child; + int count = 0; + u64 total = 0; + + /* default attributes */ + t->location = SMBIOS_MA_LOCATION_MOTHERBOARD; + t->use = SMBIOS_MA_USE_SYSTEM; + t->mem_err_info_hdl = SMBIOS_MA_ERRINFO_NONE; + + /* Check custom property 'ecc-enabled' */ + if (ofnode_read_bool(node, "ecc-enabled")) + t->mem_err_corr = SMBIOS_MA_ERRCORR_SBITECC; + else + t->mem_err_corr = SMBIOS_MA_ERRCORR_UNKNOWN; + + /* Read subnodes with 'size' property */ + for (child = ofnode_first_subnode(node); ofnode_valid(child); + child = ofnode_next_subnode(child)) { + u64 sz = 0; + const fdt32_t *size; + int len; + + size = ofnode_read_prop(child, "size", &len); + if (!size || len < sizeof(fdt32_t) || len % sizeof(fdt32_t)) + continue; + + /* 64-bit size: or 32-bit size */ + if (len >= sizeof(fdt32_t) * 2) + sz = ((u64)fdt32_to_cpu(size[0]) << 32) | + fdt32_to_cpu(size[1]); + else + sz = fdt32_to_cpu(size[0]); + + count++; + total += sz; + } + + /* + * Number of memory devices associated with this array + * (i.e., how many Type17 entries link to this Type16 array) + */ + t->num_of_mem_dev = count; + + /* Use extended field */ + t->max_cap = cpu_to_le32(0x80000000); + t->ext_max_cap = cpu_to_le64(total >> 10); /* In KB */ +} + +static void smbios_pop_type16_si(struct smbios_ctx *ctx, + struct smbios_type16 *t) +{ + t->location = smbios_get_val_si(ctx, "location", SYSID_NONE, + SMBIOS_MA_LOCATION_UNKNOWN); + t->use = smbios_get_val_si(ctx, "use", SYSID_NONE, + SMBIOS_MA_USE_UNKNOWN); + t->mem_err_corr = smbios_get_val_si(ctx, "memory-error-correction", SYSID_NONE, + SMBIOS_MA_ERRCORR_UNKNOWN); + t->max_cap = smbios_get_val_si(ctx, "maximum-capacity", SYSID_NONE, 0); + t->mem_err_info_hdl = smbios_get_val_si(ctx, "memory-error-information-handle", + SYSID_NONE, SMBIOS_MA_ERRINFO_NONE); + t->num_of_mem_dev = smbios_get_val_si(ctx, "number-of-memory-devices", SYSID_NONE, 1); + t->ext_max_cap = smbios_get_u64_si(ctx, "extended-maximum-capacity", SYSID_NONE, 0); +} + +static int smbios_write_type16_1array(ulong *current, int handle, + struct smbios_ctx *ctx, int idx, + int type) +{ + struct smbios_type16 *t; + int len = sizeof(*t); + u8 *eos_addr; + void *hdl; + size_t hdl_size; + + t = map_sysmem(*current, len); + memset(t, 0, len); + + fill_smbios_header(t, SMBIOS_PHYS_MEMORY_ARRAY, len, handle); + + /* eos is at the end of the structure */ + eos_addr = (u8 *)t + len - sizeof(t->eos); + smbios_set_eos(ctx, eos_addr); + + if (type == SMBIOS_MEM_CUSTOM) + smbios_pop_type16_si(ctx, t); + else if (type == SMBIOS_MEM_FDT_MEMCON_NODE) + smbios_pop_type16_from_memcontroller_node(ctx->node, t); + + /* Save the memory array handles */ + if (!sysinfo_get_data(ctx->dev, SYSID_SM_MEMARRAY_HANDLE, &hdl, + &hdl_size) && + hdl_size == SYSINFO_MEM_HANDLE_MAX * sizeof(u16)) + *((u16 *)hdl + idx) = handle; + + len = t->hdr.length + smbios_string_table_len(ctx); + *current += len; + unmap_sysmem(t); + + return len; +} + +static int smbios_write_type16(ulong *current, int *handle, + struct smbios_ctx *ctx) +{ + int len; + struct smbios_ctx ctx_bak; + ofnode child; + int idx; + u64 total = 0; + int count = 0; + int hdl_base = *handle; + + if (!IS_ENABLED(CONFIG_OF_CONTROL)) + return 0; /* Error, return 0-length */ + + /* Step 1: Scan any subnode exists under 'memory-array' */ + len = smbios_scan_subnodes(current, ctx, handle, + smbios_write_type16_1array, + SMBIOS_MEM_CUSTOM); + if (len) + return len; + + /* Step 2: Scan 'memory' node from the entire FDT */ + for (child = ofnode_first_subnode(ofnode_root()); + ofnode_valid(child); child = ofnode_next_subnode(child)) { + const char *str; + + /* Look up for 'device_type = "memory"' */ + str = ofnode_read_string(child, "device_type"); + if (str && !strcmp(str, "memory")) { + count++; + total += smbios_pop_size_from_memory_node(child); + } + } + /* + * Generate one type16 instance for all 'memory' nodes, + * use idx=0 implicitly + */ + if (count) + len += smbios_write_type16_sum_memory_nodes(current, *handle, + ctx, count, total); + + /* Step 3: Scan 'memory-controller' node from the entire FDT */ + /* idx starts from 1 */ + memcpy(&ctx_bak, ctx, sizeof(ctx_bak)); + for (idx = 1, child = ofnode_first_subnode(ofnode_root()); + ofnode_valid(child); child = ofnode_next_subnode(child)) { + const char *compat; + const char *name; + + /* + * Look up for node with name or property 'compatible' + * containing 'memory-controller'. + */ + name = ofnode_get_name(child); + compat = ofnode_read_string(child, "compatible"); + if ((!compat || !strstr(compat, "memory-controller")) && + (!name || !strstr(name, "memory-controller"))) + continue; + + *handle = hdl_base + idx; + ctx->node = child; + /* + * Generate one type16 instance for each 'memory-controller' + * node, sum the 'size' of all subnodes. + */ + len += smbios_write_type16_1array(current, *handle, ctx, idx, + SMBIOS_MEM_FDT_MEMCON_NODE); + idx++; + memcpy(ctx, &ctx_bak, sizeof(*ctx)); + } + + return len; +} + +static void smbios_pop_type17_general_si(struct smbios_ctx *ctx, + struct smbios_type17 *t) +{ + t->mem_err_info_hdl = + smbios_get_val_si(ctx, "memory-error-information-handle", + SYSID_NONE, SMBIOS_MD_ERRINFO_NONE); + t->total_width = smbios_get_val_si(ctx, "total-width", SYSID_NONE, 0); + t->data_width = smbios_get_val_si(ctx, "data-width", SYSID_NONE, 0); + t->form_factor = smbios_get_val_si(ctx, "form-factor", + SYSID_NONE, SMBIOS_MD_FF_UNKNOWN); + t->dev_set = smbios_get_val_si(ctx, "device-set", SYSID_NONE, + SMBIOS_MD_DEVSET_UNKNOWN); + t->dev_locator = smbios_add_prop_si(ctx, "device-locator", SYSID_NONE, + NULL); + t->bank_locator = smbios_add_prop_si(ctx, "bank-locator", SYSID_NONE, + NULL); + t->mem_type = smbios_get_val_si(ctx, "memory-type", + SYSID_NONE, SMBIOS_MD_TYPE_UNKNOWN); + t->type_detail = smbios_get_val_si(ctx, "type-detail", + SYSID_NONE, SMBIOS_MD_TD_UNKNOWN); + t->speed = smbios_get_val_si(ctx, "speed", SYSID_NONE, + SMBIOS_MD_SPEED_UNKNOWN); + t->manufacturer = smbios_add_prop_si(ctx, "manufacturer", SYSID_NONE, + NULL); + t->serial_number = smbios_add_prop_si(ctx, "serial-number", SYSID_NONE, + NULL); + t->asset_tag = smbios_add_prop_si(ctx, "asset-tag", SYSID_NONE, NULL); + t->part_number = smbios_add_prop_si(ctx, "part-number", SYSID_NONE, + NULL); + t->attributes = smbios_get_val_si(ctx, "attributes", SYSID_NONE, + SMBIOS_MD_ATTR_RANK_UNKNOWN); + t->config_mem_speed = smbios_get_val_si(ctx, "configured-memory-speed", + SYSID_NONE, + SMBIOS_MD_CONFSPEED_UNKNOWN); + t->min_voltage = smbios_get_val_si(ctx, "minimum-voltage", SYSID_NONE, + SMBIOS_MD_VOLTAGE_UNKNOWN); + t->max_voltage = smbios_get_val_si(ctx, "maximum-voltage", SYSID_NONE, + SMBIOS_MD_VOLTAGE_UNKNOWN); + t->config_voltage = smbios_get_val_si(ctx, "configured-voltage", + SYSID_NONE, + SMBIOS_MD_VOLTAGE_UNKNOWN); + t->mem_tech = smbios_get_val_si(ctx, "memory-technology", + SYSID_NONE, SMBIOS_MD_TECH_UNKNOWN); + t->mem_op_mode_cap = + smbios_get_val_si(ctx, "memory-operating-mode-capability", + SYSID_NONE, SMBIOS_MD_OPMC_UNKNOWN); + t->fw_ver = smbios_add_prop_si(ctx, "firmware-version", SYSID_NONE, + NULL); + t->module_man_id = smbios_get_val_si(ctx, "module-manufacturer-id", + SYSID_NONE, 0); + t->module_prod_id = smbios_get_val_si(ctx, "module-product-id", + SYSID_NONE, 0); + t->mem_subsys_con_man_id = + smbios_get_val_si(ctx, + "memory-subsystem-controller-manufacturer-id", + SYSID_NONE, 0); + t->mem_subsys_con_prod_id = + smbios_get_val_si(ctx, + "memory-subsystem-controller-product-id", + SYSID_NONE, 0); + t->nonvolatile_size = smbios_get_u64_si(ctx, "non-volatile-size", + SYSID_NONE, + SMBIOS_MS_PORT_SIZE_UNKNOWN); + t->volatile_size = smbios_get_u64_si(ctx, "volatile-size", + SYSID_NONE, + SMBIOS_MS_PORT_SIZE_UNKNOWN); + t->cache_size = smbios_get_u64_si(ctx, "cache-size", + SYSID_NONE, + SMBIOS_MS_PORT_SIZE_UNKNOWN); + t->logical_size = smbios_get_u64_si(ctx, "logical-size", + SYSID_NONE, + SMBIOS_MS_PORT_SIZE_UNKNOWN); + t->ext_speed = smbios_get_val_si(ctx, "extended-speed", SYSID_NONE, 0); + t->ext_config_mem_speed = + smbios_get_val_si(ctx, "extended-configured-memory-speed", + SYSID_NONE, 0); + t->pmic0_man_id = smbios_get_val_si(ctx, "pmic0-manufacturer-id", + SYSID_NONE, 0); + t->pmic0_rev_num = smbios_get_val_si(ctx, "pmic0-revision-number", + SYSID_NONE, 0); + t->rcd_man_id = smbios_get_val_si(ctx, "rcd-manufacturer-id", + SYSID_NONE, 0); + t->rcd_rev_num = smbios_get_val_si(ctx, "rcd-revision-number", + SYSID_NONE, 0); +} + +static void +smbios_pop_type17_size_from_memory_node(ofnode node, struct smbios_type17 *t) +{ + const fdt32_t *reg; + int len; + u64 sz; + u32 size_mb; + + /* Read property 'reg' from the node */ + reg = ofnode_read_prop(node, "reg", &len); + if (!reg || len < sizeof(fdt32_t) * 4 || len % sizeof(fdt32_t)) + return; + + /* Combine hi/lo for size (typically 64-bit) */ + sz = ((u64)fdt32_to_cpu(reg[2]) << 32) | fdt32_to_cpu(reg[3]); + + /* Convert size to MB */ + size_mb = (u32)(sz >> 20); /* 1 MB = 2^20 */ + if (size_mb < SMBIOS_MD_SIZE_EXT) { + t->size = cpu_to_le16(size_mb); + t->ext_size = 0; + return; + } + + t->size = cpu_to_le16(SMBIOS_MD_SIZE_EXT); /* Signal extended used */ + t->ext_size = cpu_to_le32((u32)(sz >> 10)); /* In KB */ +} + +static void smbios_pop_type17_size_si(struct smbios_ctx *ctx, + struct smbios_type17 *t) +{ + t->size = smbios_get_val_si(ctx, "size", SYSID_NONE, + SMBIOS_MD_SIZE_UNKNOWN); + t->ext_size = smbios_get_val_si(ctx, "extended-size", SYSID_NONE, 0); +} + +static int +smbios_scan_memctrl_subnode(ulong *current, int *handle, struct smbios_ctx *ctx, + int idx, smbios_write_memctrlnode cb) +{ + int total_len = 0; + ofnode child; + int i = 0; + int hdl_base = *handle; + u64 base = 0; + + /* + * Enumerate all subnodes of 'memory-controller' that contain 'size' + * property and generate one instance for each. + */ + for (child = ofnode_first_subnode(ctx->node); ofnode_valid(child); + child = ofnode_next_subnode(child)) { + u64 sz = 0; + const fdt32_t *size; + int proplen; + + size = ofnode_read_prop(child, "size", &proplen); + if (!size || proplen < sizeof(fdt32_t) || + proplen % sizeof(fdt32_t)) + continue; + + /* 64-bit size: or 32-bit size */ + if (proplen >= sizeof(fdt32_t) * 2) + sz = ((u64)fdt32_to_cpu(size[0]) << 32) | + fdt32_to_cpu(size[1]); + else + sz = fdt32_to_cpu(size[0]); + + *handle = hdl_base + i; + total_len += cb(current, *handle, ctx, idx, base, sz); + base += sz; + i++; + } + + return total_len; +} + +static int +smbios_write_type17_from_memctrl_node(ulong *current, int handle, + struct smbios_ctx *ctx, int idx, + u64 __maybe_unused base, u64 sz) +{ + struct smbios_type17 *t; + int len; + u8 *eos_addr; + u32 size_mb; + void *hdl; + size_t hdl_size; + + len = sizeof(*t); + t = map_sysmem(*current, len); + memset(t, 0, len); + + fill_smbios_header(t, SMBIOS_MEMORY_DEVICE, len, handle); + + /* eos is at the end of the structure */ + eos_addr = (u8 *)t + len - sizeof(t->eos); + smbios_set_eos(ctx, eos_addr); + + /* Read the memory array handles */ + if (!sysinfo_get_data(ctx->dev, SYSID_SM_MEMARRAY_HANDLE, &hdl, + &hdl_size) && + hdl_size == SYSINFO_MEM_HANDLE_MAX * sizeof(u16)) + t->phy_mem_array_hdl = *((u16 *)hdl + idx); + + /* Convert to MB */ + size_mb = (u32)(sz >> 20); + if (size_mb < SMBIOS_MD_SIZE_EXT) { + /* Use 16-bit size field */ + t->size = cpu_to_le16(size_mb); /* In MB */ + t->ext_size = cpu_to_le32(0); + } else { + /* Signal use of extended size field */ + t->size = cpu_to_le16(SMBIOS_MD_SIZE_EXT); + t->ext_size = cpu_to_le32((u32)(sz >> 10)); /* In KB */ + } + + /* Write other general fields */ + smbios_pop_type17_general_si(ctx, t); + + len = t->hdr.length + smbios_string_table_len(ctx); + *current += len; + unmap_sysmem(t); + + return len; +} + +static int smbios_write_type17_mem(ulong *current, int handle, + struct smbios_ctx *ctx, int idx, + int type) +{ + struct smbios_type17 *t; + int len; + u8 *eos_addr; + void *hdl; + size_t hdl_size; + + len = sizeof(*t); + t = map_sysmem(*current, len); + memset(t, 0, len); + + fill_smbios_header(t, SMBIOS_MEMORY_DEVICE, len, handle); + + /* eos is at the end of the structure */ + eos_addr = (u8 *)t + len - sizeof(t->eos); + smbios_set_eos(ctx, eos_addr); + + if (type == SMBIOS_MEM_CUSTOM) { + smbios_pop_type17_size_si(ctx, t); + + t->phy_mem_array_hdl = + smbios_get_val_si(ctx, "physical-memory-array-handle", + SYSID_NONE, 0); + } else if (type == SMBIOS_MEM_FDT_MEM_NODE) { + smbios_pop_type17_size_from_memory_node(ctx->node, t); + + /* Read the memory array handles */ + if (!sysinfo_get_data(ctx->dev, SYSID_SM_MEMARRAY_HANDLE, &hdl, + &hdl_size) && + hdl_size == SYSINFO_MEM_HANDLE_MAX * sizeof(u16)) + t->phy_mem_array_hdl = *((u16 *)hdl + idx); + } + + /* Write other general fields */ + smbios_pop_type17_general_si(ctx, t); + + len = t->hdr.length + smbios_string_table_len(ctx); + *current += len; + unmap_sysmem(t); + + return len; +} + +static int smbios_scan_mem_nodes(ulong *current, int *handle, + struct smbios_ctx *ctx, + smbios_write_memnode mem_cb, + int *idx) +{ + int len = 0; + struct smbios_ctx ctx_bak; + ofnode child; + int hdl_base = *handle; + + memcpy(&ctx_bak, ctx, sizeof(ctx_bak)); + + for (child = ofnode_first_subnode(ofnode_root()); + ofnode_valid(child); child = ofnode_next_subnode(child)) { + const char *str; + + /* Look up for 'device_type = "memory"' */ + str = ofnode_read_string(child, "device_type"); + if (!str || strcmp(str, "memory")) + continue; + + ctx->node = child; + *handle = hdl_base + *idx; + /* Generate one instance for each 'memory' node */ + len += mem_cb(current, *handle, ctx, *idx, + SMBIOS_MEM_FDT_MEM_NODE); + memcpy(ctx, &ctx_bak, sizeof(*ctx)); + (*idx)++; + } + + return len; +} + +static int smbios_scan_mctrl_subnodes(ulong *current, int *handle, + struct smbios_ctx *ctx, + smbios_write_memctrlnode mctrl_wcb, + int *idx) +{ + int len = 0; + struct smbios_ctx ctx_bak; + ofnode child; + + memcpy(&ctx_bak, ctx, sizeof(ctx_bak)); + + for (child = ofnode_first_subnode(ofnode_root()); + ofnode_valid(child); child = ofnode_next_subnode(child)) { + const char *compat; + const char *name; + + /* + * Look up for node with name or property 'compatible' + * containing 'memory-controller'. + */ + name = ofnode_get_name(child); + compat = ofnode_read_string(child, "compatible"); + if ((!compat || !strstr(compat, "memory-controller")) && + (!name || !strstr(name, "memory-controller"))) + continue; + + (*handle)++; + ctx->node = child; + /* + * Generate one instance for each subnode of + * 'memory-controller' which contains property 'size'. + */ + len += smbios_scan_memctrl_subnode(current, handle, ctx, + *idx, mctrl_wcb); + memcpy(ctx, &ctx_bak, sizeof(*ctx)); + (*idx)++; + } return len; } +static int smbios_write_type1719(ulong *current, int *handle, + struct smbios_ctx *ctx, + smbios_write_memnode mem_cb, + smbios_write_memctrlnode mctrl_wcb) +{ + int len = 0; + int idx; + + if (!IS_ENABLED(CONFIG_OF_CONTROL)) + return 0; /* Error, return 0-length */ + + /* Step 1: Scan any subnode exists */ + len = smbios_scan_subnodes(current, ctx, handle, mem_cb, + SMBIOS_MEM_CUSTOM); + if (len) + return len; + + /* Step 2: Scan 'memory' node from the entire FDT */ + idx = 0; + len += smbios_scan_mem_nodes(current, handle, ctx, mem_cb, &idx); + + /* Step 3: Scan 'memory-controller' node from the entire FDT */ + len += smbios_scan_mctrl_subnodes(current, handle, ctx, mctrl_wcb, &idx); + + return len; +} + +static int smbios_write_type17(ulong *current, int *handle, + struct smbios_ctx *ctx) +{ + return smbios_write_type1719(current, handle, ctx, + smbios_write_type17_mem, + smbios_write_type17_from_memctrl_node); +} + +static void smbios_pop_type19_general_si(struct smbios_ctx *ctx, + struct smbios_type19 *t) +{ + t->partition_wid = + smbios_get_val_si(ctx, "partition-width ", + SYSID_NONE, SMBIOS_MAMA_PW_DEF); +} + +static void smbios_pop_type19_addr_si(struct smbios_ctx *ctx, + struct smbios_type19 *t) +{ + t->start_addr = smbios_get_val_si(ctx, "starting-address", SYSID_NONE, + 0); + t->end_addr = smbios_get_val_si(ctx, "ending-address", SYSID_NONE, 0); + t->ext_start_addr = smbios_get_u64_si(ctx, "extended-starting-address", + SYSID_NONE, 0); + t->ext_end_addr = smbios_get_u64_si(ctx, "extended-ending-address", + SYSID_NONE, 0); +} + +static void +smbios_pop_type19_addr_from_memory_node(ofnode node, struct smbios_type19 *t) +{ + const fdt32_t *reg; + int len; + u64 sz; + u64 addr; + + /* Read property 'reg' from the node */ + reg = ofnode_read_prop(node, "reg", &len); + if (!reg || len < sizeof(fdt32_t) * 4 || len % sizeof(fdt32_t)) + return; + + /* Combine hi/lo for size and address (typically 64-bit) */ + sz = ((u64)fdt32_to_cpu(reg[2]) << 32) | fdt32_to_cpu(reg[3]); + addr = ((u64)fdt32_to_cpu(reg[0]) << 32) | fdt32_to_cpu(reg[1]); + + t->ext_start_addr = cpu_to_le64(addr); + t->ext_end_addr = cpu_to_le64(addr + sz - 1); + + /* If address range fits in 32-bit, populate legacy fields */ + if ((addr + sz - 1) <= 0xFFFFFFFFULL) { + t->start_addr = cpu_to_le32((u32)addr); + t->end_addr = cpu_to_le32((u32)(addr + sz - 1)); + } else { + t->start_addr = cpu_to_le32(0xFFFFFFFF); + t->end_addr = cpu_to_le32(0xFFFFFFFF); + } +} + +static int +smbios_write_type19_from_memctrl_node(ulong *current, int handle, + struct smbios_ctx *ctx, int idx, + u64 base, u64 sz) +{ + struct smbios_type19 *t; + int len; + u8 *eos_addr; + void *hdl; + size_t hdl_size; + + len = sizeof(*t); + t = map_sysmem(*current, len); + memset(t, 0, len); + + fill_smbios_header(t, SMBIOS_MEMORY_ARRAY_MAPPED_ADDRESS, len, handle); + + /* eos is at the end of the structure */ + eos_addr = (u8 *)t + len - sizeof(t->eos); + smbios_set_eos(ctx, eos_addr); + + /* Read the memory array handles */ + if (!sysinfo_get_data(ctx->dev, SYSID_SM_MEMARRAY_HANDLE, &hdl, + &hdl_size) && + hdl_size == SYSINFO_MEM_HANDLE_MAX * sizeof(u16)) + t->mem_array_hdl = *((u16 *)hdl + idx); + + t->ext_start_addr = cpu_to_le64(base); + t->ext_end_addr = cpu_to_le64(base + sz - 1); + + if ((base + sz - 1) <= 0xFFFFFFFFULL) { + t->start_addr = cpu_to_le32((u32)base); + t->end_addr = cpu_to_le32((u32)(base + sz - 1)); + } else { + t->start_addr = cpu_to_le32(0xFFFFFFFF); + t->end_addr = cpu_to_le32(0xFFFFFFFF); + } + + /* Write other general fields */ + smbios_pop_type19_general_si(ctx, t); + + len = t->hdr.length + smbios_string_table_len(ctx); + *current += len; + unmap_sysmem(t); + + return len; +} + +static int smbios_write_type19_mem(ulong *current, int handle, + struct smbios_ctx *ctx, int idx, + int type) +{ + struct smbios_type19 *t; + int len; + u8 *eos_addr; + void *hdl; + size_t hdl_size; + + len = sizeof(*t); + t = map_sysmem(*current, len); + memset(t, 0, len); + + fill_smbios_header(t, SMBIOS_MEMORY_ARRAY_MAPPED_ADDRESS, len, handle); + + /* eos is at the end of the structure */ + eos_addr = (u8 *)t + len - sizeof(t->eos); + smbios_set_eos(ctx, eos_addr); + + if (type == SMBIOS_MEM_CUSTOM) { + smbios_pop_type19_addr_si(ctx, t); + t->mem_array_hdl = smbios_get_val_si(ctx, "memory-array-handle", + SYSID_NONE, 0); + } else if (type == SMBIOS_MEM_FDT_MEM_NODE) { + smbios_pop_type19_addr_from_memory_node(ctx->node, t); + /* Read the memory array handles */ + if (!sysinfo_get_data(ctx->dev, SYSID_SM_MEMARRAY_HANDLE, &hdl, + &hdl_size) && + hdl_size == SYSINFO_MEM_HANDLE_MAX * sizeof(u16)) + t->mem_array_hdl = *((u16 *)hdl + idx); + } + + /* Write other general fields */ + smbios_pop_type19_general_si(ctx, t); + + len = t->hdr.length + smbios_string_table_len(ctx); + *current += len; + unmap_sysmem(t); + + return len; +} + +static int smbios_write_type19(ulong *current, int *handle, + struct smbios_ctx *ctx) +{ + return smbios_write_type1719(current, handle, ctx, + smbios_write_type19_mem, + smbios_write_type19_from_memctrl_node); +} + #endif /* #if IS_ENABLED(CONFIG_GENERATE_SMBIOS_TABLE_VERBOSE) */ -static int smbios_write_type32(ulong *current, int handle, +static int smbios_write_type32(ulong *current, int *handle, struct smbios_ctx *ctx) { struct smbios_type32 *t; @@ -866,7 +1966,7 @@ static int smbios_write_type32(ulong *current, int handle, t = map_sysmem(*current, len); memset(t, 0, len); - fill_smbios_header(t, SMBIOS_SYSTEM_BOOT_INFORMATION, len, handle); + fill_smbios_header(t, SMBIOS_SYSTEM_BOOT_INFORMATION, len, *handle); smbios_set_eos(ctx, t->eos); *current += len; @@ -875,7 +1975,7 @@ static int smbios_write_type32(ulong *current, int handle, return len; } -static int smbios_write_type127(ulong *current, int handle, +static int smbios_write_type127(ulong *current, int *handle, struct smbios_ctx *ctx) { struct smbios_type127 *t; @@ -883,7 +1983,7 @@ static int smbios_write_type127(ulong *current, int handle, t = map_sysmem(*current, len); memset(t, 0, len); - fill_smbios_header(t, SMBIOS_END_OF_TABLE, len, handle); + fill_smbios_header(t, SMBIOS_END_OF_TABLE, len, *handle); *current += len; unmap_sysmem(t); @@ -902,6 +2002,12 @@ 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"}, + { smbios_write_type16, "memory-array"}, + { smbios_write_type17, "memory-device"}, + { smbios_write_type19, "memory-array-mapped-address"}, +#endif { smbios_write_type32, }, { smbios_write_type127 }, }; @@ -954,7 +2060,8 @@ ulong write_smbios_table(ulong addr) ctx.node = ofnode_find_subnode(parent_node, method->subnode_name); } - len += method->write((ulong *)&addr, handle++, &ctx); + len += method->write((ulong *)&addr, &handle, &ctx); + handle++; } /*