blob: 7fd1cf50c856e2e977f9ba7bf21076a1ada83328 [file] [log] [blame]
/* SPDX-License-Identifier: GPL-2.0-only */
#include <stddef.h>
#include <acpi/acpi.h>
#include <assert.h>
#include <console/console.h>
#include <cbmem.h>
#include <cf9_reset.h>
#include <cpu/intel/microcode.h>
#include <ec/google/chromeec/ec.h>
#include <ec/google/chromeec/ec_commands.h>
#include <elog.h>
#include <fsp/romstage.h>
#include <mrc_cache.h>
#include <program_loading.h>
#include <romstage_handoff.h>
#include <smbios.h>
#include <stage_cache.h>
#include <string.h>
#include <timestamp.h>
static void raminit_common(struct romstage_params *params)
{
bool s3wake;
size_t mrc_size;
post_code(0x32);
timestamp_add_now(TS_INITRAM_START);
s3wake = params->power_state->prev_sleep_state == ACPI_S3;
elog_boot_notify(s3wake);
post_code(0x33);
/* Check recovery and MRC cache */
params->saved_data_size = 0;
params->saved_data = NULL;
if (!params->disable_saved_data) {
/* Assume boot device is memory mapped. */
assert(CONFIG(BOOT_DEVICE_MEMORY_MAPPED));
params->saved_data = NULL;
if (CONFIG(CACHE_MRC_SETTINGS))
params->saved_data =
mrc_cache_current_mmap_leak(MRC_TRAINING_DATA,
params->fsp_version,
&mrc_size);
if (params->saved_data) {
/* MRC cache found */
params->saved_data_size = mrc_size;
} else if (s3wake) {
/* Waking from S3 and no cache. */
printk(BIOS_DEBUG,
"No MRC cache "
"found in S3 resume path.\n");
post_code(POST_RESUME_FAILURE);
/* FIXME: A "system" reset is likely enough: */
full_reset();
} else {
printk(BIOS_DEBUG, "No MRC cache found.\n");
}
}
/* Initialize RAM */
raminit(params);
timestamp_add_now(TS_INITRAM_END);
/* Save MRC output */
if (CONFIG(CACHE_MRC_SETTINGS)) {
printk(BIOS_DEBUG, "MRC data at %p %zu bytes\n",
params->data_to_save, params->data_to_save_size);
if (!s3wake
&& (params->data_to_save_size != 0)
&& (params->data_to_save != NULL))
mrc_cache_stash_data(MRC_TRAINING_DATA,
params->fsp_version,
params->data_to_save,
params->data_to_save_size);
}
/* Save DIMM information */
if (!s3wake)
mainboard_save_dimm_info(params);
/* Create romstage handof information */
if (romstage_handoff_init(
params->power_state->prev_sleep_state == ACPI_S3) < 0)
/* FIXME: A "system" reset is likely enough: */
full_reset();
}
void cache_as_ram_stage_main(FSP_INFO_HEADER *fih)
{
struct romstage_params params = {
.chipset_context = fih,
};
post_code(0x30);
timestamp_add_now(TS_ROMSTAGE_START);
/* Display parameters */
if (!CONFIG(NO_ECAM_MMCONF_SUPPORT))
printk(BIOS_SPEW, "CONFIG_ECAM_MMCONF_BASE_ADDRESS: 0x%08x\n",
CONFIG_ECAM_MMCONF_BASE_ADDRESS);
printk(BIOS_INFO, "Using FSP 1.1\n");
/* Display FSP banner */
print_fsp_info(fih);
/* Stash FSP version. */
params.fsp_version = fsp_version(fih);
/* Get power state */
params.power_state = fill_power_state();
/* Board initialization before and after RAM is enabled */
mainboard_pre_raminit(&params);
post_code(0x31);
/* Initialize memory */
raminit_common(&params);
soc_after_ram_init(&params);
post_code(0x38);
}
/* Board initialization before and after RAM is enabled */
__weak void mainboard_pre_raminit(struct romstage_params *params)
{
}
/* Save the DIMM information for SMBIOS table 17 */
__weak void mainboard_save_dimm_info(
struct romstage_params *params)
{
int channel;
CHANNEL_INFO *channel_info;
int dimm;
DIMM_INFO *dimm_info;
int dimm_max;
void *hob_list_ptr;
EFI_HOB_GUID_TYPE *hob_ptr;
int index;
struct memory_info *mem_info;
FSP_SMBIOS_MEMORY_INFO *memory_info_hob;
const EFI_GUID memory_info_hob_guid = FSP_SMBIOS_MEMORY_INFO_GUID;
/* Locate the memory info HOB, presence validated by raminit */
hob_list_ptr = fsp_get_hob_list();
hob_ptr = get_next_guid_hob(&memory_info_hob_guid, hob_list_ptr);
memory_info_hob = (FSP_SMBIOS_MEMORY_INFO *)(hob_ptr + 1);
/* Display the data in the FSP_SMBIOS_MEMORY_INFO HOB */
if (CONFIG(DISPLAY_HOBS)) {
printk(BIOS_DEBUG, "FSP_SMBIOS_MEMORY_INFO HOB\n");
printk(BIOS_DEBUG, " 0x%02x: Revision\n",
memory_info_hob->Revision);
printk(BIOS_DEBUG, " 0x%02x: MemoryType\n",
memory_info_hob->MemoryType);
printk(BIOS_DEBUG, " %d: MemoryFrequencyInMHz\n",
memory_info_hob->MemoryFrequencyInMHz);
printk(BIOS_DEBUG, " %d: DataWidth in bits\n",
memory_info_hob->DataWidth);
printk(BIOS_DEBUG, " 0x%02x: ErrorCorrectionType\n",
memory_info_hob->ErrorCorrectionType);
printk(BIOS_DEBUG, " 0x%02x: ChannelCount\n",
memory_info_hob->ChannelCount);
for (channel = 0; channel < memory_info_hob->ChannelCount;
channel++) {
channel_info = &memory_info_hob->ChannelInfo[channel];
printk(BIOS_DEBUG, " Channel %d\n", channel);
printk(BIOS_DEBUG, " 0x%02x: ChannelId\n",
channel_info->ChannelId);
printk(BIOS_DEBUG, " 0x%02x: DimmCount\n",
channel_info->DimmCount);
for (dimm = 0; dimm < channel_info->DimmCount;
dimm++) {
dimm_info = &channel_info->DimmInfo[dimm];
printk(BIOS_DEBUG, " DIMM %d\n", dimm);
printk(BIOS_DEBUG, " 0x%02x: DimmId\n",
dimm_info->DimmId);
printk(BIOS_DEBUG, " %d: SizeInMb\n",
dimm_info->SizeInMb);
}
}
}
/*
* Allocate CBMEM area for DIMM information used to populate SMBIOS
* table 17
*/
mem_info = cbmem_add(CBMEM_ID_MEMINFO, sizeof(*mem_info));
printk(BIOS_DEBUG, "CBMEM entry for DIMM info: %p\n", mem_info);
if (mem_info == NULL)
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);
for (channel = 0; channel < memory_info_hob->ChannelCount; channel++) {
if (index >= dimm_max)
break;
channel_info = &memory_info_hob->ChannelInfo[channel];
for (dimm = 0; dimm < channel_info->DimmCount; dimm++) {
if (index >= dimm_max)
break;
dimm_info = &channel_info->DimmInfo[dimm];
/* Populate the DIMM information */
if (dimm_info->SizeInMb) {
mem_info->dimm[index].dimm_size =
dimm_info->SizeInMb;
mem_info->dimm[index].ddr_type =
memory_info_hob->MemoryType;
mem_info->dimm[index].ddr_frequency =
memory_info_hob->MemoryFrequencyInMHz;
mem_info->dimm[index].channel_num =
channel_info->ChannelId;
mem_info->dimm[index].dimm_num =
dimm_info->DimmId;
switch (memory_info_hob->DataWidth) {
default:
case 8:
mem_info->dimm[index].bus_width =
MEMORY_BUS_WIDTH_8;
break;
case 16:
mem_info->dimm[index].bus_width =
MEMORY_BUS_WIDTH_16;
break;
case 32:
mem_info->dimm[index].bus_width =
MEMORY_BUS_WIDTH_32;
break;
case 64:
mem_info->dimm[index].bus_width =
MEMORY_BUS_WIDTH_64;
break;
case 128:
mem_info->dimm[index].bus_width =
MEMORY_BUS_WIDTH_128;
break;
}
index++;
}
}
}
mem_info->dimm_cnt = index;
printk(BIOS_DEBUG, "%d DIMMs found\n", mem_info->dimm_cnt);
}