Home | History | Annotate | Download | only in Mem
      1 /** @file
      2   Support routines for UEFI memory profile.
      3 
      4   Copyright (c) 2014 - 2016, Intel Corporation. All rights reserved.<BR>
      5   This program and the accompanying materials
      6   are licensed and made available under the terms and conditions of the BSD License
      7   which accompanies this distribution.  The full text of the license may be found at
      8   http://opensource.org/licenses/bsd-license.php.
      9 
     10   THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
     11   WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
     12 
     13 **/
     14 
     15 #include "DxeMain.h"
     16 #include "Imem.h"
     17 
     18 #define IS_UEFI_MEMORY_PROFILE_ENABLED ((PcdGet8 (PcdMemoryProfilePropertyMask) & BIT0) != 0)
     19 
     20 #define GET_OCCUPIED_SIZE(ActualSize, Alignment) \
     21   ((ActualSize) + (((Alignment) - ((ActualSize) & ((Alignment) - 1))) & ((Alignment) - 1)))
     22 
     23 typedef struct {
     24   UINT32                        Signature;
     25   MEMORY_PROFILE_CONTEXT        Context;
     26   LIST_ENTRY                    *DriverInfoList;
     27 } MEMORY_PROFILE_CONTEXT_DATA;
     28 
     29 typedef struct {
     30   UINT32                        Signature;
     31   MEMORY_PROFILE_DRIVER_INFO    DriverInfo;
     32   LIST_ENTRY                    *AllocInfoList;
     33   CHAR8                         *PdbString;
     34   LIST_ENTRY                    Link;
     35 } MEMORY_PROFILE_DRIVER_INFO_DATA;
     36 
     37 typedef struct {
     38   UINT32                        Signature;
     39   MEMORY_PROFILE_ALLOC_INFO     AllocInfo;
     40   CHAR8                         *ActionString;
     41   LIST_ENTRY                    Link;
     42 } MEMORY_PROFILE_ALLOC_INFO_DATA;
     43 
     44 
     45 GLOBAL_REMOVE_IF_UNREFERENCED LIST_ENTRY  mImageQueue = INITIALIZE_LIST_HEAD_VARIABLE (mImageQueue);
     46 GLOBAL_REMOVE_IF_UNREFERENCED MEMORY_PROFILE_CONTEXT_DATA mMemoryProfileContext = {
     47   MEMORY_PROFILE_CONTEXT_SIGNATURE,
     48   {
     49     {
     50       MEMORY_PROFILE_CONTEXT_SIGNATURE,
     51       sizeof (MEMORY_PROFILE_CONTEXT),
     52       MEMORY_PROFILE_CONTEXT_REVISION
     53     },
     54     0,
     55     0,
     56     {0},
     57     {0},
     58     0,
     59     0,
     60     0
     61   },
     62   &mImageQueue,
     63 };
     64 GLOBAL_REMOVE_IF_UNREFERENCED MEMORY_PROFILE_CONTEXT_DATA *mMemoryProfileContextPtr = NULL;
     65 
     66 EFI_LOCK mMemoryProfileLock = EFI_INITIALIZE_LOCK_VARIABLE (TPL_NOTIFY);
     67 BOOLEAN mMemoryProfileGettingStatus = FALSE;
     68 BOOLEAN mMemoryProfileRecordingEnable = MEMORY_PROFILE_RECORDING_DISABLE;
     69 EFI_DEVICE_PATH_PROTOCOL *mMemoryProfileDriverPath;
     70 UINTN                    mMemoryProfileDriverPathSize;
     71 
     72 /**
     73   Get memory profile data.
     74 
     75   @param[in]      This              The EDKII_MEMORY_PROFILE_PROTOCOL instance.
     76   @param[in, out] ProfileSize       On entry, points to the size in bytes of the ProfileBuffer.
     77                                     On return, points to the size of the data returned in ProfileBuffer.
     78   @param[out]     ProfileBuffer     Profile buffer.
     79 
     80   @return EFI_SUCCESS               Get the memory profile data successfully.
     81   @return EFI_UNSUPPORTED           Memory profile is unsupported.
     82   @return EFI_BUFFER_TO_SMALL       The ProfileSize is too small for the resulting data.
     83                                     ProfileSize is updated with the size required.
     84 
     85 **/
     86 EFI_STATUS
     87 EFIAPI
     88 ProfileProtocolGetData (
     89   IN     EDKII_MEMORY_PROFILE_PROTOCOL  *This,
     90   IN OUT UINT64                         *ProfileSize,
     91      OUT VOID                           *ProfileBuffer
     92   );
     93 
     94 /**
     95   Register image to memory profile.
     96 
     97   @param[in] This               The EDKII_MEMORY_PROFILE_PROTOCOL instance.
     98   @param[in] FilePath           File path of the image.
     99   @param[in] ImageBase          Image base address.
    100   @param[in] ImageSize          Image size.
    101   @param[in] FileType           File type of the image.
    102 
    103   @return EFI_SUCCESS           Register successfully.
    104   @return EFI_UNSUPPORTED       Memory profile is unsupported,
    105                                 or memory profile for the image is not required.
    106   @return EFI_OUT_OF_RESOURCE   No enough resource for this register.
    107 
    108 **/
    109 EFI_STATUS
    110 EFIAPI
    111 ProfileProtocolRegisterImage (
    112   IN EDKII_MEMORY_PROFILE_PROTOCOL      *This,
    113   IN EFI_DEVICE_PATH_PROTOCOL           *FilePath,
    114   IN PHYSICAL_ADDRESS                   ImageBase,
    115   IN UINT64                             ImageSize,
    116   IN EFI_FV_FILETYPE                    FileType
    117   );
    118 
    119 /**
    120   Unregister image from memory profile.
    121 
    122   @param[in] This               The EDKII_MEMORY_PROFILE_PROTOCOL instance.
    123   @param[in] FilePath           File path of the image.
    124   @param[in] ImageBase          Image base address.
    125   @param[in] ImageSize          Image size.
    126 
    127   @return EFI_SUCCESS           Unregister successfully.
    128   @return EFI_UNSUPPORTED       Memory profile is unsupported,
    129                                 or memory profile for the image is not required.
    130   @return EFI_NOT_FOUND         The image is not found.
    131 
    132 **/
    133 EFI_STATUS
    134 EFIAPI
    135 ProfileProtocolUnregisterImage (
    136   IN EDKII_MEMORY_PROFILE_PROTOCOL      *This,
    137   IN EFI_DEVICE_PATH_PROTOCOL           *FilePath,
    138   IN PHYSICAL_ADDRESS                   ImageBase,
    139   IN UINT64                             ImageSize
    140   );
    141 
    142 /**
    143   Get memory profile recording state.
    144 
    145   @param[in]  This              The EDKII_MEMORY_PROFILE_PROTOCOL instance.
    146   @param[out] RecordingState    Recording state.
    147 
    148   @return EFI_SUCCESS           Memory profile recording state is returned.
    149   @return EFI_UNSUPPORTED       Memory profile is unsupported.
    150   @return EFI_INVALID_PARAMETER RecordingState is NULL.
    151 
    152 **/
    153 EFI_STATUS
    154 EFIAPI
    155 ProfileProtocolGetRecordingState (
    156   IN EDKII_MEMORY_PROFILE_PROTOCOL      *This,
    157   OUT BOOLEAN                           *RecordingState
    158   );
    159 
    160 /**
    161   Set memory profile recording state.
    162 
    163   @param[in] This               The EDKII_MEMORY_PROFILE_PROTOCOL instance.
    164   @param[in] RecordingState     Recording state.
    165 
    166   @return EFI_SUCCESS           Set memory profile recording state successfully.
    167   @return EFI_UNSUPPORTED       Memory profile is unsupported.
    168 
    169 **/
    170 EFI_STATUS
    171 EFIAPI
    172 ProfileProtocolSetRecordingState (
    173   IN EDKII_MEMORY_PROFILE_PROTOCOL      *This,
    174   IN BOOLEAN                            RecordingState
    175   );
    176 
    177 /**
    178   Record memory profile of multilevel caller.
    179 
    180   @param[in] This               The EDKII_MEMORY_PROFILE_PROTOCOL instance.
    181   @param[in] CallerAddress      Address of caller.
    182   @param[in] Action             Memory profile action.
    183   @param[in] MemoryType         Memory type.
    184                                 EfiMaxMemoryType means the MemoryType is unknown.
    185   @param[in] Buffer             Buffer address.
    186   @param[in] Size               Buffer size.
    187   @param[in] ActionString       String for memory profile action.
    188                                 Only needed for user defined allocate action.
    189 
    190   @return EFI_SUCCESS           Memory profile is updated.
    191   @return EFI_UNSUPPORTED       Memory profile is unsupported,
    192                                 or memory profile for the image is not required,
    193                                 or memory profile for the memory type is not required.
    194   @return EFI_ACCESS_DENIED     It is during memory profile data getting.
    195   @return EFI_ABORTED           Memory profile recording is not enabled.
    196   @return EFI_OUT_OF_RESOURCES  No enough resource to update memory profile for allocate action.
    197   @return EFI_NOT_FOUND         No matched allocate info found for free action.
    198 
    199 **/
    200 EFI_STATUS
    201 EFIAPI
    202 ProfileProtocolRecord (
    203   IN EDKII_MEMORY_PROFILE_PROTOCOL      *This,
    204   IN PHYSICAL_ADDRESS                   CallerAddress,
    205   IN MEMORY_PROFILE_ACTION              Action,
    206   IN EFI_MEMORY_TYPE                    MemoryType,
    207   IN VOID                               *Buffer,
    208   IN UINTN                              Size,
    209   IN CHAR8                              *ActionString OPTIONAL
    210   );
    211 
    212 EDKII_MEMORY_PROFILE_PROTOCOL mProfileProtocol = {
    213   ProfileProtocolGetData,
    214   ProfileProtocolRegisterImage,
    215   ProfileProtocolUnregisterImage,
    216   ProfileProtocolGetRecordingState,
    217   ProfileProtocolSetRecordingState,
    218   ProfileProtocolRecord,
    219 };
    220 
    221 /**
    222   Acquire lock on mMemoryProfileLock.
    223 **/
    224 VOID
    225 CoreAcquireMemoryProfileLock (
    226   VOID
    227   )
    228 {
    229   CoreAcquireLock (&mMemoryProfileLock);
    230 }
    231 
    232 /**
    233   Release lock on mMemoryProfileLock.
    234 **/
    235 VOID
    236 CoreReleaseMemoryProfileLock (
    237   VOID
    238   )
    239 {
    240   CoreReleaseLock (&mMemoryProfileLock);
    241 }
    242 
    243 /**
    244   Return memory profile context.
    245 
    246   @return Memory profile context.
    247 
    248 **/
    249 MEMORY_PROFILE_CONTEXT_DATA *
    250 GetMemoryProfileContext (
    251   VOID
    252   )
    253 {
    254   return mMemoryProfileContextPtr;
    255 }
    256 
    257 /**
    258   Retrieves the magic value from the PE/COFF header.
    259 
    260   @param Hdr    The buffer in which to return the PE32, PE32+, or TE header.
    261 
    262   @return EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC - Image is PE32
    263   @return EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC - Image is PE32+
    264 
    265 **/
    266 UINT16
    267 InternalPeCoffGetPeHeaderMagicValue (
    268   IN  EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION  Hdr
    269   )
    270 {
    271   //
    272   // NOTE: Some versions of Linux ELILO for Itanium have an incorrect magic value
    273   //       in the PE/COFF Header.  If the MachineType is Itanium(IA64) and the
    274   //       Magic value in the OptionalHeader is  EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
    275   //       then override the returned value to EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC
    276   //
    277   if (Hdr.Pe32->FileHeader.Machine == IMAGE_FILE_MACHINE_IA64 && Hdr.Pe32->OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
    278     return EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC;
    279   }
    280   //
    281   // Return the magic value from the PC/COFF Optional Header
    282   //
    283   return Hdr.Pe32->OptionalHeader.Magic;
    284 }
    285 
    286 /**
    287   Retrieves and returns the Subsystem of a PE/COFF image that has been loaded into system memory.
    288   If Pe32Data is NULL, then ASSERT().
    289 
    290   @param Pe32Data   The pointer to the PE/COFF image that is loaded in system memory.
    291 
    292   @return The Subsystem of the PE/COFF image.
    293 
    294 **/
    295 UINT16
    296 InternalPeCoffGetSubsystem (
    297   IN VOID  *Pe32Data
    298   )
    299 {
    300   EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION  Hdr;
    301   EFI_IMAGE_DOS_HEADER                 *DosHdr;
    302   UINT16                               Magic;
    303 
    304   ASSERT (Pe32Data != NULL);
    305 
    306   DosHdr = (EFI_IMAGE_DOS_HEADER *) Pe32Data;
    307   if (DosHdr->e_magic == EFI_IMAGE_DOS_SIGNATURE) {
    308     //
    309     // DOS image header is present, so read the PE header after the DOS image header.
    310     //
    311     Hdr.Pe32 = (EFI_IMAGE_NT_HEADERS32 *) ((UINTN) Pe32Data + (UINTN) ((DosHdr->e_lfanew) & 0x0ffff));
    312   } else {
    313     //
    314     // DOS image header is not present, so PE header is at the image base.
    315     //
    316     Hdr.Pe32 = (EFI_IMAGE_NT_HEADERS32 *) Pe32Data;
    317   }
    318 
    319   if (Hdr.Te->Signature == EFI_TE_IMAGE_HEADER_SIGNATURE) {
    320     return Hdr.Te->Subsystem;
    321   } else if (Hdr.Pe32->Signature == EFI_IMAGE_NT_SIGNATURE)  {
    322     Magic = InternalPeCoffGetPeHeaderMagicValue (Hdr);
    323     if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
    324       return Hdr.Pe32->OptionalHeader.Subsystem;
    325     } else if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC) {
    326       return Hdr.Pe32Plus->OptionalHeader.Subsystem;
    327     }
    328   }
    329 
    330   return 0x0000;
    331 }
    332 
    333 /**
    334   Retrieves and returns a pointer to the entry point to a PE/COFF image that has been loaded
    335   into system memory with the PE/COFF Loader Library functions.
    336 
    337   Retrieves the entry point to the PE/COFF image specified by Pe32Data and returns this entry
    338   point in EntryPoint.  If the entry point could not be retrieved from the PE/COFF image, then
    339   return RETURN_INVALID_PARAMETER.  Otherwise return RETURN_SUCCESS.
    340   If Pe32Data is NULL, then ASSERT().
    341   If EntryPoint is NULL, then ASSERT().
    342 
    343   @param  Pe32Data                  The pointer to the PE/COFF image that is loaded in system memory.
    344   @param  EntryPoint                The pointer to entry point to the PE/COFF image to return.
    345 
    346   @retval RETURN_SUCCESS            EntryPoint was returned.
    347   @retval RETURN_INVALID_PARAMETER  The entry point could not be found in the PE/COFF image.
    348 
    349 **/
    350 RETURN_STATUS
    351 InternalPeCoffGetEntryPoint (
    352   IN  VOID  *Pe32Data,
    353   OUT VOID  **EntryPoint
    354   )
    355 {
    356   EFI_IMAGE_DOS_HEADER                  *DosHdr;
    357   EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION   Hdr;
    358 
    359   ASSERT (Pe32Data   != NULL);
    360   ASSERT (EntryPoint != NULL);
    361 
    362   DosHdr = (EFI_IMAGE_DOS_HEADER *) Pe32Data;
    363   if (DosHdr->e_magic == EFI_IMAGE_DOS_SIGNATURE) {
    364     //
    365     // DOS image header is present, so read the PE header after the DOS image header.
    366     //
    367     Hdr.Pe32 = (EFI_IMAGE_NT_HEADERS32 *) ((UINTN) Pe32Data + (UINTN) ((DosHdr->e_lfanew) & 0x0ffff));
    368   } else {
    369     //
    370     // DOS image header is not present, so PE header is at the image base.
    371     //
    372     Hdr.Pe32 = (EFI_IMAGE_NT_HEADERS32 *) Pe32Data;
    373   }
    374 
    375   //
    376   // Calculate the entry point relative to the start of the image.
    377   // AddressOfEntryPoint is common for PE32 & PE32+
    378   //
    379   if (Hdr.Te->Signature == EFI_TE_IMAGE_HEADER_SIGNATURE) {
    380     *EntryPoint = (VOID *) ((UINTN) Pe32Data + (UINTN) (Hdr.Te->AddressOfEntryPoint & 0x0ffffffff) + sizeof (EFI_TE_IMAGE_HEADER) - Hdr.Te->StrippedSize);
    381     return RETURN_SUCCESS;
    382   } else if (Hdr.Pe32->Signature == EFI_IMAGE_NT_SIGNATURE) {
    383     *EntryPoint = (VOID *) ((UINTN) Pe32Data + (UINTN) (Hdr.Pe32->OptionalHeader.AddressOfEntryPoint & 0x0ffffffff));
    384     return RETURN_SUCCESS;
    385   }
    386 
    387   return RETURN_UNSUPPORTED;
    388 }
    389 
    390 /**
    391   Build driver info.
    392 
    393   @param ContextData    Memory profile context.
    394   @param FileName       File name of the image.
    395   @param ImageBase      Image base address.
    396   @param ImageSize      Image size.
    397   @param EntryPoint     Entry point of the image.
    398   @param ImageSubsystem Image subsystem of the image.
    399   @param FileType       File type of the image.
    400 
    401   @return Pointer to memory profile driver info.
    402 
    403 **/
    404 MEMORY_PROFILE_DRIVER_INFO_DATA *
    405 BuildDriverInfo (
    406   IN MEMORY_PROFILE_CONTEXT_DATA    *ContextData,
    407   IN EFI_GUID                       *FileName,
    408   IN PHYSICAL_ADDRESS               ImageBase,
    409   IN UINT64                         ImageSize,
    410   IN PHYSICAL_ADDRESS               EntryPoint,
    411   IN UINT16                         ImageSubsystem,
    412   IN EFI_FV_FILETYPE                FileType
    413   )
    414 {
    415   EFI_STATUS                        Status;
    416   MEMORY_PROFILE_DRIVER_INFO        *DriverInfo;
    417   MEMORY_PROFILE_DRIVER_INFO_DATA   *DriverInfoData;
    418   VOID                              *EntryPointInImage;
    419   CHAR8                             *PdbString;
    420   UINTN                             PdbSize;
    421   UINTN                             PdbOccupiedSize;
    422 
    423   PdbSize = 0;
    424   PdbOccupiedSize = 0;
    425   PdbString = NULL;
    426   if (ImageBase != 0) {
    427     PdbString = PeCoffLoaderGetPdbPointer ((VOID*) (UINTN) ImageBase);
    428     if (PdbString != NULL) {
    429       PdbSize = AsciiStrSize (PdbString);
    430       PdbOccupiedSize = GET_OCCUPIED_SIZE (PdbSize, sizeof (UINT64));
    431     }
    432   }
    433 
    434   //
    435   // Use CoreInternalAllocatePool() that will not update profile for this AllocatePool action.
    436   //
    437   Status = CoreInternalAllocatePool (
    438              EfiBootServicesData,
    439              sizeof (*DriverInfoData) + sizeof (LIST_ENTRY) + PdbSize,
    440              (VOID **) &DriverInfoData
    441              );
    442   if (EFI_ERROR (Status)) {
    443     return NULL;
    444   }
    445   ASSERT (DriverInfoData != NULL);
    446 
    447   ZeroMem (DriverInfoData, sizeof (*DriverInfoData));
    448 
    449   DriverInfo = &DriverInfoData->DriverInfo;
    450   DriverInfoData->Signature = MEMORY_PROFILE_DRIVER_INFO_SIGNATURE;
    451   DriverInfo->Header.Signature = MEMORY_PROFILE_DRIVER_INFO_SIGNATURE;
    452   DriverInfo->Header.Length = (UINT16) (sizeof (MEMORY_PROFILE_DRIVER_INFO) + PdbOccupiedSize);
    453   DriverInfo->Header.Revision = MEMORY_PROFILE_DRIVER_INFO_REVISION;
    454   if (FileName != NULL) {
    455     CopyMem (&DriverInfo->FileName, FileName, sizeof (EFI_GUID));
    456   }
    457   DriverInfo->ImageBase = ImageBase;
    458   DriverInfo->ImageSize = ImageSize;
    459   DriverInfo->EntryPoint = EntryPoint;
    460   DriverInfo->ImageSubsystem = ImageSubsystem;
    461   if ((EntryPoint != 0) && ((EntryPoint < ImageBase) || (EntryPoint >= (ImageBase + ImageSize)))) {
    462     //
    463     // If the EntryPoint is not in the range of image buffer, it should come from emulation environment.
    464     // So patch ImageBuffer here to align the EntryPoint.
    465     //
    466     Status = InternalPeCoffGetEntryPoint ((VOID *) (UINTN) ImageBase, &EntryPointInImage);
    467     ASSERT_EFI_ERROR (Status);
    468     DriverInfo->ImageBase = ImageBase + EntryPoint - (PHYSICAL_ADDRESS) (UINTN) EntryPointInImage;
    469   }
    470   DriverInfo->FileType = FileType;
    471   DriverInfoData->AllocInfoList = (LIST_ENTRY *) (DriverInfoData + 1);
    472   InitializeListHead (DriverInfoData->AllocInfoList);
    473   DriverInfo->CurrentUsage = 0;
    474   DriverInfo->PeakUsage = 0;
    475   DriverInfo->AllocRecordCount = 0;
    476   if (PdbSize != 0) {
    477     DriverInfo->PdbStringOffset = (UINT16) sizeof (MEMORY_PROFILE_DRIVER_INFO);
    478     DriverInfoData->PdbString = (CHAR8 *) (DriverInfoData->AllocInfoList + 1);
    479     CopyMem (DriverInfoData->PdbString, PdbString, PdbSize);
    480   } else {
    481     DriverInfo->PdbStringOffset = 0;
    482     DriverInfoData->PdbString = NULL;
    483   }
    484 
    485   InsertTailList (ContextData->DriverInfoList, &DriverInfoData->Link);
    486   ContextData->Context.ImageCount ++;
    487   ContextData->Context.TotalImageSize += DriverInfo->ImageSize;
    488 
    489   return DriverInfoData;
    490 }
    491 
    492 /**
    493   Return if record for this driver is needed..
    494 
    495   @param DriverFilePath     Driver file path.
    496 
    497   @retval TRUE              Record for this driver is needed.
    498   @retval FALSE             Record for this driver is not needed.
    499 
    500 **/
    501 BOOLEAN
    502 NeedRecordThisDriver (
    503   IN EFI_DEVICE_PATH_PROTOCOL       *DriverFilePath
    504   )
    505 {
    506   EFI_DEVICE_PATH_PROTOCOL          *TmpDevicePath;
    507   EFI_DEVICE_PATH_PROTOCOL          *DevicePathInstance;
    508   UINTN                             DevicePathSize;
    509   UINTN                             FilePathSize;
    510 
    511   if (!IsDevicePathValid (mMemoryProfileDriverPath, mMemoryProfileDriverPathSize)) {
    512     //
    513     // Invalid Device Path means record all.
    514     //
    515     return TRUE;
    516   }
    517 
    518   //
    519   // Record FilePath without END node.
    520   //
    521   FilePathSize = GetDevicePathSize (DriverFilePath) - sizeof(EFI_DEVICE_PATH_PROTOCOL);
    522 
    523   DevicePathInstance = mMemoryProfileDriverPath;
    524   do {
    525     //
    526     // Find END node (it might be END_ENTIRE or END_INSTANCE).
    527     //
    528     TmpDevicePath = DevicePathInstance;
    529     while (!IsDevicePathEndType (TmpDevicePath)) {
    530       TmpDevicePath = NextDevicePathNode (TmpDevicePath);
    531     }
    532 
    533     //
    534     // Do not compare END node.
    535     //
    536     DevicePathSize = (UINTN)TmpDevicePath - (UINTN)DevicePathInstance;
    537     if ((FilePathSize == DevicePathSize) &&
    538         (CompareMem (DriverFilePath, DevicePathInstance, DevicePathSize) == 0)) {
    539       return TRUE;
    540     }
    541 
    542     //
    543     // Get next instance.
    544     //
    545     DevicePathInstance = (EFI_DEVICE_PATH_PROTOCOL *)((UINTN)DevicePathInstance + DevicePathSize + DevicePathNodeLength(TmpDevicePath));
    546   } while (DevicePathSubType (TmpDevicePath) != END_ENTIRE_DEVICE_PATH_SUBTYPE);
    547 
    548   return FALSE;
    549 }
    550 
    551 /**
    552   Register DXE Core to memory profile.
    553 
    554   @param HobStart       The start address of the HOB.
    555   @param ContextData    Memory profile context.
    556 
    557   @retval TRUE      Register success.
    558   @retval FALSE     Register fail.
    559 
    560 **/
    561 BOOLEAN
    562 RegisterDxeCore (
    563   IN VOID                           *HobStart,
    564   IN MEMORY_PROFILE_CONTEXT_DATA    *ContextData
    565   )
    566 {
    567   EFI_PEI_HOB_POINTERS              DxeCoreHob;
    568   MEMORY_PROFILE_DRIVER_INFO_DATA   *DriverInfoData;
    569   PHYSICAL_ADDRESS                  ImageBase;
    570   UINT8                             TempBuffer[sizeof(MEDIA_FW_VOL_FILEPATH_DEVICE_PATH) + sizeof(EFI_DEVICE_PATH_PROTOCOL)];
    571   MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *FilePath;
    572 
    573   ASSERT (ContextData != NULL);
    574 
    575   //
    576   // Searching for image hob
    577   //
    578   DxeCoreHob.Raw          = HobStart;
    579   while ((DxeCoreHob.Raw = GetNextHob (EFI_HOB_TYPE_MEMORY_ALLOCATION, DxeCoreHob.Raw)) != NULL) {
    580     if (CompareGuid (&DxeCoreHob.MemoryAllocationModule->MemoryAllocationHeader.Name, &gEfiHobMemoryAllocModuleGuid)) {
    581       //
    582       // Find Dxe Core HOB
    583       //
    584       break;
    585     }
    586     DxeCoreHob.Raw = GET_NEXT_HOB (DxeCoreHob);
    587   }
    588   ASSERT (DxeCoreHob.Raw != NULL);
    589 
    590   FilePath = (MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *) TempBuffer;
    591   EfiInitializeFwVolDevicepathNode (FilePath, &DxeCoreHob.MemoryAllocationModule->ModuleName);
    592   SetDevicePathEndNode (FilePath + 1);
    593 
    594   if (!NeedRecordThisDriver ((EFI_DEVICE_PATH_PROTOCOL *) FilePath)) {
    595     return FALSE;
    596   }
    597 
    598   ImageBase = DxeCoreHob.MemoryAllocationModule->MemoryAllocationHeader.MemoryBaseAddress;
    599   DriverInfoData = BuildDriverInfo (
    600                      ContextData,
    601                      &DxeCoreHob.MemoryAllocationModule->ModuleName,
    602                      ImageBase,
    603                      DxeCoreHob.MemoryAllocationModule->MemoryAllocationHeader.MemoryLength,
    604                      DxeCoreHob.MemoryAllocationModule->EntryPoint,
    605                      InternalPeCoffGetSubsystem ((VOID *) (UINTN) ImageBase),
    606                      EFI_FV_FILETYPE_DXE_CORE
    607                      );
    608   if (DriverInfoData == NULL) {
    609     return FALSE;
    610   }
    611 
    612   return TRUE;
    613 }
    614 
    615 /**
    616   Initialize memory profile.
    617 
    618   @param HobStart   The start address of the HOB.
    619 
    620 **/
    621 VOID
    622 MemoryProfileInit (
    623   IN VOID   *HobStart
    624   )
    625 {
    626   MEMORY_PROFILE_CONTEXT_DATA   *ContextData;
    627 
    628   if (!IS_UEFI_MEMORY_PROFILE_ENABLED) {
    629     return;
    630   }
    631 
    632   ContextData = GetMemoryProfileContext ();
    633   if (ContextData != NULL) {
    634     return;
    635   }
    636 
    637   mMemoryProfileGettingStatus = FALSE;
    638   if ((PcdGet8 (PcdMemoryProfilePropertyMask) & BIT7) != 0) {
    639     mMemoryProfileRecordingEnable = MEMORY_PROFILE_RECORDING_DISABLE;
    640   } else {
    641     mMemoryProfileRecordingEnable = MEMORY_PROFILE_RECORDING_ENABLE;
    642   }
    643   mMemoryProfileDriverPathSize = PcdGetSize (PcdMemoryProfileDriverPath);
    644   mMemoryProfileDriverPath = AllocateCopyPool (mMemoryProfileDriverPathSize, PcdGetPtr (PcdMemoryProfileDriverPath));
    645   mMemoryProfileContextPtr = &mMemoryProfileContext;
    646 
    647   RegisterDxeCore (HobStart, &mMemoryProfileContext);
    648 
    649   DEBUG ((EFI_D_INFO, "MemoryProfileInit MemoryProfileContext - 0x%x\n", &mMemoryProfileContext));
    650 }
    651 
    652 /**
    653   Install memory profile protocol.
    654 
    655 **/
    656 VOID
    657 MemoryProfileInstallProtocol (
    658   VOID
    659   )
    660 {
    661   EFI_HANDLE    Handle;
    662   EFI_STATUS    Status;
    663 
    664   if (!IS_UEFI_MEMORY_PROFILE_ENABLED) {
    665     return;
    666   }
    667 
    668   Handle = NULL;
    669   Status = CoreInstallMultipleProtocolInterfaces (
    670              &Handle,
    671              &gEdkiiMemoryProfileGuid,
    672              &mProfileProtocol,
    673              NULL
    674              );
    675   ASSERT_EFI_ERROR (Status);
    676 }
    677 
    678 /**
    679   Get the GUID file name from the file path.
    680 
    681   @param FilePath  File path.
    682 
    683   @return The GUID file name from the file path.
    684 
    685 **/
    686 EFI_GUID *
    687 GetFileNameFromFilePath (
    688   IN EFI_DEVICE_PATH_PROTOCOL   *FilePath
    689   )
    690 {
    691   MEDIA_FW_VOL_FILEPATH_DEVICE_PATH     *ThisFilePath;
    692   EFI_GUID                              *FileName;
    693 
    694   FileName = NULL;
    695   if (FilePath != NULL) {
    696     ThisFilePath = (MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *) FilePath;
    697     while (!IsDevicePathEnd (ThisFilePath)) {
    698       FileName = EfiGetNameGuidFromFwVolDevicePathNode (ThisFilePath);
    699       if (FileName != NULL) {
    700         break;
    701       }
    702       ThisFilePath = (MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *) NextDevicePathNode (ThisFilePath);
    703     }
    704   }
    705 
    706   return FileName;
    707 }
    708 
    709 /**
    710   Register image to memory profile.
    711 
    712   @param DriverEntry    Image info.
    713   @param FileType       Image file type.
    714 
    715   @return EFI_SUCCESS           Register successfully.
    716   @return EFI_UNSUPPORTED       Memory profile is unsupported,
    717                                 or memory profile for the image is not required.
    718   @return EFI_OUT_OF_RESOURCES  No enough resource for this register.
    719 
    720 **/
    721 EFI_STATUS
    722 RegisterMemoryProfileImage (
    723   IN LOADED_IMAGE_PRIVATE_DATA  *DriverEntry,
    724   IN EFI_FV_FILETYPE            FileType
    725   )
    726 {
    727   MEMORY_PROFILE_CONTEXT_DATA       *ContextData;
    728   MEMORY_PROFILE_DRIVER_INFO_DATA   *DriverInfoData;
    729 
    730   if (!IS_UEFI_MEMORY_PROFILE_ENABLED) {
    731     return EFI_UNSUPPORTED;
    732   }
    733 
    734   if (!NeedRecordThisDriver (DriverEntry->Info.FilePath)) {
    735     return EFI_UNSUPPORTED;
    736   }
    737 
    738   ContextData = GetMemoryProfileContext ();
    739   if (ContextData == NULL) {
    740     return EFI_UNSUPPORTED;
    741   }
    742 
    743   DriverInfoData = BuildDriverInfo (
    744                      ContextData,
    745                      GetFileNameFromFilePath (DriverEntry->Info.FilePath),
    746                      DriverEntry->ImageContext.ImageAddress,
    747                      DriverEntry->ImageContext.ImageSize,
    748                      DriverEntry->ImageContext.EntryPoint,
    749                      DriverEntry->ImageContext.ImageType,
    750                      FileType
    751                      );
    752   if (DriverInfoData == NULL) {
    753     return EFI_OUT_OF_RESOURCES;
    754   }
    755 
    756   return EFI_SUCCESS;
    757 }
    758 
    759 /**
    760   Search image from memory profile.
    761 
    762   @param ContextData    Memory profile context.
    763   @param FileName       Image file name.
    764   @param Address        Image Address.
    765 
    766   @return Pointer to memory profile driver info.
    767 
    768 **/
    769 MEMORY_PROFILE_DRIVER_INFO_DATA *
    770 GetMemoryProfileDriverInfoByFileNameAndAddress (
    771   IN MEMORY_PROFILE_CONTEXT_DATA    *ContextData,
    772   IN EFI_GUID                       *FileName,
    773   IN PHYSICAL_ADDRESS               Address
    774   )
    775 {
    776   MEMORY_PROFILE_DRIVER_INFO        *DriverInfo;
    777   MEMORY_PROFILE_DRIVER_INFO_DATA   *DriverInfoData;
    778   LIST_ENTRY                        *DriverLink;
    779   LIST_ENTRY                        *DriverInfoList;
    780 
    781   DriverInfoList = ContextData->DriverInfoList;
    782 
    783   for (DriverLink = DriverInfoList->ForwardLink;
    784        DriverLink != DriverInfoList;
    785        DriverLink = DriverLink->ForwardLink) {
    786     DriverInfoData = CR (
    787                        DriverLink,
    788                        MEMORY_PROFILE_DRIVER_INFO_DATA,
    789                        Link,
    790                        MEMORY_PROFILE_DRIVER_INFO_SIGNATURE
    791                        );
    792     DriverInfo = &DriverInfoData->DriverInfo;
    793     if ((CompareGuid (&DriverInfo->FileName, FileName)) &&
    794         (Address >= DriverInfo->ImageBase) &&
    795         (Address < (DriverInfo->ImageBase + DriverInfo->ImageSize))) {
    796       return DriverInfoData;
    797     }
    798   }
    799 
    800   return NULL;
    801 }
    802 
    803 /**
    804   Search image from memory profile.
    805   It will return image, if (Address >= ImageBuffer) AND (Address < ImageBuffer + ImageSize).
    806 
    807   @param ContextData    Memory profile context.
    808   @param Address        Image or Function address.
    809 
    810   @return Pointer to memory profile driver info.
    811 
    812 **/
    813 MEMORY_PROFILE_DRIVER_INFO_DATA *
    814 GetMemoryProfileDriverInfoFromAddress (
    815   IN MEMORY_PROFILE_CONTEXT_DATA    *ContextData,
    816   IN PHYSICAL_ADDRESS               Address
    817   )
    818 {
    819   MEMORY_PROFILE_DRIVER_INFO        *DriverInfo;
    820   MEMORY_PROFILE_DRIVER_INFO_DATA   *DriverInfoData;
    821   LIST_ENTRY                        *DriverLink;
    822   LIST_ENTRY                        *DriverInfoList;
    823 
    824   DriverInfoList = ContextData->DriverInfoList;
    825 
    826   for (DriverLink = DriverInfoList->ForwardLink;
    827        DriverLink != DriverInfoList;
    828        DriverLink = DriverLink->ForwardLink) {
    829     DriverInfoData = CR (
    830                        DriverLink,
    831                        MEMORY_PROFILE_DRIVER_INFO_DATA,
    832                        Link,
    833                        MEMORY_PROFILE_DRIVER_INFO_SIGNATURE
    834                        );
    835     DriverInfo = &DriverInfoData->DriverInfo;
    836     if ((Address >= DriverInfo->ImageBase) &&
    837         (Address < (DriverInfo->ImageBase + DriverInfo->ImageSize))) {
    838       return DriverInfoData;
    839     }
    840   }
    841 
    842   return NULL;
    843 }
    844 
    845 /**
    846   Unregister image from memory profile.
    847 
    848   @param DriverEntry    Image info.
    849 
    850   @return EFI_SUCCESS           Unregister successfully.
    851   @return EFI_UNSUPPORTED       Memory profile is unsupported,
    852                                 or memory profile for the image is not required.
    853   @return EFI_NOT_FOUND         The image is not found.
    854 
    855 **/
    856 EFI_STATUS
    857 UnregisterMemoryProfileImage (
    858   IN LOADED_IMAGE_PRIVATE_DATA      *DriverEntry
    859   )
    860 {
    861   EFI_STATUS                        Status;
    862   MEMORY_PROFILE_CONTEXT_DATA       *ContextData;
    863   MEMORY_PROFILE_DRIVER_INFO_DATA   *DriverInfoData;
    864   EFI_GUID                          *FileName;
    865   PHYSICAL_ADDRESS                  ImageAddress;
    866   VOID                              *EntryPointInImage;
    867 
    868   if (!IS_UEFI_MEMORY_PROFILE_ENABLED) {
    869     return EFI_UNSUPPORTED;
    870   }
    871 
    872   if (!NeedRecordThisDriver (DriverEntry->Info.FilePath)) {
    873     return EFI_UNSUPPORTED;
    874   }
    875 
    876   ContextData = GetMemoryProfileContext ();
    877   if (ContextData == NULL) {
    878     return EFI_UNSUPPORTED;
    879   }
    880 
    881   DriverInfoData = NULL;
    882   FileName = GetFileNameFromFilePath (DriverEntry->Info.FilePath);
    883   ImageAddress = DriverEntry->ImageContext.ImageAddress;
    884   if ((DriverEntry->ImageContext.EntryPoint < ImageAddress) || (DriverEntry->ImageContext.EntryPoint >= (ImageAddress + DriverEntry->ImageContext.ImageSize))) {
    885     //
    886     // If the EntryPoint is not in the range of image buffer, it should come from emulation environment.
    887     // So patch ImageAddress here to align the EntryPoint.
    888     //
    889     Status = InternalPeCoffGetEntryPoint ((VOID *) (UINTN) ImageAddress, &EntryPointInImage);
    890     ASSERT_EFI_ERROR (Status);
    891     ImageAddress = ImageAddress + (UINTN) DriverEntry->ImageContext.EntryPoint - (UINTN) EntryPointInImage;
    892   }
    893   if (FileName != NULL) {
    894     DriverInfoData = GetMemoryProfileDriverInfoByFileNameAndAddress (ContextData, FileName, ImageAddress);
    895   }
    896   if (DriverInfoData == NULL) {
    897     DriverInfoData = GetMemoryProfileDriverInfoFromAddress (ContextData, ImageAddress);
    898   }
    899   if (DriverInfoData == NULL) {
    900     return EFI_NOT_FOUND;
    901   }
    902 
    903   ContextData->Context.TotalImageSize -= DriverInfoData->DriverInfo.ImageSize;
    904 
    905   // Keep the ImageBase for RVA calculation in Application.
    906   //DriverInfoData->DriverInfo.ImageBase = 0;
    907   DriverInfoData->DriverInfo.ImageSize = 0;
    908 
    909   if (DriverInfoData->DriverInfo.PeakUsage == 0) {
    910     ContextData->Context.ImageCount --;
    911     RemoveEntryList (&DriverInfoData->Link);
    912     //
    913     // Use CoreInternalFreePool() that will not update profile for this FreePool action.
    914     //
    915     CoreInternalFreePool (DriverInfoData, NULL);
    916   }
    917 
    918   return EFI_SUCCESS;
    919 }
    920 
    921 /**
    922   Return if this memory type needs to be recorded into memory profile.
    923   If BIOS memory type (0 ~ EfiMaxMemoryType - 1), it checks bit (1 << MemoryType).
    924   If OS memory type (0x80000000 ~ 0xFFFFFFFF), it checks bit63 - 0x8000000000000000.
    925   If OEM memory type (0x70000000 ~ 0x7FFFFFFF), it checks bit62 - 0x4000000000000000.
    926 
    927   @param MemoryType     Memory type.
    928 
    929   @retval TRUE          This memory type need to be recorded.
    930   @retval FALSE         This memory type need not to be recorded.
    931 
    932 **/
    933 BOOLEAN
    934 CoreNeedRecordProfile (
    935   IN EFI_MEMORY_TYPE    MemoryType
    936   )
    937 {
    938   UINT64 TestBit;
    939 
    940   if ((UINT32) MemoryType >= MEMORY_TYPE_OS_RESERVED_MIN) {
    941     TestBit = BIT63;
    942   } else if ((UINT32) MemoryType >= MEMORY_TYPE_OEM_RESERVED_MIN) {
    943     TestBit = BIT62;
    944   } else {
    945     TestBit = LShiftU64 (1, MemoryType);
    946   }
    947 
    948   if ((PcdGet64 (PcdMemoryProfileMemoryType) & TestBit) != 0) {
    949     return TRUE;
    950   } else {
    951     return FALSE;
    952   }
    953 }
    954 
    955 /**
    956   Convert EFI memory type to profile memory index. The rule is:
    957   If BIOS memory type (0 ~ EfiMaxMemoryType - 1), ProfileMemoryIndex = MemoryType.
    958   If OS memory type (0x80000000 ~ 0xFFFFFFFF), ProfileMemoryIndex = EfiMaxMemoryType.
    959   If OEM memory type (0x70000000 ~ 0x7FFFFFFF), ProfileMemoryIndex = EfiMaxMemoryType + 1.
    960 
    961   @param MemoryType     Memory type.
    962 
    963   @return Profile memory index.
    964 
    965 **/
    966 UINTN
    967 GetProfileMemoryIndex (
    968   IN EFI_MEMORY_TYPE    MemoryType
    969   )
    970 {
    971   if ((UINT32) MemoryType >= MEMORY_TYPE_OS_RESERVED_MIN) {
    972     return EfiMaxMemoryType;
    973   } else if ((UINT32) MemoryType >= MEMORY_TYPE_OEM_RESERVED_MIN) {
    974     return EfiMaxMemoryType + 1;
    975   } else {
    976     return MemoryType;
    977   }
    978 }
    979 
    980 /**
    981   Update memory profile Allocate information.
    982 
    983   @param CallerAddress  Address of caller who call Allocate.
    984   @param Action         This Allocate action.
    985   @param MemoryType     Memory type.
    986   @param Size           Buffer size.
    987   @param Buffer         Buffer address.
    988   @param ActionString   String for memory profile action.
    989 
    990   @return EFI_SUCCESS           Memory profile is updated.
    991   @return EFI_UNSUPPORTED       Memory profile is unsupported,
    992                                 or memory profile for the image is not required.
    993   @return EFI_OUT_OF_RESOURCES  No enough resource to update memory profile for allocate action.
    994 
    995 **/
    996 EFI_STATUS
    997 CoreUpdateProfileAllocate (
    998   IN PHYSICAL_ADDRESS       CallerAddress,
    999   IN MEMORY_PROFILE_ACTION  Action,
   1000   IN EFI_MEMORY_TYPE        MemoryType,
   1001   IN UINTN                  Size,
   1002   IN VOID                   *Buffer,
   1003   IN CHAR8                  *ActionString OPTIONAL
   1004   )
   1005 {
   1006   EFI_STATUS                        Status;
   1007   MEMORY_PROFILE_CONTEXT            *Context;
   1008   MEMORY_PROFILE_DRIVER_INFO        *DriverInfo;
   1009   MEMORY_PROFILE_ALLOC_INFO         *AllocInfo;
   1010   MEMORY_PROFILE_CONTEXT_DATA       *ContextData;
   1011   MEMORY_PROFILE_DRIVER_INFO_DATA   *DriverInfoData;
   1012   MEMORY_PROFILE_ALLOC_INFO_DATA    *AllocInfoData;
   1013   UINTN                             ProfileMemoryIndex;
   1014   MEMORY_PROFILE_ACTION             BasicAction;
   1015   UINTN                             ActionStringSize;
   1016   UINTN                             ActionStringOccupiedSize;
   1017 
   1018   BasicAction = Action & MEMORY_PROFILE_ACTION_BASIC_MASK;
   1019 
   1020   ContextData = GetMemoryProfileContext ();
   1021   if (ContextData == NULL) {
   1022     return EFI_UNSUPPORTED;
   1023   }
   1024 
   1025   DriverInfoData = GetMemoryProfileDriverInfoFromAddress (ContextData, CallerAddress);
   1026   if (DriverInfoData == NULL) {
   1027     return EFI_UNSUPPORTED;
   1028   }
   1029 
   1030   ActionStringSize = 0;
   1031   ActionStringOccupiedSize = 0;
   1032   if (ActionString != NULL) {
   1033     ActionStringSize = AsciiStrSize (ActionString);
   1034     ActionStringOccupiedSize = GET_OCCUPIED_SIZE (ActionStringSize, sizeof (UINT64));
   1035   }
   1036 
   1037   //
   1038   // Use CoreInternalAllocatePool() that will not update profile for this AllocatePool action.
   1039   //
   1040   AllocInfoData = NULL;
   1041   Status = CoreInternalAllocatePool (
   1042              EfiBootServicesData,
   1043              sizeof (*AllocInfoData) + ActionStringSize,
   1044              (VOID **) &AllocInfoData
   1045              );
   1046   if (EFI_ERROR (Status)) {
   1047     return EFI_OUT_OF_RESOURCES;
   1048   }
   1049   ASSERT (AllocInfoData != NULL);
   1050 
   1051   //
   1052   // Only update SequenceCount if and only if it is basic action.
   1053   //
   1054   if (Action == BasicAction) {
   1055     ContextData->Context.SequenceCount ++;
   1056   }
   1057 
   1058   AllocInfo = &AllocInfoData->AllocInfo;
   1059   AllocInfoData->Signature      = MEMORY_PROFILE_ALLOC_INFO_SIGNATURE;
   1060   AllocInfo->Header.Signature   = MEMORY_PROFILE_ALLOC_INFO_SIGNATURE;
   1061   AllocInfo->Header.Length      = (UINT16) (sizeof (MEMORY_PROFILE_ALLOC_INFO) + ActionStringOccupiedSize);
   1062   AllocInfo->Header.Revision    = MEMORY_PROFILE_ALLOC_INFO_REVISION;
   1063   AllocInfo->CallerAddress      = CallerAddress;
   1064   AllocInfo->SequenceId         = ContextData->Context.SequenceCount;
   1065   AllocInfo->Action             = Action;
   1066   AllocInfo->MemoryType         = MemoryType;
   1067   AllocInfo->Buffer             = (PHYSICAL_ADDRESS) (UINTN) Buffer;
   1068   AllocInfo->Size               = Size;
   1069   if (ActionString != NULL) {
   1070     AllocInfo->ActionStringOffset = (UINT16) sizeof (MEMORY_PROFILE_ALLOC_INFO);
   1071     AllocInfoData->ActionString = (CHAR8 *) (AllocInfoData + 1);
   1072     CopyMem (AllocInfoData->ActionString, ActionString, ActionStringSize);
   1073   } else {
   1074     AllocInfo->ActionStringOffset = 0;
   1075     AllocInfoData->ActionString = NULL;
   1076   }
   1077 
   1078   InsertTailList (DriverInfoData->AllocInfoList, &AllocInfoData->Link);
   1079 
   1080   Context = &ContextData->Context;
   1081   DriverInfo = &DriverInfoData->DriverInfo;
   1082   DriverInfo->AllocRecordCount ++;
   1083 
   1084   //
   1085   // Update summary if and only if it is basic action.
   1086   //
   1087   if (Action == BasicAction) {
   1088     ProfileMemoryIndex = GetProfileMemoryIndex (MemoryType);
   1089 
   1090     DriverInfo->CurrentUsage += Size;
   1091     if (DriverInfo->PeakUsage < DriverInfo->CurrentUsage) {
   1092       DriverInfo->PeakUsage = DriverInfo->CurrentUsage;
   1093     }
   1094     DriverInfo->CurrentUsageByType[ProfileMemoryIndex] += Size;
   1095     if (DriverInfo->PeakUsageByType[ProfileMemoryIndex] < DriverInfo->CurrentUsageByType[ProfileMemoryIndex]) {
   1096       DriverInfo->PeakUsageByType[ProfileMemoryIndex] = DriverInfo->CurrentUsageByType[ProfileMemoryIndex];
   1097     }
   1098 
   1099     Context->CurrentTotalUsage += Size;
   1100     if (Context->PeakTotalUsage < Context->CurrentTotalUsage) {
   1101       Context->PeakTotalUsage = Context->CurrentTotalUsage;
   1102     }
   1103     Context->CurrentTotalUsageByType[ProfileMemoryIndex] += Size;
   1104     if (Context->PeakTotalUsageByType[ProfileMemoryIndex] < Context->CurrentTotalUsageByType[ProfileMemoryIndex]) {
   1105       Context->PeakTotalUsageByType[ProfileMemoryIndex] = Context->CurrentTotalUsageByType[ProfileMemoryIndex];
   1106     }
   1107   }
   1108 
   1109   return EFI_SUCCESS;
   1110 }
   1111 
   1112 /**
   1113   Get memory profile alloc info from memory profile.
   1114 
   1115   @param DriverInfoData     Driver info.
   1116   @param BasicAction        This Free basic action.
   1117   @param Size               Buffer size.
   1118   @param Buffer             Buffer address.
   1119 
   1120   @return Pointer to memory profile alloc info.
   1121 
   1122 **/
   1123 MEMORY_PROFILE_ALLOC_INFO_DATA *
   1124 GetMemoryProfileAllocInfoFromAddress (
   1125   IN MEMORY_PROFILE_DRIVER_INFO_DATA    *DriverInfoData,
   1126   IN MEMORY_PROFILE_ACTION              BasicAction,
   1127   IN UINTN                              Size,
   1128   IN VOID                               *Buffer
   1129   )
   1130 {
   1131   LIST_ENTRY                        *AllocInfoList;
   1132   LIST_ENTRY                        *AllocLink;
   1133   MEMORY_PROFILE_ALLOC_INFO         *AllocInfo;
   1134   MEMORY_PROFILE_ALLOC_INFO_DATA    *AllocInfoData;
   1135 
   1136   AllocInfoList = DriverInfoData->AllocInfoList;
   1137 
   1138   for (AllocLink = AllocInfoList->ForwardLink;
   1139        AllocLink != AllocInfoList;
   1140        AllocLink = AllocLink->ForwardLink) {
   1141     AllocInfoData = CR (
   1142                       AllocLink,
   1143                       MEMORY_PROFILE_ALLOC_INFO_DATA,
   1144                       Link,
   1145                       MEMORY_PROFILE_ALLOC_INFO_SIGNATURE
   1146                       );
   1147     AllocInfo = &AllocInfoData->AllocInfo;
   1148     if ((AllocInfo->Action & MEMORY_PROFILE_ACTION_BASIC_MASK) != BasicAction) {
   1149       continue;
   1150     }
   1151     switch (BasicAction) {
   1152       case MemoryProfileActionAllocatePages:
   1153         if ((AllocInfo->Buffer <= (PHYSICAL_ADDRESS) (UINTN) Buffer) &&
   1154             ((AllocInfo->Buffer + AllocInfo->Size) >= ((PHYSICAL_ADDRESS) (UINTN) Buffer + Size))) {
   1155           return AllocInfoData;
   1156         }
   1157         break;
   1158       case MemoryProfileActionAllocatePool:
   1159         if (AllocInfo->Buffer == (PHYSICAL_ADDRESS) (UINTN) Buffer) {
   1160           return AllocInfoData;
   1161         }
   1162         break;
   1163       default:
   1164         ASSERT (FALSE);
   1165         break;
   1166     }
   1167   }
   1168 
   1169   return NULL;
   1170 }
   1171 
   1172 /**
   1173   Update memory profile Free information.
   1174 
   1175   @param CallerAddress  Address of caller who call Free.
   1176   @param Action         This Free action.
   1177   @param Size           Buffer size.
   1178   @param Buffer         Buffer address.
   1179 
   1180   @return EFI_SUCCESS           Memory profile is updated.
   1181   @return EFI_UNSUPPORTED       Memory profile is unsupported.
   1182   @return EFI_NOT_FOUND         No matched allocate info found for free action.
   1183 
   1184 **/
   1185 EFI_STATUS
   1186 CoreUpdateProfileFree (
   1187   IN PHYSICAL_ADDRESS       CallerAddress,
   1188   IN MEMORY_PROFILE_ACTION  Action,
   1189   IN UINTN                  Size,
   1190   IN VOID                   *Buffer
   1191   )
   1192 {
   1193   MEMORY_PROFILE_CONTEXT           *Context;
   1194   MEMORY_PROFILE_DRIVER_INFO       *DriverInfo;
   1195   MEMORY_PROFILE_ALLOC_INFO        *AllocInfo;
   1196   MEMORY_PROFILE_CONTEXT_DATA      *ContextData;
   1197   MEMORY_PROFILE_DRIVER_INFO_DATA  *DriverInfoData;
   1198   LIST_ENTRY                       *DriverLink;
   1199   LIST_ENTRY                       *DriverInfoList;
   1200   MEMORY_PROFILE_DRIVER_INFO_DATA  *ThisDriverInfoData;
   1201   MEMORY_PROFILE_ALLOC_INFO_DATA   *AllocInfoData;
   1202   UINTN                            ProfileMemoryIndex;
   1203   MEMORY_PROFILE_ACTION            BasicAction;
   1204   BOOLEAN                          Found;
   1205 
   1206   BasicAction = Action & MEMORY_PROFILE_ACTION_BASIC_MASK;
   1207 
   1208   ContextData = GetMemoryProfileContext ();
   1209   if (ContextData == NULL) {
   1210     return EFI_UNSUPPORTED;
   1211   }
   1212 
   1213   DriverInfoData = GetMemoryProfileDriverInfoFromAddress (ContextData, CallerAddress);
   1214 
   1215   //
   1216   // Do not return if DriverInfoData == NULL here,
   1217   // because driver A might free memory allocated by driver B.
   1218   //
   1219 
   1220   //
   1221   // Need use do-while loop to find all possible records,
   1222   // because one address might be recorded multiple times.
   1223   //
   1224   Found = FALSE;
   1225   AllocInfoData = NULL;
   1226   do {
   1227     if (DriverInfoData != NULL) {
   1228       switch (BasicAction) {
   1229         case MemoryProfileActionFreePages:
   1230           AllocInfoData = GetMemoryProfileAllocInfoFromAddress (DriverInfoData, MemoryProfileActionAllocatePages, Size, Buffer);
   1231           break;
   1232         case MemoryProfileActionFreePool:
   1233           AllocInfoData = GetMemoryProfileAllocInfoFromAddress (DriverInfoData, MemoryProfileActionAllocatePool, 0, Buffer);
   1234           break;
   1235         default:
   1236           ASSERT (FALSE);
   1237           AllocInfoData = NULL;
   1238           break;
   1239       }
   1240     }
   1241     if (AllocInfoData == NULL) {
   1242       //
   1243       // Legal case, because driver A might free memory allocated by driver B, by some protocol.
   1244       //
   1245       DriverInfoList = ContextData->DriverInfoList;
   1246 
   1247       for (DriverLink = DriverInfoList->ForwardLink;
   1248            DriverLink != DriverInfoList;
   1249            DriverLink = DriverLink->ForwardLink) {
   1250         ThisDriverInfoData = CR (
   1251                                DriverLink,
   1252                                MEMORY_PROFILE_DRIVER_INFO_DATA,
   1253                                Link,
   1254                                MEMORY_PROFILE_DRIVER_INFO_SIGNATURE
   1255                                );
   1256         switch (BasicAction) {
   1257           case MemoryProfileActionFreePages:
   1258             AllocInfoData = GetMemoryProfileAllocInfoFromAddress (ThisDriverInfoData, MemoryProfileActionAllocatePages, Size, Buffer);
   1259             break;
   1260           case MemoryProfileActionFreePool:
   1261             AllocInfoData = GetMemoryProfileAllocInfoFromAddress (ThisDriverInfoData, MemoryProfileActionAllocatePool, 0, Buffer);
   1262             break;
   1263           default:
   1264             ASSERT (FALSE);
   1265             AllocInfoData = NULL;
   1266             break;
   1267         }
   1268         if (AllocInfoData != NULL) {
   1269           DriverInfoData = ThisDriverInfoData;
   1270           break;
   1271         }
   1272       }
   1273 
   1274       if (AllocInfoData == NULL) {
   1275         //
   1276         // If (!Found), no matched allocate info is found for this free action.
   1277         // It is because the specified memory type allocate actions have been filtered by
   1278         // CoreNeedRecordProfile(), but free actions may have no memory type information,
   1279         // they can not be filtered by CoreNeedRecordProfile(). Then, they will be
   1280         // filtered here.
   1281         //
   1282         // If (Found), it is normal exit path.
   1283         return (Found ? EFI_SUCCESS : EFI_NOT_FOUND);
   1284       }
   1285     }
   1286 
   1287     ASSERT (DriverInfoData != NULL);
   1288     ASSERT (AllocInfoData != NULL);
   1289 
   1290     Found = TRUE;
   1291 
   1292     Context = &ContextData->Context;
   1293     DriverInfo = &DriverInfoData->DriverInfo;
   1294     AllocInfo = &AllocInfoData->AllocInfo;
   1295 
   1296     DriverInfo->AllocRecordCount --;
   1297     //
   1298     // Update summary if and only if it is basic action.
   1299     //
   1300     if (AllocInfo->Action == (AllocInfo->Action & MEMORY_PROFILE_ACTION_BASIC_MASK)) {
   1301       ProfileMemoryIndex = GetProfileMemoryIndex (AllocInfo->MemoryType);
   1302 
   1303       Context->CurrentTotalUsage -= AllocInfo->Size;
   1304       Context->CurrentTotalUsageByType[ProfileMemoryIndex] -= AllocInfo->Size;
   1305 
   1306       DriverInfo->CurrentUsage -= AllocInfo->Size;
   1307       DriverInfo->CurrentUsageByType[ProfileMemoryIndex] -= AllocInfo->Size;
   1308     }
   1309 
   1310     RemoveEntryList (&AllocInfoData->Link);
   1311 
   1312     if (BasicAction == MemoryProfileActionFreePages) {
   1313       if (AllocInfo->Buffer != (PHYSICAL_ADDRESS) (UINTN) Buffer) {
   1314         CoreUpdateProfileAllocate (
   1315           AllocInfo->CallerAddress,
   1316           AllocInfo->Action,
   1317           AllocInfo->MemoryType,
   1318           (UINTN) ((PHYSICAL_ADDRESS) (UINTN) Buffer - AllocInfo->Buffer),
   1319           (VOID *) (UINTN) AllocInfo->Buffer,
   1320           AllocInfoData->ActionString
   1321           );
   1322       }
   1323       if (AllocInfo->Buffer + AllocInfo->Size != ((PHYSICAL_ADDRESS) (UINTN) Buffer + Size)) {
   1324         CoreUpdateProfileAllocate (
   1325           AllocInfo->CallerAddress,
   1326           AllocInfo->Action,
   1327           AllocInfo->MemoryType,
   1328           (UINTN) ((AllocInfo->Buffer + AllocInfo->Size) - ((PHYSICAL_ADDRESS) (UINTN) Buffer + Size)),
   1329           (VOID *) ((UINTN) Buffer + Size),
   1330           AllocInfoData->ActionString
   1331           );
   1332       }
   1333     }
   1334 
   1335     //
   1336     // Use CoreInternalFreePool() that will not update profile for this FreePool action.
   1337     //
   1338     CoreInternalFreePool (AllocInfoData, NULL);
   1339   } while (TRUE);
   1340 }
   1341 
   1342 /**
   1343   Update memory profile information.
   1344 
   1345   @param CallerAddress  Address of caller who call Allocate or Free.
   1346   @param Action         This Allocate or Free action.
   1347   @param MemoryType     Memory type.
   1348                         EfiMaxMemoryType means the MemoryType is unknown.
   1349   @param Size           Buffer size.
   1350   @param Buffer         Buffer address.
   1351   @param ActionString   String for memory profile action.
   1352                         Only needed for user defined allocate action.
   1353 
   1354   @return EFI_SUCCESS           Memory profile is updated.
   1355   @return EFI_UNSUPPORTED       Memory profile is unsupported,
   1356                                 or memory profile for the image is not required,
   1357                                 or memory profile for the memory type is not required.
   1358   @return EFI_ACCESS_DENIED     It is during memory profile data getting.
   1359   @return EFI_ABORTED           Memory profile recording is not enabled.
   1360   @return EFI_OUT_OF_RESOURCES  No enough resource to update memory profile for allocate action.
   1361   @return EFI_NOT_FOUND         No matched allocate info found for free action.
   1362 
   1363 **/
   1364 EFI_STATUS
   1365 EFIAPI
   1366 CoreUpdateProfile (
   1367   IN PHYSICAL_ADDRESS       CallerAddress,
   1368   IN MEMORY_PROFILE_ACTION  Action,
   1369   IN EFI_MEMORY_TYPE        MemoryType,
   1370   IN UINTN                  Size,       // Valid for AllocatePages/FreePages/AllocatePool
   1371   IN VOID                   *Buffer,
   1372   IN CHAR8                  *ActionString OPTIONAL
   1373   )
   1374 {
   1375   EFI_STATUS                    Status;
   1376   MEMORY_PROFILE_CONTEXT_DATA   *ContextData;
   1377   MEMORY_PROFILE_ACTION         BasicAction;
   1378 
   1379   if (!IS_UEFI_MEMORY_PROFILE_ENABLED) {
   1380     return EFI_UNSUPPORTED;
   1381   }
   1382 
   1383   if (mMemoryProfileGettingStatus) {
   1384     return EFI_ACCESS_DENIED;
   1385   }
   1386 
   1387   if (!mMemoryProfileRecordingEnable) {
   1388     return EFI_ABORTED;
   1389   }
   1390 
   1391   //
   1392   // Get the basic action to know how to process the record
   1393   //
   1394   BasicAction = Action & MEMORY_PROFILE_ACTION_BASIC_MASK;
   1395 
   1396   //
   1397   // EfiMaxMemoryType means the MemoryType is unknown.
   1398   //
   1399   if (MemoryType != EfiMaxMemoryType) {
   1400     //
   1401     // Only record limited MemoryType.
   1402     //
   1403     if (!CoreNeedRecordProfile (MemoryType)) {
   1404       return EFI_UNSUPPORTED;
   1405     }
   1406   }
   1407 
   1408   ContextData = GetMemoryProfileContext ();
   1409   if (ContextData == NULL) {
   1410     return EFI_UNSUPPORTED;
   1411   }
   1412 
   1413   CoreAcquireMemoryProfileLock ();
   1414   switch (BasicAction) {
   1415     case MemoryProfileActionAllocatePages:
   1416       Status = CoreUpdateProfileAllocate (CallerAddress, Action, MemoryType, Size, Buffer, ActionString);
   1417       break;
   1418     case MemoryProfileActionFreePages:
   1419       Status = CoreUpdateProfileFree (CallerAddress, Action, Size, Buffer);
   1420       break;
   1421     case MemoryProfileActionAllocatePool:
   1422       Status = CoreUpdateProfileAllocate (CallerAddress, Action, MemoryType, Size, Buffer, ActionString);
   1423       break;
   1424     case MemoryProfileActionFreePool:
   1425       Status = CoreUpdateProfileFree (CallerAddress, Action, 0, Buffer);
   1426       break;
   1427     default:
   1428       ASSERT (FALSE);
   1429       Status = EFI_UNSUPPORTED;
   1430       break;
   1431   }
   1432   CoreReleaseMemoryProfileLock ();
   1433 
   1434   return Status;
   1435 }
   1436 
   1437 ////////////////////
   1438 
   1439 /**
   1440   Get memory profile data size.
   1441 
   1442   @return Memory profile data size.
   1443 
   1444 **/
   1445 UINTN
   1446 MemoryProfileGetDataSize (
   1447   VOID
   1448   )
   1449 {
   1450   MEMORY_PROFILE_CONTEXT_DATA       *ContextData;
   1451   MEMORY_PROFILE_DRIVER_INFO_DATA   *DriverInfoData;
   1452   MEMORY_PROFILE_ALLOC_INFO_DATA    *AllocInfoData;
   1453   LIST_ENTRY                        *DriverInfoList;
   1454   LIST_ENTRY                        *DriverLink;
   1455   LIST_ENTRY                        *AllocInfoList;
   1456   LIST_ENTRY                        *AllocLink;
   1457   UINTN                             TotalSize;
   1458 
   1459 
   1460   ContextData = GetMemoryProfileContext ();
   1461   if (ContextData == NULL) {
   1462     return 0;
   1463   }
   1464 
   1465   TotalSize = sizeof (MEMORY_PROFILE_CONTEXT);
   1466 
   1467   DriverInfoList = ContextData->DriverInfoList;
   1468   for (DriverLink = DriverInfoList->ForwardLink;
   1469        DriverLink != DriverInfoList;
   1470        DriverLink = DriverLink->ForwardLink) {
   1471     DriverInfoData = CR (
   1472                        DriverLink,
   1473                        MEMORY_PROFILE_DRIVER_INFO_DATA,
   1474                        Link,
   1475                        MEMORY_PROFILE_DRIVER_INFO_SIGNATURE
   1476                        );
   1477     TotalSize += DriverInfoData->DriverInfo.Header.Length;
   1478 
   1479     AllocInfoList = DriverInfoData->AllocInfoList;
   1480     for (AllocLink = AllocInfoList->ForwardLink;
   1481          AllocLink != AllocInfoList;
   1482          AllocLink = AllocLink->ForwardLink) {
   1483       AllocInfoData = CR (
   1484                         AllocLink,
   1485                         MEMORY_PROFILE_ALLOC_INFO_DATA,
   1486                         Link,
   1487                         MEMORY_PROFILE_ALLOC_INFO_SIGNATURE
   1488                         );
   1489       TotalSize += AllocInfoData->AllocInfo.Header.Length;
   1490     }
   1491   }
   1492 
   1493   return TotalSize;
   1494 }
   1495 
   1496 /**
   1497   Copy memory profile data.
   1498 
   1499   @param ProfileBuffer  The buffer to hold memory profile data.
   1500 
   1501 **/
   1502 VOID
   1503 MemoryProfileCopyData (
   1504   IN VOID   *ProfileBuffer
   1505   )
   1506 {
   1507   MEMORY_PROFILE_CONTEXT            *Context;
   1508   MEMORY_PROFILE_DRIVER_INFO        *DriverInfo;
   1509   MEMORY_PROFILE_ALLOC_INFO         *AllocInfo;
   1510   MEMORY_PROFILE_CONTEXT_DATA       *ContextData;
   1511   MEMORY_PROFILE_DRIVER_INFO_DATA   *DriverInfoData;
   1512   MEMORY_PROFILE_ALLOC_INFO_DATA    *AllocInfoData;
   1513   LIST_ENTRY                        *DriverInfoList;
   1514   LIST_ENTRY                        *DriverLink;
   1515   LIST_ENTRY                        *AllocInfoList;
   1516   LIST_ENTRY                        *AllocLink;
   1517   UINTN                             PdbSize;
   1518   UINTN                             ActionStringSize;
   1519 
   1520   ContextData = GetMemoryProfileContext ();
   1521   if (ContextData == NULL) {
   1522     return ;
   1523   }
   1524 
   1525   Context = ProfileBuffer;
   1526   CopyMem (Context, &ContextData->Context, sizeof (MEMORY_PROFILE_CONTEXT));
   1527   DriverInfo = (MEMORY_PROFILE_DRIVER_INFO *) (Context + 1);
   1528 
   1529   DriverInfoList = ContextData->DriverInfoList;
   1530   for (DriverLink = DriverInfoList->ForwardLink;
   1531        DriverLink != DriverInfoList;
   1532        DriverLink = DriverLink->ForwardLink) {
   1533     DriverInfoData = CR (
   1534                        DriverLink,
   1535                        MEMORY_PROFILE_DRIVER_INFO_DATA,
   1536                        Link,
   1537                        MEMORY_PROFILE_DRIVER_INFO_SIGNATURE
   1538                        );
   1539     CopyMem (DriverInfo, &DriverInfoData->DriverInfo, sizeof (MEMORY_PROFILE_DRIVER_INFO));
   1540     if (DriverInfo->PdbStringOffset != 0) {
   1541       PdbSize = AsciiStrSize (DriverInfoData->PdbString);
   1542       CopyMem ((VOID *) ((UINTN) DriverInfo + DriverInfo->PdbStringOffset), DriverInfoData->PdbString, PdbSize);
   1543     }
   1544     AllocInfo = (MEMORY_PROFILE_ALLOC_INFO *) ((UINTN) DriverInfo + DriverInfo->Header.Length);
   1545 
   1546     AllocInfoList = DriverInfoData->AllocInfoList;
   1547     for (AllocLink = AllocInfoList->ForwardLink;
   1548          AllocLink != AllocInfoList;
   1549          AllocLink = AllocLink->ForwardLink) {
   1550       AllocInfoData = CR (
   1551                         AllocLink,
   1552                         MEMORY_PROFILE_ALLOC_INFO_DATA,
   1553                         Link,
   1554                         MEMORY_PROFILE_ALLOC_INFO_SIGNATURE
   1555                         );
   1556       CopyMem (AllocInfo, &AllocInfoData->AllocInfo, sizeof (MEMORY_PROFILE_ALLOC_INFO));
   1557       if (AllocInfo->ActionStringOffset != 0) {
   1558         ActionStringSize = AsciiStrSize (AllocInfoData->ActionString);
   1559         CopyMem ((VOID *) ((UINTN) AllocInfo + AllocInfo->ActionStringOffset), AllocInfoData->ActionString, ActionStringSize);
   1560       }
   1561       AllocInfo = (MEMORY_PROFILE_ALLOC_INFO *) ((UINTN) AllocInfo + AllocInfo->Header.Length);
   1562     }
   1563 
   1564     DriverInfo = (MEMORY_PROFILE_DRIVER_INFO *)  AllocInfo;
   1565   }
   1566 }
   1567 
   1568 /**
   1569   Get memory profile data.
   1570 
   1571   @param[in]      This              The EDKII_MEMORY_PROFILE_PROTOCOL instance.
   1572   @param[in, out] ProfileSize       On entry, points to the size in bytes of the ProfileBuffer.
   1573                                     On return, points to the size of the data returned in ProfileBuffer.
   1574   @param[out]     ProfileBuffer     Profile buffer.
   1575 
   1576   @return EFI_SUCCESS               Get the memory profile data successfully.
   1577   @return EFI_UNSUPPORTED           Memory profile is unsupported.
   1578   @return EFI_BUFFER_TO_SMALL       The ProfileSize is too small for the resulting data.
   1579                                     ProfileSize is updated with the size required.
   1580 
   1581 **/
   1582 EFI_STATUS
   1583 EFIAPI
   1584 ProfileProtocolGetData (
   1585   IN     EDKII_MEMORY_PROFILE_PROTOCOL  *This,
   1586   IN OUT UINT64                         *ProfileSize,
   1587      OUT VOID                           *ProfileBuffer
   1588   )
   1589 {
   1590   UINTN                                 Size;
   1591   MEMORY_PROFILE_CONTEXT_DATA           *ContextData;
   1592   BOOLEAN                               MemoryProfileGettingStatus;
   1593 
   1594   ContextData = GetMemoryProfileContext ();
   1595   if (ContextData == NULL) {
   1596     return EFI_UNSUPPORTED;
   1597   }
   1598 
   1599   MemoryProfileGettingStatus = mMemoryProfileGettingStatus;
   1600   mMemoryProfileGettingStatus = TRUE;
   1601 
   1602   Size = MemoryProfileGetDataSize ();
   1603 
   1604   if (*ProfileSize < Size) {
   1605     *ProfileSize = Size;
   1606     mMemoryProfileGettingStatus = MemoryProfileGettingStatus;
   1607     return EFI_BUFFER_TOO_SMALL;
   1608   }
   1609 
   1610   *ProfileSize = Size;
   1611   MemoryProfileCopyData (ProfileBuffer);
   1612 
   1613   mMemoryProfileGettingStatus = MemoryProfileGettingStatus;
   1614   return EFI_SUCCESS;
   1615 }
   1616 
   1617 /**
   1618   Register image to memory profile.
   1619 
   1620   @param[in] This               The EDKII_MEMORY_PROFILE_PROTOCOL instance.
   1621   @param[in] FilePath           File path of the image.
   1622   @param[in] ImageBase          Image base address.
   1623   @param[in] ImageSize          Image size.
   1624   @param[in] FileType           File type of the image.
   1625 
   1626   @return EFI_SUCCESS           Register successfully.
   1627   @return EFI_UNSUPPORTED       Memory profile is unsupported,
   1628                                 or memory profile for the image is not required.
   1629   @return EFI_OUT_OF_RESOURCES  No enough resource for this register.
   1630 
   1631 **/
   1632 EFI_STATUS
   1633 EFIAPI
   1634 ProfileProtocolRegisterImage (
   1635   IN EDKII_MEMORY_PROFILE_PROTOCOL  *This,
   1636   IN EFI_DEVICE_PATH_PROTOCOL       *FilePath,
   1637   IN PHYSICAL_ADDRESS               ImageBase,
   1638   IN UINT64                         ImageSize,
   1639   IN EFI_FV_FILETYPE                FileType
   1640   )
   1641 {
   1642   EFI_STATUS                        Status;
   1643   LOADED_IMAGE_PRIVATE_DATA         DriverEntry;
   1644   VOID                              *EntryPointInImage;
   1645 
   1646   ZeroMem (&DriverEntry, sizeof (DriverEntry));
   1647   DriverEntry.Info.FilePath = FilePath;
   1648   DriverEntry.ImageContext.ImageAddress = ImageBase;
   1649   DriverEntry.ImageContext.ImageSize = ImageSize;
   1650   Status = InternalPeCoffGetEntryPoint ((VOID *) (UINTN) ImageBase, &EntryPointInImage);
   1651   ASSERT_EFI_ERROR (Status);
   1652   DriverEntry.ImageContext.EntryPoint = (PHYSICAL_ADDRESS) (UINTN) EntryPointInImage;
   1653   DriverEntry.ImageContext.ImageType = InternalPeCoffGetSubsystem ((VOID *) (UINTN) ImageBase);
   1654 
   1655   return RegisterMemoryProfileImage (&DriverEntry, FileType);
   1656 }
   1657 
   1658 /**
   1659   Unregister image from memory profile.
   1660 
   1661   @param[in] This               The EDKII_MEMORY_PROFILE_PROTOCOL instance.
   1662   @param[in] FilePath           File path of the image.
   1663   @param[in] ImageBase          Image base address.
   1664   @param[in] ImageSize          Image size.
   1665 
   1666   @return EFI_SUCCESS           Unregister successfully.
   1667   @return EFI_UNSUPPORTED       Memory profile is unsupported,
   1668                                 or memory profile for the image is not required.
   1669   @return EFI_NOT_FOUND         The image is not found.
   1670 
   1671 **/
   1672 EFI_STATUS
   1673 EFIAPI
   1674 ProfileProtocolUnregisterImage (
   1675   IN EDKII_MEMORY_PROFILE_PROTOCOL  *This,
   1676   IN EFI_DEVICE_PATH_PROTOCOL       *FilePath,
   1677   IN PHYSICAL_ADDRESS               ImageBase,
   1678   IN UINT64                         ImageSize
   1679   )
   1680 {
   1681   EFI_STATUS                        Status;
   1682   LOADED_IMAGE_PRIVATE_DATA         DriverEntry;
   1683   VOID                              *EntryPointInImage;
   1684 
   1685   ZeroMem (&DriverEntry, sizeof (DriverEntry));
   1686   DriverEntry.Info.FilePath = FilePath;
   1687   DriverEntry.ImageContext.ImageAddress = ImageBase;
   1688   DriverEntry.ImageContext.ImageSize = ImageSize;
   1689   Status = InternalPeCoffGetEntryPoint ((VOID *) (UINTN) ImageBase, &EntryPointInImage);
   1690   ASSERT_EFI_ERROR (Status);
   1691   DriverEntry.ImageContext.EntryPoint = (PHYSICAL_ADDRESS) (UINTN) EntryPointInImage;
   1692 
   1693   return UnregisterMemoryProfileImage (&DriverEntry);
   1694 }
   1695 
   1696 /**
   1697   Get memory profile recording state.
   1698 
   1699   @param[in]  This              The EDKII_MEMORY_PROFILE_PROTOCOL instance.
   1700   @param[out] RecordingState    Recording state.
   1701 
   1702   @return EFI_SUCCESS           Memory profile recording state is returned.
   1703   @return EFI_UNSUPPORTED       Memory profile is unsupported.
   1704   @return EFI_INVALID_PARAMETER RecordingState is NULL.
   1705 
   1706 **/
   1707 EFI_STATUS
   1708 EFIAPI
   1709 ProfileProtocolGetRecordingState (
   1710   IN EDKII_MEMORY_PROFILE_PROTOCOL      *This,
   1711   OUT BOOLEAN                           *RecordingState
   1712   )
   1713 {
   1714   MEMORY_PROFILE_CONTEXT_DATA       *ContextData;
   1715 
   1716   ContextData = GetMemoryProfileContext ();
   1717   if (ContextData == NULL) {
   1718     return EFI_UNSUPPORTED;
   1719   }
   1720 
   1721   if (RecordingState == NULL) {
   1722     return EFI_INVALID_PARAMETER;
   1723   }
   1724   *RecordingState = mMemoryProfileRecordingEnable;
   1725   return EFI_SUCCESS;
   1726 }
   1727 
   1728 /**
   1729   Set memory profile recording state.
   1730 
   1731   @param[in] This               The EDKII_MEMORY_PROFILE_PROTOCOL instance.
   1732   @param[in] RecordingState     Recording state.
   1733 
   1734   @return EFI_SUCCESS           Set memory profile recording state successfully.
   1735   @return EFI_UNSUPPORTED       Memory profile is unsupported.
   1736 
   1737 **/
   1738 EFI_STATUS
   1739 EFIAPI
   1740 ProfileProtocolSetRecordingState (
   1741   IN EDKII_MEMORY_PROFILE_PROTOCOL      *This,
   1742   IN BOOLEAN                            RecordingState
   1743   )
   1744 {
   1745   MEMORY_PROFILE_CONTEXT_DATA       *ContextData;
   1746 
   1747   ContextData = GetMemoryProfileContext ();
   1748   if (ContextData == NULL) {
   1749     return EFI_UNSUPPORTED;
   1750   }
   1751 
   1752   mMemoryProfileRecordingEnable = RecordingState;
   1753   return EFI_SUCCESS;
   1754 }
   1755 
   1756 /**
   1757   Record memory profile of multilevel caller.
   1758 
   1759   @param[in] This               The EDKII_MEMORY_PROFILE_PROTOCOL instance.
   1760   @param[in] CallerAddress      Address of caller.
   1761   @param[in] Action             Memory profile action.
   1762   @param[in] MemoryType         Memory type.
   1763                                 EfiMaxMemoryType means the MemoryType is unknown.
   1764   @param[in] Buffer             Buffer address.
   1765   @param[in] Size               Buffer size.
   1766   @param[in] ActionString       String for memory profile action.
   1767                                 Only needed for user defined allocate action.
   1768 
   1769   @return EFI_SUCCESS           Memory profile is updated.
   1770   @return EFI_UNSUPPORTED       Memory profile is unsupported,
   1771                                 or memory profile for the image is not required,
   1772                                 or memory profile for the memory type is not required.
   1773   @return EFI_ACCESS_DENIED     It is during memory profile data getting.
   1774   @return EFI_ABORTED           Memory profile recording is not enabled.
   1775   @return EFI_OUT_OF_RESOURCES  No enough resource to update memory profile for allocate action.
   1776   @return EFI_NOT_FOUND         No matched allocate info found for free action.
   1777 
   1778 **/
   1779 EFI_STATUS
   1780 EFIAPI
   1781 ProfileProtocolRecord (
   1782   IN EDKII_MEMORY_PROFILE_PROTOCOL      *This,
   1783   IN PHYSICAL_ADDRESS                   CallerAddress,
   1784   IN MEMORY_PROFILE_ACTION              Action,
   1785   IN EFI_MEMORY_TYPE                    MemoryType,
   1786   IN VOID                               *Buffer,
   1787   IN UINTN                              Size,
   1788   IN CHAR8                              *ActionString OPTIONAL
   1789   )
   1790 {
   1791   return CoreUpdateProfile (CallerAddress, Action, MemoryType, Size, Buffer, ActionString);
   1792 }
   1793 
   1794 ////////////////////
   1795