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_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) */

View File

@ -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

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) {
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);
}

View File

@ -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

View File

@ -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;
};

View File

@ -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_ */

View File

@ -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>

View File

@ -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 */
if (!CONFIG(PLATFORM_USES_FSP2_2))
return;
printk(BIOS_SPEW, "FspSiliconInit returned 0x%08x\n", status);
die_with_post_code(postcode,
"FspSiliconInit returned an error!\n");
/* 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,

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->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;
}

View File

@ -288,6 +288,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
*