diff --git a/src/soc/intel/apollolake/Kconfig b/src/soc/intel/apollolake/Kconfig index d1d660bc78..092102cfbc 100644 --- a/src/soc/intel/apollolake/Kconfig +++ b/src/soc/intel/apollolake/Kconfig @@ -161,6 +161,10 @@ config CACHE_MRC_SETTINGS bool default y +config MRC_SETTINGS_VARIABLE_DATA + bool + default y + config FSP_M_ADDR hex default 0xfef40000 diff --git a/src/soc/intel/apollolake/romstage.c b/src/soc/intel/apollolake/romstage.c index d623913086..039b586263 100644 --- a/src/soc/intel/apollolake/romstage.c +++ b/src/soc/intel/apollolake/romstage.c @@ -32,6 +32,7 @@ #include #include #include +#include #include #include #include @@ -47,6 +48,13 @@ static struct chipset_power_state power_state CAR_GLOBAL; +static const uint8_t hob_variable_guid[16] = { + 0x7d, 0x14, 0x34, 0xa0, 0x0c, 0x69, 0x54, 0x41, + 0x8d, 0xe6, 0xc0, 0x44, 0x64, 0x1d, 0xe9, 0x42, +}; + +static uint32_t fsp_version CAR_GLOBAL; + /* High Performance Event Timer Configuration */ #define P2SB_HPTC 0x60 #define P2SB_HPTC_ADDRESS_ENABLE (1 << 7) @@ -170,7 +178,8 @@ asmlinkage void car_stage_entry(void) bool s3wake; struct chipset_power_state *ps = car_get_var_ptr(&power_state); void *smm_base; - size_t smm_size; + size_t smm_size, var_size; + const void *new_var_data; uintptr_t tseg_base; timestamp_add_now(TS_START_ROMSTAGE); @@ -188,6 +197,15 @@ asmlinkage void car_stage_entry(void) else printk(BIOS_DEBUG, "Punit failed to initialize properly\n"); + /* Stash variable MRC data and let cache system update it later */ + new_var_data = fsp_find_extension_hob_by_guid(hob_variable_guid, + &var_size); + if (new_var_data) + mrc_cache_stash_vardata(new_var_data, var_size, + car_get_var(fsp_version)); + else + printk(BIOS_ERR, "Failed to determine variable data\n"); + if (postcar_frame_init(&pcf, 1*KiB)) die("Unable to initialize postcar frame.\n"); @@ -239,6 +257,8 @@ static void fill_console_params(FSPM_UPD *mupd) void platform_fsp_memory_init_params_cb(FSPM_UPD *mupd, uint32_t version) { + const struct mrc_saved_data *msd; + fill_console_params(mupd); mainboard_memory_init_params(mupd); @@ -262,6 +282,23 @@ void platform_fsp_memory_init_params_cb(FSPM_UPD *mupd, uint32_t version) * skip HECI2 reset. */ mupd->FspmConfig.EnableS3Heci2 = 0; + + /* + * Apollolake splits MRC cache into two parts: constant and variable. + * The constant part is not expected to change often and variable is. + * Currently variable part consists of parameters that change on cold + * boots such as scrambler seed and some memory controller registers. + * Scrambler seed is vital for S3 resume case because attempt to use + * wrong/missing key renders DRAM contents useless. + */ + + if (mrc_cache_get_vardata(&msd, version) < 0) { + printk(BIOS_DEBUG, "MRC variable data missing/invalid\n"); + } else { + mupd->FspmConfig.VariableNvsBufferPtr = (void*) msd->data; + } + + car_set_var(fsp_version, version); } __attribute__ ((weak))