1 /** @file 2 3 Copyright (c) 2014 - 2015, Intel Corporation. All rights reserved.<BR> 4 This program and the accompanying materials 5 are licensed and made available under the terms and conditions of the BSD License 6 which accompanies this distribution. The full text of the license may be found at 7 http://opensource.org/licenses/bsd-license.php. 8 9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, 10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. 11 12 **/ 13 14 #include <PiPei.h> 15 #include <Library/PeiServicesLib.h> 16 #include <Library/PeiServicesTablePointerLib.h> 17 #include <Library/BaseLib.h> 18 #include <Library/BaseMemoryLib.h> 19 #include <Library/PcdLib.h> 20 #include <Library/DebugLib.h> 21 #include <Library/HobLib.h> 22 #include <Library/FspSwitchStackLib.h> 23 #include <Library/FspCommonLib.h> 24 #include <Guid/EventGroup.h> 25 #include <FspApi.h> 26 #include <Protocol/PciEnumerationComplete.h> 27 28 EFI_PEI_PPI_DESCRIPTOR mPeiPostPciEnumerationPpi = { 29 (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST), 30 &gEfiPciEnumerationCompleteProtocolGuid, 31 NULL 32 }; 33 34 EFI_PEI_PPI_DESCRIPTOR mPeiReadyToBootPpi = { 35 (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST), 36 &gEfiEventReadyToBootGuid, 37 NULL 38 }; 39 40 41 UINT32 mFspNotifySequence[] = { 42 EnumInitPhaseAfterPciEnumeration, 43 EnumInitPhaseReadyToBoot 44 }; 45 46 /** 47 Install FSP notification. 48 49 @param[in] NotificationCode FSP notification code 50 51 @retval EFI_SUCCESS Notify FSP successfully 52 @retval EFI_INVALID_PARAMETER NotificationCode is invalid 53 54 **/ 55 EFI_STATUS 56 EFIAPI 57 FspNotificationHandler ( 58 IN UINT32 NotificationCode 59 ) 60 { 61 EFI_STATUS Status; 62 63 Status = EFI_SUCCESS; 64 65 switch (NotificationCode) { 66 case EnumInitPhaseAfterPciEnumeration: 67 // 68 // Do POST PCI initialization if needed 69 // 70 DEBUG ((DEBUG_INFO | DEBUG_INIT, "FSP Post PCI Enumeration ...\n")); 71 PeiServicesInstallPpi (&mPeiPostPciEnumerationPpi); 72 break; 73 74 case EnumInitPhaseReadyToBoot: 75 // 76 // Ready To Boot 77 // 78 DEBUG ((DEBUG_INFO| DEBUG_INIT, "FSP Ready To Boot ...\n")); 79 PeiServicesInstallPpi (&mPeiReadyToBootPpi); 80 break; 81 82 default: 83 Status = EFI_INVALID_PARAMETER; 84 break; 85 } 86 87 return Status; 88 } 89 90 /** 91 This function transfer control to the ContinuationFunc passed in by the 92 BootLoader. 93 94 **/ 95 VOID 96 EFIAPI 97 FspInitDone ( 98 VOID 99 ) 100 { 101 FSP_INIT_PARAMS *FspInitParams; 102 103 if (GetFspApiCallingMode() == 0) { 104 // 105 // FspInit API is used, so jump into the ContinuationFunc 106 // 107 FspInitParams = (FSP_INIT_PARAMS *)GetFspApiParameter (); 108 109 // 110 // Modify the parameters for ContinuationFunc 111 // 112 SetFspContinuationFuncParameter(EFI_SUCCESS, 0); 113 SetFspContinuationFuncParameter((UINT32)GetHobList(), 1); 114 115 // 116 // Modify the return address to ContinuationFunc 117 // 118 SetFspApiReturnAddress((UINT32)FspInitParams->ContinuationFunc); 119 120 // 121 // Give control back to the boot loader framework caller after FspInit is done 122 // It is done throught the continuation function 123 // 124 SetFspMeasurePoint (FSP_PERF_ID_API_FSPINIT_EXIT); 125 } else { 126 // 127 // FspMemoryInit API is used, so return directly 128 // 129 130 // 131 // This is the end of the FspSiliconInit API 132 // Give control back to the boot loader 133 // 134 DEBUG ((DEBUG_INFO | DEBUG_INIT, "FspSiliconInitApi() - End\n")); 135 SetFspApiReturnStatus (EFI_SUCCESS); 136 } 137 138 Pei2LoaderSwitchStack(); 139 } 140 141 /** 142 This function handle NotifyPhase API call from the BootLoader. 143 It gives control back to the BootLoader after it is handled. If the 144 Notification code is a ReadyToBoot event, this function will return 145 and FSP continues the remaining execution until it reaches the DxeIpl. 146 147 **/ 148 VOID 149 FspWaitForNotify ( 150 VOID 151 ) 152 { 153 EFI_STATUS Status; 154 UINT32 NotificationValue; 155 UINT32 NotificationCount; 156 UINT8 Count; 157 158 NotificationCount = 0; 159 while (NotificationCount < sizeof(mFspNotifySequence) / sizeof(UINT32)) { 160 161 Count = (UINT8)((NotificationCount << 1) & 0x07); 162 SetFspMeasurePoint (FSP_PERF_ID_API_NOTIFY_POSTPCI_ENTRY + Count); 163 164 NotificationValue = ((NOTIFY_PHASE_PARAMS *)(UINTN)GetFspApiParameter ())->Phase; 165 DEBUG ((DEBUG_INFO, "FSP Got Notification. Notification Value : 0x%08X\n", NotificationValue)); 166 167 if (mFspNotifySequence[NotificationCount] != NotificationValue) { 168 // 169 // Notify code does not follow the predefined order 170 // 171 DEBUG ((DEBUG_INFO, "Unsupported FSP Notification Value\n")); 172 SetFspApiReturnStatus(EFI_UNSUPPORTED); 173 } else { 174 // 175 // Process Notification and Give control back to the boot loader framework caller 176 // 177 Status = FspNotificationHandler (NotificationValue); 178 DEBUG ((DEBUG_INFO, "FSP Notification Handler Returns : 0x%08X\n", Status)); 179 SetFspApiReturnStatus(Status); 180 if (!EFI_ERROR(Status)) { 181 NotificationCount++; 182 SetFspApiReturnStatus(EFI_SUCCESS); 183 if (NotificationValue == EnumInitPhaseReadyToBoot) { 184 break; 185 } 186 } 187 } 188 SetFspMeasurePoint (FSP_PERF_ID_API_NOTIFY_POSTPCI_EXIT + Count); 189 Pei2LoaderSwitchStack(); 190 } 191 192 // 193 // Control goes back to the PEI Core and it dispatches further PEIMs. 194 // DXEIPL is the final one to transfer control back to the boot loader. 195 // 196 } 197 198