IntelFsp2Pkg: Added changes to enable FPDT performance measurements
[mirror_edk2.git] / IntelFsp2Pkg / Library / BaseFspPlatformLib / FspPlatformNotify.c
1 /** @file\r
2 \r
3   Copyright (c) 2014 - 2016, Intel Corporation. All rights reserved.<BR>\r
4   This program and the accompanying materials\r
5   are licensed and made available under the terms and conditions of the BSD License\r
6   which accompanies this distribution.  The full text of the license may be found at\r
7   http://opensource.org/licenses/bsd-license.php.\r
8 \r
9   THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
10   WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
11 \r
12 **/\r
13 \r
14 #include <PiPei.h>\r
15 #include <Library/PeiServicesLib.h>\r
16 #include <Library/PeiServicesTablePointerLib.h>\r
17 #include <Library/BaseLib.h>\r
18 #include <Library/BaseMemoryLib.h>\r
19 #include <Library/PcdLib.h>\r
20 #include <Library/DebugLib.h>\r
21 #include <Library/HobLib.h>\r
22 #include <Library/FspSwitchStackLib.h>\r
23 #include <Library/FspCommonLib.h>\r
24 #include <Guid/EventGroup.h>\r
25 #include <FspEas.h>\r
26 #include <FspStatusCode.h>\r
27 #include <Protocol/PciEnumerationComplete.h>\r
28 #include <Library/ReportStatusCodeLib.h>\r
29 #include <Library/PerformanceLib.h>\r
30 extern EFI_GUID gFspPerformanceDataGuid;\r
31 \r
32 EFI_PEI_PPI_DESCRIPTOR      mPeiPostPciEnumerationPpi = {\r
33   (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),\r
34   &gEfiPciEnumerationCompleteProtocolGuid,\r
35   NULL\r
36 };\r
37 \r
38 EFI_PEI_PPI_DESCRIPTOR      mPeiReadyToBootPpi = {\r
39   (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),\r
40   &gEfiEventReadyToBootGuid,\r
41   NULL\r
42 };\r
43 \r
44 EFI_PEI_PPI_DESCRIPTOR      mPeiEndOfFirmwarePpi = {\r
45   (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),\r
46   &gFspEventEndOfFirmwareGuid,\r
47   NULL\r
48 };\r
49 \r
50 UINT32  mFspNotifySequence[] = {\r
51   EnumInitPhaseAfterPciEnumeration,\r
52   EnumInitPhaseReadyToBoot,\r
53   EnumInitPhaseEndOfFirmware\r
54 };\r
55 \r
56 /**\r
57   Install FSP notification.\r
58 \r
59   @param[in] NotificationCode  FSP notification code\r
60 \r
61   @retval EFI_SUCCESS            Notify FSP successfully\r
62   @retval EFI_INVALID_PARAMETER  NotificationCode is invalid\r
63 \r
64 **/\r
65 EFI_STATUS\r
66 EFIAPI\r
67 FspNotificationHandler (\r
68   IN  UINT32     NotificationCode\r
69   )\r
70 {\r
71   EFI_STATUS                Status;\r
72 \r
73   Status   = EFI_SUCCESS;\r
74 \r
75   switch (NotificationCode) {\r
76   case EnumInitPhaseAfterPciEnumeration:\r
77     //\r
78     // Do POST PCI initialization if needed\r
79     //\r
80     DEBUG ((DEBUG_INFO | DEBUG_INIT, "FSP Post PCI Enumeration ...\n"));\r
81     PeiServicesInstallPpi (&mPeiPostPciEnumerationPpi);\r
82     break;\r
83 \r
84   case EnumInitPhaseReadyToBoot:\r
85     //\r
86     // Ready To Boot\r
87     //\r
88     DEBUG ((DEBUG_INFO| DEBUG_INIT, "FSP Ready To Boot ...\n"));\r
89     PeiServicesInstallPpi (&mPeiReadyToBootPpi);\r
90     break;\r
91 \r
92   case EnumInitPhaseEndOfFirmware:\r
93     //\r
94     // End of Firmware\r
95     //\r
96     DEBUG ((DEBUG_INFO| DEBUG_INIT, "FSP End of Firmware ...\n"));\r
97     PeiServicesInstallPpi (&mPeiEndOfFirmwarePpi);\r
98     break;\r
99 \r
100   default:\r
101     Status = EFI_INVALID_PARAMETER;\r
102     break;\r
103   }\r
104 \r
105   return Status;\r
106 }\r
107 \r
108 /**\r
109   This function transfer control back to BootLoader after FspSiliconInit.\r
110 \r
111 **/\r
112 VOID\r
113 EFIAPI\r
114 FspSiliconInitDone (\r
115   VOID\r
116   )\r
117 {\r
118   //\r
119   // This is the end of the FspSiliconInit API\r
120   // Give control back to the boot loader\r
121   //\r
122   SetFspMeasurePoint (FSP_PERF_ID_API_FSP_SILICON_INIT_EXIT);\r
123   DEBUG ((DEBUG_INFO | DEBUG_INIT, "FspSiliconInitApi() - End\n"));\r
124   PERF_END_EX (&gFspPerformanceDataGuid, "EventRec", NULL, 0, FSP_STATUS_CODE_SILICON_INIT | FSP_STATUS_CODE_COMMON_CODE | FSP_STATUS_CODE_API_EXIT);\r
125   REPORT_STATUS_CODE (EFI_PROGRESS_CODE, FSP_STATUS_CODE_COMMON_CODE | FSP_STATUS_CODE_API_EXIT);\r
126   SetFspApiReturnStatus (EFI_SUCCESS);\r
127 \r
128   Pei2LoaderSwitchStack();\r
129 \r
130 }\r
131 \r
132 /**\r
133   This function returns control to BootLoader after MemoryInitApi.\r
134 \r
135   @param[in,out] HobListPtr The address of HobList pointer.\r
136 **/\r
137 VOID\r
138 EFIAPI\r
139 FspMemoryInitDone (\r
140   IN OUT VOID   **HobListPtr\r
141   )\r
142 {\r
143   FSP_GLOBAL_DATA   *FspData;\r
144   //\r
145   // Calling use FspMemoryInit API\r
146   // Update HOB and return the control directly\r
147   //\r
148   if (HobListPtr != NULL) {\r
149     *HobListPtr = (VOID *) GetHobList ();\r
150   }\r
151 \r
152   //\r
153   // This is the end of the FspMemoryInit API\r
154   // Give control back to the boot loader\r
155   //\r
156   DEBUG ((DEBUG_INFO | DEBUG_INIT, "FspMemoryInitApi() - End\n"));\r
157   SetFspMeasurePoint (FSP_PERF_ID_API_FSP_MEMORY_INIT_EXIT);\r
158   FspData = GetFspGlobalDataPointer ();\r
159   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);\r
160   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);\r
161   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);\r
162   PERF_END_EX(&gFspPerformanceDataGuid, "EventRec", NULL, 0, FSP_STATUS_CODE_MEMORY_INIT | FSP_STATUS_CODE_COMMON_CODE | FSP_STATUS_CODE_API_EXIT);\r
163   REPORT_STATUS_CODE (EFI_PROGRESS_CODE, FSP_STATUS_CODE_MEMORY_INIT | FSP_STATUS_CODE_COMMON_CODE | FSP_STATUS_CODE_API_EXIT);\r
164   SetFspApiReturnStatus (EFI_SUCCESS);\r
165   Pei2LoaderSwitchStack ();\r
166 \r
167   //\r
168   // The TempRamExitApi is called\r
169   //\r
170   if (GetFspApiCallingIndex () == TempRamExitApiIndex) {\r
171     SetPhaseStatusCode (FSP_STATUS_CODE_TEMP_RAM_EXIT);\r
172     SetFspMeasurePoint (FSP_PERF_ID_API_TEMP_RAM_EXIT_ENTRY);\r
173     PERF_START_EX(&gFspPerformanceDataGuid, "EventRec", NULL, 0, FSP_STATUS_CODE_TEMP_RAM_EXIT | FSP_STATUS_CODE_COMMON_CODE | FSP_STATUS_CODE_API_ENTRY);\r
174     REPORT_STATUS_CODE (EFI_PROGRESS_CODE, FSP_STATUS_CODE_TEMP_RAM_EXIT | FSP_STATUS_CODE_COMMON_CODE | FSP_STATUS_CODE_API_ENTRY);\r
175     DEBUG ((DEBUG_INFO | DEBUG_INIT, "TempRamExitApi() - Begin\n"));\r
176   } else {\r
177     SetPhaseStatusCode (FSP_STATUS_CODE_SILICON_INIT);\r
178     SetFspMeasurePoint (FSP_PERF_ID_API_FSP_SILICON_INIT_ENTRY);\r
179     PERF_START_EX(&gFspPerformanceDataGuid, "EventRec", NULL, 0, FSP_STATUS_CODE_SILICON_INIT | FSP_STATUS_CODE_COMMON_CODE | FSP_STATUS_CODE_API_ENTRY);\r
180     REPORT_STATUS_CODE (EFI_PROGRESS_CODE, FSP_STATUS_CODE_SILICON_INIT | FSP_STATUS_CODE_COMMON_CODE | FSP_STATUS_CODE_API_ENTRY);\r
181     DEBUG ((DEBUG_INFO | DEBUG_INIT, "FspSiliconInitApi() - Begin\n"));\r
182   }\r
183 }\r
184 \r
185 /**\r
186   This function returns control to BootLoader after TempRamExitApi.\r
187 \r
188 **/\r
189 VOID\r
190 EFIAPI\r
191 FspTempRamExitDone (\r
192   VOID\r
193   )\r
194 {\r
195 \r
196   //\r
197   // This is the end of the TempRamExit API\r
198   // Give control back to the boot loader\r
199   //\r
200   DEBUG ((DEBUG_INFO | DEBUG_INIT, "TempRamExitApi() - End\n"));\r
201   SetFspMeasurePoint (FSP_PERF_ID_API_TEMP_RAM_EXIT_EXIT);\r
202   PERF_END_EX(&gFspPerformanceDataGuid, "EventRec", NULL, 0, FSP_STATUS_CODE_TEMP_RAM_EXIT | FSP_STATUS_CODE_COMMON_CODE | FSP_STATUS_CODE_API_EXIT);\r
203   REPORT_STATUS_CODE (EFI_PROGRESS_CODE, FSP_STATUS_CODE_TEMP_RAM_EXIT | FSP_STATUS_CODE_COMMON_CODE | FSP_STATUS_CODE_API_EXIT);\r
204   SetFspApiReturnStatus (EFI_SUCCESS);\r
205   Pei2LoaderSwitchStack ();\r
206 \r
207   SetPhaseStatusCode (FSP_STATUS_CODE_SILICON_INIT);\r
208   SetFspMeasurePoint (FSP_PERF_ID_API_FSP_SILICON_INIT_ENTRY);\r
209   PERF_START_EX(&gFspPerformanceDataGuid, "EventRec", NULL, 0, FSP_STATUS_CODE_SILICON_INIT | FSP_STATUS_CODE_COMMON_CODE | FSP_STATUS_CODE_API_ENTRY);\r
210   REPORT_STATUS_CODE (EFI_PROGRESS_CODE, FSP_STATUS_CODE_SILICON_INIT | FSP_STATUS_CODE_COMMON_CODE | FSP_STATUS_CODE_API_ENTRY);\r
211   DEBUG ((DEBUG_INFO | DEBUG_INIT, "SiliconInitApi() - Begin\n"));\r
212 }\r
213 \r
214 /**\r
215   This function handle NotifyPhase API call from the BootLoader.\r
216   It gives control back to the BootLoader after it is handled. If the\r
217   Notification code is a ReadyToBoot event, this function will return\r
218   and FSP continues the remaining execution until it reaches the DxeIpl.\r
219 \r
220 **/\r
221 VOID\r
222 FspWaitForNotify (\r
223   VOID\r
224   )\r
225 {\r
226   EFI_STATUS                 Status;\r
227   UINT32                     NotificationValue;\r
228   UINT32                     NotificationCount;\r
229   UINT8                      Count;\r
230 \r
231   NotificationCount = 0;\r
232   while (NotificationCount < sizeof(mFspNotifySequence) / sizeof(UINT32)) {\r
233 \r
234     Count = (UINT8)((NotificationCount << 1) & 0x07);\r
235     SetFspMeasurePoint (FSP_PERF_ID_API_NOTIFY_POST_PCI_ENTRY + Count);\r
236 \r
237     if (NotificationCount == 0) {\r
238       SetPhaseStatusCode (FSP_STATUS_CODE_POST_PCIE_ENUM_NOTIFICATION);\r
239       PERF_START_EX (&gFspPerformanceDataGuid, "EventRec", NULL, 0, FSP_STATUS_CODE_POST_PCIE_ENUM_NOTIFICATION | FSP_STATUS_CODE_COMMON_CODE | FSP_STATUS_CODE_API_ENTRY);\r
240       REPORT_STATUS_CODE (EFI_PROGRESS_CODE, FSP_STATUS_CODE_POST_PCIE_ENUM_NOTIFICATION | FSP_STATUS_CODE_COMMON_CODE | FSP_STATUS_CODE_API_ENTRY);\r
241     } else if (NotificationCount == 1) {\r
242       SetPhaseStatusCode (FSP_STATUS_CODE_READY_TO_BOOT_NOTIFICATION);\r
243       PERF_START_EX(&gFspPerformanceDataGuid, "EventRec", NULL, 0, FSP_STATUS_CODE_READY_TO_BOOT_NOTIFICATION | FSP_STATUS_CODE_COMMON_CODE | FSP_STATUS_CODE_API_ENTRY);\r
244       REPORT_STATUS_CODE (EFI_PROGRESS_CODE, FSP_STATUS_CODE_READY_TO_BOOT_NOTIFICATION | FSP_STATUS_CODE_COMMON_CODE | FSP_STATUS_CODE_API_ENTRY);\r
245     } else if (NotificationCount == 2) {\r
246       SetPhaseStatusCode (FSP_STATUS_CODE_END_OF_FIRMWARE_NOTIFICATION);\r
247       PERF_START_EX (&gFspPerformanceDataGuid, "EventRec", NULL, 0, FSP_STATUS_CODE_END_OF_FIRMWARE_NOTIFICATION | FSP_STATUS_CODE_COMMON_CODE | FSP_STATUS_CODE_API_ENTRY);\r
248       REPORT_STATUS_CODE (EFI_PROGRESS_CODE, FSP_STATUS_CODE_END_OF_FIRMWARE_NOTIFICATION | FSP_STATUS_CODE_COMMON_CODE | FSP_STATUS_CODE_API_ENTRY);\r
249     }\r
250 \r
251     NotificationValue = ((NOTIFY_PHASE_PARAMS *)(UINTN)GetFspApiParameter ())->Phase;\r
252     DEBUG ((DEBUG_INFO | DEBUG_INIT, "NotifyPhaseApi() - Begin  [Phase: %08X]\n", NotificationValue));\r
253     if (mFspNotifySequence[NotificationCount] != NotificationValue) {\r
254       //\r
255       // Notify code does not follow the predefined order\r
256       //\r
257       DEBUG ((DEBUG_INFO, "Unsupported FSP Notification Value\n"));\r
258       Status = EFI_UNSUPPORTED;\r
259     } else {\r
260       //\r
261       // Process Notification and Give control back to the boot loader framework caller\r
262       //\r
263       Status = FspNotificationHandler (NotificationValue);\r
264       if (!EFI_ERROR(Status)) {\r
265         NotificationCount++;\r
266       }\r
267     }\r
268 \r
269     SetFspApiReturnStatus(Status);\r
270     DEBUG ((DEBUG_INFO | DEBUG_INIT, "NotifyPhaseApi() - End  [Status: 0x%08X]\n", Status));\r
271 \r
272     SetFspMeasurePoint (FSP_PERF_ID_API_NOTIFY_POST_PCI_EXIT + Count);\r
273 \r
274     if ((NotificationCount - 1) == 0) {\r
275       PERF_END_EX(&gFspPerformanceDataGuid, "EventRec", NULL, 0, FSP_STATUS_CODE_POST_PCIE_ENUM_NOTIFICATION | FSP_STATUS_CODE_COMMON_CODE | FSP_STATUS_CODE_API_EXIT);\r
276       REPORT_STATUS_CODE (EFI_PROGRESS_CODE, FSP_STATUS_CODE_POST_PCIE_ENUM_NOTIFICATION | FSP_STATUS_CODE_COMMON_CODE | FSP_STATUS_CODE_API_EXIT);\r
277     } else if ((NotificationCount - 1) == 1) {\r
278       PERF_END_EX(&gFspPerformanceDataGuid, "EventRec", NULL, 0, FSP_STATUS_CODE_READY_TO_BOOT_NOTIFICATION | FSP_STATUS_CODE_COMMON_CODE | FSP_STATUS_CODE_API_EXIT);\r
279       REPORT_STATUS_CODE (EFI_PROGRESS_CODE, FSP_STATUS_CODE_READY_TO_BOOT_NOTIFICATION | FSP_STATUS_CODE_COMMON_CODE | FSP_STATUS_CODE_API_EXIT);\r
280     } else if ((NotificationCount - 1) == 2) {\r
281       PERF_END_EX(&gFspPerformanceDataGuid, "EventRec", NULL, 0, FSP_STATUS_CODE_END_OF_FIRMWARE_NOTIFICATION | FSP_STATUS_CODE_COMMON_CODE | FSP_STATUS_CODE_API_EXIT);\r
282       REPORT_STATUS_CODE (EFI_PROGRESS_CODE, FSP_STATUS_CODE_END_OF_FIRMWARE_NOTIFICATION | FSP_STATUS_CODE_COMMON_CODE | FSP_STATUS_CODE_API_EXIT);\r
283     }\r
284     Pei2LoaderSwitchStack();\r
285   }\r
286 \r
287   //\r
288   // Control goes back to the PEI Core and it dispatches further PEIMs.\r
289   // DXEIPL is the final one to transfer control back to the boot loader.\r
290   //\r
291 }\r
292 \r