2 Support routines for UEFI memory profile.
4 Copyright (c) 2014 - 2018, Intel Corporation. All rights reserved.<BR>
5 SPDX-License-Identifier: BSD-2-Clause-Patent
12 #define IS_UEFI_MEMORY_PROFILE_ENABLED ((PcdGet8 (PcdMemoryProfilePropertyMask) & BIT0) != 0)
14 #define GET_OCCUPIED_SIZE(ActualSize, Alignment) \
15 ((ActualSize) + (((Alignment) - ((ActualSize) & ((Alignment) - 1))) & ((Alignment) - 1)))
19 MEMORY_PROFILE_CONTEXT Context
;
20 LIST_ENTRY
*DriverInfoList
;
21 } MEMORY_PROFILE_CONTEXT_DATA
;
25 MEMORY_PROFILE_DRIVER_INFO DriverInfo
;
26 LIST_ENTRY
*AllocInfoList
;
29 } MEMORY_PROFILE_DRIVER_INFO_DATA
;
33 MEMORY_PROFILE_ALLOC_INFO AllocInfo
;
36 } MEMORY_PROFILE_ALLOC_INFO_DATA
;
38 GLOBAL_REMOVE_IF_UNREFERENCED LIST_ENTRY mImageQueue
= INITIALIZE_LIST_HEAD_VARIABLE (mImageQueue
);
39 GLOBAL_REMOVE_IF_UNREFERENCED MEMORY_PROFILE_CONTEXT_DATA mMemoryProfileContext
= {
40 MEMORY_PROFILE_CONTEXT_SIGNATURE
,
43 MEMORY_PROFILE_CONTEXT_SIGNATURE
,
44 sizeof (MEMORY_PROFILE_CONTEXT
),
45 MEMORY_PROFILE_CONTEXT_REVISION
57 GLOBAL_REMOVE_IF_UNREFERENCED MEMORY_PROFILE_CONTEXT_DATA
*mMemoryProfileContextPtr
= NULL
;
59 GLOBAL_REMOVE_IF_UNREFERENCED EFI_LOCK mMemoryProfileLock
= EFI_INITIALIZE_LOCK_VARIABLE (TPL_NOTIFY
);
60 GLOBAL_REMOVE_IF_UNREFERENCED BOOLEAN mMemoryProfileGettingStatus
= FALSE
;
61 GLOBAL_REMOVE_IF_UNREFERENCED BOOLEAN mMemoryProfileRecordingEnable
= MEMORY_PROFILE_RECORDING_DISABLE
;
62 GLOBAL_REMOVE_IF_UNREFERENCED EFI_DEVICE_PATH_PROTOCOL
*mMemoryProfileDriverPath
;
63 GLOBAL_REMOVE_IF_UNREFERENCED UINTN mMemoryProfileDriverPathSize
;
66 Get memory profile data.
68 @param[in] This The EDKII_MEMORY_PROFILE_PROTOCOL instance.
69 @param[in, out] ProfileSize On entry, points to the size in bytes of the ProfileBuffer.
70 On return, points to the size of the data returned in ProfileBuffer.
71 @param[out] ProfileBuffer Profile buffer.
73 @return EFI_SUCCESS Get the memory profile data successfully.
74 @return EFI_UNSUPPORTED Memory profile is unsupported.
75 @return EFI_BUFFER_TO_SMALL The ProfileSize is too small for the resulting data.
76 ProfileSize is updated with the size required.
81 ProfileProtocolGetData (
82 IN EDKII_MEMORY_PROFILE_PROTOCOL
*This
,
83 IN OUT UINT64
*ProfileSize
,
84 OUT VOID
*ProfileBuffer
88 Register image to memory profile.
90 @param[in] This The EDKII_MEMORY_PROFILE_PROTOCOL instance.
91 @param[in] FilePath File path of the image.
92 @param[in] ImageBase Image base address.
93 @param[in] ImageSize Image size.
94 @param[in] FileType File type of the image.
96 @return EFI_SUCCESS Register successfully.
97 @return EFI_UNSUPPORTED Memory profile is unsupported,
98 or memory profile for the image is not required.
99 @return EFI_OUT_OF_RESOURCE No enough resource for this register.
104 ProfileProtocolRegisterImage (
105 IN EDKII_MEMORY_PROFILE_PROTOCOL
*This
,
106 IN EFI_DEVICE_PATH_PROTOCOL
*FilePath
,
107 IN PHYSICAL_ADDRESS ImageBase
,
109 IN EFI_FV_FILETYPE FileType
113 Unregister image from memory profile.
115 @param[in] This The EDKII_MEMORY_PROFILE_PROTOCOL instance.
116 @param[in] FilePath File path of the image.
117 @param[in] ImageBase Image base address.
118 @param[in] ImageSize Image size.
120 @return EFI_SUCCESS Unregister successfully.
121 @return EFI_UNSUPPORTED Memory profile is unsupported,
122 or memory profile for the image is not required.
123 @return EFI_NOT_FOUND The image is not found.
128 ProfileProtocolUnregisterImage (
129 IN EDKII_MEMORY_PROFILE_PROTOCOL
*This
,
130 IN EFI_DEVICE_PATH_PROTOCOL
*FilePath
,
131 IN PHYSICAL_ADDRESS ImageBase
,
136 Get memory profile recording state.
138 @param[in] This The EDKII_MEMORY_PROFILE_PROTOCOL instance.
139 @param[out] RecordingState Recording state.
141 @return EFI_SUCCESS Memory profile recording state is returned.
142 @return EFI_UNSUPPORTED Memory profile is unsupported.
143 @return EFI_INVALID_PARAMETER RecordingState is NULL.
148 ProfileProtocolGetRecordingState (
149 IN EDKII_MEMORY_PROFILE_PROTOCOL
*This
,
150 OUT BOOLEAN
*RecordingState
154 Set memory profile recording state.
156 @param[in] This The EDKII_MEMORY_PROFILE_PROTOCOL instance.
157 @param[in] RecordingState Recording state.
159 @return EFI_SUCCESS Set memory profile recording state successfully.
160 @return EFI_UNSUPPORTED Memory profile is unsupported.
165 ProfileProtocolSetRecordingState (
166 IN EDKII_MEMORY_PROFILE_PROTOCOL
*This
,
167 IN BOOLEAN RecordingState
171 Record memory profile of multilevel caller.
173 @param[in] This The EDKII_MEMORY_PROFILE_PROTOCOL instance.
174 @param[in] CallerAddress Address of caller.
175 @param[in] Action Memory profile action.
176 @param[in] MemoryType Memory type.
177 EfiMaxMemoryType means the MemoryType is unknown.
178 @param[in] Buffer Buffer address.
179 @param[in] Size Buffer size.
180 @param[in] ActionString String for memory profile action.
181 Only needed for user defined allocate action.
183 @return EFI_SUCCESS Memory profile is updated.
184 @return EFI_UNSUPPORTED Memory profile is unsupported,
185 or memory profile for the image is not required,
186 or memory profile for the memory type is not required.
187 @return EFI_ACCESS_DENIED It is during memory profile data getting.
188 @return EFI_ABORTED Memory profile recording is not enabled.
189 @return EFI_OUT_OF_RESOURCES No enough resource to update memory profile for allocate action.
190 @return EFI_NOT_FOUND No matched allocate info found for free action.
195 ProfileProtocolRecord (
196 IN EDKII_MEMORY_PROFILE_PROTOCOL
*This
,
197 IN PHYSICAL_ADDRESS CallerAddress
,
198 IN MEMORY_PROFILE_ACTION Action
,
199 IN EFI_MEMORY_TYPE MemoryType
,
202 IN CHAR8
*ActionString OPTIONAL
205 GLOBAL_REMOVE_IF_UNREFERENCED EDKII_MEMORY_PROFILE_PROTOCOL mProfileProtocol
= {
206 ProfileProtocolGetData
,
207 ProfileProtocolRegisterImage
,
208 ProfileProtocolUnregisterImage
,
209 ProfileProtocolGetRecordingState
,
210 ProfileProtocolSetRecordingState
,
211 ProfileProtocolRecord
,
215 Acquire lock on mMemoryProfileLock.
218 CoreAcquireMemoryProfileLock (
222 CoreAcquireLock (&mMemoryProfileLock
);
226 Release lock on mMemoryProfileLock.
229 CoreReleaseMemoryProfileLock (
233 CoreReleaseLock (&mMemoryProfileLock
);
237 Return memory profile context.
239 @return Memory profile context.
242 MEMORY_PROFILE_CONTEXT_DATA
*
243 GetMemoryProfileContext (
247 return mMemoryProfileContextPtr
;
251 Retrieves and returns the Subsystem of a PE/COFF image that has been loaded into system memory.
252 If Pe32Data is NULL, then ASSERT().
254 @param Pe32Data The pointer to the PE/COFF image that is loaded in system memory.
256 @return The Subsystem of the PE/COFF image.
260 InternalPeCoffGetSubsystem (
264 EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION Hdr
;
265 EFI_IMAGE_DOS_HEADER
*DosHdr
;
268 ASSERT (Pe32Data
!= NULL
);
270 DosHdr
= (EFI_IMAGE_DOS_HEADER
*)Pe32Data
;
271 if (DosHdr
->e_magic
== EFI_IMAGE_DOS_SIGNATURE
) {
273 // DOS image header is present, so read the PE header after the DOS image header.
275 Hdr
.Pe32
= (EFI_IMAGE_NT_HEADERS32
*)((UINTN
)Pe32Data
+ (UINTN
)((DosHdr
->e_lfanew
) & 0x0ffff));
278 // DOS image header is not present, so PE header is at the image base.
280 Hdr
.Pe32
= (EFI_IMAGE_NT_HEADERS32
*)Pe32Data
;
283 if (Hdr
.Te
->Signature
== EFI_TE_IMAGE_HEADER_SIGNATURE
) {
284 return Hdr
.Te
->Subsystem
;
285 } else if (Hdr
.Pe32
->Signature
== EFI_IMAGE_NT_SIGNATURE
) {
286 Magic
= Hdr
.Pe32
->OptionalHeader
.Magic
;
287 if (Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
288 return Hdr
.Pe32
->OptionalHeader
.Subsystem
;
289 } else if (Magic
== EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC
) {
290 return Hdr
.Pe32Plus
->OptionalHeader
.Subsystem
;
298 Retrieves and returns a pointer to the entry point to a PE/COFF image that has been loaded
299 into system memory with the PE/COFF Loader Library functions.
301 Retrieves the entry point to the PE/COFF image specified by Pe32Data and returns this entry
302 point in EntryPoint. If the entry point could not be retrieved from the PE/COFF image, then
303 return RETURN_INVALID_PARAMETER. Otherwise return RETURN_SUCCESS.
304 If Pe32Data is NULL, then ASSERT().
305 If EntryPoint is NULL, then ASSERT().
307 @param Pe32Data The pointer to the PE/COFF image that is loaded in system memory.
308 @param EntryPoint The pointer to entry point to the PE/COFF image to return.
310 @retval RETURN_SUCCESS EntryPoint was returned.
311 @retval RETURN_INVALID_PARAMETER The entry point could not be found in the PE/COFF image.
315 InternalPeCoffGetEntryPoint (
317 OUT VOID
**EntryPoint
320 EFI_IMAGE_DOS_HEADER
*DosHdr
;
321 EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION Hdr
;
323 ASSERT (Pe32Data
!= NULL
);
324 ASSERT (EntryPoint
!= NULL
);
326 DosHdr
= (EFI_IMAGE_DOS_HEADER
*)Pe32Data
;
327 if (DosHdr
->e_magic
== EFI_IMAGE_DOS_SIGNATURE
) {
329 // DOS image header is present, so read the PE header after the DOS image header.
331 Hdr
.Pe32
= (EFI_IMAGE_NT_HEADERS32
*)((UINTN
)Pe32Data
+ (UINTN
)((DosHdr
->e_lfanew
) & 0x0ffff));
334 // DOS image header is not present, so PE header is at the image base.
336 Hdr
.Pe32
= (EFI_IMAGE_NT_HEADERS32
*)Pe32Data
;
340 // Calculate the entry point relative to the start of the image.
341 // AddressOfEntryPoint is common for PE32 & PE32+
343 if (Hdr
.Te
->Signature
== EFI_TE_IMAGE_HEADER_SIGNATURE
) {
344 *EntryPoint
= (VOID
*)((UINTN
)Pe32Data
+ (UINTN
)(Hdr
.Te
->AddressOfEntryPoint
& 0x0ffffffff) + sizeof (EFI_TE_IMAGE_HEADER
) - Hdr
.Te
->StrippedSize
);
345 return RETURN_SUCCESS
;
346 } else if (Hdr
.Pe32
->Signature
== EFI_IMAGE_NT_SIGNATURE
) {
347 *EntryPoint
= (VOID
*)((UINTN
)Pe32Data
+ (UINTN
)(Hdr
.Pe32
->OptionalHeader
.AddressOfEntryPoint
& 0x0ffffffff));
348 return RETURN_SUCCESS
;
351 return RETURN_UNSUPPORTED
;
357 @param ContextData Memory profile context.
358 @param FileName File name of the image.
359 @param ImageBase Image base address.
360 @param ImageSize Image size.
361 @param EntryPoint Entry point of the image.
362 @param ImageSubsystem Image subsystem of the image.
363 @param FileType File type of the image.
365 @return Pointer to memory profile driver info.
368 MEMORY_PROFILE_DRIVER_INFO_DATA
*
370 IN MEMORY_PROFILE_CONTEXT_DATA
*ContextData
,
371 IN EFI_GUID
*FileName
,
372 IN PHYSICAL_ADDRESS ImageBase
,
374 IN PHYSICAL_ADDRESS EntryPoint
,
375 IN UINT16 ImageSubsystem
,
376 IN EFI_FV_FILETYPE FileType
380 MEMORY_PROFILE_DRIVER_INFO
*DriverInfo
;
381 MEMORY_PROFILE_DRIVER_INFO_DATA
*DriverInfoData
;
382 VOID
*EntryPointInImage
;
385 UINTN PdbOccupiedSize
;
390 if (ImageBase
!= 0) {
391 PdbString
= PeCoffLoaderGetPdbPointer ((VOID
*)(UINTN
)ImageBase
);
392 if (PdbString
!= NULL
) {
393 PdbSize
= AsciiStrSize (PdbString
);
394 PdbOccupiedSize
= GET_OCCUPIED_SIZE (PdbSize
, sizeof (UINT64
));
399 // Use CoreInternalAllocatePool() that will not update profile for this AllocatePool action.
401 Status
= CoreInternalAllocatePool (
403 sizeof (*DriverInfoData
) + sizeof (LIST_ENTRY
) + PdbSize
,
404 (VOID
**)&DriverInfoData
406 if (EFI_ERROR (Status
)) {
410 ASSERT (DriverInfoData
!= NULL
);
412 ZeroMem (DriverInfoData
, sizeof (*DriverInfoData
));
414 DriverInfo
= &DriverInfoData
->DriverInfo
;
415 DriverInfoData
->Signature
= MEMORY_PROFILE_DRIVER_INFO_SIGNATURE
;
416 DriverInfo
->Header
.Signature
= MEMORY_PROFILE_DRIVER_INFO_SIGNATURE
;
417 DriverInfo
->Header
.Length
= (UINT16
)(sizeof (MEMORY_PROFILE_DRIVER_INFO
) + PdbOccupiedSize
);
418 DriverInfo
->Header
.Revision
= MEMORY_PROFILE_DRIVER_INFO_REVISION
;
419 if (FileName
!= NULL
) {
420 CopyMem (&DriverInfo
->FileName
, FileName
, sizeof (EFI_GUID
));
423 DriverInfo
->ImageBase
= ImageBase
;
424 DriverInfo
->ImageSize
= ImageSize
;
425 DriverInfo
->EntryPoint
= EntryPoint
;
426 DriverInfo
->ImageSubsystem
= ImageSubsystem
;
427 if ((EntryPoint
!= 0) && ((EntryPoint
< ImageBase
) || (EntryPoint
>= (ImageBase
+ ImageSize
)))) {
429 // If the EntryPoint is not in the range of image buffer, it should come from emulation environment.
430 // So patch ImageBuffer here to align the EntryPoint.
432 Status
= InternalPeCoffGetEntryPoint ((VOID
*)(UINTN
)ImageBase
, &EntryPointInImage
);
433 ASSERT_EFI_ERROR (Status
);
434 DriverInfo
->ImageBase
= ImageBase
+ EntryPoint
- (PHYSICAL_ADDRESS
)(UINTN
)EntryPointInImage
;
437 DriverInfo
->FileType
= FileType
;
438 DriverInfoData
->AllocInfoList
= (LIST_ENTRY
*)(DriverInfoData
+ 1);
439 InitializeListHead (DriverInfoData
->AllocInfoList
);
440 DriverInfo
->CurrentUsage
= 0;
441 DriverInfo
->PeakUsage
= 0;
442 DriverInfo
->AllocRecordCount
= 0;
444 DriverInfo
->PdbStringOffset
= (UINT16
)sizeof (MEMORY_PROFILE_DRIVER_INFO
);
445 DriverInfoData
->PdbString
= (CHAR8
*)(DriverInfoData
->AllocInfoList
+ 1);
446 CopyMem (DriverInfoData
->PdbString
, PdbString
, PdbSize
);
448 DriverInfo
->PdbStringOffset
= 0;
449 DriverInfoData
->PdbString
= NULL
;
452 InsertTailList (ContextData
->DriverInfoList
, &DriverInfoData
->Link
);
453 ContextData
->Context
.ImageCount
++;
454 ContextData
->Context
.TotalImageSize
+= DriverInfo
->ImageSize
;
456 return DriverInfoData
;
460 Return if record for this driver is needed..
462 @param DriverFilePath Driver file path.
464 @retval TRUE Record for this driver is needed.
465 @retval FALSE Record for this driver is not needed.
469 NeedRecordThisDriver (
470 IN EFI_DEVICE_PATH_PROTOCOL
*DriverFilePath
473 EFI_DEVICE_PATH_PROTOCOL
*TmpDevicePath
;
474 EFI_DEVICE_PATH_PROTOCOL
*DevicePathInstance
;
475 UINTN DevicePathSize
;
478 if (!IsDevicePathValid (mMemoryProfileDriverPath
, mMemoryProfileDriverPathSize
)) {
480 // Invalid Device Path means record all.
486 // Record FilePath without END node.
488 FilePathSize
= GetDevicePathSize (DriverFilePath
) - sizeof (EFI_DEVICE_PATH_PROTOCOL
);
490 DevicePathInstance
= mMemoryProfileDriverPath
;
493 // Find END node (it might be END_ENTIRE or END_INSTANCE).
495 TmpDevicePath
= DevicePathInstance
;
496 while (!IsDevicePathEndType (TmpDevicePath
)) {
497 TmpDevicePath
= NextDevicePathNode (TmpDevicePath
);
501 // Do not compare END node.
503 DevicePathSize
= (UINTN
)TmpDevicePath
- (UINTN
)DevicePathInstance
;
504 if ((FilePathSize
== DevicePathSize
) &&
505 (CompareMem (DriverFilePath
, DevicePathInstance
, DevicePathSize
) == 0))
511 // Get next instance.
513 DevicePathInstance
= (EFI_DEVICE_PATH_PROTOCOL
*)((UINTN
)DevicePathInstance
+ DevicePathSize
+ DevicePathNodeLength (TmpDevicePath
));
514 } while (DevicePathSubType (TmpDevicePath
) != END_ENTIRE_DEVICE_PATH_SUBTYPE
);
520 Register DXE Core to memory profile.
522 @param HobStart The start address of the HOB.
523 @param ContextData Memory profile context.
525 @retval TRUE Register success.
526 @retval FALSE Register fail.
532 IN MEMORY_PROFILE_CONTEXT_DATA
*ContextData
535 EFI_PEI_HOB_POINTERS DxeCoreHob
;
536 MEMORY_PROFILE_DRIVER_INFO_DATA
*DriverInfoData
;
537 PHYSICAL_ADDRESS ImageBase
;
538 UINT8 TempBuffer
[sizeof (MEDIA_FW_VOL_FILEPATH_DEVICE_PATH
) + sizeof (EFI_DEVICE_PATH_PROTOCOL
)];
539 MEDIA_FW_VOL_FILEPATH_DEVICE_PATH
*FilePath
;
541 ASSERT (ContextData
!= NULL
);
544 // Searching for image hob
546 DxeCoreHob
.Raw
= HobStart
;
547 while ((DxeCoreHob
.Raw
= GetNextHob (EFI_HOB_TYPE_MEMORY_ALLOCATION
, DxeCoreHob
.Raw
)) != NULL
) {
548 if (CompareGuid (&DxeCoreHob
.MemoryAllocationModule
->MemoryAllocationHeader
.Name
, &gEfiHobMemoryAllocModuleGuid
)) {
555 DxeCoreHob
.Raw
= GET_NEXT_HOB (DxeCoreHob
);
558 ASSERT (DxeCoreHob
.Raw
!= NULL
);
560 FilePath
= (MEDIA_FW_VOL_FILEPATH_DEVICE_PATH
*)TempBuffer
;
561 EfiInitializeFwVolDevicepathNode (FilePath
, &DxeCoreHob
.MemoryAllocationModule
->ModuleName
);
562 SetDevicePathEndNode (FilePath
+ 1);
564 if (!NeedRecordThisDriver ((EFI_DEVICE_PATH_PROTOCOL
*)FilePath
)) {
568 ImageBase
= DxeCoreHob
.MemoryAllocationModule
->MemoryAllocationHeader
.MemoryBaseAddress
;
569 DriverInfoData
= BuildDriverInfo (
571 &DxeCoreHob
.MemoryAllocationModule
->ModuleName
,
573 DxeCoreHob
.MemoryAllocationModule
->MemoryAllocationHeader
.MemoryLength
,
574 DxeCoreHob
.MemoryAllocationModule
->EntryPoint
,
575 InternalPeCoffGetSubsystem ((VOID
*)(UINTN
)ImageBase
),
576 EFI_FV_FILETYPE_DXE_CORE
578 if (DriverInfoData
== NULL
) {
586 Initialize memory profile.
588 @param HobStart The start address of the HOB.
596 MEMORY_PROFILE_CONTEXT_DATA
*ContextData
;
598 if (!IS_UEFI_MEMORY_PROFILE_ENABLED
) {
602 ContextData
= GetMemoryProfileContext ();
603 if (ContextData
!= NULL
) {
607 mMemoryProfileGettingStatus
= FALSE
;
608 if ((PcdGet8 (PcdMemoryProfilePropertyMask
) & BIT7
) != 0) {
609 mMemoryProfileRecordingEnable
= MEMORY_PROFILE_RECORDING_DISABLE
;
611 mMemoryProfileRecordingEnable
= MEMORY_PROFILE_RECORDING_ENABLE
;
614 mMemoryProfileDriverPathSize
= PcdGetSize (PcdMemoryProfileDriverPath
);
615 mMemoryProfileDriverPath
= AllocateCopyPool (mMemoryProfileDriverPathSize
, PcdGetPtr (PcdMemoryProfileDriverPath
));
616 mMemoryProfileContextPtr
= &mMemoryProfileContext
;
618 RegisterDxeCore (HobStart
, &mMemoryProfileContext
);
620 DEBUG ((DEBUG_INFO
, "MemoryProfileInit MemoryProfileContext - 0x%x\n", &mMemoryProfileContext
));
624 Install memory profile protocol.
628 MemoryProfileInstallProtocol (
635 if (!IS_UEFI_MEMORY_PROFILE_ENABLED
) {
640 Status
= CoreInstallMultipleProtocolInterfaces (
642 &gEdkiiMemoryProfileGuid
,
646 ASSERT_EFI_ERROR (Status
);
650 Get the GUID file name from the file path.
652 @param FilePath File path.
654 @return The GUID file name from the file path.
658 GetFileNameFromFilePath (
659 IN EFI_DEVICE_PATH_PROTOCOL
*FilePath
662 MEDIA_FW_VOL_FILEPATH_DEVICE_PATH
*ThisFilePath
;
666 if (FilePath
!= NULL
) {
667 ThisFilePath
= (MEDIA_FW_VOL_FILEPATH_DEVICE_PATH
*)FilePath
;
668 while (!IsDevicePathEnd (ThisFilePath
)) {
669 FileName
= EfiGetNameGuidFromFwVolDevicePathNode (ThisFilePath
);
670 if (FileName
!= NULL
) {
674 ThisFilePath
= (MEDIA_FW_VOL_FILEPATH_DEVICE_PATH
*)NextDevicePathNode (ThisFilePath
);
682 Register image to memory profile.
684 @param DriverEntry Image info.
685 @param FileType Image file type.
687 @return EFI_SUCCESS Register successfully.
688 @return EFI_UNSUPPORTED Memory profile is unsupported,
689 or memory profile for the image is not required.
690 @return EFI_OUT_OF_RESOURCES No enough resource for this register.
694 RegisterMemoryProfileImage (
695 IN LOADED_IMAGE_PRIVATE_DATA
*DriverEntry
,
696 IN EFI_FV_FILETYPE FileType
699 MEMORY_PROFILE_CONTEXT_DATA
*ContextData
;
700 MEMORY_PROFILE_DRIVER_INFO_DATA
*DriverInfoData
;
702 if (!IS_UEFI_MEMORY_PROFILE_ENABLED
) {
703 return EFI_UNSUPPORTED
;
706 if (!NeedRecordThisDriver (DriverEntry
->Info
.FilePath
)) {
707 return EFI_UNSUPPORTED
;
710 ContextData
= GetMemoryProfileContext ();
711 if (ContextData
== NULL
) {
712 return EFI_UNSUPPORTED
;
715 DriverInfoData
= BuildDriverInfo (
717 GetFileNameFromFilePath (DriverEntry
->Info
.FilePath
),
718 DriverEntry
->ImageContext
.ImageAddress
,
719 DriverEntry
->ImageContext
.ImageSize
,
720 DriverEntry
->ImageContext
.EntryPoint
,
721 DriverEntry
->ImageContext
.ImageType
,
724 if (DriverInfoData
== NULL
) {
725 return EFI_OUT_OF_RESOURCES
;
732 Search image from memory profile.
734 @param ContextData Memory profile context.
735 @param FileName Image file name.
736 @param Address Image Address.
738 @return Pointer to memory profile driver info.
741 MEMORY_PROFILE_DRIVER_INFO_DATA
*
742 GetMemoryProfileDriverInfoByFileNameAndAddress (
743 IN MEMORY_PROFILE_CONTEXT_DATA
*ContextData
,
744 IN EFI_GUID
*FileName
,
745 IN PHYSICAL_ADDRESS Address
748 MEMORY_PROFILE_DRIVER_INFO
*DriverInfo
;
749 MEMORY_PROFILE_DRIVER_INFO_DATA
*DriverInfoData
;
750 LIST_ENTRY
*DriverLink
;
751 LIST_ENTRY
*DriverInfoList
;
753 DriverInfoList
= ContextData
->DriverInfoList
;
755 for (DriverLink
= DriverInfoList
->ForwardLink
;
756 DriverLink
!= DriverInfoList
;
757 DriverLink
= DriverLink
->ForwardLink
)
759 DriverInfoData
= CR (
761 MEMORY_PROFILE_DRIVER_INFO_DATA
,
763 MEMORY_PROFILE_DRIVER_INFO_SIGNATURE
765 DriverInfo
= &DriverInfoData
->DriverInfo
;
766 if ((CompareGuid (&DriverInfo
->FileName
, FileName
)) &&
767 (Address
>= DriverInfo
->ImageBase
) &&
768 (Address
< (DriverInfo
->ImageBase
+ DriverInfo
->ImageSize
)))
770 return DriverInfoData
;
778 Search image from memory profile.
779 It will return image, if (Address >= ImageBuffer) AND (Address < ImageBuffer + ImageSize).
781 @param ContextData Memory profile context.
782 @param Address Image or Function address.
784 @return Pointer to memory profile driver info.
787 MEMORY_PROFILE_DRIVER_INFO_DATA
*
788 GetMemoryProfileDriverInfoFromAddress (
789 IN MEMORY_PROFILE_CONTEXT_DATA
*ContextData
,
790 IN PHYSICAL_ADDRESS Address
793 MEMORY_PROFILE_DRIVER_INFO
*DriverInfo
;
794 MEMORY_PROFILE_DRIVER_INFO_DATA
*DriverInfoData
;
795 LIST_ENTRY
*DriverLink
;
796 LIST_ENTRY
*DriverInfoList
;
798 DriverInfoList
= ContextData
->DriverInfoList
;
800 for (DriverLink
= DriverInfoList
->ForwardLink
;
801 DriverLink
!= DriverInfoList
;
802 DriverLink
= DriverLink
->ForwardLink
)
804 DriverInfoData
= CR (
806 MEMORY_PROFILE_DRIVER_INFO_DATA
,
808 MEMORY_PROFILE_DRIVER_INFO_SIGNATURE
810 DriverInfo
= &DriverInfoData
->DriverInfo
;
811 if ((Address
>= DriverInfo
->ImageBase
) &&
812 (Address
< (DriverInfo
->ImageBase
+ DriverInfo
->ImageSize
)))
814 return DriverInfoData
;
822 Unregister image from memory profile.
824 @param DriverEntry Image info.
826 @return EFI_SUCCESS Unregister successfully.
827 @return EFI_UNSUPPORTED Memory profile is unsupported,
828 or memory profile for the image is not required.
829 @return EFI_NOT_FOUND The image is not found.
833 UnregisterMemoryProfileImage (
834 IN LOADED_IMAGE_PRIVATE_DATA
*DriverEntry
838 MEMORY_PROFILE_CONTEXT_DATA
*ContextData
;
839 MEMORY_PROFILE_DRIVER_INFO_DATA
*DriverInfoData
;
841 PHYSICAL_ADDRESS ImageAddress
;
842 VOID
*EntryPointInImage
;
844 if (!IS_UEFI_MEMORY_PROFILE_ENABLED
) {
845 return EFI_UNSUPPORTED
;
848 if (!NeedRecordThisDriver (DriverEntry
->Info
.FilePath
)) {
849 return EFI_UNSUPPORTED
;
852 ContextData
= GetMemoryProfileContext ();
853 if (ContextData
== NULL
) {
854 return EFI_UNSUPPORTED
;
857 DriverInfoData
= NULL
;
858 FileName
= GetFileNameFromFilePath (DriverEntry
->Info
.FilePath
);
859 ImageAddress
= DriverEntry
->ImageContext
.ImageAddress
;
860 if ((DriverEntry
->ImageContext
.EntryPoint
< ImageAddress
) || (DriverEntry
->ImageContext
.EntryPoint
>= (ImageAddress
+ DriverEntry
->ImageContext
.ImageSize
))) {
862 // If the EntryPoint is not in the range of image buffer, it should come from emulation environment.
863 // So patch ImageAddress here to align the EntryPoint.
865 Status
= InternalPeCoffGetEntryPoint ((VOID
*)(UINTN
)ImageAddress
, &EntryPointInImage
);
866 ASSERT_EFI_ERROR (Status
);
867 ImageAddress
= ImageAddress
+ (UINTN
)DriverEntry
->ImageContext
.EntryPoint
- (UINTN
)EntryPointInImage
;
870 if (FileName
!= NULL
) {
871 DriverInfoData
= GetMemoryProfileDriverInfoByFileNameAndAddress (ContextData
, FileName
, ImageAddress
);
874 if (DriverInfoData
== NULL
) {
875 DriverInfoData
= GetMemoryProfileDriverInfoFromAddress (ContextData
, ImageAddress
);
878 if (DriverInfoData
== NULL
) {
879 return EFI_NOT_FOUND
;
882 ContextData
->Context
.TotalImageSize
-= DriverInfoData
->DriverInfo
.ImageSize
;
884 // Keep the ImageBase for RVA calculation in Application.
885 // DriverInfoData->DriverInfo.ImageBase = 0;
886 DriverInfoData
->DriverInfo
.ImageSize
= 0;
888 if (DriverInfoData
->DriverInfo
.PeakUsage
== 0) {
889 ContextData
->Context
.ImageCount
--;
890 RemoveEntryList (&DriverInfoData
->Link
);
892 // Use CoreInternalFreePool() that will not update profile for this FreePool action.
894 CoreInternalFreePool (DriverInfoData
, NULL
);
901 Return if this memory type needs to be recorded into memory profile.
902 If BIOS memory type (0 ~ EfiMaxMemoryType - 1), it checks bit (1 << MemoryType).
903 If OS memory type (0x80000000 ~ 0xFFFFFFFF), it checks bit63 - 0x8000000000000000.
904 If OEM memory type (0x70000000 ~ 0x7FFFFFFF), it checks bit62 - 0x4000000000000000.
906 @param MemoryType Memory type.
908 @retval TRUE This memory type need to be recorded.
909 @retval FALSE This memory type need not to be recorded.
913 CoreNeedRecordProfile (
914 IN EFI_MEMORY_TYPE MemoryType
919 if ((UINT32
)MemoryType
>= MEMORY_TYPE_OS_RESERVED_MIN
) {
921 } else if ((UINT32
)MemoryType
>= MEMORY_TYPE_OEM_RESERVED_MIN
) {
924 TestBit
= LShiftU64 (1, MemoryType
);
927 if ((PcdGet64 (PcdMemoryProfileMemoryType
) & TestBit
) != 0) {
935 Convert EFI memory type to profile memory index. The rule is:
936 If BIOS memory type (0 ~ EfiMaxMemoryType - 1), ProfileMemoryIndex = MemoryType.
937 If OS memory type (0x80000000 ~ 0xFFFFFFFF), ProfileMemoryIndex = EfiMaxMemoryType.
938 If OEM memory type (0x70000000 ~ 0x7FFFFFFF), ProfileMemoryIndex = EfiMaxMemoryType + 1.
940 @param MemoryType Memory type.
942 @return Profile memory index.
946 GetProfileMemoryIndex (
947 IN EFI_MEMORY_TYPE MemoryType
950 if ((UINT32
)MemoryType
>= MEMORY_TYPE_OS_RESERVED_MIN
) {
951 return EfiMaxMemoryType
;
952 } else if ((UINT32
)MemoryType
>= MEMORY_TYPE_OEM_RESERVED_MIN
) {
953 return EfiMaxMemoryType
+ 1;
960 Update memory profile Allocate information.
962 @param CallerAddress Address of caller who call Allocate.
963 @param Action This Allocate action.
964 @param MemoryType Memory type.
965 @param Size Buffer size.
966 @param Buffer Buffer address.
967 @param ActionString String for memory profile action.
969 @return EFI_SUCCESS Memory profile is updated.
970 @return EFI_UNSUPPORTED Memory profile is unsupported,
971 or memory profile for the image is not required.
972 @return EFI_OUT_OF_RESOURCES No enough resource to update memory profile for allocate action.
976 CoreUpdateProfileAllocate (
977 IN PHYSICAL_ADDRESS CallerAddress
,
978 IN MEMORY_PROFILE_ACTION Action
,
979 IN EFI_MEMORY_TYPE MemoryType
,
982 IN CHAR8
*ActionString OPTIONAL
986 MEMORY_PROFILE_CONTEXT
*Context
;
987 MEMORY_PROFILE_DRIVER_INFO
*DriverInfo
;
988 MEMORY_PROFILE_ALLOC_INFO
*AllocInfo
;
989 MEMORY_PROFILE_CONTEXT_DATA
*ContextData
;
990 MEMORY_PROFILE_DRIVER_INFO_DATA
*DriverInfoData
;
991 MEMORY_PROFILE_ALLOC_INFO_DATA
*AllocInfoData
;
992 UINTN ProfileMemoryIndex
;
993 MEMORY_PROFILE_ACTION BasicAction
;
994 UINTN ActionStringSize
;
995 UINTN ActionStringOccupiedSize
;
997 BasicAction
= Action
& MEMORY_PROFILE_ACTION_BASIC_MASK
;
999 ContextData
= GetMemoryProfileContext ();
1000 if (ContextData
== NULL
) {
1001 return EFI_UNSUPPORTED
;
1004 DriverInfoData
= GetMemoryProfileDriverInfoFromAddress (ContextData
, CallerAddress
);
1005 if (DriverInfoData
== NULL
) {
1006 return EFI_UNSUPPORTED
;
1009 ActionStringSize
= 0;
1010 ActionStringOccupiedSize
= 0;
1011 if (ActionString
!= NULL
) {
1012 ActionStringSize
= AsciiStrSize (ActionString
);
1013 ActionStringOccupiedSize
= GET_OCCUPIED_SIZE (ActionStringSize
, sizeof (UINT64
));
1017 // Use CoreInternalAllocatePool() that will not update profile for this AllocatePool action.
1019 AllocInfoData
= NULL
;
1020 Status
= CoreInternalAllocatePool (
1021 EfiBootServicesData
,
1022 sizeof (*AllocInfoData
) + ActionStringSize
,
1023 (VOID
**)&AllocInfoData
1025 if (EFI_ERROR (Status
)) {
1026 return EFI_OUT_OF_RESOURCES
;
1029 ASSERT (AllocInfoData
!= NULL
);
1032 // Only update SequenceCount if and only if it is basic action.
1034 if (Action
== BasicAction
) {
1035 ContextData
->Context
.SequenceCount
++;
1038 AllocInfo
= &AllocInfoData
->AllocInfo
;
1039 AllocInfoData
->Signature
= MEMORY_PROFILE_ALLOC_INFO_SIGNATURE
;
1040 AllocInfo
->Header
.Signature
= MEMORY_PROFILE_ALLOC_INFO_SIGNATURE
;
1041 AllocInfo
->Header
.Length
= (UINT16
)(sizeof (MEMORY_PROFILE_ALLOC_INFO
) + ActionStringOccupiedSize
);
1042 AllocInfo
->Header
.Revision
= MEMORY_PROFILE_ALLOC_INFO_REVISION
;
1043 AllocInfo
->CallerAddress
= CallerAddress
;
1044 AllocInfo
->SequenceId
= ContextData
->Context
.SequenceCount
;
1045 AllocInfo
->Action
= Action
;
1046 AllocInfo
->MemoryType
= MemoryType
;
1047 AllocInfo
->Buffer
= (PHYSICAL_ADDRESS
)(UINTN
)Buffer
;
1048 AllocInfo
->Size
= Size
;
1049 if (ActionString
!= NULL
) {
1050 AllocInfo
->ActionStringOffset
= (UINT16
)sizeof (MEMORY_PROFILE_ALLOC_INFO
);
1051 AllocInfoData
->ActionString
= (CHAR8
*)(AllocInfoData
+ 1);
1052 CopyMem (AllocInfoData
->ActionString
, ActionString
, ActionStringSize
);
1054 AllocInfo
->ActionStringOffset
= 0;
1055 AllocInfoData
->ActionString
= NULL
;
1058 InsertTailList (DriverInfoData
->AllocInfoList
, &AllocInfoData
->Link
);
1060 Context
= &ContextData
->Context
;
1061 DriverInfo
= &DriverInfoData
->DriverInfo
;
1062 DriverInfo
->AllocRecordCount
++;
1065 // Update summary if and only if it is basic action.
1067 if (Action
== BasicAction
) {
1068 ProfileMemoryIndex
= GetProfileMemoryIndex (MemoryType
);
1070 DriverInfo
->CurrentUsage
+= Size
;
1071 if (DriverInfo
->PeakUsage
< DriverInfo
->CurrentUsage
) {
1072 DriverInfo
->PeakUsage
= DriverInfo
->CurrentUsage
;
1075 DriverInfo
->CurrentUsageByType
[ProfileMemoryIndex
] += Size
;
1076 if (DriverInfo
->PeakUsageByType
[ProfileMemoryIndex
] < DriverInfo
->CurrentUsageByType
[ProfileMemoryIndex
]) {
1077 DriverInfo
->PeakUsageByType
[ProfileMemoryIndex
] = DriverInfo
->CurrentUsageByType
[ProfileMemoryIndex
];
1080 Context
->CurrentTotalUsage
+= Size
;
1081 if (Context
->PeakTotalUsage
< Context
->CurrentTotalUsage
) {
1082 Context
->PeakTotalUsage
= Context
->CurrentTotalUsage
;
1085 Context
->CurrentTotalUsageByType
[ProfileMemoryIndex
] += Size
;
1086 if (Context
->PeakTotalUsageByType
[ProfileMemoryIndex
] < Context
->CurrentTotalUsageByType
[ProfileMemoryIndex
]) {
1087 Context
->PeakTotalUsageByType
[ProfileMemoryIndex
] = Context
->CurrentTotalUsageByType
[ProfileMemoryIndex
];
1095 Get memory profile alloc info from memory profile.
1097 @param DriverInfoData Driver info.
1098 @param BasicAction This Free basic action.
1099 @param Size Buffer size.
1100 @param Buffer Buffer address.
1102 @return Pointer to memory profile alloc info.
1105 MEMORY_PROFILE_ALLOC_INFO_DATA
*
1106 GetMemoryProfileAllocInfoFromAddress (
1107 IN MEMORY_PROFILE_DRIVER_INFO_DATA
*DriverInfoData
,
1108 IN MEMORY_PROFILE_ACTION BasicAction
,
1113 LIST_ENTRY
*AllocInfoList
;
1114 LIST_ENTRY
*AllocLink
;
1115 MEMORY_PROFILE_ALLOC_INFO
*AllocInfo
;
1116 MEMORY_PROFILE_ALLOC_INFO_DATA
*AllocInfoData
;
1118 AllocInfoList
= DriverInfoData
->AllocInfoList
;
1120 for (AllocLink
= AllocInfoList
->ForwardLink
;
1121 AllocLink
!= AllocInfoList
;
1122 AllocLink
= AllocLink
->ForwardLink
)
1124 AllocInfoData
= CR (
1126 MEMORY_PROFILE_ALLOC_INFO_DATA
,
1128 MEMORY_PROFILE_ALLOC_INFO_SIGNATURE
1130 AllocInfo
= &AllocInfoData
->AllocInfo
;
1131 if ((AllocInfo
->Action
& MEMORY_PROFILE_ACTION_BASIC_MASK
) != BasicAction
) {
1135 switch (BasicAction
) {
1136 case MemoryProfileActionAllocatePages
:
1137 if ((AllocInfo
->Buffer
<= (PHYSICAL_ADDRESS
)(UINTN
)Buffer
) &&
1138 ((AllocInfo
->Buffer
+ AllocInfo
->Size
) >= ((PHYSICAL_ADDRESS
)(UINTN
)Buffer
+ Size
)))
1140 return AllocInfoData
;
1144 case MemoryProfileActionAllocatePool
:
1145 if (AllocInfo
->Buffer
== (PHYSICAL_ADDRESS
)(UINTN
)Buffer
) {
1146 return AllocInfoData
;
1160 Update memory profile Free information.
1162 @param CallerAddress Address of caller who call Free.
1163 @param Action This Free action.
1164 @param Size Buffer size.
1165 @param Buffer Buffer address.
1167 @return EFI_SUCCESS Memory profile is updated.
1168 @return EFI_UNSUPPORTED Memory profile is unsupported.
1169 @return EFI_NOT_FOUND No matched allocate info found for free action.
1173 CoreUpdateProfileFree (
1174 IN PHYSICAL_ADDRESS CallerAddress
,
1175 IN MEMORY_PROFILE_ACTION Action
,
1180 MEMORY_PROFILE_CONTEXT
*Context
;
1181 MEMORY_PROFILE_DRIVER_INFO
*DriverInfo
;
1182 MEMORY_PROFILE_ALLOC_INFO
*AllocInfo
;
1183 MEMORY_PROFILE_CONTEXT_DATA
*ContextData
;
1184 MEMORY_PROFILE_DRIVER_INFO_DATA
*DriverInfoData
;
1185 LIST_ENTRY
*DriverLink
;
1186 LIST_ENTRY
*DriverInfoList
;
1187 MEMORY_PROFILE_DRIVER_INFO_DATA
*ThisDriverInfoData
;
1188 MEMORY_PROFILE_ALLOC_INFO_DATA
*AllocInfoData
;
1189 UINTN ProfileMemoryIndex
;
1190 MEMORY_PROFILE_ACTION BasicAction
;
1193 BasicAction
= Action
& MEMORY_PROFILE_ACTION_BASIC_MASK
;
1195 ContextData
= GetMemoryProfileContext ();
1196 if (ContextData
== NULL
) {
1197 return EFI_UNSUPPORTED
;
1200 DriverInfoData
= GetMemoryProfileDriverInfoFromAddress (ContextData
, CallerAddress
);
1203 // Do not return if DriverInfoData == NULL here,
1204 // because driver A might free memory allocated by driver B.
1208 // Need use do-while loop to find all possible records,
1209 // because one address might be recorded multiple times.
1212 AllocInfoData
= NULL
;
1214 if (DriverInfoData
!= NULL
) {
1215 switch (BasicAction
) {
1216 case MemoryProfileActionFreePages
:
1217 AllocInfoData
= GetMemoryProfileAllocInfoFromAddress (DriverInfoData
, MemoryProfileActionAllocatePages
, Size
, Buffer
);
1219 case MemoryProfileActionFreePool
:
1220 AllocInfoData
= GetMemoryProfileAllocInfoFromAddress (DriverInfoData
, MemoryProfileActionAllocatePool
, 0, Buffer
);
1224 AllocInfoData
= NULL
;
1229 if (AllocInfoData
== NULL
) {
1231 // Legal case, because driver A might free memory allocated by driver B, by some protocol.
1233 DriverInfoList
= ContextData
->DriverInfoList
;
1235 for (DriverLink
= DriverInfoList
->ForwardLink
;
1236 DriverLink
!= DriverInfoList
;
1237 DriverLink
= DriverLink
->ForwardLink
)
1239 ThisDriverInfoData
= CR (
1241 MEMORY_PROFILE_DRIVER_INFO_DATA
,
1243 MEMORY_PROFILE_DRIVER_INFO_SIGNATURE
1245 switch (BasicAction
) {
1246 case MemoryProfileActionFreePages
:
1247 AllocInfoData
= GetMemoryProfileAllocInfoFromAddress (ThisDriverInfoData
, MemoryProfileActionAllocatePages
, Size
, Buffer
);
1249 case MemoryProfileActionFreePool
:
1250 AllocInfoData
= GetMemoryProfileAllocInfoFromAddress (ThisDriverInfoData
, MemoryProfileActionAllocatePool
, 0, Buffer
);
1254 AllocInfoData
= NULL
;
1258 if (AllocInfoData
!= NULL
) {
1259 DriverInfoData
= ThisDriverInfoData
;
1264 if (AllocInfoData
== NULL
) {
1266 // If (!Found), no matched allocate info is found for this free action.
1267 // It is because the specified memory type allocate actions have been filtered by
1268 // CoreNeedRecordProfile(), but free actions may have no memory type information,
1269 // they can not be filtered by CoreNeedRecordProfile(). Then, they will be
1272 // If (Found), it is normal exit path.
1273 return (Found
? EFI_SUCCESS
: EFI_NOT_FOUND
);
1277 ASSERT (DriverInfoData
!= NULL
);
1278 ASSERT (AllocInfoData
!= NULL
);
1282 Context
= &ContextData
->Context
;
1283 DriverInfo
= &DriverInfoData
->DriverInfo
;
1284 AllocInfo
= &AllocInfoData
->AllocInfo
;
1286 DriverInfo
->AllocRecordCount
--;
1288 // Update summary if and only if it is basic action.
1290 if (AllocInfo
->Action
== (AllocInfo
->Action
& MEMORY_PROFILE_ACTION_BASIC_MASK
)) {
1291 ProfileMemoryIndex
= GetProfileMemoryIndex (AllocInfo
->MemoryType
);
1293 Context
->CurrentTotalUsage
-= AllocInfo
->Size
;
1294 Context
->CurrentTotalUsageByType
[ProfileMemoryIndex
] -= AllocInfo
->Size
;
1296 DriverInfo
->CurrentUsage
-= AllocInfo
->Size
;
1297 DriverInfo
->CurrentUsageByType
[ProfileMemoryIndex
] -= AllocInfo
->Size
;
1300 RemoveEntryList (&AllocInfoData
->Link
);
1302 if (BasicAction
== MemoryProfileActionFreePages
) {
1303 if (AllocInfo
->Buffer
!= (PHYSICAL_ADDRESS
)(UINTN
)Buffer
) {
1304 CoreUpdateProfileAllocate (
1305 AllocInfo
->CallerAddress
,
1307 AllocInfo
->MemoryType
,
1308 (UINTN
)((PHYSICAL_ADDRESS
)(UINTN
)Buffer
- AllocInfo
->Buffer
),
1309 (VOID
*)(UINTN
)AllocInfo
->Buffer
,
1310 AllocInfoData
->ActionString
1314 if (AllocInfo
->Buffer
+ AllocInfo
->Size
!= ((PHYSICAL_ADDRESS
)(UINTN
)Buffer
+ Size
)) {
1315 CoreUpdateProfileAllocate (
1316 AllocInfo
->CallerAddress
,
1318 AllocInfo
->MemoryType
,
1319 (UINTN
)((AllocInfo
->Buffer
+ AllocInfo
->Size
) - ((PHYSICAL_ADDRESS
)(UINTN
)Buffer
+ Size
)),
1320 (VOID
*)((UINTN
)Buffer
+ Size
),
1321 AllocInfoData
->ActionString
1327 // Use CoreInternalFreePool() that will not update profile for this FreePool action.
1329 CoreInternalFreePool (AllocInfoData
, NULL
);
1334 Update memory profile information.
1336 @param CallerAddress Address of caller who call Allocate or Free.
1337 @param Action This Allocate or Free action.
1338 @param MemoryType Memory type.
1339 EfiMaxMemoryType means the MemoryType is unknown.
1340 @param Size Buffer size.
1341 @param Buffer Buffer address.
1342 @param ActionString String for memory profile action.
1343 Only needed for user defined allocate action.
1345 @return EFI_SUCCESS Memory profile is updated.
1346 @return EFI_UNSUPPORTED Memory profile is unsupported,
1347 or memory profile for the image is not required,
1348 or memory profile for the memory type is not required.
1349 @return EFI_ACCESS_DENIED It is during memory profile data getting.
1350 @return EFI_ABORTED Memory profile recording is not enabled.
1351 @return EFI_OUT_OF_RESOURCES No enough resource to update memory profile for allocate action.
1352 @return EFI_NOT_FOUND No matched allocate info found for free action.
1358 IN PHYSICAL_ADDRESS CallerAddress
,
1359 IN MEMORY_PROFILE_ACTION Action
,
1360 IN EFI_MEMORY_TYPE MemoryType
,
1361 IN UINTN Size
, // Valid for AllocatePages/FreePages/AllocatePool
1363 IN CHAR8
*ActionString OPTIONAL
1367 MEMORY_PROFILE_CONTEXT_DATA
*ContextData
;
1368 MEMORY_PROFILE_ACTION BasicAction
;
1370 if (!IS_UEFI_MEMORY_PROFILE_ENABLED
) {
1371 return EFI_UNSUPPORTED
;
1374 if (mMemoryProfileGettingStatus
) {
1375 return EFI_ACCESS_DENIED
;
1378 if (!mMemoryProfileRecordingEnable
) {
1383 // Get the basic action to know how to process the record
1385 BasicAction
= Action
& MEMORY_PROFILE_ACTION_BASIC_MASK
;
1388 // EfiMaxMemoryType means the MemoryType is unknown.
1390 if (MemoryType
!= EfiMaxMemoryType
) {
1392 // Only record limited MemoryType.
1394 if (!CoreNeedRecordProfile (MemoryType
)) {
1395 return EFI_UNSUPPORTED
;
1399 ContextData
= GetMemoryProfileContext ();
1400 if (ContextData
== NULL
) {
1401 return EFI_UNSUPPORTED
;
1404 CoreAcquireMemoryProfileLock ();
1405 switch (BasicAction
) {
1406 case MemoryProfileActionAllocatePages
:
1407 Status
= CoreUpdateProfileAllocate (CallerAddress
, Action
, MemoryType
, Size
, Buffer
, ActionString
);
1409 case MemoryProfileActionFreePages
:
1410 Status
= CoreUpdateProfileFree (CallerAddress
, Action
, Size
, Buffer
);
1412 case MemoryProfileActionAllocatePool
:
1413 Status
= CoreUpdateProfileAllocate (CallerAddress
, Action
, MemoryType
, Size
, Buffer
, ActionString
);
1415 case MemoryProfileActionFreePool
:
1416 Status
= CoreUpdateProfileFree (CallerAddress
, Action
, 0, Buffer
);
1420 Status
= EFI_UNSUPPORTED
;
1424 CoreReleaseMemoryProfileLock ();
1429 ////////////////////
1432 Get memory profile data size.
1434 @return Memory profile data size.
1438 MemoryProfileGetDataSize (
1442 MEMORY_PROFILE_CONTEXT_DATA
*ContextData
;
1443 MEMORY_PROFILE_DRIVER_INFO_DATA
*DriverInfoData
;
1444 MEMORY_PROFILE_ALLOC_INFO_DATA
*AllocInfoData
;
1445 LIST_ENTRY
*DriverInfoList
;
1446 LIST_ENTRY
*DriverLink
;
1447 LIST_ENTRY
*AllocInfoList
;
1448 LIST_ENTRY
*AllocLink
;
1451 ContextData
= GetMemoryProfileContext ();
1452 if (ContextData
== NULL
) {
1456 TotalSize
= sizeof (MEMORY_PROFILE_CONTEXT
);
1458 DriverInfoList
= ContextData
->DriverInfoList
;
1459 for (DriverLink
= DriverInfoList
->ForwardLink
;
1460 DriverLink
!= DriverInfoList
;
1461 DriverLink
= DriverLink
->ForwardLink
)
1463 DriverInfoData
= CR (
1465 MEMORY_PROFILE_DRIVER_INFO_DATA
,
1467 MEMORY_PROFILE_DRIVER_INFO_SIGNATURE
1469 TotalSize
+= DriverInfoData
->DriverInfo
.Header
.Length
;
1471 AllocInfoList
= DriverInfoData
->AllocInfoList
;
1472 for (AllocLink
= AllocInfoList
->ForwardLink
;
1473 AllocLink
!= AllocInfoList
;
1474 AllocLink
= AllocLink
->ForwardLink
)
1476 AllocInfoData
= CR (
1478 MEMORY_PROFILE_ALLOC_INFO_DATA
,
1480 MEMORY_PROFILE_ALLOC_INFO_SIGNATURE
1482 TotalSize
+= AllocInfoData
->AllocInfo
.Header
.Length
;
1490 Copy memory profile data.
1492 @param ProfileBuffer The buffer to hold memory profile data.
1496 MemoryProfileCopyData (
1497 IN VOID
*ProfileBuffer
1500 MEMORY_PROFILE_CONTEXT
*Context
;
1501 MEMORY_PROFILE_DRIVER_INFO
*DriverInfo
;
1502 MEMORY_PROFILE_ALLOC_INFO
*AllocInfo
;
1503 MEMORY_PROFILE_CONTEXT_DATA
*ContextData
;
1504 MEMORY_PROFILE_DRIVER_INFO_DATA
*DriverInfoData
;
1505 MEMORY_PROFILE_ALLOC_INFO_DATA
*AllocInfoData
;
1506 LIST_ENTRY
*DriverInfoList
;
1507 LIST_ENTRY
*DriverLink
;
1508 LIST_ENTRY
*AllocInfoList
;
1509 LIST_ENTRY
*AllocLink
;
1511 UINTN ActionStringSize
;
1513 ContextData
= GetMemoryProfileContext ();
1514 if (ContextData
== NULL
) {
1518 Context
= ProfileBuffer
;
1519 CopyMem (Context
, &ContextData
->Context
, sizeof (MEMORY_PROFILE_CONTEXT
));
1520 DriverInfo
= (MEMORY_PROFILE_DRIVER_INFO
*)(Context
+ 1);
1522 DriverInfoList
= ContextData
->DriverInfoList
;
1523 for (DriverLink
= DriverInfoList
->ForwardLink
;
1524 DriverLink
!= DriverInfoList
;
1525 DriverLink
= DriverLink
->ForwardLink
)
1527 DriverInfoData
= CR (
1529 MEMORY_PROFILE_DRIVER_INFO_DATA
,
1531 MEMORY_PROFILE_DRIVER_INFO_SIGNATURE
1533 CopyMem (DriverInfo
, &DriverInfoData
->DriverInfo
, sizeof (MEMORY_PROFILE_DRIVER_INFO
));
1534 if (DriverInfo
->PdbStringOffset
!= 0) {
1535 PdbSize
= AsciiStrSize (DriverInfoData
->PdbString
);
1536 CopyMem ((VOID
*)((UINTN
)DriverInfo
+ DriverInfo
->PdbStringOffset
), DriverInfoData
->PdbString
, PdbSize
);
1539 AllocInfo
= (MEMORY_PROFILE_ALLOC_INFO
*)((UINTN
)DriverInfo
+ DriverInfo
->Header
.Length
);
1541 AllocInfoList
= DriverInfoData
->AllocInfoList
;
1542 for (AllocLink
= AllocInfoList
->ForwardLink
;
1543 AllocLink
!= AllocInfoList
;
1544 AllocLink
= AllocLink
->ForwardLink
)
1546 AllocInfoData
= CR (
1548 MEMORY_PROFILE_ALLOC_INFO_DATA
,
1550 MEMORY_PROFILE_ALLOC_INFO_SIGNATURE
1552 CopyMem (AllocInfo
, &AllocInfoData
->AllocInfo
, sizeof (MEMORY_PROFILE_ALLOC_INFO
));
1553 if (AllocInfo
->ActionStringOffset
!= 0) {
1554 ActionStringSize
= AsciiStrSize (AllocInfoData
->ActionString
);
1555 CopyMem ((VOID
*)((UINTN
)AllocInfo
+ AllocInfo
->ActionStringOffset
), AllocInfoData
->ActionString
, ActionStringSize
);
1558 AllocInfo
= (MEMORY_PROFILE_ALLOC_INFO
*)((UINTN
)AllocInfo
+ AllocInfo
->Header
.Length
);
1561 DriverInfo
= (MEMORY_PROFILE_DRIVER_INFO
*)AllocInfo
;
1566 Get memory profile data.
1568 @param[in] This The EDKII_MEMORY_PROFILE_PROTOCOL instance.
1569 @param[in, out] ProfileSize On entry, points to the size in bytes of the ProfileBuffer.
1570 On return, points to the size of the data returned in ProfileBuffer.
1571 @param[out] ProfileBuffer Profile buffer.
1573 @return EFI_SUCCESS Get the memory profile data successfully.
1574 @return EFI_UNSUPPORTED Memory profile is unsupported.
1575 @return EFI_BUFFER_TO_SMALL The ProfileSize is too small for the resulting data.
1576 ProfileSize is updated with the size required.
1581 ProfileProtocolGetData (
1582 IN EDKII_MEMORY_PROFILE_PROTOCOL
*This
,
1583 IN OUT UINT64
*ProfileSize
,
1584 OUT VOID
*ProfileBuffer
1588 MEMORY_PROFILE_CONTEXT_DATA
*ContextData
;
1589 BOOLEAN MemoryProfileGettingStatus
;
1591 ContextData
= GetMemoryProfileContext ();
1592 if (ContextData
== NULL
) {
1593 return EFI_UNSUPPORTED
;
1596 MemoryProfileGettingStatus
= mMemoryProfileGettingStatus
;
1597 mMemoryProfileGettingStatus
= TRUE
;
1599 Size
= MemoryProfileGetDataSize ();
1601 if (*ProfileSize
< Size
) {
1602 *ProfileSize
= Size
;
1603 mMemoryProfileGettingStatus
= MemoryProfileGettingStatus
;
1604 return EFI_BUFFER_TOO_SMALL
;
1607 *ProfileSize
= Size
;
1608 MemoryProfileCopyData (ProfileBuffer
);
1610 mMemoryProfileGettingStatus
= MemoryProfileGettingStatus
;
1615 Register image to memory profile.
1617 @param[in] This The EDKII_MEMORY_PROFILE_PROTOCOL instance.
1618 @param[in] FilePath File path of the image.
1619 @param[in] ImageBase Image base address.
1620 @param[in] ImageSize Image size.
1621 @param[in] FileType File type of the image.
1623 @return EFI_SUCCESS Register successfully.
1624 @return EFI_UNSUPPORTED Memory profile is unsupported,
1625 or memory profile for the image is not required.
1626 @return EFI_OUT_OF_RESOURCES No enough resource for this register.
1631 ProfileProtocolRegisterImage (
1632 IN EDKII_MEMORY_PROFILE_PROTOCOL
*This
,
1633 IN EFI_DEVICE_PATH_PROTOCOL
*FilePath
,
1634 IN PHYSICAL_ADDRESS ImageBase
,
1635 IN UINT64 ImageSize
,
1636 IN EFI_FV_FILETYPE FileType
1640 LOADED_IMAGE_PRIVATE_DATA DriverEntry
;
1641 VOID
*EntryPointInImage
;
1643 ZeroMem (&DriverEntry
, sizeof (DriverEntry
));
1644 DriverEntry
.Info
.FilePath
= FilePath
;
1645 DriverEntry
.ImageContext
.ImageAddress
= ImageBase
;
1646 DriverEntry
.ImageContext
.ImageSize
= ImageSize
;
1647 Status
= InternalPeCoffGetEntryPoint ((VOID
*)(UINTN
)ImageBase
, &EntryPointInImage
);
1648 ASSERT_EFI_ERROR (Status
);
1649 DriverEntry
.ImageContext
.EntryPoint
= (PHYSICAL_ADDRESS
)(UINTN
)EntryPointInImage
;
1650 DriverEntry
.ImageContext
.ImageType
= InternalPeCoffGetSubsystem ((VOID
*)(UINTN
)ImageBase
);
1652 return RegisterMemoryProfileImage (&DriverEntry
, FileType
);
1656 Unregister image from memory profile.
1658 @param[in] This The EDKII_MEMORY_PROFILE_PROTOCOL instance.
1659 @param[in] FilePath File path of the image.
1660 @param[in] ImageBase Image base address.
1661 @param[in] ImageSize Image size.
1663 @return EFI_SUCCESS Unregister successfully.
1664 @return EFI_UNSUPPORTED Memory profile is unsupported,
1665 or memory profile for the image is not required.
1666 @return EFI_NOT_FOUND The image is not found.
1671 ProfileProtocolUnregisterImage (
1672 IN EDKII_MEMORY_PROFILE_PROTOCOL
*This
,
1673 IN EFI_DEVICE_PATH_PROTOCOL
*FilePath
,
1674 IN PHYSICAL_ADDRESS ImageBase
,
1679 LOADED_IMAGE_PRIVATE_DATA DriverEntry
;
1680 VOID
*EntryPointInImage
;
1682 ZeroMem (&DriverEntry
, sizeof (DriverEntry
));
1683 DriverEntry
.Info
.FilePath
= FilePath
;
1684 DriverEntry
.ImageContext
.ImageAddress
= ImageBase
;
1685 DriverEntry
.ImageContext
.ImageSize
= ImageSize
;
1686 Status
= InternalPeCoffGetEntryPoint ((VOID
*)(UINTN
)ImageBase
, &EntryPointInImage
);
1687 ASSERT_EFI_ERROR (Status
);
1688 DriverEntry
.ImageContext
.EntryPoint
= (PHYSICAL_ADDRESS
)(UINTN
)EntryPointInImage
;
1690 return UnregisterMemoryProfileImage (&DriverEntry
);
1694 Get memory profile recording state.
1696 @param[in] This The EDKII_MEMORY_PROFILE_PROTOCOL instance.
1697 @param[out] RecordingState Recording state.
1699 @return EFI_SUCCESS Memory profile recording state is returned.
1700 @return EFI_UNSUPPORTED Memory profile is unsupported.
1701 @return EFI_INVALID_PARAMETER RecordingState is NULL.
1706 ProfileProtocolGetRecordingState (
1707 IN EDKII_MEMORY_PROFILE_PROTOCOL
*This
,
1708 OUT BOOLEAN
*RecordingState
1711 MEMORY_PROFILE_CONTEXT_DATA
*ContextData
;
1713 ContextData
= GetMemoryProfileContext ();
1714 if (ContextData
== NULL
) {
1715 return EFI_UNSUPPORTED
;
1718 if (RecordingState
== NULL
) {
1719 return EFI_INVALID_PARAMETER
;
1722 *RecordingState
= mMemoryProfileRecordingEnable
;
1727 Set memory profile recording state.
1729 @param[in] This The EDKII_MEMORY_PROFILE_PROTOCOL instance.
1730 @param[in] RecordingState Recording state.
1732 @return EFI_SUCCESS Set memory profile recording state successfully.
1733 @return EFI_UNSUPPORTED Memory profile is unsupported.
1738 ProfileProtocolSetRecordingState (
1739 IN EDKII_MEMORY_PROFILE_PROTOCOL
*This
,
1740 IN BOOLEAN RecordingState
1743 MEMORY_PROFILE_CONTEXT_DATA
*ContextData
;
1745 ContextData
= GetMemoryProfileContext ();
1746 if (ContextData
== NULL
) {
1747 return EFI_UNSUPPORTED
;
1750 mMemoryProfileRecordingEnable
= RecordingState
;
1755 Record memory profile of multilevel caller.
1757 @param[in] This The EDKII_MEMORY_PROFILE_PROTOCOL instance.
1758 @param[in] CallerAddress Address of caller.
1759 @param[in] Action Memory profile action.
1760 @param[in] MemoryType Memory type.
1761 EfiMaxMemoryType means the MemoryType is unknown.
1762 @param[in] Buffer Buffer address.
1763 @param[in] Size Buffer size.
1764 @param[in] ActionString String for memory profile action.
1765 Only needed for user defined allocate action.
1767 @return EFI_SUCCESS Memory profile is updated.
1768 @return EFI_UNSUPPORTED Memory profile is unsupported,
1769 or memory profile for the image is not required,
1770 or memory profile for the memory type is not required.
1771 @return EFI_ACCESS_DENIED It is during memory profile data getting.
1772 @return EFI_ABORTED Memory profile recording is not enabled.
1773 @return EFI_OUT_OF_RESOURCES No enough resource to update memory profile for allocate action.
1774 @return EFI_NOT_FOUND No matched allocate info found for free action.
1779 ProfileProtocolRecord (
1780 IN EDKII_MEMORY_PROFILE_PROTOCOL
*This
,
1781 IN PHYSICAL_ADDRESS CallerAddress
,
1782 IN MEMORY_PROFILE_ACTION Action
,
1783 IN EFI_MEMORY_TYPE MemoryType
,
1786 IN CHAR8
*ActionString OPTIONAL
1789 return CoreUpdateProfile (CallerAddress
, Action
, MemoryType
, Size
, Buffer
, ActionString
);
1792 ////////////////////