2 Support routines for UEFI memory profile.
4 Copyright (c) 2014 - 2018, Intel Corporation. All rights reserved.<BR>
5 This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php.
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
18 #define IS_UEFI_MEMORY_PROFILE_ENABLED ((PcdGet8 (PcdMemoryProfilePropertyMask) & BIT0) != 0)
20 #define GET_OCCUPIED_SIZE(ActualSize, Alignment) \
21 ((ActualSize) + (((Alignment) - ((ActualSize) & ((Alignment) - 1))) & ((Alignment) - 1)))
25 MEMORY_PROFILE_CONTEXT Context
;
26 LIST_ENTRY
*DriverInfoList
;
27 } MEMORY_PROFILE_CONTEXT_DATA
;
31 MEMORY_PROFILE_DRIVER_INFO DriverInfo
;
32 LIST_ENTRY
*AllocInfoList
;
35 } MEMORY_PROFILE_DRIVER_INFO_DATA
;
39 MEMORY_PROFILE_ALLOC_INFO AllocInfo
;
42 } MEMORY_PROFILE_ALLOC_INFO_DATA
;
45 GLOBAL_REMOVE_IF_UNREFERENCED LIST_ENTRY mImageQueue
= INITIALIZE_LIST_HEAD_VARIABLE (mImageQueue
);
46 GLOBAL_REMOVE_IF_UNREFERENCED MEMORY_PROFILE_CONTEXT_DATA mMemoryProfileContext
= {
47 MEMORY_PROFILE_CONTEXT_SIGNATURE
,
50 MEMORY_PROFILE_CONTEXT_SIGNATURE
,
51 sizeof (MEMORY_PROFILE_CONTEXT
),
52 MEMORY_PROFILE_CONTEXT_REVISION
64 GLOBAL_REMOVE_IF_UNREFERENCED MEMORY_PROFILE_CONTEXT_DATA
*mMemoryProfileContextPtr
= NULL
;
66 GLOBAL_REMOVE_IF_UNREFERENCED EFI_LOCK mMemoryProfileLock
= EFI_INITIALIZE_LOCK_VARIABLE (TPL_NOTIFY
);
67 GLOBAL_REMOVE_IF_UNREFERENCED BOOLEAN mMemoryProfileGettingStatus
= FALSE
;
68 GLOBAL_REMOVE_IF_UNREFERENCED BOOLEAN mMemoryProfileRecordingEnable
= MEMORY_PROFILE_RECORDING_DISABLE
;
69 GLOBAL_REMOVE_IF_UNREFERENCED EFI_DEVICE_PATH_PROTOCOL
*mMemoryProfileDriverPath
;
70 GLOBAL_REMOVE_IF_UNREFERENCED UINTN mMemoryProfileDriverPathSize
;
73 Get memory profile data.
75 @param[in] This The EDKII_MEMORY_PROFILE_PROTOCOL instance.
76 @param[in, out] ProfileSize On entry, points to the size in bytes of the ProfileBuffer.
77 On return, points to the size of the data returned in ProfileBuffer.
78 @param[out] ProfileBuffer Profile buffer.
80 @return EFI_SUCCESS Get the memory profile data successfully.
81 @return EFI_UNSUPPORTED Memory profile is unsupported.
82 @return EFI_BUFFER_TO_SMALL The ProfileSize is too small for the resulting data.
83 ProfileSize is updated with the size required.
88 ProfileProtocolGetData (
89 IN EDKII_MEMORY_PROFILE_PROTOCOL
*This
,
90 IN OUT UINT64
*ProfileSize
,
91 OUT VOID
*ProfileBuffer
95 Register image to memory profile.
97 @param[in] This The EDKII_MEMORY_PROFILE_PROTOCOL instance.
98 @param[in] FilePath File path of the image.
99 @param[in] ImageBase Image base address.
100 @param[in] ImageSize Image size.
101 @param[in] FileType File type of the image.
103 @return EFI_SUCCESS Register successfully.
104 @return EFI_UNSUPPORTED Memory profile is unsupported,
105 or memory profile for the image is not required.
106 @return EFI_OUT_OF_RESOURCE No enough resource for this register.
111 ProfileProtocolRegisterImage (
112 IN EDKII_MEMORY_PROFILE_PROTOCOL
*This
,
113 IN EFI_DEVICE_PATH_PROTOCOL
*FilePath
,
114 IN PHYSICAL_ADDRESS ImageBase
,
116 IN EFI_FV_FILETYPE FileType
120 Unregister image from memory profile.
122 @param[in] This The EDKII_MEMORY_PROFILE_PROTOCOL instance.
123 @param[in] FilePath File path of the image.
124 @param[in] ImageBase Image base address.
125 @param[in] ImageSize Image size.
127 @return EFI_SUCCESS Unregister successfully.
128 @return EFI_UNSUPPORTED Memory profile is unsupported,
129 or memory profile for the image is not required.
130 @return EFI_NOT_FOUND The image is not found.
135 ProfileProtocolUnregisterImage (
136 IN EDKII_MEMORY_PROFILE_PROTOCOL
*This
,
137 IN EFI_DEVICE_PATH_PROTOCOL
*FilePath
,
138 IN PHYSICAL_ADDRESS ImageBase
,
143 Get memory profile recording state.
145 @param[in] This The EDKII_MEMORY_PROFILE_PROTOCOL instance.
146 @param[out] RecordingState Recording state.
148 @return EFI_SUCCESS Memory profile recording state is returned.
149 @return EFI_UNSUPPORTED Memory profile is unsupported.
150 @return EFI_INVALID_PARAMETER RecordingState is NULL.
155 ProfileProtocolGetRecordingState (
156 IN EDKII_MEMORY_PROFILE_PROTOCOL
*This
,
157 OUT BOOLEAN
*RecordingState
161 Set memory profile recording state.
163 @param[in] This The EDKII_MEMORY_PROFILE_PROTOCOL instance.
164 @param[in] RecordingState Recording state.
166 @return EFI_SUCCESS Set memory profile recording state successfully.
167 @return EFI_UNSUPPORTED Memory profile is unsupported.
172 ProfileProtocolSetRecordingState (
173 IN EDKII_MEMORY_PROFILE_PROTOCOL
*This
,
174 IN BOOLEAN RecordingState
178 Record memory profile of multilevel caller.
180 @param[in] This The EDKII_MEMORY_PROFILE_PROTOCOL instance.
181 @param[in] CallerAddress Address of caller.
182 @param[in] Action Memory profile action.
183 @param[in] MemoryType Memory type.
184 EfiMaxMemoryType means the MemoryType is unknown.
185 @param[in] Buffer Buffer address.
186 @param[in] Size Buffer size.
187 @param[in] ActionString String for memory profile action.
188 Only needed for user defined allocate action.
190 @return EFI_SUCCESS Memory profile is updated.
191 @return EFI_UNSUPPORTED Memory profile is unsupported,
192 or memory profile for the image is not required,
193 or memory profile for the memory type is not required.
194 @return EFI_ACCESS_DENIED It is during memory profile data getting.
195 @return EFI_ABORTED Memory profile recording is not enabled.
196 @return EFI_OUT_OF_RESOURCES No enough resource to update memory profile for allocate action.
197 @return EFI_NOT_FOUND No matched allocate info found for free action.
202 ProfileProtocolRecord (
203 IN EDKII_MEMORY_PROFILE_PROTOCOL
*This
,
204 IN PHYSICAL_ADDRESS CallerAddress
,
205 IN MEMORY_PROFILE_ACTION Action
,
206 IN EFI_MEMORY_TYPE MemoryType
,
209 IN CHAR8
*ActionString OPTIONAL
212 GLOBAL_REMOVE_IF_UNREFERENCED EDKII_MEMORY_PROFILE_PROTOCOL mProfileProtocol
= {
213 ProfileProtocolGetData
,
214 ProfileProtocolRegisterImage
,
215 ProfileProtocolUnregisterImage
,
216 ProfileProtocolGetRecordingState
,
217 ProfileProtocolSetRecordingState
,
218 ProfileProtocolRecord
,
222 Acquire lock on mMemoryProfileLock.
225 CoreAcquireMemoryProfileLock (
229 CoreAcquireLock (&mMemoryProfileLock
);
233 Release lock on mMemoryProfileLock.
236 CoreReleaseMemoryProfileLock (
240 CoreReleaseLock (&mMemoryProfileLock
);
244 Return memory profile context.
246 @return Memory profile context.
249 MEMORY_PROFILE_CONTEXT_DATA
*
250 GetMemoryProfileContext (
254 return mMemoryProfileContextPtr
;
258 Retrieves and returns the Subsystem of a PE/COFF image that has been loaded into system memory.
259 If Pe32Data is NULL, then ASSERT().
261 @param Pe32Data The pointer to the PE/COFF image that is loaded in system memory.
263 @return The Subsystem of the PE/COFF image.
267 InternalPeCoffGetSubsystem (
271 EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION Hdr
;
272 EFI_IMAGE_DOS_HEADER
*DosHdr
;
275 ASSERT (Pe32Data
!= NULL
);
277 DosHdr
= (EFI_IMAGE_DOS_HEADER
*) Pe32Data
;
278 if (DosHdr
->e_magic
== EFI_IMAGE_DOS_SIGNATURE
) {
280 // DOS image header is present, so read the PE header after the DOS image header.
282 Hdr
.Pe32
= (EFI_IMAGE_NT_HEADERS32
*) ((UINTN
) Pe32Data
+ (UINTN
) ((DosHdr
->e_lfanew
) & 0x0ffff));
285 // DOS image header is not present, so PE header is at the image base.
287 Hdr
.Pe32
= (EFI_IMAGE_NT_HEADERS32
*) Pe32Data
;
290 if (Hdr
.Te
->Signature
== EFI_TE_IMAGE_HEADER_SIGNATURE
) {
291 return Hdr
.Te
->Subsystem
;
292 } else if (Hdr
.Pe32
->Signature
== EFI_IMAGE_NT_SIGNATURE
) {
293 Magic
= Hdr
.Pe32
->OptionalHeader
.Magic
;
294 if (Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
295 return Hdr
.Pe32
->OptionalHeader
.Subsystem
;
296 } else if (Magic
== EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC
) {
297 return Hdr
.Pe32Plus
->OptionalHeader
.Subsystem
;
305 Retrieves and returns a pointer to the entry point to a PE/COFF image that has been loaded
306 into system memory with the PE/COFF Loader Library functions.
308 Retrieves the entry point to the PE/COFF image specified by Pe32Data and returns this entry
309 point in EntryPoint. If the entry point could not be retrieved from the PE/COFF image, then
310 return RETURN_INVALID_PARAMETER. Otherwise return RETURN_SUCCESS.
311 If Pe32Data is NULL, then ASSERT().
312 If EntryPoint is NULL, then ASSERT().
314 @param Pe32Data The pointer to the PE/COFF image that is loaded in system memory.
315 @param EntryPoint The pointer to entry point to the PE/COFF image to return.
317 @retval RETURN_SUCCESS EntryPoint was returned.
318 @retval RETURN_INVALID_PARAMETER The entry point could not be found in the PE/COFF image.
322 InternalPeCoffGetEntryPoint (
324 OUT VOID
**EntryPoint
327 EFI_IMAGE_DOS_HEADER
*DosHdr
;
328 EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION Hdr
;
330 ASSERT (Pe32Data
!= NULL
);
331 ASSERT (EntryPoint
!= NULL
);
333 DosHdr
= (EFI_IMAGE_DOS_HEADER
*) Pe32Data
;
334 if (DosHdr
->e_magic
== EFI_IMAGE_DOS_SIGNATURE
) {
336 // DOS image header is present, so read the PE header after the DOS image header.
338 Hdr
.Pe32
= (EFI_IMAGE_NT_HEADERS32
*) ((UINTN
) Pe32Data
+ (UINTN
) ((DosHdr
->e_lfanew
) & 0x0ffff));
341 // DOS image header is not present, so PE header is at the image base.
343 Hdr
.Pe32
= (EFI_IMAGE_NT_HEADERS32
*) Pe32Data
;
347 // Calculate the entry point relative to the start of the image.
348 // AddressOfEntryPoint is common for PE32 & PE32+
350 if (Hdr
.Te
->Signature
== EFI_TE_IMAGE_HEADER_SIGNATURE
) {
351 *EntryPoint
= (VOID
*) ((UINTN
) Pe32Data
+ (UINTN
) (Hdr
.Te
->AddressOfEntryPoint
& 0x0ffffffff) + sizeof (EFI_TE_IMAGE_HEADER
) - Hdr
.Te
->StrippedSize
);
352 return RETURN_SUCCESS
;
353 } else if (Hdr
.Pe32
->Signature
== EFI_IMAGE_NT_SIGNATURE
) {
354 *EntryPoint
= (VOID
*) ((UINTN
) Pe32Data
+ (UINTN
) (Hdr
.Pe32
->OptionalHeader
.AddressOfEntryPoint
& 0x0ffffffff));
355 return RETURN_SUCCESS
;
358 return RETURN_UNSUPPORTED
;
364 @param ContextData Memory profile context.
365 @param FileName File name of the image.
366 @param ImageBase Image base address.
367 @param ImageSize Image size.
368 @param EntryPoint Entry point of the image.
369 @param ImageSubsystem Image subsystem of the image.
370 @param FileType File type of the image.
372 @return Pointer to memory profile driver info.
375 MEMORY_PROFILE_DRIVER_INFO_DATA
*
377 IN MEMORY_PROFILE_CONTEXT_DATA
*ContextData
,
378 IN EFI_GUID
*FileName
,
379 IN PHYSICAL_ADDRESS ImageBase
,
381 IN PHYSICAL_ADDRESS EntryPoint
,
382 IN UINT16 ImageSubsystem
,
383 IN EFI_FV_FILETYPE FileType
387 MEMORY_PROFILE_DRIVER_INFO
*DriverInfo
;
388 MEMORY_PROFILE_DRIVER_INFO_DATA
*DriverInfoData
;
389 VOID
*EntryPointInImage
;
392 UINTN PdbOccupiedSize
;
397 if (ImageBase
!= 0) {
398 PdbString
= PeCoffLoaderGetPdbPointer ((VOID
*) (UINTN
) ImageBase
);
399 if (PdbString
!= NULL
) {
400 PdbSize
= AsciiStrSize (PdbString
);
401 PdbOccupiedSize
= GET_OCCUPIED_SIZE (PdbSize
, sizeof (UINT64
));
406 // Use CoreInternalAllocatePool() that will not update profile for this AllocatePool action.
408 Status
= CoreInternalAllocatePool (
410 sizeof (*DriverInfoData
) + sizeof (LIST_ENTRY
) + PdbSize
,
411 (VOID
**) &DriverInfoData
413 if (EFI_ERROR (Status
)) {
416 ASSERT (DriverInfoData
!= NULL
);
418 ZeroMem (DriverInfoData
, sizeof (*DriverInfoData
));
420 DriverInfo
= &DriverInfoData
->DriverInfo
;
421 DriverInfoData
->Signature
= MEMORY_PROFILE_DRIVER_INFO_SIGNATURE
;
422 DriverInfo
->Header
.Signature
= MEMORY_PROFILE_DRIVER_INFO_SIGNATURE
;
423 DriverInfo
->Header
.Length
= (UINT16
) (sizeof (MEMORY_PROFILE_DRIVER_INFO
) + PdbOccupiedSize
);
424 DriverInfo
->Header
.Revision
= MEMORY_PROFILE_DRIVER_INFO_REVISION
;
425 if (FileName
!= NULL
) {
426 CopyMem (&DriverInfo
->FileName
, FileName
, sizeof (EFI_GUID
));
428 DriverInfo
->ImageBase
= ImageBase
;
429 DriverInfo
->ImageSize
= ImageSize
;
430 DriverInfo
->EntryPoint
= EntryPoint
;
431 DriverInfo
->ImageSubsystem
= ImageSubsystem
;
432 if ((EntryPoint
!= 0) && ((EntryPoint
< ImageBase
) || (EntryPoint
>= (ImageBase
+ ImageSize
)))) {
434 // If the EntryPoint is not in the range of image buffer, it should come from emulation environment.
435 // So patch ImageBuffer here to align the EntryPoint.
437 Status
= InternalPeCoffGetEntryPoint ((VOID
*) (UINTN
) ImageBase
, &EntryPointInImage
);
438 ASSERT_EFI_ERROR (Status
);
439 DriverInfo
->ImageBase
= ImageBase
+ EntryPoint
- (PHYSICAL_ADDRESS
) (UINTN
) EntryPointInImage
;
441 DriverInfo
->FileType
= FileType
;
442 DriverInfoData
->AllocInfoList
= (LIST_ENTRY
*) (DriverInfoData
+ 1);
443 InitializeListHead (DriverInfoData
->AllocInfoList
);
444 DriverInfo
->CurrentUsage
= 0;
445 DriverInfo
->PeakUsage
= 0;
446 DriverInfo
->AllocRecordCount
= 0;
448 DriverInfo
->PdbStringOffset
= (UINT16
) sizeof (MEMORY_PROFILE_DRIVER_INFO
);
449 DriverInfoData
->PdbString
= (CHAR8
*) (DriverInfoData
->AllocInfoList
+ 1);
450 CopyMem (DriverInfoData
->PdbString
, PdbString
, PdbSize
);
452 DriverInfo
->PdbStringOffset
= 0;
453 DriverInfoData
->PdbString
= NULL
;
456 InsertTailList (ContextData
->DriverInfoList
, &DriverInfoData
->Link
);
457 ContextData
->Context
.ImageCount
++;
458 ContextData
->Context
.TotalImageSize
+= DriverInfo
->ImageSize
;
460 return DriverInfoData
;
464 Return if record for this driver is needed..
466 @param DriverFilePath Driver file path.
468 @retval TRUE Record for this driver is needed.
469 @retval FALSE Record for this driver is not needed.
473 NeedRecordThisDriver (
474 IN EFI_DEVICE_PATH_PROTOCOL
*DriverFilePath
477 EFI_DEVICE_PATH_PROTOCOL
*TmpDevicePath
;
478 EFI_DEVICE_PATH_PROTOCOL
*DevicePathInstance
;
479 UINTN DevicePathSize
;
482 if (!IsDevicePathValid (mMemoryProfileDriverPath
, mMemoryProfileDriverPathSize
)) {
484 // Invalid Device Path means record all.
490 // Record FilePath without END node.
492 FilePathSize
= GetDevicePathSize (DriverFilePath
) - sizeof(EFI_DEVICE_PATH_PROTOCOL
);
494 DevicePathInstance
= mMemoryProfileDriverPath
;
497 // Find END node (it might be END_ENTIRE or END_INSTANCE).
499 TmpDevicePath
= DevicePathInstance
;
500 while (!IsDevicePathEndType (TmpDevicePath
)) {
501 TmpDevicePath
= NextDevicePathNode (TmpDevicePath
);
505 // Do not compare END node.
507 DevicePathSize
= (UINTN
)TmpDevicePath
- (UINTN
)DevicePathInstance
;
508 if ((FilePathSize
== DevicePathSize
) &&
509 (CompareMem (DriverFilePath
, DevicePathInstance
, DevicePathSize
) == 0)) {
514 // Get next instance.
516 DevicePathInstance
= (EFI_DEVICE_PATH_PROTOCOL
*)((UINTN
)DevicePathInstance
+ DevicePathSize
+ DevicePathNodeLength(TmpDevicePath
));
517 } while (DevicePathSubType (TmpDevicePath
) != END_ENTIRE_DEVICE_PATH_SUBTYPE
);
523 Register DXE Core to memory profile.
525 @param HobStart The start address of the HOB.
526 @param ContextData Memory profile context.
528 @retval TRUE Register success.
529 @retval FALSE Register fail.
535 IN MEMORY_PROFILE_CONTEXT_DATA
*ContextData
538 EFI_PEI_HOB_POINTERS DxeCoreHob
;
539 MEMORY_PROFILE_DRIVER_INFO_DATA
*DriverInfoData
;
540 PHYSICAL_ADDRESS ImageBase
;
541 UINT8 TempBuffer
[sizeof(MEDIA_FW_VOL_FILEPATH_DEVICE_PATH
) + sizeof(EFI_DEVICE_PATH_PROTOCOL
)];
542 MEDIA_FW_VOL_FILEPATH_DEVICE_PATH
*FilePath
;
544 ASSERT (ContextData
!= NULL
);
547 // Searching for image hob
549 DxeCoreHob
.Raw
= HobStart
;
550 while ((DxeCoreHob
.Raw
= GetNextHob (EFI_HOB_TYPE_MEMORY_ALLOCATION
, DxeCoreHob
.Raw
)) != NULL
) {
551 if (CompareGuid (&DxeCoreHob
.MemoryAllocationModule
->MemoryAllocationHeader
.Name
, &gEfiHobMemoryAllocModuleGuid
)) {
557 DxeCoreHob
.Raw
= GET_NEXT_HOB (DxeCoreHob
);
559 ASSERT (DxeCoreHob
.Raw
!= NULL
);
561 FilePath
= (MEDIA_FW_VOL_FILEPATH_DEVICE_PATH
*) TempBuffer
;
562 EfiInitializeFwVolDevicepathNode (FilePath
, &DxeCoreHob
.MemoryAllocationModule
->ModuleName
);
563 SetDevicePathEndNode (FilePath
+ 1);
565 if (!NeedRecordThisDriver ((EFI_DEVICE_PATH_PROTOCOL
*) FilePath
)) {
569 ImageBase
= DxeCoreHob
.MemoryAllocationModule
->MemoryAllocationHeader
.MemoryBaseAddress
;
570 DriverInfoData
= BuildDriverInfo (
572 &DxeCoreHob
.MemoryAllocationModule
->ModuleName
,
574 DxeCoreHob
.MemoryAllocationModule
->MemoryAllocationHeader
.MemoryLength
,
575 DxeCoreHob
.MemoryAllocationModule
->EntryPoint
,
576 InternalPeCoffGetSubsystem ((VOID
*) (UINTN
) ImageBase
),
577 EFI_FV_FILETYPE_DXE_CORE
579 if (DriverInfoData
== NULL
) {
587 Initialize memory profile.
589 @param HobStart The start address of the HOB.
597 MEMORY_PROFILE_CONTEXT_DATA
*ContextData
;
599 if (!IS_UEFI_MEMORY_PROFILE_ENABLED
) {
603 ContextData
= GetMemoryProfileContext ();
604 if (ContextData
!= NULL
) {
608 mMemoryProfileGettingStatus
= FALSE
;
609 if ((PcdGet8 (PcdMemoryProfilePropertyMask
) & BIT7
) != 0) {
610 mMemoryProfileRecordingEnable
= MEMORY_PROFILE_RECORDING_DISABLE
;
612 mMemoryProfileRecordingEnable
= MEMORY_PROFILE_RECORDING_ENABLE
;
614 mMemoryProfileDriverPathSize
= PcdGetSize (PcdMemoryProfileDriverPath
);
615 mMemoryProfileDriverPath
= AllocateCopyPool (mMemoryProfileDriverPathSize
, PcdGetPtr (PcdMemoryProfileDriverPath
));
616 mMemoryProfileContextPtr
= &mMemoryProfileContext
;
618 RegisterDxeCore (HobStart
, &mMemoryProfileContext
);
620 DEBUG ((EFI_D_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
) {
673 ThisFilePath
= (MEDIA_FW_VOL_FILEPATH_DEVICE_PATH
*) NextDevicePathNode (ThisFilePath
);
681 Register image to memory profile.
683 @param DriverEntry Image info.
684 @param FileType Image file type.
686 @return EFI_SUCCESS Register successfully.
687 @return EFI_UNSUPPORTED Memory profile is unsupported,
688 or memory profile for the image is not required.
689 @return EFI_OUT_OF_RESOURCES No enough resource for this register.
693 RegisterMemoryProfileImage (
694 IN LOADED_IMAGE_PRIVATE_DATA
*DriverEntry
,
695 IN EFI_FV_FILETYPE FileType
698 MEMORY_PROFILE_CONTEXT_DATA
*ContextData
;
699 MEMORY_PROFILE_DRIVER_INFO_DATA
*DriverInfoData
;
701 if (!IS_UEFI_MEMORY_PROFILE_ENABLED
) {
702 return EFI_UNSUPPORTED
;
705 if (!NeedRecordThisDriver (DriverEntry
->Info
.FilePath
)) {
706 return EFI_UNSUPPORTED
;
709 ContextData
= GetMemoryProfileContext ();
710 if (ContextData
== NULL
) {
711 return EFI_UNSUPPORTED
;
714 DriverInfoData
= BuildDriverInfo (
716 GetFileNameFromFilePath (DriverEntry
->Info
.FilePath
),
717 DriverEntry
->ImageContext
.ImageAddress
,
718 DriverEntry
->ImageContext
.ImageSize
,
719 DriverEntry
->ImageContext
.EntryPoint
,
720 DriverEntry
->ImageContext
.ImageType
,
723 if (DriverInfoData
== NULL
) {
724 return EFI_OUT_OF_RESOURCES
;
731 Search image from memory profile.
733 @param ContextData Memory profile context.
734 @param FileName Image file name.
735 @param Address Image Address.
737 @return Pointer to memory profile driver info.
740 MEMORY_PROFILE_DRIVER_INFO_DATA
*
741 GetMemoryProfileDriverInfoByFileNameAndAddress (
742 IN MEMORY_PROFILE_CONTEXT_DATA
*ContextData
,
743 IN EFI_GUID
*FileName
,
744 IN PHYSICAL_ADDRESS Address
747 MEMORY_PROFILE_DRIVER_INFO
*DriverInfo
;
748 MEMORY_PROFILE_DRIVER_INFO_DATA
*DriverInfoData
;
749 LIST_ENTRY
*DriverLink
;
750 LIST_ENTRY
*DriverInfoList
;
752 DriverInfoList
= ContextData
->DriverInfoList
;
754 for (DriverLink
= DriverInfoList
->ForwardLink
;
755 DriverLink
!= DriverInfoList
;
756 DriverLink
= DriverLink
->ForwardLink
) {
757 DriverInfoData
= CR (
759 MEMORY_PROFILE_DRIVER_INFO_DATA
,
761 MEMORY_PROFILE_DRIVER_INFO_SIGNATURE
763 DriverInfo
= &DriverInfoData
->DriverInfo
;
764 if ((CompareGuid (&DriverInfo
->FileName
, FileName
)) &&
765 (Address
>= DriverInfo
->ImageBase
) &&
766 (Address
< (DriverInfo
->ImageBase
+ DriverInfo
->ImageSize
))) {
767 return DriverInfoData
;
775 Search image from memory profile.
776 It will return image, if (Address >= ImageBuffer) AND (Address < ImageBuffer + ImageSize).
778 @param ContextData Memory profile context.
779 @param Address Image or Function address.
781 @return Pointer to memory profile driver info.
784 MEMORY_PROFILE_DRIVER_INFO_DATA
*
785 GetMemoryProfileDriverInfoFromAddress (
786 IN MEMORY_PROFILE_CONTEXT_DATA
*ContextData
,
787 IN PHYSICAL_ADDRESS Address
790 MEMORY_PROFILE_DRIVER_INFO
*DriverInfo
;
791 MEMORY_PROFILE_DRIVER_INFO_DATA
*DriverInfoData
;
792 LIST_ENTRY
*DriverLink
;
793 LIST_ENTRY
*DriverInfoList
;
795 DriverInfoList
= ContextData
->DriverInfoList
;
797 for (DriverLink
= DriverInfoList
->ForwardLink
;
798 DriverLink
!= DriverInfoList
;
799 DriverLink
= DriverLink
->ForwardLink
) {
800 DriverInfoData
= CR (
802 MEMORY_PROFILE_DRIVER_INFO_DATA
,
804 MEMORY_PROFILE_DRIVER_INFO_SIGNATURE
806 DriverInfo
= &DriverInfoData
->DriverInfo
;
807 if ((Address
>= DriverInfo
->ImageBase
) &&
808 (Address
< (DriverInfo
->ImageBase
+ DriverInfo
->ImageSize
))) {
809 return DriverInfoData
;
817 Unregister image from memory profile.
819 @param DriverEntry Image info.
821 @return EFI_SUCCESS Unregister successfully.
822 @return EFI_UNSUPPORTED Memory profile is unsupported,
823 or memory profile for the image is not required.
824 @return EFI_NOT_FOUND The image is not found.
828 UnregisterMemoryProfileImage (
829 IN LOADED_IMAGE_PRIVATE_DATA
*DriverEntry
833 MEMORY_PROFILE_CONTEXT_DATA
*ContextData
;
834 MEMORY_PROFILE_DRIVER_INFO_DATA
*DriverInfoData
;
836 PHYSICAL_ADDRESS ImageAddress
;
837 VOID
*EntryPointInImage
;
839 if (!IS_UEFI_MEMORY_PROFILE_ENABLED
) {
840 return EFI_UNSUPPORTED
;
843 if (!NeedRecordThisDriver (DriverEntry
->Info
.FilePath
)) {
844 return EFI_UNSUPPORTED
;
847 ContextData
= GetMemoryProfileContext ();
848 if (ContextData
== NULL
) {
849 return EFI_UNSUPPORTED
;
852 DriverInfoData
= NULL
;
853 FileName
= GetFileNameFromFilePath (DriverEntry
->Info
.FilePath
);
854 ImageAddress
= DriverEntry
->ImageContext
.ImageAddress
;
855 if ((DriverEntry
->ImageContext
.EntryPoint
< ImageAddress
) || (DriverEntry
->ImageContext
.EntryPoint
>= (ImageAddress
+ DriverEntry
->ImageContext
.ImageSize
))) {
857 // If the EntryPoint is not in the range of image buffer, it should come from emulation environment.
858 // So patch ImageAddress here to align the EntryPoint.
860 Status
= InternalPeCoffGetEntryPoint ((VOID
*) (UINTN
) ImageAddress
, &EntryPointInImage
);
861 ASSERT_EFI_ERROR (Status
);
862 ImageAddress
= ImageAddress
+ (UINTN
) DriverEntry
->ImageContext
.EntryPoint
- (UINTN
) EntryPointInImage
;
864 if (FileName
!= NULL
) {
865 DriverInfoData
= GetMemoryProfileDriverInfoByFileNameAndAddress (ContextData
, FileName
, ImageAddress
);
867 if (DriverInfoData
== NULL
) {
868 DriverInfoData
= GetMemoryProfileDriverInfoFromAddress (ContextData
, ImageAddress
);
870 if (DriverInfoData
== NULL
) {
871 return EFI_NOT_FOUND
;
874 ContextData
->Context
.TotalImageSize
-= DriverInfoData
->DriverInfo
.ImageSize
;
876 // Keep the ImageBase for RVA calculation in Application.
877 //DriverInfoData->DriverInfo.ImageBase = 0;
878 DriverInfoData
->DriverInfo
.ImageSize
= 0;
880 if (DriverInfoData
->DriverInfo
.PeakUsage
== 0) {
881 ContextData
->Context
.ImageCount
--;
882 RemoveEntryList (&DriverInfoData
->Link
);
884 // Use CoreInternalFreePool() that will not update profile for this FreePool action.
886 CoreInternalFreePool (DriverInfoData
, NULL
);
893 Return if this memory type needs to be recorded into memory profile.
894 If BIOS memory type (0 ~ EfiMaxMemoryType - 1), it checks bit (1 << MemoryType).
895 If OS memory type (0x80000000 ~ 0xFFFFFFFF), it checks bit63 - 0x8000000000000000.
896 If OEM memory type (0x70000000 ~ 0x7FFFFFFF), it checks bit62 - 0x4000000000000000.
898 @param MemoryType Memory type.
900 @retval TRUE This memory type need to be recorded.
901 @retval FALSE This memory type need not to be recorded.
905 CoreNeedRecordProfile (
906 IN EFI_MEMORY_TYPE MemoryType
911 if ((UINT32
) MemoryType
>= MEMORY_TYPE_OS_RESERVED_MIN
) {
913 } else if ((UINT32
) MemoryType
>= MEMORY_TYPE_OEM_RESERVED_MIN
) {
916 TestBit
= LShiftU64 (1, MemoryType
);
919 if ((PcdGet64 (PcdMemoryProfileMemoryType
) & TestBit
) != 0) {
927 Convert EFI memory type to profile memory index. The rule is:
928 If BIOS memory type (0 ~ EfiMaxMemoryType - 1), ProfileMemoryIndex = MemoryType.
929 If OS memory type (0x80000000 ~ 0xFFFFFFFF), ProfileMemoryIndex = EfiMaxMemoryType.
930 If OEM memory type (0x70000000 ~ 0x7FFFFFFF), ProfileMemoryIndex = EfiMaxMemoryType + 1.
932 @param MemoryType Memory type.
934 @return Profile memory index.
938 GetProfileMemoryIndex (
939 IN EFI_MEMORY_TYPE MemoryType
942 if ((UINT32
) MemoryType
>= MEMORY_TYPE_OS_RESERVED_MIN
) {
943 return EfiMaxMemoryType
;
944 } else if ((UINT32
) MemoryType
>= MEMORY_TYPE_OEM_RESERVED_MIN
) {
945 return EfiMaxMemoryType
+ 1;
952 Update memory profile Allocate information.
954 @param CallerAddress Address of caller who call Allocate.
955 @param Action This Allocate action.
956 @param MemoryType Memory type.
957 @param Size Buffer size.
958 @param Buffer Buffer address.
959 @param ActionString String for memory profile action.
961 @return EFI_SUCCESS Memory profile is updated.
962 @return EFI_UNSUPPORTED Memory profile is unsupported,
963 or memory profile for the image is not required.
964 @return EFI_OUT_OF_RESOURCES No enough resource to update memory profile for allocate action.
968 CoreUpdateProfileAllocate (
969 IN PHYSICAL_ADDRESS CallerAddress
,
970 IN MEMORY_PROFILE_ACTION Action
,
971 IN EFI_MEMORY_TYPE MemoryType
,
974 IN CHAR8
*ActionString OPTIONAL
978 MEMORY_PROFILE_CONTEXT
*Context
;
979 MEMORY_PROFILE_DRIVER_INFO
*DriverInfo
;
980 MEMORY_PROFILE_ALLOC_INFO
*AllocInfo
;
981 MEMORY_PROFILE_CONTEXT_DATA
*ContextData
;
982 MEMORY_PROFILE_DRIVER_INFO_DATA
*DriverInfoData
;
983 MEMORY_PROFILE_ALLOC_INFO_DATA
*AllocInfoData
;
984 UINTN ProfileMemoryIndex
;
985 MEMORY_PROFILE_ACTION BasicAction
;
986 UINTN ActionStringSize
;
987 UINTN ActionStringOccupiedSize
;
989 BasicAction
= Action
& MEMORY_PROFILE_ACTION_BASIC_MASK
;
991 ContextData
= GetMemoryProfileContext ();
992 if (ContextData
== NULL
) {
993 return EFI_UNSUPPORTED
;
996 DriverInfoData
= GetMemoryProfileDriverInfoFromAddress (ContextData
, CallerAddress
);
997 if (DriverInfoData
== NULL
) {
998 return EFI_UNSUPPORTED
;
1001 ActionStringSize
= 0;
1002 ActionStringOccupiedSize
= 0;
1003 if (ActionString
!= NULL
) {
1004 ActionStringSize
= AsciiStrSize (ActionString
);
1005 ActionStringOccupiedSize
= GET_OCCUPIED_SIZE (ActionStringSize
, sizeof (UINT64
));
1009 // Use CoreInternalAllocatePool() that will not update profile for this AllocatePool action.
1011 AllocInfoData
= NULL
;
1012 Status
= CoreInternalAllocatePool (
1013 EfiBootServicesData
,
1014 sizeof (*AllocInfoData
) + ActionStringSize
,
1015 (VOID
**) &AllocInfoData
1017 if (EFI_ERROR (Status
)) {
1018 return EFI_OUT_OF_RESOURCES
;
1020 ASSERT (AllocInfoData
!= NULL
);
1023 // Only update SequenceCount if and only if it is basic action.
1025 if (Action
== BasicAction
) {
1026 ContextData
->Context
.SequenceCount
++;
1029 AllocInfo
= &AllocInfoData
->AllocInfo
;
1030 AllocInfoData
->Signature
= MEMORY_PROFILE_ALLOC_INFO_SIGNATURE
;
1031 AllocInfo
->Header
.Signature
= MEMORY_PROFILE_ALLOC_INFO_SIGNATURE
;
1032 AllocInfo
->Header
.Length
= (UINT16
) (sizeof (MEMORY_PROFILE_ALLOC_INFO
) + ActionStringOccupiedSize
);
1033 AllocInfo
->Header
.Revision
= MEMORY_PROFILE_ALLOC_INFO_REVISION
;
1034 AllocInfo
->CallerAddress
= CallerAddress
;
1035 AllocInfo
->SequenceId
= ContextData
->Context
.SequenceCount
;
1036 AllocInfo
->Action
= Action
;
1037 AllocInfo
->MemoryType
= MemoryType
;
1038 AllocInfo
->Buffer
= (PHYSICAL_ADDRESS
) (UINTN
) Buffer
;
1039 AllocInfo
->Size
= Size
;
1040 if (ActionString
!= NULL
) {
1041 AllocInfo
->ActionStringOffset
= (UINT16
) sizeof (MEMORY_PROFILE_ALLOC_INFO
);
1042 AllocInfoData
->ActionString
= (CHAR8
*) (AllocInfoData
+ 1);
1043 CopyMem (AllocInfoData
->ActionString
, ActionString
, ActionStringSize
);
1045 AllocInfo
->ActionStringOffset
= 0;
1046 AllocInfoData
->ActionString
= NULL
;
1049 InsertTailList (DriverInfoData
->AllocInfoList
, &AllocInfoData
->Link
);
1051 Context
= &ContextData
->Context
;
1052 DriverInfo
= &DriverInfoData
->DriverInfo
;
1053 DriverInfo
->AllocRecordCount
++;
1056 // Update summary if and only if it is basic action.
1058 if (Action
== BasicAction
) {
1059 ProfileMemoryIndex
= GetProfileMemoryIndex (MemoryType
);
1061 DriverInfo
->CurrentUsage
+= Size
;
1062 if (DriverInfo
->PeakUsage
< DriverInfo
->CurrentUsage
) {
1063 DriverInfo
->PeakUsage
= DriverInfo
->CurrentUsage
;
1065 DriverInfo
->CurrentUsageByType
[ProfileMemoryIndex
] += Size
;
1066 if (DriverInfo
->PeakUsageByType
[ProfileMemoryIndex
] < DriverInfo
->CurrentUsageByType
[ProfileMemoryIndex
]) {
1067 DriverInfo
->PeakUsageByType
[ProfileMemoryIndex
] = DriverInfo
->CurrentUsageByType
[ProfileMemoryIndex
];
1070 Context
->CurrentTotalUsage
+= Size
;
1071 if (Context
->PeakTotalUsage
< Context
->CurrentTotalUsage
) {
1072 Context
->PeakTotalUsage
= Context
->CurrentTotalUsage
;
1074 Context
->CurrentTotalUsageByType
[ProfileMemoryIndex
] += Size
;
1075 if (Context
->PeakTotalUsageByType
[ProfileMemoryIndex
] < Context
->CurrentTotalUsageByType
[ProfileMemoryIndex
]) {
1076 Context
->PeakTotalUsageByType
[ProfileMemoryIndex
] = Context
->CurrentTotalUsageByType
[ProfileMemoryIndex
];
1084 Get memory profile alloc info from memory profile.
1086 @param DriverInfoData Driver info.
1087 @param BasicAction This Free basic action.
1088 @param Size Buffer size.
1089 @param Buffer Buffer address.
1091 @return Pointer to memory profile alloc info.
1094 MEMORY_PROFILE_ALLOC_INFO_DATA
*
1095 GetMemoryProfileAllocInfoFromAddress (
1096 IN MEMORY_PROFILE_DRIVER_INFO_DATA
*DriverInfoData
,
1097 IN MEMORY_PROFILE_ACTION BasicAction
,
1102 LIST_ENTRY
*AllocInfoList
;
1103 LIST_ENTRY
*AllocLink
;
1104 MEMORY_PROFILE_ALLOC_INFO
*AllocInfo
;
1105 MEMORY_PROFILE_ALLOC_INFO_DATA
*AllocInfoData
;
1107 AllocInfoList
= DriverInfoData
->AllocInfoList
;
1109 for (AllocLink
= AllocInfoList
->ForwardLink
;
1110 AllocLink
!= AllocInfoList
;
1111 AllocLink
= AllocLink
->ForwardLink
) {
1112 AllocInfoData
= CR (
1114 MEMORY_PROFILE_ALLOC_INFO_DATA
,
1116 MEMORY_PROFILE_ALLOC_INFO_SIGNATURE
1118 AllocInfo
= &AllocInfoData
->AllocInfo
;
1119 if ((AllocInfo
->Action
& MEMORY_PROFILE_ACTION_BASIC_MASK
) != BasicAction
) {
1122 switch (BasicAction
) {
1123 case MemoryProfileActionAllocatePages
:
1124 if ((AllocInfo
->Buffer
<= (PHYSICAL_ADDRESS
) (UINTN
) Buffer
) &&
1125 ((AllocInfo
->Buffer
+ AllocInfo
->Size
) >= ((PHYSICAL_ADDRESS
) (UINTN
) Buffer
+ Size
))) {
1126 return AllocInfoData
;
1129 case MemoryProfileActionAllocatePool
:
1130 if (AllocInfo
->Buffer
== (PHYSICAL_ADDRESS
) (UINTN
) Buffer
) {
1131 return AllocInfoData
;
1144 Update memory profile Free information.
1146 @param CallerAddress Address of caller who call Free.
1147 @param Action This Free action.
1148 @param Size Buffer size.
1149 @param Buffer Buffer address.
1151 @return EFI_SUCCESS Memory profile is updated.
1152 @return EFI_UNSUPPORTED Memory profile is unsupported.
1153 @return EFI_NOT_FOUND No matched allocate info found for free action.
1157 CoreUpdateProfileFree (
1158 IN PHYSICAL_ADDRESS CallerAddress
,
1159 IN MEMORY_PROFILE_ACTION Action
,
1164 MEMORY_PROFILE_CONTEXT
*Context
;
1165 MEMORY_PROFILE_DRIVER_INFO
*DriverInfo
;
1166 MEMORY_PROFILE_ALLOC_INFO
*AllocInfo
;
1167 MEMORY_PROFILE_CONTEXT_DATA
*ContextData
;
1168 MEMORY_PROFILE_DRIVER_INFO_DATA
*DriverInfoData
;
1169 LIST_ENTRY
*DriverLink
;
1170 LIST_ENTRY
*DriverInfoList
;
1171 MEMORY_PROFILE_DRIVER_INFO_DATA
*ThisDriverInfoData
;
1172 MEMORY_PROFILE_ALLOC_INFO_DATA
*AllocInfoData
;
1173 UINTN ProfileMemoryIndex
;
1174 MEMORY_PROFILE_ACTION BasicAction
;
1177 BasicAction
= Action
& MEMORY_PROFILE_ACTION_BASIC_MASK
;
1179 ContextData
= GetMemoryProfileContext ();
1180 if (ContextData
== NULL
) {
1181 return EFI_UNSUPPORTED
;
1184 DriverInfoData
= GetMemoryProfileDriverInfoFromAddress (ContextData
, CallerAddress
);
1187 // Do not return if DriverInfoData == NULL here,
1188 // because driver A might free memory allocated by driver B.
1192 // Need use do-while loop to find all possible records,
1193 // because one address might be recorded multiple times.
1196 AllocInfoData
= NULL
;
1198 if (DriverInfoData
!= NULL
) {
1199 switch (BasicAction
) {
1200 case MemoryProfileActionFreePages
:
1201 AllocInfoData
= GetMemoryProfileAllocInfoFromAddress (DriverInfoData
, MemoryProfileActionAllocatePages
, Size
, Buffer
);
1203 case MemoryProfileActionFreePool
:
1204 AllocInfoData
= GetMemoryProfileAllocInfoFromAddress (DriverInfoData
, MemoryProfileActionAllocatePool
, 0, Buffer
);
1208 AllocInfoData
= NULL
;
1212 if (AllocInfoData
== NULL
) {
1214 // Legal case, because driver A might free memory allocated by driver B, by some protocol.
1216 DriverInfoList
= ContextData
->DriverInfoList
;
1218 for (DriverLink
= DriverInfoList
->ForwardLink
;
1219 DriverLink
!= DriverInfoList
;
1220 DriverLink
= DriverLink
->ForwardLink
) {
1221 ThisDriverInfoData
= CR (
1223 MEMORY_PROFILE_DRIVER_INFO_DATA
,
1225 MEMORY_PROFILE_DRIVER_INFO_SIGNATURE
1227 switch (BasicAction
) {
1228 case MemoryProfileActionFreePages
:
1229 AllocInfoData
= GetMemoryProfileAllocInfoFromAddress (ThisDriverInfoData
, MemoryProfileActionAllocatePages
, Size
, Buffer
);
1231 case MemoryProfileActionFreePool
:
1232 AllocInfoData
= GetMemoryProfileAllocInfoFromAddress (ThisDriverInfoData
, MemoryProfileActionAllocatePool
, 0, Buffer
);
1236 AllocInfoData
= NULL
;
1239 if (AllocInfoData
!= NULL
) {
1240 DriverInfoData
= ThisDriverInfoData
;
1245 if (AllocInfoData
== NULL
) {
1247 // If (!Found), no matched allocate info is found for this free action.
1248 // It is because the specified memory type allocate actions have been filtered by
1249 // CoreNeedRecordProfile(), but free actions may have no memory type information,
1250 // they can not be filtered by CoreNeedRecordProfile(). Then, they will be
1253 // If (Found), it is normal exit path.
1254 return (Found
? EFI_SUCCESS
: EFI_NOT_FOUND
);
1258 ASSERT (DriverInfoData
!= NULL
);
1259 ASSERT (AllocInfoData
!= NULL
);
1263 Context
= &ContextData
->Context
;
1264 DriverInfo
= &DriverInfoData
->DriverInfo
;
1265 AllocInfo
= &AllocInfoData
->AllocInfo
;
1267 DriverInfo
->AllocRecordCount
--;
1269 // Update summary if and only if it is basic action.
1271 if (AllocInfo
->Action
== (AllocInfo
->Action
& MEMORY_PROFILE_ACTION_BASIC_MASK
)) {
1272 ProfileMemoryIndex
= GetProfileMemoryIndex (AllocInfo
->MemoryType
);
1274 Context
->CurrentTotalUsage
-= AllocInfo
->Size
;
1275 Context
->CurrentTotalUsageByType
[ProfileMemoryIndex
] -= AllocInfo
->Size
;
1277 DriverInfo
->CurrentUsage
-= AllocInfo
->Size
;
1278 DriverInfo
->CurrentUsageByType
[ProfileMemoryIndex
] -= AllocInfo
->Size
;
1281 RemoveEntryList (&AllocInfoData
->Link
);
1283 if (BasicAction
== MemoryProfileActionFreePages
) {
1284 if (AllocInfo
->Buffer
!= (PHYSICAL_ADDRESS
) (UINTN
) Buffer
) {
1285 CoreUpdateProfileAllocate (
1286 AllocInfo
->CallerAddress
,
1288 AllocInfo
->MemoryType
,
1289 (UINTN
) ((PHYSICAL_ADDRESS
) (UINTN
) Buffer
- AllocInfo
->Buffer
),
1290 (VOID
*) (UINTN
) AllocInfo
->Buffer
,
1291 AllocInfoData
->ActionString
1294 if (AllocInfo
->Buffer
+ AllocInfo
->Size
!= ((PHYSICAL_ADDRESS
) (UINTN
) Buffer
+ Size
)) {
1295 CoreUpdateProfileAllocate (
1296 AllocInfo
->CallerAddress
,
1298 AllocInfo
->MemoryType
,
1299 (UINTN
) ((AllocInfo
->Buffer
+ AllocInfo
->Size
) - ((PHYSICAL_ADDRESS
) (UINTN
) Buffer
+ Size
)),
1300 (VOID
*) ((UINTN
) Buffer
+ Size
),
1301 AllocInfoData
->ActionString
1307 // Use CoreInternalFreePool() that will not update profile for this FreePool action.
1309 CoreInternalFreePool (AllocInfoData
, NULL
);
1314 Update memory profile information.
1316 @param CallerAddress Address of caller who call Allocate or Free.
1317 @param Action This Allocate or Free action.
1318 @param MemoryType Memory type.
1319 EfiMaxMemoryType means the MemoryType is unknown.
1320 @param Size Buffer size.
1321 @param Buffer Buffer address.
1322 @param ActionString String for memory profile action.
1323 Only needed for user defined allocate action.
1325 @return EFI_SUCCESS Memory profile is updated.
1326 @return EFI_UNSUPPORTED Memory profile is unsupported,
1327 or memory profile for the image is not required,
1328 or memory profile for the memory type is not required.
1329 @return EFI_ACCESS_DENIED It is during memory profile data getting.
1330 @return EFI_ABORTED Memory profile recording is not enabled.
1331 @return EFI_OUT_OF_RESOURCES No enough resource to update memory profile for allocate action.
1332 @return EFI_NOT_FOUND No matched allocate info found for free action.
1338 IN PHYSICAL_ADDRESS CallerAddress
,
1339 IN MEMORY_PROFILE_ACTION Action
,
1340 IN EFI_MEMORY_TYPE MemoryType
,
1341 IN UINTN Size
, // Valid for AllocatePages/FreePages/AllocatePool
1343 IN CHAR8
*ActionString OPTIONAL
1347 MEMORY_PROFILE_CONTEXT_DATA
*ContextData
;
1348 MEMORY_PROFILE_ACTION BasicAction
;
1350 if (!IS_UEFI_MEMORY_PROFILE_ENABLED
) {
1351 return EFI_UNSUPPORTED
;
1354 if (mMemoryProfileGettingStatus
) {
1355 return EFI_ACCESS_DENIED
;
1358 if (!mMemoryProfileRecordingEnable
) {
1363 // Get the basic action to know how to process the record
1365 BasicAction
= Action
& MEMORY_PROFILE_ACTION_BASIC_MASK
;
1368 // EfiMaxMemoryType means the MemoryType is unknown.
1370 if (MemoryType
!= EfiMaxMemoryType
) {
1372 // Only record limited MemoryType.
1374 if (!CoreNeedRecordProfile (MemoryType
)) {
1375 return EFI_UNSUPPORTED
;
1379 ContextData
= GetMemoryProfileContext ();
1380 if (ContextData
== NULL
) {
1381 return EFI_UNSUPPORTED
;
1384 CoreAcquireMemoryProfileLock ();
1385 switch (BasicAction
) {
1386 case MemoryProfileActionAllocatePages
:
1387 Status
= CoreUpdateProfileAllocate (CallerAddress
, Action
, MemoryType
, Size
, Buffer
, ActionString
);
1389 case MemoryProfileActionFreePages
:
1390 Status
= CoreUpdateProfileFree (CallerAddress
, Action
, Size
, Buffer
);
1392 case MemoryProfileActionAllocatePool
:
1393 Status
= CoreUpdateProfileAllocate (CallerAddress
, Action
, MemoryType
, Size
, Buffer
, ActionString
);
1395 case MemoryProfileActionFreePool
:
1396 Status
= CoreUpdateProfileFree (CallerAddress
, Action
, 0, Buffer
);
1400 Status
= EFI_UNSUPPORTED
;
1403 CoreReleaseMemoryProfileLock ();
1408 ////////////////////
1411 Get memory profile data size.
1413 @return Memory profile data size.
1417 MemoryProfileGetDataSize (
1421 MEMORY_PROFILE_CONTEXT_DATA
*ContextData
;
1422 MEMORY_PROFILE_DRIVER_INFO_DATA
*DriverInfoData
;
1423 MEMORY_PROFILE_ALLOC_INFO_DATA
*AllocInfoData
;
1424 LIST_ENTRY
*DriverInfoList
;
1425 LIST_ENTRY
*DriverLink
;
1426 LIST_ENTRY
*AllocInfoList
;
1427 LIST_ENTRY
*AllocLink
;
1431 ContextData
= GetMemoryProfileContext ();
1432 if (ContextData
== NULL
) {
1436 TotalSize
= sizeof (MEMORY_PROFILE_CONTEXT
);
1438 DriverInfoList
= ContextData
->DriverInfoList
;
1439 for (DriverLink
= DriverInfoList
->ForwardLink
;
1440 DriverLink
!= DriverInfoList
;
1441 DriverLink
= DriverLink
->ForwardLink
) {
1442 DriverInfoData
= CR (
1444 MEMORY_PROFILE_DRIVER_INFO_DATA
,
1446 MEMORY_PROFILE_DRIVER_INFO_SIGNATURE
1448 TotalSize
+= DriverInfoData
->DriverInfo
.Header
.Length
;
1450 AllocInfoList
= DriverInfoData
->AllocInfoList
;
1451 for (AllocLink
= AllocInfoList
->ForwardLink
;
1452 AllocLink
!= AllocInfoList
;
1453 AllocLink
= AllocLink
->ForwardLink
) {
1454 AllocInfoData
= CR (
1456 MEMORY_PROFILE_ALLOC_INFO_DATA
,
1458 MEMORY_PROFILE_ALLOC_INFO_SIGNATURE
1460 TotalSize
+= AllocInfoData
->AllocInfo
.Header
.Length
;
1468 Copy memory profile data.
1470 @param ProfileBuffer The buffer to hold memory profile data.
1474 MemoryProfileCopyData (
1475 IN VOID
*ProfileBuffer
1478 MEMORY_PROFILE_CONTEXT
*Context
;
1479 MEMORY_PROFILE_DRIVER_INFO
*DriverInfo
;
1480 MEMORY_PROFILE_ALLOC_INFO
*AllocInfo
;
1481 MEMORY_PROFILE_CONTEXT_DATA
*ContextData
;
1482 MEMORY_PROFILE_DRIVER_INFO_DATA
*DriverInfoData
;
1483 MEMORY_PROFILE_ALLOC_INFO_DATA
*AllocInfoData
;
1484 LIST_ENTRY
*DriverInfoList
;
1485 LIST_ENTRY
*DriverLink
;
1486 LIST_ENTRY
*AllocInfoList
;
1487 LIST_ENTRY
*AllocLink
;
1489 UINTN ActionStringSize
;
1491 ContextData
= GetMemoryProfileContext ();
1492 if (ContextData
== NULL
) {
1496 Context
= ProfileBuffer
;
1497 CopyMem (Context
, &ContextData
->Context
, sizeof (MEMORY_PROFILE_CONTEXT
));
1498 DriverInfo
= (MEMORY_PROFILE_DRIVER_INFO
*) (Context
+ 1);
1500 DriverInfoList
= ContextData
->DriverInfoList
;
1501 for (DriverLink
= DriverInfoList
->ForwardLink
;
1502 DriverLink
!= DriverInfoList
;
1503 DriverLink
= DriverLink
->ForwardLink
) {
1504 DriverInfoData
= CR (
1506 MEMORY_PROFILE_DRIVER_INFO_DATA
,
1508 MEMORY_PROFILE_DRIVER_INFO_SIGNATURE
1510 CopyMem (DriverInfo
, &DriverInfoData
->DriverInfo
, sizeof (MEMORY_PROFILE_DRIVER_INFO
));
1511 if (DriverInfo
->PdbStringOffset
!= 0) {
1512 PdbSize
= AsciiStrSize (DriverInfoData
->PdbString
);
1513 CopyMem ((VOID
*) ((UINTN
) DriverInfo
+ DriverInfo
->PdbStringOffset
), DriverInfoData
->PdbString
, PdbSize
);
1515 AllocInfo
= (MEMORY_PROFILE_ALLOC_INFO
*) ((UINTN
) DriverInfo
+ DriverInfo
->Header
.Length
);
1517 AllocInfoList
= DriverInfoData
->AllocInfoList
;
1518 for (AllocLink
= AllocInfoList
->ForwardLink
;
1519 AllocLink
!= AllocInfoList
;
1520 AllocLink
= AllocLink
->ForwardLink
) {
1521 AllocInfoData
= CR (
1523 MEMORY_PROFILE_ALLOC_INFO_DATA
,
1525 MEMORY_PROFILE_ALLOC_INFO_SIGNATURE
1527 CopyMem (AllocInfo
, &AllocInfoData
->AllocInfo
, sizeof (MEMORY_PROFILE_ALLOC_INFO
));
1528 if (AllocInfo
->ActionStringOffset
!= 0) {
1529 ActionStringSize
= AsciiStrSize (AllocInfoData
->ActionString
);
1530 CopyMem ((VOID
*) ((UINTN
) AllocInfo
+ AllocInfo
->ActionStringOffset
), AllocInfoData
->ActionString
, ActionStringSize
);
1532 AllocInfo
= (MEMORY_PROFILE_ALLOC_INFO
*) ((UINTN
) AllocInfo
+ AllocInfo
->Header
.Length
);
1535 DriverInfo
= (MEMORY_PROFILE_DRIVER_INFO
*) AllocInfo
;
1540 Get memory profile data.
1542 @param[in] This The EDKII_MEMORY_PROFILE_PROTOCOL instance.
1543 @param[in, out] ProfileSize On entry, points to the size in bytes of the ProfileBuffer.
1544 On return, points to the size of the data returned in ProfileBuffer.
1545 @param[out] ProfileBuffer Profile buffer.
1547 @return EFI_SUCCESS Get the memory profile data successfully.
1548 @return EFI_UNSUPPORTED Memory profile is unsupported.
1549 @return EFI_BUFFER_TO_SMALL The ProfileSize is too small for the resulting data.
1550 ProfileSize is updated with the size required.
1555 ProfileProtocolGetData (
1556 IN EDKII_MEMORY_PROFILE_PROTOCOL
*This
,
1557 IN OUT UINT64
*ProfileSize
,
1558 OUT VOID
*ProfileBuffer
1562 MEMORY_PROFILE_CONTEXT_DATA
*ContextData
;
1563 BOOLEAN MemoryProfileGettingStatus
;
1565 ContextData
= GetMemoryProfileContext ();
1566 if (ContextData
== NULL
) {
1567 return EFI_UNSUPPORTED
;
1570 MemoryProfileGettingStatus
= mMemoryProfileGettingStatus
;
1571 mMemoryProfileGettingStatus
= TRUE
;
1573 Size
= MemoryProfileGetDataSize ();
1575 if (*ProfileSize
< Size
) {
1576 *ProfileSize
= Size
;
1577 mMemoryProfileGettingStatus
= MemoryProfileGettingStatus
;
1578 return EFI_BUFFER_TOO_SMALL
;
1581 *ProfileSize
= Size
;
1582 MemoryProfileCopyData (ProfileBuffer
);
1584 mMemoryProfileGettingStatus
= MemoryProfileGettingStatus
;
1589 Register image to memory profile.
1591 @param[in] This The EDKII_MEMORY_PROFILE_PROTOCOL instance.
1592 @param[in] FilePath File path of the image.
1593 @param[in] ImageBase Image base address.
1594 @param[in] ImageSize Image size.
1595 @param[in] FileType File type of the image.
1597 @return EFI_SUCCESS Register successfully.
1598 @return EFI_UNSUPPORTED Memory profile is unsupported,
1599 or memory profile for the image is not required.
1600 @return EFI_OUT_OF_RESOURCES No enough resource for this register.
1605 ProfileProtocolRegisterImage (
1606 IN EDKII_MEMORY_PROFILE_PROTOCOL
*This
,
1607 IN EFI_DEVICE_PATH_PROTOCOL
*FilePath
,
1608 IN PHYSICAL_ADDRESS ImageBase
,
1609 IN UINT64 ImageSize
,
1610 IN EFI_FV_FILETYPE FileType
1614 LOADED_IMAGE_PRIVATE_DATA DriverEntry
;
1615 VOID
*EntryPointInImage
;
1617 ZeroMem (&DriverEntry
, sizeof (DriverEntry
));
1618 DriverEntry
.Info
.FilePath
= FilePath
;
1619 DriverEntry
.ImageContext
.ImageAddress
= ImageBase
;
1620 DriverEntry
.ImageContext
.ImageSize
= ImageSize
;
1621 Status
= InternalPeCoffGetEntryPoint ((VOID
*) (UINTN
) ImageBase
, &EntryPointInImage
);
1622 ASSERT_EFI_ERROR (Status
);
1623 DriverEntry
.ImageContext
.EntryPoint
= (PHYSICAL_ADDRESS
) (UINTN
) EntryPointInImage
;
1624 DriverEntry
.ImageContext
.ImageType
= InternalPeCoffGetSubsystem ((VOID
*) (UINTN
) ImageBase
);
1626 return RegisterMemoryProfileImage (&DriverEntry
, FileType
);
1630 Unregister image from memory profile.
1632 @param[in] This The EDKII_MEMORY_PROFILE_PROTOCOL instance.
1633 @param[in] FilePath File path of the image.
1634 @param[in] ImageBase Image base address.
1635 @param[in] ImageSize Image size.
1637 @return EFI_SUCCESS Unregister successfully.
1638 @return EFI_UNSUPPORTED Memory profile is unsupported,
1639 or memory profile for the image is not required.
1640 @return EFI_NOT_FOUND The image is not found.
1645 ProfileProtocolUnregisterImage (
1646 IN EDKII_MEMORY_PROFILE_PROTOCOL
*This
,
1647 IN EFI_DEVICE_PATH_PROTOCOL
*FilePath
,
1648 IN PHYSICAL_ADDRESS ImageBase
,
1653 LOADED_IMAGE_PRIVATE_DATA DriverEntry
;
1654 VOID
*EntryPointInImage
;
1656 ZeroMem (&DriverEntry
, sizeof (DriverEntry
));
1657 DriverEntry
.Info
.FilePath
= FilePath
;
1658 DriverEntry
.ImageContext
.ImageAddress
= ImageBase
;
1659 DriverEntry
.ImageContext
.ImageSize
= ImageSize
;
1660 Status
= InternalPeCoffGetEntryPoint ((VOID
*) (UINTN
) ImageBase
, &EntryPointInImage
);
1661 ASSERT_EFI_ERROR (Status
);
1662 DriverEntry
.ImageContext
.EntryPoint
= (PHYSICAL_ADDRESS
) (UINTN
) EntryPointInImage
;
1664 return UnregisterMemoryProfileImage (&DriverEntry
);
1668 Get memory profile recording state.
1670 @param[in] This The EDKII_MEMORY_PROFILE_PROTOCOL instance.
1671 @param[out] RecordingState Recording state.
1673 @return EFI_SUCCESS Memory profile recording state is returned.
1674 @return EFI_UNSUPPORTED Memory profile is unsupported.
1675 @return EFI_INVALID_PARAMETER RecordingState is NULL.
1680 ProfileProtocolGetRecordingState (
1681 IN EDKII_MEMORY_PROFILE_PROTOCOL
*This
,
1682 OUT BOOLEAN
*RecordingState
1685 MEMORY_PROFILE_CONTEXT_DATA
*ContextData
;
1687 ContextData
= GetMemoryProfileContext ();
1688 if (ContextData
== NULL
) {
1689 return EFI_UNSUPPORTED
;
1692 if (RecordingState
== NULL
) {
1693 return EFI_INVALID_PARAMETER
;
1695 *RecordingState
= mMemoryProfileRecordingEnable
;
1700 Set memory profile recording state.
1702 @param[in] This The EDKII_MEMORY_PROFILE_PROTOCOL instance.
1703 @param[in] RecordingState Recording state.
1705 @return EFI_SUCCESS Set memory profile recording state successfully.
1706 @return EFI_UNSUPPORTED Memory profile is unsupported.
1711 ProfileProtocolSetRecordingState (
1712 IN EDKII_MEMORY_PROFILE_PROTOCOL
*This
,
1713 IN BOOLEAN RecordingState
1716 MEMORY_PROFILE_CONTEXT_DATA
*ContextData
;
1718 ContextData
= GetMemoryProfileContext ();
1719 if (ContextData
== NULL
) {
1720 return EFI_UNSUPPORTED
;
1723 mMemoryProfileRecordingEnable
= RecordingState
;
1728 Record memory profile of multilevel caller.
1730 @param[in] This The EDKII_MEMORY_PROFILE_PROTOCOL instance.
1731 @param[in] CallerAddress Address of caller.
1732 @param[in] Action Memory profile action.
1733 @param[in] MemoryType Memory type.
1734 EfiMaxMemoryType means the MemoryType is unknown.
1735 @param[in] Buffer Buffer address.
1736 @param[in] Size Buffer size.
1737 @param[in] ActionString String for memory profile action.
1738 Only needed for user defined allocate action.
1740 @return EFI_SUCCESS Memory profile is updated.
1741 @return EFI_UNSUPPORTED Memory profile is unsupported,
1742 or memory profile for the image is not required,
1743 or memory profile for the memory type is not required.
1744 @return EFI_ACCESS_DENIED It is during memory profile data getting.
1745 @return EFI_ABORTED Memory profile recording is not enabled.
1746 @return EFI_OUT_OF_RESOURCES No enough resource to update memory profile for allocate action.
1747 @return EFI_NOT_FOUND No matched allocate info found for free action.
1752 ProfileProtocolRecord (
1753 IN EDKII_MEMORY_PROFILE_PROTOCOL
*This
,
1754 IN PHYSICAL_ADDRESS CallerAddress
,
1755 IN MEMORY_PROFILE_ACTION Action
,
1756 IN EFI_MEMORY_TYPE MemoryType
,
1759 IN CHAR8
*ActionString OPTIONAL
1762 return CoreUpdateProfile (CallerAddress
, Action
, MemoryType
, Size
, Buffer
, ActionString
);
1765 ////////////////////