| /** @file | |
| Copyright (c) 2014 - 2015, 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 <FspApi.h> | |
| #include <Protocol/PciEnumerationComplete.h> | |
| 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 | |
| }; | |
| UINT32 mFspNotifySequence[] = { | |
| EnumInitPhaseAfterPciEnumeration, | |
| EnumInitPhaseReadyToBoot | |
| }; | |
| /** | |
| 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; | |
| default: | |
| Status = EFI_INVALID_PARAMETER; | |
| break; | |
| } | |
| return Status; | |
| } | |
| /** | |
| This function transfer control to the ContinuationFunc passed in by the | |
| BootLoader. | |
| **/ | |
| VOID | |
| EFIAPI | |
| FspInitDone ( | |
| VOID | |
| ) | |
| { | |
| FSP_INIT_PARAMS *FspInitParams; | |
| if (GetFspApiCallingMode() == 0) { | |
| // | |
| // FspInit API is used, so jump into the ContinuationFunc | |
| // | |
| FspInitParams = (FSP_INIT_PARAMS *)GetFspApiParameter (); | |
| // | |
| // Modify the parameters for ContinuationFunc | |
| // | |
| SetFspContinuationFuncParameter(EFI_SUCCESS, 0); | |
| SetFspContinuationFuncParameter((UINT32)GetHobList(), 1); | |
| // | |
| // Modify the return address to ContinuationFunc | |
| // | |
| SetFspApiReturnAddress((UINT32)FspInitParams->ContinuationFunc); | |
| // | |
| // Give control back to the boot loader framework caller after FspInit is done | |
| // It is done throught the continuation function | |
| // | |
| SetFspMeasurePoint (FSP_PERF_ID_API_FSPINIT_EXIT); | |
| } else { | |
| // | |
| // FspMemoryInit API is used, so return directly | |
| // | |
| // | |
| // This is the end of the FspSiliconInit API | |
| // Give control back to the boot loader | |
| // | |
| DEBUG ((DEBUG_INFO | DEBUG_INIT, "FspSiliconInitApi() - End\n")); | |
| SetFspApiReturnStatus (EFI_SUCCESS); | |
| } | |
| Pei2LoaderSwitchStack(); | |
| } | |
| /** | |
| 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_POSTPCI_ENTRY + Count); | |
| NotificationValue = ((NOTIFY_PHASE_PARAMS *)(UINTN)GetFspApiParameter ())->Phase; | |
| DEBUG ((DEBUG_INFO, "FSP Got Notification. Notification Value : 0x%08X\n", NotificationValue)); | |
| if (mFspNotifySequence[NotificationCount] != NotificationValue) { | |
| // | |
| // Notify code does not follow the predefined order | |
| // | |
| DEBUG ((DEBUG_INFO, "Unsupported FSP Notification Value\n")); | |
| SetFspApiReturnStatus(EFI_UNSUPPORTED); | |
| } else { | |
| // | |
| // Process Notification and Give control back to the boot loader framework caller | |
| // | |
| Status = FspNotificationHandler (NotificationValue); | |
| DEBUG ((DEBUG_INFO, "FSP Notification Handler Returns : 0x%08X\n", Status)); | |
| SetFspApiReturnStatus(Status); | |
| if (!EFI_ERROR(Status)) { | |
| NotificationCount++; | |
| SetFspApiReturnStatus(EFI_SUCCESS); | |
| if (NotificationValue == EnumInitPhaseReadyToBoot) { | |
| break; | |
| } | |
| } | |
| } | |
| SetFspMeasurePoint (FSP_PERF_ID_API_NOTIFY_POSTPCI_EXIT + Count); | |
| Pei2LoaderSwitchStack(); | |
| } | |
| // | |
| // 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. | |
| // | |
| } | |