3 Copyright (c) 2014 - 2018, Intel Corporation. All rights reserved.<BR>
4 SPDX-License-Identifier: BSD-2-Clause-Patent
9 #include <Library/PeiServicesLib.h>
10 #include <Library/PeiServicesTablePointerLib.h>
11 #include <Library/BaseLib.h>
12 #include <Library/BaseMemoryLib.h>
13 #include <Library/PcdLib.h>
14 #include <Library/DebugLib.h>
15 #include <Library/HobLib.h>
16 #include <Library/FspSwitchStackLib.h>
17 #include <Library/FspCommonLib.h>
18 #include <Guid/EventGroup.h>
20 #include <FspStatusCode.h>
21 #include <Protocol/PciEnumerationComplete.h>
22 #include <Library/ReportStatusCodeLib.h>
23 #include <Library/PerformanceLib.h>
24 extern EFI_GUID gFspPerformanceDataGuid
;
26 EFI_PEI_PPI_DESCRIPTOR mPeiPostPciEnumerationPpi
= {
27 (EFI_PEI_PPI_DESCRIPTOR_PPI
| EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST
),
28 &gEfiPciEnumerationCompleteProtocolGuid
,
32 EFI_PEI_PPI_DESCRIPTOR mPeiReadyToBootPpi
= {
33 (EFI_PEI_PPI_DESCRIPTOR_PPI
| EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST
),
34 &gEfiEventReadyToBootGuid
,
38 EFI_PEI_PPI_DESCRIPTOR mPeiEndOfFirmwarePpi
= {
39 (EFI_PEI_PPI_DESCRIPTOR_PPI
| EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST
),
40 &gFspEventEndOfFirmwareGuid
,
44 UINT32 mFspNotifySequence
[] = {
45 EnumInitPhaseAfterPciEnumeration
,
46 EnumInitPhaseReadyToBoot
,
47 EnumInitPhaseEndOfFirmware
51 Install FSP notification.
53 @param[in] NotificationCode FSP notification code
55 @retval EFI_SUCCESS Notify FSP successfully
56 @retval EFI_INVALID_PARAMETER NotificationCode is invalid
61 FspNotificationHandler (
62 IN UINT32 NotificationCode
69 switch (NotificationCode
) {
70 case EnumInitPhaseAfterPciEnumeration
:
72 // Do POST PCI initialization if needed
74 DEBUG ((DEBUG_INFO
| DEBUG_INIT
, "FSP Post PCI Enumeration ...\n"));
75 PeiServicesInstallPpi (&mPeiPostPciEnumerationPpi
);
78 case EnumInitPhaseReadyToBoot
:
82 DEBUG ((DEBUG_INFO
| DEBUG_INIT
, "FSP Ready To Boot ...\n"));
83 PeiServicesInstallPpi (&mPeiReadyToBootPpi
);
86 case EnumInitPhaseEndOfFirmware
:
90 DEBUG ((DEBUG_INFO
| DEBUG_INIT
, "FSP End of Firmware ...\n"));
91 PeiServicesInstallPpi (&mPeiEndOfFirmwarePpi
);
95 Status
= EFI_INVALID_PARAMETER
;
103 This function transfer control back to BootLoader after FspSiliconInit.
105 @param[in] Status return status for the FspSiliconInit.
110 FspSiliconInitDone2 (
114 volatile EFI_STATUS FspStatus
;
118 // Convert to FSP EAS defined API return codes
122 case EFI_INVALID_PARAMETER
:
123 case EFI_UNSUPPORTED
:
124 case EFI_DEVICE_ERROR
:
127 DEBUG ((DEBUG_INFO
| DEBUG_INIT
, "FspSiliconInitApi() Invalid Error - [Status: 0x%08X]\n", Status
));
128 Status
= EFI_DEVICE_ERROR
; // Force to known error.
133 // This is the end of the FspSiliconInit API
134 // Give control back to the boot loader
136 SetFspMeasurePoint (FSP_PERF_ID_API_FSP_SILICON_INIT_EXIT
);
137 DEBUG ((DEBUG_INFO
| DEBUG_INIT
, "FspSiliconInitApi() - [Status: 0x%08X] - End\n", Status
));
138 PERF_END_EX (&gFspPerformanceDataGuid
, "EventRec", NULL
, 0, FSP_STATUS_CODE_SILICON_INIT
| FSP_STATUS_CODE_COMMON_CODE
| FSP_STATUS_CODE_API_EXIT
);
139 REPORT_STATUS_CODE (EFI_PROGRESS_CODE
, FSP_STATUS_CODE_COMMON_CODE
| FSP_STATUS_CODE_API_EXIT
);
140 if (GetFspGlobalDataPointer ()->FspMode
== FSP_IN_API_MODE
) {
142 SetFspApiReturnStatus (Status
);
143 Pei2LoaderSwitchStack ();
144 if (Status
!= EFI_SUCCESS
) {
145 DEBUG ((DEBUG_ERROR
, "!!!ERROR: FspSiliconInitApi() - [Status: 0x%08X] - Error encountered during previous API and cannot proceed further\n", Status
));
147 } while (FspStatus
!= EFI_SUCCESS
);
152 This function returns control to BootLoader after MemoryInitApi.
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 ()
160 IN EFI_STATUS Status
,
161 IN OUT VOID
**HobListPtr
164 FSP_GLOBAL_DATA
*FspData
;
165 volatile EFI_STATUS FspStatus
;
169 // Calling use FspMemoryInit API
170 // Update HOB and return the control directly
172 if (HobListPtr
== NULL
) {
173 HobListPtr
= (VOID
**)GetFspApiParameter2 ();
176 if (HobListPtr
!= NULL
) {
177 *HobListPtr
= (VOID
*)GetHobList ();
181 // Convert to FSP EAS defined API return codes
185 case EFI_INVALID_PARAMETER
:
186 case EFI_UNSUPPORTED
:
187 case EFI_DEVICE_ERROR
:
188 case EFI_OUT_OF_RESOURCES
:
191 DEBUG ((DEBUG_INFO
| DEBUG_INIT
, "FspMemoryInitApi() Invalid Error [Status: 0x%08X]\n", Status
));
192 Status
= EFI_DEVICE_ERROR
; // Force to known error.
197 // This is the end of the FspMemoryInit API
198 // Give control back to the boot loader
200 DEBUG ((DEBUG_INFO
| DEBUG_INIT
, "FspMemoryInitApi() - [Status: 0x%08X] - End\n", Status
));
201 SetFspMeasurePoint (FSP_PERF_ID_API_FSP_MEMORY_INIT_EXIT
);
202 FspData
= GetFspGlobalDataPointer ();
203 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
);
204 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
);
205 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
);
206 PERF_END_EX (&gFspPerformanceDataGuid
, "EventRec", NULL
, 0, FSP_STATUS_CODE_MEMORY_INIT
| FSP_STATUS_CODE_COMMON_CODE
| FSP_STATUS_CODE_API_EXIT
);
207 REPORT_STATUS_CODE (EFI_PROGRESS_CODE
, FSP_STATUS_CODE_MEMORY_INIT
| FSP_STATUS_CODE_COMMON_CODE
| FSP_STATUS_CODE_API_EXIT
);
208 if (GetFspGlobalDataPointer ()->FspMode
== FSP_IN_API_MODE
) {
210 SetFspApiReturnStatus (Status
);
211 Pei2LoaderSwitchStack ();
212 if (Status
!= EFI_SUCCESS
) {
213 DEBUG ((DEBUG_ERROR
, "!!!ERROR: FspMemoryInitApi() - [Status: 0x%08X] - Error encountered during previous API and cannot proceed further\n", Status
));
215 } while (FspStatus
!= EFI_SUCCESS
);
219 // The TempRamExitApi is called
221 if (GetFspApiCallingIndex () == TempRamExitApiIndex
) {
222 SetPhaseStatusCode (FSP_STATUS_CODE_TEMP_RAM_EXIT
);
223 SetFspMeasurePoint (FSP_PERF_ID_API_TEMP_RAM_EXIT_ENTRY
);
224 PERF_START_EX (&gFspPerformanceDataGuid
, "EventRec", NULL
, 0, FSP_STATUS_CODE_TEMP_RAM_EXIT
| FSP_STATUS_CODE_COMMON_CODE
| FSP_STATUS_CODE_API_ENTRY
);
225 REPORT_STATUS_CODE (EFI_PROGRESS_CODE
, FSP_STATUS_CODE_TEMP_RAM_EXIT
| FSP_STATUS_CODE_COMMON_CODE
| FSP_STATUS_CODE_API_ENTRY
);
226 DEBUG ((DEBUG_INFO
| DEBUG_INIT
, "TempRamExitApi() - Begin\n"));
228 SetPhaseStatusCode (FSP_STATUS_CODE_SILICON_INIT
);
229 SetFspMeasurePoint (FSP_PERF_ID_API_FSP_SILICON_INIT_ENTRY
);
230 PERF_START_EX (&gFspPerformanceDataGuid
, "EventRec", NULL
, 0, FSP_STATUS_CODE_SILICON_INIT
| FSP_STATUS_CODE_COMMON_CODE
| FSP_STATUS_CODE_API_ENTRY
);
231 REPORT_STATUS_CODE (EFI_PROGRESS_CODE
, FSP_STATUS_CODE_SILICON_INIT
| FSP_STATUS_CODE_COMMON_CODE
| FSP_STATUS_CODE_API_ENTRY
);
232 DEBUG ((DEBUG_INFO
| DEBUG_INIT
, "FspSiliconInitApi() - Begin\n"));
237 This function returns control to BootLoader after TempRamExitApi.
239 @param[in] Status return status for the TempRamExitApi.
244 FspTempRamExitDone2 (
249 volatile EFI_STATUS FspStatus
;
252 // Convert to FSP EAS defined API return codes
256 case EFI_INVALID_PARAMETER
:
257 case EFI_UNSUPPORTED
:
258 case EFI_DEVICE_ERROR
:
261 DEBUG ((DEBUG_INFO
| DEBUG_INIT
, "TempRamExitApi() Invalid Error - [Status: 0x%08X]\n", Status
));
262 Status
= EFI_DEVICE_ERROR
; // Force to known error.
267 // This is the end of the TempRamExit API
268 // Give control back to the boot loader
270 DEBUG ((DEBUG_INFO
| DEBUG_INIT
, "TempRamExitApi() - [Status: 0x%08X] - End\n", Status
));
271 SetFspMeasurePoint (FSP_PERF_ID_API_TEMP_RAM_EXIT_EXIT
);
272 PERF_END_EX (&gFspPerformanceDataGuid
, "EventRec", NULL
, 0, FSP_STATUS_CODE_TEMP_RAM_EXIT
| FSP_STATUS_CODE_COMMON_CODE
| FSP_STATUS_CODE_API_EXIT
);
273 REPORT_STATUS_CODE (EFI_PROGRESS_CODE
, FSP_STATUS_CODE_TEMP_RAM_EXIT
| FSP_STATUS_CODE_COMMON_CODE
| FSP_STATUS_CODE_API_EXIT
);
274 if (GetFspGlobalDataPointer ()->FspMode
== FSP_IN_API_MODE
) {
276 SetFspApiReturnStatus (Status
);
277 Pei2LoaderSwitchStack ();
278 if (Status
!= EFI_SUCCESS
) {
279 DEBUG ((DEBUG_ERROR
, "!!!ERROR: TempRamExitApi() - [Status: 0x%08X] - Error encountered during previous API and cannot proceed further\n", Status
));
281 } while (FspStatus
!= EFI_SUCCESS
);
284 SetPhaseStatusCode (FSP_STATUS_CODE_SILICON_INIT
);
285 SetFspMeasurePoint (FSP_PERF_ID_API_FSP_SILICON_INIT_ENTRY
);
286 PERF_START_EX (&gFspPerformanceDataGuid
, "EventRec", NULL
, 0, FSP_STATUS_CODE_SILICON_INIT
| FSP_STATUS_CODE_COMMON_CODE
| FSP_STATUS_CODE_API_ENTRY
);
287 REPORT_STATUS_CODE (EFI_PROGRESS_CODE
, FSP_STATUS_CODE_SILICON_INIT
| FSP_STATUS_CODE_COMMON_CODE
| FSP_STATUS_CODE_API_ENTRY
);
288 DEBUG ((DEBUG_INFO
| DEBUG_INIT
, "SiliconInitApi() - Begin\n"));
292 This function handle NotifyPhase API call from the BootLoader.
293 It gives control back to the BootLoader after it is handled. If the
294 Notification code is a ReadyToBoot event, this function will return
295 and FSP continues the remaining execution until it reaches the DxeIpl.
304 UINT32 NotificationValue
;
305 UINT32 NotificationCount
;
307 volatile EFI_STATUS FspStatus
;
309 NotificationCount
= 0;
310 while (NotificationCount
< sizeof (mFspNotifySequence
) / sizeof (UINT32
)) {
311 Count
= (UINT8
)((NotificationCount
<< 1) & 0x07);
312 SetFspMeasurePoint (FSP_PERF_ID_API_NOTIFY_POST_PCI_ENTRY
+ Count
);
314 if (NotificationCount
== 0) {
315 SetPhaseStatusCode (FSP_STATUS_CODE_POST_PCIE_ENUM_NOTIFICATION
);
316 PERF_START_EX (&gFspPerformanceDataGuid
, "EventRec", NULL
, 0, FSP_STATUS_CODE_POST_PCIE_ENUM_NOTIFICATION
| FSP_STATUS_CODE_COMMON_CODE
| FSP_STATUS_CODE_API_ENTRY
);
317 REPORT_STATUS_CODE (EFI_PROGRESS_CODE
, FSP_STATUS_CODE_POST_PCIE_ENUM_NOTIFICATION
| FSP_STATUS_CODE_COMMON_CODE
| FSP_STATUS_CODE_API_ENTRY
);
318 } else if (NotificationCount
== 1) {
319 SetPhaseStatusCode (FSP_STATUS_CODE_READY_TO_BOOT_NOTIFICATION
);
320 PERF_START_EX (&gFspPerformanceDataGuid
, "EventRec", NULL
, 0, FSP_STATUS_CODE_READY_TO_BOOT_NOTIFICATION
| FSP_STATUS_CODE_COMMON_CODE
| FSP_STATUS_CODE_API_ENTRY
);
321 REPORT_STATUS_CODE (EFI_PROGRESS_CODE
, FSP_STATUS_CODE_READY_TO_BOOT_NOTIFICATION
| FSP_STATUS_CODE_COMMON_CODE
| FSP_STATUS_CODE_API_ENTRY
);
322 } else if (NotificationCount
== 2) {
323 SetPhaseStatusCode (FSP_STATUS_CODE_END_OF_FIRMWARE_NOTIFICATION
);
324 PERF_START_EX (&gFspPerformanceDataGuid
, "EventRec", NULL
, 0, FSP_STATUS_CODE_END_OF_FIRMWARE_NOTIFICATION
| FSP_STATUS_CODE_COMMON_CODE
| FSP_STATUS_CODE_API_ENTRY
);
325 REPORT_STATUS_CODE (EFI_PROGRESS_CODE
, FSP_STATUS_CODE_END_OF_FIRMWARE_NOTIFICATION
| FSP_STATUS_CODE_COMMON_CODE
| FSP_STATUS_CODE_API_ENTRY
);
328 NotificationValue
= ((NOTIFY_PHASE_PARAMS
*)(UINTN
)GetFspApiParameter ())->Phase
;
329 DEBUG ((DEBUG_INFO
| DEBUG_INIT
, "NotifyPhaseApi() - Begin [Phase: %08X]\n", NotificationValue
));
330 if (mFspNotifySequence
[NotificationCount
] != NotificationValue
) {
332 // Notify code does not follow the predefined order
334 DEBUG ((DEBUG_INFO
, "Unsupported FSP Notification Value\n"));
335 Status
= EFI_UNSUPPORTED
;
338 // Process Notification and Give control back to the boot loader framework caller
340 Status
= FspNotificationHandler (NotificationValue
);
341 if (!EFI_ERROR (Status
)) {
346 DEBUG ((DEBUG_INFO
| DEBUG_INIT
, "NotifyPhaseApi() - End [Status: 0x%08X]\n", Status
));
347 SetFspMeasurePoint (FSP_PERF_ID_API_NOTIFY_POST_PCI_EXIT
+ Count
);
349 if ((NotificationCount
- 1) == 0) {
350 PERF_END_EX (&gFspPerformanceDataGuid
, "EventRec", NULL
, 0, FSP_STATUS_CODE_POST_PCIE_ENUM_NOTIFICATION
| FSP_STATUS_CODE_COMMON_CODE
| FSP_STATUS_CODE_API_EXIT
);
351 REPORT_STATUS_CODE (EFI_PROGRESS_CODE
, FSP_STATUS_CODE_POST_PCIE_ENUM_NOTIFICATION
| FSP_STATUS_CODE_COMMON_CODE
| FSP_STATUS_CODE_API_EXIT
);
352 } else if ((NotificationCount
- 1) == 1) {
353 PERF_END_EX (&gFspPerformanceDataGuid
, "EventRec", NULL
, 0, FSP_STATUS_CODE_READY_TO_BOOT_NOTIFICATION
| FSP_STATUS_CODE_COMMON_CODE
| FSP_STATUS_CODE_API_EXIT
);
354 REPORT_STATUS_CODE (EFI_PROGRESS_CODE
, FSP_STATUS_CODE_READY_TO_BOOT_NOTIFICATION
| FSP_STATUS_CODE_COMMON_CODE
| FSP_STATUS_CODE_API_EXIT
);
355 } else if ((NotificationCount
- 1) == 2) {
356 PERF_END_EX (&gFspPerformanceDataGuid
, "EventRec", NULL
, 0, FSP_STATUS_CODE_END_OF_FIRMWARE_NOTIFICATION
| FSP_STATUS_CODE_COMMON_CODE
| FSP_STATUS_CODE_API_EXIT
);
357 REPORT_STATUS_CODE (EFI_PROGRESS_CODE
, FSP_STATUS_CODE_END_OF_FIRMWARE_NOTIFICATION
| FSP_STATUS_CODE_COMMON_CODE
| FSP_STATUS_CODE_API_EXIT
);
360 if (GetFspGlobalDataPointer ()->FspMode
== FSP_IN_API_MODE
) {
363 SetFspApiReturnStatus (Status
);
364 Pei2LoaderSwitchStack ();
365 if (Status
!= EFI_SUCCESS
) {
366 DEBUG ((DEBUG_ERROR
, "!!!ERROR: NotifyPhaseApi() [Phase: %08X] - Failed - [Status: 0x%08X]\n", NotificationValue
, Status
));
368 } while (FspStatus
!= EFI_SUCCESS
);
373 // Control goes back to the PEI Core and it dispatches further PEIMs.
374 // DXEIPL is the final one to transfer control back to the boot loader.
379 This function transfer control back to BootLoader after FspSiliconInit.
388 FspSiliconInitDone2 (EFI_SUCCESS
);
392 This function returns control to BootLoader after MemoryInitApi.
394 @param[in,out] HobListPtr The address of HobList pointer.
399 IN OUT VOID
**HobListPtr
402 FspMemoryInitDone2 (EFI_SUCCESS
, HobListPtr
);
406 This function returns control to BootLoader after TempRamExitApi.
415 FspTempRamExitDone2 (EFI_SUCCESS
);