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
;
39 GLOBAL_REMOVE_IF_UNREFERENCED LIST_ENTRY mImageQueue
= INITIALIZE_LIST_HEAD_VARIABLE (mImageQueue
);
40 GLOBAL_REMOVE_IF_UNREFERENCED MEMORY_PROFILE_CONTEXT_DATA mMemoryProfileContext
= {
41 MEMORY_PROFILE_CONTEXT_SIGNATURE
,
44 MEMORY_PROFILE_CONTEXT_SIGNATURE
,
45 sizeof (MEMORY_PROFILE_CONTEXT
),
46 MEMORY_PROFILE_CONTEXT_REVISION
58 GLOBAL_REMOVE_IF_UNREFERENCED MEMORY_PROFILE_CONTEXT_DATA
*mMemoryProfileContextPtr
= NULL
;
60 GLOBAL_REMOVE_IF_UNREFERENCED EFI_LOCK mMemoryProfileLock
= EFI_INITIALIZE_LOCK_VARIABLE (TPL_NOTIFY
);
61 GLOBAL_REMOVE_IF_UNREFERENCED BOOLEAN mMemoryProfileGettingStatus
= FALSE
;
62 GLOBAL_REMOVE_IF_UNREFERENCED BOOLEAN mMemoryProfileRecordingEnable
= MEMORY_PROFILE_RECORDING_DISABLE
;
63 GLOBAL_REMOVE_IF_UNREFERENCED EFI_DEVICE_PATH_PROTOCOL
*mMemoryProfileDriverPath
;
64 GLOBAL_REMOVE_IF_UNREFERENCED UINTN mMemoryProfileDriverPathSize
;
67 Get memory profile data.
69 @param[in] This The EDKII_MEMORY_PROFILE_PROTOCOL instance.
70 @param[in, out] ProfileSize On entry, points to the size in bytes of the ProfileBuffer.
71 On return, points to the size of the data returned in ProfileBuffer.
72 @param[out] ProfileBuffer Profile buffer.
74 @return EFI_SUCCESS Get the memory profile data successfully.
75 @return EFI_UNSUPPORTED Memory profile is unsupported.
76 @return EFI_BUFFER_TO_SMALL The ProfileSize is too small for the resulting data.
77 ProfileSize is updated with the size required.
82 ProfileProtocolGetData (
83 IN EDKII_MEMORY_PROFILE_PROTOCOL
*This
,
84 IN OUT UINT64
*ProfileSize
,
85 OUT VOID
*ProfileBuffer
89 Register image to memory profile.
91 @param[in] This The EDKII_MEMORY_PROFILE_PROTOCOL instance.
92 @param[in] FilePath File path of the image.
93 @param[in] ImageBase Image base address.
94 @param[in] ImageSize Image size.
95 @param[in] FileType File type of the image.
97 @return EFI_SUCCESS Register successfully.
98 @return EFI_UNSUPPORTED Memory profile is unsupported,
99 or memory profile for the image is not required.
100 @return EFI_OUT_OF_RESOURCE No enough resource for this register.
105 ProfileProtocolRegisterImage (
106 IN EDKII_MEMORY_PROFILE_PROTOCOL
*This
,
107 IN EFI_DEVICE_PATH_PROTOCOL
*FilePath
,
108 IN PHYSICAL_ADDRESS ImageBase
,
110 IN EFI_FV_FILETYPE FileType
114 Unregister image from memory profile.
116 @param[in] This The EDKII_MEMORY_PROFILE_PROTOCOL instance.
117 @param[in] FilePath File path of the image.
118 @param[in] ImageBase Image base address.
119 @param[in] ImageSize Image size.
121 @return EFI_SUCCESS Unregister successfully.
122 @return EFI_UNSUPPORTED Memory profile is unsupported,
123 or memory profile for the image is not required.
124 @return EFI_NOT_FOUND The image is not found.
129 ProfileProtocolUnregisterImage (
130 IN EDKII_MEMORY_PROFILE_PROTOCOL
*This
,
131 IN EFI_DEVICE_PATH_PROTOCOL
*FilePath
,
132 IN PHYSICAL_ADDRESS ImageBase
,
137 Get memory profile recording state.
139 @param[in] This The EDKII_MEMORY_PROFILE_PROTOCOL instance.
140 @param[out] RecordingState Recording state.
142 @return EFI_SUCCESS Memory profile recording state is returned.
143 @return EFI_UNSUPPORTED Memory profile is unsupported.
144 @return EFI_INVALID_PARAMETER RecordingState is NULL.
149 ProfileProtocolGetRecordingState (
150 IN EDKII_MEMORY_PROFILE_PROTOCOL
*This
,
151 OUT BOOLEAN
*RecordingState
155 Set memory profile recording state.
157 @param[in] This The EDKII_MEMORY_PROFILE_PROTOCOL instance.
158 @param[in] RecordingState Recording state.
160 @return EFI_SUCCESS Set memory profile recording state successfully.
161 @return EFI_UNSUPPORTED Memory profile is unsupported.
166 ProfileProtocolSetRecordingState (
167 IN EDKII_MEMORY_PROFILE_PROTOCOL
*This
,
168 IN BOOLEAN RecordingState
172 Record memory profile of multilevel caller.
174 @param[in] This The EDKII_MEMORY_PROFILE_PROTOCOL instance.
175 @param[in] CallerAddress Address of caller.
176 @param[in] Action Memory profile action.
177 @param[in] MemoryType Memory type.
178 EfiMaxMemoryType means the MemoryType is unknown.
179 @param[in] Buffer Buffer address.
180 @param[in] Size Buffer size.
181 @param[in] ActionString String for memory profile action.
182 Only needed for user defined allocate action.
184 @return EFI_SUCCESS Memory profile is updated.
185 @return EFI_UNSUPPORTED Memory profile is unsupported,
186 or memory profile for the image is not required,
187 or memory profile for the memory type is not required.
188 @return EFI_ACCESS_DENIED It is during memory profile data getting.
189 @return EFI_ABORTED Memory profile recording is not enabled.
190 @return EFI_OUT_OF_RESOURCES No enough resource to update memory profile for allocate action.
191 @return EFI_NOT_FOUND No matched allocate info found for free action.
196 ProfileProtocolRecord (
197 IN EDKII_MEMORY_PROFILE_PROTOCOL
*This
,
198 IN PHYSICAL_ADDRESS CallerAddress
,
199 IN MEMORY_PROFILE_ACTION Action
,
200 IN EFI_MEMORY_TYPE MemoryType
,
203 IN CHAR8
*ActionString OPTIONAL
206 GLOBAL_REMOVE_IF_UNREFERENCED EDKII_MEMORY_PROFILE_PROTOCOL mProfileProtocol
= {
207 ProfileProtocolGetData
,
208 ProfileProtocolRegisterImage
,
209 ProfileProtocolUnregisterImage
,
210 ProfileProtocolGetRecordingState
,
211 ProfileProtocolSetRecordingState
,
212 ProfileProtocolRecord
,
216 Acquire lock on mMemoryProfileLock.
219 CoreAcquireMemoryProfileLock (
223 CoreAcquireLock (&mMemoryProfileLock
);
227 Release lock on mMemoryProfileLock.
230 CoreReleaseMemoryProfileLock (
234 CoreReleaseLock (&mMemoryProfileLock
);
238 Return memory profile context.
240 @return Memory profile context.
243 MEMORY_PROFILE_CONTEXT_DATA
*
244 GetMemoryProfileContext (
248 return mMemoryProfileContextPtr
;
252 Retrieves and returns the Subsystem of a PE/COFF image that has been loaded into system memory.
253 If Pe32Data is NULL, then ASSERT().
255 @param Pe32Data The pointer to the PE/COFF image that is loaded in system memory.
257 @return The Subsystem of the PE/COFF image.
261 InternalPeCoffGetSubsystem (
265 EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION Hdr
;
266 EFI_IMAGE_DOS_HEADER
*DosHdr
;
269 ASSERT (Pe32Data
!= NULL
);
271 DosHdr
= (EFI_IMAGE_DOS_HEADER
*) Pe32Data
;
272 if (DosHdr
->e_magic
== EFI_IMAGE_DOS_SIGNATURE
) {
274 // DOS image header is present, so read the PE header after the DOS image header.
276 Hdr
.Pe32
= (EFI_IMAGE_NT_HEADERS32
*) ((UINTN
) Pe32Data
+ (UINTN
) ((DosHdr
->e_lfanew
) & 0x0ffff));
279 // DOS image header is not present, so PE header is at the image base.
281 Hdr
.Pe32
= (EFI_IMAGE_NT_HEADERS32
*) Pe32Data
;
284 if (Hdr
.Te
->Signature
== EFI_TE_IMAGE_HEADER_SIGNATURE
) {
285 return Hdr
.Te
->Subsystem
;
286 } else if (Hdr
.Pe32
->Signature
== EFI_IMAGE_NT_SIGNATURE
) {
287 Magic
= Hdr
.Pe32
->OptionalHeader
.Magic
;
288 if (Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
289 return Hdr
.Pe32
->OptionalHeader
.Subsystem
;
290 } else if (Magic
== EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC
) {
291 return Hdr
.Pe32Plus
->OptionalHeader
.Subsystem
;
299 Retrieves and returns a pointer to the entry point to a PE/COFF image that has been loaded
300 into system memory with the PE/COFF Loader Library functions.
302 Retrieves the entry point to the PE/COFF image specified by Pe32Data and returns this entry
303 point in EntryPoint. If the entry point could not be retrieved from the PE/COFF image, then
304 return RETURN_INVALID_PARAMETER. Otherwise return RETURN_SUCCESS.
305 If Pe32Data is NULL, then ASSERT().
306 If EntryPoint is NULL, then ASSERT().
308 @param Pe32Data The pointer to the PE/COFF image that is loaded in system memory.
309 @param EntryPoint The pointer to entry point to the PE/COFF image to return.
311 @retval RETURN_SUCCESS EntryPoint was returned.
312 @retval RETURN_INVALID_PARAMETER The entry point could not be found in the PE/COFF image.
316 InternalPeCoffGetEntryPoint (
318 OUT VOID
**EntryPoint
321 EFI_IMAGE_DOS_HEADER
*DosHdr
;
322 EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION Hdr
;
324 ASSERT (Pe32Data
!= NULL
);
325 ASSERT (EntryPoint
!= NULL
);
327 DosHdr
= (EFI_IMAGE_DOS_HEADER
*) Pe32Data
;
328 if (DosHdr
->e_magic
== EFI_IMAGE_DOS_SIGNATURE
) {
330 // DOS image header is present, so read the PE header after the DOS image header.
332 Hdr
.Pe32
= (EFI_IMAGE_NT_HEADERS32
*) ((UINTN
) Pe32Data
+ (UINTN
) ((DosHdr
->e_lfanew
) & 0x0ffff));
335 // DOS image header is not present, so PE header is at the image base.
337 Hdr
.Pe32
= (EFI_IMAGE_NT_HEADERS32
*) Pe32Data
;
341 // Calculate the entry point relative to the start of the image.
342 // AddressOfEntryPoint is common for PE32 & PE32+
344 if (Hdr
.Te
->Signature
== EFI_TE_IMAGE_HEADER_SIGNATURE
) {
345 *EntryPoint
= (VOID
*) ((UINTN
) Pe32Data
+ (UINTN
) (Hdr
.Te
->AddressOfEntryPoint
& 0x0ffffffff) + sizeof (EFI_TE_IMAGE_HEADER
) - Hdr
.Te
->StrippedSize
);
346 return RETURN_SUCCESS
;
347 } else if (Hdr
.Pe32
->Signature
== EFI_IMAGE_NT_SIGNATURE
) {
348 *EntryPoint
= (VOID
*) ((UINTN
) Pe32Data
+ (UINTN
) (Hdr
.Pe32
->OptionalHeader
.AddressOfEntryPoint
& 0x0ffffffff));
349 return RETURN_SUCCESS
;
352 return RETURN_UNSUPPORTED
;
358 @param ContextData Memory profile context.
359 @param FileName File name of the image.
360 @param ImageBase Image base address.
361 @param ImageSize Image size.
362 @param EntryPoint Entry point of the image.
363 @param ImageSubsystem Image subsystem of the image.
364 @param FileType File type of the image.
366 @return Pointer to memory profile driver info.
369 MEMORY_PROFILE_DRIVER_INFO_DATA
*
371 IN MEMORY_PROFILE_CONTEXT_DATA
*ContextData
,
372 IN EFI_GUID
*FileName
,
373 IN PHYSICAL_ADDRESS ImageBase
,
375 IN PHYSICAL_ADDRESS EntryPoint
,
376 IN UINT16 ImageSubsystem
,
377 IN EFI_FV_FILETYPE FileType
381 MEMORY_PROFILE_DRIVER_INFO
*DriverInfo
;
382 MEMORY_PROFILE_DRIVER_INFO_DATA
*DriverInfoData
;
383 VOID
*EntryPointInImage
;
386 UINTN PdbOccupiedSize
;
391 if (ImageBase
!= 0) {
392 PdbString
= PeCoffLoaderGetPdbPointer ((VOID
*) (UINTN
) ImageBase
);
393 if (PdbString
!= NULL
) {
394 PdbSize
= AsciiStrSize (PdbString
);
395 PdbOccupiedSize
= GET_OCCUPIED_SIZE (PdbSize
, sizeof (UINT64
));
400 // Use CoreInternalAllocatePool() that will not update profile for this AllocatePool action.
402 Status
= CoreInternalAllocatePool (
404 sizeof (*DriverInfoData
) + sizeof (LIST_ENTRY
) + PdbSize
,
405 (VOID
**) &DriverInfoData
407 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
));
422 DriverInfo
->ImageBase
= ImageBase
;
423 DriverInfo
->ImageSize
= ImageSize
;
424 DriverInfo
->EntryPoint
= EntryPoint
;
425 DriverInfo
->ImageSubsystem
= ImageSubsystem
;
426 if ((EntryPoint
!= 0) && ((EntryPoint
< ImageBase
) || (EntryPoint
>= (ImageBase
+ ImageSize
)))) {
428 // If the EntryPoint is not in the range of image buffer, it should come from emulation environment.
429 // So patch ImageBuffer here to align the EntryPoint.
431 Status
= InternalPeCoffGetEntryPoint ((VOID
*) (UINTN
) ImageBase
, &EntryPointInImage
);
432 ASSERT_EFI_ERROR (Status
);
433 DriverInfo
->ImageBase
= ImageBase
+ EntryPoint
- (PHYSICAL_ADDRESS
) (UINTN
) EntryPointInImage
;
435 DriverInfo
->FileType
= FileType
;
436 DriverInfoData
->AllocInfoList
= (LIST_ENTRY
*) (DriverInfoData
+ 1);
437 InitializeListHead (DriverInfoData
->AllocInfoList
);
438 DriverInfo
->CurrentUsage
= 0;
439 DriverInfo
->PeakUsage
= 0;
440 DriverInfo
->AllocRecordCount
= 0;
442 DriverInfo
->PdbStringOffset
= (UINT16
) sizeof (MEMORY_PROFILE_DRIVER_INFO
);
443 DriverInfoData
->PdbString
= (CHAR8
*) (DriverInfoData
->AllocInfoList
+ 1);
444 CopyMem (DriverInfoData
->PdbString
, PdbString
, PdbSize
);
446 DriverInfo
->PdbStringOffset
= 0;
447 DriverInfoData
->PdbString
= NULL
;
450 InsertTailList (ContextData
->DriverInfoList
, &DriverInfoData
->Link
);
451 ContextData
->Context
.ImageCount
++;
452 ContextData
->Context
.TotalImageSize
+= DriverInfo
->ImageSize
;
454 return DriverInfoData
;
458 Return if record for this driver is needed..
460 @param DriverFilePath Driver file path.
462 @retval TRUE Record for this driver is needed.
463 @retval FALSE Record for this driver is not needed.
467 NeedRecordThisDriver (
468 IN EFI_DEVICE_PATH_PROTOCOL
*DriverFilePath
471 EFI_DEVICE_PATH_PROTOCOL
*TmpDevicePath
;
472 EFI_DEVICE_PATH_PROTOCOL
*DevicePathInstance
;
473 UINTN DevicePathSize
;
476 if (!IsDevicePathValid (mMemoryProfileDriverPath
, mMemoryProfileDriverPathSize
)) {
478 // Invalid Device Path means record all.
484 // Record FilePath without END node.
486 FilePathSize
= GetDevicePathSize (DriverFilePath
) - sizeof(EFI_DEVICE_PATH_PROTOCOL
);
488 DevicePathInstance
= mMemoryProfileDriverPath
;
491 // Find END node (it might be END_ENTIRE or END_INSTANCE).
493 TmpDevicePath
= DevicePathInstance
;
494 while (!IsDevicePathEndType (TmpDevicePath
)) {
495 TmpDevicePath
= NextDevicePathNode (TmpDevicePath
);
499 // Do not compare END node.
501 DevicePathSize
= (UINTN
)TmpDevicePath
- (UINTN
)DevicePathInstance
;
502 if ((FilePathSize
== DevicePathSize
) &&
503 (CompareMem (DriverFilePath
, DevicePathInstance
, DevicePathSize
) == 0)) {
508 // Get next instance.
510 DevicePathInstance
= (EFI_DEVICE_PATH_PROTOCOL
*)((UINTN
)DevicePathInstance
+ DevicePathSize
+ DevicePathNodeLength(TmpDevicePath
));
511 } while (DevicePathSubType (TmpDevicePath
) != END_ENTIRE_DEVICE_PATH_SUBTYPE
);
517 Register DXE Core to memory profile.
519 @param HobStart The start address of the HOB.
520 @param ContextData Memory profile context.
522 @retval TRUE Register success.
523 @retval FALSE Register fail.
529 IN MEMORY_PROFILE_CONTEXT_DATA
*ContextData
532 EFI_PEI_HOB_POINTERS DxeCoreHob
;
533 MEMORY_PROFILE_DRIVER_INFO_DATA
*DriverInfoData
;
534 PHYSICAL_ADDRESS ImageBase
;
535 UINT8 TempBuffer
[sizeof(MEDIA_FW_VOL_FILEPATH_DEVICE_PATH
) + sizeof(EFI_DEVICE_PATH_PROTOCOL
)];
536 MEDIA_FW_VOL_FILEPATH_DEVICE_PATH
*FilePath
;
538 ASSERT (ContextData
!= NULL
);
541 // Searching for image hob
543 DxeCoreHob
.Raw
= HobStart
;
544 while ((DxeCoreHob
.Raw
= GetNextHob (EFI_HOB_TYPE_MEMORY_ALLOCATION
, DxeCoreHob
.Raw
)) != NULL
) {
545 if (CompareGuid (&DxeCoreHob
.MemoryAllocationModule
->MemoryAllocationHeader
.Name
, &gEfiHobMemoryAllocModuleGuid
)) {
551 DxeCoreHob
.Raw
= GET_NEXT_HOB (DxeCoreHob
);
553 ASSERT (DxeCoreHob
.Raw
!= NULL
);
555 FilePath
= (MEDIA_FW_VOL_FILEPATH_DEVICE_PATH
*) TempBuffer
;
556 EfiInitializeFwVolDevicepathNode (FilePath
, &DxeCoreHob
.MemoryAllocationModule
->ModuleName
);
557 SetDevicePathEndNode (FilePath
+ 1);
559 if (!NeedRecordThisDriver ((EFI_DEVICE_PATH_PROTOCOL
*) FilePath
)) {
563 ImageBase
= DxeCoreHob
.MemoryAllocationModule
->MemoryAllocationHeader
.MemoryBaseAddress
;
564 DriverInfoData
= BuildDriverInfo (
566 &DxeCoreHob
.MemoryAllocationModule
->ModuleName
,
568 DxeCoreHob
.MemoryAllocationModule
->MemoryAllocationHeader
.MemoryLength
,
569 DxeCoreHob
.MemoryAllocationModule
->EntryPoint
,
570 InternalPeCoffGetSubsystem ((VOID
*) (UINTN
) ImageBase
),
571 EFI_FV_FILETYPE_DXE_CORE
573 if (DriverInfoData
== NULL
) {
581 Initialize memory profile.
583 @param HobStart The start address of the HOB.
591 MEMORY_PROFILE_CONTEXT_DATA
*ContextData
;
593 if (!IS_UEFI_MEMORY_PROFILE_ENABLED
) {
597 ContextData
= GetMemoryProfileContext ();
598 if (ContextData
!= NULL
) {
602 mMemoryProfileGettingStatus
= FALSE
;
603 if ((PcdGet8 (PcdMemoryProfilePropertyMask
) & BIT7
) != 0) {
604 mMemoryProfileRecordingEnable
= MEMORY_PROFILE_RECORDING_DISABLE
;
606 mMemoryProfileRecordingEnable
= MEMORY_PROFILE_RECORDING_ENABLE
;
608 mMemoryProfileDriverPathSize
= PcdGetSize (PcdMemoryProfileDriverPath
);
609 mMemoryProfileDriverPath
= AllocateCopyPool (mMemoryProfileDriverPathSize
, PcdGetPtr (PcdMemoryProfileDriverPath
));
610 mMemoryProfileContextPtr
= &mMemoryProfileContext
;
612 RegisterDxeCore (HobStart
, &mMemoryProfileContext
);
614 DEBUG ((DEBUG_INFO
, "MemoryProfileInit MemoryProfileContext - 0x%x\n", &mMemoryProfileContext
));
618 Install memory profile protocol.
622 MemoryProfileInstallProtocol (
629 if (!IS_UEFI_MEMORY_PROFILE_ENABLED
) {
634 Status
= CoreInstallMultipleProtocolInterfaces (
636 &gEdkiiMemoryProfileGuid
,
640 ASSERT_EFI_ERROR (Status
);
644 Get the GUID file name from the file path.
646 @param FilePath File path.
648 @return The GUID file name from the file path.
652 GetFileNameFromFilePath (
653 IN EFI_DEVICE_PATH_PROTOCOL
*FilePath
656 MEDIA_FW_VOL_FILEPATH_DEVICE_PATH
*ThisFilePath
;
660 if (FilePath
!= NULL
) {
661 ThisFilePath
= (MEDIA_FW_VOL_FILEPATH_DEVICE_PATH
*) FilePath
;
662 while (!IsDevicePathEnd (ThisFilePath
)) {
663 FileName
= EfiGetNameGuidFromFwVolDevicePathNode (ThisFilePath
);
664 if (FileName
!= NULL
) {
667 ThisFilePath
= (MEDIA_FW_VOL_FILEPATH_DEVICE_PATH
*) NextDevicePathNode (ThisFilePath
);
675 Register image to memory profile.
677 @param DriverEntry Image info.
678 @param FileType Image file type.
680 @return EFI_SUCCESS Register successfully.
681 @return EFI_UNSUPPORTED Memory profile is unsupported,
682 or memory profile for the image is not required.
683 @return EFI_OUT_OF_RESOURCES No enough resource for this register.
687 RegisterMemoryProfileImage (
688 IN LOADED_IMAGE_PRIVATE_DATA
*DriverEntry
,
689 IN EFI_FV_FILETYPE FileType
692 MEMORY_PROFILE_CONTEXT_DATA
*ContextData
;
693 MEMORY_PROFILE_DRIVER_INFO_DATA
*DriverInfoData
;
695 if (!IS_UEFI_MEMORY_PROFILE_ENABLED
) {
696 return EFI_UNSUPPORTED
;
699 if (!NeedRecordThisDriver (DriverEntry
->Info
.FilePath
)) {
700 return EFI_UNSUPPORTED
;
703 ContextData
= GetMemoryProfileContext ();
704 if (ContextData
== NULL
) {
705 return EFI_UNSUPPORTED
;
708 DriverInfoData
= BuildDriverInfo (
710 GetFileNameFromFilePath (DriverEntry
->Info
.FilePath
),
711 DriverEntry
->ImageContext
.ImageAddress
,
712 DriverEntry
->ImageContext
.ImageSize
,
713 DriverEntry
->ImageContext
.EntryPoint
,
714 DriverEntry
->ImageContext
.ImageType
,
717 if (DriverInfoData
== NULL
) {
718 return EFI_OUT_OF_RESOURCES
;
725 Search image from memory profile.
727 @param ContextData Memory profile context.
728 @param FileName Image file name.
729 @param Address Image Address.
731 @return Pointer to memory profile driver info.
734 MEMORY_PROFILE_DRIVER_INFO_DATA
*
735 GetMemoryProfileDriverInfoByFileNameAndAddress (
736 IN MEMORY_PROFILE_CONTEXT_DATA
*ContextData
,
737 IN EFI_GUID
*FileName
,
738 IN PHYSICAL_ADDRESS Address
741 MEMORY_PROFILE_DRIVER_INFO
*DriverInfo
;
742 MEMORY_PROFILE_DRIVER_INFO_DATA
*DriverInfoData
;
743 LIST_ENTRY
*DriverLink
;
744 LIST_ENTRY
*DriverInfoList
;
746 DriverInfoList
= ContextData
->DriverInfoList
;
748 for (DriverLink
= DriverInfoList
->ForwardLink
;
749 DriverLink
!= DriverInfoList
;
750 DriverLink
= DriverLink
->ForwardLink
) {
751 DriverInfoData
= CR (
753 MEMORY_PROFILE_DRIVER_INFO_DATA
,
755 MEMORY_PROFILE_DRIVER_INFO_SIGNATURE
757 DriverInfo
= &DriverInfoData
->DriverInfo
;
758 if ((CompareGuid (&DriverInfo
->FileName
, FileName
)) &&
759 (Address
>= DriverInfo
->ImageBase
) &&
760 (Address
< (DriverInfo
->ImageBase
+ DriverInfo
->ImageSize
))) {
761 return DriverInfoData
;
769 Search image from memory profile.
770 It will return image, if (Address >= ImageBuffer) AND (Address < ImageBuffer + ImageSize).
772 @param ContextData Memory profile context.
773 @param Address Image or Function address.
775 @return Pointer to memory profile driver info.
778 MEMORY_PROFILE_DRIVER_INFO_DATA
*
779 GetMemoryProfileDriverInfoFromAddress (
780 IN MEMORY_PROFILE_CONTEXT_DATA
*ContextData
,
781 IN PHYSICAL_ADDRESS Address
784 MEMORY_PROFILE_DRIVER_INFO
*DriverInfo
;
785 MEMORY_PROFILE_DRIVER_INFO_DATA
*DriverInfoData
;
786 LIST_ENTRY
*DriverLink
;
787 LIST_ENTRY
*DriverInfoList
;
789 DriverInfoList
= ContextData
->DriverInfoList
;
791 for (DriverLink
= DriverInfoList
->ForwardLink
;
792 DriverLink
!= DriverInfoList
;
793 DriverLink
= DriverLink
->ForwardLink
) {
794 DriverInfoData
= CR (
796 MEMORY_PROFILE_DRIVER_INFO_DATA
,
798 MEMORY_PROFILE_DRIVER_INFO_SIGNATURE
800 DriverInfo
= &DriverInfoData
->DriverInfo
;
801 if ((Address
>= DriverInfo
->ImageBase
) &&
802 (Address
< (DriverInfo
->ImageBase
+ DriverInfo
->ImageSize
))) {
803 return DriverInfoData
;
811 Unregister image from memory profile.
813 @param DriverEntry Image info.
815 @return EFI_SUCCESS Unregister successfully.
816 @return EFI_UNSUPPORTED Memory profile is unsupported,
817 or memory profile for the image is not required.
818 @return EFI_NOT_FOUND The image is not found.
822 UnregisterMemoryProfileImage (
823 IN LOADED_IMAGE_PRIVATE_DATA
*DriverEntry
827 MEMORY_PROFILE_CONTEXT_DATA
*ContextData
;
828 MEMORY_PROFILE_DRIVER_INFO_DATA
*DriverInfoData
;
830 PHYSICAL_ADDRESS ImageAddress
;
831 VOID
*EntryPointInImage
;
833 if (!IS_UEFI_MEMORY_PROFILE_ENABLED
) {
834 return EFI_UNSUPPORTED
;
837 if (!NeedRecordThisDriver (DriverEntry
->Info
.FilePath
)) {
838 return EFI_UNSUPPORTED
;
841 ContextData
= GetMemoryProfileContext ();
842 if (ContextData
== NULL
) {
843 return EFI_UNSUPPORTED
;
846 DriverInfoData
= NULL
;
847 FileName
= GetFileNameFromFilePath (DriverEntry
->Info
.FilePath
);
848 ImageAddress
= DriverEntry
->ImageContext
.ImageAddress
;
849 if ((DriverEntry
->ImageContext
.EntryPoint
< ImageAddress
) || (DriverEntry
->ImageContext
.EntryPoint
>= (ImageAddress
+ DriverEntry
->ImageContext
.ImageSize
))) {
851 // If the EntryPoint is not in the range of image buffer, it should come from emulation environment.
852 // So patch ImageAddress here to align the EntryPoint.
854 Status
= InternalPeCoffGetEntryPoint ((VOID
*) (UINTN
) ImageAddress
, &EntryPointInImage
);
855 ASSERT_EFI_ERROR (Status
);
856 ImageAddress
= ImageAddress
+ (UINTN
) DriverEntry
->ImageContext
.EntryPoint
- (UINTN
) EntryPointInImage
;
858 if (FileName
!= NULL
) {
859 DriverInfoData
= GetMemoryProfileDriverInfoByFileNameAndAddress (ContextData
, FileName
, ImageAddress
);
861 if (DriverInfoData
== NULL
) {
862 DriverInfoData
= GetMemoryProfileDriverInfoFromAddress (ContextData
, ImageAddress
);
864 if (DriverInfoData
== NULL
) {
865 return EFI_NOT_FOUND
;
868 ContextData
->Context
.TotalImageSize
-= DriverInfoData
->DriverInfo
.ImageSize
;
870 // Keep the ImageBase for RVA calculation in Application.
871 //DriverInfoData->DriverInfo.ImageBase = 0;
872 DriverInfoData
->DriverInfo
.ImageSize
= 0;
874 if (DriverInfoData
->DriverInfo
.PeakUsage
== 0) {
875 ContextData
->Context
.ImageCount
--;
876 RemoveEntryList (&DriverInfoData
->Link
);
878 // Use CoreInternalFreePool() that will not update profile for this FreePool action.
880 CoreInternalFreePool (DriverInfoData
, NULL
);
887 Return if this memory type needs to be recorded into memory profile.
888 If BIOS memory type (0 ~ EfiMaxMemoryType - 1), it checks bit (1 << MemoryType).
889 If OS memory type (0x80000000 ~ 0xFFFFFFFF), it checks bit63 - 0x8000000000000000.
890 If OEM memory type (0x70000000 ~ 0x7FFFFFFF), it checks bit62 - 0x4000000000000000.
892 @param MemoryType Memory type.
894 @retval TRUE This memory type need to be recorded.
895 @retval FALSE This memory type need not to be recorded.
899 CoreNeedRecordProfile (
900 IN EFI_MEMORY_TYPE MemoryType
905 if ((UINT32
) MemoryType
>= MEMORY_TYPE_OS_RESERVED_MIN
) {
907 } else if ((UINT32
) MemoryType
>= MEMORY_TYPE_OEM_RESERVED_MIN
) {
910 TestBit
= LShiftU64 (1, MemoryType
);
913 if ((PcdGet64 (PcdMemoryProfileMemoryType
) & TestBit
) != 0) {
921 Convert EFI memory type to profile memory index. The rule is:
922 If BIOS memory type (0 ~ EfiMaxMemoryType - 1), ProfileMemoryIndex = MemoryType.
923 If OS memory type (0x80000000 ~ 0xFFFFFFFF), ProfileMemoryIndex = EfiMaxMemoryType.
924 If OEM memory type (0x70000000 ~ 0x7FFFFFFF), ProfileMemoryIndex = EfiMaxMemoryType + 1.
926 @param MemoryType Memory type.
928 @return Profile memory index.
932 GetProfileMemoryIndex (
933 IN EFI_MEMORY_TYPE MemoryType
936 if ((UINT32
) MemoryType
>= MEMORY_TYPE_OS_RESERVED_MIN
) {
937 return EfiMaxMemoryType
;
938 } else if ((UINT32
) MemoryType
>= MEMORY_TYPE_OEM_RESERVED_MIN
) {
939 return EfiMaxMemoryType
+ 1;
946 Update memory profile Allocate information.
948 @param CallerAddress Address of caller who call Allocate.
949 @param Action This Allocate action.
950 @param MemoryType Memory type.
951 @param Size Buffer size.
952 @param Buffer Buffer address.
953 @param ActionString String for memory profile action.
955 @return EFI_SUCCESS Memory profile is updated.
956 @return EFI_UNSUPPORTED Memory profile is unsupported,
957 or memory profile for the image is not required.
958 @return EFI_OUT_OF_RESOURCES No enough resource to update memory profile for allocate action.
962 CoreUpdateProfileAllocate (
963 IN PHYSICAL_ADDRESS CallerAddress
,
964 IN MEMORY_PROFILE_ACTION Action
,
965 IN EFI_MEMORY_TYPE MemoryType
,
968 IN CHAR8
*ActionString OPTIONAL
972 MEMORY_PROFILE_CONTEXT
*Context
;
973 MEMORY_PROFILE_DRIVER_INFO
*DriverInfo
;
974 MEMORY_PROFILE_ALLOC_INFO
*AllocInfo
;
975 MEMORY_PROFILE_CONTEXT_DATA
*ContextData
;
976 MEMORY_PROFILE_DRIVER_INFO_DATA
*DriverInfoData
;
977 MEMORY_PROFILE_ALLOC_INFO_DATA
*AllocInfoData
;
978 UINTN ProfileMemoryIndex
;
979 MEMORY_PROFILE_ACTION BasicAction
;
980 UINTN ActionStringSize
;
981 UINTN ActionStringOccupiedSize
;
983 BasicAction
= Action
& MEMORY_PROFILE_ACTION_BASIC_MASK
;
985 ContextData
= GetMemoryProfileContext ();
986 if (ContextData
== NULL
) {
987 return EFI_UNSUPPORTED
;
990 DriverInfoData
= GetMemoryProfileDriverInfoFromAddress (ContextData
, CallerAddress
);
991 if (DriverInfoData
== NULL
) {
992 return EFI_UNSUPPORTED
;
995 ActionStringSize
= 0;
996 ActionStringOccupiedSize
= 0;
997 if (ActionString
!= NULL
) {
998 ActionStringSize
= AsciiStrSize (ActionString
);
999 ActionStringOccupiedSize
= GET_OCCUPIED_SIZE (ActionStringSize
, sizeof (UINT64
));
1003 // Use CoreInternalAllocatePool() that will not update profile for this AllocatePool action.
1005 AllocInfoData
= NULL
;
1006 Status
= CoreInternalAllocatePool (
1007 EfiBootServicesData
,
1008 sizeof (*AllocInfoData
) + ActionStringSize
,
1009 (VOID
**) &AllocInfoData
1011 if (EFI_ERROR (Status
)) {
1012 return EFI_OUT_OF_RESOURCES
;
1014 ASSERT (AllocInfoData
!= NULL
);
1017 // Only update SequenceCount if and only if it is basic action.
1019 if (Action
== BasicAction
) {
1020 ContextData
->Context
.SequenceCount
++;
1023 AllocInfo
= &AllocInfoData
->AllocInfo
;
1024 AllocInfoData
->Signature
= MEMORY_PROFILE_ALLOC_INFO_SIGNATURE
;
1025 AllocInfo
->Header
.Signature
= MEMORY_PROFILE_ALLOC_INFO_SIGNATURE
;
1026 AllocInfo
->Header
.Length
= (UINT16
) (sizeof (MEMORY_PROFILE_ALLOC_INFO
) + ActionStringOccupiedSize
);
1027 AllocInfo
->Header
.Revision
= MEMORY_PROFILE_ALLOC_INFO_REVISION
;
1028 AllocInfo
->CallerAddress
= CallerAddress
;
1029 AllocInfo
->SequenceId
= ContextData
->Context
.SequenceCount
;
1030 AllocInfo
->Action
= Action
;
1031 AllocInfo
->MemoryType
= MemoryType
;
1032 AllocInfo
->Buffer
= (PHYSICAL_ADDRESS
) (UINTN
) Buffer
;
1033 AllocInfo
->Size
= Size
;
1034 if (ActionString
!= NULL
) {
1035 AllocInfo
->ActionStringOffset
= (UINT16
) sizeof (MEMORY_PROFILE_ALLOC_INFO
);
1036 AllocInfoData
->ActionString
= (CHAR8
*) (AllocInfoData
+ 1);
1037 CopyMem (AllocInfoData
->ActionString
, ActionString
, ActionStringSize
);
1039 AllocInfo
->ActionStringOffset
= 0;
1040 AllocInfoData
->ActionString
= NULL
;
1043 InsertTailList (DriverInfoData
->AllocInfoList
, &AllocInfoData
->Link
);
1045 Context
= &ContextData
->Context
;
1046 DriverInfo
= &DriverInfoData
->DriverInfo
;
1047 DriverInfo
->AllocRecordCount
++;
1050 // Update summary if and only if it is basic action.
1052 if (Action
== BasicAction
) {
1053 ProfileMemoryIndex
= GetProfileMemoryIndex (MemoryType
);
1055 DriverInfo
->CurrentUsage
+= Size
;
1056 if (DriverInfo
->PeakUsage
< DriverInfo
->CurrentUsage
) {
1057 DriverInfo
->PeakUsage
= DriverInfo
->CurrentUsage
;
1059 DriverInfo
->CurrentUsageByType
[ProfileMemoryIndex
] += Size
;
1060 if (DriverInfo
->PeakUsageByType
[ProfileMemoryIndex
] < DriverInfo
->CurrentUsageByType
[ProfileMemoryIndex
]) {
1061 DriverInfo
->PeakUsageByType
[ProfileMemoryIndex
] = DriverInfo
->CurrentUsageByType
[ProfileMemoryIndex
];
1064 Context
->CurrentTotalUsage
+= Size
;
1065 if (Context
->PeakTotalUsage
< Context
->CurrentTotalUsage
) {
1066 Context
->PeakTotalUsage
= Context
->CurrentTotalUsage
;
1068 Context
->CurrentTotalUsageByType
[ProfileMemoryIndex
] += Size
;
1069 if (Context
->PeakTotalUsageByType
[ProfileMemoryIndex
] < Context
->CurrentTotalUsageByType
[ProfileMemoryIndex
]) {
1070 Context
->PeakTotalUsageByType
[ProfileMemoryIndex
] = Context
->CurrentTotalUsageByType
[ProfileMemoryIndex
];
1078 Get memory profile alloc info from memory profile.
1080 @param DriverInfoData Driver info.
1081 @param BasicAction This Free basic action.
1082 @param Size Buffer size.
1083 @param Buffer Buffer address.
1085 @return Pointer to memory profile alloc info.
1088 MEMORY_PROFILE_ALLOC_INFO_DATA
*
1089 GetMemoryProfileAllocInfoFromAddress (
1090 IN MEMORY_PROFILE_DRIVER_INFO_DATA
*DriverInfoData
,
1091 IN MEMORY_PROFILE_ACTION BasicAction
,
1096 LIST_ENTRY
*AllocInfoList
;
1097 LIST_ENTRY
*AllocLink
;
1098 MEMORY_PROFILE_ALLOC_INFO
*AllocInfo
;
1099 MEMORY_PROFILE_ALLOC_INFO_DATA
*AllocInfoData
;
1101 AllocInfoList
= DriverInfoData
->AllocInfoList
;
1103 for (AllocLink
= AllocInfoList
->ForwardLink
;
1104 AllocLink
!= AllocInfoList
;
1105 AllocLink
= AllocLink
->ForwardLink
) {
1106 AllocInfoData
= CR (
1108 MEMORY_PROFILE_ALLOC_INFO_DATA
,
1110 MEMORY_PROFILE_ALLOC_INFO_SIGNATURE
1112 AllocInfo
= &AllocInfoData
->AllocInfo
;
1113 if ((AllocInfo
->Action
& MEMORY_PROFILE_ACTION_BASIC_MASK
) != BasicAction
) {
1116 switch (BasicAction
) {
1117 case MemoryProfileActionAllocatePages
:
1118 if ((AllocInfo
->Buffer
<= (PHYSICAL_ADDRESS
) (UINTN
) Buffer
) &&
1119 ((AllocInfo
->Buffer
+ AllocInfo
->Size
) >= ((PHYSICAL_ADDRESS
) (UINTN
) Buffer
+ Size
))) {
1120 return AllocInfoData
;
1123 case MemoryProfileActionAllocatePool
:
1124 if (AllocInfo
->Buffer
== (PHYSICAL_ADDRESS
) (UINTN
) Buffer
) {
1125 return AllocInfoData
;
1138 Update memory profile Free information.
1140 @param CallerAddress Address of caller who call Free.
1141 @param Action This Free action.
1142 @param Size Buffer size.
1143 @param Buffer Buffer address.
1145 @return EFI_SUCCESS Memory profile is updated.
1146 @return EFI_UNSUPPORTED Memory profile is unsupported.
1147 @return EFI_NOT_FOUND No matched allocate info found for free action.
1151 CoreUpdateProfileFree (
1152 IN PHYSICAL_ADDRESS CallerAddress
,
1153 IN MEMORY_PROFILE_ACTION Action
,
1158 MEMORY_PROFILE_CONTEXT
*Context
;
1159 MEMORY_PROFILE_DRIVER_INFO
*DriverInfo
;
1160 MEMORY_PROFILE_ALLOC_INFO
*AllocInfo
;
1161 MEMORY_PROFILE_CONTEXT_DATA
*ContextData
;
1162 MEMORY_PROFILE_DRIVER_INFO_DATA
*DriverInfoData
;
1163 LIST_ENTRY
*DriverLink
;
1164 LIST_ENTRY
*DriverInfoList
;
1165 MEMORY_PROFILE_DRIVER_INFO_DATA
*ThisDriverInfoData
;
1166 MEMORY_PROFILE_ALLOC_INFO_DATA
*AllocInfoData
;
1167 UINTN ProfileMemoryIndex
;
1168 MEMORY_PROFILE_ACTION BasicAction
;
1171 BasicAction
= Action
& MEMORY_PROFILE_ACTION_BASIC_MASK
;
1173 ContextData
= GetMemoryProfileContext ();
1174 if (ContextData
== NULL
) {
1175 return EFI_UNSUPPORTED
;
1178 DriverInfoData
= GetMemoryProfileDriverInfoFromAddress (ContextData
, CallerAddress
);
1181 // Do not return if DriverInfoData == NULL here,
1182 // because driver A might free memory allocated by driver B.
1186 // Need use do-while loop to find all possible records,
1187 // because one address might be recorded multiple times.
1190 AllocInfoData
= NULL
;
1192 if (DriverInfoData
!= NULL
) {
1193 switch (BasicAction
) {
1194 case MemoryProfileActionFreePages
:
1195 AllocInfoData
= GetMemoryProfileAllocInfoFromAddress (DriverInfoData
, MemoryProfileActionAllocatePages
, Size
, Buffer
);
1197 case MemoryProfileActionFreePool
:
1198 AllocInfoData
= GetMemoryProfileAllocInfoFromAddress (DriverInfoData
, MemoryProfileActionAllocatePool
, 0, Buffer
);
1202 AllocInfoData
= NULL
;
1206 if (AllocInfoData
== NULL
) {
1208 // Legal case, because driver A might free memory allocated by driver B, by some protocol.
1210 DriverInfoList
= ContextData
->DriverInfoList
;
1212 for (DriverLink
= DriverInfoList
->ForwardLink
;
1213 DriverLink
!= DriverInfoList
;
1214 DriverLink
= DriverLink
->ForwardLink
) {
1215 ThisDriverInfoData
= CR (
1217 MEMORY_PROFILE_DRIVER_INFO_DATA
,
1219 MEMORY_PROFILE_DRIVER_INFO_SIGNATURE
1221 switch (BasicAction
) {
1222 case MemoryProfileActionFreePages
:
1223 AllocInfoData
= GetMemoryProfileAllocInfoFromAddress (ThisDriverInfoData
, MemoryProfileActionAllocatePages
, Size
, Buffer
);
1225 case MemoryProfileActionFreePool
:
1226 AllocInfoData
= GetMemoryProfileAllocInfoFromAddress (ThisDriverInfoData
, MemoryProfileActionAllocatePool
, 0, Buffer
);
1230 AllocInfoData
= NULL
;
1233 if (AllocInfoData
!= NULL
) {
1234 DriverInfoData
= ThisDriverInfoData
;
1239 if (AllocInfoData
== NULL
) {
1241 // If (!Found), no matched allocate info is found for this free action.
1242 // It is because the specified memory type allocate actions have been filtered by
1243 // CoreNeedRecordProfile(), but free actions may have no memory type information,
1244 // they can not be filtered by CoreNeedRecordProfile(). Then, they will be
1247 // If (Found), it is normal exit path.
1248 return (Found
? EFI_SUCCESS
: EFI_NOT_FOUND
);
1252 ASSERT (DriverInfoData
!= NULL
);
1253 ASSERT (AllocInfoData
!= NULL
);
1257 Context
= &ContextData
->Context
;
1258 DriverInfo
= &DriverInfoData
->DriverInfo
;
1259 AllocInfo
= &AllocInfoData
->AllocInfo
;
1261 DriverInfo
->AllocRecordCount
--;
1263 // Update summary if and only if it is basic action.
1265 if (AllocInfo
->Action
== (AllocInfo
->Action
& MEMORY_PROFILE_ACTION_BASIC_MASK
)) {
1266 ProfileMemoryIndex
= GetProfileMemoryIndex (AllocInfo
->MemoryType
);
1268 Context
->CurrentTotalUsage
-= AllocInfo
->Size
;
1269 Context
->CurrentTotalUsageByType
[ProfileMemoryIndex
] -= AllocInfo
->Size
;
1271 DriverInfo
->CurrentUsage
-= AllocInfo
->Size
;
1272 DriverInfo
->CurrentUsageByType
[ProfileMemoryIndex
] -= AllocInfo
->Size
;
1275 RemoveEntryList (&AllocInfoData
->Link
);
1277 if (BasicAction
== MemoryProfileActionFreePages
) {
1278 if (AllocInfo
->Buffer
!= (PHYSICAL_ADDRESS
) (UINTN
) Buffer
) {
1279 CoreUpdateProfileAllocate (
1280 AllocInfo
->CallerAddress
,
1282 AllocInfo
->MemoryType
,
1283 (UINTN
) ((PHYSICAL_ADDRESS
) (UINTN
) Buffer
- AllocInfo
->Buffer
),
1284 (VOID
*) (UINTN
) AllocInfo
->Buffer
,
1285 AllocInfoData
->ActionString
1288 if (AllocInfo
->Buffer
+ AllocInfo
->Size
!= ((PHYSICAL_ADDRESS
) (UINTN
) Buffer
+ Size
)) {
1289 CoreUpdateProfileAllocate (
1290 AllocInfo
->CallerAddress
,
1292 AllocInfo
->MemoryType
,
1293 (UINTN
) ((AllocInfo
->Buffer
+ AllocInfo
->Size
) - ((PHYSICAL_ADDRESS
) (UINTN
) Buffer
+ Size
)),
1294 (VOID
*) ((UINTN
) Buffer
+ Size
),
1295 AllocInfoData
->ActionString
1301 // Use CoreInternalFreePool() that will not update profile for this FreePool action.
1303 CoreInternalFreePool (AllocInfoData
, NULL
);
1308 Update memory profile information.
1310 @param CallerAddress Address of caller who call Allocate or Free.
1311 @param Action This Allocate or Free action.
1312 @param MemoryType Memory type.
1313 EfiMaxMemoryType means the MemoryType is unknown.
1314 @param Size Buffer size.
1315 @param Buffer Buffer address.
1316 @param ActionString String for memory profile action.
1317 Only needed for user defined allocate action.
1319 @return EFI_SUCCESS Memory profile is updated.
1320 @return EFI_UNSUPPORTED Memory profile is unsupported,
1321 or memory profile for the image is not required,
1322 or memory profile for the memory type is not required.
1323 @return EFI_ACCESS_DENIED It is during memory profile data getting.
1324 @return EFI_ABORTED Memory profile recording is not enabled.
1325 @return EFI_OUT_OF_RESOURCES No enough resource to update memory profile for allocate action.
1326 @return EFI_NOT_FOUND No matched allocate info found for free action.
1332 IN PHYSICAL_ADDRESS CallerAddress
,
1333 IN MEMORY_PROFILE_ACTION Action
,
1334 IN EFI_MEMORY_TYPE MemoryType
,
1335 IN UINTN Size
, // Valid for AllocatePages/FreePages/AllocatePool
1337 IN CHAR8
*ActionString OPTIONAL
1341 MEMORY_PROFILE_CONTEXT_DATA
*ContextData
;
1342 MEMORY_PROFILE_ACTION BasicAction
;
1344 if (!IS_UEFI_MEMORY_PROFILE_ENABLED
) {
1345 return EFI_UNSUPPORTED
;
1348 if (mMemoryProfileGettingStatus
) {
1349 return EFI_ACCESS_DENIED
;
1352 if (!mMemoryProfileRecordingEnable
) {
1357 // Get the basic action to know how to process the record
1359 BasicAction
= Action
& MEMORY_PROFILE_ACTION_BASIC_MASK
;
1362 // EfiMaxMemoryType means the MemoryType is unknown.
1364 if (MemoryType
!= EfiMaxMemoryType
) {
1366 // Only record limited MemoryType.
1368 if (!CoreNeedRecordProfile (MemoryType
)) {
1369 return EFI_UNSUPPORTED
;
1373 ContextData
= GetMemoryProfileContext ();
1374 if (ContextData
== NULL
) {
1375 return EFI_UNSUPPORTED
;
1378 CoreAcquireMemoryProfileLock ();
1379 switch (BasicAction
) {
1380 case MemoryProfileActionAllocatePages
:
1381 Status
= CoreUpdateProfileAllocate (CallerAddress
, Action
, MemoryType
, Size
, Buffer
, ActionString
);
1383 case MemoryProfileActionFreePages
:
1384 Status
= CoreUpdateProfileFree (CallerAddress
, Action
, Size
, Buffer
);
1386 case MemoryProfileActionAllocatePool
:
1387 Status
= CoreUpdateProfileAllocate (CallerAddress
, Action
, MemoryType
, Size
, Buffer
, ActionString
);
1389 case MemoryProfileActionFreePool
:
1390 Status
= CoreUpdateProfileFree (CallerAddress
, Action
, 0, Buffer
);
1394 Status
= EFI_UNSUPPORTED
;
1397 CoreReleaseMemoryProfileLock ();
1402 ////////////////////
1405 Get memory profile data size.
1407 @return Memory profile data size.
1411 MemoryProfileGetDataSize (
1415 MEMORY_PROFILE_CONTEXT_DATA
*ContextData
;
1416 MEMORY_PROFILE_DRIVER_INFO_DATA
*DriverInfoData
;
1417 MEMORY_PROFILE_ALLOC_INFO_DATA
*AllocInfoData
;
1418 LIST_ENTRY
*DriverInfoList
;
1419 LIST_ENTRY
*DriverLink
;
1420 LIST_ENTRY
*AllocInfoList
;
1421 LIST_ENTRY
*AllocLink
;
1425 ContextData
= GetMemoryProfileContext ();
1426 if (ContextData
== NULL
) {
1430 TotalSize
= sizeof (MEMORY_PROFILE_CONTEXT
);
1432 DriverInfoList
= ContextData
->DriverInfoList
;
1433 for (DriverLink
= DriverInfoList
->ForwardLink
;
1434 DriverLink
!= DriverInfoList
;
1435 DriverLink
= DriverLink
->ForwardLink
) {
1436 DriverInfoData
= CR (
1438 MEMORY_PROFILE_DRIVER_INFO_DATA
,
1440 MEMORY_PROFILE_DRIVER_INFO_SIGNATURE
1442 TotalSize
+= DriverInfoData
->DriverInfo
.Header
.Length
;
1444 AllocInfoList
= DriverInfoData
->AllocInfoList
;
1445 for (AllocLink
= AllocInfoList
->ForwardLink
;
1446 AllocLink
!= AllocInfoList
;
1447 AllocLink
= AllocLink
->ForwardLink
) {
1448 AllocInfoData
= CR (
1450 MEMORY_PROFILE_ALLOC_INFO_DATA
,
1452 MEMORY_PROFILE_ALLOC_INFO_SIGNATURE
1454 TotalSize
+= AllocInfoData
->AllocInfo
.Header
.Length
;
1462 Copy memory profile data.
1464 @param ProfileBuffer The buffer to hold memory profile data.
1468 MemoryProfileCopyData (
1469 IN VOID
*ProfileBuffer
1472 MEMORY_PROFILE_CONTEXT
*Context
;
1473 MEMORY_PROFILE_DRIVER_INFO
*DriverInfo
;
1474 MEMORY_PROFILE_ALLOC_INFO
*AllocInfo
;
1475 MEMORY_PROFILE_CONTEXT_DATA
*ContextData
;
1476 MEMORY_PROFILE_DRIVER_INFO_DATA
*DriverInfoData
;
1477 MEMORY_PROFILE_ALLOC_INFO_DATA
*AllocInfoData
;
1478 LIST_ENTRY
*DriverInfoList
;
1479 LIST_ENTRY
*DriverLink
;
1480 LIST_ENTRY
*AllocInfoList
;
1481 LIST_ENTRY
*AllocLink
;
1483 UINTN ActionStringSize
;
1485 ContextData
= GetMemoryProfileContext ();
1486 if (ContextData
== NULL
) {
1490 Context
= ProfileBuffer
;
1491 CopyMem (Context
, &ContextData
->Context
, sizeof (MEMORY_PROFILE_CONTEXT
));
1492 DriverInfo
= (MEMORY_PROFILE_DRIVER_INFO
*) (Context
+ 1);
1494 DriverInfoList
= ContextData
->DriverInfoList
;
1495 for (DriverLink
= DriverInfoList
->ForwardLink
;
1496 DriverLink
!= DriverInfoList
;
1497 DriverLink
= DriverLink
->ForwardLink
) {
1498 DriverInfoData
= CR (
1500 MEMORY_PROFILE_DRIVER_INFO_DATA
,
1502 MEMORY_PROFILE_DRIVER_INFO_SIGNATURE
1504 CopyMem (DriverInfo
, &DriverInfoData
->DriverInfo
, sizeof (MEMORY_PROFILE_DRIVER_INFO
));
1505 if (DriverInfo
->PdbStringOffset
!= 0) {
1506 PdbSize
= AsciiStrSize (DriverInfoData
->PdbString
);
1507 CopyMem ((VOID
*) ((UINTN
) DriverInfo
+ DriverInfo
->PdbStringOffset
), DriverInfoData
->PdbString
, PdbSize
);
1509 AllocInfo
= (MEMORY_PROFILE_ALLOC_INFO
*) ((UINTN
) DriverInfo
+ DriverInfo
->Header
.Length
);
1511 AllocInfoList
= DriverInfoData
->AllocInfoList
;
1512 for (AllocLink
= AllocInfoList
->ForwardLink
;
1513 AllocLink
!= AllocInfoList
;
1514 AllocLink
= AllocLink
->ForwardLink
) {
1515 AllocInfoData
= CR (
1517 MEMORY_PROFILE_ALLOC_INFO_DATA
,
1519 MEMORY_PROFILE_ALLOC_INFO_SIGNATURE
1521 CopyMem (AllocInfo
, &AllocInfoData
->AllocInfo
, sizeof (MEMORY_PROFILE_ALLOC_INFO
));
1522 if (AllocInfo
->ActionStringOffset
!= 0) {
1523 ActionStringSize
= AsciiStrSize (AllocInfoData
->ActionString
);
1524 CopyMem ((VOID
*) ((UINTN
) AllocInfo
+ AllocInfo
->ActionStringOffset
), AllocInfoData
->ActionString
, ActionStringSize
);
1526 AllocInfo
= (MEMORY_PROFILE_ALLOC_INFO
*) ((UINTN
) AllocInfo
+ AllocInfo
->Header
.Length
);
1529 DriverInfo
= (MEMORY_PROFILE_DRIVER_INFO
*) AllocInfo
;
1534 Get memory profile data.
1536 @param[in] This The EDKII_MEMORY_PROFILE_PROTOCOL instance.
1537 @param[in, out] ProfileSize On entry, points to the size in bytes of the ProfileBuffer.
1538 On return, points to the size of the data returned in ProfileBuffer.
1539 @param[out] ProfileBuffer Profile buffer.
1541 @return EFI_SUCCESS Get the memory profile data successfully.
1542 @return EFI_UNSUPPORTED Memory profile is unsupported.
1543 @return EFI_BUFFER_TO_SMALL The ProfileSize is too small for the resulting data.
1544 ProfileSize is updated with the size required.
1549 ProfileProtocolGetData (
1550 IN EDKII_MEMORY_PROFILE_PROTOCOL
*This
,
1551 IN OUT UINT64
*ProfileSize
,
1552 OUT VOID
*ProfileBuffer
1556 MEMORY_PROFILE_CONTEXT_DATA
*ContextData
;
1557 BOOLEAN MemoryProfileGettingStatus
;
1559 ContextData
= GetMemoryProfileContext ();
1560 if (ContextData
== NULL
) {
1561 return EFI_UNSUPPORTED
;
1564 MemoryProfileGettingStatus
= mMemoryProfileGettingStatus
;
1565 mMemoryProfileGettingStatus
= TRUE
;
1567 Size
= MemoryProfileGetDataSize ();
1569 if (*ProfileSize
< Size
) {
1570 *ProfileSize
= Size
;
1571 mMemoryProfileGettingStatus
= MemoryProfileGettingStatus
;
1572 return EFI_BUFFER_TOO_SMALL
;
1575 *ProfileSize
= Size
;
1576 MemoryProfileCopyData (ProfileBuffer
);
1578 mMemoryProfileGettingStatus
= MemoryProfileGettingStatus
;
1583 Register image to memory profile.
1585 @param[in] This The EDKII_MEMORY_PROFILE_PROTOCOL instance.
1586 @param[in] FilePath File path of the image.
1587 @param[in] ImageBase Image base address.
1588 @param[in] ImageSize Image size.
1589 @param[in] FileType File type of the image.
1591 @return EFI_SUCCESS Register successfully.
1592 @return EFI_UNSUPPORTED Memory profile is unsupported,
1593 or memory profile for the image is not required.
1594 @return EFI_OUT_OF_RESOURCES No enough resource for this register.
1599 ProfileProtocolRegisterImage (
1600 IN EDKII_MEMORY_PROFILE_PROTOCOL
*This
,
1601 IN EFI_DEVICE_PATH_PROTOCOL
*FilePath
,
1602 IN PHYSICAL_ADDRESS ImageBase
,
1603 IN UINT64 ImageSize
,
1604 IN EFI_FV_FILETYPE FileType
1608 LOADED_IMAGE_PRIVATE_DATA DriverEntry
;
1609 VOID
*EntryPointInImage
;
1611 ZeroMem (&DriverEntry
, sizeof (DriverEntry
));
1612 DriverEntry
.Info
.FilePath
= FilePath
;
1613 DriverEntry
.ImageContext
.ImageAddress
= ImageBase
;
1614 DriverEntry
.ImageContext
.ImageSize
= ImageSize
;
1615 Status
= InternalPeCoffGetEntryPoint ((VOID
*) (UINTN
) ImageBase
, &EntryPointInImage
);
1616 ASSERT_EFI_ERROR (Status
);
1617 DriverEntry
.ImageContext
.EntryPoint
= (PHYSICAL_ADDRESS
) (UINTN
) EntryPointInImage
;
1618 DriverEntry
.ImageContext
.ImageType
= InternalPeCoffGetSubsystem ((VOID
*) (UINTN
) ImageBase
);
1620 return RegisterMemoryProfileImage (&DriverEntry
, FileType
);
1624 Unregister image from memory profile.
1626 @param[in] This The EDKII_MEMORY_PROFILE_PROTOCOL instance.
1627 @param[in] FilePath File path of the image.
1628 @param[in] ImageBase Image base address.
1629 @param[in] ImageSize Image size.
1631 @return EFI_SUCCESS Unregister successfully.
1632 @return EFI_UNSUPPORTED Memory profile is unsupported,
1633 or memory profile for the image is not required.
1634 @return EFI_NOT_FOUND The image is not found.
1639 ProfileProtocolUnregisterImage (
1640 IN EDKII_MEMORY_PROFILE_PROTOCOL
*This
,
1641 IN EFI_DEVICE_PATH_PROTOCOL
*FilePath
,
1642 IN PHYSICAL_ADDRESS ImageBase
,
1647 LOADED_IMAGE_PRIVATE_DATA DriverEntry
;
1648 VOID
*EntryPointInImage
;
1650 ZeroMem (&DriverEntry
, sizeof (DriverEntry
));
1651 DriverEntry
.Info
.FilePath
= FilePath
;
1652 DriverEntry
.ImageContext
.ImageAddress
= ImageBase
;
1653 DriverEntry
.ImageContext
.ImageSize
= ImageSize
;
1654 Status
= InternalPeCoffGetEntryPoint ((VOID
*) (UINTN
) ImageBase
, &EntryPointInImage
);
1655 ASSERT_EFI_ERROR (Status
);
1656 DriverEntry
.ImageContext
.EntryPoint
= (PHYSICAL_ADDRESS
) (UINTN
) EntryPointInImage
;
1658 return UnregisterMemoryProfileImage (&DriverEntry
);
1662 Get memory profile recording state.
1664 @param[in] This The EDKII_MEMORY_PROFILE_PROTOCOL instance.
1665 @param[out] RecordingState Recording state.
1667 @return EFI_SUCCESS Memory profile recording state is returned.
1668 @return EFI_UNSUPPORTED Memory profile is unsupported.
1669 @return EFI_INVALID_PARAMETER RecordingState is NULL.
1674 ProfileProtocolGetRecordingState (
1675 IN EDKII_MEMORY_PROFILE_PROTOCOL
*This
,
1676 OUT BOOLEAN
*RecordingState
1679 MEMORY_PROFILE_CONTEXT_DATA
*ContextData
;
1681 ContextData
= GetMemoryProfileContext ();
1682 if (ContextData
== NULL
) {
1683 return EFI_UNSUPPORTED
;
1686 if (RecordingState
== NULL
) {
1687 return EFI_INVALID_PARAMETER
;
1689 *RecordingState
= mMemoryProfileRecordingEnable
;
1694 Set memory profile recording state.
1696 @param[in] This The EDKII_MEMORY_PROFILE_PROTOCOL instance.
1697 @param[in] RecordingState Recording state.
1699 @return EFI_SUCCESS Set memory profile recording state successfully.
1700 @return EFI_UNSUPPORTED Memory profile is unsupported.
1705 ProfileProtocolSetRecordingState (
1706 IN EDKII_MEMORY_PROFILE_PROTOCOL
*This
,
1707 IN BOOLEAN RecordingState
1710 MEMORY_PROFILE_CONTEXT_DATA
*ContextData
;
1712 ContextData
= GetMemoryProfileContext ();
1713 if (ContextData
== NULL
) {
1714 return EFI_UNSUPPORTED
;
1717 mMemoryProfileRecordingEnable
= RecordingState
;
1722 Record memory profile of multilevel caller.
1724 @param[in] This The EDKII_MEMORY_PROFILE_PROTOCOL instance.
1725 @param[in] CallerAddress Address of caller.
1726 @param[in] Action Memory profile action.
1727 @param[in] MemoryType Memory type.
1728 EfiMaxMemoryType means the MemoryType is unknown.
1729 @param[in] Buffer Buffer address.
1730 @param[in] Size Buffer size.
1731 @param[in] ActionString String for memory profile action.
1732 Only needed for user defined allocate action.
1734 @return EFI_SUCCESS Memory profile is updated.
1735 @return EFI_UNSUPPORTED Memory profile is unsupported,
1736 or memory profile for the image is not required,
1737 or memory profile for the memory type is not required.
1738 @return EFI_ACCESS_DENIED It is during memory profile data getting.
1739 @return EFI_ABORTED Memory profile recording is not enabled.
1740 @return EFI_OUT_OF_RESOURCES No enough resource to update memory profile for allocate action.
1741 @return EFI_NOT_FOUND No matched allocate info found for free action.
1746 ProfileProtocolRecord (
1747 IN EDKII_MEMORY_PROFILE_PROTOCOL
*This
,
1748 IN PHYSICAL_ADDRESS CallerAddress
,
1749 IN MEMORY_PROFILE_ACTION Action
,
1750 IN EFI_MEMORY_TYPE MemoryType
,
1753 IN CHAR8
*ActionString OPTIONAL
1756 return CoreUpdateProfile (CallerAddress
, Action
, MemoryType
, Size
, Buffer
, ActionString
);
1759 ////////////////////