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