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