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