From b4302504e3770001bf267e0a58fa4dc7f17f6871 Mon Sep 17 00:00:00 2001 From: Aaron Durbin Date: Sun, 17 Jul 2016 17:04:37 -0500 Subject: drivers/intel/fsp2_0: implement common memory_init() tasks Instead of performing the same tasks in the chipset code move the common sequences into the FSP 2.0 driver. This handles the S3 paths as well as saving and restoring the memory data. The chipset code can always override the settings if needed. BUG=chrome-os-partner:52679 Change-Id: I098bf95139a0360f028a50aa50d16d264bede386 Signed-off-by: Aaron Durbin Reviewed-on: https://review.coreboot.org/15739 Tested-by: build bot (Jenkins) Reviewed-by: Furquan Shaikh --- src/drivers/intel/fsp2_0/include/fsp/api.h | 12 +--- src/drivers/intel/fsp2_0/memory_init.c | 101 +++++++++++++++++++++++++++-- 2 files changed, 97 insertions(+), 16 deletions(-) (limited to 'src/drivers/intel') diff --git a/src/drivers/intel/fsp2_0/include/fsp/api.h b/src/drivers/intel/fsp2_0/include/fsp/api.h index aa45d97876..9f8aae7f80 100644 --- a/src/drivers/intel/fsp2_0/include/fsp/api.h +++ b/src/drivers/intel/fsp2_0/include/fsp/api.h @@ -58,7 +58,7 @@ enum fsp_notify_phase { /* Main FSP stages */ -enum fsp_status fsp_memory_init(void **hob_list, struct range_entry *r); +enum fsp_status fsp_memory_init(struct range_entry *r, bool s3wake); enum fsp_status fsp_silicon_init(struct range_entry *r); enum fsp_status fsp_notify(enum fsp_notify_phase phase); @@ -74,24 +74,18 @@ void platform_fsp_silicon_init_params_cb(struct FSPS_UPD *supd); * points and map 1:1 to the FSP entry points of the same name. * * ### fsp_memory_init(): - * - hob_list: retuns a pointer to the HOB storage area created by FSP * - r: memory range that the binary is allowed to be loaded into + * - s3wake: boolean indicating if the system is waking from resume * * This function is responsible for loading and executing the memory * initialization code from the FSP-M binary. It expects this binary to reside * in cbfs as FSP_M_FILE. * - * The function takes one parameter, which is described below, but does not + * The function takes two parameters, which are described above, but does not * take in memory parameters as an argument. The memory parameters can be filled * in with platform_fsp_memory_init_params_cb(). This is a callback symbol * that fsp_memory_init() will call. The platform must provide this symbol. * - * FSP returns information about the memory layout in a series of structures - * called hand-off-blocks (HOB). The "hob_list" output parameter will point to - * the start of the HOB list. The fsp reserved region will also be described by - * one of the HOBs. For more information on parsing these structures, see - * fsp/util.h - * * * ### fsp_silicon_init(): * - r: memory range that the binary is allowed to be loaded into diff --git a/src/drivers/intel/fsp2_0/memory_init.c b/src/drivers/intel/fsp2_0/memory_init.c index 5363fdd380..700d40fa7f 100644 --- a/src/drivers/intel/fsp2_0/memory_init.c +++ b/src/drivers/intel/fsp2_0/memory_init.c @@ -13,23 +13,103 @@ #include #include +#include #include #include #include #include #include +#include +#include +#include #include #include typedef asmlinkage enum fsp_status (*fsp_memory_init_fn) (void *raminit_upd, void **hob_list); -static enum fsp_status do_fsp_memory_init(void **hob_list_ptr, - struct fsp_header *hdr) +static enum fsp_status do_fsp_post_memory_init(void *hob_list_ptr, bool s3wake) +{ + struct range_entry fsp_mem; + size_t mrc_data_size; + const void *mrc_data; + struct romstage_handoff *handoff; + + fsp_find_reserved_memory(&fsp_mem, hob_list_ptr); + + /* initialize cbmem by adding FSP reserved memory first thing */ + if (!s3wake) { + cbmem_initialize_empty_id_size(CBMEM_ID_FSP_RESERVED_MEMORY, + range_entry_size(&fsp_mem)); + } else if (cbmem_initialize_id_size(CBMEM_ID_FSP_RESERVED_MEMORY, + range_entry_size(&fsp_mem))) { + if (IS_ENABLED(CONFIG_HAVE_ACPI_RESUME)) { + printk(BIOS_DEBUG, "Failed to recover CBMEM in S3 resume.\n"); + /* Failed S3 resume, reset to come up cleanly */ + hard_reset(); + } + } + + /* make sure FSP memory is reserved in cbmem */ + if (range_entry_base(&fsp_mem) != + (uintptr_t)cbmem_find(CBMEM_ID_FSP_RESERVED_MEMORY)) + die("Failed to accommodate FSP reserved memory request"); + + /* Now that CBMEM is up, save the list so ramstage can use it */ + fsp_save_hob_list(hob_list_ptr); + + /* Save MRC Data to CBMEM */ + if (IS_ENABLED(CONFIG_CACHE_MRC_SETTINGS) && !s3wake) { + mrc_data = fsp_find_nv_storage_data(&mrc_data_size); + if (mrc_data && mrc_cache_stash_data(mrc_data, mrc_data_size) < 0) + printk(BIOS_ERR, "Failed to stash MRC data\n"); + } + + /* Create romstage handof information */ + handoff = romstage_handoff_find_or_add(); + if (handoff != NULL) + handoff->s3_resume = s3wake; + else + printk(BIOS_DEBUG, "Romstage handoff structure not added!\n"); + + return FSP_SUCCESS; +} + +static void fsp_fill_common_arch_params(struct FSPM_ARCH_UPD *arch_upd, + bool s3wake) +{ + const struct mrc_saved_data *mrc_cache; + + /* + * FSPM_UPD passed here is populated with default values provided by + * the blob itself. We let FSPM use top of CAR region of the size it + * requests. + * TODO: add checks to avoid overlap/conflict of CAR usage. + */ + arch_upd->StackBase = _car_region_end - arch_upd->StackSize; + + arch_upd->BootMode = FSP_BOOT_WITH_FULL_CONFIGURATION; + + if (IS_ENABLED(CONFIG_CACHE_MRC_SETTINGS)) { + if (!mrc_cache_get_current_with_version(&mrc_cache, 0)) { + /* MRC cache found */ + arch_upd->NvsBufferPtr = (void *)mrc_cache->data; + arch_upd->BootMode = s3wake ? + FSP_BOOT_ON_S3_RESUME: + FSP_BOOT_ASSUMING_NO_CONFIGURATION_CHANGES; + printk(BIOS_DEBUG, "MRC cache found, size %x bootmode:%d\n", + mrc_cache->size, arch_upd->BootMode); + } else + printk(BIOS_DEBUG, "MRC cache was not found\n"); + } +} + +static enum fsp_status do_fsp_memory_init(struct fsp_header *hdr, bool s3wake) { enum fsp_status status; fsp_memory_init_fn fsp_raminit; struct FSPM_UPD fspm_upd, *upd; + void *hob_list_ptr; post_code(0x34); @@ -46,6 +126,9 @@ static enum fsp_status do_fsp_memory_init(void **hob_list_ptr, /* Reserve enough memory under TOLUD to save CBMEM header */ fspm_upd.FspmArchUpd.BootLoaderTolumSize = cbmem_overhead_size(); + /* Fill common settings on behalf of chipset. */ + fsp_fill_common_arch_params(&fspm_upd.FspmArchUpd, s3wake); + /* Give SoC and mainboard a chance to update the UPD */ platform_fsp_memory_init_params_cb(&fspm_upd); @@ -53,25 +136,29 @@ static enum fsp_status do_fsp_memory_init(void **hob_list_ptr, fsp_raminit = (void *)(hdr->image_base + hdr->memory_init_entry_offset); printk(BIOS_DEBUG, "Calling FspMemoryInit: 0x%p\n", fsp_raminit); printk(BIOS_SPEW, "\t%p: raminit_upd\n", &fspm_upd); - printk(BIOS_SPEW, "\t%p: hob_list ptr\n", hob_list_ptr); + printk(BIOS_SPEW, "\t%p: hob_list ptr\n", &hob_list_ptr); post_code(POST_FSP_MEMORY_INIT); timestamp_add_now(TS_FSP_MEMORY_INIT_START); - status = fsp_raminit(&fspm_upd, hob_list_ptr); + status = fsp_raminit(&fspm_upd, &hob_list_ptr); post_code(POST_FSP_MEMORY_INIT); timestamp_add_now(TS_FSP_MEMORY_INIT_END); printk(BIOS_DEBUG, "FspMemoryInit returned 0x%08x\n", status); - return status; + /* TODO: Is this the only thing that can happen? */ + if (status != FSP_SUCCESS) + return status; + + return do_fsp_post_memory_init(hob_list_ptr, s3wake); } -enum fsp_status fsp_memory_init(void **hob_list, struct range_entry *range) +enum fsp_status fsp_memory_init(struct range_entry *range, bool s3wake) { struct fsp_header hdr; if (fsp_load_binary(&hdr, CONFIG_FSP_M_CBFS, range) != CB_SUCCESS) return FSP_NOT_FOUND; - return do_fsp_memory_init(hob_list, &hdr); + return do_fsp_memory_init(&hdr, s3wake); } -- cgit v1.2.3