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