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/pci_devs.h>
15 #include <soc/pm.h>
16 #include <soc/romstage.h>
17 #include <soc/soc_chip.h>
18 #include <string.h>
19 
20 #define FSP_SMBIOS_MEMORY_INFO_GUID \
21 { \
22  0xd4, 0x71, 0x20, 0x9b, 0x54, 0xb0, 0x0c, 0x4e, \
23  0x8d, 0x09, 0x11, 0xcf, 0x8b, 0x9f, 0x03, 0x23 \
24 }
25 
26 /* Memory Channel Present Status */
27 enum {
31 };
32 
33 /* Save the DIMM information for SMBIOS table 17 */
34 static void save_dimm_info(void)
35 {
36  int channel, dimm, dimm_max, index;
37  size_t hob_size;
38  const CONTROLLER_INFO *ctrlr_info;
39  const CHANNEL_INFO *channel_info;
40  const DIMM_INFO *src_dimm;
41  struct dimm_info *dest_dimm;
42  struct memory_info *mem_info;
43  const MEMORY_INFO_DATA_HOB *memory_info_hob;
46 
47  /* Locate the memory info HOB, presence validated by raminit */
48  memory_info_hob = fsp_find_extension_hob_by_guid(
50  &hob_size);
51  if (memory_info_hob == NULL || hob_size == 0) {
52  printk(BIOS_ERR, "SMBIOS MEMORY_INFO_DATA_HOB not found\n");
53  return;
54  }
55 
56  /*
57  * Allocate CBMEM area for DIMM information used to populate SMBIOS
58  * table 17
59  */
60  mem_info = cbmem_add(CBMEM_ID_MEMINFO, sizeof(*mem_info));
61  if (mem_info == NULL) {
62  printk(BIOS_ERR, "CBMEM entry for DIMM info missing\n");
63  return;
64  }
65  memset(mem_info, 0, sizeof(*mem_info));
66 
67  /* Describe the first N DIMMs in the system */
68  index = 0;
69  dimm_max = ARRAY_SIZE(mem_info->dimm);
70  ctrlr_info = &memory_info_hob->Controller[0];
71  for (channel = 0; channel < MAX_CH && index < dimm_max; channel++) {
72  channel_info = &ctrlr_info->ChannelInfo[channel];
73  if (channel_info->Status != CHANNEL_PRESENT)
74  continue;
75  for (dimm = 0; dimm < MAX_DIMM && index < dimm_max; dimm++) {
76  src_dimm = &channel_info->DimmInfo[dimm];
77  dest_dimm = &mem_info->dimm[index];
78 
79  if (src_dimm->Status != DIMM_PRESENT)
80  continue;
81 
82  u8 memProfNum = memory_info_hob->MemoryProfile;
83 
84  /* Populate the DIMM information */
85  dimm_info_fill(dest_dimm,
86  src_dimm->DimmCapacity,
87  memory_info_hob->MemoryType,
88  memory_info_hob->ConfiguredMemoryClockSpeed,
89  src_dimm->RankInDimm,
90  channel_info->ChannelId,
91  src_dimm->DimmId,
92  (const char *)src_dimm->ModulePartNum,
93  sizeof(src_dimm->ModulePartNum),
94  src_dimm->SpdSave + SPD_SAVE_OFFSET_SERIAL,
95  memory_info_hob->DataWidth,
96  memory_info_hob->VddVoltage[memProfNum],
97  memory_info_hob->EccSupport,
98  src_dimm->MfgId,
99  src_dimm->SpdModuleType);
100  index++;
101  }
102  }
103  mem_info->dimm_cnt = index;
104  printk(BIOS_DEBUG, "%d DIMMs found\n", mem_info->dimm_cnt);
105 }
106 
108 {
109  bool s3wake;
111 
112  /* Program MCHBAR, DMIBAR, GDXBAR and EDRAMBAR */
114  /* Program SMBus base address and enable it */
116  /* initialize Heci interface */
118 
119  s3wake = pmc_fill_power_state(ps) == ACPI_S3;
120  fsp_memory_init(s3wake);
121  pmc_set_disb();
122  if (!s3wake)
123  save_dimm_info();
124 }
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
static const uint8_t smbios_memory_info_guid[16]
Definition: hob_display.c:55
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
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_NOT_PRESENT
Definition: romstage.c:28
@ CHANNEL_DISABLED
Definition: romstage.c:29
@ CHANNEL_PRESENT
Definition: romstage.c:30
static void save_dimm_info(void)
Definition: romstage.c:34
#define FSP_SMBIOS_MEMORY_INFO_GUID
Definition: romstage.c:20
#define NULL
Definition: stddef.h:19
uint8_t u8
Definition: stdint.h:45
unsigned char uint8_t
Definition: stdint.h:8
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