--- /dev/null
+/** @file\r
+\r
+ Copyright (c) 2014, 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 <FspApi.h>\r
+#include <Protocol/PciEnumerationComplete.h>\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
+\r
+UINT32 mFspNotfifySequence[] = {\r
+ EnumInitPhaseAfterPciEnumeration,\r
+ EnumInitPhaseReadyToBoot\r
+};\r
+\r
+/**\r
+ Install FSP notification.\r
+\r
+ @param[in] NotificatonCode FSP notification code\r
+\r
+ @retval EFI_SUCCESS Notify FSP successfully\r
+ @retval EFI_INVALID_PARAMETER NotificatonCode is invalid\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+FspNotificationHandler (\r
+ IN UINT32 NotificatonCode\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+\r
+ Status = EFI_SUCCESS;\r
+\r
+ switch (NotificatonCode) {\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
+ default:\r
+ Status = EFI_INVALID_PARAMETER;\r
+ break;\r
+ }\r
+\r
+ return Status;\r
+}\r
+\r
+/**\r
+ This function transfer control to the ContinuationFunc passed in by the\r
+ bootloader.\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+FspInitDone (\r
+ VOID\r
+ )\r
+{\r
+ FSP_INIT_PARAMS *FspInitParams;\r
+\r
+ FspInitParams = (FSP_INIT_PARAMS *)GetFspApiParameter ();\r
+\r
+ //\r
+ // Modify the parameters for ContinuationFunc\r
+ //\r
+ SetFspContinuationFuncParameter(EFI_SUCCESS, 0);\r
+ SetFspContinuationFuncParameter((UINT32)GetHobList(), 1);\r
+\r
+ //\r
+ // Modify the return address to ContinuationFunc\r
+ //\r
+ SetFspApiReturnAddress((UINT32)FspInitParams->ContinuationFunc);\r
+\r
+ //\r
+ // Give control back to the boot loader framework caller after FspInit is done\r
+ // It is done throught the continuation function\r
+ //\r
+ SetFspMeasurePoint (FSP_PERF_ID_API_FSPINIT_EXIT);\r
+ Pei2LoaderSwitchStack();\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 NotificatonValue;\r
+ UINT32 NotificatonCount;\r
+ UINT8 Count;\r
+\r
+ NotificatonCount = 0;\r
+ while (NotificatonCount < sizeof(mFspNotfifySequence) / sizeof(UINT32)) {\r
+\r
+ Count = (NotificatonCount << 1) & 0x07;\r
+ SetFspMeasurePoint (FSP_PERF_ID_API_NOTIFY_POSTPCI_ENTRY + Count);\r
+\r
+ NotificatonValue = ((NOTIFY_PHASE_PARAMS *)(UINTN)GetFspApiParameter ())->Phase;\r
+ DEBUG ((DEBUG_INFO, "FSP Got Notification. Notification Value : 0x%08X\n", NotificatonValue));\r
+\r
+ if (mFspNotfifySequence[NotificatonCount] != NotificatonValue) {\r
+ //\r
+ // Notify code does not follow the predefined order\r
+ //\r
+ SetFspApiReturnStatus(EFI_UNSUPPORTED);\r
+ } else {\r
+ //\r
+ // Process Notification and Give control back to the boot loader framework caller\r
+ //\r
+ Status = FspNotificationHandler (NotificatonValue);\r
+ SetFspApiReturnStatus(Status);\r
+ if (!EFI_ERROR(Status)) {\r
+ NotificatonCount++;\r
+ SetFspApiReturnStatus(EFI_SUCCESS);\r
+ if (NotificatonValue == EnumInitPhaseReadyToBoot) {\r
+ break;\r
+ }\r
+ }\r
+ }\r
+ SetFspMeasurePoint (FSP_PERF_ID_API_NOTIFY_POSTPCI_EXIT + Count);\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