mirror of https://github.com/acidanthera/audk.git
1368 lines
50 KiB
C
1368 lines
50 KiB
C
/** @file
|
|
|
|
Copyright (c) 2014 - 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 <Uefi.h>
|
|
#include <PiDxe.h>
|
|
#include <Library/BaseLib.h>
|
|
#include <Library/BaseMemoryLib.h>
|
|
#include <Library/MemoryAllocationLib.h>
|
|
#include <Library/UefiLib.h>
|
|
#include <Library/UefiApplicationEntryPoint.h>
|
|
#include <Library/UefiBootServicesTableLib.h>
|
|
#include <Library/UefiRuntimeServicesTableLib.h>
|
|
#include <Library/DebugLib.h>
|
|
#include <Library/DxeServicesLib.h>
|
|
#include <Library/PrintLib.h>
|
|
|
|
#include <Protocol/SmmCommunication.h>
|
|
#include <Protocol/SmmAccess2.h>
|
|
|
|
#include <Guid/MemoryProfile.h>
|
|
#include <Guid/PiSmmCommunicationRegionTable.h>
|
|
|
|
CHAR8 *mActionString[] = {
|
|
"Unknown",
|
|
"gBS->AllocatePages",
|
|
"gBS->FreePages",
|
|
"gBS->AllocatePool",
|
|
"gBS->FreePool",
|
|
};
|
|
|
|
CHAR8 *mSmmActionString[] = {
|
|
"SmmUnknown",
|
|
"gSmst->SmmAllocatePages",
|
|
"gSmst->SmmFreePages",
|
|
"gSmst->SmmAllocatePool",
|
|
"gSmst->SmmFreePool",
|
|
};
|
|
|
|
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"},
|
|
};
|
|
|
|
CHAR8 mUserDefinedActionString[] = {"UserDefined-0x80000000"};
|
|
|
|
CHAR8 *mMemoryTypeString[] = {
|
|
"EfiReservedMemoryType",
|
|
"EfiLoaderCode",
|
|
"EfiLoaderData",
|
|
"EfiBootServicesCode",
|
|
"EfiBootServicesData",
|
|
"EfiRuntimeServicesCode",
|
|
"EfiRuntimeServicesData",
|
|
"EfiConventionalMemory",
|
|
"EfiUnusableMemory",
|
|
"EfiACPIReclaimMemory",
|
|
"EfiACPIMemoryNVS",
|
|
"EfiMemoryMappedIO",
|
|
"EfiMemoryMappedIOPortSpace",
|
|
"EfiPalCode",
|
|
"EfiPersistentMemory",
|
|
"EfiOSReserved",
|
|
"EfiOemReserved",
|
|
};
|
|
|
|
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",
|
|
};
|
|
|
|
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 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 copied into
|
|
AsciiBuffer. The name is truncated, if necessary, to ensure that
|
|
AsciiBuffer is not overrun.
|
|
|
|
@param[in] PdbFileName Pdb file name.
|
|
@param[out] AsciiBuffer The resultant Ascii File Name.
|
|
|
|
**/
|
|
VOID
|
|
GetShortPdbFileName (
|
|
IN CHAR8 *PdbFileName,
|
|
OUT CHAR8 *AsciiBuffer
|
|
)
|
|
{
|
|
UINTN IndexPdb; // Current work location within a Pdb string.
|
|
UINTN IndexBuffer; // Current work location within a Buffer string.
|
|
UINTN StartIndex;
|
|
UINTN EndIndex;
|
|
|
|
ZeroMem (AsciiBuffer, PROFILE_NAME_STRING_LENGTH + 1);
|
|
|
|
if (PdbFileName == NULL) {
|
|
AsciiStrnCpyS (AsciiBuffer, PROFILE_NAME_STRING_LENGTH + 1, " ", 1);
|
|
} else {
|
|
StartIndex = 0;
|
|
for (EndIndex = 0; PdbFileName[EndIndex] != 0; EndIndex++);
|
|
for (IndexPdb = 0; PdbFileName[IndexPdb] != 0; IndexPdb++) {
|
|
if ((PdbFileName[IndexPdb] == '\\') || (PdbFileName[IndexPdb] == '/')) {
|
|
StartIndex = IndexPdb + 1;
|
|
}
|
|
|
|
if (PdbFileName[IndexPdb] == '.') {
|
|
EndIndex = IndexPdb;
|
|
}
|
|
}
|
|
|
|
IndexBuffer = 0;
|
|
for (IndexPdb = StartIndex; IndexPdb < EndIndex; IndexPdb++) {
|
|
AsciiBuffer[IndexBuffer] = PdbFileName[IndexPdb];
|
|
IndexBuffer++;
|
|
if (IndexBuffer >= PROFILE_NAME_STRING_LENGTH) {
|
|
AsciiBuffer[PROFILE_NAME_STRING_LENGTH] = 0;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
Get a human readable name for an image.
|
|
The following methods will be tried orderly:
|
|
1. Image PDB
|
|
2. FFS UI section
|
|
3. Image GUID
|
|
|
|
@param[in] DriverInfo Pointer to memory profile driver info.
|
|
|
|
@return The resulting Ascii name string is stored in the mNameString global array.
|
|
|
|
**/
|
|
CHAR8 *
|
|
GetDriverNameString (
|
|
IN MEMORY_PROFILE_DRIVER_INFO *DriverInfo
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
CHAR16 *NameString;
|
|
UINTN StringSize;
|
|
|
|
//
|
|
// Method 1: Get the name string from image PDB
|
|
//
|
|
if (DriverInfo->PdbStringOffset != 0) {
|
|
GetShortPdbFileName ((CHAR8 *) ((UINTN) DriverInfo + DriverInfo->PdbStringOffset), mNameString);
|
|
return mNameString;
|
|
}
|
|
|
|
if (!IsZeroGuid (&DriverInfo->FileName)) {
|
|
//
|
|
// Try to get the image's FFS UI section by image GUID
|
|
//
|
|
NameString = NULL;
|
|
StringSize = 0;
|
|
Status = GetSectionFromAnyFv (
|
|
&DriverInfo->FileName,
|
|
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", &DriverInfo->FileName);
|
|
return mNameString;
|
|
}
|
|
|
|
/**
|
|
Memory type to string.
|
|
|
|
@param[in] MemoryType Memory type.
|
|
|
|
@return Pointer to string.
|
|
|
|
**/
|
|
CHAR8 *
|
|
ProfileMemoryTypeToStr (
|
|
IN EFI_MEMORY_TYPE MemoryType
|
|
)
|
|
{
|
|
UINTN Index;
|
|
|
|
if ((UINT32) MemoryType >= 0x80000000) {
|
|
//
|
|
// OS reserved memory type.
|
|
//
|
|
Index = EfiMaxMemoryType;
|
|
} else if ((UINT32) MemoryType >= 0x70000000) {
|
|
//
|
|
// OEM reserved memory type.
|
|
//
|
|
Index = EfiMaxMemoryType + 1;
|
|
} else {
|
|
Index = MemoryType;
|
|
}
|
|
|
|
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.
|
|
|
|
**/
|
|
MEMORY_PROFILE_ALLOC_INFO *
|
|
DumpMemoryProfileAllocInfo (
|
|
IN MEMORY_PROFILE_DRIVER_INFO *DriverInfo,
|
|
IN UINTN AllocIndex,
|
|
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" 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 (%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);
|
|
|
|
return (MEMORY_PROFILE_ALLOC_INFO *) ((UINTN) AllocInfo + AllocInfo->Header.Length);
|
|
}
|
|
|
|
/**
|
|
Dump memory profile driver information.
|
|
|
|
@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.
|
|
|
|
**/
|
|
MEMORY_PROFILE_DRIVER_INFO *
|
|
DumpMemoryProfileDriverInfo (
|
|
IN UINTN DriverIndex,
|
|
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;
|
|
}
|
|
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);
|
|
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 (%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 (%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, IsForSmm);
|
|
if (AllocInfo == NULL) {
|
|
return NULL;
|
|
}
|
|
}
|
|
return (MEMORY_PROFILE_DRIVER_INFO *) AllocInfo;
|
|
}
|
|
|
|
/**
|
|
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 BOOLEAN IsForSmm
|
|
)
|
|
{
|
|
UINTN TypeIndex;
|
|
MEMORY_PROFILE_DRIVER_INFO *DriverInfo;
|
|
UINTN DriverIndex;
|
|
|
|
if (Context->Header.Signature != MEMORY_PROFILE_CONTEXT_SIGNATURE) {
|
|
return NULL;
|
|
}
|
|
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" 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 (%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);
|
|
Print (L" ImageCount - 0x%08x\n", Context->ImageCount);
|
|
Print (L" SequenceCount - 0x%08x\n", Context->SequenceCount);
|
|
|
|
DriverInfo = (MEMORY_PROFILE_DRIVER_INFO *) ((UINTN) Context + Context->Header.Length);
|
|
for (DriverIndex = 0; DriverIndex < Context->ImageCount; DriverIndex++) {
|
|
DriverInfo = DumpMemoryProfileDriverInfo (DriverIndex, DriverInfo, IsForSmm);
|
|
if (DriverInfo == NULL) {
|
|
return NULL;
|
|
}
|
|
}
|
|
return (VOID *) DriverInfo;
|
|
}
|
|
|
|
/**
|
|
Dump memory profile descriptor information.
|
|
|
|
@param[in] DescriptorIndex Memory profile descriptor index.
|
|
@param[in] Descriptor Pointer to memory profile descriptor.
|
|
|
|
@return Pointer to next memory profile descriptor.
|
|
|
|
**/
|
|
MEMORY_PROFILE_DESCRIPTOR *
|
|
DumpMemoryProfileDescriptor (
|
|
IN UINTN DescriptorIndex,
|
|
IN MEMORY_PROFILE_DESCRIPTOR *Descriptor
|
|
)
|
|
{
|
|
if (Descriptor->Header.Signature != MEMORY_PROFILE_DESCRIPTOR_SIGNATURE) {
|
|
return NULL;
|
|
}
|
|
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" Address - 0x%016lx\n", Descriptor->Address);
|
|
Print (L" Size - 0x%016lx\n", Descriptor->Size);
|
|
|
|
return (MEMORY_PROFILE_DESCRIPTOR *) ((UINTN) Descriptor + Descriptor->Header.Length);
|
|
}
|
|
|
|
/**
|
|
Dump memory profile free memory information.
|
|
|
|
@param[in] FreeMemory Pointer to memory profile free memory.
|
|
|
|
@return Pointer to the end of memory profile free memory buffer.
|
|
|
|
**/
|
|
VOID *
|
|
DumpMemoryProfileFreeMemory (
|
|
IN MEMORY_PROFILE_FREE_MEMORY *FreeMemory
|
|
)
|
|
{
|
|
MEMORY_PROFILE_DESCRIPTOR *Descriptor;
|
|
UINTN DescriptorIndex;
|
|
|
|
if (FreeMemory->Header.Signature != MEMORY_PROFILE_FREE_MEMORY_SIGNATURE) {
|
|
return NULL;
|
|
}
|
|
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" TotalFreeMemoryPages - 0x%016lx\n", FreeMemory->TotalFreeMemoryPages);
|
|
Print (L" FreeMemoryEntryCount - 0x%08x\n", FreeMemory->FreeMemoryEntryCount);
|
|
|
|
Descriptor = (MEMORY_PROFILE_DESCRIPTOR *) ((UINTN) FreeMemory + FreeMemory->Header.Length);
|
|
for (DescriptorIndex = 0; DescriptorIndex < FreeMemory->FreeMemoryEntryCount; DescriptorIndex++) {
|
|
Descriptor = DumpMemoryProfileDescriptor (DescriptorIndex, Descriptor);
|
|
if (Descriptor == NULL) {
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
return (VOID *) Descriptor;
|
|
}
|
|
|
|
/**
|
|
Dump memory profile memory range information.
|
|
|
|
@param[in] MemoryRange Pointer to memory profile memory range.
|
|
|
|
@return Pointer to the end of memory profile memory range buffer.
|
|
|
|
**/
|
|
VOID *
|
|
DumpMemoryProfileMemoryRange (
|
|
IN MEMORY_PROFILE_MEMORY_RANGE *MemoryRange
|
|
)
|
|
{
|
|
MEMORY_PROFILE_DESCRIPTOR *Descriptor;
|
|
UINTN DescriptorIndex;
|
|
|
|
if (MemoryRange->Header.Signature != MEMORY_PROFILE_MEMORY_RANGE_SIGNATURE) {
|
|
return NULL;
|
|
}
|
|
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" MemoryRangeCount - 0x%08x\n", MemoryRange->MemoryRangeCount);
|
|
|
|
Descriptor = (MEMORY_PROFILE_DESCRIPTOR *) ((UINTN) MemoryRange + MemoryRange->Header.Length);
|
|
for (DescriptorIndex = 0; DescriptorIndex < MemoryRange->MemoryRangeCount; DescriptorIndex++) {
|
|
Descriptor = DumpMemoryProfileDescriptor (DescriptorIndex, Descriptor);
|
|
if (Descriptor == NULL) {
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
return (VOID *) Descriptor;
|
|
}
|
|
|
|
/**
|
|
Scan memory profile by Signature.
|
|
|
|
@param[in] ProfileBuffer Memory profile base address.
|
|
@param[in] ProfileSize Memory profile size.
|
|
@param[in] Signature Signature.
|
|
|
|
@return Pointer to the stucture with the signature.
|
|
|
|
**/
|
|
VOID *
|
|
ScanMemoryProfileBySignature (
|
|
IN PHYSICAL_ADDRESS ProfileBuffer,
|
|
IN UINT64 ProfileSize,
|
|
IN UINT32 Signature
|
|
)
|
|
{
|
|
MEMORY_PROFILE_COMMON_HEADER *CommonHeader;
|
|
UINTN ProfileEnd;
|
|
|
|
ProfileEnd = (UINTN) (ProfileBuffer + ProfileSize);
|
|
CommonHeader = (MEMORY_PROFILE_COMMON_HEADER *) (UINTN) ProfileBuffer;
|
|
while ((UINTN) CommonHeader < ProfileEnd) {
|
|
if (CommonHeader->Signature == Signature) {
|
|
//
|
|
// Found it.
|
|
//
|
|
return (VOID *) CommonHeader;
|
|
}
|
|
if (CommonHeader->Length == 0) {
|
|
ASSERT (FALSE);
|
|
return NULL;
|
|
}
|
|
CommonHeader = (MEMORY_PROFILE_COMMON_HEADER *) ((UINTN) CommonHeader + CommonHeader->Length);
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
/**
|
|
Dump memory profile information.
|
|
|
|
@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 BOOLEAN IsForSmm
|
|
)
|
|
{
|
|
MEMORY_PROFILE_CONTEXT *Context;
|
|
MEMORY_PROFILE_FREE_MEMORY *FreeMemory;
|
|
MEMORY_PROFILE_MEMORY_RANGE *MemoryRange;
|
|
|
|
Context = (MEMORY_PROFILE_CONTEXT *) ScanMemoryProfileBySignature (ProfileBuffer, ProfileSize, MEMORY_PROFILE_CONTEXT_SIGNATURE);
|
|
if (Context != NULL) {
|
|
DumpMemoryProfileContext (Context, IsForSmm);
|
|
}
|
|
|
|
FreeMemory = (MEMORY_PROFILE_FREE_MEMORY *) ScanMemoryProfileBySignature (ProfileBuffer, ProfileSize, MEMORY_PROFILE_FREE_MEMORY_SIGNATURE);
|
|
if (FreeMemory != NULL) {
|
|
DumpMemoryProfileFreeMemory (FreeMemory);
|
|
}
|
|
|
|
MemoryRange = (MEMORY_PROFILE_MEMORY_RANGE *) ScanMemoryProfileBySignature (ProfileBuffer, ProfileSize, MEMORY_PROFILE_MEMORY_RANGE_SIGNATURE);
|
|
if (MemoryRange != NULL) {
|
|
DumpMemoryProfileMemoryRange (MemoryRange);
|
|
}
|
|
}
|
|
|
|
/**
|
|
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.
|
|
|
|
@return EFI_SUCCESS Get the memory profile data successfully.
|
|
@return other Fail to get the memory profile data.
|
|
|
|
**/
|
|
EFI_STATUS
|
|
GetUefiMemoryProfileData (
|
|
VOID
|
|
)
|
|
{
|
|
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)) {
|
|
DEBUG ((EFI_D_ERROR, "UefiMemoryProfile: Locate MemoryProfile protocol - %r\n", Status));
|
|
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 (
|
|
ProfileProtocol,
|
|
&Size,
|
|
Data
|
|
);
|
|
if (Status != EFI_BUFFER_TOO_SMALL) {
|
|
Print (L"UefiMemoryProfile: GetData - %r\n", Status);
|
|
goto Done;
|
|
}
|
|
|
|
Data = AllocateZeroPool ((UINTN) Size);
|
|
if (Data == NULL) {
|
|
Status = EFI_OUT_OF_RESOURCES;
|
|
Print (L"UefiMemoryProfile: AllocateZeroPool (0x%x) - %r\n", Size, Status);
|
|
return Status;
|
|
}
|
|
|
|
Status = ProfileProtocol->GetData (
|
|
ProfileProtocol,
|
|
&Size,
|
|
Data
|
|
);
|
|
if (EFI_ERROR (Status)) {
|
|
Print (L"UefiMemoryProfile: GetData - %r\n", Status);
|
|
goto Done;
|
|
}
|
|
|
|
|
|
Print (L"UefiMemoryProfileSize - 0x%x\n", Size);
|
|
Print (L"======= UefiMemoryProfile begin =======\n");
|
|
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");
|
|
|
|
Done:
|
|
if (Data != NULL) {
|
|
FreePool (Data);
|
|
}
|
|
|
|
//
|
|
// Restore recording state if needed.
|
|
//
|
|
if (RecordingState == MEMORY_PROFILE_RECORDING_ENABLE) {
|
|
ProfileProtocol->SetRecordingState (ProfileProtocol, MEMORY_PROFILE_RECORDING_ENABLE);
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|
|
/**
|
|
Get and dump SMRAM profile data.
|
|
|
|
@return EFI_SUCCESS Get the SMRAM profile data successfully.
|
|
@return other Fail to get the SMRAM profile data.
|
|
|
|
**/
|
|
EFI_STATUS
|
|
GetSmramProfileData (
|
|
VOID
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
UINTN CommSize;
|
|
UINT8 *CommBuffer;
|
|
EFI_SMM_COMMUNICATE_HEADER *CommHeader;
|
|
SMRAM_PROFILE_PARAMETER_GET_PROFILE_INFO *CommGetProfileInfo;
|
|
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)) {
|
|
DEBUG ((EFI_D_ERROR, "SmramProfile: Locate SmmCommunication protocol - %r\n", Status));
|
|
return 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
|
|
//
|
|
CommHeader = (EFI_SMM_COMMUNICATE_HEADER *) &CommBuffer[0];
|
|
CopyMem (&CommHeader->HeaderGuid, &gEdkiiMemoryProfileGuid, sizeof (gEdkiiMemoryProfileGuid));
|
|
CommHeader->MessageLength = sizeof (SMRAM_PROFILE_PARAMETER_GET_PROFILE_INFO);
|
|
|
|
CommGetProfileInfo = (SMRAM_PROFILE_PARAMETER_GET_PROFILE_INFO *) &CommBuffer[OFFSET_OF (EFI_SMM_COMMUNICATE_HEADER, Data)];
|
|
CommGetProfileInfo->Header.Command = SMRAM_PROFILE_COMMAND_GET_PROFILE_INFO;
|
|
CommGetProfileInfo->Header.DataLength = sizeof (*CommGetProfileInfo);
|
|
CommGetProfileInfo->Header.ReturnStatus = (UINT64)-1;
|
|
CommGetProfileInfo->ProfileSize = 0;
|
|
|
|
CommSize = sizeof (EFI_GUID) + sizeof (UINTN) + CommHeader->MessageLength;
|
|
Status = SmmCommunication->Communicate (SmmCommunication, CommBuffer, &CommSize);
|
|
ASSERT_EFI_ERROR (Status);
|
|
|
|
if (CommGetProfileInfo->Header.ReturnStatus != 0) {
|
|
Status = EFI_SUCCESS;
|
|
Print (L"SmramProfile: GetProfileInfo - 0x%0x\n", CommGetProfileInfo->Header.ReturnStatus);
|
|
goto Done;
|
|
}
|
|
|
|
ProfileSize = (UINTN) CommGetProfileInfo->ProfileSize;
|
|
|
|
//
|
|
// Get Data
|
|
//
|
|
ProfileBuffer = AllocateZeroPool (ProfileSize);
|
|
if (ProfileBuffer == NULL) {
|
|
Status = EFI_OUT_OF_RESOURCES;
|
|
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_BY_OFFSET);
|
|
|
|
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;
|
|
|
|
CommSize = sizeof (EFI_GUID) + sizeof (UINTN) + CommHeader->MessageLength;
|
|
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) {
|
|
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", ProfileSize);
|
|
Print (L"======= SmramProfile begin =======\n");
|
|
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");
|
|
|
|
Done:
|
|
if (ProfileBuffer != NULL) {
|
|
FreePool (ProfileBuffer);
|
|
}
|
|
|
|
//
|
|
// 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] 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.
|
|
|
|
**/
|
|
EFI_STATUS
|
|
EFIAPI
|
|
UefiMain (
|
|
IN EFI_HANDLE ImageHandle,
|
|
IN EFI_SYSTEM_TABLE *SystemTable
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
|
|
Status = GetUefiMemoryProfileData ();
|
|
if (EFI_ERROR (Status)) {
|
|
DEBUG ((EFI_D_ERROR, "GetUefiMemoryProfileData - %r\n", Status));
|
|
}
|
|
|
|
Status = GetSmramProfileData ();
|
|
if (EFI_ERROR (Status)) {
|
|
DEBUG ((EFI_D_ERROR, "GetSmramProfileData - %r\n", Status));
|
|
}
|
|
|
|
return EFI_SUCCESS;
|
|
}
|