diff options
Diffstat (limited to 'EDK/Foundation/Library/EdkIIGlueLib/Library/SmmRuntimeDxeReportStatusCodeLib/SmmRuntimeDxeSupport.c')
-rw-r--r-- | EDK/Foundation/Library/EdkIIGlueLib/Library/SmmRuntimeDxeReportStatusCodeLib/SmmRuntimeDxeSupport.c | 698 |
1 files changed, 698 insertions, 0 deletions
diff --git a/EDK/Foundation/Library/EdkIIGlueLib/Library/SmmRuntimeDxeReportStatusCodeLib/SmmRuntimeDxeSupport.c b/EDK/Foundation/Library/EdkIIGlueLib/Library/SmmRuntimeDxeReportStatusCodeLib/SmmRuntimeDxeSupport.c new file mode 100644 index 0000000..07b1487 --- /dev/null +++ b/EDK/Foundation/Library/EdkIIGlueLib/Library/SmmRuntimeDxeReportStatusCodeLib/SmmRuntimeDxeSupport.c @@ -0,0 +1,698 @@ +/*++ + +Copyright (c) 2004 - 2011, Intel Corporation +All rights reserved. This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + +Module Name: + + SmmRuntimeDxeSupport.c + +Abstract: + + Report Status Code Library for DXE Phase. + +--*/ + +#include "ReportStatusCodeLibInternal.h" +#include EFI_PROTOCOL_DEFINITION (SmmStatusCode) +#include EFI_GUID_DEFINITION (GlobalVariable) + +#define DEBUG_MASK_VARIABLE_NAME L"EFIDebug" + +EFI_EVENT mVirtualAddressChangeEvent; +EFI_EVENT mExitBootServicesEvent; +EFI_EVENT mSmmStatusCodeEvent = NULL; +EFI_STATUS_CODE_DATA *mStatusCodeData; +BOOLEAN mInSmm; +EFI_SMM_BASE_PROTOCOL *mSmmBase; +EFI_RUNTIME_SERVICES *mRTSmmRuntimeDxeReportStatusCodeLib; +BOOLEAN mHaveExitedBootServices = FALSE; +EFI_SMM_STATUS_CODE_PROTOCOL *mSmmStatusCode; +UINTN mErrorLevel = EDKII_GLUE_DebugPrintErrorLevel; +BOOLEAN mDebugMaskInitialized = FALSE; + +EFI_STATUS +InstallSmmDebugMaskProtocol ( + IN EFI_HANDLE ImageHandle + ); + +EFI_STATUS +InstallRuntimeDebugMaskProtocol ( + IN EFI_HANDLE ImageHandle + ); + +EFI_STATUS +UnInstallRuntimeDebugMaskProtocol ( + IN EFI_HANDLE ImageHandle + ); + +EFI_STATUS +UnInstallSmmDebugMaskProtocol ( + IN EFI_HANDLE ImageHandle + ); + +VOID +InitializeDebugMask ( + ) +/*++ + +Routine Description: + + Initialize the debug mask when the variable service is ready. + +--*/ +{ + EFI_STATUS Status; + UINTN DebugMask; + UINTN DataSize; + + DataSize = sizeof(UINTN); + Status = gRT->GetVariable( + DEBUG_MASK_VARIABLE_NAME, + &gEfiGlobalVariableGuid, + NULL, + &DataSize, + &DebugMask + ); + + if (Status != EFI_NOT_AVAILABLE_YET) { + // + // If EFI Variable Services are available, then set a flag so the EFI + // Variable will not be read again by this module. + // + mDebugMaskInitialized = TRUE; + if (!EFI_ERROR (Status)) { + // + // If the EFI Varible exists, then set this module's module's mask to + // the global level mask value. + // + mErrorLevel = DebugMask; + } + } +} + +EFI_STATUS +EFIAPI +GetDebugMask ( + IN EFI_DEBUG_MASK_PROTOCOL *This, // Calling context + IN OUT UINTN *CurrentDebugMask // Ptr to store current debug mask + ) +/*++ + +Routine Description: + DebugMask protocol member function. + Gets the current debug mask for an image, on which this protocol has been installed. + +Arguments: + + This - Indicates calling context + CurrentDebugMask - Ptr to store current debug mask + +Returns: + EFI_SUCCESS - Debug mask is retrieved successfully + EFI_INVALID_PARAMETER - CurrentDebugMask is NULL. + EFI_UNSUPPORTED - The handle on which this protocol is installed is not an image handle. + +--*/ +{ + // + // Check Parameter + // + if (CurrentDebugMask == NULL){ + return EFI_INVALID_PARAMETER; + } + + *CurrentDebugMask = mErrorLevel; + return EFI_SUCCESS; +} + +EFI_STATUS +EFIAPI +SetDebugMask ( + IN EFI_DEBUG_MASK_PROTOCOL *This, // Calling context + IN UINTN NewDebugMask // New Debug Mask value to set + ) +/*++ + +Routine Description: + DebugMask protocol member function. + Updates the current debug mask for an image, on which this protocol has been installed. + +Arguments: + + This - Calling context + NewDebugMask - New Debug Mask value to set + +Returns: + EFI_SUCCESS - Debug mask is updated with the new value successfully + EFI_UNSUPPORTED - The handle on which this protocol is installed is not an image handle. + +--*/ +{ + + if (!mDebugMaskInitialized) { + // + // If DebugMask is set, it is initialized. Don't need to init again. + // + mDebugMaskInitialized = TRUE; + } + + mErrorLevel = NewDebugMask; + return EFI_SUCCESS; +} + +// +// Debug Mask Protocol instance +// +EFI_DEBUG_MASK_PROTOCOL mDebugMaskProtocol = { + EFI_DEBUG_MASK_REVISION, + GetDebugMask, + SetDebugMask +}; + +EFI_STATUS +InstallSmmDebugMaskProtocol ( + IN EFI_HANDLE ImageHandle + ) +/*++ + +Routine Description: + + Install Smm debug mask protocol on an image handle. + +Arguments: + + ImageHandle - Image handle which debug mask protocol will install on + +Returns: + + EFI_INVALID_PARAMETER - Invalid image handle + EFI_OUT_OF_RESOURCES - No enough buffer could be allocated + EFI_SUCCESS - Debug mask protocol successfully installed + +--*/ +{ + EFI_STATUS Status; + + // + // Install Debug Mask Protocol in Image Handle + // + Status = gBS->InstallProtocolInterface ( + &ImageHandle, + &gEfiSmmDebugMaskProtocolGuid, + EFI_NATIVE_INTERFACE, + &mDebugMaskProtocol + ); + return Status; +} + +EFI_STATUS +UnInstallSmmDebugMaskProtocol ( + IN EFI_HANDLE ImageHandle + ) +/*++ + +Routine Description: + + Uninstall Smm debug mask protocol on an image handle. + +Arguments: + + ImageHandle - Image handle which debug mask protocol will uninstall on + +Returns: + + EFI_INVALID_PARAMETER - Invalid image handle + EFI_SUCCESS - Debug mask protocol successfully uninstalled + +--*/ +{ + EFI_STATUS Status; + + if (ImageHandle == NULL) { + return EFI_INVALID_PARAMETER; + } + + // + // Install Debug Mask Protocol in Image Handle + // + Status = gBS->UninstallProtocolInterface ( + &ImageHandle, + &gEfiSmmDebugMaskProtocolGuid, + &mDebugMaskProtocol + ); + + if (EFI_ERROR (Status)) { + return Status; + } + return EFI_SUCCESS; +} + +EFI_STATUS +InstallRuntimeDebugMaskProtocol ( + IN EFI_HANDLE ImageHandle + ) +/*++ + +Routine Description: + + Install Runtime debug mask protocol on an image handle. + +Arguments: + + ImageHandle - Image handle which debug mask protocol will install on + +Returns: + + EFI_INVALID_PARAMETER - Invalid image handle + EFI_OUT_OF_RESOURCES - No enough buffer could be allocated + EFI_SUCCESS - Debug mask protocol successfully installed + +--*/ +{ + EFI_STATUS Status; + + // + // Install Debug Mask Protocol in Image Handle + // + Status = gBS->InstallProtocolInterface ( + &ImageHandle, + &gEfiRuntimeDebugMaskProtocolGuid, + EFI_NATIVE_INTERFACE, + &mDebugMaskProtocol + ); + return EFI_SUCCESS; +} + +EFI_STATUS +UnInstallRuntimeDebugMaskProtocol ( + IN EFI_HANDLE ImageHandle + ) +/*++ + +Routine Description: + + Uninstall Runtime debug mask protocol on an image handle. + +Arguments: + + ImageHandle - Image handle which debug mask protocol will uninstall on + +Returns: + + EFI_INVALID_PARAMETER - Invalid image handle + EFI_SUCCESS - Debug mask protocol successfully uninstalled + +--*/ +{ + EFI_STATUS Status; + + if (ImageHandle == NULL) { + return EFI_INVALID_PARAMETER; + } + + // + // Remove Protocol from ImageHandle + // + Status = gBS->UninstallProtocolInterface ( + ImageHandle, + &gEfiDebugMaskProtocolGuid, + &mDebugMaskProtocol + ); + if (EFI_ERROR (Status)) { + return Status; + } + return EFI_SUCCESS; +} + +VOID +EFIAPI +InitializeSmmStatusCode ( + IN EFI_EVENT Event, + IN VOID *Context + ) +/*++ + +Routine Description: + + Initialize the Smm Status code point + +Arguments: + + Event The Event that is being processed + Context Event Context + +Returns: + + None + +--*/ +{ + EFI_STATUS Status; + + Status = gBS->LocateProtocol (&gEfiSmmStatusCodeProtocolGuid, NULL, (VOID **) &mSmmStatusCode); + if (EFI_ERROR (Status)) { + mSmmStatusCode = NULL; + } else { + gBS->CloseEvent (mSmmStatusCodeEvent); + } +} + +EFI_STATUS +SmmStatusCodeReport ( + IN EFI_STATUS_CODE_TYPE Type, + IN EFI_STATUS_CODE_VALUE Value, + IN UINT32 Instance, + IN EFI_GUID *CallerId OPTIONAL, + IN EFI_STATUS_CODE_DATA *Data OPTIONAL + ) +{ + if (mSmmStatusCode != NULL) { + (mSmmStatusCode->ReportStatusCode) (mSmmStatusCode, Type, Value, Instance, CallerId, Data); + } + return EFI_SUCCESS; +} + +/** + Locate he report status code service. + + @return EFI_REPORT_STATUS_CODE function point to + ReportStatusCode. +**/ +EFI_REPORT_STATUS_CODE +InternalGetReportStatusCode ( + VOID + ) +{ +#if (EFI_SPECIFICATION_VERSION >= 0x00020000) + EFI_STATUS_CODE_PROTOCOL *StatusCodeProtocol; + EFI_STATUS Status; +#endif + + if (mInSmm) { + return (EFI_REPORT_STATUS_CODE) SmmStatusCodeReport; +#if (EFI_SPECIFICATION_VERSION >= 0x00020000) + } else if (!mHaveExitedBootServices) { + // + // Check gBS just in case. ReportStatusCode is called before gBS is initialized. + // + if (gBS != NULL) { + Status = gBS->LocateProtocol (&gEfiStatusCodeRuntimeProtocolGuid, NULL, (VOID**)&StatusCodeProtocol); + if (!EFI_ERROR (Status) && StatusCodeProtocol != NULL) { + return StatusCodeProtocol->ReportStatusCode; + } + } + } +#elif (TIANO_RELEASE_VERSION != 0) + } else if (mRTSmmRuntimeDxeReportStatusCodeLib != NULL) { + return mRTSmmRuntimeDxeReportStatusCodeLib->ReportStatusCode; + } +#endif + + return NULL; +} + + +/** + Fixup internal report status code protocol interface. + + @param[in] Event The Event that is being processed + @param[in] Context Event Context +**/ +VOID +EFIAPI +ReportStatusCodeLibVirtualAddressChange ( + IN EFI_EVENT Event, + IN VOID *Context + ) +{ + mRTSmmRuntimeDxeReportStatusCodeLib->ConvertPointer (0, (VOID **) &gDebugMaskInterface->GetDebugMask); + mRTSmmRuntimeDxeReportStatusCodeLib->ConvertPointer (0, (VOID **) &gDebugMaskInterface); + if (NULL != mReportStatusCode) { + mRTSmmRuntimeDxeReportStatusCodeLib->ConvertPointer (0, (VOID **) &mReportStatusCode); + } + mRTSmmRuntimeDxeReportStatusCodeLib->ConvertPointer (0, (VOID **) &mStatusCodeData); + mRTSmmRuntimeDxeReportStatusCodeLib->ConvertPointer (0, (VOID **) &mRTSmmRuntimeDxeReportStatusCodeLib); +} + +/** + Update the In Runtime Indicator. + + @param[in] Event The Event that is being processed + @param[in] Context Event Context +**/ +VOID +EFIAPI +ReportStatusCodeLibExitBootServices ( + IN EFI_EVENT Event, + IN VOID *Context + ) +{ + if (!mDebugMaskInitialized) { + InitializeDebugMask (); + } + + if (mReportStatusCode == NULL) { + mReportStatusCode = InternalGetReportStatusCode (); + } + mHaveExitedBootServices = TRUE; +} + +/** + Intialize Report Status Code Lib. + + @param[in] ImageHandle The firmware allocated handle for the EFI image. + @param[in] SystemTable A pointer to the EFI System Table. + + @return EFI_STATUS always returns EFI_SUCCESS. +**/ +EFI_STATUS +EFIAPI +ReportStatusCodeLibConstruct ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + VOID *SmmStatusCodeRegistration; + + // + // SMM driver depends on the SMM BASE protocol. + // the SMM driver must be success to locate protocol. + // + Status = gBS->LocateProtocol (&gEfiSmmBaseProtocolGuid, NULL, (VOID **) &mSmmBase); + if (!EFI_ERROR (Status)) { + mSmmBase->InSmm (mSmmBase, &mInSmm); + if (mInSmm) { + Status = mSmmBase->SmmAllocatePool ( + mSmmBase, + EfiRuntimeServicesData, + sizeof (EFI_STATUS_CODE_DATA) + EFI_STATUS_CODE_DATA_MAX_SIZE, + (VOID **) &mStatusCodeData + ); + ASSERT_EFI_ERROR (Status); + Status = gBS->LocateProtocol (&gEfiSmmStatusCodeProtocolGuid, NULL, (VOID **) &mSmmStatusCode); + if (EFI_ERROR (Status)) { + mSmmStatusCode = NULL; + // + // Create the event + // + Status = gBS->CreateEvent ( + EFI_EVENT_NOTIFY_SIGNAL, + TPL_CALLBACK, + InitializeSmmStatusCode, + NULL, + &mSmmStatusCodeEvent + ); + ASSERT_EFI_ERROR (Status); + // + // Register for protocol notifactions on this event + // NOTE: Because this protocol will be installed in SMM, it is safety to + // register ProtocolNotify here. This event will be triggered in SMM later. + // + Status = gBS->RegisterProtocolNotify ( + &gEfiSmmStatusCodeProtocolGuid, + mSmmStatusCodeEvent, + &SmmStatusCodeRegistration + ); + ASSERT_EFI_ERROR (Status); + } + Status = InstallSmmDebugMaskProtocol (ImageHandle); + return EFI_SUCCESS; + } + } + + Status = InstallRuntimeDebugMaskProtocol (ImageHandle); + + // + // Library should not use the gRT directly, since it + // may be converted by other library instance. + // + mRTSmmRuntimeDxeReportStatusCodeLib = gRT; + mInSmm = FALSE; + + (gBS->AllocatePool) (EfiRuntimeServicesData, sizeof (EFI_STATUS_CODE_DATA) + EFI_STATUS_CODE_DATA_MAX_SIZE, (VOID **)&mStatusCodeData); + ASSERT (NULL != mStatusCodeData); + // + // Cache the report status code service + // + mReportStatusCode = InternalGetReportStatusCode (); + + // + // Register the call back of virtual address change + // + Status = gBS->CreateEvent ( + EFI_EVENT_SIGNAL_VIRTUAL_ADDRESS_CHANGE, + TPL_NOTIFY, + ReportStatusCodeLibVirtualAddressChange, + NULL, + &mVirtualAddressChangeEvent + ); + ASSERT_EFI_ERROR (Status); + + + // + // Register the call back of exit boot services + // + Status = gBS->CreateEvent ( + EFI_EVENT_SIGNAL_EXIT_BOOT_SERVICES, + TPL_NOTIFY, + ReportStatusCodeLibExitBootServices, + NULL, + &mExitBootServicesEvent + ); + ASSERT_EFI_ERROR (Status); + + return Status; +} + +/** + Desctructor of library will close events. + + @param ImageHandle callder module's image handle + @param SystemTable pointer to EFI system table. + @return the status of close event. +**/ +EFI_STATUS +EFIAPI +ReportStatusCodeLibDestruct ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + + if (!mInSmm) { + // + // Close SetVirtualAddressMap () notify function + // + ASSERT (gBS != NULL); + Status = gBS->CloseEvent (mVirtualAddressChangeEvent); + ASSERT_EFI_ERROR (Status); + Status = gBS->CloseEvent (mExitBootServicesEvent); + ASSERT_EFI_ERROR (Status); + + (gBS->FreePool) (mStatusCodeData); + UnInstallRuntimeDebugMaskProtocol (ImageHandle); + } else { + if (mSmmStatusCodeEvent != NULL) { + Status = gBS->CloseEvent (mSmmStatusCodeEvent); + ASSERT_EFI_ERROR (Status); + } + mSmmBase->SmmFreePool (mSmmBase, mStatusCodeData); + UnInstallSmmDebugMaskProtocol (ImageHandle); + } + + return EFI_SUCCESS; +} + +/** + Reports a status code with full parameters. + + The function reports a status code. If ExtendedData is NULL and ExtendedDataSize + is 0, then an extended data buffer is not reported. If ExtendedData is not + NULL and ExtendedDataSize is not 0, then an extended data buffer is allocated. + ExtendedData is assumed not have the standard status code header, so this function + is responsible for allocating a buffer large enough for the standard header and + the extended data passed into this function. The standard header is filled in + with a GUID specified by ExtendedDataGuid. If ExtendedDataGuid is NULL, then a + GUID of gEfiStatusCodeSpecificDatauid is used. The status code is reported with + an instance specified by Instance and a caller ID specified by CallerId. If + CallerId is NULL, then a caller ID of gEfiCallerIdGuid is used. + + ReportStatusCodeEx()must actively prevent recursion. If ReportStatusCodeEx() + is called while processing another any other Report Status Code Library function, + then ReportStatusCodeEx() must return EFI_DEVICE_ERROR immediately. + + If ExtendedData is NULL and ExtendedDataSize is not zero, then ASSERT(). + If ExtendedData is not NULL and ExtendedDataSize is zero, then ASSERT(). + + @param Type Status code type. + @param Value Status code value. + @param Instance Status code instance number. + @param CallerId Pointer to a GUID that identifies the caller of this + function. If this parameter is NULL, then a caller + ID of gEfiCallerIdGuid is used. + @param ExtendedDataGuid Pointer to the GUID for the extended data buffer. + If this parameter is NULL, then a the status code + standard header is filled in with + gEfiStatusCodeSpecificDataGuid. + @param ExtendedData Pointer to the extended data buffer. This is an + optional parameter that may be NULL. + @param ExtendedDataSize The size, in bytes, of the extended data buffer. + + @retval EFI_SUCCESS The status code was reported. + @retval EFI_OUT_OF_RESOURCES There were not enough resources to allocate + the extended data section if it was specified. + @retval EFI_UNSUPPORTED Report status code is not supported + +**/ +EFI_STATUS +EFIAPI +InternalReportStatusCodeEx ( + IN EFI_STATUS_CODE_TYPE Type, + IN EFI_STATUS_CODE_VALUE Value, + IN UINT32 Instance, + IN CONST EFI_GUID *CallerId OPTIONAL, + IN CONST EFI_GUID *ExtendedDataGuid OPTIONAL, + IN CONST VOID *ExtendedData OPTIONAL, + IN UINTN ExtendedDataSize + ) +{ + ASSERT (!((ExtendedData == NULL) && (ExtendedDataSize != 0))); + ASSERT (!((ExtendedData != NULL) && (ExtendedDataSize == 0))); + + if (ExtendedDataSize > EFI_STATUS_CODE_DATA_MAX_SIZE) { + return EFI_OUT_OF_RESOURCES; + } + + // + // Fill in the extended data header + // + mStatusCodeData->HeaderSize = sizeof (EFI_STATUS_CODE_DATA); + mStatusCodeData->Size = (UINT16)ExtendedDataSize; + if (ExtendedDataGuid == NULL) { + ExtendedDataGuid = &gEfiStatusCodeSpecificDataGuid; + } + CopyGuid (&mStatusCodeData->Type, ExtendedDataGuid); + + // + // Fill in the extended data buffer + // + CopyMem (mStatusCodeData + 1, ExtendedData, ExtendedDataSize); + + // + // Report the status code + // + if (CallerId == NULL) { + CallerId = &gEfiCallerIdGuid; + } + return InternalReportStatusCode (Type, Value, Instance, CallerId, mStatusCodeData); +}
\ No newline at end of file |