[edk2] [PATCH 08/12] MdeModulePkg/App: Add SmiHandlerProfile dump app.

Jiewen Yao posted 12 patches 7 years, 8 months ago
Only 9 patches received!
[edk2] [PATCH 08/12] MdeModulePkg/App: Add SmiHandlerProfile dump app.
Posted by Jiewen Yao 7 years, 8 months ago
This app uses SMM communication to get SMI handler profile
from SMM core.

Cc: Feng Tian <feng.tian@intel.com>
Cc: Star Zeng <star.zeng@intel.com>
Cc: Michael D Kinney <michael.d.kinney@intel.com>
Cc: Laszlo Ersek <lersek@redhat.com>
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Jiewen Yao <jiewen.yao@intel.com>
---
 MdeModulePkg/Application/SmiHandlerProfileInfo/SmiHandlerProfileInfo.c        | 685 ++++++++++++++++++++
 MdeModulePkg/Application/SmiHandlerProfileInfo/SmiHandlerProfileInfo.inf      |  65 ++
 MdeModulePkg/Application/SmiHandlerProfileInfo/SmiHandlerProfileInfo.uni      |  22 +
 MdeModulePkg/Application/SmiHandlerProfileInfo/SmiHandlerProfileInfoExtra.uni |  19 +
 4 files changed, 791 insertions(+)

diff --git a/MdeModulePkg/Application/SmiHandlerProfileInfo/SmiHandlerProfileInfo.c b/MdeModulePkg/Application/SmiHandlerProfileInfo/SmiHandlerProfileInfo.c
new file mode 100644
index 0000000..00cab0c
--- /dev/null
+++ b/MdeModulePkg/Application/SmiHandlerProfileInfo/SmiHandlerProfileInfo.c
@@ -0,0 +1,685 @@
+/** @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] DriverInfo Pointer to memory profile driver info.
+
+  @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->Header.Length > sizeof (SMM_CORE_IMAGE_DATABASE_STRUCTURE)) {
+    GetShortPdbFileName ((CHAR8 *) (ImageStruct + 1), 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%x\" Size=\"0x%x\"", ImageStruct->ImageBase, ImageStruct->ImageSize);
+      if (ImageStruct->EntryPoint != 0) {
+        Print(L" EntryPoint=\"0x%x\"", ImageStruct->EntryPoint);
+      }
+      Print(L" FvFile=\"%g\"", &ImageStruct->FileGuid);
+      Print(L" RefId=\"0x%x\"", ImageStruct->ImageRef);
+      Print(L">\n");
+      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
+  )
+{
+  if (CompareGuid (HandlerType, &gEfiSmmSwDispatch2ProtocolGuid)) {
+    Print(L" SwSmi=\"0x%x\"", ((EFI_SMM_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));
+    Print(L" UsbDevicePath=\"%s\"", ConvertDevicePathToText((EFI_DEVICE_PATH_PROTOCOL *)(((SMI_HANDLER_PROFILE_USB_REGISTER_CONTEXT *)Context) + 1), TRUE, TRUE));
+  } 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%x\">\n", SmiHandlerStruct->Handler);
+        if (ImageStruct != NULL) {
+          Print(L"         <RVA>0x%x</RVA>\n", SmiHandlerStruct->Handler - ImageStruct->ImageBase);
+        }
+        Print(L"      </Handler>\n", SmiHandlerStruct->Handler);
+        Print(L"      <Caller Address=\"0x%x\">\n", SmiHandlerStruct->CallerAddr);
+        if (ImageStruct != NULL) {
+          Print(L"         <RVA>0x%x</RVA>\n", 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;
+}
diff --git a/MdeModulePkg/Application/SmiHandlerProfileInfo/SmiHandlerProfileInfo.inf b/MdeModulePkg/Application/SmiHandlerProfileInfo/SmiHandlerProfileInfo.inf
new file mode 100644
index 0000000..73cc052
--- /dev/null
+++ b/MdeModulePkg/Application/SmiHandlerProfileInfo/SmiHandlerProfileInfo.inf
@@ -0,0 +1,65 @@
+## @file
+#  Shell application to dump SMI handler profile information.
+#
+# Note that if the feature is not enabled by setting PcdSmiHandlerProfilePropertyMask,
+# the application will not display 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 that 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.
+#
+##
+
+[Defines]
+  INF_VERSION                    = 0x00010005
+  BASE_NAME                      = SmiHandlerProfileInfo
+  MODULE_UNI_FILE                = SmiHandlerProfileInfo.uni
+  FILE_GUID                      = 611EA796-8DF8-4BB6-91FE-6540ED70DC66
+  MODULE_TYPE                    = UEFI_APPLICATION
+  VERSION_STRING                 = 1.0
+  ENTRY_POINT                    = SmiHandlerProfileInfoEntrypoint
+
+[Sources]
+  SmiHandlerProfileInfo.c
+
+[Packages]
+  MdePkg/MdePkg.dec
+  MdeModulePkg/MdeModulePkg.dec
+
+[LibraryClasses]
+  UefiApplicationEntryPoint
+  BaseLib
+  BaseMemoryLib
+  MemoryAllocationLib
+  DebugLib
+  UefiBootServicesTableLib
+  UefiRuntimeServicesTableLib
+  UefiLib
+  PrintLib
+  DevicePathLib
+  PeCoffGetEntryPointLib
+  DxeServicesLib
+
+[Protocols]
+  gEfiSmmCommunicationProtocolGuid             ## CONSUMES
+  gEfiSmmSwDispatch2ProtocolGuid               ## SOMETIMES_CONSUMES
+  gEfiSmmSxDispatch2ProtocolGuid               ## SOMETIMES_CONSUMES
+  gEfiSmmPowerButtonDispatch2ProtocolGuid      ## SOMETIMES_CONSUMES
+  gEfiSmmStandbyButtonDispatch2ProtocolGuid    ## SOMETIMES_CONSUMES
+  gEfiSmmPeriodicTimerDispatch2ProtocolGuid    ## SOMETIMES_CONSUMES
+  gEfiSmmGpiDispatch2ProtocolGuid              ## SOMETIMES_CONSUMES
+  gEfiSmmIoTrapDispatch2ProtocolGuid           ## SOMETIMES_CONSUMES
+  gEfiSmmUsbDispatch2ProtocolGuid              ## SOMETIMES_CONSUMES
+
+[Guids]
+  gEdkiiPiSmmCommunicationRegionTableGuid  ## CONSUMES  ## SystemTable
+  gSmiHandlerProfileGuid                   ## SOMETIMES_CONSUMES   ## GUID # SmiHandlerRegister
+
+[UserExtensions.TianoCore."ExtraFiles"]
+  SmiHandlerProfileInfoExtra.uni
+
diff --git a/MdeModulePkg/Application/SmiHandlerProfileInfo/SmiHandlerProfileInfo.uni b/MdeModulePkg/Application/SmiHandlerProfileInfo/SmiHandlerProfileInfo.uni
new file mode 100644
index 0000000..d73a1a0
--- /dev/null
+++ b/MdeModulePkg/Application/SmiHandlerProfileInfo/SmiHandlerProfileInfo.uni
@@ -0,0 +1,22 @@
+// /** @file
+// Shell application to dump SMI handler profile information.
+//
+// Note that if the feature is not enabled by setting PcdSmiHandlerProfilePropertyMask,
+// the application will not display 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.
+//
+// **/
+
+
+#string STR_MODULE_ABSTRACT             #language en-US "Shell application to dump SMI handler profile information."
+
+#string STR_MODULE_DESCRIPTION          #language en-US "Note that if the feature is not enabled by setting PcdSmiHandlerProfilePropertyMask, the application will not display SMI handler profile information."
+
diff --git a/MdeModulePkg/Application/SmiHandlerProfileInfo/SmiHandlerProfileInfoExtra.uni b/MdeModulePkg/Application/SmiHandlerProfileInfo/SmiHandlerProfileInfoExtra.uni
new file mode 100644
index 0000000..b10c71a
--- /dev/null
+++ b/MdeModulePkg/Application/SmiHandlerProfileInfo/SmiHandlerProfileInfoExtra.uni
@@ -0,0 +1,19 @@
+// /** @file
+// SmiHandlerProfileInfo Localized Strings and Content
+//
+// 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.
+//
+// **/
+
+#string STR_PROPERTIES_MODULE_NAME
+#language en-US
+"SMI Handler Profile Information Application"
+
+
-- 
2.7.4.windows.1

_______________________________________________
edk2-devel mailing list
edk2-devel@lists.01.org
https://lists.01.org/mailman/listinfo/edk2-devel