summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/soc/intel/skylake/romstage/romstage_fsp20.c79
1 files changed, 78 insertions, 1 deletions
diff --git a/src/soc/intel/skylake/romstage/romstage_fsp20.c b/src/soc/intel/skylake/romstage/romstage_fsp20.c
index a4bb6849e4..be71e58541 100644
--- a/src/soc/intel/skylake/romstage/romstage_fsp20.c
+++ b/src/soc/intel/skylake/romstage/romstage_fsp20.c
@@ -26,10 +26,13 @@
#include <device/pci_def.h>
#include <fsp/util.h>
#include <fsp/memmap.h>
+#include <memory_info.h>
+#include <soc/intel/common/smbios.h>
#include <soc/msr.h>
#include <soc/pci_devs.h>
#include <soc/pm.h>
#include <soc/romstage.h>
+#include <string.h>
#include <timestamp.h>
#include <vboot/vboot_common.h>
@@ -39,6 +42,79 @@
*/
#define ROMSTAGE_RAM_STACK_SIZE 0x5000
+#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)
+{
+ int 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 *memory_info_hob;
+ const uint8_t smbios_memory_info_guid[16] = FSP_SMBIOS_MEMORY_INFO_GUID;
+
+ /* Locate the memory info HOB, presence validated by raminit */
+ memory_info_hob =
+ fsp_find_extension_hob_by_guid(smbios_memory_info_guid,
+ &hob_size);
+ if (memory_info_hob == NULL) {
+ 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 == NULL) {
+ printk(BIOS_ERR, "CBMEM entry for DIMM info missing\n");
+ return;
+ }
+ memset(mem_info, 0, sizeof(*mem_info));
+
+ /* Describe the first N DIMMs in the system */
+ index = 0;
+ dimm_max = ARRAY_SIZE(mem_info->dimm);
+ ctrlr_info = &memory_info_hob->Controller[0];
+ for (channel = 0; channel < ctrlr_info->ChannelCount; channel++) {
+ if (index >= dimm_max)
+ break;
+ channel_info = &ctrlr_info->Channel[channel];
+ for (dimm = 0; dimm < channel_info->DimmCount; dimm++) {
+ if (index >= dimm_max)
+ break;
+ src_dimm = &channel_info->Dimm[dimm];
+ dest_dimm = &mem_info->dimm[index];
+
+ if (!src_dimm->DimmCapacity)
+ continue;
+
+ /* Populate the DIMM information */
+ dimm_info_fill(dest_dimm,
+ src_dimm->DimmCapacity,
+ memory_info_hob->DdrType,
+ memory_info_hob->Frequency,
+ channel_info->ChannelId,
+ src_dimm->DimmId,
+ (const char *)src_dimm->ModulePartNum,
+ sizeof(src_dimm->ModulePartNum),
+ memory_info_hob->DataWidth);
+ index++;
+ }
+ }
+ mem_info->dimm_cnt = index;
+ printk(BIOS_DEBUG, "%d DIMMs found\n", mem_info->dimm_cnt);
+}
+
asmlinkage void *car_stage_c_entry(void)
{
bool s3wake;
@@ -56,7 +132,8 @@ asmlinkage void *car_stage_c_entry(void)
s3wake = ps->prev_sleep_state == ACPI_S3;
fsp_memory_init(s3wake);
pmc_set_disb();
-
+ if (!s3wake)
+ save_dimm_info();
if (postcar_frame_init(&pcf, ROMSTAGE_RAM_STACK_SIZE))
die("Unable to initialize postcar frame.\n");