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