smbios: add support for dynamic generation of Type 17 table

This commit implements SMBIOS Type 17 (Memory Device) generation with a
hybrid approach supporting both:

1. Explicit definition via Device Tree 'smbios' node:
   Child node under '/smbios/smbios/memory-device' will be used to
   populate as individual Type 17 structure directly.
   - Properties follow SMBIOS field names with lowercase letters and
     hyphen-separated words (e.g., 'physical-memory-array-handle',
     ' memory-error-information-handle', 'configured-memory-speed', etc.).
   - This method supports precise platform-defined overrides and system
     descriptions.

2. Fallback to automatic DT-based discovery:
   If child node under '/smbios/smbios/memory-device' does not exist,
   the implementation will:
   - Scan all top-level 'memory@' nodes to populate Type 17 structure with
     inferred size and location data.
   - Scan nodes named or marked as 'memory-controller' and parse
     associated 'dimm@' subnodes (if present) to extract DIMM sizes and
     map them accordingly.

This dual-mode support enables flexible firmware SMBIOS reporting while
aligning with spec-compliant naming and runtime-detected memory topology.

Type 17 support is under GENERATE_SMBIOS_TABLE_VERBOSE to avoid
increasing rom size for those platforms which only require basic SMBIOS
support.

Signed-off-by: Raymond Mao <raymondmaoca@gmail.com>
Tested-by: Ilias Apalodimas <ilias.apalodimas@linaro.org>
This commit is contained in:
Raymond Mao
2026-02-13 17:52:49 -05:00
committed by Tom Rini
parent 374896158b
commit 23674dee60
5 changed files with 677 additions and 0 deletions

View File

@@ -194,6 +194,74 @@ static const struct str_lookup_table ma_err_corr_strings[] = {
{ 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
*
@@ -557,6 +625,61 @@ static void smbios_print_type16(struct smbios_type16 *table)
printf("\tExtended Maximum Capacity: 0x%016llx\n", table->ext_max_cap);
}
static void smbios_print_type17(struct smbios_type17 *table)
{
printf("Memory Device:\n");
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);
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);
printf("\tAttributes: 0x%04x\n", table->attributes);
printf("\tExtended Size: 0x%08x\n", table->ext_size);
printf("\tConfigured Memory Speed: 0x%04x\n", table->config_mem_speed);
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);
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);
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_type127(struct smbios_type127 *table)
{
printf("End Of Table\n");
@@ -642,6 +765,9 @@ static int do_smbios(struct cmd_tbl *cmdtp, int flag, int argc,
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_END_OF_TABLE:
smbios_print_type127((struct smbios_type127 *)pos);
break;