/** @file | |
Copyright (c) 2014 - 2018, Intel Corporation. All rights reserved.<BR> | |
SPDX-License-Identifier: BSD-2-Clause-Patent | |
**/ | |
#include <PiPei.h> | |
#include <Library/PeiServicesLib.h> | |
#include <Library/PeiServicesTablePointerLib.h> | |
#include <Library/BaseLib.h> | |
#include <Library/BaseMemoryLib.h> | |
#include <Library/PcdLib.h> | |
#include <Library/DebugLib.h> | |
#include <Library/HobLib.h> | |
#include <Library/FspSwitchStackLib.h> | |
#include <Library/FspCommonLib.h> | |
#include <Guid/EventGroup.h> | |
#include <FspEas.h> | |
#include <FspStatusCode.h> | |
#include <Protocol/PciEnumerationComplete.h> | |
#include <Library/ReportStatusCodeLib.h> | |
#include <Library/PerformanceLib.h> | |
extern EFI_GUID gFspPerformanceDataGuid; | |
EFI_PEI_PPI_DESCRIPTOR mPeiPostPciEnumerationPpi = { | |
(EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST), | |
&gEfiPciEnumerationCompleteProtocolGuid, | |
NULL | |
}; | |
EFI_PEI_PPI_DESCRIPTOR mPeiReadyToBootPpi = { | |
(EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST), | |
&gEfiEventReadyToBootGuid, | |
NULL | |
}; | |
EFI_PEI_PPI_DESCRIPTOR mPeiEndOfFirmwarePpi = { | |
(EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST), | |
&gFspEventEndOfFirmwareGuid, | |
NULL | |
}; | |
UINT32 mFspNotifySequence[] = { | |
EnumInitPhaseAfterPciEnumeration, | |
EnumInitPhaseReadyToBoot, | |
EnumInitPhaseEndOfFirmware | |
}; | |
/** | |
Install FSP notification. | |
@param[in] NotificationCode FSP notification code | |
@retval EFI_SUCCESS Notify FSP successfully | |
@retval EFI_INVALID_PARAMETER NotificationCode is invalid | |
**/ | |
EFI_STATUS | |
EFIAPI | |
FspNotificationHandler ( | |
IN UINT32 NotificationCode | |
) | |
{ | |
EFI_STATUS Status; | |
Status = EFI_SUCCESS; | |
switch (NotificationCode) { | |
case EnumInitPhaseAfterPciEnumeration: | |
// | |
// Do POST PCI initialization if needed | |
// | |
DEBUG ((DEBUG_INFO | DEBUG_INIT, "FSP Post PCI Enumeration ...\n")); | |
PeiServicesInstallPpi (&mPeiPostPciEnumerationPpi); | |
break; | |
case EnumInitPhaseReadyToBoot: | |
// | |
// Ready To Boot | |
// | |
DEBUG ((DEBUG_INFO| DEBUG_INIT, "FSP Ready To Boot ...\n")); | |
PeiServicesInstallPpi (&mPeiReadyToBootPpi); | |
break; | |
case EnumInitPhaseEndOfFirmware: | |
// | |
// End of Firmware | |
// | |
DEBUG ((DEBUG_INFO| DEBUG_INIT, "FSP End of Firmware ...\n")); | |
PeiServicesInstallPpi (&mPeiEndOfFirmwarePpi); | |
break; | |
default: | |
Status = EFI_INVALID_PARAMETER; | |
break; | |
} | |
return Status; | |
} | |
/** | |
This function transfer control back to BootLoader after FspSiliconInit. | |
@param[in] Status return status for the FspSiliconInit. | |
**/ | |
VOID | |
EFIAPI | |
FspSiliconInitDone2 ( | |
IN EFI_STATUS Status | |
) | |
{ | |
volatile EFI_STATUS FspStatus; | |
FspStatus = Status; | |
// | |
// Convert to FSP EAS defined API return codes | |
// | |
switch (Status) { | |
case EFI_SUCCESS: | |
case EFI_INVALID_PARAMETER: | |
case EFI_UNSUPPORTED: | |
case EFI_DEVICE_ERROR: | |
break; | |
default: | |
DEBUG ((DEBUG_INFO | DEBUG_INIT, "FspSiliconInitApi() Invalid Error - [Status: 0x%08X]\n", Status)); | |
Status = EFI_DEVICE_ERROR; // Force to known error. | |
break; | |
} | |
// | |
// This is the end of the FspSiliconInit API | |
// Give control back to the boot loader | |
// | |
SetFspMeasurePoint (FSP_PERF_ID_API_FSP_SILICON_INIT_EXIT); | |
DEBUG ((DEBUG_INFO | DEBUG_INIT, "FspSiliconInitApi() - [Status: 0x%08X] - End\n", Status)); | |
PERF_END_EX (&gFspPerformanceDataGuid, "EventRec", NULL, 0, FSP_STATUS_CODE_SILICON_INIT | FSP_STATUS_CODE_COMMON_CODE | FSP_STATUS_CODE_API_EXIT); | |
REPORT_STATUS_CODE (EFI_PROGRESS_CODE, FSP_STATUS_CODE_COMMON_CODE | FSP_STATUS_CODE_API_EXIT); | |
if (GetFspGlobalDataPointer ()->FspMode == FSP_IN_API_MODE) { | |
do { | |
SetFspApiReturnStatus (Status); | |
Pei2LoaderSwitchStack (); | |
if (Status != EFI_SUCCESS) { | |
DEBUG ((DEBUG_ERROR, "!!!ERROR: FspSiliconInitApi() - [Status: 0x%08X] - Error encountered during previous API and cannot proceed further\n", Status)); | |
} | |
} while (FspStatus != EFI_SUCCESS); | |
} | |
} | |
/** | |
This function returns control to BootLoader after MemoryInitApi. | |
@param[in] Status return status for the MemoryInitApi. | |
@param[in,out] HobListPtr The address of HobList pointer, if NULL, will get value from GetFspApiParameter2 () | |
**/ | |
VOID | |
EFIAPI | |
FspMemoryInitDone2 ( | |
IN EFI_STATUS Status, | |
IN OUT VOID **HobListPtr | |
) | |
{ | |
FSP_GLOBAL_DATA *FspData; | |
volatile EFI_STATUS FspStatus; | |
FspStatus = Status; | |
// | |
// Calling use FspMemoryInit API | |
// Update HOB and return the control directly | |
// | |
if (HobListPtr == NULL) { | |
HobListPtr = (VOID **)GetFspApiParameter2 (); | |
} | |
if (HobListPtr != NULL) { | |
*HobListPtr = (VOID *)GetHobList (); | |
} | |
// | |
// Convert to FSP EAS defined API return codes | |
// | |
switch (Status) { | |
case EFI_SUCCESS: | |
case EFI_INVALID_PARAMETER: | |
case EFI_UNSUPPORTED: | |
case EFI_DEVICE_ERROR: | |
case EFI_OUT_OF_RESOURCES: | |
break; | |
default: | |
DEBUG ((DEBUG_INFO | DEBUG_INIT, "FspMemoryInitApi() Invalid Error [Status: 0x%08X]\n", Status)); | |
Status = EFI_DEVICE_ERROR; // Force to known error. | |
break; | |
} | |
// | |
// This is the end of the FspMemoryInit API | |
// Give control back to the boot loader | |
// | |
DEBUG ((DEBUG_INFO | DEBUG_INIT, "FspMemoryInitApi() - [Status: 0x%08X] - End\n", Status)); | |
SetFspMeasurePoint (FSP_PERF_ID_API_FSP_MEMORY_INIT_EXIT); | |
FspData = GetFspGlobalDataPointer (); | |
PERF_START_EX (&gFspPerformanceDataGuid, "EventRec", NULL, (FspData->PerfData[0] & FSP_PERFORMANCE_DATA_TIMER_MASK), FSP_STATUS_CODE_TEMP_RAM_INIT | FSP_STATUS_CODE_COMMON_CODE| FSP_STATUS_CODE_API_ENTRY); | |
PERF_END_EX (&gFspPerformanceDataGuid, "EventRec", NULL, (FspData->PerfData[1] & FSP_PERFORMANCE_DATA_TIMER_MASK), FSP_STATUS_CODE_TEMP_RAM_INIT | FSP_STATUS_CODE_COMMON_CODE | FSP_STATUS_CODE_API_EXIT); | |
PERF_START_EX (&gFspPerformanceDataGuid, "EventRec", NULL, (FspData->PerfData[2] & FSP_PERFORMANCE_DATA_TIMER_MASK), FSP_STATUS_CODE_MEMORY_INIT | FSP_STATUS_CODE_COMMON_CODE | FSP_STATUS_CODE_API_ENTRY); | |
PERF_END_EX (&gFspPerformanceDataGuid, "EventRec", NULL, 0, FSP_STATUS_CODE_MEMORY_INIT | FSP_STATUS_CODE_COMMON_CODE | FSP_STATUS_CODE_API_EXIT); | |
REPORT_STATUS_CODE (EFI_PROGRESS_CODE, FSP_STATUS_CODE_MEMORY_INIT | FSP_STATUS_CODE_COMMON_CODE | FSP_STATUS_CODE_API_EXIT); | |
if (GetFspGlobalDataPointer ()->FspMode == FSP_IN_API_MODE) { | |
do { | |
SetFspApiReturnStatus (Status); | |
Pei2LoaderSwitchStack (); | |
if (Status != EFI_SUCCESS) { | |
DEBUG ((DEBUG_ERROR, "!!!ERROR: FspMemoryInitApi() - [Status: 0x%08X] - Error encountered during previous API and cannot proceed further\n", Status)); | |
} | |
} while (FspStatus != EFI_SUCCESS); | |
} | |
// | |
// The TempRamExitApi is called | |
// | |
if (GetFspApiCallingIndex () == TempRamExitApiIndex) { | |
SetPhaseStatusCode (FSP_STATUS_CODE_TEMP_RAM_EXIT); | |
SetFspMeasurePoint (FSP_PERF_ID_API_TEMP_RAM_EXIT_ENTRY); | |
PERF_START_EX (&gFspPerformanceDataGuid, "EventRec", NULL, 0, FSP_STATUS_CODE_TEMP_RAM_EXIT | FSP_STATUS_CODE_COMMON_CODE | FSP_STATUS_CODE_API_ENTRY); | |
REPORT_STATUS_CODE (EFI_PROGRESS_CODE, FSP_STATUS_CODE_TEMP_RAM_EXIT | FSP_STATUS_CODE_COMMON_CODE | FSP_STATUS_CODE_API_ENTRY); | |
DEBUG ((DEBUG_INFO | DEBUG_INIT, "TempRamExitApi() - Begin\n")); | |
} else { | |
SetPhaseStatusCode (FSP_STATUS_CODE_SILICON_INIT); | |
SetFspMeasurePoint (FSP_PERF_ID_API_FSP_SILICON_INIT_ENTRY); | |
PERF_START_EX (&gFspPerformanceDataGuid, "EventRec", NULL, 0, FSP_STATUS_CODE_SILICON_INIT | FSP_STATUS_CODE_COMMON_CODE | FSP_STATUS_CODE_API_ENTRY); | |
REPORT_STATUS_CODE (EFI_PROGRESS_CODE, FSP_STATUS_CODE_SILICON_INIT | FSP_STATUS_CODE_COMMON_CODE | FSP_STATUS_CODE_API_ENTRY); | |
DEBUG ((DEBUG_INFO | DEBUG_INIT, "FspSiliconInitApi() - Begin\n")); | |
} | |
} | |
/** | |
This function returns control to BootLoader after TempRamExitApi. | |
@param[in] Status return status for the TempRamExitApi. | |
**/ | |
VOID | |
EFIAPI | |
FspTempRamExitDone2 ( | |
IN EFI_STATUS Status | |
) | |
{ | |
// | |
volatile EFI_STATUS FspStatus; | |
FspStatus = Status; | |
// Convert to FSP EAS defined API return codes | |
// | |
switch (Status) { | |
case EFI_SUCCESS: | |
case EFI_INVALID_PARAMETER: | |
case EFI_UNSUPPORTED: | |
case EFI_DEVICE_ERROR: | |
break; | |
default: | |
DEBUG ((DEBUG_INFO | DEBUG_INIT, "TempRamExitApi() Invalid Error - [Status: 0x%08X]\n", Status)); | |
Status = EFI_DEVICE_ERROR; // Force to known error. | |
break; | |
} | |
// | |
// This is the end of the TempRamExit API | |
// Give control back to the boot loader | |
// | |
DEBUG ((DEBUG_INFO | DEBUG_INIT, "TempRamExitApi() - [Status: 0x%08X] - End\n", Status)); | |
SetFspMeasurePoint (FSP_PERF_ID_API_TEMP_RAM_EXIT_EXIT); | |
PERF_END_EX (&gFspPerformanceDataGuid, "EventRec", NULL, 0, FSP_STATUS_CODE_TEMP_RAM_EXIT | FSP_STATUS_CODE_COMMON_CODE | FSP_STATUS_CODE_API_EXIT); | |
REPORT_STATUS_CODE (EFI_PROGRESS_CODE, FSP_STATUS_CODE_TEMP_RAM_EXIT | FSP_STATUS_CODE_COMMON_CODE | FSP_STATUS_CODE_API_EXIT); | |
if (GetFspGlobalDataPointer ()->FspMode == FSP_IN_API_MODE) { | |
do { | |
SetFspApiReturnStatus (Status); | |
Pei2LoaderSwitchStack (); | |
if (Status != EFI_SUCCESS) { | |
DEBUG ((DEBUG_ERROR, "!!!ERROR: TempRamExitApi() - [Status: 0x%08X] - Error encountered during previous API and cannot proceed further\n", Status)); | |
} | |
} while (FspStatus != EFI_SUCCESS); | |
} | |
SetPhaseStatusCode (FSP_STATUS_CODE_SILICON_INIT); | |
SetFspMeasurePoint (FSP_PERF_ID_API_FSP_SILICON_INIT_ENTRY); | |
PERF_START_EX (&gFspPerformanceDataGuid, "EventRec", NULL, 0, FSP_STATUS_CODE_SILICON_INIT | FSP_STATUS_CODE_COMMON_CODE | FSP_STATUS_CODE_API_ENTRY); | |
REPORT_STATUS_CODE (EFI_PROGRESS_CODE, FSP_STATUS_CODE_SILICON_INIT | FSP_STATUS_CODE_COMMON_CODE | FSP_STATUS_CODE_API_ENTRY); | |
DEBUG ((DEBUG_INFO | DEBUG_INIT, "SiliconInitApi() - Begin\n")); | |
} | |
/** | |
This function handle NotifyPhase API call from the BootLoader. | |
It gives control back to the BootLoader after it is handled. If the | |
Notification code is a ReadyToBoot event, this function will return | |
and FSP continues the remaining execution until it reaches the DxeIpl. | |
**/ | |
VOID | |
EFIAPI | |
FspWaitForNotify ( | |
VOID | |
) | |
{ | |
EFI_STATUS Status; | |
UINT32 NotificationValue; | |
UINT32 NotificationCount; | |
UINT8 Count; | |
volatile EFI_STATUS FspStatus; | |
NotificationCount = 0; | |
while (NotificationCount < sizeof (mFspNotifySequence) / sizeof (UINT32)) { | |
Count = (UINT8)((NotificationCount << 1) & 0x07); | |
SetFspMeasurePoint (FSP_PERF_ID_API_NOTIFY_POST_PCI_ENTRY + Count); | |
if (NotificationCount == 0) { | |
SetPhaseStatusCode (FSP_STATUS_CODE_POST_PCIE_ENUM_NOTIFICATION); | |
PERF_START_EX (&gFspPerformanceDataGuid, "EventRec", NULL, 0, FSP_STATUS_CODE_POST_PCIE_ENUM_NOTIFICATION | FSP_STATUS_CODE_COMMON_CODE | FSP_STATUS_CODE_API_ENTRY); | |
REPORT_STATUS_CODE (EFI_PROGRESS_CODE, FSP_STATUS_CODE_POST_PCIE_ENUM_NOTIFICATION | FSP_STATUS_CODE_COMMON_CODE | FSP_STATUS_CODE_API_ENTRY); | |
} else if (NotificationCount == 1) { | |
SetPhaseStatusCode (FSP_STATUS_CODE_READY_TO_BOOT_NOTIFICATION); | |
PERF_START_EX (&gFspPerformanceDataGuid, "EventRec", NULL, 0, FSP_STATUS_CODE_READY_TO_BOOT_NOTIFICATION | FSP_STATUS_CODE_COMMON_CODE | FSP_STATUS_CODE_API_ENTRY); | |
REPORT_STATUS_CODE (EFI_PROGRESS_CODE, FSP_STATUS_CODE_READY_TO_BOOT_NOTIFICATION | FSP_STATUS_CODE_COMMON_CODE | FSP_STATUS_CODE_API_ENTRY); | |
} else if (NotificationCount == 2) { | |
SetPhaseStatusCode (FSP_STATUS_CODE_END_OF_FIRMWARE_NOTIFICATION); | |
PERF_START_EX (&gFspPerformanceDataGuid, "EventRec", NULL, 0, FSP_STATUS_CODE_END_OF_FIRMWARE_NOTIFICATION | FSP_STATUS_CODE_COMMON_CODE | FSP_STATUS_CODE_API_ENTRY); | |
REPORT_STATUS_CODE (EFI_PROGRESS_CODE, FSP_STATUS_CODE_END_OF_FIRMWARE_NOTIFICATION | FSP_STATUS_CODE_COMMON_CODE | FSP_STATUS_CODE_API_ENTRY); | |
} | |
NotificationValue = ((NOTIFY_PHASE_PARAMS *)(UINTN)GetFspApiParameter ())->Phase; | |
DEBUG ((DEBUG_INFO | DEBUG_INIT, "NotifyPhaseApi() - Begin [Phase: %08X]\n", NotificationValue)); | |
if (mFspNotifySequence[NotificationCount] != NotificationValue) { | |
// | |
// Notify code does not follow the predefined order | |
// | |
DEBUG ((DEBUG_INFO, "Unsupported FSP Notification Value\n")); | |
Status = EFI_UNSUPPORTED; | |
} else { | |
// | |
// Process Notification and Give control back to the boot loader framework caller | |
// | |
Status = FspNotificationHandler (NotificationValue); | |
if (!EFI_ERROR (Status)) { | |
NotificationCount++; | |
} | |
} | |
DEBUG ((DEBUG_INFO | DEBUG_INIT, "NotifyPhaseApi() - End [Status: 0x%08X]\n", Status)); | |
SetFspMeasurePoint (FSP_PERF_ID_API_NOTIFY_POST_PCI_EXIT + Count); | |
if ((NotificationCount - 1) == 0) { | |
PERF_END_EX (&gFspPerformanceDataGuid, "EventRec", NULL, 0, FSP_STATUS_CODE_POST_PCIE_ENUM_NOTIFICATION | FSP_STATUS_CODE_COMMON_CODE | FSP_STATUS_CODE_API_EXIT); | |
REPORT_STATUS_CODE (EFI_PROGRESS_CODE, FSP_STATUS_CODE_POST_PCIE_ENUM_NOTIFICATION | FSP_STATUS_CODE_COMMON_CODE | FSP_STATUS_CODE_API_EXIT); | |
} else if ((NotificationCount - 1) == 1) { | |
PERF_END_EX (&gFspPerformanceDataGuid, "EventRec", NULL, 0, FSP_STATUS_CODE_READY_TO_BOOT_NOTIFICATION | FSP_STATUS_CODE_COMMON_CODE | FSP_STATUS_CODE_API_EXIT); | |
REPORT_STATUS_CODE (EFI_PROGRESS_CODE, FSP_STATUS_CODE_READY_TO_BOOT_NOTIFICATION | FSP_STATUS_CODE_COMMON_CODE | FSP_STATUS_CODE_API_EXIT); | |
} else if ((NotificationCount - 1) == 2) { | |
PERF_END_EX (&gFspPerformanceDataGuid, "EventRec", NULL, 0, FSP_STATUS_CODE_END_OF_FIRMWARE_NOTIFICATION | FSP_STATUS_CODE_COMMON_CODE | FSP_STATUS_CODE_API_EXIT); | |
REPORT_STATUS_CODE (EFI_PROGRESS_CODE, FSP_STATUS_CODE_END_OF_FIRMWARE_NOTIFICATION | FSP_STATUS_CODE_COMMON_CODE | FSP_STATUS_CODE_API_EXIT); | |
} | |
if (GetFspGlobalDataPointer ()->FspMode == FSP_IN_API_MODE) { | |
FspStatus = Status; | |
do { | |
SetFspApiReturnStatus (Status); | |
Pei2LoaderSwitchStack (); | |
if (Status != EFI_SUCCESS) { | |
DEBUG ((DEBUG_ERROR, "!!!ERROR: NotifyPhaseApi() [Phase: %08X] - Failed - [Status: 0x%08X]\n", NotificationValue, Status)); | |
} | |
} while (FspStatus != EFI_SUCCESS); | |
} | |
} | |
// | |
// Control goes back to the PEI Core and it dispatches further PEIMs. | |
// DXEIPL is the final one to transfer control back to the boot loader. | |
// | |
} | |
/** | |
This function transfer control back to BootLoader after FspSiliconInit. | |
**/ | |
VOID | |
EFIAPI | |
FspSiliconInitDone ( | |
VOID | |
) | |
{ | |
FspSiliconInitDone2 (EFI_SUCCESS); | |
} | |
/** | |
This function returns control to BootLoader after MemoryInitApi. | |
@param[in,out] HobListPtr The address of HobList pointer. | |
**/ | |
VOID | |
EFIAPI | |
FspMemoryInitDone ( | |
IN OUT VOID **HobListPtr | |
) | |
{ | |
FspMemoryInitDone2 (EFI_SUCCESS, HobListPtr); | |
} | |
/** | |
This function returns control to BootLoader after TempRamExitApi. | |
**/ | |
VOID | |
EFIAPI | |
FspTempRamExitDone ( | |
VOID | |
) | |
{ | |
FspTempRamExitDone2 (EFI_SUCCESS); | |
} |