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 32typedef 33EFI_STATUS 34(EFIAPI * ADD_PERFORMANCE_RECORDS)( 35 IN CONST VOID *HobStart 36 ); 37 38struct _ADD_PERFORMANCE_RECORD_PROTOCOL { 39 ADD_PERFORMANCE_RECORDS AddPerformanceRecords; 40}; 41 42typedef struct _ADD_PERFORMANCE_RECORD_PROTOCOL ADD_PERFORMANCE_RECORD_PROTOCOL; 43 44extern EFI_GUID gAddPerfRecordProtocolGuid; 45extern EFI_GUID gFspHobGuid; 46extern EFI_GUID gFspApiPerformanceGuid; 47 48EFI_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**/ 60EFI_STATUS 61RelocateImageUnder4GIfNeeded ( 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**/ 72VOID 73EFIAPI 74OnPciEnumerationComplete ( 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**/ 127VOID 128EFIAPI 129OnReadyToBoot ( 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**/ 168VOID 169EFIAPI 170OnEndOfFirmware ( 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**/ 230EFI_STATUS 231EFIAPI 232FspWrapperNotifyDxeEntryPoint ( 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