drivers/intel/fsp2_0: Add FSP 2.2 specific support

• Based on FSP EAS v2.1 – Backward compatibility is retained.
• Add multi-phase silicon initialization to increase the modularity of the
FspSiliconInit() API.
• Add FspMultiPhaseSiInit() API
• FSP_INFO_HEADER changes
   o Added FspMultiPhaseSiInitEntryOffset
• Add FSPS_ARCH_UPD
   o Added EnableMultiPhaseSiliconInit, bootloaders designed for
     FSP 2.0/2.1 can disable the FspMultiPhaseSiInit() API and
     continue to use FspSiliconInit() without change.

FSP 2.2 Specification:
https://www.intel.com/content/www/us/en/intelligent-systems/intel-firmware-support-package/intel-fsp-overview.html

Change-Id: If7177a267f3a9b4cbb60a639f1c737b9a3341913
Signed-off-by: Subrata Banik <subrata.banik@intel.com>
Reviewed-on: https://review.coreboot.org/c/coreboot/+/41728
Reviewed-by: Srinidhi N Kaushik <srinidhi.n.kaushik@intel.com>
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
This commit is contained in:
Subrata Banik 2020-05-26 18:26:54 +05:30 committed by Duncan Laurie
parent f7841d03e2
commit 33d9c4ad7e
10 changed files with 175 additions and 13 deletions

View File

@ -115,6 +115,8 @@ enum timestamp_id {
TS_FSP_AFTER_FINALIZE = 959, TS_FSP_AFTER_FINALIZE = 959,
TS_FSP_BEFORE_END_OF_FIRMWARE = 960, TS_FSP_BEFORE_END_OF_FIRMWARE = 960,
TS_FSP_AFTER_END_OF_FIRMWARE = 961, 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) */ /* 1000+ reserved for payloads (1000-1200: ChromeOS depthcharge) */

View File

@ -18,6 +18,19 @@ config PLATFORM_USES_FSP2_1
1. Remove FSP stack switch and use the same stack with boot firmware 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 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 if PLATFORM_USES_FSP2_0
config HAVE_INTEL_FSP_REPO config HAVE_INTEL_FSP_REPO

View File

@ -40,6 +40,9 @@ void fsp_print_header_info(const struct fsp_header *hdr)
if ((hdr->component_attribute >> 12) == FSP_HDR_ATTRIB_FSPS) { if ((hdr->component_attribute >> 12) == FSP_HDR_ATTRIB_FSPS) {
printk(BIOS_SPEW, "\tSilicon init offset 0x%zx\n", printk(BIOS_SPEW, "\tSilicon init offset 0x%zx\n",
hdr->silicon_init_entry_offset); 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", printk(BIOS_SPEW, "\tNotify phase offset 0x%zx\n",
hdr->notify_phase_entry_offset); hdr->notify_phase_entry_offset);
} }

View File

@ -47,7 +47,10 @@ void fsps_load(bool s3wake);
/* Callbacks for updating stage-specific parameters */ /* Callbacks for updating stage-specific parameters */
void platform_fsp_memory_init_params_cb(FSPM_UPD *mupd, uint32_t version); void platform_fsp_memory_init_params_cb(FSPM_UPD *mupd, uint32_t version);
void platform_fsp_silicon_init_params_cb(FSPS_UPD *supd); 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 * The following functions are used when FSP_PLATFORM_MEMORY_SETTINGS_VERSION
* is employed allowing the mainboard and SoC to supply their own version * is employed allowing the mainboard and SoC to supply their own version

View File

@ -6,7 +6,11 @@
#include <types.h> #include <types.h>
#define FSP_HDR_OFFSET 0x94 #define FSP_HDR_OFFSET 0x94
#if CONFIG(PLATFORM_USES_FSP2_2)
#define FSP_HDR_LEN 0x4c
#else
#define FSP_HDR_LEN 0x48 #define FSP_HDR_LEN 0x48
#endif
#define FSP_HDR_SIGNATURE "FSPH" #define FSP_HDR_SIGNATURE "FSPH"
#define FSP_HDR_ATTRIB_FSPT 1 #define FSP_HDR_ATTRIB_FSPT 1
#define FSP_HDR_ATTRIB_FSPM 2 #define FSP_HDR_ATTRIB_FSPM 2
@ -26,6 +30,7 @@ struct fsp_header {
size_t notify_phase_entry_offset; size_t notify_phase_entry_offset;
size_t memory_init_entry_offset; size_t memory_init_entry_offset;
size_t silicon_init_entry_offset; size_t silicon_init_entry_offset;
size_t multi_phase_si_init_entry_offset;
char image_id[sizeof(uint64_t) + 1]; char image_id[sizeof(uint64_t) + 1];
uint8_t revision; uint8_t revision;
}; };

View File

@ -54,4 +54,22 @@ struct FSPM_ARCH_UPD {
uint8_t Reserved1[8]; uint8_t Reserved1[8];
} __packed; } __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_ */ #endif /* _FSP2_0_UPD_H_ */

View File

@ -21,6 +21,17 @@ struct fsp_notify_params {
enum fsp_notify_phase phase; 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 { struct hob_resource {
uint8_t owner_guid[16]; uint8_t owner_guid[16];
uint32_t type; 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) typedef asmlinkage uint32_t (*fsp_memory_init_fn)
(void *raminit_upd, void **hob_list); (void *raminit_upd, void **hob_list);
typedef asmlinkage uint32_t (*fsp_silicon_init_fn)(void *silicon_upd); 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 *); typedef asmlinkage uint32_t (*fsp_notify_fn)(struct fsp_notify_params *);
#include <fsp/debug.h> #include <fsp/debug.h>

View File

@ -16,13 +16,74 @@
struct fsp_header fsps_hdr; 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) static void do_silicon_init(struct fsp_header *hdr)
{ {
FSPS_UPD *upd, *supd; FSPS_UPD *upd, *supd;
fsp_silicon_init_fn silicon_init; fsp_silicon_init_fn silicon_init;
uint32_t status; uint32_t status;
uint8_t postcode;
const struct cbmem_entry *logo_entry = NULL; 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); 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); cbmem_entry_remove(logo_entry);
fsp_debug_after_silicon_init(status); fsp_debug_after_silicon_init(status);
fsps_return_value_handler(FSP_SILICON_INIT_API, status);
/* Handle any errors returned by FspSiliconInit */ if (!CONFIG(PLATFORM_USES_FSP2_2))
fsp_handle_reset(status); return;
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); /* Check if SoC user would like to call Multi Phase Init */
die_with_post_code(postcode, if (!soc_fsp_multi_phase_init_is_enable())
"FspSiliconInit returned an error!\n"); 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, static int fsps_get_dest(const struct fsp_load_descriptor *fspld, void **dest,

View File

@ -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->notify_phase_entry_offset = read32(raw_hdr + 56);
hdr->memory_init_entry_offset = read32(raw_hdr + 60); hdr->memory_init_entry_offset = read32(raw_hdr + 60);
hdr->silicon_init_entry_offset = read32(raw_hdr + 68); 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; return CB_SUCCESS;
} }

View File

@ -288,6 +288,20 @@
*/ */
#define POST_FSP_SILICON_EXIT 0x99 #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 * \brief Entry into elf boot
* *