3 Copyright (c) 2014 - 2018, 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.
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.
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>
26 #include <FspStatusCode.h>
27 #include <Protocol/PciEnumerationComplete.h>
28 #include <Library/ReportStatusCodeLib.h>
29 #include <Library/PerformanceLib.h>
30 extern EFI_GUID gFspPerformanceDataGuid
;
32 EFI_PEI_PPI_DESCRIPTOR mPeiPostPciEnumerationPpi
= {
33 (EFI_PEI_PPI_DESCRIPTOR_PPI
| EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST
),
34 &gEfiPciEnumerationCompleteProtocolGuid
,
38 EFI_PEI_PPI_DESCRIPTOR mPeiReadyToBootPpi
= {
39 (EFI_PEI_PPI_DESCRIPTOR_PPI
| EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST
),
40 &gEfiEventReadyToBootGuid
,
44 EFI_PEI_PPI_DESCRIPTOR mPeiEndOfFirmwarePpi
= {
45 (EFI_PEI_PPI_DESCRIPTOR_PPI
| EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST
),
46 &gFspEventEndOfFirmwareGuid
,
50 UINT32 mFspNotifySequence
[] = {
51 EnumInitPhaseAfterPciEnumeration
,
52 EnumInitPhaseReadyToBoot
,
53 EnumInitPhaseEndOfFirmware
57 Install FSP notification.
59 @param[in] NotificationCode FSP notification code
61 @retval EFI_SUCCESS Notify FSP successfully
62 @retval EFI_INVALID_PARAMETER NotificationCode is invalid
67 FspNotificationHandler (
68 IN UINT32 NotificationCode
75 switch (NotificationCode
) {
76 case EnumInitPhaseAfterPciEnumeration
:
78 // Do POST PCI initialization if needed
80 DEBUG ((DEBUG_INFO
| DEBUG_INIT
, "FSP Post PCI Enumeration ...\n"));
81 PeiServicesInstallPpi (&mPeiPostPciEnumerationPpi
);
84 case EnumInitPhaseReadyToBoot
:
88 DEBUG ((DEBUG_INFO
| DEBUG_INIT
, "FSP Ready To Boot ...\n"));
89 PeiServicesInstallPpi (&mPeiReadyToBootPpi
);
92 case EnumInitPhaseEndOfFirmware
:
96 DEBUG ((DEBUG_INFO
| DEBUG_INIT
, "FSP End of Firmware ...\n"));
97 PeiServicesInstallPpi (&mPeiEndOfFirmwarePpi
);
101 Status
= EFI_INVALID_PARAMETER
;
109 This function transfer control back to BootLoader after FspSiliconInit.
111 @param[in] Status return status for the FspSiliconInit.
116 FspSiliconInitDone2 (
120 volatile EFI_STATUS FspStatus
;
124 // Convert to FSP EAS defined API return codes
128 case EFI_INVALID_PARAMETER
:
129 case EFI_UNSUPPORTED
:
130 case EFI_DEVICE_ERROR
:
133 DEBUG ((DEBUG_INFO
| DEBUG_INIT
, "FspSiliconInitApi() Invalid Error - [Status: 0x%08X]\n", Status
));
134 Status
= EFI_DEVICE_ERROR
; // Force to known error.
138 // This is the end of the FspSiliconInit API
139 // Give control back to the boot loader
141 SetFspMeasurePoint (FSP_PERF_ID_API_FSP_SILICON_INIT_EXIT
);
142 DEBUG ((DEBUG_INFO
| DEBUG_INIT
, "FspSiliconInitApi() - [Status: 0x%08X] - End\n", Status
));
143 PERF_END_EX (&gFspPerformanceDataGuid
, "EventRec", NULL
, 0, FSP_STATUS_CODE_SILICON_INIT
| FSP_STATUS_CODE_COMMON_CODE
| FSP_STATUS_CODE_API_EXIT
);
144 REPORT_STATUS_CODE (EFI_PROGRESS_CODE
, FSP_STATUS_CODE_COMMON_CODE
| FSP_STATUS_CODE_API_EXIT
);
145 if (GetFspGlobalDataPointer ()->FspMode
== FSP_IN_API_MODE
) {
147 SetFspApiReturnStatus (Status
);
148 Pei2LoaderSwitchStack ();
149 if (Status
!= EFI_SUCCESS
) {
150 DEBUG ((DEBUG_ERROR
, "!!!ERROR: FspSiliconInitApi() - [Status: 0x%08X] - Error encountered during previous API and cannot proceed further\n", Status
));
152 } while (FspStatus
!= EFI_SUCCESS
);
157 This function returns control to BootLoader after MemoryInitApi.
159 @param[in] Status return status for the MemoryInitApi.
160 @param[in,out] HobListPtr The address of HobList pointer, if NULL, will get value from GetFspApiParameter2 ()
165 IN EFI_STATUS Status
,
166 IN OUT VOID
**HobListPtr
169 FSP_GLOBAL_DATA
*FspData
;
170 volatile EFI_STATUS FspStatus
;
174 // Calling use FspMemoryInit API
175 // Update HOB and return the control directly
177 if (HobListPtr
== NULL
) {
178 HobListPtr
= (VOID
**)GetFspApiParameter2 ();
180 if (HobListPtr
!= NULL
) {
181 *HobListPtr
= (VOID
*) GetHobList ();
184 // Convert to FSP EAS defined API return codes
188 case EFI_INVALID_PARAMETER
:
189 case EFI_UNSUPPORTED
:
190 case EFI_DEVICE_ERROR
:
191 case EFI_OUT_OF_RESOURCES
:
194 DEBUG ((DEBUG_INFO
| DEBUG_INIT
, "FspMemoryInitApi() Invalid Error [Status: 0x%08X]\n", Status
));
195 Status
= EFI_DEVICE_ERROR
; // Force to known error.
199 // This is the end of the FspMemoryInit API
200 // Give control back to the boot loader
202 DEBUG ((DEBUG_INFO
| DEBUG_INIT
, "FspMemoryInitApi() - [Status: 0x%08X] - End\n", Status
));
203 SetFspMeasurePoint (FSP_PERF_ID_API_FSP_MEMORY_INIT_EXIT
);
204 FspData
= GetFspGlobalDataPointer ();
205 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
);
206 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
);
207 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
);
208 PERF_END_EX(&gFspPerformanceDataGuid
, "EventRec", NULL
, 0, FSP_STATUS_CODE_MEMORY_INIT
| FSP_STATUS_CODE_COMMON_CODE
| FSP_STATUS_CODE_API_EXIT
);
209 REPORT_STATUS_CODE (EFI_PROGRESS_CODE
, FSP_STATUS_CODE_MEMORY_INIT
| FSP_STATUS_CODE_COMMON_CODE
| FSP_STATUS_CODE_API_EXIT
);
210 if (GetFspGlobalDataPointer ()->FspMode
== FSP_IN_API_MODE
) {
212 SetFspApiReturnStatus (Status
);
213 Pei2LoaderSwitchStack ();
214 if (Status
!= EFI_SUCCESS
) {
215 DEBUG ((DEBUG_ERROR
, "!!!ERROR: FspMemoryInitApi() - [Status: 0x%08X] - Error encountered during previous API and cannot proceed further\n", Status
));
217 } while (FspStatus
!= EFI_SUCCESS
);
221 // The TempRamExitApi is called
223 if (GetFspApiCallingIndex () == TempRamExitApiIndex
) {
224 SetPhaseStatusCode (FSP_STATUS_CODE_TEMP_RAM_EXIT
);
225 SetFspMeasurePoint (FSP_PERF_ID_API_TEMP_RAM_EXIT_ENTRY
);
226 PERF_START_EX(&gFspPerformanceDataGuid
, "EventRec", NULL
, 0, FSP_STATUS_CODE_TEMP_RAM_EXIT
| FSP_STATUS_CODE_COMMON_CODE
| FSP_STATUS_CODE_API_ENTRY
);
227 REPORT_STATUS_CODE (EFI_PROGRESS_CODE
, FSP_STATUS_CODE_TEMP_RAM_EXIT
| FSP_STATUS_CODE_COMMON_CODE
| FSP_STATUS_CODE_API_ENTRY
);
228 DEBUG ((DEBUG_INFO
| DEBUG_INIT
, "TempRamExitApi() - Begin\n"));
230 SetPhaseStatusCode (FSP_STATUS_CODE_SILICON_INIT
);
231 SetFspMeasurePoint (FSP_PERF_ID_API_FSP_SILICON_INIT_ENTRY
);
232 PERF_START_EX(&gFspPerformanceDataGuid
, "EventRec", NULL
, 0, FSP_STATUS_CODE_SILICON_INIT
| FSP_STATUS_CODE_COMMON_CODE
| FSP_STATUS_CODE_API_ENTRY
);
233 REPORT_STATUS_CODE (EFI_PROGRESS_CODE
, FSP_STATUS_CODE_SILICON_INIT
| FSP_STATUS_CODE_COMMON_CODE
| FSP_STATUS_CODE_API_ENTRY
);
234 DEBUG ((DEBUG_INFO
| DEBUG_INIT
, "FspSiliconInitApi() - Begin\n"));
239 This function returns control to BootLoader after TempRamExitApi.
241 @param[in] Status return status for the TempRamExitApi.
246 FspTempRamExitDone2 (
251 volatile EFI_STATUS FspStatus
;
254 // Convert to FSP EAS defined API return codes
258 case EFI_INVALID_PARAMETER
:
259 case EFI_UNSUPPORTED
:
260 case EFI_DEVICE_ERROR
:
263 DEBUG ((DEBUG_INFO
| DEBUG_INIT
, "TempRamExitApi() Invalid Error - [Status: 0x%08X]\n", Status
));
264 Status
= EFI_DEVICE_ERROR
; // Force to known error.
268 // This is the end of the TempRamExit API
269 // Give control back to the boot loader
271 DEBUG ((DEBUG_INFO
| DEBUG_INIT
, "TempRamExitApi() - [Status: 0x%08X] - End\n", Status
));
272 SetFspMeasurePoint (FSP_PERF_ID_API_TEMP_RAM_EXIT_EXIT
);
273 PERF_END_EX(&gFspPerformanceDataGuid
, "EventRec", NULL
, 0, FSP_STATUS_CODE_TEMP_RAM_EXIT
| FSP_STATUS_CODE_COMMON_CODE
| FSP_STATUS_CODE_API_EXIT
);
274 REPORT_STATUS_CODE (EFI_PROGRESS_CODE
, FSP_STATUS_CODE_TEMP_RAM_EXIT
| FSP_STATUS_CODE_COMMON_CODE
| FSP_STATUS_CODE_API_EXIT
);
275 if (GetFspGlobalDataPointer ()->FspMode
== FSP_IN_API_MODE
) {
277 SetFspApiReturnStatus (Status
);
278 Pei2LoaderSwitchStack ();
279 if (Status
!= EFI_SUCCESS
) {
280 DEBUG ((DEBUG_ERROR
, "!!!ERROR: TempRamExitApi() - [Status: 0x%08X] - Error encountered during previous API and cannot proceed further\n", Status
));
282 } 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
)) {
312 Count
= (UINT8
)((NotificationCount
<< 1) & 0x07);
313 SetFspMeasurePoint (FSP_PERF_ID_API_NOTIFY_POST_PCI_ENTRY
+ Count
);
315 if (NotificationCount
== 0) {
316 SetPhaseStatusCode (FSP_STATUS_CODE_POST_PCIE_ENUM_NOTIFICATION
);
317 PERF_START_EX (&gFspPerformanceDataGuid
, "EventRec", NULL
, 0, FSP_STATUS_CODE_POST_PCIE_ENUM_NOTIFICATION
| FSP_STATUS_CODE_COMMON_CODE
| FSP_STATUS_CODE_API_ENTRY
);
318 REPORT_STATUS_CODE (EFI_PROGRESS_CODE
, FSP_STATUS_CODE_POST_PCIE_ENUM_NOTIFICATION
| FSP_STATUS_CODE_COMMON_CODE
| FSP_STATUS_CODE_API_ENTRY
);
319 } else if (NotificationCount
== 1) {
320 SetPhaseStatusCode (FSP_STATUS_CODE_READY_TO_BOOT_NOTIFICATION
);
321 PERF_START_EX(&gFspPerformanceDataGuid
, "EventRec", NULL
, 0, FSP_STATUS_CODE_READY_TO_BOOT_NOTIFICATION
| FSP_STATUS_CODE_COMMON_CODE
| FSP_STATUS_CODE_API_ENTRY
);
322 REPORT_STATUS_CODE (EFI_PROGRESS_CODE
, FSP_STATUS_CODE_READY_TO_BOOT_NOTIFICATION
| FSP_STATUS_CODE_COMMON_CODE
| FSP_STATUS_CODE_API_ENTRY
);
323 } else if (NotificationCount
== 2) {
324 SetPhaseStatusCode (FSP_STATUS_CODE_END_OF_FIRMWARE_NOTIFICATION
);
325 PERF_START_EX (&gFspPerformanceDataGuid
, "EventRec", NULL
, 0, FSP_STATUS_CODE_END_OF_FIRMWARE_NOTIFICATION
| FSP_STATUS_CODE_COMMON_CODE
| FSP_STATUS_CODE_API_ENTRY
);
326 REPORT_STATUS_CODE (EFI_PROGRESS_CODE
, FSP_STATUS_CODE_END_OF_FIRMWARE_NOTIFICATION
| FSP_STATUS_CODE_COMMON_CODE
| FSP_STATUS_CODE_API_ENTRY
);
329 NotificationValue
= ((NOTIFY_PHASE_PARAMS
*)(UINTN
)GetFspApiParameter ())->Phase
;
330 DEBUG ((DEBUG_INFO
| DEBUG_INIT
, "NotifyPhaseApi() - Begin [Phase: %08X]\n", NotificationValue
));
331 if (mFspNotifySequence
[NotificationCount
] != NotificationValue
) {
333 // Notify code does not follow the predefined order
335 DEBUG ((DEBUG_INFO
, "Unsupported FSP Notification Value\n"));
336 Status
= EFI_UNSUPPORTED
;
339 // Process Notification and Give control back to the boot loader framework caller
341 Status
= FspNotificationHandler (NotificationValue
);
342 if (!EFI_ERROR(Status
)) {
347 DEBUG ((DEBUG_INFO
| DEBUG_INIT
, "NotifyPhaseApi() - End [Status: 0x%08X]\n", Status
));
348 SetFspMeasurePoint (FSP_PERF_ID_API_NOTIFY_POST_PCI_EXIT
+ Count
);
350 if ((NotificationCount
- 1) == 0) {
351 PERF_END_EX(&gFspPerformanceDataGuid
, "EventRec", NULL
, 0, FSP_STATUS_CODE_POST_PCIE_ENUM_NOTIFICATION
| FSP_STATUS_CODE_COMMON_CODE
| FSP_STATUS_CODE_API_EXIT
);
352 REPORT_STATUS_CODE (EFI_PROGRESS_CODE
, FSP_STATUS_CODE_POST_PCIE_ENUM_NOTIFICATION
| FSP_STATUS_CODE_COMMON_CODE
| FSP_STATUS_CODE_API_EXIT
);
353 } else if ((NotificationCount
- 1) == 1) {
354 PERF_END_EX(&gFspPerformanceDataGuid
, "EventRec", NULL
, 0, FSP_STATUS_CODE_READY_TO_BOOT_NOTIFICATION
| FSP_STATUS_CODE_COMMON_CODE
| FSP_STATUS_CODE_API_EXIT
);
355 REPORT_STATUS_CODE (EFI_PROGRESS_CODE
, FSP_STATUS_CODE_READY_TO_BOOT_NOTIFICATION
| FSP_STATUS_CODE_COMMON_CODE
| FSP_STATUS_CODE_API_EXIT
);
356 } else if ((NotificationCount
- 1) == 2) {
357 PERF_END_EX(&gFspPerformanceDataGuid
, "EventRec", NULL
, 0, FSP_STATUS_CODE_END_OF_FIRMWARE_NOTIFICATION
| FSP_STATUS_CODE_COMMON_CODE
| FSP_STATUS_CODE_API_EXIT
);
358 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
);
372 // Control goes back to the PEI Core and it dispatches further PEIMs.
373 // DXEIPL is the final one to transfer control back to the boot loader.
378 This function transfer control back to BootLoader after FspSiliconInit.
387 FspSiliconInitDone2 (EFI_SUCCESS
);
391 This function returns control to BootLoader after MemoryInitApi.
393 @param[in,out] HobListPtr The address of HobList pointer.
398 IN OUT VOID
**HobListPtr
401 FspMemoryInitDone2 (EFI_SUCCESS
, HobListPtr
);
405 This function returns control to BootLoader after TempRamExitApi.
414 FspTempRamExitDone2 (EFI_SUCCESS
);