| /** @file | |
| Copyright (c) 2014 - 2016, Intel Corporation. All rights reserved.<BR> | |
| This program and the accompanying materials | |
| are licensed and made available under the terms and conditions of the BSD License | |
| which accompanies this distribution. The full text of the license may be found at | |
| http://opensource.org/licenses/bsd-license.php. | |
| THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, | |
| WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. | |
| **/ | |
| #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 | |
| ) | |
| { | |
| // | |
| // 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); | |
| 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 (Status != 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; | |
| // | |
| // 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); | |
| 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 (Status != 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 | |
| ) | |
| { | |
| // | |
| // 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); | |
| 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 (Status != 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 | |
| FspWaitForNotify ( | |
| VOID | |
| ) | |
| { | |
| EFI_STATUS Status; | |
| UINT32 NotificationValue; | |
| UINT32 NotificationCount; | |
| UINT8 Count; | |
| 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); | |
| } | |
| do { | |
| SetFspApiReturnStatus(Status); | |
| Pei2LoaderSwitchStack(); | |
| if (Status != EFI_SUCCESS) { | |
| DEBUG ((DEBUG_ERROR, "!!!ERROR: NotifyPhaseApi() [Phase: %08X] - Failed - [Status: 0x%08X]\n", NotificationValue, Status)); | |
| } | |
| } while (Status != 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); | |
| } |