MdeModulePkg/App: Add SmiHandlerProfile dump app.
authorJiewen Yao <jiewen.yao@intel.com>
Fri, 20 Jan 2017 14:14:59 +0000 (06:14 -0800)
committerJiewen Yao <jiewen.yao@intel.com>
Wed, 22 Feb 2017 07:28:19 +0000 (15:28 +0800)
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>
Reviewed-by: Star Zeng <star.zeng@intel.com>
MdeModulePkg/Application/SmiHandlerProfileInfo/SmiHandlerProfileInfo.c [new file with mode: 0644]
MdeModulePkg/Application/SmiHandlerProfileInfo/SmiHandlerProfileInfo.inf [new file with mode: 0644]
MdeModulePkg/Application/SmiHandlerProfileInfo/SmiHandlerProfileInfo.uni [new file with mode: 0644]
MdeModulePkg/Application/SmiHandlerProfileInfo/SmiHandlerProfileInfoExtra.uni [new file with mode: 0644]

diff --git a/MdeModulePkg/Application/SmiHandlerProfileInfo/SmiHandlerProfileInfo.c b/MdeModulePkg/Application/SmiHandlerProfileInfo/SmiHandlerProfileInfo.c
new file mode 100644 (file)
index 0000000..00cab0c
--- /dev/null
@@ -0,0 +1,685 @@
+/** @file\r
+  Shell application to dump SMI handler profile information.\r
+\r
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>\r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include <PiDxe.h>\r
+#include <Library/BaseLib.h>\r
+#include <Library/BaseMemoryLib.h>\r
+#include <Library/MemoryAllocationLib.h>\r
+#include <Library/UefiBootServicesTableLib.h>\r
+#include <Library/UefiRuntimeServicesTableLib.h>\r
+#include <Library/DebugLib.h>\r
+#include <Library/PrintLib.h>\r
+#include <Library/UefiLib.h>\r
+#include <Library/DevicePathLib.h>\r
+#include <Library/PeCoffGetEntryPointLib.h>\r
+#include <Library/DxeServicesLib.h>\r
+#include <Protocol/SmmCommunication.h>\r
+#include <Guid/PiSmmCommunicationRegionTable.h>\r
+\r
+#include <Guid/SmiHandlerProfile.h>\r
+\r
+#define PROFILE_NAME_STRING_LENGTH  64\r
+CHAR8 mNameString[PROFILE_NAME_STRING_LENGTH + 1];\r
+\r
+VOID   *mSmiHandlerProfileDatabase;\r
+UINTN  mSmiHandlerProfileDatabaseSize;\r
+\r
+/**\r
+  This function dump raw data.\r
+\r
+  @param  Data  raw data\r
+  @param  Size  raw data size\r
+**/\r
+VOID\r
+InternalDumpData (\r
+  IN UINT8  *Data,\r
+  IN UINTN  Size\r
+  )\r
+{\r
+  UINTN  Index;\r
+  for (Index = 0; Index < Size; Index++) {\r
+    Print (L"%02x", (UINTN)Data[Index]);\r
+    if ((Index + 1) != Size) {\r
+      Print (L" ");\r
+    }\r
+  }\r
+}\r
+\r
+/**\r
+  Get SMI handler profile database.\r
+**/\r
+VOID\r
+GetSmiHandlerProfileDatabase(\r
+  VOID\r
+  )\r
+{\r
+  EFI_STATUS                                          Status;\r
+  UINTN                                               CommSize;\r
+  UINT8                                               *CommBuffer;\r
+  EFI_SMM_COMMUNICATE_HEADER                          *CommHeader;\r
+  SMI_HANDLER_PROFILE_PARAMETER_GET_INFO              *CommGetInfo;\r
+  SMI_HANDLER_PROFILE_PARAMETER_GET_DATA_BY_OFFSET    *CommGetData;\r
+  EFI_SMM_COMMUNICATION_PROTOCOL                      *SmmCommunication;\r
+  UINTN                                               MinimalSizeNeeded;\r
+  EDKII_PI_SMM_COMMUNICATION_REGION_TABLE             *PiSmmCommunicationRegionTable;\r
+  UINT32                                              Index;\r
+  EFI_MEMORY_DESCRIPTOR                               *Entry;\r
+  VOID                                                *Buffer;\r
+  UINTN                                               Size;\r
+  UINTN                                               Offset;\r
+\r
+  Status = gBS->LocateProtocol(&gEfiSmmCommunicationProtocolGuid, NULL, (VOID **)&SmmCommunication);\r
+  if (EFI_ERROR(Status)) {\r
+    Print(L"SmiHandlerProfile: Locate SmmCommunication protocol - %r\n", Status);\r
+    return ;\r
+  }\r
+\r
+  MinimalSizeNeeded = EFI_PAGE_SIZE;\r
+\r
+  Status = EfiGetSystemConfigurationTable(\r
+             &gEdkiiPiSmmCommunicationRegionTableGuid,\r
+             (VOID **)&PiSmmCommunicationRegionTable\r
+             );\r
+  if (EFI_ERROR(Status)) {\r
+    Print(L"SmiHandlerProfile: Get PiSmmCommunicationRegionTable - %r\n", Status);\r
+    return ;\r
+  }\r
+  ASSERT(PiSmmCommunicationRegionTable != NULL);\r
+  Entry = (EFI_MEMORY_DESCRIPTOR *)(PiSmmCommunicationRegionTable + 1);\r
+  Size = 0;\r
+  for (Index = 0; Index < PiSmmCommunicationRegionTable->NumberOfEntries; Index++) {\r
+    if (Entry->Type == EfiConventionalMemory) {\r
+      Size = EFI_PAGES_TO_SIZE((UINTN)Entry->NumberOfPages);\r
+      if (Size >= MinimalSizeNeeded) {\r
+        break;\r
+      }\r
+    }\r
+    Entry = (EFI_MEMORY_DESCRIPTOR *)((UINT8 *)Entry + PiSmmCommunicationRegionTable->DescriptorSize);\r
+  }\r
+  ASSERT(Index < PiSmmCommunicationRegionTable->NumberOfEntries);\r
+  CommBuffer = (UINT8 *)(UINTN)Entry->PhysicalStart;\r
+\r
+  //\r
+  // Get Size\r
+  //\r
+  CommHeader = (EFI_SMM_COMMUNICATE_HEADER *)&CommBuffer[0];\r
+  CopyMem(&CommHeader->HeaderGuid, &gSmiHandlerProfileGuid, sizeof(gSmiHandlerProfileGuid));\r
+  CommHeader->MessageLength = sizeof(SMI_HANDLER_PROFILE_PARAMETER_GET_INFO);\r
+\r
+  CommGetInfo = (SMI_HANDLER_PROFILE_PARAMETER_GET_INFO *)&CommBuffer[OFFSET_OF(EFI_SMM_COMMUNICATE_HEADER, Data)];\r
+  CommGetInfo->Header.Command = SMI_HANDLER_PROFILE_COMMAND_GET_INFO;\r
+  CommGetInfo->Header.DataLength = sizeof(*CommGetInfo);\r
+  CommGetInfo->Header.ReturnStatus = (UINT64)-1;\r
+  CommGetInfo->DataSize = 0;\r
+\r
+  CommSize = sizeof(EFI_GUID) + sizeof(UINTN) + CommHeader->MessageLength;\r
+  Status = SmmCommunication->Communicate(SmmCommunication, CommBuffer, &CommSize);\r
+  if (EFI_ERROR(Status)) {\r
+    Print(L"SmiHandlerProfile: SmmCommunication - %r\n", Status);\r
+    return ;\r
+  }\r
+\r
+  if (CommGetInfo->Header.ReturnStatus != 0) {\r
+    Print(L"SmiHandlerProfile: GetInfo - 0x%0x\n", CommGetInfo->Header.ReturnStatus);\r
+    return ;\r
+  }\r
+\r
+  mSmiHandlerProfileDatabaseSize = (UINTN)CommGetInfo->DataSize;\r
+\r
+  //\r
+  // Get Data\r
+  //\r
+  mSmiHandlerProfileDatabase = AllocateZeroPool(mSmiHandlerProfileDatabaseSize);\r
+  if (mSmiHandlerProfileDatabase == NULL) {\r
+    Status = EFI_OUT_OF_RESOURCES;\r
+    Print(L"SmiHandlerProfile: AllocateZeroPool (0x%x) for dump buffer - %r\n", mSmiHandlerProfileDatabaseSize, Status);\r
+    return ;\r
+  }\r
+\r
+  CommHeader = (EFI_SMM_COMMUNICATE_HEADER *)&CommBuffer[0];\r
+  CopyMem(&CommHeader->HeaderGuid, &gSmiHandlerProfileGuid, sizeof(gSmiHandlerProfileGuid));\r
+  CommHeader->MessageLength = sizeof(SMI_HANDLER_PROFILE_PARAMETER_GET_DATA_BY_OFFSET);\r
+\r
+  CommGetData = (SMI_HANDLER_PROFILE_PARAMETER_GET_DATA_BY_OFFSET *)&CommBuffer[OFFSET_OF(EFI_SMM_COMMUNICATE_HEADER, Data)];\r
+  CommGetData->Header.Command = SMI_HANDLER_PROFILE_COMMAND_GET_DATA_BY_OFFSET;\r
+  CommGetData->Header.DataLength = sizeof(*CommGetData);\r
+  CommGetData->Header.ReturnStatus = (UINT64)-1;\r
+\r
+  CommSize = sizeof(EFI_GUID) + sizeof(UINTN) + CommHeader->MessageLength;\r
+  Buffer = (UINT8 *)CommHeader + CommSize;\r
+  Size -= CommSize;\r
+\r
+  CommGetData->DataBuffer = (PHYSICAL_ADDRESS)(UINTN)Buffer;\r
+  CommGetData->DataOffset = 0;\r
+  while (CommGetData->DataOffset < mSmiHandlerProfileDatabaseSize) {\r
+    Offset = (UINTN)CommGetData->DataOffset;\r
+    if (Size <= (mSmiHandlerProfileDatabaseSize - CommGetData->DataOffset)) {\r
+      CommGetData->DataSize = (UINT64)Size;\r
+    } else {\r
+      CommGetData->DataSize = (UINT64)(mSmiHandlerProfileDatabaseSize - CommGetData->DataOffset);\r
+    }\r
+    Status = SmmCommunication->Communicate(SmmCommunication, CommBuffer, &CommSize);\r
+    ASSERT_EFI_ERROR(Status);\r
+\r
+    if (CommGetData->Header.ReturnStatus != 0) {\r
+      FreePool(mSmiHandlerProfileDatabase);\r
+      mSmiHandlerProfileDatabase = NULL;\r
+      Print(L"SmiHandlerProfile: GetData - 0x%x\n", CommGetData->Header.ReturnStatus);\r
+      return ;\r
+    }\r
+    CopyMem((UINT8 *)mSmiHandlerProfileDatabase + Offset, (VOID *)(UINTN)CommGetData->DataBuffer, (UINTN)CommGetData->DataSize);\r
+  }\r
+\r
+  DEBUG ((DEBUG_INFO, "SmiHandlerProfileSize - 0x%x\n", mSmiHandlerProfileDatabaseSize));\r
+\r
+  return ;\r
+}\r
+\r
+/**\r
+  Get the file name portion of the Pdb File Name.\r
+\r
+  The portion of the Pdb File Name between the last backslash and\r
+  either a following period or the end of the string is copied into\r
+  AsciiBuffer.  The name is truncated, if necessary, to ensure that\r
+  AsciiBuffer is not overrun.\r
+\r
+  @param[in]  PdbFileName     Pdb file name.\r
+  @param[out] AsciiBuffer     The resultant Ascii File Name.\r
+\r
+**/\r
+VOID\r
+GetShortPdbFileName (\r
+  IN  CHAR8     *PdbFileName,\r
+  OUT CHAR8     *AsciiBuffer\r
+  )\r
+{\r
+  UINTN IndexPdb;     // Current work location within a Pdb string.\r
+  UINTN IndexBuffer;  // Current work location within a Buffer string.\r
+  UINTN StartIndex;\r
+  UINTN EndIndex;\r
+\r
+  ZeroMem (AsciiBuffer, PROFILE_NAME_STRING_LENGTH + 1);\r
+\r
+  if (PdbFileName == NULL) {\r
+    AsciiStrnCpyS (AsciiBuffer, PROFILE_NAME_STRING_LENGTH + 1, " ", 1);\r
+  } else {\r
+    StartIndex = 0;\r
+    for (EndIndex = 0; PdbFileName[EndIndex] != 0; EndIndex++);\r
+    for (IndexPdb = 0; PdbFileName[IndexPdb] != 0; IndexPdb++) {\r
+      if ((PdbFileName[IndexPdb] == '\\') || (PdbFileName[IndexPdb] == '/')) {\r
+        StartIndex = IndexPdb + 1;\r
+      }\r
+\r
+      if (PdbFileName[IndexPdb] == '.') {\r
+        EndIndex = IndexPdb;\r
+      }\r
+    }\r
+\r
+    IndexBuffer = 0;\r
+    for (IndexPdb = StartIndex; IndexPdb < EndIndex; IndexPdb++) {\r
+      AsciiBuffer[IndexBuffer] = PdbFileName[IndexPdb];\r
+      IndexBuffer++;\r
+      if (IndexBuffer >= PROFILE_NAME_STRING_LENGTH) {\r
+        AsciiBuffer[PROFILE_NAME_STRING_LENGTH] = 0;\r
+        break;\r
+      }\r
+    }\r
+  }\r
+}\r
+\r
+/**\r
+  Get a human readable name for an image.\r
+  The following methods will be tried orderly:\r
+    1. Image PDB\r
+    2. FFS UI section\r
+    3. Image GUID\r
+\r
+  @param[in] DriverInfo Pointer to memory profile driver info.\r
+\r
+  @return The resulting Ascii name string is stored in the mNameString global array.\r
+\r
+**/\r
+CHAR8 *\r
+GetDriverNameString (\r
+  IN SMM_CORE_IMAGE_DATABASE_STRUCTURE  *ImageStruct\r
+  )\r
+{\r
+  EFI_STATUS                  Status;\r
+  CHAR16                      *NameString;\r
+  UINTN                       StringSize;\r
+\r
+  if (ImageStruct == NULL) {\r
+    return "???";\r
+  }\r
+\r
+  //\r
+  // Method 1: Get the name string from image PDB\r
+  //\r
+  if (ImageStruct->Header.Length > sizeof (SMM_CORE_IMAGE_DATABASE_STRUCTURE)) {\r
+    GetShortPdbFileName ((CHAR8 *) (ImageStruct + 1), mNameString);\r
+    return mNameString;\r
+  }\r
+\r
+  if (!IsZeroGuid (&ImageStruct->FileGuid)) {\r
+    //\r
+    // Try to get the image's FFS UI section by image GUID\r
+    //\r
+    NameString = NULL;\r
+    StringSize = 0;\r
+    Status = GetSectionFromAnyFv (\r
+              &ImageStruct->FileGuid,\r
+              EFI_SECTION_USER_INTERFACE,\r
+              0,\r
+              (VOID **) &NameString,\r
+              &StringSize\r
+              );\r
+    if (!EFI_ERROR (Status)) {\r
+      //\r
+      // Method 2: Get the name string from FFS UI section\r
+      //\r
+      if (StrLen (NameString) > PROFILE_NAME_STRING_LENGTH) {\r
+        NameString[PROFILE_NAME_STRING_LENGTH] = 0;\r
+      }\r
+      UnicodeStrToAsciiStrS (NameString, mNameString, sizeof (mNameString));\r
+      FreePool (NameString);\r
+      return mNameString;\r
+    }\r
+  }\r
+\r
+  //\r
+  // Method 3: Get the name string from image GUID\r
+  //\r
+  AsciiSPrint (mNameString, sizeof (mNameString), "%g", &ImageStruct->FileGuid);\r
+  return mNameString;\r
+}\r
+\r
+/**\r
+  Get image structure from reference index.\r
+\r
+  @param ImageRef   the image reference index\r
+\r
+  @return image structure\r
+**/\r
+SMM_CORE_IMAGE_DATABASE_STRUCTURE *\r
+GetImageFromRef (\r
+  IN UINTN ImageRef\r
+  )\r
+{\r
+  SMM_CORE_IMAGE_DATABASE_STRUCTURE  *ImageStruct;\r
+\r
+  ImageStruct = (VOID *)mSmiHandlerProfileDatabase;\r
+  while ((UINTN)ImageStruct < (UINTN)mSmiHandlerProfileDatabase + mSmiHandlerProfileDatabaseSize) {\r
+    if (ImageStruct->Header.Signature == SMM_CORE_IMAGE_DATABASE_SIGNATURE) {\r
+      if (ImageStruct->ImageRef == ImageRef) {\r
+        return ImageStruct;\r
+      }\r
+    }\r
+    ImageStruct = (VOID *)((UINTN)ImageStruct + ImageStruct->Header.Length);\r
+  }\r
+\r
+  return NULL;\r
+}\r
+\r
+/**\r
+  Dump SMM loaded image information.\r
+**/\r
+VOID\r
+DumpSmmLoadedImage(\r
+  VOID\r
+  )\r
+{\r
+  SMM_CORE_IMAGE_DATABASE_STRUCTURE  *ImageStruct;\r
+  CHAR8                              *PdbString;\r
+  CHAR8                              *NameString;\r
+\r
+  ImageStruct = (VOID *)mSmiHandlerProfileDatabase;\r
+  while ((UINTN)ImageStruct < (UINTN)mSmiHandlerProfileDatabase + mSmiHandlerProfileDatabaseSize) {\r
+    if (ImageStruct->Header.Signature == SMM_CORE_IMAGE_DATABASE_SIGNATURE) {\r
+      NameString = GetDriverNameString (ImageStruct);\r
+      Print(L"  <Image Name=\"%a\"", NameString);\r
+      Print(L" Base=\"0x%x\" Size=\"0x%x\"", ImageStruct->ImageBase, ImageStruct->ImageSize);\r
+      if (ImageStruct->EntryPoint != 0) {\r
+        Print(L" EntryPoint=\"0x%x\"", ImageStruct->EntryPoint);\r
+      }\r
+      Print(L" FvFile=\"%g\"", &ImageStruct->FileGuid);\r
+      Print(L" RefId=\"0x%x\"", ImageStruct->ImageRef);\r
+      Print(L">\n");\r
+      PdbString = (CHAR8 *)((UINTN)ImageStruct + ImageStruct->PdbStringOffset);\r
+      Print(L"    <Pdb>%a</Pdb>\n", PdbString);\r
+      Print(L"  </Image>\n");\r
+    }\r
+\r
+    ImageStruct = (VOID *)((UINTN)ImageStruct + ImageStruct->Header.Length);\r
+  }\r
+\r
+  return;\r
+}\r
+\r
+CHAR8 *mSxTypeString[] = {\r
+  "SxS0",\r
+  "SxS1",\r
+  "SxS2",\r
+  "SxS3",\r
+  "SxS4",\r
+  "SxS5",\r
+};\r
+\r
+/**\r
+  Convert SxType to a string.\r
+\r
+  @param Type SxType\r
+\r
+  @return SxType string\r
+**/\r
+CHAR8 *\r
+SxTypeToString (\r
+  IN EFI_SLEEP_TYPE  Type\r
+  )\r
+{\r
+  if (Type >= 0 && Type <= ARRAY_SIZE(mSxTypeString)) {\r
+    return mSxTypeString[Type];\r
+  } else {\r
+    AsciiSPrint (mNameString, sizeof(mNameString), "0x%x", Type);\r
+    return mNameString;\r
+  }\r
+}\r
+\r
+CHAR8 *mSxPhaseString[] = {\r
+  "SxEntry",\r
+  "SxExit",\r
+};\r
+\r
+/**\r
+  Convert SxPhase to a string.\r
+\r
+  @param Phase SxPhase\r
+\r
+  @return SxPhase string\r
+**/\r
+CHAR8 *\r
+SxPhaseToString (\r
+  IN EFI_SLEEP_PHASE Phase\r
+  )\r
+{\r
+  if (Phase >= 0 && Phase <= ARRAY_SIZE(mSxPhaseString)) {\r
+    return mSxPhaseString[Phase];\r
+  } else {\r
+    AsciiSPrint (mNameString, sizeof(mNameString), "0x%x", Phase);\r
+    return mNameString;\r
+  }\r
+}\r
+\r
+CHAR8 *mPowerButtonPhaseString[] = {\r
+  "PowerButtonEntry",\r
+  "PowerButtonExit",\r
+};\r
+\r
+/**\r
+  Convert PowerButtonPhase to a string.\r
+\r
+  @param Phase PowerButtonPhase\r
+\r
+  @return PowerButtonPhase string\r
+**/\r
+CHAR8 *\r
+PowerButtonPhaseToString (\r
+  IN EFI_POWER_BUTTON_PHASE  Phase\r
+  )\r
+{\r
+  if (Phase >= 0 && Phase <= ARRAY_SIZE(mPowerButtonPhaseString)) {\r
+    return mPowerButtonPhaseString[Phase];\r
+  } else {\r
+    AsciiSPrint (mNameString, sizeof(mNameString), "0x%x", Phase);\r
+    return mNameString;\r
+  }\r
+}\r
+\r
+CHAR8 *mStandbyButtonPhaseString[] = {\r
+  "StandbyButtonEntry",\r
+  "StandbyButtonExit",\r
+};\r
+\r
+/**\r
+  Convert StandbyButtonPhase to a string.\r
+\r
+  @param Phase StandbyButtonPhase\r
+\r
+  @return StandbyButtonPhase string\r
+**/\r
+CHAR8 *\r
+StandbyButtonPhaseToString (\r
+  IN EFI_STANDBY_BUTTON_PHASE  Phase\r
+  )\r
+{\r
+  if (Phase >= 0 && Phase <= ARRAY_SIZE(mStandbyButtonPhaseString)) {\r
+    return mStandbyButtonPhaseString[Phase];\r
+  } else {\r
+    AsciiSPrint (mNameString, sizeof(mNameString), "0x%x", Phase);\r
+    return mNameString;\r
+  }\r
+}\r
+\r
+CHAR8 *mIoTrapTypeString[] = {\r
+  "WriteTrap",\r
+  "ReadTrap",\r
+  "ReadWriteTrap",\r
+};\r
+\r
+/**\r
+  Convert IoTrapType to a string.\r
+\r
+  @param Type IoTrapType\r
+\r
+  @return IoTrapType string\r
+**/\r
+CHAR8 *\r
+IoTrapTypeToString (\r
+  IN EFI_SMM_IO_TRAP_DISPATCH_TYPE  Type\r
+  )\r
+{\r
+  if (Type >= 0 && Type <= ARRAY_SIZE(mIoTrapTypeString)) {\r
+    return mIoTrapTypeString[Type];\r
+  } else {\r
+    AsciiSPrint (mNameString, sizeof(mNameString), "0x%x", Type);\r
+    return mNameString;\r
+  }\r
+}\r
+\r
+CHAR8 *mUsbTypeString[] = {\r
+  "UsbLegacy",\r
+  "UsbWake",\r
+};\r
+\r
+/**\r
+  Convert UsbType to a string.\r
+\r
+  @param Type UsbType\r
+\r
+  @return UsbType string\r
+**/\r
+CHAR8 *\r
+UsbTypeToString (\r
+  IN EFI_USB_SMI_TYPE          Type\r
+  )\r
+{\r
+  if (Type >= 0 && Type <= ARRAY_SIZE(mUsbTypeString)) {\r
+    return mUsbTypeString[Type];\r
+  } else {\r
+    AsciiSPrint (mNameString, sizeof(mNameString), "0x%x", Type);\r
+    return mNameString;\r
+  }\r
+}\r
+\r
+/**\r
+  Dump SMI child context.\r
+\r
+  @param HandlerType  the handler type\r
+  @param Context      the handler context\r
+  @param ContextSize  the handler context size\r
+**/\r
+VOID\r
+DumpSmiChildContext (\r
+  IN EFI_GUID   *HandlerType,\r
+  IN VOID       *Context,\r
+  IN UINTN      ContextSize\r
+  )\r
+{\r
+  if (CompareGuid (HandlerType, &gEfiSmmSwDispatch2ProtocolGuid)) {\r
+    Print(L" SwSmi=\"0x%x\"", ((EFI_SMM_SW_REGISTER_CONTEXT *)Context)->SwSmiInputValue);\r
+  } else if (CompareGuid (HandlerType, &gEfiSmmSxDispatch2ProtocolGuid)) {\r
+    Print(L" SxType=\"%a\"", SxTypeToString(((EFI_SMM_SX_REGISTER_CONTEXT *)Context)->Type));\r
+    Print(L" SxPhase=\"%a\"", SxPhaseToString(((EFI_SMM_SX_REGISTER_CONTEXT *)Context)->Phase));\r
+  } else if (CompareGuid (HandlerType, &gEfiSmmPowerButtonDispatch2ProtocolGuid)) {\r
+    Print(L" PowerButtonPhase=\"%a\"", PowerButtonPhaseToString(((EFI_SMM_POWER_BUTTON_REGISTER_CONTEXT *)Context)->Phase));\r
+  } else if (CompareGuid (HandlerType, &gEfiSmmStandbyButtonDispatch2ProtocolGuid)) {\r
+    Print(L" StandbyButtonPhase=\"%a\"", StandbyButtonPhaseToString(((EFI_SMM_STANDBY_BUTTON_REGISTER_CONTEXT *)Context)->Phase));\r
+  } else if (CompareGuid (HandlerType, &gEfiSmmPeriodicTimerDispatch2ProtocolGuid)) {\r
+    Print(L" PeriodicTimerPeriod=\"%ld\"", ((EFI_SMM_PERIODIC_TIMER_REGISTER_CONTEXT *)Context)->Period);\r
+    Print(L" PeriodicTimerSmiTickInterval=\"%ld\"", ((EFI_SMM_PERIODIC_TIMER_REGISTER_CONTEXT *)Context)->SmiTickInterval);\r
+  } else if (CompareGuid (HandlerType, &gEfiSmmGpiDispatch2ProtocolGuid)) {\r
+    Print(L" GpiNum=\"0x%lx\"", ((EFI_SMM_GPI_REGISTER_CONTEXT *)Context)->GpiNum);\r
+  } else if (CompareGuid (HandlerType, &gEfiSmmIoTrapDispatch2ProtocolGuid)) {\r
+    Print(L" IoTrapAddress=\"0x%x\"", ((EFI_SMM_IO_TRAP_REGISTER_CONTEXT *)Context)->Address);\r
+    Print(L" IoTrapLength=\"0x%x\"", ((EFI_SMM_IO_TRAP_REGISTER_CONTEXT *)Context)->Length);\r
+    Print(L" IoTrapType=\"%a\"", IoTrapTypeToString(((EFI_SMM_IO_TRAP_REGISTER_CONTEXT *)Context)->Type));\r
+  } else if (CompareGuid (HandlerType, &gEfiSmmUsbDispatch2ProtocolGuid)) {\r
+    Print(L" UsbType=\"0x%x\"", UsbTypeToString(((SMI_HANDLER_PROFILE_USB_REGISTER_CONTEXT *)Context)->Type));\r
+    Print(L" UsbDevicePath=\"%s\"", ConvertDevicePathToText((EFI_DEVICE_PATH_PROTOCOL *)(((SMI_HANDLER_PROFILE_USB_REGISTER_CONTEXT *)Context) + 1), TRUE, TRUE));\r
+  } else {\r
+    Print(L" Context=\"");\r
+    InternalDumpData (Context, ContextSize);\r
+    Print(L"\"");\r
+  }\r
+}\r
+\r
+/**\r
+  Dump SMI handler in HandlerCategory.\r
+\r
+  @param HandlerCategory  SMI handler category\r
+**/\r
+VOID\r
+DumpSmiHandler(\r
+  IN UINT32 HandlerCategory\r
+  )\r
+{\r
+  SMM_CORE_SMI_DATABASE_STRUCTURE    *SmiStruct;\r
+  SMM_CORE_SMI_HANDLER_STRUCTURE     *SmiHandlerStruct;\r
+  UINTN                              Index;\r
+  SMM_CORE_IMAGE_DATABASE_STRUCTURE  *ImageStruct;\r
+  CHAR8                              *NameString;\r
+\r
+  SmiStruct = (VOID *)mSmiHandlerProfileDatabase;\r
+  while ((UINTN)SmiStruct < (UINTN)mSmiHandlerProfileDatabase + mSmiHandlerProfileDatabaseSize) {\r
+    if ((SmiStruct->Header.Signature == SMM_CORE_SMI_DATABASE_SIGNATURE) && (SmiStruct->HandlerCategory == HandlerCategory)) {\r
+      SmiHandlerStruct = (VOID *)(SmiStruct + 1);\r
+      Print(L"  <SmiEntry");\r
+      if (!IsZeroGuid (&SmiStruct->HandlerType)) {\r
+        Print(L" HandlerType=\"%g\"", &SmiStruct->HandlerType);\r
+      }\r
+      Print(L">\n");\r
+      for (Index = 0; Index < SmiStruct->HandlerCount; Index++) {\r
+        Print(L"    <SmiHandler");\r
+        if (SmiHandlerStruct->ContextBufferSize != 0) {\r
+          DumpSmiChildContext (&SmiStruct->HandlerType, (UINT8 *)SmiHandlerStruct + SmiHandlerStruct->ContextBufferOffset, SmiHandlerStruct->ContextBufferSize);\r
+        }\r
+        Print(L">\n");\r
+        ImageStruct = GetImageFromRef((UINTN)SmiHandlerStruct->ImageRef);\r
+        NameString = GetDriverNameString (ImageStruct);\r
+        Print(L"      <Module RefId=\"0x%x\" Name=\"%a\">\n", SmiHandlerStruct->ImageRef, NameString);\r
+        if ((ImageStruct != NULL) && (ImageStruct->PdbStringOffset != 0)) {\r
+          Print(L"      <Pdb>%a</Pdb>\n", (UINT8 *)ImageStruct + ImageStruct->PdbStringOffset);\r
+        }\r
+        Print(L"      </Module>\n");\r
+        Print(L"      <Handler Address=\"0x%x\">\n", SmiHandlerStruct->Handler);\r
+        if (ImageStruct != NULL) {\r
+          Print(L"         <RVA>0x%x</RVA>\n", SmiHandlerStruct->Handler - ImageStruct->ImageBase);\r
+        }\r
+        Print(L"      </Handler>\n", SmiHandlerStruct->Handler);\r
+        Print(L"      <Caller Address=\"0x%x\">\n", SmiHandlerStruct->CallerAddr);\r
+        if (ImageStruct != NULL) {\r
+          Print(L"         <RVA>0x%x</RVA>\n", SmiHandlerStruct->CallerAddr - ImageStruct->ImageBase);\r
+        }\r
+        Print(L"      </Caller>\n", SmiHandlerStruct->Handler);\r
+        SmiHandlerStruct = (VOID *)((UINTN)SmiHandlerStruct + SmiHandlerStruct->Length);\r
+        Print(L"    </SmiHandler>\n");\r
+      }\r
+      Print(L"  </SmiEntry>\n");\r
+    }\r
+    SmiStruct = (VOID *)((UINTN)SmiStruct + SmiStruct->Header.Length);\r
+  }\r
+\r
+  return;\r
+}\r
+\r
+/**\r
+  The Entry Point for SMI handler profile info application.\r
+\r
+  @param  ImageHandle    The firmware allocated handle for the EFI image.\r
+  @param  SystemTable    A pointer to the EFI System Table.\r
+\r
+  @retval EFI_SUCCESS    The entry point is executed successfully.\r
+  @retval Other          Some error occurred when executing this entry point.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+SmiHandlerProfileInfoEntrypoint (\r
+  IN EFI_HANDLE           ImageHandle,\r
+  IN EFI_SYSTEM_TABLE     *SystemTable\r
+  )\r
+{\r
+  GetSmiHandlerProfileDatabase();\r
+\r
+  if (mSmiHandlerProfileDatabase == NULL) {\r
+    return EFI_SUCCESS;\r
+  }\r
+\r
+  //\r
+  // Dump all image\r
+  //\r
+  Print(L"<?xml version=\"1.0\" encoding=\"utf-8\"?>\n");\r
+  Print(L"<SmiHandlerProfile>\n");\r
+  Print(L"<ImageDatabase>\n");\r
+  Print(L"  <!-- SMM image loaded -->\n");\r
+  DumpSmmLoadedImage();\r
+  Print(L"</ImageDatabase>\n\n");\r
+\r
+  //\r
+  // Dump SMI Handler\r
+  //\r
+  Print(L"<SmiHandlerDatabase>\n");\r
+  Print(L"  <!-- SMI Handler registered -->\n\n");\r
+  Print(L"  <SmiHandlerCategory Name=\"RootSmi\">\n");\r
+  Print(L"  <!-- The root SMI Handler registered by SmmCore -->\n");\r
+  DumpSmiHandler(SmmCoreSmiHandlerCategoryRootHandler);\r
+  Print(L"  </SmiHandlerCategory>\n\n");\r
+\r
+  Print(L"  <SmiHandlerCategory Name=\"GuidSmi\">\n");\r
+  Print(L"  <!-- The GUID SMI Handler registered by SmmCore -->\n");\r
+  DumpSmiHandler(SmmCoreSmiHandlerCategoryGuidHandler);\r
+  Print(L"  </SmiHandlerCategory>\n\n");\r
+\r
+  Print(L"  <SmiHandlerCategory Name=\"HardwareSmi\">\n");\r
+  Print(L"  <!-- The hardware SMI Handler registered by SmmChildDispatcher -->\n");\r
+  DumpSmiHandler(SmmCoreSmiHandlerCategoryHardwareHandler);\r
+  Print(L"  </SmiHandlerCategory>\n\n");\r
+\r
+  Print(L"</SmiHandlerDatabase>\n");\r
+  Print(L"</SmiHandlerProfile>\n");\r
+\r
+  if (mSmiHandlerProfileDatabase != NULL) {\r
+    FreePool(mSmiHandlerProfileDatabase);\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
diff --git a/MdeModulePkg/Application/SmiHandlerProfileInfo/SmiHandlerProfileInfo.inf b/MdeModulePkg/Application/SmiHandlerProfileInfo/SmiHandlerProfileInfo.inf
new file mode 100644 (file)
index 0000000..73cc052
--- /dev/null
@@ -0,0 +1,65 @@
+## @file\r
+#  Shell application to dump SMI handler profile information.\r
+#\r
+# Note that if the feature is not enabled by setting PcdSmiHandlerProfilePropertyMask,\r
+# the application will not display SMI handler profile information.\r
+#\r
+# Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>\r
+# This program and the accompanying materials are licensed and made available under\r
+# the terms and conditions of the BSD License that accompanies this distribution.\r
+# The full text of the license may be found at\r
+# http://opensource.org/licenses/bsd-license.php.\r
+#\r
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+#\r
+##\r
+\r
+[Defines]\r
+  INF_VERSION                    = 0x00010005\r
+  BASE_NAME                      = SmiHandlerProfileInfo\r
+  MODULE_UNI_FILE                = SmiHandlerProfileInfo.uni\r
+  FILE_GUID                      = 611EA796-8DF8-4BB6-91FE-6540ED70DC66\r
+  MODULE_TYPE                    = UEFI_APPLICATION\r
+  VERSION_STRING                 = 1.0\r
+  ENTRY_POINT                    = SmiHandlerProfileInfoEntrypoint\r
+\r
+[Sources]\r
+  SmiHandlerProfileInfo.c\r
+\r
+[Packages]\r
+  MdePkg/MdePkg.dec\r
+  MdeModulePkg/MdeModulePkg.dec\r
+\r
+[LibraryClasses]\r
+  UefiApplicationEntryPoint\r
+  BaseLib\r
+  BaseMemoryLib\r
+  MemoryAllocationLib\r
+  DebugLib\r
+  UefiBootServicesTableLib\r
+  UefiRuntimeServicesTableLib\r
+  UefiLib\r
+  PrintLib\r
+  DevicePathLib\r
+  PeCoffGetEntryPointLib\r
+  DxeServicesLib\r
+\r
+[Protocols]\r
+  gEfiSmmCommunicationProtocolGuid             ## CONSUMES\r
+  gEfiSmmSwDispatch2ProtocolGuid               ## SOMETIMES_CONSUMES\r
+  gEfiSmmSxDispatch2ProtocolGuid               ## SOMETIMES_CONSUMES\r
+  gEfiSmmPowerButtonDispatch2ProtocolGuid      ## SOMETIMES_CONSUMES\r
+  gEfiSmmStandbyButtonDispatch2ProtocolGuid    ## SOMETIMES_CONSUMES\r
+  gEfiSmmPeriodicTimerDispatch2ProtocolGuid    ## SOMETIMES_CONSUMES\r
+  gEfiSmmGpiDispatch2ProtocolGuid              ## SOMETIMES_CONSUMES\r
+  gEfiSmmIoTrapDispatch2ProtocolGuid           ## SOMETIMES_CONSUMES\r
+  gEfiSmmUsbDispatch2ProtocolGuid              ## SOMETIMES_CONSUMES\r
+\r
+[Guids]\r
+  gEdkiiPiSmmCommunicationRegionTableGuid  ## CONSUMES  ## SystemTable\r
+  gSmiHandlerProfileGuid                   ## SOMETIMES_CONSUMES   ## GUID # SmiHandlerRegister\r
+\r
+[UserExtensions.TianoCore."ExtraFiles"]\r
+  SmiHandlerProfileInfoExtra.uni\r
+\r
diff --git a/MdeModulePkg/Application/SmiHandlerProfileInfo/SmiHandlerProfileInfo.uni b/MdeModulePkg/Application/SmiHandlerProfileInfo/SmiHandlerProfileInfo.uni
new file mode 100644 (file)
index 0000000..d73a1a0
--- /dev/null
@@ -0,0 +1,22 @@
+// /** @file\r
+// Shell application to dump SMI handler profile information.\r
+//\r
+// Note that if the feature is not enabled by setting PcdSmiHandlerProfilePropertyMask,\r
+// the application will not display SMI handler profile information.\r
+//\r
+// Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>\r
+//\r
+// This program and the accompanying materials\r
+// are licensed and made available under the terms and conditions of the BSD License\r
+// which accompanies this distribution. The full text of the license may be found at\r
+// http://opensource.org/licenses/bsd-license.php\r
+// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+//\r
+// **/\r
+\r
+\r
+#string STR_MODULE_ABSTRACT             #language en-US "Shell application to dump SMI handler profile information."\r
+\r
+#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."\r
+\r
diff --git a/MdeModulePkg/Application/SmiHandlerProfileInfo/SmiHandlerProfileInfoExtra.uni b/MdeModulePkg/Application/SmiHandlerProfileInfo/SmiHandlerProfileInfoExtra.uni
new file mode 100644 (file)
index 0000000..b10c71a
--- /dev/null
@@ -0,0 +1,19 @@
+// /** @file\r
+// SmiHandlerProfileInfo Localized Strings and Content\r
+//\r
+// Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>\r
+//\r
+// This program and the accompanying materials\r
+// are licensed and made available under the terms and conditions of the BSD License\r
+// which accompanies this distribution. The full text of the license may be found at\r
+// http://opensource.org/licenses/bsd-license.php\r
+// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+//\r
+// **/\r
+\r
+#string STR_PROPERTIES_MODULE_NAME\r
+#language en-US\r
+"SMI Handler Profile Information Application"\r
+\r
+\r