FspWrapperNotifyDxe.c 9.1 KB

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