coreboot
coreboot is an Open Source project aimed at replacing the proprietary BIOS found in most computers.
romstage.c
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-only */
2 
3 #include <arch/romstage.h>
4 #include <cbmem.h>
5 #include <console/console.h>
6 #include <fsp/util.h>
7 #include <intelblocks/cfg.h>
8 #include <intelblocks/cse.h>
9 #include <intelblocks/pmclib.h>
10 #include <intelblocks/smbus.h>
11 #include <memory_info.h>
13 #include <soc/iomap.h>
14 #include <soc/pm.h>
15 #include <soc/romstage.h>
16 #include <soc/soc_chip.h>
17 #include <string.h>
18 
19 #define FSP_SMBIOS_MEMORY_INFO_GUID \
20 { \
21  0xd4, 0x71, 0x20, 0x9b, 0x54, 0xb0, 0x0c, 0x4e, \
22  0x8d, 0x09, 0x11, 0xcf, 0x8b, 0x9f, 0x03, 0x23 \
23 }
24 
25 /* Save the DIMM information for SMBIOS table 17 */
26 static void save_dimm_info(void)
27 {
28  int node, channel, dimm, dimm_max, index;
29  size_t hob_size;
30  const CONTROLLER_INFO *ctrlr_info;
31  const CHANNEL_INFO *channel_info;
32  const DIMM_INFO *src_dimm;
33  struct dimm_info *dest_dimm;
34  struct memory_info *mem_info;
35  const MEMORY_INFO_DATA_HOB *meminfo_hob;
38  const uint8_t *serial_num;
39  const char *dram_part_num = NULL;
40  size_t dram_part_num_len = 0;
41  bool is_dram_part_overridden = false;
42 
43  /* Locate the memory info HOB, presence validated by raminit */
44  meminfo_hob = fsp_find_extension_hob_by_guid(
46  &hob_size);
47  if (meminfo_hob == NULL || hob_size == 0) {
48  printk(BIOS_ERR, "SMBIOS MEMORY_INFO_DATA_HOB not found\n");
49  return;
50  }
51 
52  /*
53  * Allocate CBMEM area for DIMM information used to populate SMBIOS
54  * table 17
55  */
56  mem_info = cbmem_add(CBMEM_ID_MEMINFO, sizeof(*mem_info));
57  if (mem_info == NULL) {
58  printk(BIOS_ERR, "CBMEM entry for DIMM info missing\n");
59  return;
60  }
61  memset(mem_info, 0, sizeof(*mem_info));
62 
63  /* Allow mainboard to override DRAM part number. */
64  dram_part_num = mainboard_get_dram_part_num();
65  if (dram_part_num) {
66  dram_part_num_len = strlen(dram_part_num);
67  is_dram_part_overridden = true;
68  }
69 
70  /* Save available DIMM information */
71  index = 0;
72  dimm_max = ARRAY_SIZE(mem_info->dimm);
73  for (node = 0; node < MAX_NODE; node++) {
74  ctrlr_info = &meminfo_hob->Controller[node];
75  for (channel = 0; channel < MAX_CH && index < dimm_max;
76  channel++) {
77  channel_info = &ctrlr_info->ChannelInfo[channel];
78  if (channel_info->Status != CHANNEL_PRESENT)
79  continue;
80 
81  for (dimm = 0; dimm < MAX_DIMM && index < dimm_max;
82  dimm++) {
83  src_dimm = &channel_info->DimmInfo[dimm];
84  dest_dimm = &mem_info->dimm[index];
85  if (src_dimm->Status != DIMM_PRESENT)
86  continue;
87 
88  /* If there is no DRAM part number overridden by
89  * mainboard then use original one. */
90  if (!is_dram_part_overridden) {
91  dram_part_num_len = sizeof(src_dimm->ModulePartNum);
92  dram_part_num = (const char *)
93  &src_dimm->ModulePartNum[0];
94  }
95 
96  u8 memProfNum = meminfo_hob->MemoryProfile;
97  serial_num = src_dimm->SpdSave +
99 
100  /* Populate the DIMM information */
101  dimm_info_fill(dest_dimm,
102  src_dimm->DimmCapacity,
103  meminfo_hob->MemoryType,
104  meminfo_hob->ConfiguredMemoryClockSpeed,
105  src_dimm->RankInDimm,
106  channel_info->ChannelId,
107  src_dimm->DimmId,
108  dram_part_num,
109  dram_part_num_len,
110  serial_num,
111  meminfo_hob->DataWidth,
112  meminfo_hob->VddVoltage[memProfNum],
113  meminfo_hob->EccSupport,
114  src_dimm->MfgId,
115  src_dimm->SpdModuleType);
116  index++;
117  }
118  }
119  }
120  mem_info->dimm_cnt = index;
121  printk(BIOS_DEBUG, "%d DIMMs found\n", mem_info->dimm_cnt);
122 }
123 
125 {
126  bool s3wake;
128 
129  /* Program MCHBAR, DMIBAR, GDXBAR and EDRAMBAR */
131  /* Program SMBus base address and enable it */
133  /* initialize Heci interface */
135 
136  s3wake = pmc_fill_power_state(ps) == ACPI_S3;
137  fsp_memory_init(s3wake);
138  pmc_set_disb();
139  if (!s3wake) {
140  /*
141  * cse_fw_sync() must be called after DRAM initialization as
142  * HMRFPO_ENABLE HECI command (which is used by cse_fw_sync())
143  * is expected to be executed after DRAM initialization.
144  */
145 
146  if (CONFIG(SOC_INTEL_CSE_LITE_SKU))
147  cse_fw_sync();
148 
149  save_dimm_info();
150  }
151 
152 }
void pmc_set_disb(void)
Definition: pmutil.c:121
void * memset(void *dstpp, int c, size_t len)
Definition: memset.c:12
#define ARRAY_SIZE(a)
Definition: helpers.h:12
void * cbmem_add(u32 id, u64 size)
Definition: imd_cbmem.c:144
#define CBMEM_ID_MEMINFO
Definition: cbmem_id.h:33
void heci_init(uintptr_t tempbar)
Definition: cse.c:92
#define printk(level,...)
Definition: stdlib.h:16
void cse_fw_sync(void)
Definition: cse_lite.c:1042
static const uint8_t smbios_memory_info_guid[16]
Definition: hob_display.c:55
@ CONFIG
Definition: dsi_common.h:201
void fsp_memory_init(bool s3wake)
Definition: memory_init.c:350
const void * fsp_find_extension_hob_by_guid(const uint8_t *guid, size_t *size)
@ ACPI_S3
Definition: acpi.h:1383
#define HECI1_BASE_ADDRESS
Definition: iomap.h:77
#define BIOS_DEBUG
BIOS_DEBUG - Verbose output.
Definition: loglevel.h:128
#define BIOS_ERR
BIOS_ERR - System in incomplete state.
Definition: loglevel.h:72
void mainboard_romstage_entry(void)
Definition: romstage.c:6
const char * mainboard_get_dram_part_num(void)
Definition: spd_bin.c:21
void systemagent_early_init(void)
Definition: early_init.c:151
int pmc_fill_power_state(struct chipset_power_state *ps)
Definition: pmclib.c:437
struct chipset_power_state * pmc_get_power_state(void)
Definition: pmclib.c:58
void smbus_common_init(void)
Definition: smbus_early.c:11
void dimm_info_fill(struct dimm_info *dimm, u32 dimm_capacity, u8 ddr_type, u32 frequency, u8 rank_per_dimm, u8 channel_id, u8 dimm_id, const char *module_part_num, size_t module_part_number_size, const u8 *module_serial_num, u16 data_width, u32 vdd_voltage, bool ecc_support, u16 mod_id, u8 mod_type)
Definition: smbios.c:13
#define SPD_SAVE_OFFSET_SERIAL
Definition: smbios.h:10
@ CHANNEL_PRESENT
Definition: romstage.c:30
static void save_dimm_info(void)
Definition: romstage.c:26
#define FSP_SMBIOS_MEMORY_INFO_GUID
Definition: romstage.c:19
#define NULL
Definition: stddef.h:19
uint8_t u8
Definition: stdint.h:45
unsigned char uint8_t
Definition: stdint.h:8
size_t strlen(const char *src)
Definition: string.c:42
If this table is filled and put in CBMEM, then these info in CBMEM will be used to generate smbios ty...
Definition: memory_info.h:19
struct dimm_info dimm[DIMM_INFO_TOTAL]
Definition: memory_info.h:110
uint8_t dimm_cnt
Definition: memory_info.h:109