Some redundant library classes and GUIDs have been removed in inf, .c and .h files. https://bugzilla.tianocore.org/show_bug.cgi?id=1044 https://bugzilla.tianocore.org/show_bug.cgi?id=1045 https://bugzilla.tianocore.org/show_bug.cgi?id=1047 https://bugzilla.tianocore.org/show_bug.cgi?id=1049 https://bugzilla.tianocore.org/show_bug.cgi?id=1051 https://bugzilla.tianocore.org/show_bug.cgi?id=1052 https://bugzilla.tianocore.org/show_bug.cgi?id=1053 https://bugzilla.tianocore.org/show_bug.cgi?id=1054 https://bugzilla.tianocore.org/show_bug.cgi?id=1055 https://bugzilla.tianocore.org/show_bug.cgi?id=1056 https://bugzilla.tianocore.org/show_bug.cgi?id=1017 https://bugzilla.tianocore.org/show_bug.cgi?id=1035 https://bugzilla.tianocore.org/show_bug.cgi?id=1033 https://bugzilla.tianocore.org/show_bug.cgi?id=1012 https://bugzilla.tianocore.org/show_bug.cgi?id=1011 https://bugzilla.tianocore.org/show_bug.cgi?id=1062 v2: 1. Correct copyright year. 2. Fix alignment issue in AcpiPlatformDxe.inf. 3. Add DevicePathLib which is removed before in I2cHostDxe.inf. 4. Update NvmExpressPei.inf, NvmExpressPei.h, IScsiDxe.inf, IScsiDxe.inf, IScsiDxe.h, DxeMain.inf, DxeMain.h, PiSmmCore.inf and PiSmmCore.h for https://bugzilla.tianocore.org/show_bug.cgi?id=1062. v3: 1. Add https://bugzilla.tianocore.org/show_bug.cgi?id=1062 to the link list. 2. Remove DevicePathLib from I2cHostDxe.inf. 3. Update NvmExpressPei.inf, NvmExpressPei.h, UfsPciHcDxe.inf, UfsPciHcDxe.h, I2cHostDxe.inf, AtaBusDxe.inf, IScsiDxe.inf, IScsiDxe.h, DxeMain.inf, DxeMain.h, PiSmmCore.inf and PiSmmCore.h for https://bugzilla.tianocore.org/show_bug.cgi?id=1062. (Forget to add UfsPciHcDxe.inf, UfsPciHcDxe.h, AtaBusDxe.inf, and I2cHostDxe.inf previously.) Cc: Star Zeng <star.zeng@intel.com> Cc: Eric Dong <eric.dong@intel.com> Contributed-under: TianoCore Contribution Agreement 1.1 Signed-off-by: shenglei <shenglei.zhang@intel.com> Reviewed-by: Star Zeng <star.zeng@intel.com>
		
			
				
	
	
		
			693 lines
		
	
	
		
			22 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			693 lines
		
	
	
		
			22 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /** @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/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;
 | |
| }
 |