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.
132 // This is the end of the FspSiliconInit API
133 // Give control back to the boot loader
135 SetFspMeasurePoint (FSP_PERF_ID_API_FSP_SILICON_INIT_EXIT
);
136 DEBUG ((DEBUG_INFO
| DEBUG_INIT
, "FspSiliconInitApi() - [Status: 0x%08X] - End\n", Status
));
137 PERF_END_EX (&gFspPerformanceDataGuid
, "EventRec", NULL
, 0, FSP_STATUS_CODE_SILICON_INIT
| FSP_STATUS_CODE_COMMON_CODE
| FSP_STATUS_CODE_API_EXIT
);
138 REPORT_STATUS_CODE (EFI_PROGRESS_CODE
, FSP_STATUS_CODE_COMMON_CODE
| FSP_STATUS_CODE_API_EXIT
);
139 if (GetFspGlobalDataPointer ()->FspMode
== FSP_IN_API_MODE
) {
141 SetFspApiReturnStatus (Status
);
142 Pei2LoaderSwitchStack ();
143 if (Status
!= EFI_SUCCESS
) {
144 DEBUG ((DEBUG_ERROR
, "!!!ERROR: FspSiliconInitApi() - [Status: 0x%08X] - Error encountered during previous API and cannot proceed further\n", Status
));
146 } while (FspStatus
!= EFI_SUCCESS
);
151 This function returns control to BootLoader after MemoryInitApi.
153 @param[in] Status return status for the MemoryInitApi.
154 @param[in,out] HobListPtr The address of HobList pointer, if NULL, will get value from GetFspApiParameter2 ()
159 IN EFI_STATUS Status
,
160 IN OUT VOID
**HobListPtr
163 FSP_GLOBAL_DATA
*FspData
;
164 volatile EFI_STATUS FspStatus
;
168 // Calling use FspMemoryInit API
169 // Update HOB and return the control directly
171 if (HobListPtr
== NULL
) {
172 HobListPtr
= (VOID
**)GetFspApiParameter2 ();
174 if (HobListPtr
!= NULL
) {
175 *HobListPtr
= (VOID
*) GetHobList ();
178 // Convert to FSP EAS defined API return codes
182 case EFI_INVALID_PARAMETER
:
183 case EFI_UNSUPPORTED
:
184 case EFI_DEVICE_ERROR
:
185 case EFI_OUT_OF_RESOURCES
:
188 DEBUG ((DEBUG_INFO
| DEBUG_INIT
, "FspMemoryInitApi() Invalid Error [Status: 0x%08X]\n", Status
));
189 Status
= EFI_DEVICE_ERROR
; // Force to known error.
193 // This is the end of the FspMemoryInit API
194 // Give control back to the boot loader
196 DEBUG ((DEBUG_INFO
| DEBUG_INIT
, "FspMemoryInitApi() - [Status: 0x%08X] - End\n", Status
));
197 SetFspMeasurePoint (FSP_PERF_ID_API_FSP_MEMORY_INIT_EXIT
);
198 FspData
= GetFspGlobalDataPointer ();
199 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
);
200 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
);
201 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
);
202 PERF_END_EX(&gFspPerformanceDataGuid
, "EventRec", NULL
, 0, FSP_STATUS_CODE_MEMORY_INIT
| FSP_STATUS_CODE_COMMON_CODE
| FSP_STATUS_CODE_API_EXIT
);
203 REPORT_STATUS_CODE (EFI_PROGRESS_CODE
, FSP_STATUS_CODE_MEMORY_INIT
| FSP_STATUS_CODE_COMMON_CODE
| FSP_STATUS_CODE_API_EXIT
);
204 if (GetFspGlobalDataPointer ()->FspMode
== FSP_IN_API_MODE
) {
206 SetFspApiReturnStatus (Status
);
207 Pei2LoaderSwitchStack ();
208 if (Status
!= EFI_SUCCESS
) {
209 DEBUG ((DEBUG_ERROR
, "!!!ERROR: FspMemoryInitApi() - [Status: 0x%08X] - Error encountered during previous API and cannot proceed further\n", Status
));
211 } while (FspStatus
!= EFI_SUCCESS
);
215 // The TempRamExitApi is called
217 if (GetFspApiCallingIndex () == TempRamExitApiIndex
) {
218 SetPhaseStatusCode (FSP_STATUS_CODE_TEMP_RAM_EXIT
);
219 SetFspMeasurePoint (FSP_PERF_ID_API_TEMP_RAM_EXIT_ENTRY
);
220 PERF_START_EX(&gFspPerformanceDataGuid
, "EventRec", NULL
, 0, FSP_STATUS_CODE_TEMP_RAM_EXIT
| FSP_STATUS_CODE_COMMON_CODE
| FSP_STATUS_CODE_API_ENTRY
);
221 REPORT_STATUS_CODE (EFI_PROGRESS_CODE
, FSP_STATUS_CODE_TEMP_RAM_EXIT
| FSP_STATUS_CODE_COMMON_CODE
| FSP_STATUS_CODE_API_ENTRY
);
222 DEBUG ((DEBUG_INFO
| DEBUG_INIT
, "TempRamExitApi() - Begin\n"));
224 SetPhaseStatusCode (FSP_STATUS_CODE_SILICON_INIT
);
225 SetFspMeasurePoint (FSP_PERF_ID_API_FSP_SILICON_INIT_ENTRY
);
226 PERF_START_EX(&gFspPerformanceDataGuid
, "EventRec", NULL
, 0, FSP_STATUS_CODE_SILICON_INIT
| FSP_STATUS_CODE_COMMON_CODE
| FSP_STATUS_CODE_API_ENTRY
);
227 REPORT_STATUS_CODE (EFI_PROGRESS_CODE
, FSP_STATUS_CODE_SILICON_INIT
| FSP_STATUS_CODE_COMMON_CODE
| FSP_STATUS_CODE_API_ENTRY
);
228 DEBUG ((DEBUG_INFO
| DEBUG_INIT
, "FspSiliconInitApi() - Begin\n"));
233 This function returns control to BootLoader after TempRamExitApi.
235 @param[in] Status return status for the TempRamExitApi.
240 FspTempRamExitDone2 (
245 volatile EFI_STATUS FspStatus
;
248 // Convert to FSP EAS defined API return codes
252 case EFI_INVALID_PARAMETER
:
253 case EFI_UNSUPPORTED
:
254 case EFI_DEVICE_ERROR
:
257 DEBUG ((DEBUG_INFO
| DEBUG_INIT
, "TempRamExitApi() Invalid Error - [Status: 0x%08X]\n", Status
));
258 Status
= EFI_DEVICE_ERROR
; // Force to known error.
262 // This is the end of the TempRamExit API
263 // Give control back to the boot loader
265 DEBUG ((DEBUG_INFO
| DEBUG_INIT
, "TempRamExitApi() - [Status: 0x%08X] - End\n", Status
));
266 SetFspMeasurePoint (FSP_PERF_ID_API_TEMP_RAM_EXIT_EXIT
);
267 PERF_END_EX(&gFspPerformanceDataGuid
, "EventRec", NULL
, 0, FSP_STATUS_CODE_TEMP_RAM_EXIT
| FSP_STATUS_CODE_COMMON_CODE
| FSP_STATUS_CODE_API_EXIT
);
268 REPORT_STATUS_CODE (EFI_PROGRESS_CODE
, FSP_STATUS_CODE_TEMP_RAM_EXIT
| FSP_STATUS_CODE_COMMON_CODE
| FSP_STATUS_CODE_API_EXIT
);
269 if (GetFspGlobalDataPointer ()->FspMode
== FSP_IN_API_MODE
) {
271 SetFspApiReturnStatus (Status
);
272 Pei2LoaderSwitchStack ();
273 if (Status
!= EFI_SUCCESS
) {
274 DEBUG ((DEBUG_ERROR
, "!!!ERROR: TempRamExitApi() - [Status: 0x%08X] - Error encountered during previous API and cannot proceed further\n", Status
));
276 } while (FspStatus
!= EFI_SUCCESS
);
278 SetPhaseStatusCode (FSP_STATUS_CODE_SILICON_INIT
);
279 SetFspMeasurePoint (FSP_PERF_ID_API_FSP_SILICON_INIT_ENTRY
);
280 PERF_START_EX(&gFspPerformanceDataGuid
, "EventRec", NULL
, 0, FSP_STATUS_CODE_SILICON_INIT
| FSP_STATUS_CODE_COMMON_CODE
| FSP_STATUS_CODE_API_ENTRY
);
281 REPORT_STATUS_CODE (EFI_PROGRESS_CODE
, FSP_STATUS_CODE_SILICON_INIT
| FSP_STATUS_CODE_COMMON_CODE
| FSP_STATUS_CODE_API_ENTRY
);
282 DEBUG ((DEBUG_INFO
| DEBUG_INIT
, "SiliconInitApi() - Begin\n"));
286 This function handle NotifyPhase API call from the BootLoader.
287 It gives control back to the BootLoader after it is handled. If the
288 Notification code is a ReadyToBoot event, this function will return
289 and FSP continues the remaining execution until it reaches the DxeIpl.
298 UINT32 NotificationValue
;
299 UINT32 NotificationCount
;
301 volatile EFI_STATUS FspStatus
;
303 NotificationCount
= 0;
304 while (NotificationCount
< sizeof(mFspNotifySequence
) / sizeof(UINT32
)) {
306 Count
= (UINT8
)((NotificationCount
<< 1) & 0x07);
307 SetFspMeasurePoint (FSP_PERF_ID_API_NOTIFY_POST_PCI_ENTRY
+ Count
);
309 if (NotificationCount
== 0) {
310 SetPhaseStatusCode (FSP_STATUS_CODE_POST_PCIE_ENUM_NOTIFICATION
);
311 PERF_START_EX (&gFspPerformanceDataGuid
, "EventRec", NULL
, 0, FSP_STATUS_CODE_POST_PCIE_ENUM_NOTIFICATION
| FSP_STATUS_CODE_COMMON_CODE
| FSP_STATUS_CODE_API_ENTRY
);
312 REPORT_STATUS_CODE (EFI_PROGRESS_CODE
, FSP_STATUS_CODE_POST_PCIE_ENUM_NOTIFICATION
| FSP_STATUS_CODE_COMMON_CODE
| FSP_STATUS_CODE_API_ENTRY
);
313 } else if (NotificationCount
== 1) {
314 SetPhaseStatusCode (FSP_STATUS_CODE_READY_TO_BOOT_NOTIFICATION
);
315 PERF_START_EX(&gFspPerformanceDataGuid
, "EventRec", NULL
, 0, FSP_STATUS_CODE_READY_TO_BOOT_NOTIFICATION
| FSP_STATUS_CODE_COMMON_CODE
| FSP_STATUS_CODE_API_ENTRY
);
316 REPORT_STATUS_CODE (EFI_PROGRESS_CODE
, FSP_STATUS_CODE_READY_TO_BOOT_NOTIFICATION
| FSP_STATUS_CODE_COMMON_CODE
| FSP_STATUS_CODE_API_ENTRY
);
317 } else if (NotificationCount
== 2) {
318 SetPhaseStatusCode (FSP_STATUS_CODE_END_OF_FIRMWARE_NOTIFICATION
);
319 PERF_START_EX (&gFspPerformanceDataGuid
, "EventRec", NULL
, 0, FSP_STATUS_CODE_END_OF_FIRMWARE_NOTIFICATION
| FSP_STATUS_CODE_COMMON_CODE
| FSP_STATUS_CODE_API_ENTRY
);
320 REPORT_STATUS_CODE (EFI_PROGRESS_CODE
, FSP_STATUS_CODE_END_OF_FIRMWARE_NOTIFICATION
| FSP_STATUS_CODE_COMMON_CODE
| FSP_STATUS_CODE_API_ENTRY
);
323 NotificationValue
= ((NOTIFY_PHASE_PARAMS
*)(UINTN
)GetFspApiParameter ())->Phase
;
324 DEBUG ((DEBUG_INFO
| DEBUG_INIT
, "NotifyPhaseApi() - Begin [Phase: %08X]\n", NotificationValue
));
325 if (mFspNotifySequence
[NotificationCount
] != NotificationValue
) {
327 // Notify code does not follow the predefined order
329 DEBUG ((DEBUG_INFO
, "Unsupported FSP Notification Value\n"));
330 Status
= EFI_UNSUPPORTED
;
333 // Process Notification and Give control back to the boot loader framework caller
335 Status
= FspNotificationHandler (NotificationValue
);
336 if (!EFI_ERROR(Status
)) {
341 DEBUG ((DEBUG_INFO
| DEBUG_INIT
, "NotifyPhaseApi() - End [Status: 0x%08X]\n", Status
));
342 SetFspMeasurePoint (FSP_PERF_ID_API_NOTIFY_POST_PCI_EXIT
+ Count
);
344 if ((NotificationCount
- 1) == 0) {
345 PERF_END_EX(&gFspPerformanceDataGuid
, "EventRec", NULL
, 0, FSP_STATUS_CODE_POST_PCIE_ENUM_NOTIFICATION
| FSP_STATUS_CODE_COMMON_CODE
| FSP_STATUS_CODE_API_EXIT
);
346 REPORT_STATUS_CODE (EFI_PROGRESS_CODE
, FSP_STATUS_CODE_POST_PCIE_ENUM_NOTIFICATION
| FSP_STATUS_CODE_COMMON_CODE
| FSP_STATUS_CODE_API_EXIT
);
347 } else if ((NotificationCount
- 1) == 1) {
348 PERF_END_EX(&gFspPerformanceDataGuid
, "EventRec", NULL
, 0, FSP_STATUS_CODE_READY_TO_BOOT_NOTIFICATION
| FSP_STATUS_CODE_COMMON_CODE
| FSP_STATUS_CODE_API_EXIT
);
349 REPORT_STATUS_CODE (EFI_PROGRESS_CODE
, FSP_STATUS_CODE_READY_TO_BOOT_NOTIFICATION
| FSP_STATUS_CODE_COMMON_CODE
| FSP_STATUS_CODE_API_EXIT
);
350 } else if ((NotificationCount
- 1) == 2) {
351 PERF_END_EX(&gFspPerformanceDataGuid
, "EventRec", NULL
, 0, FSP_STATUS_CODE_END_OF_FIRMWARE_NOTIFICATION
| FSP_STATUS_CODE_COMMON_CODE
| FSP_STATUS_CODE_API_EXIT
);
352 REPORT_STATUS_CODE (EFI_PROGRESS_CODE
, FSP_STATUS_CODE_END_OF_FIRMWARE_NOTIFICATION
| FSP_STATUS_CODE_COMMON_CODE
| FSP_STATUS_CODE_API_EXIT
);
354 if (GetFspGlobalDataPointer ()->FspMode
== FSP_IN_API_MODE
) {
357 SetFspApiReturnStatus(Status
);
358 Pei2LoaderSwitchStack();
359 if (Status
!= EFI_SUCCESS
) {
360 DEBUG ((DEBUG_ERROR
, "!!!ERROR: NotifyPhaseApi() [Phase: %08X] - Failed - [Status: 0x%08X]\n", NotificationValue
, Status
));
362 } while (FspStatus
!= EFI_SUCCESS
);
366 // Control goes back to the PEI Core and it dispatches further PEIMs.
367 // DXEIPL is the final one to transfer control back to the boot loader.
372 This function transfer control back to BootLoader after FspSiliconInit.
381 FspSiliconInitDone2 (EFI_SUCCESS
);
385 This function returns control to BootLoader after MemoryInitApi.
387 @param[in,out] HobListPtr The address of HobList pointer.
392 IN OUT VOID
**HobListPtr
395 FspMemoryInitDone2 (EFI_SUCCESS
, HobListPtr
);
399 This function returns control to BootLoader after TempRamExitApi.
408 FspTempRamExitDone2 (EFI_SUCCESS
);