Home | History | Annotate | Download | only in MemoryProfileInfo
      1 /** @file
      2 
      3   Copyright (c) 2014 - 2016, Intel Corporation. All rights reserved.<BR>
      4   This program and the accompanying materials
      5   are licensed and made available under the terms and conditions of the BSD License
      6   which accompanies this distribution.  The full text of the license may be found at
      7   http://opensource.org/licenses/bsd-license.php
      8 
      9   THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
     10   WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
     11 
     12 **/
     13 
     14 #include <Uefi.h>
     15 #include <PiDxe.h>
     16 #include <Library/BaseLib.h>
     17 #include <Library/BaseMemoryLib.h>
     18 #include <Library/MemoryAllocationLib.h>
     19 #include <Library/UefiLib.h>
     20 #include <Library/UefiApplicationEntryPoint.h>
     21 #include <Library/UefiBootServicesTableLib.h>
     22 #include <Library/UefiRuntimeServicesTableLib.h>
     23 #include <Library/DebugLib.h>
     24 #include <Library/DxeServicesLib.h>
     25 #include <Library/PrintLib.h>
     26 
     27 #include <Protocol/SmmCommunication.h>
     28 #include <Protocol/SmmAccess2.h>
     29 
     30 #include <Guid/MemoryProfile.h>
     31 #include <Guid/PiSmmCommunicationRegionTable.h>
     32 
     33 CHAR8 *mActionString[] = {
     34   "Unknown",
     35   "gBS->AllocatePages",
     36   "gBS->FreePages",
     37   "gBS->AllocatePool",
     38   "gBS->FreePool",
     39 };
     40 
     41 CHAR8 *mSmmActionString[] = {
     42   "SmmUnknown",
     43   "gSmst->SmmAllocatePages",
     44   "gSmst->SmmFreePages",
     45   "gSmst->SmmAllocatePool",
     46   "gSmst->SmmFreePool",
     47 };
     48 
     49 typedef struct {
     50   MEMORY_PROFILE_ACTION  Action;
     51   CHAR8                 *String;
     52 } ACTION_STRING;
     53 
     54 ACTION_STRING mExtActionString[] = {
     55   {MEMORY_PROFILE_ACTION_LIB_ALLOCATE_PAGES,                    "Lib:AllocatePages"},
     56   {MEMORY_PROFILE_ACTION_LIB_ALLOCATE_RUNTIME_PAGES,            "Lib:AllocateRuntimePages"},
     57   {MEMORY_PROFILE_ACTION_LIB_ALLOCATE_RESERVED_PAGES,           "Lib:AllocateReservedPages"},
     58   {MEMORY_PROFILE_ACTION_LIB_FREE_PAGES,                        "Lib:FreePages"},
     59   {MEMORY_PROFILE_ACTION_LIB_ALLOCATE_ALIGNED_PAGES,            "Lib:AllocateAlignedPages"},
     60   {MEMORY_PROFILE_ACTION_LIB_ALLOCATE_ALIGNED_RUNTIME_PAGES,    "Lib:AllocateAlignedRuntimePages"},
     61   {MEMORY_PROFILE_ACTION_LIB_ALLOCATE_ALIGNED_RESERVED_PAGES,   "Lib:AllocateAlignedReservedPages"},
     62   {MEMORY_PROFILE_ACTION_LIB_FREE_ALIGNED_PAGES,                "Lib:FreeAlignedPages"},
     63   {MEMORY_PROFILE_ACTION_LIB_ALLOCATE_POOL,                     "Lib:AllocatePool"},
     64   {MEMORY_PROFILE_ACTION_LIB_ALLOCATE_RUNTIME_POOL,             "Lib:AllocateRuntimePool"},
     65   {MEMORY_PROFILE_ACTION_LIB_ALLOCATE_RESERVED_POOL,            "Lib:AllocateReservedPool"},
     66   {MEMORY_PROFILE_ACTION_LIB_FREE_POOL,                         "Lib:FreePool"},
     67   {MEMORY_PROFILE_ACTION_LIB_ALLOCATE_ZERO_POOL,                "Lib:AllocateZeroPool"},
     68   {MEMORY_PROFILE_ACTION_LIB_ALLOCATE_RUNTIME_ZERO_POOL,        "Lib:AllocateRuntimeZeroPool"},
     69   {MEMORY_PROFILE_ACTION_LIB_ALLOCATE_RESERVED_ZERO_POOL,       "Lib:AllocateReservedZeroPool"},
     70   {MEMORY_PROFILE_ACTION_LIB_ALLOCATE_COPY_POOL,                "Lib:AllocateCopyPool"},
     71   {MEMORY_PROFILE_ACTION_LIB_ALLOCATE_RUNTIME_COPY_POOL,        "Lib:AllocateRuntimeCopyPool"},
     72   {MEMORY_PROFILE_ACTION_LIB_ALLOCATE_RESERVED_COPY_POOL,       "Lib:AllocateReservedCopyPool"},
     73   {MEMORY_PROFILE_ACTION_LIB_REALLOCATE_POOL,                   "Lib:ReallocatePool"},
     74   {MEMORY_PROFILE_ACTION_LIB_REALLOCATE_RUNTIME_POOL,           "Lib:ReallocateRuntimePool"},
     75   {MEMORY_PROFILE_ACTION_LIB_REALLOCATE_RESERVED_POOL,          "Lib:ReallocateReservedPool"},
     76 };
     77 
     78 CHAR8 mUserDefinedActionString[] = {"UserDefined-0x80000000"};
     79 
     80 CHAR8 *mMemoryTypeString[] = {
     81   "EfiReservedMemoryType",
     82   "EfiLoaderCode",
     83   "EfiLoaderData",
     84   "EfiBootServicesCode",
     85   "EfiBootServicesData",
     86   "EfiRuntimeServicesCode",
     87   "EfiRuntimeServicesData",
     88   "EfiConventionalMemory",
     89   "EfiUnusableMemory",
     90   "EfiACPIReclaimMemory",
     91   "EfiACPIMemoryNVS",
     92   "EfiMemoryMappedIO",
     93   "EfiMemoryMappedIOPortSpace",
     94   "EfiPalCode",
     95   "EfiPersistentMemory",
     96   "EfiOSReserved",
     97   "EfiOemReserved",
     98 };
     99 
    100 CHAR8 *mSubsystemString[] = {
    101   "Unknown",
    102   "NATIVE",
    103   "WINDOWS_GUI",
    104   "WINDOWS_CUI",
    105   "Unknown",
    106   "Unknown",
    107   "Unknown",
    108   "POSIX_CUI",
    109   "Unknown",
    110   "WINDOWS_CE_GUI",
    111   "EFI_APPLICATION",
    112   "EFI_BOOT_SERVICE_DRIVER",
    113   "EFI_RUNTIME_DRIVER",
    114   "EFI_ROM",
    115   "XBOX",
    116   "Unknown",
    117 };
    118 
    119 CHAR8 *mFileTypeString[] = {
    120   "Unknown",
    121   "RAW",
    122   "FREEFORM",
    123   "SECURITY_CORE",
    124   "PEI_CORE",
    125   "DXE_CORE",
    126   "PEIM",
    127   "DRIVER",
    128   "COMBINED_PEIM_DRIVER",
    129   "APPLICATION",
    130   "SMM",
    131   "FIRMWARE_VOLUME_IMAGE",
    132   "COMBINED_SMM_DXE",
    133   "SMM_CORE",
    134 };
    135 
    136 #define PROFILE_NAME_STRING_LENGTH  64
    137 CHAR8 mNameString[PROFILE_NAME_STRING_LENGTH + 1];
    138 
    139 //
    140 // Profile summary information
    141 //
    142 #define MEMORY_PROFILE_ALLOC_SUMMARY_INFO_SIGNATURE SIGNATURE_32 ('M','P','A','S')
    143 #define MEMORY_PROFILE_ALLOC_SUMMARY_INFO_REVISION 0x0001
    144 
    145 typedef struct {
    146   MEMORY_PROFILE_COMMON_HEADER  Header;
    147   PHYSICAL_ADDRESS              CallerAddress;
    148   MEMORY_PROFILE_ACTION         Action;
    149   CHAR8                         *ActionString;
    150   UINT32                        AllocateCount;
    151   UINT64                        TotalSize;
    152 } MEMORY_PROFILE_ALLOC_SUMMARY_INFO;
    153 
    154 typedef struct {
    155   UINT32                            Signature;
    156   MEMORY_PROFILE_ALLOC_SUMMARY_INFO AllocSummaryInfo;
    157   LIST_ENTRY                        Link;
    158 } MEMORY_PROFILE_ALLOC_SUMMARY_INFO_DATA;
    159 
    160 typedef struct {
    161   UINT32                        Signature;
    162   MEMORY_PROFILE_DRIVER_INFO    *DriverInfo;
    163   LIST_ENTRY                    *AllocSummaryInfoList;
    164   LIST_ENTRY                    Link;
    165 } MEMORY_PROFILE_DRIVER_SUMMARY_INFO_DATA;
    166 
    167 typedef struct {
    168   UINT32                        Signature;
    169   MEMORY_PROFILE_CONTEXT        *Context;
    170   LIST_ENTRY                    *DriverSummaryInfoList;
    171 } MEMORY_PROFILE_CONTEXT_SUMMARY_DATA;
    172 
    173 LIST_ENTRY  mImageSummaryQueue = INITIALIZE_LIST_HEAD_VARIABLE (mImageSummaryQueue);
    174 MEMORY_PROFILE_CONTEXT_SUMMARY_DATA mMemoryProfileContextSummary;
    175 
    176 /**
    177   Get the file name portion of the Pdb File Name.
    178 
    179   The portion of the Pdb File Name between the last backslash and
    180   either a following period or the end of the string is copied into
    181   AsciiBuffer.  The name is truncated, if necessary, to ensure that
    182   AsciiBuffer is not overrun.
    183 
    184   @param[in]  PdbFileName     Pdb file name.
    185   @param[out] AsciiBuffer     The resultant Ascii File Name.
    186 
    187 **/
    188 VOID
    189 GetShortPdbFileName (
    190   IN  CHAR8     *PdbFileName,
    191   OUT CHAR8     *AsciiBuffer
    192   )
    193 {
    194   UINTN IndexPdb;     // Current work location within a Pdb string.
    195   UINTN IndexBuffer;  // Current work location within a Buffer string.
    196   UINTN StartIndex;
    197   UINTN EndIndex;
    198 
    199   ZeroMem (AsciiBuffer, PROFILE_NAME_STRING_LENGTH + 1);
    200 
    201   if (PdbFileName == NULL) {
    202     AsciiStrnCpyS (AsciiBuffer, PROFILE_NAME_STRING_LENGTH + 1, " ", 1);
    203   } else {
    204     StartIndex = 0;
    205     for (EndIndex = 0; PdbFileName[EndIndex] != 0; EndIndex++);
    206     for (IndexPdb = 0; PdbFileName[IndexPdb] != 0; IndexPdb++) {
    207       if ((PdbFileName[IndexPdb] == '\\') || (PdbFileName[IndexPdb] == '/')) {
    208         StartIndex = IndexPdb + 1;
    209       }
    210 
    211       if (PdbFileName[IndexPdb] == '.') {
    212         EndIndex = IndexPdb;
    213       }
    214     }
    215 
    216     IndexBuffer = 0;
    217     for (IndexPdb = StartIndex; IndexPdb < EndIndex; IndexPdb++) {
    218       AsciiBuffer[IndexBuffer] = PdbFileName[IndexPdb];
    219       IndexBuffer++;
    220       if (IndexBuffer >= PROFILE_NAME_STRING_LENGTH) {
    221         AsciiBuffer[PROFILE_NAME_STRING_LENGTH] = 0;
    222         break;
    223       }
    224     }
    225   }
    226 }
    227 
    228 /**
    229   Get a human readable name for an image.
    230   The following methods will be tried orderly:
    231     1. Image PDB
    232     2. FFS UI section
    233     3. Image GUID
    234 
    235   @param[in] DriverInfo Pointer to memory profile driver info.
    236 
    237   @return The resulting Ascii name string is stored in the mNameString global array.
    238 
    239 **/
    240 CHAR8 *
    241 GetDriverNameString (
    242  IN MEMORY_PROFILE_DRIVER_INFO  *DriverInfo
    243  )
    244 {
    245   EFI_STATUS                  Status;
    246   CHAR16                      *NameString;
    247   UINTN                       StringSize;
    248 
    249   //
    250   // Method 1: Get the name string from image PDB
    251   //
    252   if (DriverInfo->Header.Length > sizeof (MEMORY_PROFILE_DRIVER_INFO)) {
    253     GetShortPdbFileName ((CHAR8 *) (DriverInfo + 1), mNameString);
    254     return mNameString;
    255   }
    256 
    257   if (!IsZeroGuid (&DriverInfo->FileName)) {
    258     //
    259     // Try to get the image's FFS UI section by image GUID
    260     //
    261     NameString = NULL;
    262     StringSize = 0;
    263     Status = GetSectionFromAnyFv (
    264               &DriverInfo->FileName,
    265               EFI_SECTION_USER_INTERFACE,
    266               0,
    267               (VOID **) &NameString,
    268               &StringSize
    269               );
    270     if (!EFI_ERROR (Status)) {
    271       //
    272       // Method 2: Get the name string from FFS UI section
    273       //
    274       if (StrLen (NameString) > PROFILE_NAME_STRING_LENGTH) {
    275         NameString[PROFILE_NAME_STRING_LENGTH] = 0;
    276       }
    277       UnicodeStrToAsciiStrS (NameString, mNameString, sizeof (mNameString));
    278       FreePool (NameString);
    279       return mNameString;
    280     }
    281   }
    282 
    283   //
    284   // Method 3: Get the name string from image GUID
    285   //
    286   AsciiSPrint (mNameString, sizeof (mNameString), "%g", &DriverInfo->FileName);
    287   return mNameString;
    288 }
    289 
    290 /**
    291   Memory type to string.
    292 
    293   @param[in] MemoryType Memory type.
    294 
    295   @return Pointer to string.
    296 
    297 **/
    298 CHAR8 *
    299 ProfileMemoryTypeToStr (
    300   IN EFI_MEMORY_TYPE    MemoryType
    301   )
    302 {
    303   UINTN     Index;
    304 
    305   if ((UINT32) MemoryType >= 0x80000000) {
    306     //
    307     // OS reserved memory type.
    308     //
    309     Index = EfiMaxMemoryType;
    310   } else if ((UINT32) MemoryType >= 0x70000000) {
    311     //
    312     // OEM reserved memory type.
    313     //
    314     Index = EfiMaxMemoryType + 1;
    315   } else {
    316     Index = MemoryType;
    317   }
    318 
    319   return mMemoryTypeString[Index];
    320 }
    321 
    322 /**
    323   Action to string.
    324 
    325   @param[in] Action                     Profile action.
    326   @param[in] UserDefinedActionString    Pointer to user defined action string.
    327   @param[in] IsForSmm                   TRUE  - SMRAM profile.
    328                                         FALSE - UEFI memory profile.
    329 
    330   @return Pointer to string.
    331 
    332 **/
    333 CHAR8 *
    334 ProfileActionToStr (
    335   IN MEMORY_PROFILE_ACTION  Action,
    336   IN CHAR8                  *UserDefinedActionString,
    337   IN BOOLEAN                IsForSmm
    338   )
    339 {
    340   UINTN     Index;
    341   UINTN     ActionStringCount;
    342   CHAR8     **ActionString;
    343 
    344   if (IsForSmm) {
    345     ActionString = mSmmActionString;
    346     ActionStringCount = ARRAY_SIZE (mSmmActionString);
    347   } else {
    348     ActionString = mActionString;
    349     ActionStringCount = ARRAY_SIZE (mActionString);
    350   }
    351 
    352   if ((UINTN) (UINT32) Action < ActionStringCount) {
    353     return ActionString[Action];
    354   }
    355   for (Index = 0; Index < ARRAY_SIZE (mExtActionString); Index++) {
    356     if (mExtActionString[Index].Action == Action) {
    357       return mExtActionString[Index].String;
    358     }
    359   }
    360   if ((Action & MEMORY_PROFILE_ACTION_USER_DEFINED_MASK) != 0) {
    361     if (UserDefinedActionString != NULL) {
    362       return UserDefinedActionString;
    363     }
    364     AsciiSPrint (mUserDefinedActionString, sizeof (mUserDefinedActionString), "UserDefined-0x%08x", Action);
    365     return mUserDefinedActionString;
    366   }
    367 
    368   return ActionString[0];
    369 }
    370 
    371 /**
    372   Dump memory profile allocate information.
    373 
    374   @param[in] DriverInfo         Pointer to memory profile driver info.
    375   @param[in] AllocIndex         Memory profile alloc info index.
    376   @param[in] AllocInfo          Pointer to memory profile alloc info.
    377   @param[in] IsForSmm           TRUE  - SMRAM profile.
    378                                 FALSE - UEFI memory profile.
    379 
    380   @return Pointer to next memory profile alloc info.
    381 
    382 **/
    383 MEMORY_PROFILE_ALLOC_INFO *
    384 DumpMemoryProfileAllocInfo (
    385   IN MEMORY_PROFILE_DRIVER_INFO *DriverInfo,
    386   IN UINTN                      AllocIndex,
    387   IN MEMORY_PROFILE_ALLOC_INFO  *AllocInfo,
    388   IN BOOLEAN                    IsForSmm
    389   )
    390 {
    391   CHAR8     *ActionString;
    392 
    393   if (AllocInfo->Header.Signature != MEMORY_PROFILE_ALLOC_INFO_SIGNATURE) {
    394     return NULL;
    395   }
    396 
    397   if (AllocInfo->ActionStringOffset != 0) {
    398     ActionString = (CHAR8 *) ((UINTN) AllocInfo + AllocInfo->ActionStringOffset);
    399   } else {
    400     ActionString = NULL;
    401   }
    402 
    403   Print (L"    MEMORY_PROFILE_ALLOC_INFO (0x%x)\n", AllocIndex);
    404   Print (L"      Signature     - 0x%08x\n", AllocInfo->Header.Signature);
    405   Print (L"      Length        - 0x%04x\n", AllocInfo->Header.Length);
    406   Print (L"      Revision      - 0x%04x\n", AllocInfo->Header.Revision);
    407   Print (L"      CallerAddress - 0x%016lx (Offset: 0x%08x)\n", AllocInfo->CallerAddress, (UINTN) (AllocInfo->CallerAddress - DriverInfo->ImageBase));
    408   Print (L"      SequenceId    - 0x%08x\n", AllocInfo->SequenceId);
    409   Print (L"      Action        - 0x%08x (%a)\n", AllocInfo->Action, ProfileActionToStr (AllocInfo->Action, ActionString, IsForSmm));
    410   Print (L"      MemoryType    - 0x%08x (%a)\n", AllocInfo->MemoryType, ProfileMemoryTypeToStr (AllocInfo->MemoryType));
    411   Print (L"      Buffer        - 0x%016lx\n", AllocInfo->Buffer);
    412   Print (L"      Size          - 0x%016lx\n", AllocInfo->Size);
    413 
    414   return (MEMORY_PROFILE_ALLOC_INFO *) ((UINTN) AllocInfo + AllocInfo->Header.Length);
    415 }
    416 
    417 /**
    418   Dump memory profile driver information.
    419 
    420   @param[in] DriverIndex        Memory profile driver info index.
    421   @param[in] DriverInfo         Pointer to memory profile driver info.
    422   @param[in] IsForSmm           TRUE  - SMRAM profile.
    423                                 FALSE - UEFI memory profile.
    424 
    425   @return Pointer to next memory profile driver info.
    426 
    427 **/
    428 MEMORY_PROFILE_DRIVER_INFO *
    429 DumpMemoryProfileDriverInfo (
    430   IN UINTN                      DriverIndex,
    431   IN MEMORY_PROFILE_DRIVER_INFO *DriverInfo,
    432   IN BOOLEAN                    IsForSmm
    433   )
    434 {
    435   UINTN                         TypeIndex;
    436   MEMORY_PROFILE_ALLOC_INFO     *AllocInfo;
    437   UINTN                         AllocIndex;
    438   CHAR8                         *NameString;
    439 
    440   if (DriverInfo->Header.Signature != MEMORY_PROFILE_DRIVER_INFO_SIGNATURE) {
    441     return NULL;
    442   }
    443   Print (L"  MEMORY_PROFILE_DRIVER_INFO (0x%x)\n", DriverIndex);
    444   Print (L"    Signature               - 0x%08x\n", DriverInfo->Header.Signature);
    445   Print (L"    Length                  - 0x%04x\n", DriverInfo->Header.Length);
    446   Print (L"    Revision                - 0x%04x\n", DriverInfo->Header.Revision);
    447   NameString = GetDriverNameString (DriverInfo);
    448   Print (L"    FileName                - %a\n", NameString);
    449   if (DriverInfo->PdbStringOffset != 0) {
    450     Print (L"    Pdb                     - %a\n", (CHAR8 *) ((UINTN) DriverInfo + DriverInfo->PdbStringOffset));
    451   }
    452   Print (L"    ImageBase               - 0x%016lx\n", DriverInfo->ImageBase);
    453   Print (L"    ImageSize               - 0x%016lx\n", DriverInfo->ImageSize);
    454   Print (L"    EntryPoint              - 0x%016lx\n", DriverInfo->EntryPoint);
    455   Print (L"    ImageSubsystem          - 0x%04x (%a)\n", DriverInfo->ImageSubsystem, mSubsystemString[(DriverInfo->ImageSubsystem < sizeof(mSubsystemString)/sizeof(mSubsystemString[0])) ? DriverInfo->ImageSubsystem : 0]);
    456   Print (L"    FileType                - 0x%02x (%a)\n", DriverInfo->FileType, mFileTypeString[(DriverInfo->FileType < sizeof(mFileTypeString)/sizeof(mFileTypeString[0])) ? DriverInfo->FileType : 0]);
    457   Print (L"    CurrentUsage            - 0x%016lx\n", DriverInfo->CurrentUsage);
    458   Print (L"    PeakUsage               - 0x%016lx\n", DriverInfo->PeakUsage);
    459   for (TypeIndex = 0; TypeIndex < sizeof (DriverInfo->CurrentUsageByType) / sizeof (DriverInfo->CurrentUsageByType[0]); TypeIndex++) {
    460     if ((DriverInfo->CurrentUsageByType[TypeIndex] != 0) ||
    461         (DriverInfo->PeakUsageByType[TypeIndex] != 0)) {
    462       Print (L"    CurrentUsage[0x%02x]      - 0x%016lx (%a)\n", TypeIndex, DriverInfo->CurrentUsageByType[TypeIndex], mMemoryTypeString[TypeIndex]);
    463       Print (L"    PeakUsage[0x%02x]         - 0x%016lx (%a)\n", TypeIndex, DriverInfo->PeakUsageByType[TypeIndex], mMemoryTypeString[TypeIndex]);
    464     }
    465   }
    466   Print (L"    AllocRecordCount        - 0x%08x\n", DriverInfo->AllocRecordCount);
    467 
    468   AllocInfo = (MEMORY_PROFILE_ALLOC_INFO *) ((UINTN) DriverInfo + DriverInfo->Header.Length);
    469   for (AllocIndex = 0; AllocIndex < DriverInfo->AllocRecordCount; AllocIndex++) {
    470     AllocInfo = DumpMemoryProfileAllocInfo (DriverInfo, AllocIndex, AllocInfo, IsForSmm);
    471     if (AllocInfo == NULL) {
    472       return NULL;
    473     }
    474   }
    475   return (MEMORY_PROFILE_DRIVER_INFO *) AllocInfo;
    476 }
    477 
    478 /**
    479   Dump memory profile context information.
    480 
    481   @param[in] Context            Pointer to memory profile context.
    482   @param[in] IsForSmm           TRUE  - SMRAM profile.
    483                                 FALSE - UEFI memory profile.
    484 
    485   @return Pointer to the end of memory profile context buffer.
    486 
    487 **/
    488 VOID *
    489 DumpMemoryProfileContext (
    490   IN MEMORY_PROFILE_CONTEXT     *Context,
    491   IN BOOLEAN                    IsForSmm
    492   )
    493 {
    494   UINTN                         TypeIndex;
    495   MEMORY_PROFILE_DRIVER_INFO    *DriverInfo;
    496   UINTN                         DriverIndex;
    497 
    498   if (Context->Header.Signature != MEMORY_PROFILE_CONTEXT_SIGNATURE) {
    499     return NULL;
    500   }
    501   Print (L"MEMORY_PROFILE_CONTEXT\n");
    502   Print (L"  Signature                     - 0x%08x\n", Context->Header.Signature);
    503   Print (L"  Length                        - 0x%04x\n", Context->Header.Length);
    504   Print (L"  Revision                      - 0x%04x\n", Context->Header.Revision);
    505   Print (L"  CurrentTotalUsage             - 0x%016lx\n", Context->CurrentTotalUsage);
    506   Print (L"  PeakTotalUsage                - 0x%016lx\n", Context->PeakTotalUsage);
    507   for (TypeIndex = 0; TypeIndex < sizeof (Context->CurrentTotalUsageByType) / sizeof (Context->CurrentTotalUsageByType[0]); TypeIndex++) {
    508     if ((Context->CurrentTotalUsageByType[TypeIndex] != 0) ||
    509         (Context->PeakTotalUsageByType[TypeIndex] != 0)) {
    510       Print (L"  CurrentTotalUsage[0x%02x]       - 0x%016lx (%a)\n", TypeIndex, Context->CurrentTotalUsageByType[TypeIndex], mMemoryTypeString[TypeIndex]);
    511       Print (L"  PeakTotalUsage[0x%02x]          - 0x%016lx (%a)\n", TypeIndex, Context->PeakTotalUsageByType[TypeIndex], mMemoryTypeString[TypeIndex]);
    512     }
    513   }
    514   Print (L"  TotalImageSize                - 0x%016lx\n", Context->TotalImageSize);
    515   Print (L"  ImageCount                    - 0x%08x\n", Context->ImageCount);
    516   Print (L"  SequenceCount                 - 0x%08x\n", Context->SequenceCount);
    517 
    518   DriverInfo = (MEMORY_PROFILE_DRIVER_INFO *) ((UINTN) Context + Context->Header.Length);
    519   for (DriverIndex = 0; DriverIndex < Context->ImageCount; DriverIndex++) {
    520     DriverInfo = DumpMemoryProfileDriverInfo (DriverIndex, DriverInfo, IsForSmm);
    521     if (DriverInfo == NULL) {
    522       return NULL;
    523     }
    524   }
    525   return (VOID *) DriverInfo;
    526 }
    527 
    528 /**
    529   Dump memory profile descriptor information.
    530 
    531   @param[in] DescriptorIndex    Memory profile descriptor index.
    532   @param[in] Descriptor         Pointer to memory profile descriptor.
    533 
    534   @return Pointer to next memory profile descriptor.
    535 
    536 **/
    537 MEMORY_PROFILE_DESCRIPTOR *
    538 DumpMemoryProfileDescriptor (
    539   IN UINTN                      DescriptorIndex,
    540   IN MEMORY_PROFILE_DESCRIPTOR  *Descriptor
    541   )
    542 {
    543   if (Descriptor->Header.Signature != MEMORY_PROFILE_DESCRIPTOR_SIGNATURE) {
    544     return NULL;
    545   }
    546   Print (L"  MEMORY_PROFILE_DESCRIPTOR (0x%x)\n", DescriptorIndex);
    547   Print (L"    Signature               - 0x%08x\n", Descriptor->Header.Signature);
    548   Print (L"    Length                  - 0x%04x\n", Descriptor->Header.Length);
    549   Print (L"    Revision                - 0x%04x\n", Descriptor->Header.Revision);
    550   Print (L"    Address                 - 0x%016lx\n", Descriptor->Address);
    551   Print (L"    Size                    - 0x%016lx\n", Descriptor->Size);
    552 
    553   return (MEMORY_PROFILE_DESCRIPTOR *) ((UINTN) Descriptor + Descriptor->Header.Length);
    554 }
    555 
    556 /**
    557   Dump memory profile free memory information.
    558 
    559   @param[in] FreeMemory         Pointer to memory profile free memory.
    560 
    561   @return Pointer to the end of memory profile free memory buffer.
    562 
    563 **/
    564 VOID *
    565 DumpMemoryProfileFreeMemory (
    566   IN MEMORY_PROFILE_FREE_MEMORY *FreeMemory
    567   )
    568 {
    569   MEMORY_PROFILE_DESCRIPTOR     *Descriptor;
    570   UINTN                         DescriptorIndex;
    571 
    572   if (FreeMemory->Header.Signature != MEMORY_PROFILE_FREE_MEMORY_SIGNATURE) {
    573     return NULL;
    574   }
    575   Print (L"MEMORY_PROFILE_FREE_MEMORY\n");
    576   Print (L"  Signature                     - 0x%08x\n", FreeMemory->Header.Signature);
    577   Print (L"  Length                        - 0x%04x\n", FreeMemory->Header.Length);
    578   Print (L"  Revision                      - 0x%04x\n", FreeMemory->Header.Revision);
    579   Print (L"  TotalFreeMemoryPages          - 0x%016lx\n", FreeMemory->TotalFreeMemoryPages);
    580   Print (L"  FreeMemoryEntryCount          - 0x%08x\n", FreeMemory->FreeMemoryEntryCount);
    581 
    582   Descriptor = (MEMORY_PROFILE_DESCRIPTOR *) ((UINTN) FreeMemory + FreeMemory->Header.Length);
    583   for (DescriptorIndex = 0; DescriptorIndex < FreeMemory->FreeMemoryEntryCount; DescriptorIndex++) {
    584     Descriptor = DumpMemoryProfileDescriptor (DescriptorIndex, Descriptor);
    585     if (Descriptor == NULL) {
    586       return NULL;
    587     }
    588   }
    589 
    590   return (VOID *) Descriptor;
    591 }
    592 
    593 /**
    594   Dump memory profile memory range information.
    595 
    596   @param[in] MemoryRange        Pointer to memory profile memory range.
    597 
    598   @return Pointer to the end of memory profile memory range buffer.
    599 
    600 **/
    601 VOID *
    602 DumpMemoryProfileMemoryRange (
    603   IN MEMORY_PROFILE_MEMORY_RANGE    *MemoryRange
    604   )
    605 {
    606   MEMORY_PROFILE_DESCRIPTOR     *Descriptor;
    607   UINTN                         DescriptorIndex;
    608 
    609   if (MemoryRange->Header.Signature != MEMORY_PROFILE_MEMORY_RANGE_SIGNATURE) {
    610     return NULL;
    611   }
    612   Print (L"MEMORY_PROFILE_MEMORY_RANGE\n");
    613   Print (L"  Signature                     - 0x%08x\n", MemoryRange->Header.Signature);
    614   Print (L"  Length                        - 0x%04x\n", MemoryRange->Header.Length);
    615   Print (L"  Revision                      - 0x%04x\n", MemoryRange->Header.Revision);
    616   Print (L"  MemoryRangeCount              - 0x%08x\n", MemoryRange->MemoryRangeCount);
    617 
    618   Descriptor = (MEMORY_PROFILE_DESCRIPTOR *) ((UINTN) MemoryRange + MemoryRange->Header.Length);
    619   for (DescriptorIndex = 0; DescriptorIndex < MemoryRange->MemoryRangeCount; DescriptorIndex++) {
    620     Descriptor = DumpMemoryProfileDescriptor (DescriptorIndex, Descriptor);
    621     if (Descriptor == NULL) {
    622       return NULL;
    623     }
    624   }
    625 
    626   return (VOID *) Descriptor;
    627 }
    628 
    629 /**
    630   Scan memory profile by Signature.
    631 
    632   @param[in] ProfileBuffer      Memory profile base address.
    633   @param[in] ProfileSize        Memory profile size.
    634   @param[in] Signature          Signature.
    635 
    636   @return Pointer to the stucture with the signature.
    637 
    638 **/
    639 VOID *
    640 ScanMemoryProfileBySignature (
    641   IN PHYSICAL_ADDRESS           ProfileBuffer,
    642   IN UINT64                     ProfileSize,
    643   IN UINT32                     Signature
    644   )
    645 {
    646   MEMORY_PROFILE_COMMON_HEADER  *CommonHeader;
    647   UINTN                          ProfileEnd;
    648 
    649   ProfileEnd = (UINTN) (ProfileBuffer + ProfileSize);
    650   CommonHeader = (MEMORY_PROFILE_COMMON_HEADER *) (UINTN) ProfileBuffer;
    651   while ((UINTN) CommonHeader < ProfileEnd) {
    652     if (CommonHeader->Signature == Signature) {
    653       //
    654       // Found it.
    655       //
    656       return (VOID *) CommonHeader;
    657     }
    658     if (CommonHeader->Length == 0) {
    659       ASSERT (FALSE);
    660       return NULL;
    661     }
    662     CommonHeader = (MEMORY_PROFILE_COMMON_HEADER *) ((UINTN) CommonHeader + CommonHeader->Length);
    663   }
    664 
    665   return NULL;
    666 }
    667 
    668 /**
    669   Dump memory profile information.
    670 
    671   @param[in] ProfileBuffer      Memory profile base address.
    672   @param[in] ProfileSize        Memory profile size.
    673   @param[in] IsForSmm           TRUE  - SMRAM profile.
    674                                 FALSE - UEFI memory profile.
    675 
    676 **/
    677 VOID
    678 DumpMemoryProfile (
    679   IN PHYSICAL_ADDRESS           ProfileBuffer,
    680   IN UINT64                     ProfileSize,
    681   IN BOOLEAN                    IsForSmm
    682   )
    683 {
    684   MEMORY_PROFILE_CONTEXT        *Context;
    685   MEMORY_PROFILE_FREE_MEMORY    *FreeMemory;
    686   MEMORY_PROFILE_MEMORY_RANGE   *MemoryRange;
    687 
    688   Context = (MEMORY_PROFILE_CONTEXT *) ScanMemoryProfileBySignature (ProfileBuffer, ProfileSize, MEMORY_PROFILE_CONTEXT_SIGNATURE);
    689   if (Context != NULL) {
    690     DumpMemoryProfileContext (Context, IsForSmm);
    691   }
    692 
    693   FreeMemory = (MEMORY_PROFILE_FREE_MEMORY *) ScanMemoryProfileBySignature (ProfileBuffer, ProfileSize, MEMORY_PROFILE_FREE_MEMORY_SIGNATURE);
    694   if (FreeMemory != NULL) {
    695     DumpMemoryProfileFreeMemory (FreeMemory);
    696   }
    697 
    698   MemoryRange = (MEMORY_PROFILE_MEMORY_RANGE *) ScanMemoryProfileBySignature (ProfileBuffer, ProfileSize, MEMORY_PROFILE_MEMORY_RANGE_SIGNATURE);
    699   if (MemoryRange != NULL) {
    700     DumpMemoryProfileMemoryRange (MemoryRange);
    701   }
    702 }
    703 
    704 /**
    705   Get Allocate summary information structure by caller address.
    706 
    707   @param[in] CallerAddress          Caller address.
    708   @param[in] DriverSummaryInfoData  Driver summary information data structure.
    709 
    710   @return Allocate summary information structure by caller address.
    711 
    712 **/
    713 MEMORY_PROFILE_ALLOC_SUMMARY_INFO_DATA *
    714 GetAllocSummaryInfoByCallerAddress (
    715   IN PHYSICAL_ADDRESS                           CallerAddress,
    716   IN MEMORY_PROFILE_DRIVER_SUMMARY_INFO_DATA    *DriverSummaryInfoData
    717   )
    718 {
    719   LIST_ENTRY                                    *AllocSummaryInfoList;
    720   LIST_ENTRY                                    *AllocSummaryLink;
    721   MEMORY_PROFILE_ALLOC_SUMMARY_INFO             *AllocSummaryInfo;
    722   MEMORY_PROFILE_ALLOC_SUMMARY_INFO_DATA        *AllocSummaryInfoData;
    723 
    724   AllocSummaryInfoList = DriverSummaryInfoData->AllocSummaryInfoList;
    725 
    726   for (AllocSummaryLink = AllocSummaryInfoList->ForwardLink;
    727        AllocSummaryLink != AllocSummaryInfoList;
    728        AllocSummaryLink = AllocSummaryLink->ForwardLink) {
    729     AllocSummaryInfoData = CR (
    730                              AllocSummaryLink,
    731                              MEMORY_PROFILE_ALLOC_SUMMARY_INFO_DATA,
    732                              Link,
    733                              MEMORY_PROFILE_ALLOC_SUMMARY_INFO_SIGNATURE
    734                              );
    735     AllocSummaryInfo = &AllocSummaryInfoData->AllocSummaryInfo;
    736     if (AllocSummaryInfo->CallerAddress == CallerAddress) {
    737       return AllocSummaryInfoData;
    738     }
    739   }
    740   return NULL;
    741 }
    742 
    743 /**
    744   Create Allocate summary information structure and
    745   link to Driver summary information data structure.
    746 
    747   @param[in, out] DriverSummaryInfoData Driver summary information data structure.
    748   @param[in]      AllocInfo             Pointer to memory profile alloc info.
    749 
    750   @return Pointer to next memory profile alloc info.
    751 
    752 **/
    753 MEMORY_PROFILE_ALLOC_INFO *
    754 CreateAllocSummaryInfo (
    755   IN OUT MEMORY_PROFILE_DRIVER_SUMMARY_INFO_DATA    *DriverSummaryInfoData,
    756   IN MEMORY_PROFILE_ALLOC_INFO                      *AllocInfo
    757   )
    758 {
    759   MEMORY_PROFILE_ALLOC_SUMMARY_INFO_DATA            *AllocSummaryInfoData;
    760   MEMORY_PROFILE_ALLOC_SUMMARY_INFO                 *AllocSummaryInfo;
    761 
    762   if (AllocInfo->Header.Signature != MEMORY_PROFILE_ALLOC_INFO_SIGNATURE) {
    763     return NULL;
    764   }
    765 
    766   AllocSummaryInfoData = GetAllocSummaryInfoByCallerAddress (AllocInfo->CallerAddress, DriverSummaryInfoData);
    767   if (AllocSummaryInfoData == NULL) {
    768     AllocSummaryInfoData = AllocatePool (sizeof (*AllocSummaryInfoData));
    769     if (AllocSummaryInfoData == NULL) {
    770       return NULL;
    771     }
    772 
    773     AllocSummaryInfoData->Signature = MEMORY_PROFILE_ALLOC_SUMMARY_INFO_SIGNATURE;
    774     AllocSummaryInfo = &AllocSummaryInfoData->AllocSummaryInfo;
    775     AllocSummaryInfo->Header.Signature = MEMORY_PROFILE_ALLOC_SUMMARY_INFO_SIGNATURE;
    776     AllocSummaryInfo->Header.Length    = sizeof (*AllocSummaryInfo);
    777     AllocSummaryInfo->Header.Revision  = MEMORY_PROFILE_ALLOC_SUMMARY_INFO_REVISION;
    778     AllocSummaryInfo->CallerAddress = AllocInfo->CallerAddress;
    779     AllocSummaryInfo->Action        = AllocInfo->Action;
    780     if (AllocInfo->ActionStringOffset != 0) {
    781       AllocSummaryInfo->ActionString = (CHAR8 *) ((UINTN) AllocInfo + AllocInfo->ActionStringOffset);
    782     } else {
    783       AllocSummaryInfo->ActionString  = NULL;
    784     }
    785     AllocSummaryInfo->AllocateCount = 0;
    786     AllocSummaryInfo->TotalSize     = 0;
    787     InsertTailList (DriverSummaryInfoData->AllocSummaryInfoList, &AllocSummaryInfoData->Link);
    788   }
    789   AllocSummaryInfo = &AllocSummaryInfoData->AllocSummaryInfo;
    790   AllocSummaryInfo->AllocateCount ++;
    791   AllocSummaryInfo->TotalSize += AllocInfo->Size;
    792 
    793   return (MEMORY_PROFILE_ALLOC_INFO *) ((UINTN) AllocInfo + AllocInfo->Header.Length);
    794 }
    795 
    796 /**
    797   Create Driver summary information structure and
    798   link to Context summary information data structure.
    799 
    800   @param[in, out] ContextSummaryData    Context summary information data structure.
    801   @param[in]      DriverInfo            Pointer to memory profile driver info.
    802 
    803   @return Pointer to next memory profile driver info.
    804 
    805 **/
    806 MEMORY_PROFILE_DRIVER_INFO *
    807 CreateDriverSummaryInfo (
    808   IN OUT MEMORY_PROFILE_CONTEXT_SUMMARY_DATA    *ContextSummaryData,
    809   IN MEMORY_PROFILE_DRIVER_INFO                 *DriverInfo
    810   )
    811 {
    812   MEMORY_PROFILE_DRIVER_SUMMARY_INFO_DATA       *DriverSummaryInfoData;
    813   MEMORY_PROFILE_ALLOC_INFO                     *AllocInfo;
    814   UINTN                                         AllocIndex;
    815 
    816   if (DriverInfo->Header.Signature != MEMORY_PROFILE_DRIVER_INFO_SIGNATURE) {
    817     return NULL;
    818   }
    819 
    820   DriverSummaryInfoData = AllocatePool (sizeof (*DriverSummaryInfoData) + sizeof (LIST_ENTRY));
    821   if (DriverSummaryInfoData == NULL) {
    822     return NULL;
    823   }
    824   DriverSummaryInfoData->Signature = MEMORY_PROFILE_DRIVER_INFO_SIGNATURE;
    825   DriverSummaryInfoData->DriverInfo = DriverInfo;
    826   DriverSummaryInfoData->AllocSummaryInfoList = (LIST_ENTRY *) (DriverSummaryInfoData + 1);
    827   InitializeListHead (DriverSummaryInfoData->AllocSummaryInfoList);
    828   InsertTailList (ContextSummaryData->DriverSummaryInfoList, &DriverSummaryInfoData->Link);
    829 
    830   AllocInfo = (MEMORY_PROFILE_ALLOC_INFO *) ((UINTN) DriverInfo + DriverInfo->Header.Length);
    831   for (AllocIndex = 0; AllocIndex < DriverInfo->AllocRecordCount; AllocIndex++) {
    832     AllocInfo = CreateAllocSummaryInfo (DriverSummaryInfoData, AllocInfo);
    833     if (AllocInfo == NULL) {
    834       return NULL;
    835     }
    836   }
    837   return (MEMORY_PROFILE_DRIVER_INFO *) AllocInfo;
    838 }
    839 
    840 /**
    841   Create Context summary information structure.
    842 
    843   @param[in] ProfileBuffer      Memory profile base address.
    844   @param[in] ProfileSize        Memory profile size.
    845 
    846   @return Context summary information structure.
    847 
    848 **/
    849 MEMORY_PROFILE_CONTEXT_SUMMARY_DATA *
    850 CreateContextSummaryData (
    851   IN PHYSICAL_ADDRESS           ProfileBuffer,
    852   IN UINT64                     ProfileSize
    853   )
    854 {
    855   MEMORY_PROFILE_CONTEXT        *Context;
    856   MEMORY_PROFILE_DRIVER_INFO    *DriverInfo;
    857   UINTN                         DriverIndex;
    858 
    859   Context = (MEMORY_PROFILE_CONTEXT *) ScanMemoryProfileBySignature (ProfileBuffer, ProfileSize, MEMORY_PROFILE_CONTEXT_SIGNATURE);
    860   if (Context == NULL) {
    861     return NULL;
    862   }
    863 
    864   mMemoryProfileContextSummary.Signature = MEMORY_PROFILE_CONTEXT_SIGNATURE;
    865   mMemoryProfileContextSummary.Context = Context;
    866   mMemoryProfileContextSummary.DriverSummaryInfoList = &mImageSummaryQueue;
    867 
    868   DriverInfo = (MEMORY_PROFILE_DRIVER_INFO *) ((UINTN) Context + Context->Header.Length);
    869   for (DriverIndex = 0; DriverIndex < Context->ImageCount; DriverIndex++) {
    870     DriverInfo = CreateDriverSummaryInfo (&mMemoryProfileContextSummary, DriverInfo);
    871     if (DriverInfo == NULL) {
    872       return NULL;
    873     }
    874   }
    875 
    876   return &mMemoryProfileContextSummary;
    877 }
    878 
    879 /**
    880   Dump Context summary information.
    881 
    882   @param[in] ContextSummaryData Context summary information data.
    883   @param[in] IsForSmm           TRUE  - SMRAM profile.
    884                                 FALSE - UEFI memory profile.
    885 
    886 **/
    887 VOID
    888 DumpContextSummaryData (
    889   IN MEMORY_PROFILE_CONTEXT_SUMMARY_DATA    *ContextSummaryData,
    890   IN BOOLEAN                                IsForSmm
    891   )
    892 {
    893   MEMORY_PROFILE_DRIVER_SUMMARY_INFO_DATA   *DriverSummaryInfoData;
    894   MEMORY_PROFILE_ALLOC_SUMMARY_INFO_DATA    *AllocSummaryInfoData;
    895   LIST_ENTRY                                *DriverSummaryInfoList;
    896   LIST_ENTRY                                *DriverSummaryLink;
    897   LIST_ENTRY                                *AllocSummaryInfoList;
    898   LIST_ENTRY                                *AllocSummaryLink;
    899   MEMORY_PROFILE_DRIVER_INFO                *DriverInfo;
    900   MEMORY_PROFILE_ALLOC_SUMMARY_INFO         *AllocSummaryInfo;
    901   CHAR8                                     *NameString;
    902 
    903   if (ContextSummaryData == NULL) {
    904     return ;
    905   }
    906 
    907   Print (L"\nSummary Data:\n");
    908 
    909   DriverSummaryInfoList = ContextSummaryData->DriverSummaryInfoList;
    910   for (DriverSummaryLink = DriverSummaryInfoList->ForwardLink;
    911        DriverSummaryLink != DriverSummaryInfoList;
    912        DriverSummaryLink = DriverSummaryLink->ForwardLink) {
    913     DriverSummaryInfoData = CR (
    914                               DriverSummaryLink,
    915                               MEMORY_PROFILE_DRIVER_SUMMARY_INFO_DATA,
    916                               Link,
    917                               MEMORY_PROFILE_DRIVER_INFO_SIGNATURE
    918                               );
    919     DriverInfo = DriverSummaryInfoData->DriverInfo;
    920 
    921     NameString = GetDriverNameString (DriverInfo);
    922     Print (L"\nDriver - %a (Usage - 0x%08x)", NameString, DriverInfo->CurrentUsage);
    923     if (DriverInfo->CurrentUsage == 0) {
    924       Print (L"\n");
    925       continue;
    926     }
    927 
    928     if (DriverInfo->PdbStringOffset != 0) {
    929       Print (L" (Pdb - %a)\n", (CHAR8 *) ((UINTN) DriverInfo + DriverInfo->PdbStringOffset));
    930     } else {
    931       Print (L"\n");
    932     }
    933     Print (L"Caller List:\n");
    934     Print(L"  Count            Size                   RVA              Action\n");
    935     Print(L"==========  ==================     ================== (================================)\n");
    936     AllocSummaryInfoList = DriverSummaryInfoData->AllocSummaryInfoList;
    937     for (AllocSummaryLink = AllocSummaryInfoList->ForwardLink;
    938          AllocSummaryLink != AllocSummaryInfoList;
    939          AllocSummaryLink = AllocSummaryLink->ForwardLink) {
    940       AllocSummaryInfoData = CR (
    941                                AllocSummaryLink,
    942                                MEMORY_PROFILE_ALLOC_SUMMARY_INFO_DATA,
    943                                Link,
    944                                MEMORY_PROFILE_ALLOC_SUMMARY_INFO_SIGNATURE
    945                                );
    946       AllocSummaryInfo = &AllocSummaryInfoData->AllocSummaryInfo;
    947 
    948       Print(L"0x%08x  0x%016lx <== 0x%016lx",
    949         AllocSummaryInfo->AllocateCount,
    950         AllocSummaryInfo->TotalSize,
    951         AllocSummaryInfo->CallerAddress - DriverInfo->ImageBase
    952         );
    953       Print (L" (%a)\n", ProfileActionToStr (AllocSummaryInfo->Action, AllocSummaryInfo->ActionString, IsForSmm));
    954     }
    955   }
    956   return ;
    957 }
    958 
    959 /**
    960   Destroy Context summary information.
    961 
    962   @param[in, out] ContextSummaryData    Context summary information data.
    963 
    964 **/
    965 VOID
    966 DestroyContextSummaryData (
    967   IN OUT MEMORY_PROFILE_CONTEXT_SUMMARY_DATA    *ContextSummaryData
    968   )
    969 {
    970   MEMORY_PROFILE_DRIVER_SUMMARY_INFO_DATA       *DriverSummaryInfoData;
    971   MEMORY_PROFILE_ALLOC_SUMMARY_INFO_DATA        *AllocSummaryInfoData;
    972   LIST_ENTRY                                    *DriverSummaryInfoList;
    973   LIST_ENTRY                                    *DriverSummaryLink;
    974   LIST_ENTRY                                    *AllocSummaryInfoList;
    975   LIST_ENTRY                                    *AllocSummaryLink;
    976 
    977   if (ContextSummaryData == NULL) {
    978     return ;
    979   }
    980 
    981   DriverSummaryInfoList = ContextSummaryData->DriverSummaryInfoList;
    982   for (DriverSummaryLink = DriverSummaryInfoList->ForwardLink;
    983        DriverSummaryLink != DriverSummaryInfoList;
    984        ) {
    985     DriverSummaryInfoData = CR (
    986                               DriverSummaryLink,
    987                               MEMORY_PROFILE_DRIVER_SUMMARY_INFO_DATA,
    988                               Link,
    989                               MEMORY_PROFILE_DRIVER_INFO_SIGNATURE
    990                               );
    991     DriverSummaryLink = DriverSummaryLink->ForwardLink;
    992 
    993     AllocSummaryInfoList = DriverSummaryInfoData->AllocSummaryInfoList;
    994     for (AllocSummaryLink = AllocSummaryInfoList->ForwardLink;
    995          AllocSummaryLink != AllocSummaryInfoList;
    996          ) {
    997       AllocSummaryInfoData = CR (
    998                                AllocSummaryLink,
    999                                MEMORY_PROFILE_ALLOC_SUMMARY_INFO_DATA,
   1000                                Link,
   1001                                MEMORY_PROFILE_ALLOC_SUMMARY_INFO_SIGNATURE
   1002                                );
   1003       AllocSummaryLink = AllocSummaryLink->ForwardLink;
   1004 
   1005       RemoveEntryList (&AllocSummaryInfoData->Link);
   1006       FreePool (AllocSummaryInfoData);
   1007     }
   1008 
   1009     RemoveEntryList (&DriverSummaryInfoData->Link);
   1010     FreePool (DriverSummaryInfoData);
   1011   }
   1012   return ;
   1013 }
   1014 
   1015 /**
   1016   Get and dump UEFI memory profile data.
   1017 
   1018   @return EFI_SUCCESS   Get the memory profile data successfully.
   1019   @return other         Fail to get the memory profile data.
   1020 
   1021 **/
   1022 EFI_STATUS
   1023 GetUefiMemoryProfileData (
   1024   VOID
   1025   )
   1026 {
   1027   EFI_STATUS                          Status;
   1028   EDKII_MEMORY_PROFILE_PROTOCOL       *ProfileProtocol;
   1029   VOID                                *Data;
   1030   UINT64                              Size;
   1031   MEMORY_PROFILE_CONTEXT_SUMMARY_DATA *MemoryProfileContextSummaryData;
   1032   BOOLEAN                             RecordingState;
   1033 
   1034   Status = gBS->LocateProtocol (&gEdkiiMemoryProfileGuid, NULL, (VOID **) &ProfileProtocol);
   1035   if (EFI_ERROR (Status)) {
   1036     DEBUG ((EFI_D_ERROR, "UefiMemoryProfile: Locate MemoryProfile protocol - %r\n", Status));
   1037     return Status;
   1038   }
   1039 
   1040   //
   1041   // Set recording state if needed.
   1042   //
   1043   RecordingState = MEMORY_PROFILE_RECORDING_DISABLE;
   1044   Status = ProfileProtocol->GetRecordingState (ProfileProtocol, &RecordingState);
   1045   if (RecordingState == MEMORY_PROFILE_RECORDING_ENABLE) {
   1046     ProfileProtocol->SetRecordingState (ProfileProtocol, MEMORY_PROFILE_RECORDING_DISABLE);
   1047   }
   1048 
   1049   Size = 0;
   1050   Data = NULL;
   1051   Status = ProfileProtocol->GetData (
   1052                               ProfileProtocol,
   1053                               &Size,
   1054                               Data
   1055                               );
   1056   if (Status != EFI_BUFFER_TOO_SMALL) {
   1057     Print (L"UefiMemoryProfile: GetData - %r\n", Status);
   1058     goto Done;
   1059   }
   1060 
   1061   Data = AllocateZeroPool ((UINTN) Size);
   1062   if (Data == NULL) {
   1063     Status = EFI_OUT_OF_RESOURCES;
   1064     Print (L"UefiMemoryProfile: AllocateZeroPool (0x%x) - %r\n", Size, Status);
   1065     return Status;
   1066   }
   1067 
   1068   Status = ProfileProtocol->GetData (
   1069                               ProfileProtocol,
   1070                               &Size,
   1071                               Data
   1072                               );
   1073   if (EFI_ERROR (Status)) {
   1074     Print (L"UefiMemoryProfile: GetData - %r\n", Status);
   1075     goto Done;
   1076   }
   1077 
   1078 
   1079   Print (L"UefiMemoryProfileSize - 0x%x\n", Size);
   1080   Print (L"======= UefiMemoryProfile begin =======\n");
   1081   DumpMemoryProfile ((PHYSICAL_ADDRESS) (UINTN) Data, Size, FALSE);
   1082 
   1083   //
   1084   // Dump summary information
   1085   //
   1086   MemoryProfileContextSummaryData = CreateContextSummaryData ((PHYSICAL_ADDRESS) (UINTN) Data, Size);
   1087   if (MemoryProfileContextSummaryData != NULL) {
   1088     DumpContextSummaryData (MemoryProfileContextSummaryData, FALSE);
   1089     DestroyContextSummaryData (MemoryProfileContextSummaryData);
   1090   }
   1091 
   1092   Print (L"======= UefiMemoryProfile end =======\n\n\n");
   1093 
   1094 Done:
   1095   if (Data != NULL) {
   1096     FreePool (Data);
   1097   }
   1098 
   1099   //
   1100   // Restore recording state if needed.
   1101   //
   1102   if (RecordingState == MEMORY_PROFILE_RECORDING_ENABLE) {
   1103     ProfileProtocol->SetRecordingState (ProfileProtocol, MEMORY_PROFILE_RECORDING_ENABLE);
   1104   }
   1105 
   1106   return Status;
   1107 }
   1108 
   1109 /**
   1110   Get and dump SMRAM profile data.
   1111 
   1112   @return EFI_SUCCESS   Get the SMRAM profile data successfully.
   1113   @return other         Fail to get the SMRAM profile data.
   1114 
   1115 **/
   1116 EFI_STATUS
   1117 GetSmramProfileData (
   1118   VOID
   1119   )
   1120 {
   1121   EFI_STATUS                                    Status;
   1122   UINTN                                         CommSize;
   1123   UINT8                                         *CommBuffer;
   1124   EFI_SMM_COMMUNICATE_HEADER                    *CommHeader;
   1125   SMRAM_PROFILE_PARAMETER_GET_PROFILE_INFO      *CommGetProfileInfo;
   1126   SMRAM_PROFILE_PARAMETER_GET_PROFILE_DATA_BY_OFFSET *CommGetProfileData;
   1127   SMRAM_PROFILE_PARAMETER_RECORDING_STATE       *CommRecordingState;
   1128   UINTN                                         ProfileSize;
   1129   VOID                                          *ProfileBuffer;
   1130   EFI_SMM_COMMUNICATION_PROTOCOL                *SmmCommunication;
   1131   UINTN                                         MinimalSizeNeeded;
   1132   EDKII_PI_SMM_COMMUNICATION_REGION_TABLE       *PiSmmCommunicationRegionTable;
   1133   UINT32                                        Index;
   1134   EFI_MEMORY_DESCRIPTOR                         *Entry;
   1135   VOID                                          *Buffer;
   1136   UINTN                                         Size;
   1137   UINTN                                         Offset;
   1138   MEMORY_PROFILE_CONTEXT_SUMMARY_DATA           *MemoryProfileContextSummaryData;
   1139   BOOLEAN                                       RecordingState;
   1140 
   1141   ProfileBuffer = NULL;
   1142 
   1143   Status = gBS->LocateProtocol (&gEfiSmmCommunicationProtocolGuid, NULL, (VOID **) &SmmCommunication);
   1144   if (EFI_ERROR (Status)) {
   1145     DEBUG ((EFI_D_ERROR, "SmramProfile: Locate SmmCommunication protocol - %r\n", Status));
   1146     return Status;
   1147   }
   1148 
   1149   MinimalSizeNeeded = sizeof (EFI_GUID) +
   1150                       sizeof (UINTN) +
   1151                       MAX (sizeof (SMRAM_PROFILE_PARAMETER_GET_PROFILE_INFO),
   1152                            MAX (sizeof (SMRAM_PROFILE_PARAMETER_GET_PROFILE_DATA_BY_OFFSET),
   1153                                 sizeof (SMRAM_PROFILE_PARAMETER_RECORDING_STATE)));
   1154   MinimalSizeNeeded += MAX (sizeof (MEMORY_PROFILE_CONTEXT),
   1155                             MAX (sizeof (MEMORY_PROFILE_DRIVER_INFO),
   1156                                  MAX (sizeof (MEMORY_PROFILE_ALLOC_INFO),
   1157                                       MAX (sizeof (MEMORY_PROFILE_DESCRIPTOR),
   1158                                            MAX (sizeof (MEMORY_PROFILE_FREE_MEMORY),
   1159                                                 sizeof (MEMORY_PROFILE_MEMORY_RANGE))))));
   1160 
   1161   Status = EfiGetSystemConfigurationTable (
   1162              &gEdkiiPiSmmCommunicationRegionTableGuid,
   1163              (VOID **) &PiSmmCommunicationRegionTable
   1164              );
   1165   if (EFI_ERROR (Status)) {
   1166     DEBUG ((EFI_D_ERROR, "SmramProfile: Get PiSmmCommunicationRegionTable - %r\n", Status));
   1167     return Status;
   1168   }
   1169   ASSERT (PiSmmCommunicationRegionTable != NULL);
   1170   Entry = (EFI_MEMORY_DESCRIPTOR *) (PiSmmCommunicationRegionTable + 1);
   1171   Size = 0;
   1172   for (Index = 0; Index < PiSmmCommunicationRegionTable->NumberOfEntries; Index++) {
   1173     if (Entry->Type == EfiConventionalMemory) {
   1174       Size = EFI_PAGES_TO_SIZE ((UINTN) Entry->NumberOfPages);
   1175       if (Size >= MinimalSizeNeeded) {
   1176         break;
   1177       }
   1178     }
   1179     Entry = (EFI_MEMORY_DESCRIPTOR *) ((UINT8 *) Entry + PiSmmCommunicationRegionTable->DescriptorSize);
   1180   }
   1181   ASSERT (Index < PiSmmCommunicationRegionTable->NumberOfEntries);
   1182   CommBuffer = (UINT8 *) (UINTN) Entry->PhysicalStart;
   1183 
   1184   //
   1185   // Set recording state if needed.
   1186   //
   1187   RecordingState = MEMORY_PROFILE_RECORDING_DISABLE;
   1188 
   1189   CommHeader = (EFI_SMM_COMMUNICATE_HEADER *) &CommBuffer[0];
   1190   CopyMem (&CommHeader->HeaderGuid, &gEdkiiMemoryProfileGuid, sizeof (gEdkiiMemoryProfileGuid));
   1191   CommHeader->MessageLength = sizeof (SMRAM_PROFILE_PARAMETER_RECORDING_STATE);
   1192 
   1193   CommRecordingState = (SMRAM_PROFILE_PARAMETER_RECORDING_STATE *) &CommBuffer[OFFSET_OF (EFI_SMM_COMMUNICATE_HEADER, Data)];
   1194   CommRecordingState->Header.Command      = SMRAM_PROFILE_COMMAND_GET_RECORDING_STATE;
   1195   CommRecordingState->Header.DataLength   = sizeof (*CommRecordingState);
   1196   CommRecordingState->Header.ReturnStatus = (UINT64)-1;
   1197   CommRecordingState->RecordingState      = MEMORY_PROFILE_RECORDING_DISABLE;
   1198 
   1199   CommSize = sizeof (EFI_GUID) + sizeof (UINTN) + CommHeader->MessageLength;
   1200   Status = SmmCommunication->Communicate (SmmCommunication, CommBuffer, &CommSize);
   1201   if (EFI_ERROR (Status)) {
   1202     DEBUG ((EFI_D_ERROR, "SmramProfile: SmmCommunication - %r\n", Status));
   1203     return Status;
   1204   }
   1205 
   1206   if (CommRecordingState->Header.ReturnStatus != 0) {
   1207     Print (L"SmramProfile: GetRecordingState - 0x%0x\n", CommRecordingState->Header.ReturnStatus);
   1208     return EFI_SUCCESS;
   1209   }
   1210   RecordingState = CommRecordingState->RecordingState;
   1211   if (RecordingState == MEMORY_PROFILE_RECORDING_ENABLE) {
   1212     CommHeader = (EFI_SMM_COMMUNICATE_HEADER *) &CommBuffer[0];
   1213     CopyMem (&CommHeader->HeaderGuid, &gEdkiiMemoryProfileGuid, sizeof (gEdkiiMemoryProfileGuid));
   1214     CommHeader->MessageLength = sizeof (SMRAM_PROFILE_PARAMETER_RECORDING_STATE);
   1215 
   1216     CommRecordingState = (SMRAM_PROFILE_PARAMETER_RECORDING_STATE *) &CommBuffer[OFFSET_OF (EFI_SMM_COMMUNICATE_HEADER, Data)];
   1217     CommRecordingState->Header.Command      = SMRAM_PROFILE_COMMAND_SET_RECORDING_STATE;
   1218     CommRecordingState->Header.DataLength   = sizeof (*CommRecordingState);
   1219     CommRecordingState->Header.ReturnStatus = (UINT64)-1;
   1220     CommRecordingState->RecordingState      = MEMORY_PROFILE_RECORDING_DISABLE;
   1221 
   1222     CommSize = sizeof (EFI_GUID) + sizeof (UINTN) + CommHeader->MessageLength;
   1223     SmmCommunication->Communicate (SmmCommunication, CommBuffer, &CommSize);
   1224   }
   1225 
   1226   //
   1227   // Get Size
   1228   //
   1229   CommHeader = (EFI_SMM_COMMUNICATE_HEADER *) &CommBuffer[0];
   1230   CopyMem (&CommHeader->HeaderGuid, &gEdkiiMemoryProfileGuid, sizeof (gEdkiiMemoryProfileGuid));
   1231   CommHeader->MessageLength = sizeof (SMRAM_PROFILE_PARAMETER_GET_PROFILE_INFO);
   1232 
   1233   CommGetProfileInfo = (SMRAM_PROFILE_PARAMETER_GET_PROFILE_INFO *) &CommBuffer[OFFSET_OF (EFI_SMM_COMMUNICATE_HEADER, Data)];
   1234   CommGetProfileInfo->Header.Command      = SMRAM_PROFILE_COMMAND_GET_PROFILE_INFO;
   1235   CommGetProfileInfo->Header.DataLength   = sizeof (*CommGetProfileInfo);
   1236   CommGetProfileInfo->Header.ReturnStatus = (UINT64)-1;
   1237   CommGetProfileInfo->ProfileSize         = 0;
   1238 
   1239   CommSize = sizeof (EFI_GUID) + sizeof (UINTN) + CommHeader->MessageLength;
   1240   Status = SmmCommunication->Communicate (SmmCommunication, CommBuffer, &CommSize);
   1241   ASSERT_EFI_ERROR (Status);
   1242 
   1243   if (CommGetProfileInfo->Header.ReturnStatus != 0) {
   1244     Status = EFI_SUCCESS;
   1245     Print (L"SmramProfile: GetProfileInfo - 0x%0x\n", CommGetProfileInfo->Header.ReturnStatus);
   1246     goto Done;
   1247   }
   1248 
   1249   ProfileSize = (UINTN) CommGetProfileInfo->ProfileSize;
   1250 
   1251   //
   1252   // Get Data
   1253   //
   1254   ProfileBuffer = AllocateZeroPool (ProfileSize);
   1255   if (ProfileBuffer == NULL) {
   1256     Status = EFI_OUT_OF_RESOURCES;
   1257     Print (L"SmramProfile: AllocateZeroPool (0x%x) for profile buffer - %r\n", ProfileSize, Status);
   1258     goto Done;
   1259   }
   1260 
   1261   CommHeader = (EFI_SMM_COMMUNICATE_HEADER *) &CommBuffer[0];
   1262   CopyMem (&CommHeader->HeaderGuid, &gEdkiiMemoryProfileGuid, sizeof(gEdkiiMemoryProfileGuid));
   1263   CommHeader->MessageLength = sizeof (SMRAM_PROFILE_PARAMETER_GET_PROFILE_DATA_BY_OFFSET);
   1264 
   1265   CommGetProfileData = (SMRAM_PROFILE_PARAMETER_GET_PROFILE_DATA_BY_OFFSET *) &CommBuffer[OFFSET_OF (EFI_SMM_COMMUNICATE_HEADER, Data)];
   1266   CommGetProfileData->Header.Command      = SMRAM_PROFILE_COMMAND_GET_PROFILE_DATA_BY_OFFSET;
   1267   CommGetProfileData->Header.DataLength   = sizeof (*CommGetProfileData);
   1268   CommGetProfileData->Header.ReturnStatus = (UINT64)-1;
   1269 
   1270   CommSize = sizeof (EFI_GUID) + sizeof (UINTN) + CommHeader->MessageLength;
   1271   Buffer = (UINT8 *) CommHeader + CommSize;
   1272   Size -= CommSize;
   1273 
   1274   CommGetProfileData->ProfileBuffer       = (PHYSICAL_ADDRESS) (UINTN) Buffer;
   1275   CommGetProfileData->ProfileOffset       = 0;
   1276   while (CommGetProfileData->ProfileOffset < ProfileSize) {
   1277     Offset = (UINTN) CommGetProfileData->ProfileOffset;
   1278     if (Size <= (ProfileSize - CommGetProfileData->ProfileOffset)) {
   1279       CommGetProfileData->ProfileSize = (UINT64) Size;
   1280     } else {
   1281       CommGetProfileData->ProfileSize = (UINT64) (ProfileSize - CommGetProfileData->ProfileOffset);
   1282     }
   1283     Status = SmmCommunication->Communicate (SmmCommunication, CommBuffer, &CommSize);
   1284     ASSERT_EFI_ERROR (Status);
   1285 
   1286     if (CommGetProfileData->Header.ReturnStatus != 0) {
   1287       Status = EFI_SUCCESS;
   1288       Print (L"GetProfileData - 0x%x\n", CommGetProfileData->Header.ReturnStatus);
   1289       goto Done;
   1290     }
   1291     CopyMem ((UINT8 *) ProfileBuffer + Offset, (VOID *) (UINTN) CommGetProfileData->ProfileBuffer, (UINTN) CommGetProfileData->ProfileSize);
   1292   }
   1293 
   1294 
   1295   Print (L"SmramProfileSize - 0x%x\n", ProfileSize);
   1296   Print (L"======= SmramProfile begin =======\n");
   1297   DumpMemoryProfile ((PHYSICAL_ADDRESS) (UINTN) ProfileBuffer, ProfileSize, TRUE);
   1298 
   1299   //
   1300   // Dump summary information
   1301   //
   1302   MemoryProfileContextSummaryData = CreateContextSummaryData ((PHYSICAL_ADDRESS) (UINTN) ProfileBuffer, ProfileSize);
   1303   if (MemoryProfileContextSummaryData != NULL) {
   1304     DumpContextSummaryData (MemoryProfileContextSummaryData, TRUE);
   1305     DestroyContextSummaryData (MemoryProfileContextSummaryData);
   1306   }
   1307 
   1308   Print (L"======= SmramProfile end =======\n\n\n");
   1309 
   1310 Done:
   1311   if (ProfileBuffer != NULL) {
   1312     FreePool (ProfileBuffer);
   1313   }
   1314 
   1315   //
   1316   // Restore recording state if needed.
   1317   //
   1318   if (RecordingState == MEMORY_PROFILE_RECORDING_ENABLE) {
   1319     CommHeader = (EFI_SMM_COMMUNICATE_HEADER *) &CommBuffer[0];
   1320     CopyMem (&CommHeader->HeaderGuid, &gEdkiiMemoryProfileGuid, sizeof (gEdkiiMemoryProfileGuid));
   1321     CommHeader->MessageLength = sizeof (SMRAM_PROFILE_PARAMETER_RECORDING_STATE);
   1322 
   1323     CommRecordingState = (SMRAM_PROFILE_PARAMETER_RECORDING_STATE *) &CommBuffer[OFFSET_OF (EFI_SMM_COMMUNICATE_HEADER, Data)];
   1324     CommRecordingState->Header.Command      = SMRAM_PROFILE_COMMAND_SET_RECORDING_STATE;
   1325     CommRecordingState->Header.DataLength   = sizeof (*CommRecordingState);
   1326     CommRecordingState->Header.ReturnStatus = (UINT64)-1;
   1327     CommRecordingState->RecordingState      = MEMORY_PROFILE_RECORDING_ENABLE;
   1328 
   1329     CommSize = sizeof (EFI_GUID) + sizeof (UINTN) + CommHeader->MessageLength;
   1330     SmmCommunication->Communicate (SmmCommunication, CommBuffer, &CommSize);
   1331   }
   1332 
   1333   return Status;
   1334 }
   1335 
   1336 /**
   1337   The user Entry Point for Application. The user code starts with this function
   1338   as the real entry point for the image goes into a library that calls this function.
   1339 
   1340   @param[in] ImageHandle    The firmware allocated handle for the EFI image.
   1341   @param[in] SystemTable    A pointer to the EFI System Table.
   1342 
   1343   @retval EFI_SUCCESS       The entry point is executed successfully.
   1344   @retval other             Some error occurs when executing this entry point.
   1345 
   1346 **/
   1347 EFI_STATUS
   1348 EFIAPI
   1349 UefiMain (
   1350   IN EFI_HANDLE         ImageHandle,
   1351   IN EFI_SYSTEM_TABLE   *SystemTable
   1352   )
   1353 {
   1354   EFI_STATUS                     Status;
   1355 
   1356   Status = GetUefiMemoryProfileData ();
   1357   if (EFI_ERROR (Status)) {
   1358     DEBUG ((EFI_D_ERROR, "GetUefiMemoryProfileData - %r\n", Status));
   1359   }
   1360 
   1361   Status = GetSmramProfileData ();
   1362   if (EFI_ERROR (Status)) {
   1363     DEBUG ((EFI_D_ERROR, "GetSmramProfileData - %r\n", Status));
   1364   }
   1365 
   1366   return EFI_SUCCESS;
   1367 }
   1368