1 /** @file 2 3 Copyright (c) 2014 - 2016, 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 <FspEas.h> 26 #include <FspStatusCode.h> 27 #include <Protocol/PciEnumerationComplete.h> 28 #include <Library/ReportStatusCodeLib.h> 29 #include <Library/PerformanceLib.h> 30 extern EFI_GUID gFspPerformanceDataGuid; 31 32 EFI_PEI_PPI_DESCRIPTOR mPeiPostPciEnumerationPpi = { 33 (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST), 34 &gEfiPciEnumerationCompleteProtocolGuid, 35 NULL 36 }; 37 38 EFI_PEI_PPI_DESCRIPTOR mPeiReadyToBootPpi = { 39 (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST), 40 &gEfiEventReadyToBootGuid, 41 NULL 42 }; 43 44 EFI_PEI_PPI_DESCRIPTOR mPeiEndOfFirmwarePpi = { 45 (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST), 46 &gFspEventEndOfFirmwareGuid, 47 NULL 48 }; 49 50 UINT32 mFspNotifySequence[] = { 51 EnumInitPhaseAfterPciEnumeration, 52 EnumInitPhaseReadyToBoot, 53 EnumInitPhaseEndOfFirmware 54 }; 55 56 /** 57 Install FSP notification. 58 59 @param[in] NotificationCode FSP notification code 60 61 @retval EFI_SUCCESS Notify FSP successfully 62 @retval EFI_INVALID_PARAMETER NotificationCode is invalid 63 64 **/ 65 EFI_STATUS 66 EFIAPI 67 FspNotificationHandler ( 68 IN UINT32 NotificationCode 69 ) 70 { 71 EFI_STATUS Status; 72 73 Status = EFI_SUCCESS; 74 75 switch (NotificationCode) { 76 case EnumInitPhaseAfterPciEnumeration: 77 // 78 // Do POST PCI initialization if needed 79 // 80 DEBUG ((DEBUG_INFO | DEBUG_INIT, "FSP Post PCI Enumeration ...\n")); 81 PeiServicesInstallPpi (&mPeiPostPciEnumerationPpi); 82 break; 83 84 case EnumInitPhaseReadyToBoot: 85 // 86 // Ready To Boot 87 // 88 DEBUG ((DEBUG_INFO| DEBUG_INIT, "FSP Ready To Boot ...\n")); 89 PeiServicesInstallPpi (&mPeiReadyToBootPpi); 90 break; 91 92 case EnumInitPhaseEndOfFirmware: 93 // 94 // End of Firmware 95 // 96 DEBUG ((DEBUG_INFO| DEBUG_INIT, "FSP End of Firmware ...\n")); 97 PeiServicesInstallPpi (&mPeiEndOfFirmwarePpi); 98 break; 99 100 default: 101 Status = EFI_INVALID_PARAMETER; 102 break; 103 } 104 105 return Status; 106 } 107 108 /** 109 This function transfer control back to BootLoader after FspSiliconInit. 110 111 @param[in] Status return status for the FspSiliconInit. 112 113 **/ 114 VOID 115 EFIAPI 116 FspSiliconInitDone2 ( 117 IN EFI_STATUS Status 118 ) 119 { 120 // 121 // Convert to FSP EAS defined API return codes 122 // 123 switch (Status) { 124 case EFI_SUCCESS: 125 case EFI_INVALID_PARAMETER: 126 case EFI_UNSUPPORTED: 127 case EFI_DEVICE_ERROR: 128 break; 129 default: 130 DEBUG ((DEBUG_INFO | DEBUG_INIT, "FspSiliconInitApi() Invalid Error - [Status: 0x%08X]\n", Status)); 131 Status = EFI_DEVICE_ERROR; // Force to known error. 132 break; 133 } 134 // 135 // This is the end of the FspSiliconInit API 136 // Give control back to the boot loader 137 // 138 SetFspMeasurePoint (FSP_PERF_ID_API_FSP_SILICON_INIT_EXIT); 139 DEBUG ((DEBUG_INFO | DEBUG_INIT, "FspSiliconInitApi() - [Status: 0x%08X] - End\n", Status)); 140 PERF_END_EX (&gFspPerformanceDataGuid, "EventRec", NULL, 0, FSP_STATUS_CODE_SILICON_INIT | FSP_STATUS_CODE_COMMON_CODE | FSP_STATUS_CODE_API_EXIT); 141 REPORT_STATUS_CODE (EFI_PROGRESS_CODE, FSP_STATUS_CODE_COMMON_CODE | FSP_STATUS_CODE_API_EXIT); 142 do { 143 SetFspApiReturnStatus (Status); 144 Pei2LoaderSwitchStack (); 145 if (Status != EFI_SUCCESS) { 146 DEBUG ((DEBUG_ERROR, "!!!ERROR: FspSiliconInitApi() - [Status: 0x%08X] - Error encountered during previous API and cannot proceed further\n", Status)); 147 } 148 } while (Status != EFI_SUCCESS); 149 } 150 151 /** 152 This function returns control to BootLoader after MemoryInitApi. 153 154 @param[in] Status return status for the MemoryInitApi. 155 @param[in,out] HobListPtr The address of HobList pointer, if NULL, will get value from GetFspApiParameter2 () 156 **/ 157 VOID 158 EFIAPI 159 FspMemoryInitDone2 ( 160 IN EFI_STATUS Status, 161 IN OUT VOID **HobListPtr 162 ) 163 { 164 FSP_GLOBAL_DATA *FspData; 165 // 166 // Calling use FspMemoryInit API 167 // Update HOB and return the control directly 168 // 169 if (HobListPtr == NULL) { 170 HobListPtr = (VOID **)GetFspApiParameter2 (); 171 } 172 if (HobListPtr != NULL) { 173 *HobListPtr = (VOID *) GetHobList (); 174 } 175 // 176 // Convert to FSP EAS defined API return codes 177 // 178 switch (Status) { 179 case EFI_SUCCESS: 180 case EFI_INVALID_PARAMETER: 181 case EFI_UNSUPPORTED: 182 case EFI_DEVICE_ERROR: 183 case EFI_OUT_OF_RESOURCES: 184 break; 185 default: 186 DEBUG ((DEBUG_INFO | DEBUG_INIT, "FspMemoryInitApi() Invalid Error [Status: 0x%08X]\n", Status)); 187 Status = EFI_DEVICE_ERROR; // Force to known error. 188 break; 189 } 190 // 191 // This is the end of the FspMemoryInit API 192 // Give control back to the boot loader 193 // 194 DEBUG ((DEBUG_INFO | DEBUG_INIT, "FspMemoryInitApi() - [Status: 0x%08X] - End\n", Status)); 195 SetFspMeasurePoint (FSP_PERF_ID_API_FSP_MEMORY_INIT_EXIT); 196 FspData = GetFspGlobalDataPointer (); 197 PERF_START_EX(&gFspPerformanceDataGuid, "EventRec", NULL, (FspData->PerfData[0] & FSP_PERFORMANCE_DATA_TIMER_MASK), FSP_STATUS_CODE_TEMP_RAM_INIT | FSP_STATUS_CODE_COMMON_CODE| FSP_STATUS_CODE_API_ENTRY); 198 PERF_END_EX(&gFspPerformanceDataGuid, "EventRec", NULL, (FspData->PerfData[1] & FSP_PERFORMANCE_DATA_TIMER_MASK), FSP_STATUS_CODE_TEMP_RAM_INIT | FSP_STATUS_CODE_COMMON_CODE | FSP_STATUS_CODE_API_EXIT); 199 PERF_START_EX(&gFspPerformanceDataGuid, "EventRec", NULL, (FspData->PerfData[2] & FSP_PERFORMANCE_DATA_TIMER_MASK), FSP_STATUS_CODE_MEMORY_INIT | FSP_STATUS_CODE_COMMON_CODE | FSP_STATUS_CODE_API_ENTRY); 200 PERF_END_EX(&gFspPerformanceDataGuid, "EventRec", NULL, 0, FSP_STATUS_CODE_MEMORY_INIT | FSP_STATUS_CODE_COMMON_CODE | FSP_STATUS_CODE_API_EXIT); 201 REPORT_STATUS_CODE (EFI_PROGRESS_CODE, FSP_STATUS_CODE_MEMORY_INIT | FSP_STATUS_CODE_COMMON_CODE | FSP_STATUS_CODE_API_EXIT); 202 do { 203 SetFspApiReturnStatus (Status); 204 Pei2LoaderSwitchStack (); 205 if (Status != EFI_SUCCESS) { 206 DEBUG ((DEBUG_ERROR, "!!!ERROR: FspMemoryInitApi() - [Status: 0x%08X] - Error encountered during previous API and cannot proceed further\n", Status)); 207 } 208 } while (Status != EFI_SUCCESS); 209 210 // 211 // The TempRamExitApi is called 212 // 213 if (GetFspApiCallingIndex () == TempRamExitApiIndex) { 214 SetPhaseStatusCode (FSP_STATUS_CODE_TEMP_RAM_EXIT); 215 SetFspMeasurePoint (FSP_PERF_ID_API_TEMP_RAM_EXIT_ENTRY); 216 PERF_START_EX(&gFspPerformanceDataGuid, "EventRec", NULL, 0, FSP_STATUS_CODE_TEMP_RAM_EXIT | FSP_STATUS_CODE_COMMON_CODE | FSP_STATUS_CODE_API_ENTRY); 217 REPORT_STATUS_CODE (EFI_PROGRESS_CODE, FSP_STATUS_CODE_TEMP_RAM_EXIT | FSP_STATUS_CODE_COMMON_CODE | FSP_STATUS_CODE_API_ENTRY); 218 DEBUG ((DEBUG_INFO | DEBUG_INIT, "TempRamExitApi() - Begin\n")); 219 } else { 220 SetPhaseStatusCode (FSP_STATUS_CODE_SILICON_INIT); 221 SetFspMeasurePoint (FSP_PERF_ID_API_FSP_SILICON_INIT_ENTRY); 222 PERF_START_EX(&gFspPerformanceDataGuid, "EventRec", NULL, 0, FSP_STATUS_CODE_SILICON_INIT | FSP_STATUS_CODE_COMMON_CODE | FSP_STATUS_CODE_API_ENTRY); 223 REPORT_STATUS_CODE (EFI_PROGRESS_CODE, FSP_STATUS_CODE_SILICON_INIT | FSP_STATUS_CODE_COMMON_CODE | FSP_STATUS_CODE_API_ENTRY); 224 DEBUG ((DEBUG_INFO | DEBUG_INIT, "FspSiliconInitApi() - Begin\n")); 225 } 226 } 227 228 /** 229 This function returns control to BootLoader after TempRamExitApi. 230 231 @param[in] Status return status for the TempRamExitApi. 232 233 **/ 234 VOID 235 EFIAPI 236 FspTempRamExitDone2 ( 237 IN EFI_STATUS Status 238 ) 239 { 240 // 241 // Convert to FSP EAS defined API return codes 242 // 243 switch (Status) { 244 case EFI_SUCCESS: 245 case EFI_INVALID_PARAMETER: 246 case EFI_UNSUPPORTED: 247 case EFI_DEVICE_ERROR: 248 break; 249 default: 250 DEBUG ((DEBUG_INFO | DEBUG_INIT, "TempRamExitApi() Invalid Error - [Status: 0x%08X]\n", Status)); 251 Status = EFI_DEVICE_ERROR; // Force to known error. 252 break; 253 } 254 // 255 // This is the end of the TempRamExit API 256 // Give control back to the boot loader 257 // 258 DEBUG ((DEBUG_INFO | DEBUG_INIT, "TempRamExitApi() - [Status: 0x%08X] - End\n", Status)); 259 SetFspMeasurePoint (FSP_PERF_ID_API_TEMP_RAM_EXIT_EXIT); 260 PERF_END_EX(&gFspPerformanceDataGuid, "EventRec", NULL, 0, FSP_STATUS_CODE_TEMP_RAM_EXIT | FSP_STATUS_CODE_COMMON_CODE | FSP_STATUS_CODE_API_EXIT); 261 REPORT_STATUS_CODE (EFI_PROGRESS_CODE, FSP_STATUS_CODE_TEMP_RAM_EXIT | FSP_STATUS_CODE_COMMON_CODE | FSP_STATUS_CODE_API_EXIT); 262 do { 263 SetFspApiReturnStatus (Status); 264 Pei2LoaderSwitchStack (); 265 if (Status != EFI_SUCCESS) { 266 DEBUG ((DEBUG_ERROR, "!!!ERROR: TempRamExitApi() - [Status: 0x%08X] - Error encountered during previous API and cannot proceed further\n", Status)); 267 } 268 } while (Status != EFI_SUCCESS); 269 SetPhaseStatusCode (FSP_STATUS_CODE_SILICON_INIT); 270 SetFspMeasurePoint (FSP_PERF_ID_API_FSP_SILICON_INIT_ENTRY); 271 PERF_START_EX(&gFspPerformanceDataGuid, "EventRec", NULL, 0, FSP_STATUS_CODE_SILICON_INIT | FSP_STATUS_CODE_COMMON_CODE | FSP_STATUS_CODE_API_ENTRY); 272 REPORT_STATUS_CODE (EFI_PROGRESS_CODE, FSP_STATUS_CODE_SILICON_INIT | FSP_STATUS_CODE_COMMON_CODE | FSP_STATUS_CODE_API_ENTRY); 273 DEBUG ((DEBUG_INFO | DEBUG_INIT, "SiliconInitApi() - Begin\n")); 274 } 275 276 /** 277 This function handle NotifyPhase API call from the BootLoader. 278 It gives control back to the BootLoader after it is handled. If the 279 Notification code is a ReadyToBoot event, this function will return 280 and FSP continues the remaining execution until it reaches the DxeIpl. 281 282 **/ 283 VOID 284 FspWaitForNotify ( 285 VOID 286 ) 287 { 288 EFI_STATUS Status; 289 UINT32 NotificationValue; 290 UINT32 NotificationCount; 291 UINT8 Count; 292 293 NotificationCount = 0; 294 while (NotificationCount < sizeof(mFspNotifySequence) / sizeof(UINT32)) { 295 296 Count = (UINT8)((NotificationCount << 1) & 0x07); 297 SetFspMeasurePoint (FSP_PERF_ID_API_NOTIFY_POST_PCI_ENTRY + Count); 298 299 if (NotificationCount == 0) { 300 SetPhaseStatusCode (FSP_STATUS_CODE_POST_PCIE_ENUM_NOTIFICATION); 301 PERF_START_EX (&gFspPerformanceDataGuid, "EventRec", NULL, 0, FSP_STATUS_CODE_POST_PCIE_ENUM_NOTIFICATION | FSP_STATUS_CODE_COMMON_CODE | FSP_STATUS_CODE_API_ENTRY); 302 REPORT_STATUS_CODE (EFI_PROGRESS_CODE, FSP_STATUS_CODE_POST_PCIE_ENUM_NOTIFICATION | FSP_STATUS_CODE_COMMON_CODE | FSP_STATUS_CODE_API_ENTRY); 303 } else if (NotificationCount == 1) { 304 SetPhaseStatusCode (FSP_STATUS_CODE_READY_TO_BOOT_NOTIFICATION); 305 PERF_START_EX(&gFspPerformanceDataGuid, "EventRec", NULL, 0, FSP_STATUS_CODE_READY_TO_BOOT_NOTIFICATION | FSP_STATUS_CODE_COMMON_CODE | FSP_STATUS_CODE_API_ENTRY); 306 REPORT_STATUS_CODE (EFI_PROGRESS_CODE, FSP_STATUS_CODE_READY_TO_BOOT_NOTIFICATION | FSP_STATUS_CODE_COMMON_CODE | FSP_STATUS_CODE_API_ENTRY); 307 } else if (NotificationCount == 2) { 308 SetPhaseStatusCode (FSP_STATUS_CODE_END_OF_FIRMWARE_NOTIFICATION); 309 PERF_START_EX (&gFspPerformanceDataGuid, "EventRec", NULL, 0, FSP_STATUS_CODE_END_OF_FIRMWARE_NOTIFICATION | FSP_STATUS_CODE_COMMON_CODE | FSP_STATUS_CODE_API_ENTRY); 310 REPORT_STATUS_CODE (EFI_PROGRESS_CODE, FSP_STATUS_CODE_END_OF_FIRMWARE_NOTIFICATION | FSP_STATUS_CODE_COMMON_CODE | FSP_STATUS_CODE_API_ENTRY); 311 } 312 313 NotificationValue = ((NOTIFY_PHASE_PARAMS *)(UINTN)GetFspApiParameter ())->Phase; 314 DEBUG ((DEBUG_INFO | DEBUG_INIT, "NotifyPhaseApi() - Begin [Phase: %08X]\n", NotificationValue)); 315 if (mFspNotifySequence[NotificationCount] != NotificationValue) { 316 // 317 // Notify code does not follow the predefined order 318 // 319 DEBUG ((DEBUG_INFO, "Unsupported FSP Notification Value\n")); 320 Status = EFI_UNSUPPORTED; 321 } else { 322 // 323 // Process Notification and Give control back to the boot loader framework caller 324 // 325 Status = FspNotificationHandler (NotificationValue); 326 if (!EFI_ERROR(Status)) { 327 NotificationCount++; 328 } 329 } 330 331 DEBUG ((DEBUG_INFO | DEBUG_INIT, "NotifyPhaseApi() - End [Status: 0x%08X]\n", Status)); 332 SetFspMeasurePoint (FSP_PERF_ID_API_NOTIFY_POST_PCI_EXIT + Count); 333 334 if ((NotificationCount - 1) == 0) { 335 PERF_END_EX(&gFspPerformanceDataGuid, "EventRec", NULL, 0, FSP_STATUS_CODE_POST_PCIE_ENUM_NOTIFICATION | FSP_STATUS_CODE_COMMON_CODE | FSP_STATUS_CODE_API_EXIT); 336 REPORT_STATUS_CODE (EFI_PROGRESS_CODE, FSP_STATUS_CODE_POST_PCIE_ENUM_NOTIFICATION | FSP_STATUS_CODE_COMMON_CODE | FSP_STATUS_CODE_API_EXIT); 337 } else if ((NotificationCount - 1) == 1) { 338 PERF_END_EX(&gFspPerformanceDataGuid, "EventRec", NULL, 0, FSP_STATUS_CODE_READY_TO_BOOT_NOTIFICATION | FSP_STATUS_CODE_COMMON_CODE | FSP_STATUS_CODE_API_EXIT); 339 REPORT_STATUS_CODE (EFI_PROGRESS_CODE, FSP_STATUS_CODE_READY_TO_BOOT_NOTIFICATION | FSP_STATUS_CODE_COMMON_CODE | FSP_STATUS_CODE_API_EXIT); 340 } else if ((NotificationCount - 1) == 2) { 341 PERF_END_EX(&gFspPerformanceDataGuid, "EventRec", NULL, 0, FSP_STATUS_CODE_END_OF_FIRMWARE_NOTIFICATION | FSP_STATUS_CODE_COMMON_CODE | FSP_STATUS_CODE_API_EXIT); 342 REPORT_STATUS_CODE (EFI_PROGRESS_CODE, FSP_STATUS_CODE_END_OF_FIRMWARE_NOTIFICATION | FSP_STATUS_CODE_COMMON_CODE | FSP_STATUS_CODE_API_EXIT); 343 } 344 do { 345 SetFspApiReturnStatus(Status); 346 Pei2LoaderSwitchStack(); 347 if (Status != EFI_SUCCESS) { 348 DEBUG ((DEBUG_ERROR, "!!!ERROR: NotifyPhaseApi() [Phase: %08X] - Failed - [Status: 0x%08X]\n", NotificationValue, Status)); 349 } 350 } while (Status != EFI_SUCCESS); 351 } 352 353 // 354 // Control goes back to the PEI Core and it dispatches further PEIMs. 355 // DXEIPL is the final one to transfer control back to the boot loader. 356 // 357 } 358 359 /** 360 This function transfer control back to BootLoader after FspSiliconInit. 361 362 **/ 363 VOID 364 EFIAPI 365 FspSiliconInitDone ( 366 VOID 367 ) 368 { 369 FspSiliconInitDone2 (EFI_SUCCESS); 370 } 371 372 /** 373 This function returns control to BootLoader after MemoryInitApi. 374 375 @param[in,out] HobListPtr The address of HobList pointer. 376 **/ 377 VOID 378 EFIAPI 379 FspMemoryInitDone ( 380 IN OUT VOID **HobListPtr 381 ) 382 { 383 FspMemoryInitDone2 (EFI_SUCCESS, HobListPtr); 384 } 385 386 /** 387 This function returns control to BootLoader after TempRamExitApi. 388 389 **/ 390 VOID 391 EFIAPI 392 FspTempRamExitDone ( 393 VOID 394 ) 395 { 396 FspTempRamExitDone2 (EFI_SUCCESS); 397 } 398