2 Support routines for UEFI memory profile.
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.
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.
18 #define IS_UEFI_MEMORY_PROFILE_ENABLED ((PcdGet8 (PcdMemoryProfilePropertyMask) & BIT0) != 0)
20 #define GET_OCCUPIED_SIZE(ActualSize, Alignment) \
21 ((ActualSize) + (((Alignment) - ((ActualSize) & ((Alignment) - 1))) & ((Alignment) - 1)))
25 MEMORY_PROFILE_CONTEXT Context
;
26 LIST_ENTRY
*DriverInfoList
;
27 } MEMORY_PROFILE_CONTEXT_DATA
;
31 MEMORY_PROFILE_DRIVER_INFO DriverInfo
;
32 LIST_ENTRY
*AllocInfoList
;
35 } MEMORY_PROFILE_DRIVER_INFO_DATA
;
39 MEMORY_PROFILE_ALLOC_INFO AllocInfo
;
42 } MEMORY_PROFILE_ALLOC_INFO_DATA
;
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
,
50 MEMORY_PROFILE_CONTEXT_SIGNATURE
,
51 sizeof (MEMORY_PROFILE_CONTEXT
),
52 MEMORY_PROFILE_CONTEXT_REVISION
64 GLOBAL_REMOVE_IF_UNREFERENCED MEMORY_PROFILE_CONTEXT_DATA
*mMemoryProfileContextPtr
= NULL
;
66 GLOBAL_REMOVE_IF_UNREFERENCED EFI_LOCK mMemoryProfileLock
= EFI_INITIALIZE_LOCK_VARIABLE (TPL_NOTIFY
);
67 GLOBAL_REMOVE_IF_UNREFERENCED BOOLEAN mMemoryProfileGettingStatus
= FALSE
;
68 GLOBAL_REMOVE_IF_UNREFERENCED BOOLEAN mMemoryProfileRecordingEnable
= MEMORY_PROFILE_RECORDING_DISABLE
;
69 GLOBAL_REMOVE_IF_UNREFERENCED EFI_DEVICE_PATH_PROTOCOL
*mMemoryProfileDriverPath
;
70 GLOBAL_REMOVE_IF_UNREFERENCED UINTN mMemoryProfileDriverPathSize
;
73 Get memory profile data.
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.
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.
88 ProfileProtocolGetData (
89 IN EDKII_MEMORY_PROFILE_PROTOCOL
*This
,
90 IN OUT UINT64
*ProfileSize
,
91 OUT VOID
*ProfileBuffer
95 Register image to memory profile.
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.
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.
111 ProfileProtocolRegisterImage (
112 IN EDKII_MEMORY_PROFILE_PROTOCOL
*This
,
113 IN EFI_DEVICE_PATH_PROTOCOL
*FilePath
,
114 IN PHYSICAL_ADDRESS ImageBase
,
116 IN EFI_FV_FILETYPE FileType
120 Unregister image from memory profile.
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.
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.
135 ProfileProtocolUnregisterImage (
136 IN EDKII_MEMORY_PROFILE_PROTOCOL
*This
,
137 IN EFI_DEVICE_PATH_PROTOCOL
*FilePath
,
138 IN PHYSICAL_ADDRESS ImageBase
,
143 Get memory profile recording state.
145 @param[in] This The EDKII_MEMORY_PROFILE_PROTOCOL instance.
146 @param[out] RecordingState Recording state.
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.
155 ProfileProtocolGetRecordingState (
156 IN EDKII_MEMORY_PROFILE_PROTOCOL
*This
,
157 OUT BOOLEAN
*RecordingState
161 Set memory profile recording state.
163 @param[in] This The EDKII_MEMORY_PROFILE_PROTOCOL instance.
164 @param[in] RecordingState Recording state.
166 @return EFI_SUCCESS Set memory profile recording state successfully.
167 @return EFI_UNSUPPORTED Memory profile is unsupported.
172 ProfileProtocolSetRecordingState (
173 IN EDKII_MEMORY_PROFILE_PROTOCOL
*This
,
174 IN BOOLEAN RecordingState
178 Record memory profile of multilevel caller.
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.
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.
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
,
209 IN CHAR8
*ActionString OPTIONAL
212 GLOBAL_REMOVE_IF_UNREFERENCED EDKII_MEMORY_PROFILE_PROTOCOL mProfileProtocol
= {
213 ProfileProtocolGetData
,
214 ProfileProtocolRegisterImage
,
215 ProfileProtocolUnregisterImage
,
216 ProfileProtocolGetRecordingState
,
217 ProfileProtocolSetRecordingState
,
218 ProfileProtocolRecord
,
222 Acquire lock on mMemoryProfileLock.
225 CoreAcquireMemoryProfileLock (
229 CoreAcquireLock (&mMemoryProfileLock
);
233 Release lock on mMemoryProfileLock.
236 CoreReleaseMemoryProfileLock (
240 CoreReleaseLock (&mMemoryProfileLock
);
244 Return memory profile context.
246 @return Memory profile context.
249 MEMORY_PROFILE_CONTEXT_DATA
*
250 GetMemoryProfileContext (
254 return mMemoryProfileContextPtr
;
258 Retrieves the magic value from the PE/COFF header.
260 @param Hdr The buffer in which to return the PE32, PE32+, or TE header.
262 @return EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC - Image is PE32
263 @return EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC - Image is PE32+
267 InternalPeCoffGetPeHeaderMagicValue (
268 IN EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION Hdr
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
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
;
281 // Return the magic value from the PC/COFF Optional Header
283 return Hdr
.Pe32
->OptionalHeader
.Magic
;
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().
290 @param Pe32Data The pointer to the PE/COFF image that is loaded in system memory.
292 @return The Subsystem of the PE/COFF image.
296 InternalPeCoffGetSubsystem (
300 EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION Hdr
;
301 EFI_IMAGE_DOS_HEADER
*DosHdr
;
304 ASSERT (Pe32Data
!= NULL
);
306 DosHdr
= (EFI_IMAGE_DOS_HEADER
*) Pe32Data
;
307 if (DosHdr
->e_magic
== EFI_IMAGE_DOS_SIGNATURE
) {
309 // DOS image header is present, so read the PE header after the DOS image header.
311 Hdr
.Pe32
= (EFI_IMAGE_NT_HEADERS32
*) ((UINTN
) Pe32Data
+ (UINTN
) ((DosHdr
->e_lfanew
) & 0x0ffff));
314 // DOS image header is not present, so PE header is at the image base.
316 Hdr
.Pe32
= (EFI_IMAGE_NT_HEADERS32
*) Pe32Data
;
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
;
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.
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().
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.
346 @retval RETURN_SUCCESS EntryPoint was returned.
347 @retval RETURN_INVALID_PARAMETER The entry point could not be found in the PE/COFF image.
351 InternalPeCoffGetEntryPoint (
353 OUT VOID
**EntryPoint
356 EFI_IMAGE_DOS_HEADER
*DosHdr
;
357 EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION Hdr
;
359 ASSERT (Pe32Data
!= NULL
);
360 ASSERT (EntryPoint
!= NULL
);
362 DosHdr
= (EFI_IMAGE_DOS_HEADER
*) Pe32Data
;
363 if (DosHdr
->e_magic
== EFI_IMAGE_DOS_SIGNATURE
) {
365 // DOS image header is present, so read the PE header after the DOS image header.
367 Hdr
.Pe32
= (EFI_IMAGE_NT_HEADERS32
*) ((UINTN
) Pe32Data
+ (UINTN
) ((DosHdr
->e_lfanew
) & 0x0ffff));
370 // DOS image header is not present, so PE header is at the image base.
372 Hdr
.Pe32
= (EFI_IMAGE_NT_HEADERS32
*) Pe32Data
;
376 // Calculate the entry point relative to the start of the image.
377 // AddressOfEntryPoint is common for PE32 & PE32+
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
;
387 return RETURN_UNSUPPORTED
;
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.
401 @return Pointer to memory profile driver info.
404 MEMORY_PROFILE_DRIVER_INFO_DATA
*
406 IN MEMORY_PROFILE_CONTEXT_DATA
*ContextData
,
407 IN EFI_GUID
*FileName
,
408 IN PHYSICAL_ADDRESS ImageBase
,
410 IN PHYSICAL_ADDRESS EntryPoint
,
411 IN UINT16 ImageSubsystem
,
412 IN EFI_FV_FILETYPE FileType
416 MEMORY_PROFILE_DRIVER_INFO
*DriverInfo
;
417 MEMORY_PROFILE_DRIVER_INFO_DATA
*DriverInfoData
;
418 VOID
*EntryPointInImage
;
421 UINTN PdbOccupiedSize
;
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
));
435 // Use CoreInternalAllocatePool() that will not update profile for this AllocatePool action.
437 Status
= CoreInternalAllocatePool (
439 sizeof (*DriverInfoData
) + sizeof (LIST_ENTRY
) + PdbSize
,
440 (VOID
**) &DriverInfoData
442 if (EFI_ERROR (Status
)) {
445 ASSERT (DriverInfoData
!= NULL
);
447 ZeroMem (DriverInfoData
, sizeof (*DriverInfoData
));
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
));
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
)))) {
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.
466 Status
= InternalPeCoffGetEntryPoint ((VOID
*) (UINTN
) ImageBase
, &EntryPointInImage
);
467 ASSERT_EFI_ERROR (Status
);
468 DriverInfo
->ImageBase
= ImageBase
+ EntryPoint
- (PHYSICAL_ADDRESS
) (UINTN
) EntryPointInImage
;
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;
477 DriverInfo
->PdbStringOffset
= (UINT16
) sizeof (MEMORY_PROFILE_DRIVER_INFO
);
478 DriverInfoData
->PdbString
= (CHAR8
*) (DriverInfoData
->AllocInfoList
+ 1);
479 CopyMem (DriverInfoData
->PdbString
, PdbString
, PdbSize
);
481 DriverInfo
->PdbStringOffset
= 0;
482 DriverInfoData
->PdbString
= NULL
;
485 InsertTailList (ContextData
->DriverInfoList
, &DriverInfoData
->Link
);
486 ContextData
->Context
.ImageCount
++;
487 ContextData
->Context
.TotalImageSize
+= DriverInfo
->ImageSize
;
489 return DriverInfoData
;
493 Return if record for this driver is needed..
495 @param DriverFilePath Driver file path.
497 @retval TRUE Record for this driver is needed.
498 @retval FALSE Record for this driver is not needed.
502 NeedRecordThisDriver (
503 IN EFI_DEVICE_PATH_PROTOCOL
*DriverFilePath
506 EFI_DEVICE_PATH_PROTOCOL
*TmpDevicePath
;
507 EFI_DEVICE_PATH_PROTOCOL
*DevicePathInstance
;
508 UINTN DevicePathSize
;
511 if (!IsDevicePathValid (mMemoryProfileDriverPath
, mMemoryProfileDriverPathSize
)) {
513 // Invalid Device Path means record all.
519 // Record FilePath without END node.
521 FilePathSize
= GetDevicePathSize (DriverFilePath
) - sizeof(EFI_DEVICE_PATH_PROTOCOL
);
523 DevicePathInstance
= mMemoryProfileDriverPath
;
526 // Find END node (it might be END_ENTIRE or END_INSTANCE).
528 TmpDevicePath
= DevicePathInstance
;
529 while (!IsDevicePathEndType (TmpDevicePath
)) {
530 TmpDevicePath
= NextDevicePathNode (TmpDevicePath
);
534 // Do not compare END node.
536 DevicePathSize
= (UINTN
)TmpDevicePath
- (UINTN
)DevicePathInstance
;
537 if ((FilePathSize
== DevicePathSize
) &&
538 (CompareMem (DriverFilePath
, DevicePathInstance
, DevicePathSize
) == 0)) {
543 // Get next instance.
545 DevicePathInstance
= (EFI_DEVICE_PATH_PROTOCOL
*)((UINTN
)DevicePathInstance
+ DevicePathSize
+ DevicePathNodeLength(TmpDevicePath
));
546 } while (DevicePathSubType (TmpDevicePath
) != END_ENTIRE_DEVICE_PATH_SUBTYPE
);
552 Register DXE Core to memory profile.
554 @param HobStart The start address of the HOB.
555 @param ContextData Memory profile context.
557 @retval TRUE Register success.
558 @retval FALSE Register fail.
564 IN MEMORY_PROFILE_CONTEXT_DATA
*ContextData
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
;
573 ASSERT (ContextData
!= NULL
);
576 // Searching for image hob
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
)) {
586 DxeCoreHob
.Raw
= GET_NEXT_HOB (DxeCoreHob
);
588 ASSERT (DxeCoreHob
.Raw
!= NULL
);
590 FilePath
= (MEDIA_FW_VOL_FILEPATH_DEVICE_PATH
*) TempBuffer
;
591 EfiInitializeFwVolDevicepathNode (FilePath
, &DxeCoreHob
.MemoryAllocationModule
->ModuleName
);
592 SetDevicePathEndNode (FilePath
+ 1);
594 if (!NeedRecordThisDriver ((EFI_DEVICE_PATH_PROTOCOL
*) FilePath
)) {
598 ImageBase
= DxeCoreHob
.MemoryAllocationModule
->MemoryAllocationHeader
.MemoryBaseAddress
;
599 DriverInfoData
= BuildDriverInfo (
601 &DxeCoreHob
.MemoryAllocationModule
->ModuleName
,
603 DxeCoreHob
.MemoryAllocationModule
->MemoryAllocationHeader
.MemoryLength
,
604 DxeCoreHob
.MemoryAllocationModule
->EntryPoint
,
605 InternalPeCoffGetSubsystem ((VOID
*) (UINTN
) ImageBase
),
606 EFI_FV_FILETYPE_DXE_CORE
608 if (DriverInfoData
== NULL
) {
616 Initialize memory profile.
618 @param HobStart The start address of the HOB.
626 MEMORY_PROFILE_CONTEXT_DATA
*ContextData
;
628 if (!IS_UEFI_MEMORY_PROFILE_ENABLED
) {
632 ContextData
= GetMemoryProfileContext ();
633 if (ContextData
!= NULL
) {
637 mMemoryProfileGettingStatus
= FALSE
;
638 if ((PcdGet8 (PcdMemoryProfilePropertyMask
) & BIT7
) != 0) {
639 mMemoryProfileRecordingEnable
= MEMORY_PROFILE_RECORDING_DISABLE
;
641 mMemoryProfileRecordingEnable
= MEMORY_PROFILE_RECORDING_ENABLE
;
643 mMemoryProfileDriverPathSize
= PcdGetSize (PcdMemoryProfileDriverPath
);
644 mMemoryProfileDriverPath
= AllocateCopyPool (mMemoryProfileDriverPathSize
, PcdGetPtr (PcdMemoryProfileDriverPath
));
645 mMemoryProfileContextPtr
= &mMemoryProfileContext
;
647 RegisterDxeCore (HobStart
, &mMemoryProfileContext
);
649 DEBUG ((EFI_D_INFO
, "MemoryProfileInit MemoryProfileContext - 0x%x\n", &mMemoryProfileContext
));
653 Install memory profile protocol.
657 MemoryProfileInstallProtocol (
664 if (!IS_UEFI_MEMORY_PROFILE_ENABLED
) {
669 Status
= CoreInstallMultipleProtocolInterfaces (
671 &gEdkiiMemoryProfileGuid
,
675 ASSERT_EFI_ERROR (Status
);
679 Get the GUID file name from the file path.
681 @param FilePath File path.
683 @return The GUID file name from the file path.
687 GetFileNameFromFilePath (
688 IN EFI_DEVICE_PATH_PROTOCOL
*FilePath
691 MEDIA_FW_VOL_FILEPATH_DEVICE_PATH
*ThisFilePath
;
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
) {
702 ThisFilePath
= (MEDIA_FW_VOL_FILEPATH_DEVICE_PATH
*) NextDevicePathNode (ThisFilePath
);
710 Register image to memory profile.
712 @param DriverEntry Image info.
713 @param FileType Image file type.
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.
722 RegisterMemoryProfileImage (
723 IN LOADED_IMAGE_PRIVATE_DATA
*DriverEntry
,
724 IN EFI_FV_FILETYPE FileType
727 MEMORY_PROFILE_CONTEXT_DATA
*ContextData
;
728 MEMORY_PROFILE_DRIVER_INFO_DATA
*DriverInfoData
;
730 if (!IS_UEFI_MEMORY_PROFILE_ENABLED
) {
731 return EFI_UNSUPPORTED
;
734 if (!NeedRecordThisDriver (DriverEntry
->Info
.FilePath
)) {
735 return EFI_UNSUPPORTED
;
738 ContextData
= GetMemoryProfileContext ();
739 if (ContextData
== NULL
) {
740 return EFI_UNSUPPORTED
;
743 DriverInfoData
= BuildDriverInfo (
745 GetFileNameFromFilePath (DriverEntry
->Info
.FilePath
),
746 DriverEntry
->ImageContext
.ImageAddress
,
747 DriverEntry
->ImageContext
.ImageSize
,
748 DriverEntry
->ImageContext
.EntryPoint
,
749 DriverEntry
->ImageContext
.ImageType
,
752 if (DriverInfoData
== NULL
) {
753 return EFI_OUT_OF_RESOURCES
;
760 Search image from memory profile.
762 @param ContextData Memory profile context.
763 @param FileName Image file name.
764 @param Address Image Address.
766 @return Pointer to memory profile driver info.
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
776 MEMORY_PROFILE_DRIVER_INFO
*DriverInfo
;
777 MEMORY_PROFILE_DRIVER_INFO_DATA
*DriverInfoData
;
778 LIST_ENTRY
*DriverLink
;
779 LIST_ENTRY
*DriverInfoList
;
781 DriverInfoList
= ContextData
->DriverInfoList
;
783 for (DriverLink
= DriverInfoList
->ForwardLink
;
784 DriverLink
!= DriverInfoList
;
785 DriverLink
= DriverLink
->ForwardLink
) {
786 DriverInfoData
= CR (
788 MEMORY_PROFILE_DRIVER_INFO_DATA
,
790 MEMORY_PROFILE_DRIVER_INFO_SIGNATURE
792 DriverInfo
= &DriverInfoData
->DriverInfo
;
793 if ((CompareGuid (&DriverInfo
->FileName
, FileName
)) &&
794 (Address
>= DriverInfo
->ImageBase
) &&
795 (Address
< (DriverInfo
->ImageBase
+ DriverInfo
->ImageSize
))) {
796 return DriverInfoData
;
804 Search image from memory profile.
805 It will return image, if (Address >= ImageBuffer) AND (Address < ImageBuffer + ImageSize).
807 @param ContextData Memory profile context.
808 @param Address Image or Function address.
810 @return Pointer to memory profile driver info.
813 MEMORY_PROFILE_DRIVER_INFO_DATA
*
814 GetMemoryProfileDriverInfoFromAddress (
815 IN MEMORY_PROFILE_CONTEXT_DATA
*ContextData
,
816 IN PHYSICAL_ADDRESS Address
819 MEMORY_PROFILE_DRIVER_INFO
*DriverInfo
;
820 MEMORY_PROFILE_DRIVER_INFO_DATA
*DriverInfoData
;
821 LIST_ENTRY
*DriverLink
;
822 LIST_ENTRY
*DriverInfoList
;
824 DriverInfoList
= ContextData
->DriverInfoList
;
826 for (DriverLink
= DriverInfoList
->ForwardLink
;
827 DriverLink
!= DriverInfoList
;
828 DriverLink
= DriverLink
->ForwardLink
) {
829 DriverInfoData
= CR (
831 MEMORY_PROFILE_DRIVER_INFO_DATA
,
833 MEMORY_PROFILE_DRIVER_INFO_SIGNATURE
835 DriverInfo
= &DriverInfoData
->DriverInfo
;
836 if ((Address
>= DriverInfo
->ImageBase
) &&
837 (Address
< (DriverInfo
->ImageBase
+ DriverInfo
->ImageSize
))) {
838 return DriverInfoData
;
846 Unregister image from memory profile.
848 @param DriverEntry Image info.
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.
857 UnregisterMemoryProfileImage (
858 IN LOADED_IMAGE_PRIVATE_DATA
*DriverEntry
862 MEMORY_PROFILE_CONTEXT_DATA
*ContextData
;
863 MEMORY_PROFILE_DRIVER_INFO_DATA
*DriverInfoData
;
865 PHYSICAL_ADDRESS ImageAddress
;
866 VOID
*EntryPointInImage
;
868 if (!IS_UEFI_MEMORY_PROFILE_ENABLED
) {
869 return EFI_UNSUPPORTED
;
872 if (!NeedRecordThisDriver (DriverEntry
->Info
.FilePath
)) {
873 return EFI_UNSUPPORTED
;
876 ContextData
= GetMemoryProfileContext ();
877 if (ContextData
== NULL
) {
878 return EFI_UNSUPPORTED
;
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
))) {
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.
889 Status
= InternalPeCoffGetEntryPoint ((VOID
*) (UINTN
) ImageAddress
, &EntryPointInImage
);
890 ASSERT_EFI_ERROR (Status
);
891 ImageAddress
= ImageAddress
+ (UINTN
) DriverEntry
->ImageContext
.EntryPoint
- (UINTN
) EntryPointInImage
;
893 if (FileName
!= NULL
) {
894 DriverInfoData
= GetMemoryProfileDriverInfoByFileNameAndAddress (ContextData
, FileName
, ImageAddress
);
896 if (DriverInfoData
== NULL
) {
897 DriverInfoData
= GetMemoryProfileDriverInfoFromAddress (ContextData
, ImageAddress
);
899 if (DriverInfoData
== NULL
) {
900 return EFI_NOT_FOUND
;
903 ContextData
->Context
.TotalImageSize
-= DriverInfoData
->DriverInfo
.ImageSize
;
905 // Keep the ImageBase for RVA calculation in Application.
906 //DriverInfoData->DriverInfo.ImageBase = 0;
907 DriverInfoData
->DriverInfo
.ImageSize
= 0;
909 if (DriverInfoData
->DriverInfo
.PeakUsage
== 0) {
910 ContextData
->Context
.ImageCount
--;
911 RemoveEntryList (&DriverInfoData
->Link
);
913 // Use CoreInternalFreePool() that will not update profile for this FreePool action.
915 CoreInternalFreePool (DriverInfoData
, NULL
);
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.
927 @param MemoryType Memory type.
929 @retval TRUE This memory type need to be recorded.
930 @retval FALSE This memory type need not to be recorded.
934 CoreNeedRecordProfile (
935 IN EFI_MEMORY_TYPE MemoryType
940 if ((UINT32
) MemoryType
>= MEMORY_TYPE_OS_RESERVED_MIN
) {
942 } else if ((UINT32
) MemoryType
>= MEMORY_TYPE_OEM_RESERVED_MIN
) {
945 TestBit
= LShiftU64 (1, MemoryType
);
948 if ((PcdGet64 (PcdMemoryProfileMemoryType
) & TestBit
) != 0) {
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.
961 @param MemoryType Memory type.
963 @return Profile memory index.
967 GetProfileMemoryIndex (
968 IN EFI_MEMORY_TYPE MemoryType
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;
981 Update memory profile Allocate information.
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.
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.
997 CoreUpdateProfileAllocate (
998 IN PHYSICAL_ADDRESS CallerAddress
,
999 IN MEMORY_PROFILE_ACTION Action
,
1000 IN EFI_MEMORY_TYPE MemoryType
,
1003 IN CHAR8
*ActionString OPTIONAL
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
;
1018 BasicAction
= Action
& MEMORY_PROFILE_ACTION_BASIC_MASK
;
1020 ContextData
= GetMemoryProfileContext ();
1021 if (ContextData
== NULL
) {
1022 return EFI_UNSUPPORTED
;
1025 DriverInfoData
= GetMemoryProfileDriverInfoFromAddress (ContextData
, CallerAddress
);
1026 if (DriverInfoData
== NULL
) {
1027 return EFI_UNSUPPORTED
;
1030 ActionStringSize
= 0;
1031 ActionStringOccupiedSize
= 0;
1032 if (ActionString
!= NULL
) {
1033 ActionStringSize
= AsciiStrSize (ActionString
);
1034 ActionStringOccupiedSize
= GET_OCCUPIED_SIZE (ActionStringSize
, sizeof (UINT64
));
1038 // Use CoreInternalAllocatePool() that will not update profile for this AllocatePool action.
1040 AllocInfoData
= NULL
;
1041 Status
= CoreInternalAllocatePool (
1042 EfiBootServicesData
,
1043 sizeof (*AllocInfoData
) + ActionStringSize
,
1044 (VOID
**) &AllocInfoData
1046 if (EFI_ERROR (Status
)) {
1047 return EFI_OUT_OF_RESOURCES
;
1049 ASSERT (AllocInfoData
!= NULL
);
1052 // Only update SequenceCount if and only if it is basic action.
1054 if (Action
== BasicAction
) {
1055 ContextData
->Context
.SequenceCount
++;
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
);
1074 AllocInfo
->ActionStringOffset
= 0;
1075 AllocInfoData
->ActionString
= NULL
;
1078 InsertTailList (DriverInfoData
->AllocInfoList
, &AllocInfoData
->Link
);
1080 Context
= &ContextData
->Context
;
1081 DriverInfo
= &DriverInfoData
->DriverInfo
;
1082 DriverInfo
->AllocRecordCount
++;
1085 // Update summary if and only if it is basic action.
1087 if (Action
== BasicAction
) {
1088 ProfileMemoryIndex
= GetProfileMemoryIndex (MemoryType
);
1090 DriverInfo
->CurrentUsage
+= Size
;
1091 if (DriverInfo
->PeakUsage
< DriverInfo
->CurrentUsage
) {
1092 DriverInfo
->PeakUsage
= DriverInfo
->CurrentUsage
;
1094 DriverInfo
->CurrentUsageByType
[ProfileMemoryIndex
] += Size
;
1095 if (DriverInfo
->PeakUsageByType
[ProfileMemoryIndex
] < DriverInfo
->CurrentUsageByType
[ProfileMemoryIndex
]) {
1096 DriverInfo
->PeakUsageByType
[ProfileMemoryIndex
] = DriverInfo
->CurrentUsageByType
[ProfileMemoryIndex
];
1099 Context
->CurrentTotalUsage
+= Size
;
1100 if (Context
->PeakTotalUsage
< Context
->CurrentTotalUsage
) {
1101 Context
->PeakTotalUsage
= Context
->CurrentTotalUsage
;
1103 Context
->CurrentTotalUsageByType
[ProfileMemoryIndex
] += Size
;
1104 if (Context
->PeakTotalUsageByType
[ProfileMemoryIndex
] < Context
->CurrentTotalUsageByType
[ProfileMemoryIndex
]) {
1105 Context
->PeakTotalUsageByType
[ProfileMemoryIndex
] = Context
->CurrentTotalUsageByType
[ProfileMemoryIndex
];
1113 Get memory profile alloc info from memory profile.
1115 @param DriverInfoData Driver info.
1116 @param BasicAction This Free basic action.
1117 @param Size Buffer size.
1118 @param Buffer Buffer address.
1120 @return Pointer to memory profile alloc info.
1123 MEMORY_PROFILE_ALLOC_INFO_DATA
*
1124 GetMemoryProfileAllocInfoFromAddress (
1125 IN MEMORY_PROFILE_DRIVER_INFO_DATA
*DriverInfoData
,
1126 IN MEMORY_PROFILE_ACTION BasicAction
,
1131 LIST_ENTRY
*AllocInfoList
;
1132 LIST_ENTRY
*AllocLink
;
1133 MEMORY_PROFILE_ALLOC_INFO
*AllocInfo
;
1134 MEMORY_PROFILE_ALLOC_INFO_DATA
*AllocInfoData
;
1136 AllocInfoList
= DriverInfoData
->AllocInfoList
;
1138 for (AllocLink
= AllocInfoList
->ForwardLink
;
1139 AllocLink
!= AllocInfoList
;
1140 AllocLink
= AllocLink
->ForwardLink
) {
1141 AllocInfoData
= CR (
1143 MEMORY_PROFILE_ALLOC_INFO_DATA
,
1145 MEMORY_PROFILE_ALLOC_INFO_SIGNATURE
1147 AllocInfo
= &AllocInfoData
->AllocInfo
;
1148 if ((AllocInfo
->Action
& MEMORY_PROFILE_ACTION_BASIC_MASK
) != BasicAction
) {
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
;
1158 case MemoryProfileActionAllocatePool
:
1159 if (AllocInfo
->Buffer
== (PHYSICAL_ADDRESS
) (UINTN
) Buffer
) {
1160 return AllocInfoData
;
1173 Update memory profile Free information.
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.
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.
1186 CoreUpdateProfileFree (
1187 IN PHYSICAL_ADDRESS CallerAddress
,
1188 IN MEMORY_PROFILE_ACTION Action
,
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
;
1206 BasicAction
= Action
& MEMORY_PROFILE_ACTION_BASIC_MASK
;
1208 ContextData
= GetMemoryProfileContext ();
1209 if (ContextData
== NULL
) {
1210 return EFI_UNSUPPORTED
;
1213 DriverInfoData
= GetMemoryProfileDriverInfoFromAddress (ContextData
, CallerAddress
);
1216 // Do not return if DriverInfoData == NULL here,
1217 // because driver A might free memory allocated by driver B.
1221 // Need use do-while loop to find all possible records,
1222 // because one address might be recorded multiple times.
1225 AllocInfoData
= NULL
;
1227 if (DriverInfoData
!= NULL
) {
1228 switch (BasicAction
) {
1229 case MemoryProfileActionFreePages
:
1230 AllocInfoData
= GetMemoryProfileAllocInfoFromAddress (DriverInfoData
, MemoryProfileActionAllocatePages
, Size
, Buffer
);
1232 case MemoryProfileActionFreePool
:
1233 AllocInfoData
= GetMemoryProfileAllocInfoFromAddress (DriverInfoData
, MemoryProfileActionAllocatePool
, 0, Buffer
);
1237 AllocInfoData
= NULL
;
1241 if (AllocInfoData
== NULL
) {
1243 // Legal case, because driver A might free memory allocated by driver B, by some protocol.
1245 DriverInfoList
= ContextData
->DriverInfoList
;
1247 for (DriverLink
= DriverInfoList
->ForwardLink
;
1248 DriverLink
!= DriverInfoList
;
1249 DriverLink
= DriverLink
->ForwardLink
) {
1250 ThisDriverInfoData
= CR (
1252 MEMORY_PROFILE_DRIVER_INFO_DATA
,
1254 MEMORY_PROFILE_DRIVER_INFO_SIGNATURE
1256 switch (BasicAction
) {
1257 case MemoryProfileActionFreePages
:
1258 AllocInfoData
= GetMemoryProfileAllocInfoFromAddress (ThisDriverInfoData
, MemoryProfileActionAllocatePages
, Size
, Buffer
);
1260 case MemoryProfileActionFreePool
:
1261 AllocInfoData
= GetMemoryProfileAllocInfoFromAddress (ThisDriverInfoData
, MemoryProfileActionAllocatePool
, 0, Buffer
);
1265 AllocInfoData
= NULL
;
1268 if (AllocInfoData
!= NULL
) {
1269 DriverInfoData
= ThisDriverInfoData
;
1274 if (AllocInfoData
== NULL
) {
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
1282 // If (Found), it is normal exit path.
1283 return (Found
? EFI_SUCCESS
: EFI_NOT_FOUND
);
1287 ASSERT (DriverInfoData
!= NULL
);
1288 ASSERT (AllocInfoData
!= NULL
);
1292 Context
= &ContextData
->Context
;
1293 DriverInfo
= &DriverInfoData
->DriverInfo
;
1294 AllocInfo
= &AllocInfoData
->AllocInfo
;
1296 DriverInfo
->AllocRecordCount
--;
1298 // Update summary if and only if it is basic action.
1300 if (AllocInfo
->Action
== (AllocInfo
->Action
& MEMORY_PROFILE_ACTION_BASIC_MASK
)) {
1301 ProfileMemoryIndex
= GetProfileMemoryIndex (AllocInfo
->MemoryType
);
1303 Context
->CurrentTotalUsage
-= AllocInfo
->Size
;
1304 Context
->CurrentTotalUsageByType
[ProfileMemoryIndex
] -= AllocInfo
->Size
;
1306 DriverInfo
->CurrentUsage
-= AllocInfo
->Size
;
1307 DriverInfo
->CurrentUsageByType
[ProfileMemoryIndex
] -= AllocInfo
->Size
;
1310 RemoveEntryList (&AllocInfoData
->Link
);
1312 if (BasicAction
== MemoryProfileActionFreePages
) {
1313 if (AllocInfo
->Buffer
!= (PHYSICAL_ADDRESS
) (UINTN
) Buffer
) {
1314 CoreUpdateProfileAllocate (
1315 AllocInfo
->CallerAddress
,
1317 AllocInfo
->MemoryType
,
1318 (UINTN
) ((PHYSICAL_ADDRESS
) (UINTN
) Buffer
- AllocInfo
->Buffer
),
1319 (VOID
*) (UINTN
) AllocInfo
->Buffer
,
1320 AllocInfoData
->ActionString
1323 if (AllocInfo
->Buffer
+ AllocInfo
->Size
!= ((PHYSICAL_ADDRESS
) (UINTN
) Buffer
+ Size
)) {
1324 CoreUpdateProfileAllocate (
1325 AllocInfo
->CallerAddress
,
1327 AllocInfo
->MemoryType
,
1328 (UINTN
) ((AllocInfo
->Buffer
+ AllocInfo
->Size
) - ((PHYSICAL_ADDRESS
) (UINTN
) Buffer
+ Size
)),
1329 (VOID
*) ((UINTN
) Buffer
+ Size
),
1330 AllocInfoData
->ActionString
1336 // Use CoreInternalFreePool() that will not update profile for this FreePool action.
1338 CoreInternalFreePool (AllocInfoData
, NULL
);
1343 Update memory profile information.
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.
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.
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
1372 IN CHAR8
*ActionString OPTIONAL
1376 MEMORY_PROFILE_CONTEXT_DATA
*ContextData
;
1377 MEMORY_PROFILE_ACTION BasicAction
;
1379 if (!IS_UEFI_MEMORY_PROFILE_ENABLED
) {
1380 return EFI_UNSUPPORTED
;
1383 if (mMemoryProfileGettingStatus
) {
1384 return EFI_ACCESS_DENIED
;
1387 if (!mMemoryProfileRecordingEnable
) {
1392 // Get the basic action to know how to process the record
1394 BasicAction
= Action
& MEMORY_PROFILE_ACTION_BASIC_MASK
;
1397 // EfiMaxMemoryType means the MemoryType is unknown.
1399 if (MemoryType
!= EfiMaxMemoryType
) {
1401 // Only record limited MemoryType.
1403 if (!CoreNeedRecordProfile (MemoryType
)) {
1404 return EFI_UNSUPPORTED
;
1408 ContextData
= GetMemoryProfileContext ();
1409 if (ContextData
== NULL
) {
1410 return EFI_UNSUPPORTED
;
1413 CoreAcquireMemoryProfileLock ();
1414 switch (BasicAction
) {
1415 case MemoryProfileActionAllocatePages
:
1416 Status
= CoreUpdateProfileAllocate (CallerAddress
, Action
, MemoryType
, Size
, Buffer
, ActionString
);
1418 case MemoryProfileActionFreePages
:
1419 Status
= CoreUpdateProfileFree (CallerAddress
, Action
, Size
, Buffer
);
1421 case MemoryProfileActionAllocatePool
:
1422 Status
= CoreUpdateProfileAllocate (CallerAddress
, Action
, MemoryType
, Size
, Buffer
, ActionString
);
1424 case MemoryProfileActionFreePool
:
1425 Status
= CoreUpdateProfileFree (CallerAddress
, Action
, 0, Buffer
);
1429 Status
= EFI_UNSUPPORTED
;
1432 CoreReleaseMemoryProfileLock ();
1437 ////////////////////
1440 Get memory profile data size.
1442 @return Memory profile data size.
1446 MemoryProfileGetDataSize (
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
;
1460 ContextData
= GetMemoryProfileContext ();
1461 if (ContextData
== NULL
) {
1465 TotalSize
= sizeof (MEMORY_PROFILE_CONTEXT
);
1467 DriverInfoList
= ContextData
->DriverInfoList
;
1468 for (DriverLink
= DriverInfoList
->ForwardLink
;
1469 DriverLink
!= DriverInfoList
;
1470 DriverLink
= DriverLink
->ForwardLink
) {
1471 DriverInfoData
= CR (
1473 MEMORY_PROFILE_DRIVER_INFO_DATA
,
1475 MEMORY_PROFILE_DRIVER_INFO_SIGNATURE
1477 TotalSize
+= DriverInfoData
->DriverInfo
.Header
.Length
;
1479 AllocInfoList
= DriverInfoData
->AllocInfoList
;
1480 for (AllocLink
= AllocInfoList
->ForwardLink
;
1481 AllocLink
!= AllocInfoList
;
1482 AllocLink
= AllocLink
->ForwardLink
) {
1483 AllocInfoData
= CR (
1485 MEMORY_PROFILE_ALLOC_INFO_DATA
,
1487 MEMORY_PROFILE_ALLOC_INFO_SIGNATURE
1489 TotalSize
+= AllocInfoData
->AllocInfo
.Header
.Length
;
1497 Copy memory profile data.
1499 @param ProfileBuffer The buffer to hold memory profile data.
1503 MemoryProfileCopyData (
1504 IN VOID
*ProfileBuffer
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
;
1518 UINTN ActionStringSize
;
1520 ContextData
= GetMemoryProfileContext ();
1521 if (ContextData
== NULL
) {
1525 Context
= ProfileBuffer
;
1526 CopyMem (Context
, &ContextData
->Context
, sizeof (MEMORY_PROFILE_CONTEXT
));
1527 DriverInfo
= (MEMORY_PROFILE_DRIVER_INFO
*) (Context
+ 1);
1529 DriverInfoList
= ContextData
->DriverInfoList
;
1530 for (DriverLink
= DriverInfoList
->ForwardLink
;
1531 DriverLink
!= DriverInfoList
;
1532 DriverLink
= DriverLink
->ForwardLink
) {
1533 DriverInfoData
= CR (
1535 MEMORY_PROFILE_DRIVER_INFO_DATA
,
1537 MEMORY_PROFILE_DRIVER_INFO_SIGNATURE
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
);
1544 AllocInfo
= (MEMORY_PROFILE_ALLOC_INFO
*) ((UINTN
) DriverInfo
+ DriverInfo
->Header
.Length
);
1546 AllocInfoList
= DriverInfoData
->AllocInfoList
;
1547 for (AllocLink
= AllocInfoList
->ForwardLink
;
1548 AllocLink
!= AllocInfoList
;
1549 AllocLink
= AllocLink
->ForwardLink
) {
1550 AllocInfoData
= CR (
1552 MEMORY_PROFILE_ALLOC_INFO_DATA
,
1554 MEMORY_PROFILE_ALLOC_INFO_SIGNATURE
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
);
1561 AllocInfo
= (MEMORY_PROFILE_ALLOC_INFO
*) ((UINTN
) AllocInfo
+ AllocInfo
->Header
.Length
);
1564 DriverInfo
= (MEMORY_PROFILE_DRIVER_INFO
*) AllocInfo
;
1569 Get memory profile data.
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.
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.
1584 ProfileProtocolGetData (
1585 IN EDKII_MEMORY_PROFILE_PROTOCOL
*This
,
1586 IN OUT UINT64
*ProfileSize
,
1587 OUT VOID
*ProfileBuffer
1591 MEMORY_PROFILE_CONTEXT_DATA
*ContextData
;
1592 BOOLEAN MemoryProfileGettingStatus
;
1594 ContextData
= GetMemoryProfileContext ();
1595 if (ContextData
== NULL
) {
1596 return EFI_UNSUPPORTED
;
1599 MemoryProfileGettingStatus
= mMemoryProfileGettingStatus
;
1600 mMemoryProfileGettingStatus
= TRUE
;
1602 Size
= MemoryProfileGetDataSize ();
1604 if (*ProfileSize
< Size
) {
1605 *ProfileSize
= Size
;
1606 mMemoryProfileGettingStatus
= MemoryProfileGettingStatus
;
1607 return EFI_BUFFER_TOO_SMALL
;
1610 *ProfileSize
= Size
;
1611 MemoryProfileCopyData (ProfileBuffer
);
1613 mMemoryProfileGettingStatus
= MemoryProfileGettingStatus
;
1618 Register image to memory profile.
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.
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.
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
1643 LOADED_IMAGE_PRIVATE_DATA DriverEntry
;
1644 VOID
*EntryPointInImage
;
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
);
1655 return RegisterMemoryProfileImage (&DriverEntry
, FileType
);
1659 Unregister image from memory profile.
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.
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.
1674 ProfileProtocolUnregisterImage (
1675 IN EDKII_MEMORY_PROFILE_PROTOCOL
*This
,
1676 IN EFI_DEVICE_PATH_PROTOCOL
*FilePath
,
1677 IN PHYSICAL_ADDRESS ImageBase
,
1682 LOADED_IMAGE_PRIVATE_DATA DriverEntry
;
1683 VOID
*EntryPointInImage
;
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
;
1693 return UnregisterMemoryProfileImage (&DriverEntry
);
1697 Get memory profile recording state.
1699 @param[in] This The EDKII_MEMORY_PROFILE_PROTOCOL instance.
1700 @param[out] RecordingState Recording state.
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.
1709 ProfileProtocolGetRecordingState (
1710 IN EDKII_MEMORY_PROFILE_PROTOCOL
*This
,
1711 OUT BOOLEAN
*RecordingState
1714 MEMORY_PROFILE_CONTEXT_DATA
*ContextData
;
1716 ContextData
= GetMemoryProfileContext ();
1717 if (ContextData
== NULL
) {
1718 return EFI_UNSUPPORTED
;
1721 if (RecordingState
== NULL
) {
1722 return EFI_INVALID_PARAMETER
;
1724 *RecordingState
= mMemoryProfileRecordingEnable
;
1729 Set memory profile recording state.
1731 @param[in] This The EDKII_MEMORY_PROFILE_PROTOCOL instance.
1732 @param[in] RecordingState Recording state.
1734 @return EFI_SUCCESS Set memory profile recording state successfully.
1735 @return EFI_UNSUPPORTED Memory profile is unsupported.
1740 ProfileProtocolSetRecordingState (
1741 IN EDKII_MEMORY_PROFILE_PROTOCOL
*This
,
1742 IN BOOLEAN RecordingState
1745 MEMORY_PROFILE_CONTEXT_DATA
*ContextData
;
1747 ContextData
= GetMemoryProfileContext ();
1748 if (ContextData
== NULL
) {
1749 return EFI_UNSUPPORTED
;
1752 mMemoryProfileRecordingEnable
= RecordingState
;
1757 Record memory profile of multilevel caller.
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.
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.
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
,
1788 IN CHAR8
*ActionString OPTIONAL
1791 return CoreUpdateProfile (CallerAddress
, Action
, MemoryType
, Size
, Buffer
, ActionString
);
1794 ////////////////////