Home | History | Annotate | Download | only in MemoryProfileInfo
      1 /** @file
      2 
      3   Copyright (c) 2014 - 2015, 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/PeCoffGetEntryPointLib.h>
     26 #include <Library/PrintLib.h>
     27 
     28 #include <Protocol/SmmCommunication.h>
     29 #include <Protocol/SmmAccess2.h>
     30 
     31 #include <Guid/ZeroGuid.h>
     32 #include <Guid/MemoryProfile.h>
     33 
     34 CHAR16 *mActionString[] = {
     35   L"Unknown",
     36   L"AllocatePages",
     37   L"FreePages",
     38   L"AllocatePool",
     39   L"FreePool",
     40 };
     41 
     42 CHAR16 *mMemoryTypeString[] = {
     43   L"EfiReservedMemoryType",
     44   L"EfiLoaderCode",
     45   L"EfiLoaderData",
     46   L"EfiBootServicesCode",
     47   L"EfiBootServicesData",
     48   L"EfiRuntimeServicesCode",
     49   L"EfiRuntimeServicesData",
     50   L"EfiConventionalMemory",
     51   L"EfiUnusableMemory",
     52   L"EfiACPIReclaimMemory",
     53   L"EfiACPIMemoryNVS",
     54   L"EfiMemoryMappedIO",
     55   L"EfiMemoryMappedIOPortSpace",
     56   L"EfiPalCode",
     57   L"EfiPersistentMemory",
     58   L"EfiOSReserved",
     59   L"EfiOemReserved",
     60 };
     61 
     62 CHAR16 *mSubsystemString[] = {
     63   L"Unknown",
     64   L"NATIVE",
     65   L"WINDOWS_GUI",
     66   L"WINDOWS_CUI",
     67   L"Unknown",
     68   L"Unknown",
     69   L"Unknown",
     70   L"POSIX_CUI",
     71   L"Unknown",
     72   L"WINDOWS_CE_GUI",
     73   L"EFI_APPLICATION",
     74   L"EFI_BOOT_SERVICE_DRIVER",
     75   L"EFI_RUNTIME_DRIVER",
     76   L"EFI_ROM",
     77   L"XBOX",
     78   L"Unknown",
     79 };
     80 
     81 CHAR16 *mFileTypeString[] = {
     82   L"Unknown",
     83   L"RAW",
     84   L"FREEFORM",
     85   L"SECURITY_CORE",
     86   L"PEI_CORE",
     87   L"DXE_CORE",
     88   L"PEIM",
     89   L"DRIVER",
     90   L"COMBINED_PEIM_DRIVER",
     91   L"APPLICATION",
     92   L"SMM",
     93   L"FIRMWARE_VOLUME_IMAGE",
     94   L"COMBINED_SMM_DXE",
     95   L"SMM_CORE",
     96 };
     97 
     98 #define PROFILE_NAME_STRING_LENGTH  36
     99 CHAR16 mNameString[PROFILE_NAME_STRING_LENGTH + 1];
    100 
    101 /**
    102   Get the file name portion of the Pdb File Name.
    103 
    104   The portion of the Pdb File Name between the last backslash and
    105   either a following period or the end of the string is converted
    106   to Unicode and copied into UnicodeBuffer.  The name is truncated,
    107   if necessary, to ensure that UnicodeBuffer is not overrun.
    108 
    109   @param[in]  PdbFileName     Pdb file name.
    110   @param[out] UnicodeBuffer   The resultant Unicode File Name.
    111 
    112 **/
    113 VOID
    114 GetShortPdbFileName (
    115   IN  CHAR8     *PdbFileName,
    116   OUT CHAR16    *UnicodeBuffer
    117   )
    118 {
    119   UINTN IndexA;     // Current work location within an ASCII string.
    120   UINTN IndexU;     // Current work location within a Unicode string.
    121   UINTN StartIndex;
    122   UINTN EndIndex;
    123 
    124   ZeroMem (UnicodeBuffer, (PROFILE_NAME_STRING_LENGTH + 1) * sizeof (CHAR16));
    125 
    126   if (PdbFileName == NULL) {
    127     StrnCpyS (UnicodeBuffer, PROFILE_NAME_STRING_LENGTH + 1, L" ", 1);
    128   } else {
    129     StartIndex = 0;
    130     for (EndIndex = 0; PdbFileName[EndIndex] != 0; EndIndex++);
    131     for (IndexA = 0; PdbFileName[IndexA] != 0; IndexA++) {
    132       if (PdbFileName[IndexA] == '\\') {
    133         StartIndex = IndexA + 1;
    134       }
    135 
    136       if (PdbFileName[IndexA] == '.') {
    137         EndIndex = IndexA;
    138       }
    139     }
    140 
    141     IndexU = 0;
    142     for (IndexA = StartIndex; IndexA < EndIndex; IndexA++) {
    143       UnicodeBuffer[IndexU] = (CHAR16) PdbFileName[IndexA];
    144       IndexU++;
    145       if (IndexU >= PROFILE_NAME_STRING_LENGTH) {
    146         UnicodeBuffer[PROFILE_NAME_STRING_LENGTH] = 0;
    147         break;
    148       }
    149     }
    150   }
    151 }
    152 
    153 /**
    154   Get a human readable name for an image.
    155   The following methods will be tried orderly:
    156     1. Image PDB
    157     2. FFS UI section
    158     3. Image GUID
    159 
    160   @param[in] DriverInfo Pointer to memory profile driver info.
    161 
    162   @post The resulting Unicode name string is stored in the mNameString global array.
    163 
    164 **/
    165 VOID
    166 GetDriverNameString (
    167  IN MEMORY_PROFILE_DRIVER_INFO  *DriverInfo
    168  )
    169 {
    170   EFI_STATUS                  Status;
    171   CHAR8                       *PdbFileName;
    172   CHAR16                      *NameString;
    173   UINTN                       StringSize;
    174 
    175   //
    176   // Method 1: Get the name string from image PDB
    177   //
    178   if ((DriverInfo->ImageBase != 0) && (DriverInfo->FileType != EFI_FV_FILETYPE_SMM) && (DriverInfo->FileType != EFI_FV_FILETYPE_SMM_CORE)) {
    179     PdbFileName = PeCoffLoaderGetPdbPointer ((VOID *) (UINTN) DriverInfo->ImageBase);
    180 
    181     if (PdbFileName != NULL) {
    182       GetShortPdbFileName (PdbFileName, mNameString);
    183       return;
    184     }
    185   }
    186 
    187   if (!CompareGuid (&DriverInfo->FileName, &gZeroGuid)) {
    188     //
    189     // Try to get the image's FFS UI section by image GUID
    190     //
    191     NameString = NULL;
    192     StringSize = 0;
    193     Status = GetSectionFromAnyFv (
    194               &DriverInfo->FileName,
    195               EFI_SECTION_USER_INTERFACE,
    196               0,
    197               (VOID **) &NameString,
    198               &StringSize
    199               );
    200     if (!EFI_ERROR (Status)) {
    201       //
    202       // Method 2: Get the name string from FFS UI section
    203       //
    204       StrnCpyS (mNameString, PROFILE_NAME_STRING_LENGTH + 1, NameString, PROFILE_NAME_STRING_LENGTH);
    205       mNameString[PROFILE_NAME_STRING_LENGTH] = 0;
    206       FreePool (NameString);
    207       return;
    208     }
    209   }
    210 
    211   //
    212   // Method 3: Get the name string from image GUID
    213   //
    214   UnicodeSPrint (mNameString, sizeof (mNameString), L"%g", &DriverInfo->FileName);
    215 }
    216 
    217 /**
    218   Memory type to string.
    219 
    220   @param[in] MemoryType Memory type.
    221 
    222   @return Pointer to string.
    223 
    224 **/
    225 CHAR16 *
    226 ProfileMemoryTypeToStr (
    227   IN EFI_MEMORY_TYPE    MemoryType
    228   )
    229 {
    230   UINTN     Index;
    231 
    232   if ((UINT32) MemoryType >= 0x80000000) {
    233     //
    234     // OS reserved memory type.
    235     //
    236     Index = EfiMaxMemoryType;
    237   } else if ((UINT32) MemoryType >= 0x70000000) {
    238     //
    239     // OEM reserved memory type.
    240     //
    241     Index = EfiMaxMemoryType + 1;
    242   } else {
    243     Index = MemoryType;
    244   }
    245 
    246   return mMemoryTypeString[Index];
    247 }
    248 
    249 /**
    250   Dump memory profile allocate information.
    251 
    252   @param[in] DriverInfo         Pointer to memory profile driver info.
    253   @param[in] AllocIndex         Memory profile alloc info index.
    254   @param[in] AllocInfo          Pointer to memory profile alloc info.
    255 
    256   @return Pointer to next memory profile alloc info.
    257 
    258 **/
    259 MEMORY_PROFILE_ALLOC_INFO *
    260 DumpMemoryProfileAllocInfo (
    261   IN MEMORY_PROFILE_DRIVER_INFO *DriverInfo,
    262   IN UINTN                      AllocIndex,
    263   IN MEMORY_PROFILE_ALLOC_INFO  *AllocInfo
    264   )
    265 {
    266   if (AllocInfo->Header.Signature != MEMORY_PROFILE_ALLOC_INFO_SIGNATURE) {
    267     return NULL;
    268   }
    269   Print (L"    MEMORY_PROFILE_ALLOC_INFO (0x%x)\n", AllocIndex);
    270   Print (L"      Signature     - 0x%08x\n", AllocInfo->Header.Signature);
    271   Print (L"      Length        - 0x%04x\n", AllocInfo->Header.Length);
    272   Print (L"      Revision      - 0x%04x\n", AllocInfo->Header.Revision);
    273   Print (L"      CallerAddress - 0x%016lx (Offset: 0x%08x)\n", AllocInfo->CallerAddress, (UINTN) (AllocInfo->CallerAddress - DriverInfo->ImageBase));
    274   Print (L"      SequenceId    - 0x%08x\n", AllocInfo->SequenceId);
    275   Print (L"      Action        - 0x%08x (%s)\n", AllocInfo->Action, mActionString[(AllocInfo->Action < sizeof(mActionString)/sizeof(mActionString[0])) ? AllocInfo->Action : 0]);
    276   Print (L"      MemoryType    - 0x%08x (%s)\n", AllocInfo->MemoryType, ProfileMemoryTypeToStr (AllocInfo->MemoryType));
    277   Print (L"      Buffer        - 0x%016lx\n", AllocInfo->Buffer);
    278   Print (L"      Size          - 0x%016lx\n", AllocInfo->Size);
    279 
    280   return (MEMORY_PROFILE_ALLOC_INFO *) ((UINTN) AllocInfo + AllocInfo->Header.Length);
    281 }
    282 
    283 /**
    284   Dump memory profile driver information.
    285 
    286   @param[in] DriverIndex        Memory profile driver info index.
    287   @param[in] DriverInfo         Pointer to memory profile driver info.
    288 
    289   @return Pointer to next memory profile driver info.
    290 
    291 **/
    292 MEMORY_PROFILE_DRIVER_INFO *
    293 DumpMemoryProfileDriverInfo (
    294   IN UINTN                      DriverIndex,
    295   IN MEMORY_PROFILE_DRIVER_INFO *DriverInfo
    296   )
    297 {
    298   UINTN                         TypeIndex;
    299   MEMORY_PROFILE_ALLOC_INFO     *AllocInfo;
    300   UINTN                         AllocIndex;
    301 
    302   if (DriverInfo->Header.Signature != MEMORY_PROFILE_DRIVER_INFO_SIGNATURE) {
    303     return NULL;
    304   }
    305   Print (L"  MEMORY_PROFILE_DRIVER_INFO (0x%x)\n", DriverIndex);
    306   Print (L"    Signature               - 0x%08x\n", DriverInfo->Header.Signature);
    307   Print (L"    Length                  - 0x%04x\n", DriverInfo->Header.Length);
    308   Print (L"    Revision                - 0x%04x\n", DriverInfo->Header.Revision);
    309   GetDriverNameString (DriverInfo);
    310   Print (L"    FileName                - %s\n", &mNameString);
    311   Print (L"    ImageBase               - 0x%016lx\n", DriverInfo->ImageBase);
    312   Print (L"    ImageSize               - 0x%016lx\n", DriverInfo->ImageSize);
    313   Print (L"    EntryPoint              - 0x%016lx\n", DriverInfo->EntryPoint);
    314   Print (L"    ImageSubsystem          - 0x%04x (%s)\n", DriverInfo->ImageSubsystem, mSubsystemString[(DriverInfo->ImageSubsystem < sizeof(mSubsystemString)/sizeof(mSubsystemString[0])) ? DriverInfo->ImageSubsystem : 0]);
    315   Print (L"    FileType                - 0x%02x (%s)\n", DriverInfo->FileType, mFileTypeString[(DriverInfo->FileType < sizeof(mFileTypeString)/sizeof(mFileTypeString[0])) ? DriverInfo->FileType : 0]);
    316   Print (L"    CurrentUsage            - 0x%016lx\n", DriverInfo->CurrentUsage);
    317   Print (L"    PeakUsage               - 0x%016lx\n", DriverInfo->PeakUsage);
    318   for (TypeIndex = 0; TypeIndex < sizeof (DriverInfo->CurrentUsageByType) / sizeof (DriverInfo->CurrentUsageByType[0]); TypeIndex++) {
    319     if ((DriverInfo->CurrentUsageByType[TypeIndex] != 0) ||
    320         (DriverInfo->PeakUsageByType[TypeIndex] != 0)) {
    321       Print (L"    CurrentUsage[0x%02x]      - 0x%016lx (%s)\n", TypeIndex, DriverInfo->CurrentUsageByType[TypeIndex], mMemoryTypeString[TypeIndex]);
    322       Print (L"    PeakUsage[0x%02x]         - 0x%016lx (%s)\n", TypeIndex, DriverInfo->PeakUsageByType[TypeIndex], mMemoryTypeString[TypeIndex]);
    323     }
    324   }
    325   Print (L"    AllocRecordCount        - 0x%08x\n", DriverInfo->AllocRecordCount);
    326 
    327   AllocInfo = (MEMORY_PROFILE_ALLOC_INFO *) ((UINTN) DriverInfo + DriverInfo->Header.Length);
    328   for (AllocIndex = 0; AllocIndex < DriverInfo->AllocRecordCount; AllocIndex++) {
    329     AllocInfo = DumpMemoryProfileAllocInfo (DriverInfo, AllocIndex, AllocInfo);
    330     if (AllocInfo == NULL) {
    331       return NULL;
    332     }
    333   }
    334   return (MEMORY_PROFILE_DRIVER_INFO *) AllocInfo;
    335 }
    336 
    337 /**
    338   Dump memory profile context information.
    339 
    340   @param[in] Context            Pointer to memory profile context.
    341 
    342   @return Pointer to the end of memory profile context buffer.
    343 
    344 **/
    345 VOID *
    346 DumpMemoryProfileContext (
    347   IN MEMORY_PROFILE_CONTEXT     *Context
    348   )
    349 {
    350   UINTN                         TypeIndex;
    351   MEMORY_PROFILE_DRIVER_INFO    *DriverInfo;
    352   UINTN                         DriverIndex;
    353 
    354   if (Context->Header.Signature != MEMORY_PROFILE_CONTEXT_SIGNATURE) {
    355     return NULL;
    356   }
    357   Print (L"MEMORY_PROFILE_CONTEXT\n");
    358   Print (L"  Signature                     - 0x%08x\n", Context->Header.Signature);
    359   Print (L"  Length                        - 0x%04x\n", Context->Header.Length);
    360   Print (L"  Revision                      - 0x%04x\n", Context->Header.Revision);
    361   Print (L"  CurrentTotalUsage             - 0x%016lx\n", Context->CurrentTotalUsage);
    362   Print (L"  PeakTotalUsage                - 0x%016lx\n", Context->PeakTotalUsage);
    363   for (TypeIndex = 0; TypeIndex < sizeof (Context->CurrentTotalUsageByType) / sizeof (Context->CurrentTotalUsageByType[0]); TypeIndex++) {
    364     if ((Context->CurrentTotalUsageByType[TypeIndex] != 0) ||
    365         (Context->PeakTotalUsageByType[TypeIndex] != 0)) {
    366       Print (L"  CurrentTotalUsage[0x%02x]       - 0x%016lx (%s)\n", TypeIndex, Context->CurrentTotalUsageByType[TypeIndex], mMemoryTypeString[TypeIndex]);
    367       Print (L"  PeakTotalUsage[0x%02x]          - 0x%016lx (%s)\n", TypeIndex, Context->PeakTotalUsageByType[TypeIndex], mMemoryTypeString[TypeIndex]);
    368     }
    369   }
    370   Print (L"  TotalImageSize                - 0x%016lx\n", Context->TotalImageSize);
    371   Print (L"  ImageCount                    - 0x%08x\n", Context->ImageCount);
    372   Print (L"  SequenceCount                 - 0x%08x\n", Context->SequenceCount);
    373 
    374   DriverInfo = (MEMORY_PROFILE_DRIVER_INFO *) ((UINTN) Context + Context->Header.Length);
    375   for (DriverIndex = 0; DriverIndex < Context->ImageCount; DriverIndex++) {
    376     DriverInfo = DumpMemoryProfileDriverInfo (DriverIndex, DriverInfo);
    377     if (DriverInfo == NULL) {
    378       return NULL;
    379     }
    380   }
    381   return (VOID *) DriverInfo;
    382 }
    383 
    384 /**
    385   Dump memory profile descriptor information.
    386 
    387   @param[in] DescriptorIndex    Memory profile descriptor index.
    388   @param[in] Descriptor         Pointer to memory profile descriptor.
    389 
    390   @return Pointer to next memory profile descriptor.
    391 
    392 **/
    393 MEMORY_PROFILE_DESCRIPTOR *
    394 DumpMemoryProfileDescriptor (
    395   IN UINTN                      DescriptorIndex,
    396   IN MEMORY_PROFILE_DESCRIPTOR  *Descriptor
    397   )
    398 {
    399   if (Descriptor->Header.Signature != MEMORY_PROFILE_DESCRIPTOR_SIGNATURE) {
    400     return NULL;
    401   }
    402   Print (L"  MEMORY_PROFILE_DESCRIPTOR (0x%x)\n", DescriptorIndex);
    403   Print (L"    Signature               - 0x%08x\n", Descriptor->Header.Signature);
    404   Print (L"    Length                  - 0x%04x\n", Descriptor->Header.Length);
    405   Print (L"    Revision                - 0x%04x\n", Descriptor->Header.Revision);
    406   Print (L"    Address                 - 0x%016lx\n", Descriptor->Address);
    407   Print (L"    Size                    - 0x%016lx\n", Descriptor->Size);
    408 
    409   return (MEMORY_PROFILE_DESCRIPTOR *) ((UINTN) Descriptor + Descriptor->Header.Length);
    410 }
    411 
    412 /**
    413   Dump memory profile free memory information.
    414 
    415   @param[in] FreeMemory         Pointer to memory profile free memory.
    416 
    417   @return Pointer to the end of memory profile free memory buffer.
    418 
    419 **/
    420 VOID *
    421 DumpMemoryProfileFreeMemory (
    422   IN MEMORY_PROFILE_FREE_MEMORY *FreeMemory
    423   )
    424 {
    425   MEMORY_PROFILE_DESCRIPTOR     *Descriptor;
    426   UINTN                         DescriptorIndex;
    427 
    428   if (FreeMemory->Header.Signature != MEMORY_PROFILE_FREE_MEMORY_SIGNATURE) {
    429     return NULL;
    430   }
    431   Print (L"MEMORY_PROFILE_FREE_MEMORY\n");
    432   Print (L"  Signature                     - 0x%08x\n", FreeMemory->Header.Signature);
    433   Print (L"  Length                        - 0x%04x\n", FreeMemory->Header.Length);
    434   Print (L"  Revision                      - 0x%04x\n", FreeMemory->Header.Revision);
    435   Print (L"  TotalFreeMemoryPages          - 0x%016lx\n", FreeMemory->TotalFreeMemoryPages);
    436   Print (L"  FreeMemoryEntryCount          - 0x%08x\n", FreeMemory->FreeMemoryEntryCount);
    437 
    438   Descriptor = (MEMORY_PROFILE_DESCRIPTOR *) ((UINTN) FreeMemory + FreeMemory->Header.Length);
    439   for (DescriptorIndex = 0; DescriptorIndex < FreeMemory->FreeMemoryEntryCount; DescriptorIndex++) {
    440     Descriptor = DumpMemoryProfileDescriptor (DescriptorIndex, Descriptor);
    441     if (Descriptor == NULL) {
    442       return NULL;
    443     }
    444   }
    445 
    446   return (VOID *) Descriptor;
    447 }
    448 
    449 /**
    450   Dump memory profile memory range information.
    451 
    452   @param[in] MemoryRange        Pointer to memory profile memory range.
    453 
    454   @return Pointer to the end of memory profile memory range buffer.
    455 
    456 **/
    457 VOID *
    458 DumpMemoryProfileMemoryRange (
    459   IN MEMORY_PROFILE_MEMORY_RANGE    *MemoryRange
    460   )
    461 {
    462   MEMORY_PROFILE_DESCRIPTOR     *Descriptor;
    463   UINTN                         DescriptorIndex;
    464 
    465   if (MemoryRange->Header.Signature != MEMORY_PROFILE_MEMORY_RANGE_SIGNATURE) {
    466     return NULL;
    467   }
    468   Print (L"MEMORY_PROFILE_MEMORY_RANGE\n");
    469   Print (L"  Signature                     - 0x%08x\n", MemoryRange->Header.Signature);
    470   Print (L"  Length                        - 0x%04x\n", MemoryRange->Header.Length);
    471   Print (L"  Revision                      - 0x%04x\n", MemoryRange->Header.Revision);
    472   Print (L"  MemoryRangeCount              - 0x%08x\n", MemoryRange->MemoryRangeCount);
    473 
    474   Descriptor = (MEMORY_PROFILE_DESCRIPTOR *) ((UINTN) MemoryRange + MemoryRange->Header.Length);
    475   for (DescriptorIndex = 0; DescriptorIndex < MemoryRange->MemoryRangeCount; DescriptorIndex++) {
    476     Descriptor = DumpMemoryProfileDescriptor (DescriptorIndex, Descriptor);
    477     if (Descriptor == NULL) {
    478       return NULL;
    479     }
    480   }
    481 
    482   return (VOID *) Descriptor;
    483 }
    484 
    485 /**
    486   Scan memory profile by Signature.
    487 
    488   @param[in] ProfileBuffer      Memory profile base address.
    489   @param[in] ProfileSize        Memory profile size.
    490   @param[in] Signature          Signature.
    491 
    492   @return Pointer to the stucture with the signature.
    493 
    494 **/
    495 VOID *
    496 ScanMemoryProfileBySignature (
    497   IN PHYSICAL_ADDRESS           ProfileBuffer,
    498   IN UINT64                     ProfileSize,
    499   IN UINT32                     Signature
    500   )
    501 {
    502   MEMORY_PROFILE_COMMON_HEADER  *CommonHeader;
    503   UINTN                          ProfileEnd;
    504 
    505   ProfileEnd = (UINTN) (ProfileBuffer + ProfileSize);
    506   CommonHeader = (MEMORY_PROFILE_COMMON_HEADER *) (UINTN) ProfileBuffer;
    507   while ((UINTN) CommonHeader < ProfileEnd) {
    508     if (CommonHeader->Signature == Signature) {
    509       //
    510       // Found it.
    511       //
    512       return (VOID *) CommonHeader;
    513     }
    514     CommonHeader = (MEMORY_PROFILE_COMMON_HEADER *) ((UINTN) CommonHeader + CommonHeader->Length);
    515   }
    516 
    517   return NULL;
    518 }
    519 
    520 /**
    521   Dump memory profile information.
    522 
    523   @param[in] ProfileBuffer      Memory profile base address.
    524   @param[in] ProfileSize        Memory profile size.
    525 
    526 **/
    527 VOID
    528 DumpMemoryProfile (
    529   IN PHYSICAL_ADDRESS           ProfileBuffer,
    530   IN UINT64                     ProfileSize
    531   )
    532 {
    533   MEMORY_PROFILE_CONTEXT        *Context;
    534   MEMORY_PROFILE_FREE_MEMORY    *FreeMemory;
    535   MEMORY_PROFILE_MEMORY_RANGE   *MemoryRange;
    536 
    537   Context = (MEMORY_PROFILE_CONTEXT *) ScanMemoryProfileBySignature (ProfileBuffer, ProfileSize, MEMORY_PROFILE_CONTEXT_SIGNATURE);
    538   if (Context != NULL) {
    539     DumpMemoryProfileContext (Context);
    540   }
    541 
    542   FreeMemory = (MEMORY_PROFILE_FREE_MEMORY *) ScanMemoryProfileBySignature (ProfileBuffer, ProfileSize, MEMORY_PROFILE_FREE_MEMORY_SIGNATURE);
    543   if (FreeMemory != NULL) {
    544     DumpMemoryProfileFreeMemory (FreeMemory);
    545   }
    546 
    547   MemoryRange = (MEMORY_PROFILE_MEMORY_RANGE *) ScanMemoryProfileBySignature (ProfileBuffer, ProfileSize, MEMORY_PROFILE_MEMORY_RANGE_SIGNATURE);
    548   if (MemoryRange != NULL) {
    549     DumpMemoryProfileMemoryRange (MemoryRange);
    550   }
    551 }
    552 
    553 /**
    554   Get and dump UEFI memory profile data.
    555 
    556   @return EFI_SUCCESS   Get the memory profile data successfully.
    557   @return other         Fail to get the memory profile data.
    558 
    559 **/
    560 EFI_STATUS
    561 GetUefiMemoryProfileData (
    562   VOID
    563   )
    564 {
    565   EFI_STATUS                    Status;
    566   EDKII_MEMORY_PROFILE_PROTOCOL *ProfileProtocol;
    567   VOID                          *Data;
    568   UINT64                        Size;
    569 
    570   Status = gBS->LocateProtocol (&gEdkiiMemoryProfileGuid, NULL, (VOID **) &ProfileProtocol);
    571   if (EFI_ERROR (Status)) {
    572     DEBUG ((EFI_D_ERROR, "UefiMemoryProfile: Locate MemoryProfile protocol - %r\n", Status));
    573     return Status;
    574   }
    575 
    576   Size = 0;
    577   Data = NULL;
    578   Status = ProfileProtocol->GetData (
    579                               ProfileProtocol,
    580                               &Size,
    581                               Data
    582                               );
    583   if (Status != EFI_BUFFER_TOO_SMALL) {
    584     Print (L"UefiMemoryProfile: GetData - %r\n", Status);
    585     return Status;
    586   }
    587 
    588   //
    589   // Add one sizeof (MEMORY_PROFILE_ALLOC_INFO) to Size for this AllocatePool action.
    590   //
    591   Size = Size + sizeof (MEMORY_PROFILE_ALLOC_INFO);
    592   Data = AllocateZeroPool ((UINTN) Size);
    593   if (Data == NULL) {
    594     Status = EFI_OUT_OF_RESOURCES;
    595     Print (L"UefiMemoryProfile: AllocateZeroPool (0x%x) - %r\n", Size, Status);
    596     return Status;
    597   }
    598 
    599   Status = ProfileProtocol->GetData (
    600                               ProfileProtocol,
    601                               &Size,
    602                               Data
    603                               );
    604   if (EFI_ERROR (Status)) {
    605     FreePool (Data);
    606     Print (L"UefiMemoryProfile: GetData - %r\n", Status);
    607     return Status;
    608   }
    609 
    610 
    611   Print (L"UefiMemoryProfileSize - 0x%x\n", Size);
    612   Print (L"======= UefiMemoryProfile begin =======\n");
    613   DumpMemoryProfile ((PHYSICAL_ADDRESS) (UINTN) Data, Size);
    614   Print (L"======= UefiMemoryProfile end =======\n\n\n");
    615 
    616   FreePool (Data);
    617 
    618   return EFI_SUCCESS;
    619 }
    620 
    621 /**
    622   Get and dump SMRAM profile data.
    623 
    624   @return EFI_SUCCESS   Get the SMRAM profile data successfully.
    625   @return other         Fail to get the SMRAM profile data.
    626 
    627 **/
    628 EFI_STATUS
    629 GetSmramProfileData (
    630   VOID
    631   )
    632 {
    633   EFI_STATUS                                    Status;
    634   UINTN                                         CommSize;
    635   UINT8                                         *CommBuffer;
    636   EFI_SMM_COMMUNICATE_HEADER                    *CommHeader;
    637   SMRAM_PROFILE_PARAMETER_GET_PROFILE_INFO      *CommGetProfileInfo;
    638   SMRAM_PROFILE_PARAMETER_GET_PROFILE_DATA      *CommGetProfileData;
    639   UINT64                                        ProfileSize;
    640   PHYSICAL_ADDRESS                              ProfileBuffer;
    641   EFI_SMM_COMMUNICATION_PROTOCOL                *SmmCommunication;
    642 
    643   Status = gBS->LocateProtocol (&gEfiSmmCommunicationProtocolGuid, NULL, (VOID **) &SmmCommunication);
    644   if (EFI_ERROR (Status)) {
    645     DEBUG ((EFI_D_ERROR, "SmramProfile: Locate SmmCommunication protocol - %r\n", Status));
    646     return Status;
    647   }
    648 
    649   CommSize = sizeof (EFI_GUID) + sizeof (UINTN) + sizeof (SMRAM_PROFILE_PARAMETER_GET_PROFILE_DATA);
    650   CommBuffer = AllocateZeroPool (CommSize);
    651   if (CommBuffer == NULL) {
    652     Status = EFI_OUT_OF_RESOURCES;
    653     Print (L"SmramProfile: AllocateZeroPool (0x%x) for comm buffer - %r\n", CommSize, Status);
    654     return Status;
    655   }
    656 
    657   //
    658   // Get Size
    659   //
    660   CommHeader = (EFI_SMM_COMMUNICATE_HEADER *) &CommBuffer[0];
    661   CopyMem (&CommHeader->HeaderGuid, &gEdkiiMemoryProfileGuid, sizeof (gEdkiiMemoryProfileGuid));
    662   CommHeader->MessageLength = sizeof (SMRAM_PROFILE_PARAMETER_GET_PROFILE_INFO);
    663 
    664   CommGetProfileInfo = (SMRAM_PROFILE_PARAMETER_GET_PROFILE_INFO *) &CommBuffer[OFFSET_OF (EFI_SMM_COMMUNICATE_HEADER, Data)];
    665   CommGetProfileInfo->Header.Command      = SMRAM_PROFILE_COMMAND_GET_PROFILE_INFO;
    666   CommGetProfileInfo->Header.DataLength   = sizeof (*CommGetProfileInfo);
    667   CommGetProfileInfo->Header.ReturnStatus = (UINT64)-1;
    668   CommGetProfileInfo->ProfileSize         = 0;
    669 
    670   CommSize = sizeof (EFI_GUID) + sizeof (UINTN) + CommHeader->MessageLength;
    671   Status = SmmCommunication->Communicate (SmmCommunication, CommBuffer, &CommSize);
    672   if (EFI_ERROR (Status)) {
    673     FreePool (CommBuffer);
    674     DEBUG ((EFI_D_ERROR, "SmramProfile: SmmCommunication - %r\n", Status));
    675     return Status;
    676   }
    677 
    678   if (CommGetProfileInfo->Header.ReturnStatus != 0) {
    679     Print (L"SmramProfile: GetProfileInfo - 0x%0x\n", CommGetProfileInfo->Header.ReturnStatus);
    680     return EFI_SUCCESS;
    681   }
    682 
    683   ProfileSize = CommGetProfileInfo->ProfileSize;
    684 
    685   //
    686   // Get Data
    687   //
    688   ProfileBuffer = (PHYSICAL_ADDRESS) (UINTN) AllocateZeroPool ((UINTN) ProfileSize);
    689   if (ProfileBuffer == 0) {
    690     FreePool (CommBuffer);
    691     Status = EFI_OUT_OF_RESOURCES;
    692     Print (L"SmramProfile: AllocateZeroPool (0x%x) for profile buffer - %r\n", (UINTN) ProfileSize, Status);
    693     return Status;
    694   }
    695 
    696   CommHeader = (EFI_SMM_COMMUNICATE_HEADER *) &CommBuffer[0];
    697   CopyMem (&CommHeader->HeaderGuid, &gEdkiiMemoryProfileGuid, sizeof(gEdkiiMemoryProfileGuid));
    698   CommHeader->MessageLength = sizeof (SMRAM_PROFILE_PARAMETER_GET_PROFILE_DATA);
    699 
    700   CommGetProfileData = (SMRAM_PROFILE_PARAMETER_GET_PROFILE_DATA *) &CommBuffer[OFFSET_OF (EFI_SMM_COMMUNICATE_HEADER, Data)];
    701   CommGetProfileData->Header.Command      = SMRAM_PROFILE_COMMAND_GET_PROFILE_DATA;
    702   CommGetProfileData->Header.DataLength   = sizeof (*CommGetProfileData);
    703   CommGetProfileData->Header.ReturnStatus = (UINT64)-1;
    704   CommGetProfileData->ProfileSize         = ProfileSize;
    705   CommGetProfileData->ProfileBuffer       = ProfileBuffer;
    706 
    707   CommSize = sizeof (EFI_GUID) + sizeof (UINTN) + CommHeader->MessageLength;
    708   Status = SmmCommunication->Communicate (SmmCommunication, CommBuffer, &CommSize);
    709   ASSERT_EFI_ERROR (Status);
    710 
    711   if (CommGetProfileData->Header.ReturnStatus != 0) {
    712     FreePool ((VOID *) (UINTN) CommGetProfileData->ProfileBuffer);
    713     FreePool (CommBuffer);
    714     Print (L"GetProfileData - 0x%x\n", CommGetProfileData->Header.ReturnStatus);
    715     return EFI_SUCCESS;
    716   }
    717 
    718 
    719   Print (L"SmramProfileSize - 0x%x\n", CommGetProfileData->ProfileSize);
    720   Print (L"======= SmramProfile begin =======\n");
    721   DumpMemoryProfile (CommGetProfileData->ProfileBuffer, CommGetProfileData->ProfileSize);
    722   Print (L"======= SmramProfile end =======\n\n\n");
    723 
    724   FreePool ((VOID *) (UINTN) CommGetProfileData->ProfileBuffer);
    725   FreePool (CommBuffer);
    726 
    727   return EFI_SUCCESS;
    728 }
    729 
    730 /**
    731   The user Entry Point for Application. The user code starts with this function
    732   as the real entry point for the image goes into a library that calls this function.
    733 
    734   @param[in] ImageHandle    The firmware allocated handle for the EFI image.
    735   @param[in] SystemTable    A pointer to the EFI System Table.
    736 
    737   @retval EFI_SUCCESS       The entry point is executed successfully.
    738   @retval other             Some error occurs when executing this entry point.
    739 
    740 **/
    741 EFI_STATUS
    742 EFIAPI
    743 UefiMain (
    744   IN EFI_HANDLE         ImageHandle,
    745   IN EFI_SYSTEM_TABLE   *SystemTable
    746   )
    747 {
    748   EFI_STATUS                    Status;
    749 
    750   Status = GetUefiMemoryProfileData ();
    751   if (EFI_ERROR (Status)) {
    752     DEBUG ((EFI_D_ERROR, "GetUefiMemoryProfileData - %r\n", Status));
    753   }
    754 
    755   Status = GetSmramProfileData ();
    756   if (EFI_ERROR (Status)) {
    757     DEBUG ((EFI_D_ERROR, "GetSmramProfileData - %r\n", Status));
    758   }
    759 
    760   return EFI_SUCCESS;
    761 }
    762