/** @file Copyright (c) 2014 - 2015, Intel Corporation. All rights reserved.
SPDX-License-Identifier: BSD-2-Clause-Patent **/ #include #include #include #include #include #include #include #include #include #include #include #include #include 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. // }