diff options
-rw-r--r-- | src/commonlib/include/commonlib/timestamp_serialized.h | 2 | ||||
-rw-r--r-- | src/drivers/intel/fsp2_0/Kconfig | 13 | ||||
-rw-r--r-- | src/drivers/intel/fsp2_0/header_display.c | 3 | ||||
-rw-r--r-- | src/drivers/intel/fsp2_0/include/fsp/api.h | 5 | ||||
-rw-r--r-- | src/drivers/intel/fsp2_0/include/fsp/info_header.h | 5 | ||||
-rw-r--r-- | src/drivers/intel/fsp2_0/include/fsp/upd.h | 18 | ||||
-rw-r--r-- | src/drivers/intel/fsp2_0/include/fsp/util.h | 12 | ||||
-rw-r--r-- | src/drivers/intel/fsp2_0/silicon_init.c | 116 | ||||
-rw-r--r-- | src/drivers/intel/fsp2_0/util.c | 2 | ||||
-rw-r--r-- | src/include/console/post_codes.h | 14 |
10 files changed, 176 insertions, 14 deletions
diff --git a/src/commonlib/include/commonlib/timestamp_serialized.h b/src/commonlib/include/commonlib/timestamp_serialized.h index 132d45b86d..b1e58c9780 100644 --- a/src/commonlib/include/commonlib/timestamp_serialized.h +++ b/src/commonlib/include/commonlib/timestamp_serialized.h @@ -115,6 +115,8 @@ enum timestamp_id { TS_FSP_AFTER_FINALIZE = 959, TS_FSP_BEFORE_END_OF_FIRMWARE = 960, TS_FSP_AFTER_END_OF_FIRMWARE = 961, + TS_FSP_MULTI_PHASE_SI_INIT_START = 962, + TS_FSP_MULTI_PHASE_SI_INIT_END = 963, /* 1000+ reserved for payloads (1000-1200: ChromeOS depthcharge) */ diff --git a/src/drivers/intel/fsp2_0/Kconfig b/src/drivers/intel/fsp2_0/Kconfig index 0344116370..c7c44cd849 100644 --- a/src/drivers/intel/fsp2_0/Kconfig +++ b/src/drivers/intel/fsp2_0/Kconfig @@ -18,6 +18,19 @@ config PLATFORM_USES_FSP2_1 1. Remove FSP stack switch and use the same stack with boot firmware 2. FSP should support external PPI interface pulled in via FSP_PEIM_TO_PEIM_INTERFACE +config PLATFORM_USES_FSP2_2 + bool + default n + select PLATFORM_USES_FSP2_1 + help + Include FSP 2.2 wrappers and functionality. + Features added into FSP 2.2 specification that impact coreboot are: + 1. Added multi-phase silicon initialization to increase the modularity of the + FspSiliconInit() API + 2. FSP_INFO_HEADER changes to add FspMultiPhaseSiInitEntryOffset + 3. Added EnableMultiPhaseSiliconInit, bootloaders designed for FSP2.0/2.1 can disable + the FspMultiPhaseSiInit() API and continue to use FspSiliconInit() without change. + if PLATFORM_USES_FSP2_0 config HAVE_INTEL_FSP_REPO diff --git a/src/drivers/intel/fsp2_0/header_display.c b/src/drivers/intel/fsp2_0/header_display.c index 097de46b5c..57e13b5354 100644 --- a/src/drivers/intel/fsp2_0/header_display.c +++ b/src/drivers/intel/fsp2_0/header_display.c @@ -40,6 +40,9 @@ void fsp_print_header_info(const struct fsp_header *hdr) if ((hdr->component_attribute >> 12) == FSP_HDR_ATTRIB_FSPS) { printk(BIOS_SPEW, "\tSilicon init offset 0x%zx\n", hdr->silicon_init_entry_offset); + if (CONFIG(PLATFORM_USES_FSP2_2)) + printk(BIOS_SPEW, "\tMultiPhaseSiInit offset 0x%zx\n", + hdr->multi_phase_si_init_entry_offset); printk(BIOS_SPEW, "\tNotify phase offset 0x%zx\n", hdr->notify_phase_entry_offset); } diff --git a/src/drivers/intel/fsp2_0/include/fsp/api.h b/src/drivers/intel/fsp2_0/include/fsp/api.h index c6c9179867..d2c556f916 100644 --- a/src/drivers/intel/fsp2_0/include/fsp/api.h +++ b/src/drivers/intel/fsp2_0/include/fsp/api.h @@ -47,7 +47,10 @@ void fsps_load(bool s3wake); /* Callbacks for updating stage-specific parameters */ void platform_fsp_memory_init_params_cb(FSPM_UPD *mupd, uint32_t version); void platform_fsp_silicon_init_params_cb(FSPS_UPD *supd); - +/* Callbacks for SoC/Mainboard specific overrides */ +void platform_fsp_multi_phase_init_cb(uint32_t phase_index); +/* Check if SoC sets EnableMultiPhaseSiliconInit UPD */ +int soc_fsp_multi_phase_init_is_enable(void); /* * The following functions are used when FSP_PLATFORM_MEMORY_SETTINGS_VERSION * is employed allowing the mainboard and SoC to supply their own version diff --git a/src/drivers/intel/fsp2_0/include/fsp/info_header.h b/src/drivers/intel/fsp2_0/include/fsp/info_header.h index 7755d2a2f9..f237a378f1 100644 --- a/src/drivers/intel/fsp2_0/include/fsp/info_header.h +++ b/src/drivers/intel/fsp2_0/include/fsp/info_header.h @@ -6,7 +6,11 @@ #include <types.h> #define FSP_HDR_OFFSET 0x94 +#if CONFIG(PLATFORM_USES_FSP2_2) +#define FSP_HDR_LEN 0x4c +#else #define FSP_HDR_LEN 0x48 +#endif #define FSP_HDR_SIGNATURE "FSPH" #define FSP_HDR_ATTRIB_FSPT 1 #define FSP_HDR_ATTRIB_FSPM 2 @@ -26,6 +30,7 @@ struct fsp_header { size_t notify_phase_entry_offset; size_t memory_init_entry_offset; size_t silicon_init_entry_offset; + size_t multi_phase_si_init_entry_offset; char image_id[sizeof(uint64_t) + 1]; uint8_t revision; }; diff --git a/src/drivers/intel/fsp2_0/include/fsp/upd.h b/src/drivers/intel/fsp2_0/include/fsp/upd.h index bcfee6c727..979cff3b91 100644 --- a/src/drivers/intel/fsp2_0/include/fsp/upd.h +++ b/src/drivers/intel/fsp2_0/include/fsp/upd.h @@ -54,4 +54,22 @@ struct FSPM_ARCH_UPD { uint8_t Reserved1[8]; } __packed; +struct FSPS_ARCH_UPD { + /// + /// Revision of the structure. For FSP v2.2 value is 1. + /// + uint8_t Revision; + uint8_t Reserved[3]; + /// + /// Length of the structure in bytes. The current value for this field is 32 + /// + uint32_t Length; + uint8_t Reserved1[4]; + /// + /// To enable multi-phase silicon initialization the bootloader must set non-zero value + /// + uint8_t EnableMultiPhaseSiliconInit; + uint8_t Reserved2[19]; +} __packed; + #endif /* _FSP2_0_UPD_H_ */ diff --git a/src/drivers/intel/fsp2_0/include/fsp/util.h b/src/drivers/intel/fsp2_0/include/fsp/util.h index 29c393b09c..ad6a4b5260 100644 --- a/src/drivers/intel/fsp2_0/include/fsp/util.h +++ b/src/drivers/intel/fsp2_0/include/fsp/util.h @@ -21,6 +21,17 @@ struct fsp_notify_params { enum fsp_notify_phase phase; }; +enum fsp_multi_phase_action { + GET_NUMBER_OF_PHASES = 0, + EXECUTE_PHASE = 1 +}; + +struct fsp_multi_phase_params { + enum fsp_multi_phase_action multi_phase_action; + uint32_t phase_index; + void *multi_phase_param_ptr; +}; + struct hob_resource { uint8_t owner_guid[16]; uint32_t type; @@ -115,6 +126,7 @@ typedef asmlinkage uint32_t (*temp_ram_exit_fn)(void *param); typedef asmlinkage uint32_t (*fsp_memory_init_fn) (void *raminit_upd, void **hob_list); typedef asmlinkage uint32_t (*fsp_silicon_init_fn)(void *silicon_upd); +typedef asmlinkage uint32_t (*fsp_multi_phase_si_init_fn)(struct fsp_multi_phase_params *); typedef asmlinkage uint32_t (*fsp_notify_fn)(struct fsp_notify_params *); #include <fsp/debug.h> diff --git a/src/drivers/intel/fsp2_0/silicon_init.c b/src/drivers/intel/fsp2_0/silicon_init.c index 6f3781afaf..663b1d7cfd 100644 --- a/src/drivers/intel/fsp2_0/silicon_init.c +++ b/src/drivers/intel/fsp2_0/silicon_init.c @@ -16,13 +16,74 @@ struct fsp_header fsps_hdr; +struct fsp_multi_phase_get_number_of_phases_params { + uint32_t number_of_phases; + uint32_t phases_executed; +}; + +/* Callbacks for SoC/Mainboard specific overrides */ +void __weak platform_fsp_multi_phase_init_cb(uint32_t phase_index) +{ + /* Leave for the SoC/Mainboard to implement if necessary. */ +} + +int __weak soc_fsp_multi_phase_init_is_enable(void) +{ + return 1; +} + +/* FSP Specification < 2.2 has only 1 stage like FspSiliconInit. FSP specification >= 2.2 + * has multiple stages as below. + */ +enum fsp_silicon_init_phases { + FSP_SILICON_INIT_API, + FSP_MULTI_PHASE_SI_INIT_GET_NUMBER_OF_PHASES_API, + FSP_MULTI_PHASE_SI_INIT_EXECUTE_PHASE_API +}; + +static void fsps_return_value_handler(enum fsp_silicon_init_phases phases, uint32_t status) +{ + uint8_t postcode; + + /* Handle any reset request returned by FSP-S APIs */ + fsp_handle_reset(status); + + if (status == FSP_SUCCESS) + return; + /* Handle all other errors returned by FSP-S APIs */ + /* Assume video failure if attempted to initialize graphics */ + if (CONFIG(RUN_FSP_GOP) && vbt_get()) + postcode = POST_VIDEO_FAILURE; + else + postcode = POST_HW_INIT_FAILURE; /* else generic */ + + switch (phases) { + case FSP_SILICON_INIT_API: + die_with_post_code(postcode, "FspSiliconInit returned with error 0x%08x\n", + status); + break; + case FSP_MULTI_PHASE_SI_INIT_GET_NUMBER_OF_PHASES_API: + printk(BIOS_SPEW, "FspMultiPhaseSiInit NumberOfPhases returned 0x%08x\n", + status); + break; + case FSP_MULTI_PHASE_SI_INIT_EXECUTE_PHASE_API: + printk(BIOS_SPEW, "FspMultiPhaseSiInit ExecutePhase returned 0x%08x\n", + status); + break; + default: + break; + } +} + static void do_silicon_init(struct fsp_header *hdr) { FSPS_UPD *upd, *supd; fsp_silicon_init_fn silicon_init; uint32_t status; - uint8_t postcode; const struct cbmem_entry *logo_entry = NULL; + fsp_multi_phase_si_init_fn multi_phase_si_init; + struct fsp_multi_phase_params multi_phase_params; + struct fsp_multi_phase_get_number_of_phases_params multi_phase_get_number; supd = (FSPS_UPD *) (hdr->cfg_region_offset + hdr->image_base); @@ -64,20 +125,49 @@ static void do_silicon_init(struct fsp_header *hdr) cbmem_entry_remove(logo_entry); fsp_debug_after_silicon_init(status); + fsps_return_value_handler(FSP_SILICON_INIT_API, status); - /* Handle any errors returned by FspSiliconInit */ - fsp_handle_reset(status); - if (status != FSP_SUCCESS) { - /* Assume video failure if attempted to initialize graphics */ - if (CONFIG(RUN_FSP_GOP) && vbt_get()) - postcode = POST_VIDEO_FAILURE; - else - postcode = POST_HW_INIT_FAILURE; /* else generic */ - - printk(BIOS_SPEW, "FspSiliconInit returned 0x%08x\n", status); - die_with_post_code(postcode, - "FspSiliconInit returned an error!\n"); + if (!CONFIG(PLATFORM_USES_FSP2_2)) + return; + + /* Check if SoC user would like to call Multi Phase Init */ + if (!soc_fsp_multi_phase_init_is_enable()) + return; + + /* Call MultiPhaseSiInit */ + multi_phase_si_init = (void *) (hdr->image_base + + hdr->multi_phase_si_init_entry_offset); + + /* Implementing multi_phase_si_init() is optional as per FSP 2.2 spec */ + if (multi_phase_si_init == NULL) + return; + + post_code(POST_FSP_MULTI_PHASE_SI_INIT_ENTRY); + timestamp_add_now(TS_FSP_MULTI_PHASE_SI_INIT_START); + /* Get NumberOfPhases Value */ + multi_phase_params.multi_phase_action = GET_NUMBER_OF_PHASES; + multi_phase_params.phase_index = 0; + multi_phase_params.multi_phase_param_ptr = &multi_phase_get_number; + status = multi_phase_si_init(&multi_phase_params); + fsps_return_value_handler(FSP_MULTI_PHASE_SI_INIT_GET_NUMBER_OF_PHASES_API, status); + + /* Execute Multi Phase Execution */ + for (int i = 1; i <= multi_phase_get_number.number_of_phases; i++) { + printk(BIOS_SPEW, "Executing Phase %d of FspMultiPhaseSiInit\n", i); + /* + * Give SoC/mainboard a chance to perform any operation before + * Multi Phase Execution + */ + platform_fsp_multi_phase_init_cb(i); + + multi_phase_params.multi_phase_action = EXECUTE_PHASE; + multi_phase_params.phase_index = i; + multi_phase_params.multi_phase_param_ptr = NULL; + status = multi_phase_si_init(&multi_phase_params); + fsps_return_value_handler(FSP_MULTI_PHASE_SI_INIT_EXECUTE_PHASE_API, status); } + timestamp_add_now(TS_FSP_MULTI_PHASE_SI_INIT_END); + post_code(POST_FSP_MULTI_PHASE_SI_INIT_EXIT); } static int fsps_get_dest(const struct fsp_load_descriptor *fspld, void **dest, diff --git a/src/drivers/intel/fsp2_0/util.c b/src/drivers/intel/fsp2_0/util.c index a00b684624..e8c587628e 100644 --- a/src/drivers/intel/fsp2_0/util.c +++ b/src/drivers/intel/fsp2_0/util.c @@ -49,6 +49,8 @@ enum cb_err fsp_identify(struct fsp_header *hdr, const void *fsp_blob) hdr->notify_phase_entry_offset = read32(raw_hdr + 56); hdr->memory_init_entry_offset = read32(raw_hdr + 60); hdr->silicon_init_entry_offset = read32(raw_hdr + 68); + if (CONFIG(PLATFORM_USES_FSP2_2)) + hdr->multi_phase_si_init_entry_offset = read32(raw_hdr + 72); return CB_SUCCESS; } diff --git a/src/include/console/post_codes.h b/src/include/console/post_codes.h index 00a2ad3dec..0c6655cec8 100644 --- a/src/include/console/post_codes.h +++ b/src/include/console/post_codes.h @@ -289,6 +289,20 @@ #define POST_FSP_SILICON_EXIT 0x99 /** + * \brief Before calling FSP Multiphase SiliconInit + * + * Going to call into FSP binary for Multiple phase SI Init + */ +#define POST_FSP_MULTI_PHASE_SI_INIT_ENTRY 0xa0 + +/** + * \brief After calling FSP Multiphase SiliconInit + * + * FSP binary returned from Multiple phase SI Init + */ +#define POST_FSP_MULTI_PHASE_SI_INIT_EXIT 0xa1 + +/** * \brief Entry into elf boot * * This POST code is called right before invoking jmp_to_elf_entry() |