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