X-Git-Url: https://git.proxmox.com/?p=mirror_edk2.git;a=blobdiff_plain;f=MdeModulePkg%2FApplication%2FMemoryProfileInfo%2FMemoryProfileInfo.c;h=072ae72dcd7614295e602e83c2bf0821145c8ceb;hp=f69a3e77486a82368f127e42b5280fb2c3608865;hb=8f7a05e1396657c8bd2948825f41d0fdf239e334;hpb=8feb7452acedf5bbe0f6c3accac8562b7cc29b3d diff --git a/MdeModulePkg/Application/MemoryProfileInfo/MemoryProfileInfo.c b/MdeModulePkg/Application/MemoryProfileInfo/MemoryProfileInfo.c index f69a3e7748..072ae72dcd 100644 --- a/MdeModulePkg/Application/MemoryProfileInfo/MemoryProfileInfo.c +++ b/MdeModulePkg/Application/MemoryProfileInfo/MemoryProfileInfo.c @@ -1,13 +1,13 @@ /** @file - - Copyright (c) 2014 - 2015, Intel Corporation. All rights reserved.
- This program and the accompanying materials - are licensed and made available under the terms and conditions of the BSD License - which accompanies this distribution. The full text of the license may be found at - http://opensource.org/licenses/bsd-license.php - THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, - WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + Copyright (c) 2014 - 2017, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. **/ @@ -22,135 +22,210 @@ #include #include #include -#include #include #include #include -#include #include +#include + +CHAR8 *mActionString[] = { + "Unknown", + "gBS->AllocatePages", + "gBS->FreePages", + "gBS->AllocatePool", + "gBS->FreePool", +}; + +CHAR8 *mSmmActionString[] = { + "SmmUnknown", + "gSmst->SmmAllocatePages", + "gSmst->SmmFreePages", + "gSmst->SmmAllocatePool", + "gSmst->SmmFreePool", +}; -CHAR16 *mActionString[] = { - L"Unknown", - L"AllocatePages", - L"FreePages", - L"AllocatePool", - L"FreePool", +typedef struct { + MEMORY_PROFILE_ACTION Action; + CHAR8 *String; +} ACTION_STRING; + +ACTION_STRING mExtActionString[] = { + {MEMORY_PROFILE_ACTION_LIB_ALLOCATE_PAGES, "Lib:AllocatePages"}, + {MEMORY_PROFILE_ACTION_LIB_ALLOCATE_RUNTIME_PAGES, "Lib:AllocateRuntimePages"}, + {MEMORY_PROFILE_ACTION_LIB_ALLOCATE_RESERVED_PAGES, "Lib:AllocateReservedPages"}, + {MEMORY_PROFILE_ACTION_LIB_FREE_PAGES, "Lib:FreePages"}, + {MEMORY_PROFILE_ACTION_LIB_ALLOCATE_ALIGNED_PAGES, "Lib:AllocateAlignedPages"}, + {MEMORY_PROFILE_ACTION_LIB_ALLOCATE_ALIGNED_RUNTIME_PAGES, "Lib:AllocateAlignedRuntimePages"}, + {MEMORY_PROFILE_ACTION_LIB_ALLOCATE_ALIGNED_RESERVED_PAGES, "Lib:AllocateAlignedReservedPages"}, + {MEMORY_PROFILE_ACTION_LIB_FREE_ALIGNED_PAGES, "Lib:FreeAlignedPages"}, + {MEMORY_PROFILE_ACTION_LIB_ALLOCATE_POOL, "Lib:AllocatePool"}, + {MEMORY_PROFILE_ACTION_LIB_ALLOCATE_RUNTIME_POOL, "Lib:AllocateRuntimePool"}, + {MEMORY_PROFILE_ACTION_LIB_ALLOCATE_RESERVED_POOL, "Lib:AllocateReservedPool"}, + {MEMORY_PROFILE_ACTION_LIB_FREE_POOL, "Lib:FreePool"}, + {MEMORY_PROFILE_ACTION_LIB_ALLOCATE_ZERO_POOL, "Lib:AllocateZeroPool"}, + {MEMORY_PROFILE_ACTION_LIB_ALLOCATE_RUNTIME_ZERO_POOL, "Lib:AllocateRuntimeZeroPool"}, + {MEMORY_PROFILE_ACTION_LIB_ALLOCATE_RESERVED_ZERO_POOL, "Lib:AllocateReservedZeroPool"}, + {MEMORY_PROFILE_ACTION_LIB_ALLOCATE_COPY_POOL, "Lib:AllocateCopyPool"}, + {MEMORY_PROFILE_ACTION_LIB_ALLOCATE_RUNTIME_COPY_POOL, "Lib:AllocateRuntimeCopyPool"}, + {MEMORY_PROFILE_ACTION_LIB_ALLOCATE_RESERVED_COPY_POOL, "Lib:AllocateReservedCopyPool"}, + {MEMORY_PROFILE_ACTION_LIB_REALLOCATE_POOL, "Lib:ReallocatePool"}, + {MEMORY_PROFILE_ACTION_LIB_REALLOCATE_RUNTIME_POOL, "Lib:ReallocateRuntimePool"}, + {MEMORY_PROFILE_ACTION_LIB_REALLOCATE_RESERVED_POOL, "Lib:ReallocateReservedPool"}, }; -CHAR16 *mMemoryTypeString[] = { - L"EfiReservedMemoryType", - L"EfiLoaderCode", - L"EfiLoaderData", - L"EfiBootServicesCode", - L"EfiBootServicesData", - L"EfiRuntimeServicesCode", - L"EfiRuntimeServicesData", - L"EfiConventionalMemory", - L"EfiUnusableMemory", - L"EfiACPIReclaimMemory", - L"EfiACPIMemoryNVS", - L"EfiMemoryMappedIO", - L"EfiMemoryMappedIOPortSpace", - L"EfiPalCode", - L"EfiPersistentMemory", - L"EfiOSReserved", - L"EfiOemReserved", +CHAR8 mUserDefinedActionString[] = {"UserDefined-0x80000000"}; + +CHAR8 *mMemoryTypeString[] = { + "EfiReservedMemoryType", + "EfiLoaderCode", + "EfiLoaderData", + "EfiBootServicesCode", + "EfiBootServicesData", + "EfiRuntimeServicesCode", + "EfiRuntimeServicesData", + "EfiConventionalMemory", + "EfiUnusableMemory", + "EfiACPIReclaimMemory", + "EfiACPIMemoryNVS", + "EfiMemoryMappedIO", + "EfiMemoryMappedIOPortSpace", + "EfiPalCode", + "EfiPersistentMemory", + "EfiOSReserved", + "EfiOemReserved", }; -CHAR16 *mSubsystemString[] = { - L"Unknown", - L"NATIVE", - L"WINDOWS_GUI", - L"WINDOWS_CUI", - L"Unknown", - L"Unknown", - L"Unknown", - L"POSIX_CUI", - L"Unknown", - L"WINDOWS_CE_GUI", - L"EFI_APPLICATION", - L"EFI_BOOT_SERVICE_DRIVER", - L"EFI_RUNTIME_DRIVER", - L"EFI_ROM", - L"XBOX", - L"Unknown", +CHAR8 *mSubsystemString[] = { + "Unknown", + "NATIVE", + "WINDOWS_GUI", + "WINDOWS_CUI", + "Unknown", + "Unknown", + "Unknown", + "POSIX_CUI", + "Unknown", + "WINDOWS_CE_GUI", + "EFI_APPLICATION", + "EFI_BOOT_SERVICE_DRIVER", + "EFI_RUNTIME_DRIVER", + "EFI_ROM", + "XBOX", + "Unknown", }; -CHAR16 *mFileTypeString[] = { - L"Unknown", - L"RAW", - L"FREEFORM", - L"SECURITY_CORE", - L"PEI_CORE", - L"DXE_CORE", - L"PEIM", - L"DRIVER", - L"COMBINED_PEIM_DRIVER", - L"APPLICATION", - L"SMM", - L"FIRMWARE_VOLUME_IMAGE", - L"COMBINED_SMM_DXE", - L"SMM_CORE", +CHAR8 *mFileTypeString[] = { + "Unknown", + "RAW", + "FREEFORM", + "SECURITY_CORE", + "PEI_CORE", + "DXE_CORE", + "PEIM", + "DRIVER", + "COMBINED_PEIM_DRIVER", + "APPLICATION", + "SMM", + "FIRMWARE_VOLUME_IMAGE", + "COMBINED_SMM_DXE", + "SMM_CORE", }; -#define PROFILE_NAME_STRING_LENGTH 36 -CHAR16 mNameString[PROFILE_NAME_STRING_LENGTH + 1]; +#define PROFILE_NAME_STRING_LENGTH 64 +CHAR8 mNameString[PROFILE_NAME_STRING_LENGTH + 1]; + +// +// Profile summary information +// +#define MEMORY_PROFILE_ALLOC_SUMMARY_INFO_SIGNATURE SIGNATURE_32 ('M','P','A','S') +#define MEMORY_PROFILE_ALLOC_SUMMARY_INFO_REVISION 0x0001 + +typedef struct { + MEMORY_PROFILE_COMMON_HEADER Header; + PHYSICAL_ADDRESS CallerAddress; + MEMORY_PROFILE_ACTION Action; + CHAR8 *ActionString; + UINT32 AllocateCount; + UINT64 TotalSize; +} MEMORY_PROFILE_ALLOC_SUMMARY_INFO; + +typedef struct { + UINT32 Signature; + MEMORY_PROFILE_ALLOC_SUMMARY_INFO AllocSummaryInfo; + LIST_ENTRY Link; +} MEMORY_PROFILE_ALLOC_SUMMARY_INFO_DATA; + +typedef struct { + UINT32 Signature; + MEMORY_PROFILE_DRIVER_INFO *DriverInfo; + LIST_ENTRY *AllocSummaryInfoList; + LIST_ENTRY Link; +} MEMORY_PROFILE_DRIVER_SUMMARY_INFO_DATA; + +typedef struct { + UINT32 Signature; + MEMORY_PROFILE_CONTEXT *Context; + LIST_ENTRY *DriverSummaryInfoList; +} MEMORY_PROFILE_CONTEXT_SUMMARY_DATA; + +LIST_ENTRY mImageSummaryQueue = INITIALIZE_LIST_HEAD_VARIABLE (mImageSummaryQueue); +MEMORY_PROFILE_CONTEXT_SUMMARY_DATA mMemoryProfileContextSummary; -/** +/** 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 converted - to Unicode and copied into UnicodeBuffer. The name is truncated, - if necessary, to ensure that UnicodeBuffer is not overrun. - + 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] UnicodeBuffer The resultant Unicode File Name. - + @param[out] AsciiBuffer The resultant Ascii File Name. + **/ VOID GetShortPdbFileName ( IN CHAR8 *PdbFileName, - OUT CHAR16 *UnicodeBuffer + OUT CHAR8 *AsciiBuffer ) { - UINTN IndexA; // Current work location within an ASCII string. - UINTN IndexU; // Current work location within a Unicode string. + UINTN IndexPdb; // Current work location within a Pdb string. + UINTN IndexBuffer; // Current work location within a Buffer string. UINTN StartIndex; UINTN EndIndex; - ZeroMem (UnicodeBuffer, (PROFILE_NAME_STRING_LENGTH + 1) * sizeof (CHAR16)); + ZeroMem (AsciiBuffer, PROFILE_NAME_STRING_LENGTH + 1); if (PdbFileName == NULL) { - StrnCpyS (UnicodeBuffer, PROFILE_NAME_STRING_LENGTH + 1, L" ", 1); + AsciiStrnCpyS (AsciiBuffer, PROFILE_NAME_STRING_LENGTH + 1, " ", 1); } else { StartIndex = 0; for (EndIndex = 0; PdbFileName[EndIndex] != 0; EndIndex++); - for (IndexA = 0; PdbFileName[IndexA] != 0; IndexA++) { - if (PdbFileName[IndexA] == '\\') { - StartIndex = IndexA + 1; + for (IndexPdb = 0; PdbFileName[IndexPdb] != 0; IndexPdb++) { + if ((PdbFileName[IndexPdb] == '\\') || (PdbFileName[IndexPdb] == '/')) { + StartIndex = IndexPdb + 1; } - if (PdbFileName[IndexA] == '.') { - EndIndex = IndexA; + if (PdbFileName[IndexPdb] == '.') { + EndIndex = IndexPdb; } } - IndexU = 0; - for (IndexA = StartIndex; IndexA < EndIndex; IndexA++) { - UnicodeBuffer[IndexU] = (CHAR16) PdbFileName[IndexA]; - IndexU++; - if (IndexU >= PROFILE_NAME_STRING_LENGTH) { - UnicodeBuffer[PROFILE_NAME_STRING_LENGTH] = 0; + 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 @@ -159,32 +234,27 @@ GetShortPdbFileName ( @param[in] DriverInfo Pointer to memory profile driver info. - @post The resulting Unicode name string is stored in the mNameString global array. + @return The resulting Ascii name string is stored in the mNameString global array. **/ -VOID +CHAR8 * GetDriverNameString ( IN MEMORY_PROFILE_DRIVER_INFO *DriverInfo ) { EFI_STATUS Status; - CHAR8 *PdbFileName; CHAR16 *NameString; UINTN StringSize; // // Method 1: Get the name string from image PDB // - if ((DriverInfo->ImageBase != 0) && (DriverInfo->FileType != EFI_FV_FILETYPE_SMM) && (DriverInfo->FileType != EFI_FV_FILETYPE_SMM_CORE)) { - PdbFileName = PeCoffLoaderGetPdbPointer ((VOID *) (UINTN) DriverInfo->ImageBase); - - if (PdbFileName != NULL) { - GetShortPdbFileName (PdbFileName, mNameString); - return; - } + if (DriverInfo->PdbStringOffset != 0) { + GetShortPdbFileName ((CHAR8 *) ((UINTN) DriverInfo + DriverInfo->PdbStringOffset), mNameString); + return mNameString; } - if (!CompareGuid (&DriverInfo->FileName, &gZeroGuid)) { + if (!IsZeroGuid (&DriverInfo->FileName)) { // // Try to get the image's FFS UI section by image GUID // @@ -201,17 +271,20 @@ GetDriverNameString ( // // Method 2: Get the name string from FFS UI section // - StrnCpyS (mNameString, PROFILE_NAME_STRING_LENGTH + 1, NameString, PROFILE_NAME_STRING_LENGTH); - mNameString[PROFILE_NAME_STRING_LENGTH] = 0; + if (StrLen (NameString) > PROFILE_NAME_STRING_LENGTH) { + NameString[PROFILE_NAME_STRING_LENGTH] = 0; + } + UnicodeStrToAsciiStrS (NameString, mNameString, sizeof (mNameString)); FreePool (NameString); - return; + return mNameString; } } // // Method 3: Get the name string from image GUID // - UnicodeSPrint (mNameString, sizeof (mNameString), L"%g", &DriverInfo->FileName); + AsciiSPrint (mNameString, sizeof (mNameString), "%g", &DriverInfo->FileName); + return mNameString; } /** @@ -222,7 +295,7 @@ GetDriverNameString ( @return Pointer to string. **/ -CHAR16 * +CHAR8 * ProfileMemoryTypeToStr ( IN EFI_MEMORY_TYPE MemoryType ) @@ -246,12 +319,63 @@ ProfileMemoryTypeToStr ( return mMemoryTypeString[Index]; } +/** + Action to string. + + @param[in] Action Profile action. + @param[in] UserDefinedActionString Pointer to user defined action string. + @param[in] IsForSmm TRUE - SMRAM profile. + FALSE - UEFI memory profile. + + @return Pointer to string. + +**/ +CHAR8 * +ProfileActionToStr ( + IN MEMORY_PROFILE_ACTION Action, + IN CHAR8 *UserDefinedActionString, + IN BOOLEAN IsForSmm + ) +{ + UINTN Index; + UINTN ActionStringCount; + CHAR8 **ActionString; + + if (IsForSmm) { + ActionString = mSmmActionString; + ActionStringCount = ARRAY_SIZE (mSmmActionString); + } else { + ActionString = mActionString; + ActionStringCount = ARRAY_SIZE (mActionString); + } + + if ((UINTN) (UINT32) Action < ActionStringCount) { + return ActionString[Action]; + } + for (Index = 0; Index < ARRAY_SIZE (mExtActionString); Index++) { + if (mExtActionString[Index].Action == Action) { + return mExtActionString[Index].String; + } + } + if ((Action & MEMORY_PROFILE_ACTION_USER_DEFINED_MASK) != 0) { + if (UserDefinedActionString != NULL) { + return UserDefinedActionString; + } + AsciiSPrint (mUserDefinedActionString, sizeof (mUserDefinedActionString), "UserDefined-0x%08x", Action); + return mUserDefinedActionString; + } + + return ActionString[0]; +} + /** Dump memory profile allocate information. @param[in] DriverInfo Pointer to memory profile driver info. @param[in] AllocIndex Memory profile alloc info index. @param[in] AllocInfo Pointer to memory profile alloc info. + @param[in] IsForSmm TRUE - SMRAM profile. + FALSE - UEFI memory profile. @return Pointer to next memory profile alloc info. @@ -260,20 +384,30 @@ MEMORY_PROFILE_ALLOC_INFO * DumpMemoryProfileAllocInfo ( IN MEMORY_PROFILE_DRIVER_INFO *DriverInfo, IN UINTN AllocIndex, - IN MEMORY_PROFILE_ALLOC_INFO *AllocInfo + IN MEMORY_PROFILE_ALLOC_INFO *AllocInfo, + IN BOOLEAN IsForSmm ) { + CHAR8 *ActionString; + if (AllocInfo->Header.Signature != MEMORY_PROFILE_ALLOC_INFO_SIGNATURE) { return NULL; } + + if (AllocInfo->ActionStringOffset != 0) { + ActionString = (CHAR8 *) ((UINTN) AllocInfo + AllocInfo->ActionStringOffset); + } else { + ActionString = NULL; + } + Print (L" MEMORY_PROFILE_ALLOC_INFO (0x%x)\n", AllocIndex); Print (L" Signature - 0x%08x\n", AllocInfo->Header.Signature); Print (L" Length - 0x%04x\n", AllocInfo->Header.Length); - Print (L" Revision - 0x%04x\n", AllocInfo->Header.Revision); + Print (L" Revision - 0x%04x\n", AllocInfo->Header.Revision); Print (L" CallerAddress - 0x%016lx (Offset: 0x%08x)\n", AllocInfo->CallerAddress, (UINTN) (AllocInfo->CallerAddress - DriverInfo->ImageBase)); Print (L" SequenceId - 0x%08x\n", AllocInfo->SequenceId); - Print (L" Action - 0x%08x (%s)\n", AllocInfo->Action, mActionString[(AllocInfo->Action < sizeof(mActionString)/sizeof(mActionString[0])) ? AllocInfo->Action : 0]); - Print (L" MemoryType - 0x%08x (%s)\n", AllocInfo->MemoryType, ProfileMemoryTypeToStr (AllocInfo->MemoryType)); + Print (L" Action - 0x%08x (%a)\n", AllocInfo->Action, ProfileActionToStr (AllocInfo->Action, ActionString, IsForSmm)); + Print (L" MemoryType - 0x%08x (%a)\n", AllocInfo->MemoryType, ProfileMemoryTypeToStr (AllocInfo->MemoryType)); Print (L" Buffer - 0x%016lx\n", AllocInfo->Buffer); Print (L" Size - 0x%016lx\n", AllocInfo->Size); @@ -285,6 +419,8 @@ DumpMemoryProfileAllocInfo ( @param[in] DriverIndex Memory profile driver info index. @param[in] DriverInfo Pointer to memory profile driver info. + @param[in] IsForSmm TRUE - SMRAM profile. + FALSE - UEFI memory profile. @return Pointer to next memory profile driver info. @@ -292,12 +428,14 @@ DumpMemoryProfileAllocInfo ( MEMORY_PROFILE_DRIVER_INFO * DumpMemoryProfileDriverInfo ( IN UINTN DriverIndex, - IN MEMORY_PROFILE_DRIVER_INFO *DriverInfo + IN MEMORY_PROFILE_DRIVER_INFO *DriverInfo, + IN BOOLEAN IsForSmm ) { UINTN TypeIndex; MEMORY_PROFILE_ALLOC_INFO *AllocInfo; UINTN AllocIndex; + CHAR8 *NameString; if (DriverInfo->Header.Signature != MEMORY_PROFILE_DRIVER_INFO_SIGNATURE) { return NULL; @@ -305,28 +443,31 @@ DumpMemoryProfileDriverInfo ( Print (L" MEMORY_PROFILE_DRIVER_INFO (0x%x)\n", DriverIndex); Print (L" Signature - 0x%08x\n", DriverInfo->Header.Signature); Print (L" Length - 0x%04x\n", DriverInfo->Header.Length); - Print (L" Revision - 0x%04x\n", DriverInfo->Header.Revision); - GetDriverNameString (DriverInfo); - Print (L" FileName - %s\n", &mNameString); + Print (L" Revision - 0x%04x\n", DriverInfo->Header.Revision); + NameString = GetDriverNameString (DriverInfo); + Print (L" FileName - %a\n", NameString); + if (DriverInfo->PdbStringOffset != 0) { + Print (L" Pdb - %a\n", (CHAR8 *) ((UINTN) DriverInfo + DriverInfo->PdbStringOffset)); + } Print (L" ImageBase - 0x%016lx\n", DriverInfo->ImageBase); Print (L" ImageSize - 0x%016lx\n", DriverInfo->ImageSize); Print (L" EntryPoint - 0x%016lx\n", DriverInfo->EntryPoint); - Print (L" ImageSubsystem - 0x%04x (%s)\n", DriverInfo->ImageSubsystem, mSubsystemString[(DriverInfo->ImageSubsystem < sizeof(mSubsystemString)/sizeof(mSubsystemString[0])) ? DriverInfo->ImageSubsystem : 0]); - Print (L" FileType - 0x%02x (%s)\n", DriverInfo->FileType, mFileTypeString[(DriverInfo->FileType < sizeof(mFileTypeString)/sizeof(mFileTypeString[0])) ? DriverInfo->FileType : 0]); + Print (L" ImageSubsystem - 0x%04x (%a)\n", DriverInfo->ImageSubsystem, mSubsystemString[(DriverInfo->ImageSubsystem < sizeof(mSubsystemString)/sizeof(mSubsystemString[0])) ? DriverInfo->ImageSubsystem : 0]); + Print (L" FileType - 0x%02x (%a)\n", DriverInfo->FileType, mFileTypeString[(DriverInfo->FileType < sizeof(mFileTypeString)/sizeof(mFileTypeString[0])) ? DriverInfo->FileType : 0]); Print (L" CurrentUsage - 0x%016lx\n", DriverInfo->CurrentUsage); Print (L" PeakUsage - 0x%016lx\n", DriverInfo->PeakUsage); for (TypeIndex = 0; TypeIndex < sizeof (DriverInfo->CurrentUsageByType) / sizeof (DriverInfo->CurrentUsageByType[0]); TypeIndex++) { if ((DriverInfo->CurrentUsageByType[TypeIndex] != 0) || (DriverInfo->PeakUsageByType[TypeIndex] != 0)) { - Print (L" CurrentUsage[0x%02x] - 0x%016lx (%s)\n", TypeIndex, DriverInfo->CurrentUsageByType[TypeIndex], mMemoryTypeString[TypeIndex]); - Print (L" PeakUsage[0x%02x] - 0x%016lx (%s)\n", TypeIndex, DriverInfo->PeakUsageByType[TypeIndex], mMemoryTypeString[TypeIndex]); + Print (L" CurrentUsage[0x%02x] - 0x%016lx (%a)\n", TypeIndex, DriverInfo->CurrentUsageByType[TypeIndex], mMemoryTypeString[TypeIndex]); + Print (L" PeakUsage[0x%02x] - 0x%016lx (%a)\n", TypeIndex, DriverInfo->PeakUsageByType[TypeIndex], mMemoryTypeString[TypeIndex]); } } Print (L" AllocRecordCount - 0x%08x\n", DriverInfo->AllocRecordCount); AllocInfo = (MEMORY_PROFILE_ALLOC_INFO *) ((UINTN) DriverInfo + DriverInfo->Header.Length); for (AllocIndex = 0; AllocIndex < DriverInfo->AllocRecordCount; AllocIndex++) { - AllocInfo = DumpMemoryProfileAllocInfo (DriverInfo, AllocIndex, AllocInfo); + AllocInfo = DumpMemoryProfileAllocInfo (DriverInfo, AllocIndex, AllocInfo, IsForSmm); if (AllocInfo == NULL) { return NULL; } @@ -338,13 +479,16 @@ DumpMemoryProfileDriverInfo ( Dump memory profile context information. @param[in] Context Pointer to memory profile context. + @param[in] IsForSmm TRUE - SMRAM profile. + FALSE - UEFI memory profile. @return Pointer to the end of memory profile context buffer. **/ VOID * DumpMemoryProfileContext ( - IN MEMORY_PROFILE_CONTEXT *Context + IN MEMORY_PROFILE_CONTEXT *Context, + IN BOOLEAN IsForSmm ) { UINTN TypeIndex; @@ -357,14 +501,14 @@ DumpMemoryProfileContext ( Print (L"MEMORY_PROFILE_CONTEXT\n"); Print (L" Signature - 0x%08x\n", Context->Header.Signature); Print (L" Length - 0x%04x\n", Context->Header.Length); - Print (L" Revision - 0x%04x\n", Context->Header.Revision); + Print (L" Revision - 0x%04x\n", Context->Header.Revision); Print (L" CurrentTotalUsage - 0x%016lx\n", Context->CurrentTotalUsage); Print (L" PeakTotalUsage - 0x%016lx\n", Context->PeakTotalUsage); for (TypeIndex = 0; TypeIndex < sizeof (Context->CurrentTotalUsageByType) / sizeof (Context->CurrentTotalUsageByType[0]); TypeIndex++) { if ((Context->CurrentTotalUsageByType[TypeIndex] != 0) || (Context->PeakTotalUsageByType[TypeIndex] != 0)) { - Print (L" CurrentTotalUsage[0x%02x] - 0x%016lx (%s)\n", TypeIndex, Context->CurrentTotalUsageByType[TypeIndex], mMemoryTypeString[TypeIndex]); - Print (L" PeakTotalUsage[0x%02x] - 0x%016lx (%s)\n", TypeIndex, Context->PeakTotalUsageByType[TypeIndex], mMemoryTypeString[TypeIndex]); + Print (L" CurrentTotalUsage[0x%02x] - 0x%016lx (%a)\n", TypeIndex, Context->CurrentTotalUsageByType[TypeIndex], mMemoryTypeString[TypeIndex]); + Print (L" PeakTotalUsage[0x%02x] - 0x%016lx (%a)\n", TypeIndex, Context->PeakTotalUsageByType[TypeIndex], mMemoryTypeString[TypeIndex]); } } Print (L" TotalImageSize - 0x%016lx\n", Context->TotalImageSize); @@ -373,7 +517,7 @@ DumpMemoryProfileContext ( DriverInfo = (MEMORY_PROFILE_DRIVER_INFO *) ((UINTN) Context + Context->Header.Length); for (DriverIndex = 0; DriverIndex < Context->ImageCount; DriverIndex++) { - DriverInfo = DumpMemoryProfileDriverInfo (DriverIndex, DriverInfo); + DriverInfo = DumpMemoryProfileDriverInfo (DriverIndex, DriverInfo, IsForSmm); if (DriverInfo == NULL) { return NULL; } @@ -402,7 +546,7 @@ DumpMemoryProfileDescriptor ( Print (L" MEMORY_PROFILE_DESCRIPTOR (0x%x)\n", DescriptorIndex); Print (L" Signature - 0x%08x\n", Descriptor->Header.Signature); Print (L" Length - 0x%04x\n", Descriptor->Header.Length); - Print (L" Revision - 0x%04x\n", Descriptor->Header.Revision); + Print (L" Revision - 0x%04x\n", Descriptor->Header.Revision); Print (L" Address - 0x%016lx\n", Descriptor->Address); Print (L" Size - 0x%016lx\n", Descriptor->Size); @@ -431,7 +575,7 @@ DumpMemoryProfileFreeMemory ( Print (L"MEMORY_PROFILE_FREE_MEMORY\n"); Print (L" Signature - 0x%08x\n", FreeMemory->Header.Signature); Print (L" Length - 0x%04x\n", FreeMemory->Header.Length); - Print (L" Revision - 0x%04x\n", FreeMemory->Header.Revision); + Print (L" Revision - 0x%04x\n", FreeMemory->Header.Revision); Print (L" TotalFreeMemoryPages - 0x%016lx\n", FreeMemory->TotalFreeMemoryPages); Print (L" FreeMemoryEntryCount - 0x%08x\n", FreeMemory->FreeMemoryEntryCount); @@ -468,7 +612,7 @@ DumpMemoryProfileMemoryRange ( Print (L"MEMORY_PROFILE_MEMORY_RANGE\n"); Print (L" Signature - 0x%08x\n", MemoryRange->Header.Signature); Print (L" Length - 0x%04x\n", MemoryRange->Header.Length); - Print (L" Revision - 0x%04x\n", MemoryRange->Header.Revision); + Print (L" Revision - 0x%04x\n", MemoryRange->Header.Revision); Print (L" MemoryRangeCount - 0x%08x\n", MemoryRange->MemoryRangeCount); Descriptor = (MEMORY_PROFILE_DESCRIPTOR *) ((UINTN) MemoryRange + MemoryRange->Header.Length); @@ -511,6 +655,10 @@ ScanMemoryProfileBySignature ( // return (VOID *) CommonHeader; } + if (CommonHeader->Length == 0) { + ASSERT (FALSE); + return NULL; + } CommonHeader = (MEMORY_PROFILE_COMMON_HEADER *) ((UINTN) CommonHeader + CommonHeader->Length); } @@ -522,12 +670,15 @@ ScanMemoryProfileBySignature ( @param[in] ProfileBuffer Memory profile base address. @param[in] ProfileSize Memory profile size. + @param[in] IsForSmm TRUE - SMRAM profile. + FALSE - UEFI memory profile. **/ VOID DumpMemoryProfile ( IN PHYSICAL_ADDRESS ProfileBuffer, - IN UINT64 ProfileSize + IN UINT64 ProfileSize, + IN BOOLEAN IsForSmm ) { MEMORY_PROFILE_CONTEXT *Context; @@ -536,7 +687,7 @@ DumpMemoryProfile ( Context = (MEMORY_PROFILE_CONTEXT *) ScanMemoryProfileBySignature (ProfileBuffer, ProfileSize, MEMORY_PROFILE_CONTEXT_SIGNATURE); if (Context != NULL) { - DumpMemoryProfileContext (Context); + DumpMemoryProfileContext (Context, IsForSmm); } FreeMemory = (MEMORY_PROFILE_FREE_MEMORY *) ScanMemoryProfileBySignature (ProfileBuffer, ProfileSize, MEMORY_PROFILE_FREE_MEMORY_SIGNATURE); @@ -550,6 +701,317 @@ DumpMemoryProfile ( } } +/** + Get Allocate summary information structure by caller address. + + @param[in] CallerAddress Caller address. + @param[in] DriverSummaryInfoData Driver summary information data structure. + + @return Allocate summary information structure by caller address. + +**/ +MEMORY_PROFILE_ALLOC_SUMMARY_INFO_DATA * +GetAllocSummaryInfoByCallerAddress ( + IN PHYSICAL_ADDRESS CallerAddress, + IN MEMORY_PROFILE_DRIVER_SUMMARY_INFO_DATA *DriverSummaryInfoData + ) +{ + LIST_ENTRY *AllocSummaryInfoList; + LIST_ENTRY *AllocSummaryLink; + MEMORY_PROFILE_ALLOC_SUMMARY_INFO *AllocSummaryInfo; + MEMORY_PROFILE_ALLOC_SUMMARY_INFO_DATA *AllocSummaryInfoData; + + AllocSummaryInfoList = DriverSummaryInfoData->AllocSummaryInfoList; + + for (AllocSummaryLink = AllocSummaryInfoList->ForwardLink; + AllocSummaryLink != AllocSummaryInfoList; + AllocSummaryLink = AllocSummaryLink->ForwardLink) { + AllocSummaryInfoData = CR ( + AllocSummaryLink, + MEMORY_PROFILE_ALLOC_SUMMARY_INFO_DATA, + Link, + MEMORY_PROFILE_ALLOC_SUMMARY_INFO_SIGNATURE + ); + AllocSummaryInfo = &AllocSummaryInfoData->AllocSummaryInfo; + if (AllocSummaryInfo->CallerAddress == CallerAddress) { + return AllocSummaryInfoData; + } + } + return NULL; +} + +/** + Create Allocate summary information structure and + link to Driver summary information data structure. + + @param[in, out] DriverSummaryInfoData Driver summary information data structure. + @param[in] AllocInfo Pointer to memory profile alloc info. + + @return Pointer to next memory profile alloc info. + +**/ +MEMORY_PROFILE_ALLOC_INFO * +CreateAllocSummaryInfo ( + IN OUT MEMORY_PROFILE_DRIVER_SUMMARY_INFO_DATA *DriverSummaryInfoData, + IN MEMORY_PROFILE_ALLOC_INFO *AllocInfo + ) +{ + MEMORY_PROFILE_ALLOC_SUMMARY_INFO_DATA *AllocSummaryInfoData; + MEMORY_PROFILE_ALLOC_SUMMARY_INFO *AllocSummaryInfo; + + if (AllocInfo->Header.Signature != MEMORY_PROFILE_ALLOC_INFO_SIGNATURE) { + return NULL; + } + + AllocSummaryInfoData = GetAllocSummaryInfoByCallerAddress (AllocInfo->CallerAddress, DriverSummaryInfoData); + if (AllocSummaryInfoData == NULL) { + AllocSummaryInfoData = AllocatePool (sizeof (*AllocSummaryInfoData)); + if (AllocSummaryInfoData == NULL) { + return NULL; + } + + AllocSummaryInfoData->Signature = MEMORY_PROFILE_ALLOC_SUMMARY_INFO_SIGNATURE; + AllocSummaryInfo = &AllocSummaryInfoData->AllocSummaryInfo; + AllocSummaryInfo->Header.Signature = MEMORY_PROFILE_ALLOC_SUMMARY_INFO_SIGNATURE; + AllocSummaryInfo->Header.Length = sizeof (*AllocSummaryInfo); + AllocSummaryInfo->Header.Revision = MEMORY_PROFILE_ALLOC_SUMMARY_INFO_REVISION; + AllocSummaryInfo->CallerAddress = AllocInfo->CallerAddress; + AllocSummaryInfo->Action = AllocInfo->Action; + if (AllocInfo->ActionStringOffset != 0) { + AllocSummaryInfo->ActionString = (CHAR8 *) ((UINTN) AllocInfo + AllocInfo->ActionStringOffset); + } else { + AllocSummaryInfo->ActionString = NULL; + } + AllocSummaryInfo->AllocateCount = 0; + AllocSummaryInfo->TotalSize = 0; + InsertTailList (DriverSummaryInfoData->AllocSummaryInfoList, &AllocSummaryInfoData->Link); + } + AllocSummaryInfo = &AllocSummaryInfoData->AllocSummaryInfo; + AllocSummaryInfo->AllocateCount ++; + AllocSummaryInfo->TotalSize += AllocInfo->Size; + + return (MEMORY_PROFILE_ALLOC_INFO *) ((UINTN) AllocInfo + AllocInfo->Header.Length); +} + +/** + Create Driver summary information structure and + link to Context summary information data structure. + + @param[in, out] ContextSummaryData Context summary information data structure. + @param[in] DriverInfo Pointer to memory profile driver info. + + @return Pointer to next memory profile driver info. + +**/ +MEMORY_PROFILE_DRIVER_INFO * +CreateDriverSummaryInfo ( + IN OUT MEMORY_PROFILE_CONTEXT_SUMMARY_DATA *ContextSummaryData, + IN MEMORY_PROFILE_DRIVER_INFO *DriverInfo + ) +{ + MEMORY_PROFILE_DRIVER_SUMMARY_INFO_DATA *DriverSummaryInfoData; + MEMORY_PROFILE_ALLOC_INFO *AllocInfo; + UINTN AllocIndex; + + if (DriverInfo->Header.Signature != MEMORY_PROFILE_DRIVER_INFO_SIGNATURE) { + return NULL; + } + + DriverSummaryInfoData = AllocatePool (sizeof (*DriverSummaryInfoData) + sizeof (LIST_ENTRY)); + if (DriverSummaryInfoData == NULL) { + return NULL; + } + DriverSummaryInfoData->Signature = MEMORY_PROFILE_DRIVER_INFO_SIGNATURE; + DriverSummaryInfoData->DriverInfo = DriverInfo; + DriverSummaryInfoData->AllocSummaryInfoList = (LIST_ENTRY *) (DriverSummaryInfoData + 1); + InitializeListHead (DriverSummaryInfoData->AllocSummaryInfoList); + InsertTailList (ContextSummaryData->DriverSummaryInfoList, &DriverSummaryInfoData->Link); + + AllocInfo = (MEMORY_PROFILE_ALLOC_INFO *) ((UINTN) DriverInfo + DriverInfo->Header.Length); + for (AllocIndex = 0; AllocIndex < DriverInfo->AllocRecordCount; AllocIndex++) { + AllocInfo = CreateAllocSummaryInfo (DriverSummaryInfoData, AllocInfo); + if (AllocInfo == NULL) { + return NULL; + } + } + return (MEMORY_PROFILE_DRIVER_INFO *) AllocInfo; +} + +/** + Create Context summary information structure. + + @param[in] ProfileBuffer Memory profile base address. + @param[in] ProfileSize Memory profile size. + + @return Context summary information structure. + +**/ +MEMORY_PROFILE_CONTEXT_SUMMARY_DATA * +CreateContextSummaryData ( + IN PHYSICAL_ADDRESS ProfileBuffer, + IN UINT64 ProfileSize + ) +{ + MEMORY_PROFILE_CONTEXT *Context; + MEMORY_PROFILE_DRIVER_INFO *DriverInfo; + UINTN DriverIndex; + + Context = (MEMORY_PROFILE_CONTEXT *) ScanMemoryProfileBySignature (ProfileBuffer, ProfileSize, MEMORY_PROFILE_CONTEXT_SIGNATURE); + if (Context == NULL) { + return NULL; + } + + mMemoryProfileContextSummary.Signature = MEMORY_PROFILE_CONTEXT_SIGNATURE; + mMemoryProfileContextSummary.Context = Context; + mMemoryProfileContextSummary.DriverSummaryInfoList = &mImageSummaryQueue; + + DriverInfo = (MEMORY_PROFILE_DRIVER_INFO *) ((UINTN) Context + Context->Header.Length); + for (DriverIndex = 0; DriverIndex < Context->ImageCount; DriverIndex++) { + DriverInfo = CreateDriverSummaryInfo (&mMemoryProfileContextSummary, DriverInfo); + if (DriverInfo == NULL) { + return NULL; + } + } + + return &mMemoryProfileContextSummary; +} + +/** + Dump Context summary information. + + @param[in] ContextSummaryData Context summary information data. + @param[in] IsForSmm TRUE - SMRAM profile. + FALSE - UEFI memory profile. + +**/ +VOID +DumpContextSummaryData ( + IN MEMORY_PROFILE_CONTEXT_SUMMARY_DATA *ContextSummaryData, + IN BOOLEAN IsForSmm + ) +{ + MEMORY_PROFILE_DRIVER_SUMMARY_INFO_DATA *DriverSummaryInfoData; + MEMORY_PROFILE_ALLOC_SUMMARY_INFO_DATA *AllocSummaryInfoData; + LIST_ENTRY *DriverSummaryInfoList; + LIST_ENTRY *DriverSummaryLink; + LIST_ENTRY *AllocSummaryInfoList; + LIST_ENTRY *AllocSummaryLink; + MEMORY_PROFILE_DRIVER_INFO *DriverInfo; + MEMORY_PROFILE_ALLOC_SUMMARY_INFO *AllocSummaryInfo; + CHAR8 *NameString; + + if (ContextSummaryData == NULL) { + return ; + } + + Print (L"\nSummary Data:\n"); + + DriverSummaryInfoList = ContextSummaryData->DriverSummaryInfoList; + for (DriverSummaryLink = DriverSummaryInfoList->ForwardLink; + DriverSummaryLink != DriverSummaryInfoList; + DriverSummaryLink = DriverSummaryLink->ForwardLink) { + DriverSummaryInfoData = CR ( + DriverSummaryLink, + MEMORY_PROFILE_DRIVER_SUMMARY_INFO_DATA, + Link, + MEMORY_PROFILE_DRIVER_INFO_SIGNATURE + ); + DriverInfo = DriverSummaryInfoData->DriverInfo; + + NameString = GetDriverNameString (DriverInfo); + Print (L"\nDriver - %a (Usage - 0x%08x)", NameString, DriverInfo->CurrentUsage); + if (DriverInfo->CurrentUsage == 0) { + Print (L"\n"); + continue; + } + + if (DriverInfo->PdbStringOffset != 0) { + Print (L" (Pdb - %a)\n", (CHAR8 *) ((UINTN) DriverInfo + DriverInfo->PdbStringOffset)); + } else { + Print (L"\n"); + } + Print (L"Caller List:\n"); + Print(L" Count Size RVA Action\n"); + Print(L"========== ================== ================== (================================)\n"); + AllocSummaryInfoList = DriverSummaryInfoData->AllocSummaryInfoList; + for (AllocSummaryLink = AllocSummaryInfoList->ForwardLink; + AllocSummaryLink != AllocSummaryInfoList; + AllocSummaryLink = AllocSummaryLink->ForwardLink) { + AllocSummaryInfoData = CR ( + AllocSummaryLink, + MEMORY_PROFILE_ALLOC_SUMMARY_INFO_DATA, + Link, + MEMORY_PROFILE_ALLOC_SUMMARY_INFO_SIGNATURE + ); + AllocSummaryInfo = &AllocSummaryInfoData->AllocSummaryInfo; + + Print(L"0x%08x 0x%016lx <== 0x%016lx", + AllocSummaryInfo->AllocateCount, + AllocSummaryInfo->TotalSize, + AllocSummaryInfo->CallerAddress - DriverInfo->ImageBase + ); + Print (L" (%a)\n", ProfileActionToStr (AllocSummaryInfo->Action, AllocSummaryInfo->ActionString, IsForSmm)); + } + } + return ; +} + +/** + Destroy Context summary information. + + @param[in, out] ContextSummaryData Context summary information data. + +**/ +VOID +DestroyContextSummaryData ( + IN OUT MEMORY_PROFILE_CONTEXT_SUMMARY_DATA *ContextSummaryData + ) +{ + MEMORY_PROFILE_DRIVER_SUMMARY_INFO_DATA *DriverSummaryInfoData; + MEMORY_PROFILE_ALLOC_SUMMARY_INFO_DATA *AllocSummaryInfoData; + LIST_ENTRY *DriverSummaryInfoList; + LIST_ENTRY *DriverSummaryLink; + LIST_ENTRY *AllocSummaryInfoList; + LIST_ENTRY *AllocSummaryLink; + + if (ContextSummaryData == NULL) { + return ; + } + + DriverSummaryInfoList = ContextSummaryData->DriverSummaryInfoList; + for (DriverSummaryLink = DriverSummaryInfoList->ForwardLink; + DriverSummaryLink != DriverSummaryInfoList; + ) { + DriverSummaryInfoData = CR ( + DriverSummaryLink, + MEMORY_PROFILE_DRIVER_SUMMARY_INFO_DATA, + Link, + MEMORY_PROFILE_DRIVER_INFO_SIGNATURE + ); + DriverSummaryLink = DriverSummaryLink->ForwardLink; + + AllocSummaryInfoList = DriverSummaryInfoData->AllocSummaryInfoList; + for (AllocSummaryLink = AllocSummaryInfoList->ForwardLink; + AllocSummaryLink != AllocSummaryInfoList; + ) { + AllocSummaryInfoData = CR ( + AllocSummaryLink, + MEMORY_PROFILE_ALLOC_SUMMARY_INFO_DATA, + Link, + MEMORY_PROFILE_ALLOC_SUMMARY_INFO_SIGNATURE + ); + AllocSummaryLink = AllocSummaryLink->ForwardLink; + + RemoveEntryList (&AllocSummaryInfoData->Link); + FreePool (AllocSummaryInfoData); + } + + RemoveEntryList (&DriverSummaryInfoData->Link); + FreePool (DriverSummaryInfoData); + } + return ; +} + /** Get and dump UEFI memory profile data. @@ -562,10 +1024,12 @@ GetUefiMemoryProfileData ( VOID ) { - EFI_STATUS Status; - EDKII_MEMORY_PROFILE_PROTOCOL *ProfileProtocol; - VOID *Data; - UINT64 Size; + EFI_STATUS Status; + EDKII_MEMORY_PROFILE_PROTOCOL *ProfileProtocol; + VOID *Data; + UINT64 Size; + MEMORY_PROFILE_CONTEXT_SUMMARY_DATA *MemoryProfileContextSummaryData; + BOOLEAN RecordingState; Status = gBS->LocateProtocol (&gEdkiiMemoryProfileGuid, NULL, (VOID **) &ProfileProtocol); if (EFI_ERROR (Status)) { @@ -573,6 +1037,15 @@ GetUefiMemoryProfileData ( return Status; } + // + // Set recording state if needed. + // + RecordingState = MEMORY_PROFILE_RECORDING_DISABLE; + Status = ProfileProtocol->GetRecordingState (ProfileProtocol, &RecordingState); + if (RecordingState == MEMORY_PROFILE_RECORDING_ENABLE) { + ProfileProtocol->SetRecordingState (ProfileProtocol, MEMORY_PROFILE_RECORDING_DISABLE); + } + Size = 0; Data = NULL; Status = ProfileProtocol->GetData ( @@ -582,13 +1055,9 @@ GetUefiMemoryProfileData ( ); if (Status != EFI_BUFFER_TOO_SMALL) { Print (L"UefiMemoryProfile: GetData - %r\n", Status); - return Status; + goto Done; } - // - // Add one sizeof (MEMORY_PROFILE_ALLOC_INFO) to Size for this AllocatePool action. - // - Size = Size + sizeof (MEMORY_PROFILE_ALLOC_INFO); Data = AllocateZeroPool ((UINTN) Size); if (Data == NULL) { Status = EFI_OUT_OF_RESOURCES; @@ -602,20 +1071,39 @@ GetUefiMemoryProfileData ( Data ); if (EFI_ERROR (Status)) { - FreePool (Data); Print (L"UefiMemoryProfile: GetData - %r\n", Status); - return Status; + goto Done; } Print (L"UefiMemoryProfileSize - 0x%x\n", Size); Print (L"======= UefiMemoryProfile begin =======\n"); - DumpMemoryProfile ((PHYSICAL_ADDRESS) (UINTN) Data, Size); + DumpMemoryProfile ((PHYSICAL_ADDRESS) (UINTN) Data, Size, FALSE); + + // + // Dump summary information + // + MemoryProfileContextSummaryData = CreateContextSummaryData ((PHYSICAL_ADDRESS) (UINTN) Data, Size); + if (MemoryProfileContextSummaryData != NULL) { + DumpContextSummaryData (MemoryProfileContextSummaryData, FALSE); + DestroyContextSummaryData (MemoryProfileContextSummaryData); + } + Print (L"======= UefiMemoryProfile end =======\n\n\n"); - FreePool (Data); +Done: + if (Data != NULL) { + FreePool (Data); + } - return EFI_SUCCESS; + // + // Restore recording state if needed. + // + if (RecordingState == MEMORY_PROFILE_RECORDING_ENABLE) { + ProfileProtocol->SetRecordingState (ProfileProtocol, MEMORY_PROFILE_RECORDING_ENABLE); + } + + return Status; } /** @@ -635,10 +1123,22 @@ GetSmramProfileData ( UINT8 *CommBuffer; EFI_SMM_COMMUNICATE_HEADER *CommHeader; SMRAM_PROFILE_PARAMETER_GET_PROFILE_INFO *CommGetProfileInfo; - SMRAM_PROFILE_PARAMETER_GET_PROFILE_DATA *CommGetProfileData; - UINT64 ProfileSize; - PHYSICAL_ADDRESS ProfileBuffer; + SMRAM_PROFILE_PARAMETER_GET_PROFILE_DATA_BY_OFFSET *CommGetProfileData; + SMRAM_PROFILE_PARAMETER_RECORDING_STATE *CommRecordingState; + UINTN ProfileSize; + VOID *ProfileBuffer; 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; + MEMORY_PROFILE_CONTEXT_SUMMARY_DATA *MemoryProfileContextSummaryData; + BOOLEAN RecordingState; + + ProfileBuffer = NULL; Status = gBS->LocateProtocol (&gEfiSmmCommunicationProtocolGuid, NULL, (VOID **) &SmmCommunication); if (EFI_ERROR (Status)) { @@ -646,14 +1146,83 @@ GetSmramProfileData ( return Status; } - CommSize = sizeof (EFI_GUID) + sizeof (UINTN) + sizeof (SMRAM_PROFILE_PARAMETER_GET_PROFILE_DATA); - CommBuffer = AllocateZeroPool (CommSize); - if (CommBuffer == NULL) { - Status = EFI_OUT_OF_RESOURCES; - Print (L"SmramProfile: AllocateZeroPool (0x%x) for comm buffer - %r\n", CommSize, Status); + MinimalSizeNeeded = sizeof (EFI_GUID) + + sizeof (UINTN) + + MAX (sizeof (SMRAM_PROFILE_PARAMETER_GET_PROFILE_INFO), + MAX (sizeof (SMRAM_PROFILE_PARAMETER_GET_PROFILE_DATA_BY_OFFSET), + sizeof (SMRAM_PROFILE_PARAMETER_RECORDING_STATE))); + MinimalSizeNeeded += MAX (sizeof (MEMORY_PROFILE_CONTEXT), + MAX (sizeof (MEMORY_PROFILE_DRIVER_INFO), + MAX (sizeof (MEMORY_PROFILE_ALLOC_INFO), + MAX (sizeof (MEMORY_PROFILE_DESCRIPTOR), + MAX (sizeof (MEMORY_PROFILE_FREE_MEMORY), + sizeof (MEMORY_PROFILE_MEMORY_RANGE)))))); + + Status = EfiGetSystemConfigurationTable ( + &gEdkiiPiSmmCommunicationRegionTableGuid, + (VOID **) &PiSmmCommunicationRegionTable + ); + if (EFI_ERROR (Status)) { + DEBUG ((EFI_D_ERROR, "SmramProfile: Get PiSmmCommunicationRegionTable - %r\n", Status)); + return Status; + } + 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; + + // + // Set recording state if needed. + // + RecordingState = MEMORY_PROFILE_RECORDING_DISABLE; + + CommHeader = (EFI_SMM_COMMUNICATE_HEADER *) &CommBuffer[0]; + CopyMem (&CommHeader->HeaderGuid, &gEdkiiMemoryProfileGuid, sizeof (gEdkiiMemoryProfileGuid)); + CommHeader->MessageLength = sizeof (SMRAM_PROFILE_PARAMETER_RECORDING_STATE); + + CommRecordingState = (SMRAM_PROFILE_PARAMETER_RECORDING_STATE *) &CommBuffer[OFFSET_OF (EFI_SMM_COMMUNICATE_HEADER, Data)]; + CommRecordingState->Header.Command = SMRAM_PROFILE_COMMAND_GET_RECORDING_STATE; + CommRecordingState->Header.DataLength = sizeof (*CommRecordingState); + CommRecordingState->Header.ReturnStatus = (UINT64)-1; + CommRecordingState->RecordingState = MEMORY_PROFILE_RECORDING_DISABLE; + + CommSize = sizeof (EFI_GUID) + sizeof (UINTN) + CommHeader->MessageLength; + Status = SmmCommunication->Communicate (SmmCommunication, CommBuffer, &CommSize); + if (EFI_ERROR (Status)) { + DEBUG ((EFI_D_ERROR, "SmramProfile: SmmCommunication - %r\n", Status)); return Status; } + if (CommRecordingState->Header.ReturnStatus != 0) { + Print (L"SmramProfile: GetRecordingState - 0x%0x\n", CommRecordingState->Header.ReturnStatus); + return EFI_SUCCESS; + } + RecordingState = CommRecordingState->RecordingState; + if (RecordingState == MEMORY_PROFILE_RECORDING_ENABLE) { + CommHeader = (EFI_SMM_COMMUNICATE_HEADER *) &CommBuffer[0]; + CopyMem (&CommHeader->HeaderGuid, &gEdkiiMemoryProfileGuid, sizeof (gEdkiiMemoryProfileGuid)); + CommHeader->MessageLength = sizeof (SMRAM_PROFILE_PARAMETER_RECORDING_STATE); + + CommRecordingState = (SMRAM_PROFILE_PARAMETER_RECORDING_STATE *) &CommBuffer[OFFSET_OF (EFI_SMM_COMMUNICATE_HEADER, Data)]; + CommRecordingState->Header.Command = SMRAM_PROFILE_COMMAND_SET_RECORDING_STATE; + CommRecordingState->Header.DataLength = sizeof (*CommRecordingState); + CommRecordingState->Header.ReturnStatus = (UINT64)-1; + CommRecordingState->RecordingState = MEMORY_PROFILE_RECORDING_DISABLE; + + CommSize = sizeof (EFI_GUID) + sizeof (UINTN) + CommHeader->MessageLength; + SmmCommunication->Communicate (SmmCommunication, CommBuffer, &CommSize); + } + // // Get Size // @@ -669,71 +1238,108 @@ GetSmramProfileData ( CommSize = sizeof (EFI_GUID) + sizeof (UINTN) + CommHeader->MessageLength; Status = SmmCommunication->Communicate (SmmCommunication, CommBuffer, &CommSize); - if (EFI_ERROR (Status)) { - FreePool (CommBuffer); - DEBUG ((EFI_D_ERROR, "SmramProfile: SmmCommunication - %r\n", Status)); - return Status; - } + ASSERT_EFI_ERROR (Status); if (CommGetProfileInfo->Header.ReturnStatus != 0) { + Status = EFI_SUCCESS; Print (L"SmramProfile: GetProfileInfo - 0x%0x\n", CommGetProfileInfo->Header.ReturnStatus); - return EFI_SUCCESS; + goto Done; } - ProfileSize = CommGetProfileInfo->ProfileSize; + ProfileSize = (UINTN) CommGetProfileInfo->ProfileSize; // // Get Data // - ProfileBuffer = (PHYSICAL_ADDRESS) (UINTN) AllocateZeroPool ((UINTN) ProfileSize); - if (ProfileBuffer == 0) { - FreePool (CommBuffer); + ProfileBuffer = AllocateZeroPool (ProfileSize); + if (ProfileBuffer == NULL) { Status = EFI_OUT_OF_RESOURCES; - Print (L"SmramProfile: AllocateZeroPool (0x%x) for profile buffer - %r\n", (UINTN) ProfileSize, Status); - return Status; + Print (L"SmramProfile: AllocateZeroPool (0x%x) for profile buffer - %r\n", ProfileSize, Status); + goto Done; } CommHeader = (EFI_SMM_COMMUNICATE_HEADER *) &CommBuffer[0]; CopyMem (&CommHeader->HeaderGuid, &gEdkiiMemoryProfileGuid, sizeof(gEdkiiMemoryProfileGuid)); - CommHeader->MessageLength = sizeof (SMRAM_PROFILE_PARAMETER_GET_PROFILE_DATA); + CommHeader->MessageLength = sizeof (SMRAM_PROFILE_PARAMETER_GET_PROFILE_DATA_BY_OFFSET); - CommGetProfileData = (SMRAM_PROFILE_PARAMETER_GET_PROFILE_DATA *) &CommBuffer[OFFSET_OF (EFI_SMM_COMMUNICATE_HEADER, Data)]; - CommGetProfileData->Header.Command = SMRAM_PROFILE_COMMAND_GET_PROFILE_DATA; + CommGetProfileData = (SMRAM_PROFILE_PARAMETER_GET_PROFILE_DATA_BY_OFFSET *) &CommBuffer[OFFSET_OF (EFI_SMM_COMMUNICATE_HEADER, Data)]; + CommGetProfileData->Header.Command = SMRAM_PROFILE_COMMAND_GET_PROFILE_DATA_BY_OFFSET; CommGetProfileData->Header.DataLength = sizeof (*CommGetProfileData); CommGetProfileData->Header.ReturnStatus = (UINT64)-1; - CommGetProfileData->ProfileSize = ProfileSize; - CommGetProfileData->ProfileBuffer = ProfileBuffer; CommSize = sizeof (EFI_GUID) + sizeof (UINTN) + CommHeader->MessageLength; - Status = SmmCommunication->Communicate (SmmCommunication, CommBuffer, &CommSize); - ASSERT_EFI_ERROR (Status); + Buffer = (UINT8 *) CommHeader + CommSize; + Size -= CommSize; + + CommGetProfileData->ProfileBuffer = (PHYSICAL_ADDRESS) (UINTN) Buffer; + CommGetProfileData->ProfileOffset = 0; + while (CommGetProfileData->ProfileOffset < ProfileSize) { + Offset = (UINTN) CommGetProfileData->ProfileOffset; + if (Size <= (ProfileSize - CommGetProfileData->ProfileOffset)) { + CommGetProfileData->ProfileSize = (UINT64) Size; + } else { + CommGetProfileData->ProfileSize = (UINT64) (ProfileSize - CommGetProfileData->ProfileOffset); + } + Status = SmmCommunication->Communicate (SmmCommunication, CommBuffer, &CommSize); + ASSERT_EFI_ERROR (Status); - if (CommGetProfileData->Header.ReturnStatus != 0) { - FreePool ((VOID *) (UINTN) CommGetProfileData->ProfileBuffer); - FreePool (CommBuffer); - Print (L"GetProfileData - 0x%x\n", CommGetProfileData->Header.ReturnStatus); - return EFI_SUCCESS; + if (CommGetProfileData->Header.ReturnStatus != 0) { + Status = EFI_SUCCESS; + Print (L"GetProfileData - 0x%x\n", CommGetProfileData->Header.ReturnStatus); + goto Done; + } + CopyMem ((UINT8 *) ProfileBuffer + Offset, (VOID *) (UINTN) CommGetProfileData->ProfileBuffer, (UINTN) CommGetProfileData->ProfileSize); } - Print (L"SmramProfileSize - 0x%x\n", CommGetProfileData->ProfileSize); + Print (L"SmramProfileSize - 0x%x\n", ProfileSize); Print (L"======= SmramProfile begin =======\n"); - DumpMemoryProfile (CommGetProfileData->ProfileBuffer, CommGetProfileData->ProfileSize); + DumpMemoryProfile ((PHYSICAL_ADDRESS) (UINTN) ProfileBuffer, ProfileSize, TRUE); + + // + // Dump summary information + // + MemoryProfileContextSummaryData = CreateContextSummaryData ((PHYSICAL_ADDRESS) (UINTN) ProfileBuffer, ProfileSize); + if (MemoryProfileContextSummaryData != NULL) { + DumpContextSummaryData (MemoryProfileContextSummaryData, TRUE); + DestroyContextSummaryData (MemoryProfileContextSummaryData); + } + Print (L"======= SmramProfile end =======\n\n\n"); - FreePool ((VOID *) (UINTN) CommGetProfileData->ProfileBuffer); - FreePool (CommBuffer); +Done: + if (ProfileBuffer != NULL) { + FreePool (ProfileBuffer); + } - return EFI_SUCCESS; + // + // Restore recording state if needed. + // + if (RecordingState == MEMORY_PROFILE_RECORDING_ENABLE) { + CommHeader = (EFI_SMM_COMMUNICATE_HEADER *) &CommBuffer[0]; + CopyMem (&CommHeader->HeaderGuid, &gEdkiiMemoryProfileGuid, sizeof (gEdkiiMemoryProfileGuid)); + CommHeader->MessageLength = sizeof (SMRAM_PROFILE_PARAMETER_RECORDING_STATE); + + CommRecordingState = (SMRAM_PROFILE_PARAMETER_RECORDING_STATE *) &CommBuffer[OFFSET_OF (EFI_SMM_COMMUNICATE_HEADER, Data)]; + CommRecordingState->Header.Command = SMRAM_PROFILE_COMMAND_SET_RECORDING_STATE; + CommRecordingState->Header.DataLength = sizeof (*CommRecordingState); + CommRecordingState->Header.ReturnStatus = (UINT64)-1; + CommRecordingState->RecordingState = MEMORY_PROFILE_RECORDING_ENABLE; + + CommSize = sizeof (EFI_GUID) + sizeof (UINTN) + CommHeader->MessageLength; + SmmCommunication->Communicate (SmmCommunication, CommBuffer, &CommSize); + } + + return Status; } /** The user Entry Point for Application. The user code starts with this function as the real entry point for the image goes into a library that calls this function. - @param[in] ImageHandle The firmware allocated handle for the EFI image. + @param[in] ImageHandle The firmware allocated handle for the EFI image. @param[in] SystemTable A pointer to the EFI System Table. - + @retval EFI_SUCCESS The entry point is executed successfully. @retval other Some error occurs when executing this entry point. @@ -745,7 +1351,7 @@ UefiMain ( IN EFI_SYSTEM_TABLE *SystemTable ) { - EFI_STATUS Status; + EFI_STATUS Status; Status = GetUefiMemoryProfileData (); if (EFI_ERROR (Status)) {