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>
This commit is contained in:
Subrata Banik 2024-10-29 02:11:56 +05:30
commit bc8cc46055

View file

@ -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)