/** @file | |
Shell application to dump SMI handler profile information. | |
Copyright (c) 2017, Intel Corporation. All rights reserved.<BR> | |
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. | |
**/ | |
#include <PiDxe.h> | |
#include <Library/BaseLib.h> | |
#include <Library/BaseMemoryLib.h> | |
#include <Library/MemoryAllocationLib.h> | |
#include <Library/UefiBootServicesTableLib.h> | |
#include <Library/UefiRuntimeServicesTableLib.h> | |
#include <Library/DebugLib.h> | |
#include <Library/PrintLib.h> | |
#include <Library/UefiLib.h> | |
#include <Library/DevicePathLib.h> | |
#include <Library/PeCoffGetEntryPointLib.h> | |
#include <Library/DxeServicesLib.h> | |
#include <Protocol/SmmCommunication.h> | |
#include <Guid/PiSmmCommunicationRegionTable.h> | |
#include <Guid/SmiHandlerProfile.h> | |
#define PROFILE_NAME_STRING_LENGTH 64 | |
CHAR8 mNameString[PROFILE_NAME_STRING_LENGTH + 1]; | |
VOID *mSmiHandlerProfileDatabase; | |
UINTN mSmiHandlerProfileDatabaseSize; | |
/** | |
This function dump raw data. | |
@param Data raw data | |
@param Size raw data size | |
**/ | |
VOID | |
InternalDumpData ( | |
IN UINT8 *Data, | |
IN UINTN Size | |
) | |
{ | |
UINTN Index; | |
for (Index = 0; Index < Size; Index++) { | |
Print (L"%02x", (UINTN)Data[Index]); | |
if ((Index + 1) != Size) { | |
Print (L" "); | |
} | |
} | |
} | |
/** | |
Get SMI handler profile database. | |
**/ | |
VOID | |
GetSmiHandlerProfileDatabase( | |
VOID | |
) | |
{ | |
EFI_STATUS Status; | |
UINTN CommSize; | |
UINT8 *CommBuffer; | |
EFI_SMM_COMMUNICATE_HEADER *CommHeader; | |
SMI_HANDLER_PROFILE_PARAMETER_GET_INFO *CommGetInfo; | |
SMI_HANDLER_PROFILE_PARAMETER_GET_DATA_BY_OFFSET *CommGetData; | |
EFI_SMM_COMMUNICATION_PROTOCOL *SmmCommunication; | |
UINTN MinimalSizeNeeded; | |
EDKII_PI_SMM_COMMUNICATION_REGION_TABLE *PiSmmCommunicationRegionTable; | |
UINT32 Index; | |
EFI_MEMORY_DESCRIPTOR *Entry; | |
VOID *Buffer; | |
UINTN Size; | |
UINTN Offset; | |
Status = gBS->LocateProtocol(&gEfiSmmCommunicationProtocolGuid, NULL, (VOID **)&SmmCommunication); | |
if (EFI_ERROR(Status)) { | |
Print(L"SmiHandlerProfile: Locate SmmCommunication protocol - %r\n", Status); | |
return ; | |
} | |
MinimalSizeNeeded = EFI_PAGE_SIZE; | |
Status = EfiGetSystemConfigurationTable( | |
&gEdkiiPiSmmCommunicationRegionTableGuid, | |
(VOID **)&PiSmmCommunicationRegionTable | |
); | |
if (EFI_ERROR(Status)) { | |
Print(L"SmiHandlerProfile: Get PiSmmCommunicationRegionTable - %r\n", Status); | |
return ; | |
} | |
ASSERT(PiSmmCommunicationRegionTable != NULL); | |
Entry = (EFI_MEMORY_DESCRIPTOR *)(PiSmmCommunicationRegionTable + 1); | |
Size = 0; | |
for (Index = 0; Index < PiSmmCommunicationRegionTable->NumberOfEntries; Index++) { | |
if (Entry->Type == EfiConventionalMemory) { | |
Size = EFI_PAGES_TO_SIZE((UINTN)Entry->NumberOfPages); | |
if (Size >= MinimalSizeNeeded) { | |
break; | |
} | |
} | |
Entry = (EFI_MEMORY_DESCRIPTOR *)((UINT8 *)Entry + PiSmmCommunicationRegionTable->DescriptorSize); | |
} | |
ASSERT(Index < PiSmmCommunicationRegionTable->NumberOfEntries); | |
CommBuffer = (UINT8 *)(UINTN)Entry->PhysicalStart; | |
// | |
// Get Size | |
// | |
CommHeader = (EFI_SMM_COMMUNICATE_HEADER *)&CommBuffer[0]; | |
CopyMem(&CommHeader->HeaderGuid, &gSmiHandlerProfileGuid, sizeof(gSmiHandlerProfileGuid)); | |
CommHeader->MessageLength = sizeof(SMI_HANDLER_PROFILE_PARAMETER_GET_INFO); | |
CommGetInfo = (SMI_HANDLER_PROFILE_PARAMETER_GET_INFO *)&CommBuffer[OFFSET_OF(EFI_SMM_COMMUNICATE_HEADER, Data)]; | |
CommGetInfo->Header.Command = SMI_HANDLER_PROFILE_COMMAND_GET_INFO; | |
CommGetInfo->Header.DataLength = sizeof(*CommGetInfo); | |
CommGetInfo->Header.ReturnStatus = (UINT64)-1; | |
CommGetInfo->DataSize = 0; | |
CommSize = sizeof(EFI_GUID) + sizeof(UINTN) + CommHeader->MessageLength; | |
Status = SmmCommunication->Communicate(SmmCommunication, CommBuffer, &CommSize); | |
if (EFI_ERROR(Status)) { | |
Print(L"SmiHandlerProfile: SmmCommunication - %r\n", Status); | |
return ; | |
} | |
if (CommGetInfo->Header.ReturnStatus != 0) { | |
Print(L"SmiHandlerProfile: GetInfo - 0x%0x\n", CommGetInfo->Header.ReturnStatus); | |
return ; | |
} | |
mSmiHandlerProfileDatabaseSize = (UINTN)CommGetInfo->DataSize; | |
// | |
// Get Data | |
// | |
mSmiHandlerProfileDatabase = AllocateZeroPool(mSmiHandlerProfileDatabaseSize); | |
if (mSmiHandlerProfileDatabase == NULL) { | |
Status = EFI_OUT_OF_RESOURCES; | |
Print(L"SmiHandlerProfile: AllocateZeroPool (0x%x) for dump buffer - %r\n", mSmiHandlerProfileDatabaseSize, Status); | |
return ; | |
} | |
CommHeader = (EFI_SMM_COMMUNICATE_HEADER *)&CommBuffer[0]; | |
CopyMem(&CommHeader->HeaderGuid, &gSmiHandlerProfileGuid, sizeof(gSmiHandlerProfileGuid)); | |
CommHeader->MessageLength = sizeof(SMI_HANDLER_PROFILE_PARAMETER_GET_DATA_BY_OFFSET); | |
CommGetData = (SMI_HANDLER_PROFILE_PARAMETER_GET_DATA_BY_OFFSET *)&CommBuffer[OFFSET_OF(EFI_SMM_COMMUNICATE_HEADER, Data)]; | |
CommGetData->Header.Command = SMI_HANDLER_PROFILE_COMMAND_GET_DATA_BY_OFFSET; | |
CommGetData->Header.DataLength = sizeof(*CommGetData); | |
CommGetData->Header.ReturnStatus = (UINT64)-1; | |
CommSize = sizeof(EFI_GUID) + sizeof(UINTN) + CommHeader->MessageLength; | |
Buffer = (UINT8 *)CommHeader + CommSize; | |
Size -= CommSize; | |
CommGetData->DataBuffer = (PHYSICAL_ADDRESS)(UINTN)Buffer; | |
CommGetData->DataOffset = 0; | |
while (CommGetData->DataOffset < mSmiHandlerProfileDatabaseSize) { | |
Offset = (UINTN)CommGetData->DataOffset; | |
if (Size <= (mSmiHandlerProfileDatabaseSize - CommGetData->DataOffset)) { | |
CommGetData->DataSize = (UINT64)Size; | |
} else { | |
CommGetData->DataSize = (UINT64)(mSmiHandlerProfileDatabaseSize - CommGetData->DataOffset); | |
} | |
Status = SmmCommunication->Communicate(SmmCommunication, CommBuffer, &CommSize); | |
ASSERT_EFI_ERROR(Status); | |
if (CommGetData->Header.ReturnStatus != 0) { | |
FreePool(mSmiHandlerProfileDatabase); | |
mSmiHandlerProfileDatabase = NULL; | |
Print(L"SmiHandlerProfile: GetData - 0x%x\n", CommGetData->Header.ReturnStatus); | |
return ; | |
} | |
CopyMem((UINT8 *)mSmiHandlerProfileDatabase + Offset, (VOID *)(UINTN)CommGetData->DataBuffer, (UINTN)CommGetData->DataSize); | |
} | |
DEBUG ((DEBUG_INFO, "SmiHandlerProfileSize - 0x%x\n", mSmiHandlerProfileDatabaseSize)); | |
return ; | |
} | |
/** | |
Get the file name portion of the Pdb File Name. | |
The portion of the Pdb File Name between the last backslash and | |
either a following period or the end of the string is copied into | |
AsciiBuffer. The name is truncated, if necessary, to ensure that | |
AsciiBuffer is not overrun. | |
@param[in] PdbFileName Pdb file name. | |
@param[out] AsciiBuffer The resultant Ascii File Name. | |
**/ | |
VOID | |
GetShortPdbFileName ( | |
IN CHAR8 *PdbFileName, | |
OUT CHAR8 *AsciiBuffer | |
) | |
{ | |
UINTN IndexPdb; // Current work location within a Pdb string. | |
UINTN IndexBuffer; // Current work location within a Buffer string. | |
UINTN StartIndex; | |
UINTN EndIndex; | |
ZeroMem (AsciiBuffer, PROFILE_NAME_STRING_LENGTH + 1); | |
if (PdbFileName == NULL) { | |
AsciiStrnCpyS (AsciiBuffer, PROFILE_NAME_STRING_LENGTH + 1, " ", 1); | |
} else { | |
StartIndex = 0; | |
for (EndIndex = 0; PdbFileName[EndIndex] != 0; EndIndex++); | |
for (IndexPdb = 0; PdbFileName[IndexPdb] != 0; IndexPdb++) { | |
if ((PdbFileName[IndexPdb] == '\\') || (PdbFileName[IndexPdb] == '/')) { | |
StartIndex = IndexPdb + 1; | |
} | |
if (PdbFileName[IndexPdb] == '.') { | |
EndIndex = IndexPdb; | |
} | |
} | |
IndexBuffer = 0; | |
for (IndexPdb = StartIndex; IndexPdb < EndIndex; IndexPdb++) { | |
AsciiBuffer[IndexBuffer] = PdbFileName[IndexPdb]; | |
IndexBuffer++; | |
if (IndexBuffer >= PROFILE_NAME_STRING_LENGTH) { | |
AsciiBuffer[PROFILE_NAME_STRING_LENGTH] = 0; | |
break; | |
} | |
} | |
} | |
} | |
/** | |
Get a human readable name for an image. | |
The following methods will be tried orderly: | |
1. Image PDB | |
2. FFS UI section | |
3. Image GUID | |
@param[in] ImageStruct Point to the image structure. | |
@return The resulting Ascii name string is stored in the mNameString global array. | |
**/ | |
CHAR8 * | |
GetDriverNameString ( | |
IN SMM_CORE_IMAGE_DATABASE_STRUCTURE *ImageStruct | |
) | |
{ | |
EFI_STATUS Status; | |
CHAR16 *NameString; | |
UINTN StringSize; | |
if (ImageStruct == NULL) { | |
return "???"; | |
} | |
// | |
// Method 1: Get the name string from image PDB | |
// | |
if (ImageStruct->PdbStringOffset != 0) { | |
GetShortPdbFileName ((CHAR8 *) ((UINTN) ImageStruct + ImageStruct->PdbStringOffset), mNameString); | |
return mNameString; | |
} | |
if (!IsZeroGuid (&ImageStruct->FileGuid)) { | |
// | |
// Try to get the image's FFS UI section by image GUID | |
// | |
NameString = NULL; | |
StringSize = 0; | |
Status = GetSectionFromAnyFv ( | |
&ImageStruct->FileGuid, | |
EFI_SECTION_USER_INTERFACE, | |
0, | |
(VOID **) &NameString, | |
&StringSize | |
); | |
if (!EFI_ERROR (Status)) { | |
// | |
// Method 2: Get the name string from FFS UI section | |
// | |
if (StrLen (NameString) > PROFILE_NAME_STRING_LENGTH) { | |
NameString[PROFILE_NAME_STRING_LENGTH] = 0; | |
} | |
UnicodeStrToAsciiStrS (NameString, mNameString, sizeof (mNameString)); | |
FreePool (NameString); | |
return mNameString; | |
} | |
} | |
// | |
// Method 3: Get the name string from image GUID | |
// | |
AsciiSPrint (mNameString, sizeof (mNameString), "%g", &ImageStruct->FileGuid); | |
return mNameString; | |
} | |
/** | |
Get image structure from reference index. | |
@param ImageRef the image reference index | |
@return image structure | |
**/ | |
SMM_CORE_IMAGE_DATABASE_STRUCTURE * | |
GetImageFromRef ( | |
IN UINTN ImageRef | |
) | |
{ | |
SMM_CORE_IMAGE_DATABASE_STRUCTURE *ImageStruct; | |
ImageStruct = (VOID *)mSmiHandlerProfileDatabase; | |
while ((UINTN)ImageStruct < (UINTN)mSmiHandlerProfileDatabase + mSmiHandlerProfileDatabaseSize) { | |
if (ImageStruct->Header.Signature == SMM_CORE_IMAGE_DATABASE_SIGNATURE) { | |
if (ImageStruct->ImageRef == ImageRef) { | |
return ImageStruct; | |
} | |
} | |
ImageStruct = (VOID *)((UINTN)ImageStruct + ImageStruct->Header.Length); | |
} | |
return NULL; | |
} | |
/** | |
Dump SMM loaded image information. | |
**/ | |
VOID | |
DumpSmmLoadedImage( | |
VOID | |
) | |
{ | |
SMM_CORE_IMAGE_DATABASE_STRUCTURE *ImageStruct; | |
CHAR8 *PdbString; | |
CHAR8 *NameString; | |
ImageStruct = (VOID *)mSmiHandlerProfileDatabase; | |
while ((UINTN)ImageStruct < (UINTN)mSmiHandlerProfileDatabase + mSmiHandlerProfileDatabaseSize) { | |
if (ImageStruct->Header.Signature == SMM_CORE_IMAGE_DATABASE_SIGNATURE) { | |
NameString = GetDriverNameString (ImageStruct); | |
Print(L" <Image Name=\"%a\"", NameString); | |
Print(L" Base=\"0x%lx\" Size=\"0x%lx\"", ImageStruct->ImageBase, ImageStruct->ImageSize); | |
if (ImageStruct->EntryPoint != 0) { | |
Print(L" EntryPoint=\"0x%lx\"", ImageStruct->EntryPoint); | |
} | |
Print(L" FvFile=\"%g\"", &ImageStruct->FileGuid); | |
Print(L" RefId=\"0x%x\"", ImageStruct->ImageRef); | |
Print(L">\n"); | |
if (ImageStruct->PdbStringOffset != 0) { | |
PdbString = (CHAR8 *)((UINTN)ImageStruct + ImageStruct->PdbStringOffset); | |
Print(L" <Pdb>%a</Pdb>\n", PdbString); | |
} | |
Print(L" </Image>\n"); | |
} | |
ImageStruct = (VOID *)((UINTN)ImageStruct + ImageStruct->Header.Length); | |
} | |
return; | |
} | |
CHAR8 *mSxTypeString[] = { | |
"SxS0", | |
"SxS1", | |
"SxS2", | |
"SxS3", | |
"SxS4", | |
"SxS5", | |
}; | |
/** | |
Convert SxType to a string. | |
@param Type SxType | |
@return SxType string | |
**/ | |
CHAR8 * | |
SxTypeToString ( | |
IN EFI_SLEEP_TYPE Type | |
) | |
{ | |
if (Type >= 0 && Type <= ARRAY_SIZE(mSxTypeString)) { | |
return mSxTypeString[Type]; | |
} else { | |
AsciiSPrint (mNameString, sizeof(mNameString), "0x%x", Type); | |
return mNameString; | |
} | |
} | |
CHAR8 *mSxPhaseString[] = { | |
"SxEntry", | |
"SxExit", | |
}; | |
/** | |
Convert SxPhase to a string. | |
@param Phase SxPhase | |
@return SxPhase string | |
**/ | |
CHAR8 * | |
SxPhaseToString ( | |
IN EFI_SLEEP_PHASE Phase | |
) | |
{ | |
if (Phase >= 0 && Phase <= ARRAY_SIZE(mSxPhaseString)) { | |
return mSxPhaseString[Phase]; | |
} else { | |
AsciiSPrint (mNameString, sizeof(mNameString), "0x%x", Phase); | |
return mNameString; | |
} | |
} | |
CHAR8 *mPowerButtonPhaseString[] = { | |
"PowerButtonEntry", | |
"PowerButtonExit", | |
}; | |
/** | |
Convert PowerButtonPhase to a string. | |
@param Phase PowerButtonPhase | |
@return PowerButtonPhase string | |
**/ | |
CHAR8 * | |
PowerButtonPhaseToString ( | |
IN EFI_POWER_BUTTON_PHASE Phase | |
) | |
{ | |
if (Phase >= 0 && Phase <= ARRAY_SIZE(mPowerButtonPhaseString)) { | |
return mPowerButtonPhaseString[Phase]; | |
} else { | |
AsciiSPrint (mNameString, sizeof(mNameString), "0x%x", Phase); | |
return mNameString; | |
} | |
} | |
CHAR8 *mStandbyButtonPhaseString[] = { | |
"StandbyButtonEntry", | |
"StandbyButtonExit", | |
}; | |
/** | |
Convert StandbyButtonPhase to a string. | |
@param Phase StandbyButtonPhase | |
@return StandbyButtonPhase string | |
**/ | |
CHAR8 * | |
StandbyButtonPhaseToString ( | |
IN EFI_STANDBY_BUTTON_PHASE Phase | |
) | |
{ | |
if (Phase >= 0 && Phase <= ARRAY_SIZE(mStandbyButtonPhaseString)) { | |
return mStandbyButtonPhaseString[Phase]; | |
} else { | |
AsciiSPrint (mNameString, sizeof(mNameString), "0x%x", Phase); | |
return mNameString; | |
} | |
} | |
CHAR8 *mIoTrapTypeString[] = { | |
"WriteTrap", | |
"ReadTrap", | |
"ReadWriteTrap", | |
}; | |
/** | |
Convert IoTrapType to a string. | |
@param Type IoTrapType | |
@return IoTrapType string | |
**/ | |
CHAR8 * | |
IoTrapTypeToString ( | |
IN EFI_SMM_IO_TRAP_DISPATCH_TYPE Type | |
) | |
{ | |
if (Type >= 0 && Type <= ARRAY_SIZE(mIoTrapTypeString)) { | |
return mIoTrapTypeString[Type]; | |
} else { | |
AsciiSPrint (mNameString, sizeof(mNameString), "0x%x", Type); | |
return mNameString; | |
} | |
} | |
CHAR8 *mUsbTypeString[] = { | |
"UsbLegacy", | |
"UsbWake", | |
}; | |
/** | |
Convert UsbType to a string. | |
@param Type UsbType | |
@return UsbType string | |
**/ | |
CHAR8 * | |
UsbTypeToString ( | |
IN EFI_USB_SMI_TYPE Type | |
) | |
{ | |
if (Type >= 0 && Type <= ARRAY_SIZE(mUsbTypeString)) { | |
return mUsbTypeString[Type]; | |
} else { | |
AsciiSPrint (mNameString, sizeof(mNameString), "0x%x", Type); | |
return mNameString; | |
} | |
} | |
/** | |
Dump SMI child context. | |
@param HandlerType the handler type | |
@param Context the handler context | |
@param ContextSize the handler context size | |
**/ | |
VOID | |
DumpSmiChildContext ( | |
IN EFI_GUID *HandlerType, | |
IN VOID *Context, | |
IN UINTN ContextSize | |
) | |
{ | |
CHAR16 *Str; | |
if (CompareGuid (HandlerType, &gEfiSmmSwDispatch2ProtocolGuid)) { | |
Print(L" SwSmi=\"0x%lx\"", ((SMI_HANDLER_PROFILE_SW_REGISTER_CONTEXT *)Context)->SwSmiInputValue); | |
} else if (CompareGuid (HandlerType, &gEfiSmmSxDispatch2ProtocolGuid)) { | |
Print(L" SxType=\"%a\"", SxTypeToString(((EFI_SMM_SX_REGISTER_CONTEXT *)Context)->Type)); | |
Print(L" SxPhase=\"%a\"", SxPhaseToString(((EFI_SMM_SX_REGISTER_CONTEXT *)Context)->Phase)); | |
} else if (CompareGuid (HandlerType, &gEfiSmmPowerButtonDispatch2ProtocolGuid)) { | |
Print(L" PowerButtonPhase=\"%a\"", PowerButtonPhaseToString(((EFI_SMM_POWER_BUTTON_REGISTER_CONTEXT *)Context)->Phase)); | |
} else if (CompareGuid (HandlerType, &gEfiSmmStandbyButtonDispatch2ProtocolGuid)) { | |
Print(L" StandbyButtonPhase=\"%a\"", StandbyButtonPhaseToString(((EFI_SMM_STANDBY_BUTTON_REGISTER_CONTEXT *)Context)->Phase)); | |
} else if (CompareGuid (HandlerType, &gEfiSmmPeriodicTimerDispatch2ProtocolGuid)) { | |
Print(L" PeriodicTimerPeriod=\"%ld\"", ((EFI_SMM_PERIODIC_TIMER_REGISTER_CONTEXT *)Context)->Period); | |
Print(L" PeriodicTimerSmiTickInterval=\"%ld\"", ((EFI_SMM_PERIODIC_TIMER_REGISTER_CONTEXT *)Context)->SmiTickInterval); | |
} else if (CompareGuid (HandlerType, &gEfiSmmGpiDispatch2ProtocolGuid)) { | |
Print(L" GpiNum=\"0x%lx\"", ((EFI_SMM_GPI_REGISTER_CONTEXT *)Context)->GpiNum); | |
} else if (CompareGuid (HandlerType, &gEfiSmmIoTrapDispatch2ProtocolGuid)) { | |
Print(L" IoTrapAddress=\"0x%x\"", ((EFI_SMM_IO_TRAP_REGISTER_CONTEXT *)Context)->Address); | |
Print(L" IoTrapLength=\"0x%x\"", ((EFI_SMM_IO_TRAP_REGISTER_CONTEXT *)Context)->Length); | |
Print(L" IoTrapType=\"%a\"", IoTrapTypeToString(((EFI_SMM_IO_TRAP_REGISTER_CONTEXT *)Context)->Type)); | |
} else if (CompareGuid (HandlerType, &gEfiSmmUsbDispatch2ProtocolGuid)) { | |
Print(L" UsbType=\"0x%x\"", UsbTypeToString(((SMI_HANDLER_PROFILE_USB_REGISTER_CONTEXT *)Context)->Type)); | |
Str = ConvertDevicePathToText((EFI_DEVICE_PATH_PROTOCOL *)(((SMI_HANDLER_PROFILE_USB_REGISTER_CONTEXT *)Context) + 1), TRUE, TRUE); | |
Print(L" UsbDevicePath=\"%s\"", Str); | |
if (Str != NULL) { | |
FreePool (Str); | |
} | |
} else { | |
Print(L" Context=\""); | |
InternalDumpData (Context, ContextSize); | |
Print(L"\""); | |
} | |
} | |
/** | |
Dump SMI handler in HandlerCategory. | |
@param HandlerCategory SMI handler category | |
**/ | |
VOID | |
DumpSmiHandler( | |
IN UINT32 HandlerCategory | |
) | |
{ | |
SMM_CORE_SMI_DATABASE_STRUCTURE *SmiStruct; | |
SMM_CORE_SMI_HANDLER_STRUCTURE *SmiHandlerStruct; | |
UINTN Index; | |
SMM_CORE_IMAGE_DATABASE_STRUCTURE *ImageStruct; | |
CHAR8 *NameString; | |
SmiStruct = (VOID *)mSmiHandlerProfileDatabase; | |
while ((UINTN)SmiStruct < (UINTN)mSmiHandlerProfileDatabase + mSmiHandlerProfileDatabaseSize) { | |
if ((SmiStruct->Header.Signature == SMM_CORE_SMI_DATABASE_SIGNATURE) && (SmiStruct->HandlerCategory == HandlerCategory)) { | |
SmiHandlerStruct = (VOID *)(SmiStruct + 1); | |
Print(L" <SmiEntry"); | |
if (!IsZeroGuid (&SmiStruct->HandlerType)) { | |
Print(L" HandlerType=\"%g\"", &SmiStruct->HandlerType); | |
} | |
Print(L">\n"); | |
for (Index = 0; Index < SmiStruct->HandlerCount; Index++) { | |
Print(L" <SmiHandler"); | |
if (SmiHandlerStruct->ContextBufferSize != 0) { | |
DumpSmiChildContext (&SmiStruct->HandlerType, (UINT8 *)SmiHandlerStruct + SmiHandlerStruct->ContextBufferOffset, SmiHandlerStruct->ContextBufferSize); | |
} | |
Print(L">\n"); | |
ImageStruct = GetImageFromRef((UINTN)SmiHandlerStruct->ImageRef); | |
NameString = GetDriverNameString (ImageStruct); | |
Print(L" <Module RefId=\"0x%x\" Name=\"%a\">\n", SmiHandlerStruct->ImageRef, NameString); | |
if ((ImageStruct != NULL) && (ImageStruct->PdbStringOffset != 0)) { | |
Print(L" <Pdb>%a</Pdb>\n", (UINT8 *)ImageStruct + ImageStruct->PdbStringOffset); | |
} | |
Print(L" </Module>\n"); | |
Print(L" <Handler Address=\"0x%lx\">\n", SmiHandlerStruct->Handler); | |
if (ImageStruct != NULL) { | |
Print(L" <RVA>0x%x</RVA>\n", (UINTN) (SmiHandlerStruct->Handler - ImageStruct->ImageBase)); | |
} | |
Print(L" </Handler>\n", SmiHandlerStruct->Handler); | |
Print(L" <Caller Address=\"0x%lx\">\n", SmiHandlerStruct->CallerAddr); | |
if (ImageStruct != NULL) { | |
Print(L" <RVA>0x%x</RVA>\n", (UINTN) (SmiHandlerStruct->CallerAddr - ImageStruct->ImageBase)); | |
} | |
Print(L" </Caller>\n", SmiHandlerStruct->Handler); | |
SmiHandlerStruct = (VOID *)((UINTN)SmiHandlerStruct + SmiHandlerStruct->Length); | |
Print(L" </SmiHandler>\n"); | |
} | |
Print(L" </SmiEntry>\n"); | |
} | |
SmiStruct = (VOID *)((UINTN)SmiStruct + SmiStruct->Header.Length); | |
} | |
return; | |
} | |
/** | |
The Entry Point for SMI handler profile info application. | |
@param ImageHandle The firmware allocated handle for the EFI image. | |
@param SystemTable A pointer to the EFI System Table. | |
@retval EFI_SUCCESS The entry point is executed successfully. | |
@retval Other Some error occurred when executing this entry point. | |
**/ | |
EFI_STATUS | |
EFIAPI | |
SmiHandlerProfileInfoEntrypoint ( | |
IN EFI_HANDLE ImageHandle, | |
IN EFI_SYSTEM_TABLE *SystemTable | |
) | |
{ | |
GetSmiHandlerProfileDatabase(); | |
if (mSmiHandlerProfileDatabase == NULL) { | |
return EFI_SUCCESS; | |
} | |
// | |
// Dump all image | |
// | |
Print(L"<?xml version=\"1.0\" encoding=\"utf-8\"?>\n"); | |
Print(L"<SmiHandlerProfile>\n"); | |
Print(L"<ImageDatabase>\n"); | |
Print(L" <!-- SMM image loaded -->\n"); | |
DumpSmmLoadedImage(); | |
Print(L"</ImageDatabase>\n\n"); | |
// | |
// Dump SMI Handler | |
// | |
Print(L"<SmiHandlerDatabase>\n"); | |
Print(L" <!-- SMI Handler registered -->\n\n"); | |
Print(L" <SmiHandlerCategory Name=\"RootSmi\">\n"); | |
Print(L" <!-- The root SMI Handler registered by SmmCore -->\n"); | |
DumpSmiHandler(SmmCoreSmiHandlerCategoryRootHandler); | |
Print(L" </SmiHandlerCategory>\n\n"); | |
Print(L" <SmiHandlerCategory Name=\"GuidSmi\">\n"); | |
Print(L" <!-- The GUID SMI Handler registered by SmmCore -->\n"); | |
DumpSmiHandler(SmmCoreSmiHandlerCategoryGuidHandler); | |
Print(L" </SmiHandlerCategory>\n\n"); | |
Print(L" <SmiHandlerCategory Name=\"HardwareSmi\">\n"); | |
Print(L" <!-- The hardware SMI Handler registered by SmmChildDispatcher -->\n"); | |
DumpSmiHandler(SmmCoreSmiHandlerCategoryHardwareHandler); | |
Print(L" </SmiHandlerCategory>\n\n"); | |
Print(L"</SmiHandlerDatabase>\n"); | |
Print(L"</SmiHandlerProfile>\n"); | |
if (mSmiHandlerProfileDatabase != NULL) { | |
FreePool(mSmiHandlerProfileDatabase); | |
} | |
return EFI_SUCCESS; | |
} |