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
FspNotificationHandler(IN UINT32 NotificationCode)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
FspSiliconInitDone2(IN EFI_STATUS Status)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
FspMemoryInitDone2(IN EFI_STATUS Status,IN OUT VOID ** HobListPtr)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
FspTempRamExitDone2(IN EFI_STATUS Status)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
FspWaitForNotify(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
FspSiliconInitDone(VOID)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
FspMemoryInitDone(IN OUT VOID ** HobListPtr)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
FspTempRamExitDone(VOID)392 FspTempRamExitDone (
393 VOID
394 )
395 {
396 FspTempRamExitDone2 (EFI_SUCCESS);
397 }
398