IntelFsp2Pkg: Added changes to enable FPDT performance measurements
[mirror_edk2.git] / IntelFsp2WrapperPkg / FspWrapperNotifyDxe / FspWrapperNotifyDxe.c
1 /** @file\r
2   This driver will register two callbacks to call fsp's notifies.\r
3 \r
4   Copyright (c) 2014 - 2016, Intel Corporation. All rights reserved.<BR>\r
5   This program and the accompanying materials\r
6   are licensed and made available under the terms and conditions of the BSD License\r
7   which accompanies this distribution.  The full text of the license may be found at\r
8   http://opensource.org/licenses/bsd-license.php.\r
9 \r
10   THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
11   WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
12 \r
13 **/\r
14 \r
15 #include <PiDxe.h>\r
16 \r
17 #include <Protocol/PciEnumerationComplete.h>\r
18 \r
19 #include <Library/UefiDriverEntryPoint.h>\r
20 #include <Library/UefiBootServicesTableLib.h>\r
21 #include <Library/DebugLib.h>\r
22 #include <Library/BaseMemoryLib.h>\r
23 #include <Library/UefiLib.h>\r
24 #include <Library/FspWrapperApiLib.h>\r
25 #include <Library/FspWrapperPlatformLib.h>\r
26 #include <Library/PerformanceLib.h>\r
27 #include <Library/HobLib.h>\r
28 #include <FspStatusCode.h>\r
29 \r
30 typedef\r
31 EFI_STATUS\r
32 (EFIAPI * ADD_PERFORMANCE_RECORDS)(\r
33   IN CONST VOID *HobStart\r
34   );\r
35 \r
36 struct _ADD_PERFORMANCE_RECORD_PROTOCOL {\r
37   ADD_PERFORMANCE_RECORDS          AddPerformanceRecords;\r
38 };\r
39 \r
40 typedef struct _ADD_PERFORMANCE_RECORD_PROTOCOL ADD_PERFORMANCE_RECORD_PROTOCOL;\r
41 \r
42 extern EFI_GUID gAddPerfRecordProtocolGuid;\r
43 extern EFI_GUID gFspHobGuid;\r
44 extern EFI_GUID gFspApiPerformanceGuid;\r
45 \r
46 EFI_EVENT mExitBootServicesEvent     = NULL;\r
47 \r
48 /**\r
49   Relocate this image under 4G memory.\r
50 \r
51   @param  ImageHandle  Handle of driver image.\r
52   @param  SystemTable  Pointer to system table.\r
53 \r
54   @retval EFI_SUCCESS  Image successfully relocated.\r
55   @retval EFI_ABORTED  Failed to relocate image.\r
56 \r
57 **/\r
58 EFI_STATUS\r
59 RelocateImageUnder4GIfNeeded (\r
60   IN EFI_HANDLE           ImageHandle,\r
61   IN EFI_SYSTEM_TABLE     *SystemTable\r
62   );\r
63 \r
64 /**\r
65   PciEnumerationComplete Protocol notification event handler.\r
66 \r
67   @param[in] Event    Event whose notification function is being invoked.\r
68   @param[in] Context  Pointer to the notification function's context.\r
69 **/\r
70 VOID\r
71 EFIAPI\r
72 OnPciEnumerationComplete (\r
73   IN EFI_EVENT  Event,\r
74   IN VOID       *Context\r
75   )\r
76 {\r
77   NOTIFY_PHASE_PARAMS NotifyPhaseParams;\r
78   EFI_STATUS          Status;\r
79   VOID                *Interface;\r
80 \r
81   //\r
82   // Try to locate it because gEfiPciEnumerationCompleteProtocolGuid will trigger it once when registration.\r
83   // Just return if it is not found.\r
84   //\r
85   Status = gBS->LocateProtocol (\r
86                   &gEfiPciEnumerationCompleteProtocolGuid,\r
87                   NULL,\r
88                   &Interface\r
89                   );\r
90   if (EFI_ERROR (Status)) {\r
91     return ;\r
92   }\r
93 \r
94   NotifyPhaseParams.Phase = EnumInitPhaseAfterPciEnumeration;\r
95   PERF_START_EX(&gFspApiPerformanceGuid, "EventRec", NULL, 0, FSP_STATUS_CODE_POST_PCIE_ENUM_NOTIFICATION | FSP_STATUS_CODE_COMMON_CODE | FSP_STATUS_CODE_API_ENTRY);\r
96   Status = CallFspNotifyPhase (&NotifyPhaseParams);\r
97   PERF_END_EX(&gFspApiPerformanceGuid, "EventRec", NULL, 0, FSP_STATUS_CODE_POST_PCIE_ENUM_NOTIFICATION | FSP_STATUS_CODE_COMMON_CODE | FSP_STATUS_CODE_API_EXIT);\r
98 \r
99   //\r
100   // Reset the system if FSP API returned FSP_STATUS_RESET_REQUIRED status\r
101   //\r
102   if ((Status >= FSP_STATUS_RESET_REQUIRED_COLD) && (Status <= FSP_STATUS_RESET_REQUIRED_8)) {\r
103     DEBUG((DEBUG_INFO, "FSP NotifyPhase AfterPciEnumeration requested reset 0x%x\n", Status));\r
104     CallFspWrapperResetSystem ((UINT32)Status);\r
105   }\r
106 \r
107   if (Status != EFI_SUCCESS) {\r
108     DEBUG((DEBUG_ERROR, "FSP NotifyPhase AfterPciEnumeration failed, status: 0x%x\n", Status));\r
109   } else {\r
110     DEBUG((DEBUG_INFO, "FSP NotifyPhase AfterPciEnumeration Success.\n"));\r
111   }\r
112 }\r
113 \r
114 /**\r
115   Notification function of EVT_GROUP_READY_TO_BOOT event group.\r
116 \r
117   This is a notification function registered on EVT_GROUP_READY_TO_BOOT event group.\r
118   When the Boot Manager is about to load and execute a boot option, it reclaims variable\r
119   storage if free size is below the threshold.\r
120 \r
121   @param[in] Event        Event whose notification function is being invoked.\r
122   @param[in] Context      Pointer to the notification function's context.\r
123 \r
124 **/\r
125 VOID\r
126 EFIAPI\r
127 OnReadyToBoot (\r
128   IN EFI_EVENT  Event,\r
129   IN VOID       *Context\r
130   )\r
131 {\r
132   NOTIFY_PHASE_PARAMS               NotifyPhaseParams;\r
133   EFI_STATUS                        Status;\r
134 \r
135   gBS->CloseEvent (Event);\r
136 \r
137   NotifyPhaseParams.Phase = EnumInitPhaseReadyToBoot;\r
138   PERF_START_EX(&gFspApiPerformanceGuid, "EventRec", NULL, 0, FSP_STATUS_CODE_READY_TO_BOOT_NOTIFICATION | FSP_STATUS_CODE_COMMON_CODE | FSP_STATUS_CODE_API_ENTRY);\r
139   Status = CallFspNotifyPhase (&NotifyPhaseParams);\r
140   PERF_END_EX(&gFspApiPerformanceGuid, "EventRec", NULL, 0, FSP_STATUS_CODE_READY_TO_BOOT_NOTIFICATION | FSP_STATUS_CODE_COMMON_CODE | FSP_STATUS_CODE_API_EXIT);\r
141 \r
142   //\r
143   // Reset the system if FSP API returned FSP_STATUS_RESET_REQUIRED status\r
144   //\r
145   if ((Status >= FSP_STATUS_RESET_REQUIRED_COLD) && (Status <= FSP_STATUS_RESET_REQUIRED_8)) {\r
146     DEBUG((DEBUG_INFO, "FSP NotifyPhase ReadyToBoot requested reset 0x%x\n", Status));\r
147     CallFspWrapperResetSystem ((UINT32)Status);\r
148   }\r
149 \r
150   if (Status != EFI_SUCCESS) {\r
151     DEBUG((DEBUG_ERROR, "FSP NotifyPhase ReadyToBoot failed, status: 0x%x\n", Status));\r
152   } else {\r
153     DEBUG((DEBUG_INFO, "FSP NotifyPhase ReadyToBoot Success.\n"));\r
154   }\r
155 }\r
156 \r
157 /**\r
158   This stage is notified just before the firmware/Preboot environment transfers\r
159   management of all system resources to the OS or next level execution environment.\r
160 \r
161   @param  Event         Event whose notification function is being invoked.\r
162   @param  Context       Pointer to the notification function's context, which is\r
163                         always zero in current implementation.\r
164 \r
165 **/\r
166 VOID\r
167 EFIAPI\r
168 OnEndOfFirmware (\r
169   IN EFI_EVENT  Event,\r
170   IN VOID       *Context\r
171   )\r
172 {\r
173   NOTIFY_PHASE_PARAMS               NotifyPhaseParams;\r
174   EFI_STATUS                        Status;\r
175   ADD_PERFORMANCE_RECORD_PROTOCOL   *AddPerfRecordInterface;\r
176   EFI_PEI_HOB_POINTERS              Hob;\r
177   VOID                              **FspHobListPtr;\r
178 \r
179   gBS->CloseEvent (Event);\r
180 \r
181   NotifyPhaseParams.Phase = EnumInitPhaseEndOfFirmware;\r
182   PERF_START_EX(&gFspApiPerformanceGuid, "EventRec", NULL, 0, FSP_STATUS_CODE_END_OF_FIRMWARE_NOTIFICATION | FSP_STATUS_CODE_COMMON_CODE | FSP_STATUS_CODE_API_ENTRY);\r
183   Status = CallFspNotifyPhase (&NotifyPhaseParams);\r
184   PERF_END_EX(&gFspApiPerformanceGuid, "EventRec", NULL, 0, FSP_STATUS_CODE_END_OF_FIRMWARE_NOTIFICATION | FSP_STATUS_CODE_COMMON_CODE | FSP_STATUS_CODE_API_EXIT);\r
185 \r
186   //\r
187   // Reset the system if FSP API returned FSP_STATUS_RESET_REQUIRED status\r
188   //\r
189   if ((Status >= FSP_STATUS_RESET_REQUIRED_COLD) && (Status <= FSP_STATUS_RESET_REQUIRED_8)) {\r
190     DEBUG((DEBUG_INFO, "FSP NotifyPhase EndOfFirmware requested reset 0x%x\n", Status));\r
191     CallFspWrapperResetSystem ((UINT32)Status);\r
192   }\r
193 \r
194   if (Status != EFI_SUCCESS) {\r
195     DEBUG((DEBUG_ERROR, "FSP NotifyPhase EndOfFirmware failed, status: 0x%x\n", Status));\r
196   } else {\r
197     DEBUG((DEBUG_INFO, "FSP NotifyPhase EndOfFirmware Success.\n"));\r
198   }\r
199   Status = gBS->LocateProtocol (\r
200                   &gAddPerfRecordProtocolGuid,\r
201                   NULL,\r
202                   (VOID**) &AddPerfRecordInterface\r
203                   );\r
204   if (EFI_ERROR (Status)) {\r
205     DEBUG((DEBUG_INFO, "gAddPerfRecordProtocolGuid - Locate protocol failed\n"));\r
206     return;\r
207   } else {\r
208     Hob.Raw = GetFirstGuidHob (&gFspHobGuid);\r
209     if (Hob.Raw != NULL) {\r
210       FspHobListPtr = GET_GUID_HOB_DATA (Hob.Raw);\r
211       AddPerfRecordInterface->AddPerformanceRecords ((VOID *)(UINTN)(((UINT32)(UINTN)*FspHobListPtr) & 0xFFFFFFFF));\r
212     }\r
213   }\r
214 }\r
215 \r
216 /**\r
217   Main entry for the FSP DXE module.\r
218 \r
219   This routine registers two callbacks to call fsp's notifies.\r
220 \r
221   @param[in] ImageHandle    The firmware allocated handle for the EFI image.\r
222   @param[in] SystemTable    A pointer to the EFI System Table.\r
223 \r
224   @retval EFI_SUCCESS       The entry point is executed successfully.\r
225   @retval other             Some error occurs when executing this entry point.\r
226 \r
227 **/\r
228 EFI_STATUS\r
229 EFIAPI\r
230 FspWrapperNotifyDxeEntryPoint (\r
231   IN EFI_HANDLE         ImageHandle,\r
232   IN EFI_SYSTEM_TABLE   *SystemTable\r
233   )\r
234 {\r
235   EFI_STATUS Status;\r
236   EFI_EVENT  ReadyToBootEvent;\r
237   VOID       *Registration;\r
238   EFI_EVENT  ProtocolNotifyEvent;\r
239 \r
240   //\r
241   // Load this driver's image to memory\r
242   //\r
243   Status = RelocateImageUnder4GIfNeeded (ImageHandle, SystemTable);\r
244   if (EFI_ERROR (Status)) {\r
245     return EFI_SUCCESS;\r
246   }\r
247 \r
248   ProtocolNotifyEvent = EfiCreateProtocolNotifyEvent (\r
249                           &gEfiPciEnumerationCompleteProtocolGuid,\r
250                           TPL_CALLBACK,\r
251                           OnPciEnumerationComplete,\r
252                           NULL,\r
253                           &Registration\r
254                           );\r
255   ASSERT (ProtocolNotifyEvent != NULL);\r
256 \r
257   Status = EfiCreateEventReadyToBootEx (\r
258              TPL_CALLBACK,\r
259              OnReadyToBoot,\r
260              NULL,\r
261              &ReadyToBootEvent\r
262              );\r
263   ASSERT_EFI_ERROR (Status);\r
264 \r
265   Status = gBS->CreateEventEx (\r
266                   EVT_NOTIFY_SIGNAL,\r
267                   TPL_NOTIFY,\r
268                   OnEndOfFirmware,\r
269                   NULL,\r
270                   &gEfiEventExitBootServicesGuid,\r
271                   &mExitBootServicesEvent\r
272                   );\r
273   ASSERT_EFI_ERROR (Status);\r
274 \r
275   return EFI_SUCCESS;\r
276 }\r
277 \r