SmmRuntimeDxeSupport.c revision e12848a3a3b8ae1470cdf53ba30a8c29c70fee51
1/** @file 2 Report Status Code Library for DXE Phase. 3 4 Copyright (c) 2006 - 2007, Intel Corporation<BR> 5 All rights reserved. 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 "ReportStatusCodeLibInternal.h" 16 17// 18// Resources need by SMM runtime instance 19// 20#include <Library/OemHookStatusCodeLib.h> 21#include <Protocol/SmmBase.h> 22 23STATIC 24EFI_EVENT mVirtualAddressChangeEvent; 25 26STATIC 27EFI_EVENT mExitBootServicesEvent; 28 29STATIC 30EFI_STATUS_CODE_DATA *mStatusCodeData; 31 32STATIC 33BOOLEAN mInSmm; 34 35STATIC 36EFI_RUNTIME_SERVICES *mRT; 37 38STATIC 39EFI_BOOT_SERVICES *mBS; 40 41STATIC 42BOOLEAN mHaveExitedBootServices = FALSE; 43 44/** 45 Locatet he report status code service. 46 47 @return EFI_REPORT_STATUS_CODE function point to 48 ReportStatusCode. 49**/ 50EFI_REPORT_STATUS_CODE 51InternalGetReportStatusCode ( 52 VOID 53 ) 54{ 55 EFI_STATUS_CODE_PROTOCOL *StatusCodeProtocol; 56 EFI_STATUS Status; 57 58 if (mInSmm) { 59 return (EFI_REPORT_STATUS_CODE) OemHookStatusCodeReport; 60 } else if (mRT->Hdr.Revision < 0x20000) { 61 return ((FRAMEWORK_EFI_RUNTIME_SERVICES*)mRT)->ReportStatusCode; 62 } else if (!mHaveExitedBootServices) { 63 Status = mBS->LocateProtocol (&gEfiStatusCodeRuntimeProtocolGuid, NULL, (VOID**)&StatusCodeProtocol); 64 if (!EFI_ERROR (Status) && StatusCodeProtocol != NULL) { 65 return StatusCodeProtocol->ReportStatusCode; 66 } 67 } 68 69 return NULL; 70} 71 72 73/** 74 Fixup internal report status code protocol interface. 75 76 @param[in] Event The Event that is being processed 77 @param[in] Context Event Context 78**/ 79STATIC 80VOID 81EFIAPI 82ReportStatusCodeLibVirtualAddressChange ( 83 IN EFI_EVENT Event, 84 IN VOID *Context 85 ) 86{ 87 if (NULL != mReportStatusCode) { 88 mRT->ConvertPointer (0, (VOID **) &mReportStatusCode); 89 } 90 mRT->ConvertPointer (0, (VOID **) &mStatusCodeData); 91 mRT->ConvertPointer (0, (VOID **) &mRT); 92} 93 94/** 95 Updatet the In Runtime Indicator. 96 97 @param[in] Event The Event that is being processed 98 @param[in] Context Event Context 99**/ 100STATIC 101VOID 102EFIAPI 103ReportStatusCodeLibExitBootServices ( 104 IN EFI_EVENT Event, 105 IN VOID *Context 106 ) 107{ 108 mHaveExitedBootServices = TRUE; 109} 110 111/** 112 Intialize Report Status Code Lib. 113 114 @param[in] ImageHandle The firmware allocated handle for the EFI image. 115 @param[in] SystemTable A pointer to the EFI System Table. 116 117 @return EFI_STATUS always returns EFI_SUCCESS. 118**/ 119EFI_STATUS 120EFIAPI 121ReportStatusCodeLibConstruct ( 122 IN EFI_HANDLE ImageHandle, 123 IN EFI_SYSTEM_TABLE *SystemTable 124 ) 125{ 126 EFI_SMM_BASE_PROTOCOL *SmmBase; 127 EFI_STATUS Status; 128 129 mBS = SystemTable->BootServices; 130 131 // 132 // SMM driver depends on the SMM BASE protocol. 133 // the SMM driver must be success to locate protocol. 134 // 135 ASSERT (mBS != NULL); 136 Status = mBS->LocateProtocol (&gEfiSmmBaseProtocolGuid, NULL, (VOID **) &SmmBase); 137 if (!EFI_ERROR (Status)) { 138 SmmBase->InSmm (SmmBase, &mInSmm); 139 if (mInSmm) { 140 Status = SmmBase->SmmAllocatePool ( 141 SmmBase, 142 EfiRuntimeServicesData, 143 sizeof (EFI_STATUS_CODE_DATA) + EFI_STATUS_CODE_DATA_MAX_SIZE, 144 (VOID **) &mStatusCodeData 145 ); 146 ASSERT_EFI_ERROR (Status); 147 OemHookStatusCodeInitialize (); 148 return EFI_SUCCESS; 149 } 150 } 151 152 // 153 // Library should not use the gRT directly, since it 154 // may be converted by other library instance. 155 // 156 mRT = gRT; 157 mInSmm = FALSE; 158 159 mBS->AllocatePool (EfiRuntimeServicesData, sizeof (EFI_STATUS_CODE_DATA) + EFI_STATUS_CODE_DATA_MAX_SIZE, (VOID **)&mStatusCodeData); 160 ASSERT (NULL != mStatusCodeData); 161 // 162 // Cache the report status code service 163 // 164 mReportStatusCode = InternalGetReportStatusCode (); 165 166 // 167 // Register the call back of virtual address change 168 // 169 Status = mBS->CreateEvent ( 170 EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE, 171 TPL_NOTIFY, 172 ReportStatusCodeLibVirtualAddressChange, 173 NULL, 174 &mVirtualAddressChangeEvent 175 ); 176 ASSERT_EFI_ERROR (Status); 177 178 179 // 180 // Register the call back of virtual address change 181 // 182 Status = mBS->CreateEvent ( 183 EVT_SIGNAL_EXIT_BOOT_SERVICES, 184 TPL_NOTIFY, 185 ReportStatusCodeLibExitBootServices, 186 NULL, 187 &mExitBootServicesEvent 188 ); 189 ASSERT_EFI_ERROR (Status); 190 191 return Status; 192} 193 194 195EFI_STATUS 196EFIAPI 197ReportStatusCodeLibDestruct ( 198 IN EFI_HANDLE ImageHandle, 199 IN EFI_SYSTEM_TABLE *SystemTable 200 ) 201{ 202 EFI_STATUS Status; 203 204 // 205 // Close SetVirtualAddressMap () notify function 206 // 207 ASSERT (mBS != NULL); 208 Status = mBS->CloseEvent (mVirtualAddressChangeEvent); 209 ASSERT_EFI_ERROR (Status); 210 Status = mBS->CloseEvent (mExitBootServicesEvent); 211 ASSERT_EFI_ERROR (Status); 212 213 mBS->FreePool (mStatusCodeData); 214 215 return Status; 216} 217 218 219/** 220 Reports a status code with full parameters. 221 222 The function reports a status code. If ExtendedData is NULL and ExtendedDataSize 223 is 0, then an extended data buffer is not reported. If ExtendedData is not 224 NULL and ExtendedDataSize is not 0, then an extended data buffer is allocated. 225 ExtendedData is assumed not have the standard status code header, so this function 226 is responsible for allocating a buffer large enough for the standard header and 227 the extended data passed into this function. The standard header is filled in 228 with a GUID specified by ExtendedDataGuid. If ExtendedDataGuid is NULL, then a 229 GUID of gEfiStatusCodeSpecificDatauid is used. The status code is reported with 230 an instance specified by Instance and a caller ID specified by CallerId. If 231 CallerId is NULL, then a caller ID of gEfiCallerIdGuid is used. 232 233 ReportStatusCodeEx()must actively prevent recursion. If ReportStatusCodeEx() 234 is called while processing another any other Report Status Code Library function, 235 then ReportStatusCodeEx() must return EFI_DEVICE_ERROR immediately. 236 237 If ExtendedData is NULL and ExtendedDataSize is not zero, then ASSERT(). 238 If ExtendedData is not NULL and ExtendedDataSize is zero, then ASSERT(). 239 240 @param Type Status code type. 241 @param Value Status code value. 242 @param Instance Status code instance number. 243 @param CallerId Pointer to a GUID that identifies the caller of this 244 function. If this parameter is NULL, then a caller 245 ID of gEfiCallerIdGuid is used. 246 @param ExtendedDataGuid Pointer to the GUID for the extended data buffer. 247 If this parameter is NULL, then a the status code 248 standard header is filled in with 249 gEfiStatusCodeSpecificDataGuid. 250 @param ExtendedData Pointer to the extended data buffer. This is an 251 optional parameter that may be NULL. 252 @param ExtendedDataSize The size, in bytes, of the extended data buffer. 253 254 @retval EFI_SUCCESS The status code was reported. 255 @retval EFI_OUT_OF_RESOURCES There were not enough resources to allocate 256 the extended data section if it was specified. 257 @retval EFI_UNSUPPORTED Report status code is not supported 258 259**/ 260EFI_STATUS 261EFIAPI 262InternalReportStatusCodeEx ( 263 IN EFI_STATUS_CODE_TYPE Type, 264 IN EFI_STATUS_CODE_VALUE Value, 265 IN UINT32 Instance, 266 IN CONST EFI_GUID *CallerId OPTIONAL, 267 IN CONST EFI_GUID *ExtendedDataGuid OPTIONAL, 268 IN CONST VOID *ExtendedData OPTIONAL, 269 IN UINTN ExtendedDataSize 270 ) 271{ 272 ASSERT (!((ExtendedData == NULL) && (ExtendedDataSize != 0))); 273 ASSERT (!((ExtendedData != NULL) && (ExtendedDataSize == 0))); 274 275 if (ExtendedDataSize > EFI_STATUS_CODE_DATA_MAX_SIZE) { 276 return EFI_OUT_OF_RESOURCES; 277 } 278 279 // 280 // Fill in the extended data header 281 // 282 mStatusCodeData->HeaderSize = sizeof (EFI_STATUS_CODE_DATA); 283 mStatusCodeData->Size = (UINT16)ExtendedDataSize; 284 if (ExtendedDataGuid == NULL) { 285 ExtendedDataGuid = &gEfiStatusCodeSpecificDataGuid; 286 } 287 CopyGuid (&mStatusCodeData->Type, ExtendedDataGuid); 288 289 // 290 // Fill in the extended data buffer 291 // 292 CopyMem (mStatusCodeData + 1, ExtendedData, ExtendedDataSize); 293 294 // 295 // Report the status code 296 // 297 if (CallerId == NULL) { 298 CallerId = &gEfiCallerIdGuid; 299 } 300 return InternalReportStatusCode (Type, Value, Instance, CallerId, mStatusCodeData); 301} 302