--- /dev/null
+/** @file\r
+\r
+ Copyright (c) 2014 - 2016, Intel Corporation. All rights reserved.<BR>\r
+ This program and the accompanying materials\r
+ are licensed and made available under the terms and conditions of the BSD License\r
+ which accompanies this distribution. The full text of the license may be found at\r
+ http://opensource.org/licenses/bsd-license.php.\r
+\r
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include <PiPei.h>\r
+#include <Library/PeiServicesLib.h>\r
+#include <Library/PeiServicesTablePointerLib.h>\r
+#include <Library/BaseLib.h>\r
+#include <Library/BaseMemoryLib.h>\r
+#include <Library/PcdLib.h>\r
+#include <Library/DebugLib.h>\r
+#include <Library/HobLib.h>\r
+#include <Library/FspSwitchStackLib.h>\r
+#include <Library/FspCommonLib.h>\r
+#include <Guid/EventGroup.h>\r
+#include <FspEas.h>\r
+#include <FspStatusCode.h>\r
+#include <Protocol/PciEnumerationComplete.h>\r
+#include <Library/ReportStatusCodeLib.h>\r
+#include <Library/PerformanceLib.h>\r
+extern EFI_GUID gFspPerformanceDataGuid;\r
+\r
+EFI_PEI_PPI_DESCRIPTOR mPeiPostPciEnumerationPpi = {\r
+ (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),\r
+ &gEfiPciEnumerationCompleteProtocolGuid,\r
+ NULL\r
+};\r
+\r
+EFI_PEI_PPI_DESCRIPTOR mPeiReadyToBootPpi = {\r
+ (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),\r
+ &gEfiEventReadyToBootGuid,\r
+ NULL\r
+};\r
+\r
+EFI_PEI_PPI_DESCRIPTOR mPeiEndOfFirmwarePpi = {\r
+ (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),\r
+ &gFspEventEndOfFirmwareGuid,\r
+ NULL\r
+};\r
+\r
+UINT32 mFspNotifySequence[] = {\r
+ EnumInitPhaseAfterPciEnumeration,\r
+ EnumInitPhaseReadyToBoot,\r
+ EnumInitPhaseEndOfFirmware\r
+};\r
+\r
+/**\r
+ Install FSP notification.\r
+\r
+ @param[in] NotificationCode FSP notification code\r
+\r
+ @retval EFI_SUCCESS Notify FSP successfully\r
+ @retval EFI_INVALID_PARAMETER NotificationCode is invalid\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+FspNotificationHandler (\r
+ IN UINT32 NotificationCode\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+\r
+ Status = EFI_SUCCESS;\r
+\r
+ switch (NotificationCode) {\r
+ case EnumInitPhaseAfterPciEnumeration:\r
+ //\r
+ // Do POST PCI initialization if needed\r
+ //\r
+ DEBUG ((DEBUG_INFO | DEBUG_INIT, "FSP Post PCI Enumeration ...\n"));\r
+ PeiServicesInstallPpi (&mPeiPostPciEnumerationPpi);\r
+ break;\r
+\r
+ case EnumInitPhaseReadyToBoot:\r
+ //\r
+ // Ready To Boot\r
+ //\r
+ DEBUG ((DEBUG_INFO| DEBUG_INIT, "FSP Ready To Boot ...\n"));\r
+ PeiServicesInstallPpi (&mPeiReadyToBootPpi);\r
+ break;\r
+\r
+ case EnumInitPhaseEndOfFirmware:\r
+ //\r
+ // End of Firmware\r
+ //\r
+ DEBUG ((DEBUG_INFO| DEBUG_INIT, "FSP End of Firmware ...\n"));\r
+ PeiServicesInstallPpi (&mPeiEndOfFirmwarePpi);\r
+ break;\r
+\r
+ default:\r
+ Status = EFI_INVALID_PARAMETER;\r
+ break;\r
+ }\r
+\r
+ return Status;\r
+}\r
+\r
+/**\r
+ This function transfer control back to BootLoader after FspSiliconInit.\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+FspSiliconInitDone (\r
+ VOID\r
+ )\r
+{\r
+ //\r
+ // This is the end of the FspSiliconInit API\r
+ // Give control back to the boot loader\r
+ //\r
+ SetFspMeasurePoint (FSP_PERF_ID_API_FSP_SILICON_INIT_EXIT);\r
+ DEBUG ((DEBUG_INFO | DEBUG_INIT, "FspSiliconInitApi() - End\n"));\r
+\r
+ PERF_END_EX (&gFspPerformanceDataGuid, "EventRec", NULL, 0, 0x907F);\r
+\r
+ REPORT_STATUS_CODE (EFI_PROGRESS_CODE, FSP_STATUS_CODE_COMMON_CODE | FSP_STATUS_CODE_API_EXIT);\r
+ SetFspApiReturnStatus (EFI_SUCCESS);\r
+\r
+ Pei2LoaderSwitchStack();\r
+\r
+ PERF_START_EX (&gFspPerformanceDataGuid, "EventRec", NULL, 0, 0x6000);\r
+}\r
+\r
+/**\r
+ This function returns control to BootLoader after MemoryInitApi.\r
+\r
+ @param[in,out] HobListPtr The address of HobList pointer.\r
+**/\r
+VOID\r
+EFIAPI\r
+FspMemoryInitDone (\r
+ IN OUT VOID **HobListPtr\r
+ )\r
+{\r
+ //\r
+ // Calling use FspMemoryInit API\r
+ // Update HOB and return the control directly\r
+ //\r
+ if (HobListPtr != NULL) {\r
+ *HobListPtr = (VOID *) GetHobList ();\r
+ }\r
+\r
+ //\r
+ // This is the end of the FspMemoryInit API\r
+ // Give control back to the boot loader\r
+ //\r
+ SetFspMeasurePoint (FSP_PERF_ID_API_FSP_MEMORY_INIT_EXIT);\r
+ DEBUG ((DEBUG_INFO | DEBUG_INIT, "FspMemoryInitApi() - End\n"));\r
+ REPORT_STATUS_CODE (EFI_PROGRESS_CODE, FSP_STATUS_CODE_MEMORY_INIT | FSP_STATUS_CODE_COMMON_CODE | FSP_STATUS_CODE_API_EXIT);\r
+ SetFspApiReturnStatus (EFI_SUCCESS);\r
+ Pei2LoaderSwitchStack ();\r
+\r
+ //\r
+ // The TempRamExitApi is called\r
+ //\r
+ if (GetFspApiCallingIndex () == TempRamExitApiIndex) {\r
+ SetPhaseStatusCode (FSP_STATUS_CODE_TEMP_RAM_EXIT);\r
+ REPORT_STATUS_CODE (EFI_PROGRESS_CODE, FSP_STATUS_CODE_TEMP_RAM_EXIT | FSP_STATUS_CODE_COMMON_CODE | FSP_STATUS_CODE_API_ENTRY);\r
+ SetFspMeasurePoint (FSP_PERF_ID_API_TEMP_RAM_EXIT_ENTRY);\r
+ DEBUG ((DEBUG_INFO | DEBUG_INIT, "TempRamExitApi() - Begin\n"));\r
+ } else {\r
+ SetFspMeasurePoint (FSP_PERF_ID_API_FSP_SILICON_INIT_ENTRY);\r
+ DEBUG ((DEBUG_INFO | DEBUG_INIT, "FspSiliconInitApi() - Begin\n"));\r
+ SetPhaseStatusCode (FSP_STATUS_CODE_SILICON_INIT);\r
+ REPORT_STATUS_CODE (EFI_PROGRESS_CODE, FSP_STATUS_CODE_SILICON_INIT | FSP_STATUS_CODE_COMMON_CODE | FSP_STATUS_CODE_API_ENTRY);\r
+ }\r
+}\r
+\r
+/**\r
+ This function returns control to BootLoader after TempRamExitApi.\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+FspTempRamExitDone (\r
+ VOID\r
+ )\r
+{\r
+\r
+ //\r
+ // This is the end of the TempRamExit API\r
+ // Give control back to the boot loader\r
+ //\r
+ SetFspMeasurePoint (FSP_PERF_ID_API_TEMP_RAM_EXIT_EXIT);\r
+ DEBUG ((DEBUG_INFO | DEBUG_INIT, "TempRamExitApi() - End\n"));\r
+ REPORT_STATUS_CODE (EFI_PROGRESS_CODE, FSP_STATUS_CODE_TEMP_RAM_EXIT | FSP_STATUS_CODE_COMMON_CODE | FSP_STATUS_CODE_API_EXIT);\r
+ SetFspApiReturnStatus (EFI_SUCCESS);\r
+ Pei2LoaderSwitchStack ();\r
+\r
+ SetPhaseStatusCode (FSP_STATUS_CODE_SILICON_INIT);\r
+ SetFspMeasurePoint (FSP_PERF_ID_API_FSP_SILICON_INIT_ENTRY);\r
+ DEBUG ((DEBUG_INFO | DEBUG_INIT, "SiliconInitApi() - Begin\n"));\r
+ REPORT_STATUS_CODE (EFI_PROGRESS_CODE, FSP_STATUS_CODE_SILICON_INIT | FSP_STATUS_CODE_COMMON_CODE | FSP_STATUS_CODE_API_ENTRY);\r
+}\r
+\r
+/**\r
+ This function handle NotifyPhase API call from the BootLoader.\r
+ It gives control back to the BootLoader after it is handled. If the\r
+ Notification code is a ReadyToBoot event, this function will return\r
+ and FSP continues the remaining execution until it reaches the DxeIpl.\r
+\r
+**/\r
+VOID\r
+FspWaitForNotify (\r
+ VOID\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ UINT32 NotificationValue;\r
+ UINT32 NotificationCount;\r
+ UINT8 Count;\r
+\r
+ NotificationCount = 0;\r
+ while (NotificationCount < sizeof(mFspNotifySequence) / sizeof(UINT32)) {\r
+\r
+ Count = (UINT8)((NotificationCount << 1) & 0x07);\r
+ SetFspMeasurePoint (FSP_PERF_ID_API_NOTIFY_POST_PCI_ENTRY + Count);\r
+\r
+ if (NotificationCount == 0) {\r
+ SetPhaseStatusCode (FSP_STATUS_CODE_POST_PCIE_ENUM_NOTIFICATION);\r
+ REPORT_STATUS_CODE (EFI_PROGRESS_CODE, FSP_STATUS_CODE_POST_PCIE_ENUM_NOTIFICATION | FSP_STATUS_CODE_COMMON_CODE | FSP_STATUS_CODE_API_ENTRY);\r
+ } else if (NotificationCount == 1) {\r
+ SetPhaseStatusCode (FSP_STATUS_CODE_READY_TO_BOOT_NOTIFICATION);\r
+ REPORT_STATUS_CODE (EFI_PROGRESS_CODE, FSP_STATUS_CODE_READY_TO_BOOT_NOTIFICATION | FSP_STATUS_CODE_COMMON_CODE | FSP_STATUS_CODE_API_ENTRY);\r
+ } else if (NotificationCount == 2) {\r
+ SetPhaseStatusCode (FSP_STATUS_CODE_END_OF_FIRMWARE_NOTIFICATION);\r
+ REPORT_STATUS_CODE (EFI_PROGRESS_CODE, FSP_STATUS_CODE_END_OF_FIRMWARE_NOTIFICATION | FSP_STATUS_CODE_COMMON_CODE | FSP_STATUS_CODE_API_ENTRY);\r
+ }\r
+\r
+ NotificationValue = ((NOTIFY_PHASE_PARAMS *)(UINTN)GetFspApiParameter ())->Phase;\r
+ DEBUG ((DEBUG_INFO | DEBUG_INIT, "NotifyPhaseApi() - Begin [Phase: %08X]\n", NotificationValue));\r
+ if (mFspNotifySequence[NotificationCount] != NotificationValue) {\r
+ //\r
+ // Notify code does not follow the predefined order\r
+ //\r
+ DEBUG ((DEBUG_INFO, "Unsupported FSP Notification Value\n"));\r
+ Status = EFI_UNSUPPORTED;\r
+ } else {\r
+ //\r
+ // Process Notification and Give control back to the boot loader framework caller\r
+ //\r
+ Status = FspNotificationHandler (NotificationValue);\r
+ if (!EFI_ERROR(Status)) {\r
+ NotificationCount++;\r
+ }\r
+ }\r
+\r
+ SetFspApiReturnStatus(Status);\r
+ DEBUG ((DEBUG_INFO | DEBUG_INIT, "NotifyPhaseApi() - End [Status: 0x%08X]\n", Status));\r
+\r
+ SetFspMeasurePoint (FSP_PERF_ID_API_NOTIFY_POST_PCI_EXIT + Count);\r
+\r
+ if ((NotificationCount - 1) == 0) {\r
+ REPORT_STATUS_CODE (EFI_PROGRESS_CODE, FSP_STATUS_CODE_POST_PCIE_ENUM_NOTIFICATION | FSP_STATUS_CODE_COMMON_CODE | FSP_STATUS_CODE_API_EXIT);\r
+ } else if ((NotificationCount - 1) == 1) {\r
+ REPORT_STATUS_CODE (EFI_PROGRESS_CODE, FSP_STATUS_CODE_READY_TO_BOOT_NOTIFICATION | FSP_STATUS_CODE_COMMON_CODE | FSP_STATUS_CODE_API_EXIT);\r
+ } else if ((NotificationCount - 1) == 2) {\r
+ REPORT_STATUS_CODE (EFI_PROGRESS_CODE, FSP_STATUS_CODE_END_OF_FIRMWARE_NOTIFICATION | FSP_STATUS_CODE_COMMON_CODE | FSP_STATUS_CODE_API_EXIT);\r
+ }\r
+ Pei2LoaderSwitchStack();\r
+ }\r
+\r
+ //\r
+ // Control goes back to the PEI Core and it dispatches further PEIMs.\r
+ // DXEIPL is the final one to transfer control back to the boot loader.\r
+ //\r
+}\r
+\r