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