mirror of
https://source.denx.de/u-boot/u-boot.git
synced 2026-06-02 09:46:37 +03:00
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:
@@ -83,6 +83,9 @@
|
||||
|
||||
memory-array {
|
||||
};
|
||||
|
||||
memory-device {
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
126
cmd/smbios.c
126
cmd/smbios.c
@@ -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;
|
||||
|
||||
@@ -327,6 +327,51 @@ struct __packed smbios_type16 {
|
||||
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_type32 {
|
||||
u8 type;
|
||||
u8 length;
|
||||
|
||||
@@ -309,4 +309,131 @@
|
||||
#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
|
||||
|
||||
#endif /* _SMBIOS_DEF_H_ */
|
||||
|
||||
376
lib/smbios.c
376
lib/smbios.c
@@ -135,6 +135,14 @@ 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
|
||||
*
|
||||
@@ -1432,6 +1440,373 @@ static int smbios_write_type16(ulong *current, int *handle,
|
||||
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: <hi lo> 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);
|
||||
}
|
||||
|
||||
#endif /* #if IS_ENABLED(CONFIG_GENERATE_SMBIOS_TABLE_VERBOSE) */
|
||||
|
||||
static int smbios_write_type32(ulong *current, int *handle,
|
||||
@@ -1481,6 +1856,7 @@ static struct smbios_write_method smbios_write_funcs[] = {
|
||||
#if IS_ENABLED(CONFIG_GENERATE_SMBIOS_TABLE_VERBOSE)
|
||||
{ smbios_write_type9, "system-slot"},
|
||||
{ smbios_write_type16, "memory-array"},
|
||||
{ smbios_write_type17, "memory-device"},
|
||||
#endif
|
||||
{ smbios_write_type32, },
|
||||
{ smbios_write_type127 },
|
||||
|
||||
Reference in New Issue
Block a user