/** 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. // }
/** 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_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. // }
/** Migrate BootLoader data before destroying CAR. **/ VOID EFIAPI FspMigrateTemporaryMemory ( VOID ) { FSP_INIT_RT_COMMON_BUFFER *FspInitRtBuffer; UINT32 BootLoaderTempRamStart; UINT32 BootLoaderTempRamEnd; UINT32 BootLoaderTempRamSize; UINT32 OffsetGap; UINT32 FspParamPtr; FSP_INIT_PARAMS *FspInitParams; UINT32 *NewStackTop; VOID *BootLoaderTempRamHob; UINT32 UpdDataRgnPtr; UINT32 MemoryInitUpdPtr; UINT32 SiliconInitUpdPtr; VOID *PlatformDataPtr; UINT8 ApiMode; ApiMode = GetFspApiCallingMode (); // // Get the temporary memory range used by the BootLoader // BootLoaderTempRamStart = PcdGet32(PcdTemporaryRamBase); BootLoaderTempRamSize = PcdGet32(PcdTemporaryRamSize) - PcdGet32(PcdFspTemporaryRamSize); BootLoaderTempRamEnd = BootLoaderTempRamStart + BootLoaderTempRamSize; // // Build a Boot Loader Temporary Memory GUID HOB // if (ApiMode == 0) { BootLoaderTempRamHob = BuildGuidHob (&gFspBootLoaderTemporaryMemoryGuid, BootLoaderTempRamSize); } else { BootLoaderTempRamHob = (VOID *)AllocatePages (EFI_SIZE_TO_PAGES (BootLoaderTempRamSize)); } ASSERT(BootLoaderTempRamHob != NULL); CopyMem (BootLoaderTempRamHob, (VOID *)BootLoaderTempRamStart, BootLoaderTempRamSize); OffsetGap = (UINT32)BootLoaderTempRamHob - BootLoaderTempRamStart; // // Set a new stack frame for the continuation function // if (ApiMode == 0) { FspInitParams = (FSP_INIT_PARAMS *)GetFspApiParameter (); FspInitRtBuffer = (FSP_INIT_RT_COMMON_BUFFER *)FspInitParams->RtBufferPtr; NewStackTop = (UINT32 *)FspInitRtBuffer->StackTop - 1; SetFspCoreStackPointer (NewStackTop); } // // Fix the FspInit Parameter Pointers to the new location. // FspParamPtr = GetFspApiParameter (); if (FspParamPtr >= BootLoaderTempRamStart && FspParamPtr < BootLoaderTempRamEnd) { SetFspApiParameter(FspParamPtr + OffsetGap); } FspInitParams = (FSP_INIT_PARAMS *)GetFspApiParameter (); if ((UINT32)(FspInitParams->RtBufferPtr) >= BootLoaderTempRamStart && (UINT32)(FspInitParams->RtBufferPtr) < BootLoaderTempRamEnd) { FspInitParams->RtBufferPtr = (VOID *)((UINT32)(FspInitParams->RtBufferPtr) + OffsetGap); } if ((UINT32)(FspInitParams->NvsBufferPtr) >= BootLoaderTempRamStart && (UINT32)(FspInitParams->NvsBufferPtr) < BootLoaderTempRamEnd) { FspInitParams->NvsBufferPtr = (VOID *)((UINT32)(FspInitParams->NvsBufferPtr) + OffsetGap); } if ((UINT32)(((FSP_INIT_RT_COMMON_BUFFER *)(FspInitParams->RtBufferPtr))->UpdDataRgnPtr) >= BootLoaderTempRamStart && (UINT32)(((FSP_INIT_RT_COMMON_BUFFER *)(FspInitParams->RtBufferPtr))->UpdDataRgnPtr) < BootLoaderTempRamEnd) { ((FSP_INIT_RT_COMMON_BUFFER *)(FspInitParams->RtBufferPtr))->UpdDataRgnPtr = \ (VOID *)((UINT32)(((FSP_INIT_RT_COMMON_BUFFER *)(FspInitParams->RtBufferPtr))->UpdDataRgnPtr) + OffsetGap); } // // Update UPD pointer in FSP Global Data // if (ApiMode == 0) { UpdDataRgnPtr = (UINT32)((UINT32 *)GetFspUpdDataPointer ()); if (UpdDataRgnPtr >= BootLoaderTempRamStart && UpdDataRgnPtr < BootLoaderTempRamEnd) { MemoryInitUpdPtr = (UINT32)((UINT32 *)GetFspMemoryInitUpdDataPointer ()); SiliconInitUpdPtr = (UINT32)((UINT32 *)GetFspSiliconInitUpdDataPointer ()); SetFspUpdDataPointer ((VOID *)(UpdDataRgnPtr + OffsetGap)); SetFspMemoryInitUpdDataPointer ((VOID *)(MemoryInitUpdPtr + OffsetGap)); SetFspSiliconInitUpdDataPointer ((VOID *)(SiliconInitUpdPtr + OffsetGap)); } } else { MemoryInitUpdPtr = (UINT32)((UINT32 *)GetFspMemoryInitUpdDataPointer ()); if (MemoryInitUpdPtr >= BootLoaderTempRamStart && MemoryInitUpdPtr < BootLoaderTempRamEnd) { SetFspMemoryInitUpdDataPointer ((VOID *)(MemoryInitUpdPtr + OffsetGap)); } } // // Update Platform data pointer in FSP Global Data // PlatformDataPtr = GetFspPlatformDataPointer (); if (((UINT32)PlatformDataPtr >= BootLoaderTempRamStart) && ((UINT32)PlatformDataPtr < BootLoaderTempRamEnd)) { SetFspPlatformDataPointer ((UINT8 *)PlatformDataPtr + OffsetGap); } }