Add IntelFsp2Pkg and IntelFsp2WrapperPkg.
[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/PerformanceLib.h>\r
26 #include <Library/HobLib.h>\r
27 \r
28 typedef\r
29 EFI_STATUS\r
30 (EFIAPI * ADD_PERFORMANCE_RECORDS)(\r
31   IN CONST VOID *HobStart\r
32   );\r
33 \r
34 struct _ADD_PERFORMANCE_RECORD_PROTOCOL {\r
35   ADD_PERFORMANCE_RECORDS          AddPerformanceRecords;\r
36 };\r
37 \r
38 typedef struct _ADD_PERFORMANCE_RECORD_PROTOCOL ADD_PERFORMANCE_RECORD_PROTOCOL;\r
39 \r
40 extern EFI_GUID gAddPerfRecordProtocolGuid;\r
41 extern EFI_GUID gFspHobGuid;\r
42 extern EFI_GUID gFspApiPerformanceGuid;\r
43 \r
44 EFI_EVENT mExitBootServicesEvent     = NULL;\r
45 \r
46 /**\r
47   Relocate this image under 4G memory.\r
48 \r
49   @param  ImageHandle  Handle of driver image.\r
50   @param  SystemTable  Pointer to system table.\r
51 \r
52   @retval EFI_SUCCESS  Image successfully relocated.\r
53   @retval EFI_ABORTED  Failed to relocate image.\r
54 \r
55 **/\r
56 EFI_STATUS\r
57 RelocateImageUnder4GIfNeeded (\r
58   IN EFI_HANDLE           ImageHandle,\r
59   IN EFI_SYSTEM_TABLE     *SystemTable\r
60   );\r
61 \r
62 /**\r
63   PciEnumerationComplete Protocol notification event handler.\r
64 \r
65   @param[in] Event    Event whose notification function is being invoked.\r
66   @param[in] Context  Pointer to the notification function's context.\r
67 **/\r
68 VOID\r
69 EFIAPI\r
70 OnPciEnumerationComplete (\r
71   IN EFI_EVENT  Event,\r
72   IN VOID       *Context\r
73   )\r
74 {\r
75   NOTIFY_PHASE_PARAMS NotifyPhaseParams;\r
76   EFI_STATUS          Status;\r
77   VOID                *Interface;\r
78 \r
79   //\r
80   // Try to locate it because gEfiPciEnumerationCompleteProtocolGuid will trigger it once when registration.\r
81   // Just return if it is not found.\r
82   //\r
83   Status = gBS->LocateProtocol (\r
84                   &gEfiPciEnumerationCompleteProtocolGuid,\r
85                   NULL,\r
86                   &Interface\r
87                   );\r
88   if (EFI_ERROR (Status)) {\r
89     return ;\r
90   }\r
91 \r
92   NotifyPhaseParams.Phase = EnumInitPhaseAfterPciEnumeration;\r
93   PERF_START_EX(&gFspApiPerformanceGuid, "EventRec", NULL, 0, 0x6000);\r
94   Status = CallFspNotifyPhase (&NotifyPhaseParams);\r
95   PERF_END_EX(&gFspApiPerformanceGuid, "EventRec", NULL, 0, 0x607F);\r
96   if (Status != EFI_SUCCESS) {\r
97     DEBUG((DEBUG_ERROR, "FSP NotifyPhase AfterPciEnumeration failed, status: 0x%x\n", Status));\r
98   } else {\r
99     DEBUG((DEBUG_INFO, "FSP NotifyPhase AfterPciEnumeration Success.\n"));\r
100   }\r
101 }\r
102 \r
103 /**\r
104   Notification function of EVT_GROUP_READY_TO_BOOT event group.\r
105 \r
106   This is a notification function registered on EVT_GROUP_READY_TO_BOOT event group.\r
107   When the Boot Manager is about to load and execute a boot option, it reclaims variable\r
108   storage if free size is below the threshold.\r
109 \r
110   @param[in] Event        Event whose notification function is being invoked.\r
111   @param[in] Context      Pointer to the notification function's context.\r
112 \r
113 **/\r
114 VOID\r
115 EFIAPI\r
116 OnReadyToBoot (\r
117   IN EFI_EVENT  Event,\r
118   IN VOID       *Context\r
119   )\r
120 {\r
121   NOTIFY_PHASE_PARAMS               NotifyPhaseParams;\r
122   EFI_STATUS                        Status;\r
123   ADD_PERFORMANCE_RECORD_PROTOCOL   *AddPerfRecordInterface;\r
124   EFI_PEI_HOB_POINTERS              Hob;\r
125   VOID                              **FspHobListPtr;\r
126 \r
127   gBS->CloseEvent (Event);\r
128 \r
129   NotifyPhaseParams.Phase = EnumInitPhaseReadyToBoot;\r
130   PERF_START_EX(&gFspApiPerformanceGuid, "EventRec", NULL, 0, 0x4000);\r
131   Status = CallFspNotifyPhase (&NotifyPhaseParams);\r
132   PERF_END_EX(&gFspApiPerformanceGuid, "EventRec", NULL, 0, 0x407F);\r
133   if (Status != EFI_SUCCESS) {\r
134     DEBUG((DEBUG_ERROR, "FSP NotifyPhase ReadyToBoot failed, status: 0x%x\n", Status));\r
135   } else {\r
136     DEBUG((DEBUG_INFO, "FSP NotifyPhase ReadyToBoot Success.\n"));\r
137   }\r
138 \r
139   Status = gBS->LocateProtocol (\r
140                   &gAddPerfRecordProtocolGuid,\r
141                   NULL,\r
142                   (VOID**) &AddPerfRecordInterface\r
143                   );\r
144   if (EFI_ERROR (Status)) {\r
145     DEBUG((DEBUG_INFO, "gAddPerfRecordProtocolGuid - Locate protocol failed\n"));\r
146     return;\r
147   } else {\r
148     Hob.Raw = GetHobList ();\r
149     if (Hob.Raw != NULL) {\r
150       Hob.Raw = GetNextGuidHob (&gFspHobGuid, Hob.Raw);\r
151       FspHobListPtr = GET_GUID_HOB_DATA(Hob.Raw);\r
152       AddPerfRecordInterface->AddPerformanceRecords((VOID *)(UINTN)(((UINT32)(UINTN)*FspHobListPtr) & 0xFFFFFFFF));\r
153     }\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 \r
176   gBS->CloseEvent (Event);\r
177 \r
178   NotifyPhaseParams.Phase = EnumInitPhaseEndOfFirmware;\r
179   PERF_START_EX(&gFspApiPerformanceGuid, "EventRec", NULL, 0, 0x2000);\r
180   Status = CallFspNotifyPhase (&NotifyPhaseParams);\r
181   PERF_END_EX(&gFspApiPerformanceGuid, "EventRec", NULL, 0, 0x207F);\r
182   if (Status != EFI_SUCCESS) {\r
183     DEBUG((DEBUG_ERROR, "FSP NotifyPhase EndOfFirmware failed, status: 0x%x\n", Status));\r
184   } else {\r
185     DEBUG((DEBUG_INFO, "FSP NotifyPhase EndOfFirmware Success.\n"));\r
186   }\r
187 }\r
188 \r
189 /**\r
190   Main entry for the FSP DXE module.\r
191 \r
192   This routine registers two callbacks to call fsp's notifies.\r
193 \r
194   @param[in] ImageHandle    The firmware allocated handle for the EFI image.\r
195   @param[in] SystemTable    A pointer to the EFI System Table.\r
196 \r
197   @retval EFI_SUCCESS       The entry point is executed successfully.\r
198   @retval other             Some error occurs when executing this entry point.\r
199 \r
200 **/\r
201 EFI_STATUS\r
202 EFIAPI\r
203 FspWrapperNotifyDxeEntryPoint (\r
204   IN EFI_HANDLE         ImageHandle,\r
205   IN EFI_SYSTEM_TABLE   *SystemTable\r
206   )\r
207 {\r
208   EFI_STATUS Status;\r
209   EFI_EVENT  ReadyToBootEvent;\r
210   VOID       *Registration;\r
211   EFI_EVENT  ProtocolNotifyEvent;\r
212 \r
213   //\r
214   // Load this driver's image to memory\r
215   //\r
216   Status = RelocateImageUnder4GIfNeeded (ImageHandle, SystemTable);\r
217   if (EFI_ERROR (Status)) {\r
218     return EFI_SUCCESS;\r
219   }\r
220 \r
221   ProtocolNotifyEvent = EfiCreateProtocolNotifyEvent (\r
222                           &gEfiPciEnumerationCompleteProtocolGuid,\r
223                           TPL_CALLBACK,\r
224                           OnPciEnumerationComplete,\r
225                           NULL,\r
226                           &Registration\r
227                           );\r
228   ASSERT (ProtocolNotifyEvent != NULL);\r
229 \r
230   Status = EfiCreateEventReadyToBootEx (\r
231              TPL_CALLBACK,\r
232              OnReadyToBoot,\r
233              NULL,\r
234              &ReadyToBootEvent\r
235              );\r
236   ASSERT_EFI_ERROR (Status);\r
237 \r
238   Status = gBS->CreateEventEx (\r
239                   EVT_NOTIFY_SIGNAL,\r
240                   TPL_NOTIFY,\r
241                   OnEndOfFirmware,\r
242                   NULL,\r
243                   &gEfiEventExitBootServicesGuid,\r
244                   &mExitBootServicesEvent\r
245                   );\r
246   ASSERT_EFI_ERROR (Status);\r
247 \r
248   return EFI_SUCCESS;\r
249 }\r
250 \r