diff options
author | Subrata Banik <subratabanik@google.com> | 2024-10-29 02:11:56 +0530 |
---|---|---|
committer | Subrata Banik <subratabanik@google.com> | 2024-10-30 07:22:23 +0000 |
commit | bc8cc460550364c16ae00b00e19fd8c033ec175c (patch) | |
tree | ed56e4b04be7c8b46720b0dfd7b08e2434b40622 /src/soc/intel | |
parent | 59bf7dd62fa121f6d98143a93dd48f745e404165 (diff) |
soc/intel/pantherlake: Populate and pass DRAM info for SMBIOS
This patch implements the `save_dimm_info()` API to populate and pass
DRAM-related information to the next stage. This information
is used to generate the SMBIOS memory table, providing details about
installed DIMMs.
This addresses the issue where SMBIOS lacked detailed DIMM information.
Verified that `dmidecode` correctly dumps the DIMM information from the
SMBIOS table after this change.
BUG=b:376103463
TEST=Built and booted successfully. Verified DIMM info in SMBIOS using
`dmidecode`.
> dmidecode -t 17
```
Getting SMBIOS data from sysfs.
SMBIOS 3.0 present.
Handle 0x000B, DMI type 17, 40 bytes
Memory Device
Array Handle: 0x000A
Error Information Handle: Not Provided
Total Width: 16 bits
Data Width: 16 bits
Size: 2 GB
Form Factor: Row Of Chips
Set: None
Locator: Channel-0-DIMM-0
Bank Locator: BANK 0
Type: LPDDR5
Type Detail: Unknown Synchronous
Speed: 6400 MT/s
Manufacturer: Hynix
Serial Number: 00000000
Asset Tag: Channel-0-DIMM-0-AssetTag
Part Number: H58G56BK7BX068
Rank: 1
Configured Memory Speed: 6400 MT/s
Minimum Voltage: 0.5 V
Maximum Voltage: 0.5 V
Configured Voltage: 0.5 V
...
...
Handle 0x0012, DMI type 17, 40 bytes
Memory Device
Array Handle: 0x000A
Error Information Handle: Not Provided
Total Width: 16 bits
Data Width: 16 bits
Size: 2 GB
Form Factor: Row Of Chips
Set: None
Locator: Channel-3-DIMM-0
Bank Locator: BANK 0
Type: LPDDR5
Type Detail: Unknown Synchronous
Speed: 6400 MT/s
Manufacturer: Hynix
Serial Number: 00000000
Asset Tag: Channel-3-DIMM-0-AssetTag
Part Number: H58G56BK7BX068
Rank: 1
Configured Memory Speed: 6400 MT/s
Minimum Voltage: 0.5 V
Maximum Voltage: 0.5 V
Configured Voltage: 0.5 V
```
Change-Id: I3b942610272de401589ee0463de9cd0985974774
Signed-off-by: Subrata Banik <subratabanik@google.com>
Reviewed-on: https://review.coreboot.org/c/coreboot/+/84903
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Pranava Y N <pranavayn@google.com>
Reviewed-by: Kapil Porwal <kapilporwal@google.com>
Diffstat (limited to 'src/soc/intel')
-rw-r--r-- | src/soc/intel/pantherlake/romstage/romstage.c | 99 |
1 files changed, 98 insertions, 1 deletions
diff --git a/src/soc/intel/pantherlake/romstage/romstage.c b/src/soc/intel/pantherlake/romstage/romstage.c index a05adc455e..46be7b96f9 100644 --- a/src/soc/intel/pantherlake/romstage/romstage.c +++ b/src/soc/intel/pantherlake/romstage/romstage.c @@ -18,10 +18,107 @@ #include <string.h> #include <timestamp.h> +#define FSP_SMBIOS_MEMORY_INFO_GUID \ +{ \ + 0xd4, 0x71, 0x20, 0x9b, 0x54, 0xb0, 0x0c, 0x4e, \ + 0x8d, 0x09, 0x11, 0xcf, 0x8b, 0x9f, 0x03, 0x23 \ +} + /* Save the DIMM information for SMBIOS table 17 */ static void save_dimm_info(void) { - /* Update after FSP is released externally released. */ + int node, channel, dimm, dimm_max, index; + size_t hob_size; + const CONTROLLER_INFO *ctrlr_info; + const CHANNEL_INFO *channel_info; + const DIMM_INFO *src_dimm; + struct dimm_info *dest_dimm; + struct memory_info *mem_info; + const MEMORY_INFO_DATA_HOB *meminfo_hob; + const uint8_t smbios_memory_info_guid[sizeof(EFI_GUID)] = FSP_SMBIOS_MEMORY_INFO_GUID; + const uint8_t *serial_num; + const char *dram_part_num = NULL; + size_t dram_part_num_len = 0; + + /* Locate the memory info HOB, presence validated by raminit */ + meminfo_hob = fsp_find_extension_hob_by_guid( + smbios_memory_info_guid, + &hob_size); + if (!meminfo_hob || hob_size == 0) { + printk(BIOS_ERR, "SMBIOS MEMORY_INFO_DATA_HOB not found\n"); + return; + } + + /* + * Allocate CBMEM area for DIMM information used to populate SMBIOS + * table 17 + */ + mem_info = cbmem_add(CBMEM_ID_MEMINFO, sizeof(*mem_info)); + if (!mem_info) { + printk(BIOS_ERR, "CBMEM entry for DIMM info missing\n"); + return; + } + memset(mem_info, 0, sizeof(*mem_info)); + + /* Allow mainboard to override DRAM part number. */ + dram_part_num = mainboard_get_dram_part_num(); + if (dram_part_num) + dram_part_num_len = strlen(dram_part_num); + + /* Save available DIMM information */ + index = 0; + dimm_max = ARRAY_SIZE(mem_info->dimm); + for (node = 0; node < MAX_NODE; node++) { + ctrlr_info = &meminfo_hob->Controller[node]; + for (channel = 0; channel < MAX_CH && index < dimm_max; channel++) { + channel_info = &ctrlr_info->ChannelInfo[channel]; + if (channel_info->Status != CHANNEL_PRESENT) + continue; + + for (dimm = 0; dimm < MAX_DIMM && index < dimm_max; dimm++) { + src_dimm = &channel_info->DimmInfo[dimm]; + dest_dimm = &mem_info->dimm[index]; + if (src_dimm->Status != DIMM_PRESENT) + continue; + + /* If there is no DRAM part number overridden by + * mainboard then use original one. */ + if (!dram_part_num) { + dram_part_num_len = sizeof(src_dimm->ModulePartNum); + dram_part_num = (const char *) + &src_dimm->ModulePartNum[0]; + } + + uint8_t memProfNum = meminfo_hob->MemoryProfile; + serial_num = src_dimm->SpdSave + SPD_SAVE_OFFSET_SERIAL; + + /* Populate the DIMM information */ + dimm_info_fill(dest_dimm, + src_dimm->DimmCapacity, + meminfo_hob->MemoryType, + meminfo_hob->ConfiguredMemoryClockSpeed, + src_dimm->RankInDimm, + channel_info->ChannelId, + src_dimm->DimmId, + dram_part_num, + dram_part_num_len, + serial_num, + meminfo_hob->DataWidth, + meminfo_hob->VddVoltage[memProfNum], + meminfo_hob->EccSupport, + src_dimm->MfgId, + src_dimm->SpdModuleType, + node, + meminfo_hob->MaximumMemoryClockSpeed); + index++; + } + } + } + mem_info->dimm_cnt = index; + if (mem_info->dimm_cnt == 0) + printk(BIOS_ERR, "No DIMMs found\n"); + else + printk(BIOS_DEBUG, "%d DIMMs found\n", mem_info->dimm_cnt); } void mainboard_romstage_entry(void) |