2 Support routines for UEFI memory profile.
4 Copyright (c) 2014 - 2016, Intel Corporation. All rights reserved.<BR>
5 This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php.
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
18 #define IS_UEFI_MEMORY_PROFILE_ENABLED ((PcdGet8 (PcdMemoryProfilePropertyMask) & BIT0) != 0)
20 #define GET_OCCUPIED_SIZE(ActualSize, Alignment) \
21 ((ActualSize) + (((Alignment) - ((ActualSize) & ((Alignment) - 1))) & ((Alignment) - 1)))
25 MEMORY_PROFILE_CONTEXT Context
;
26 LIST_ENTRY
*DriverInfoList
;
27 } MEMORY_PROFILE_CONTEXT_DATA
;
31 MEMORY_PROFILE_DRIVER_INFO DriverInfo
;
32 LIST_ENTRY
*AllocInfoList
;
35 } MEMORY_PROFILE_DRIVER_INFO_DATA
;
39 MEMORY_PROFILE_ALLOC_INFO AllocInfo
;
42 } MEMORY_PROFILE_ALLOC_INFO_DATA
;
45 GLOBAL_REMOVE_IF_UNREFERENCED LIST_ENTRY mImageQueue
= INITIALIZE_LIST_HEAD_VARIABLE (mImageQueue
);
46 GLOBAL_REMOVE_IF_UNREFERENCED MEMORY_PROFILE_CONTEXT_DATA mMemoryProfileContext
= {
47 MEMORY_PROFILE_CONTEXT_SIGNATURE
,
50 MEMORY_PROFILE_CONTEXT_SIGNATURE
,
51 sizeof (MEMORY_PROFILE_CONTEXT
),
52 MEMORY_PROFILE_CONTEXT_REVISION
64 GLOBAL_REMOVE_IF_UNREFERENCED MEMORY_PROFILE_CONTEXT_DATA
*mMemoryProfileContextPtr
= NULL
;
66 EFI_LOCK mMemoryProfileLock
= EFI_INITIALIZE_LOCK_VARIABLE (TPL_NOTIFY
);
67 BOOLEAN mMemoryProfileGettingStatus
= FALSE
;
68 BOOLEAN mMemoryProfileRecordingEnable
= MEMORY_PROFILE_RECORDING_DISABLE
;
69 EFI_DEVICE_PATH_PROTOCOL
*mMemoryProfileDriverPath
;
70 UINTN mMemoryProfileDriverPathSize
;
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 EDKII_MEMORY_PROFILE_PROTOCOL mProfileProtocol
= {
213 ProfileProtocolGetData
,
214 ProfileProtocolRegisterImage
,
215 ProfileProtocolUnregisterImage
,
216 ProfileProtocolGetRecordingState
,
217 ProfileProtocolSetRecordingState
,
218 ProfileProtocolRecord
,
222 Acquire lock on mMemoryProfileLock.
225 CoreAcquireMemoryProfileLock (
229 CoreAcquireLock (&mMemoryProfileLock
);
233 Release lock on mMemoryProfileLock.
236 CoreReleaseMemoryProfileLock (
240 CoreReleaseLock (&mMemoryProfileLock
);
244 Return memory profile context.
246 @return Memory profile context.
249 MEMORY_PROFILE_CONTEXT_DATA
*
250 GetMemoryProfileContext (
254 return mMemoryProfileContextPtr
;
258 Retrieves the magic value from the PE/COFF header.
260 @param Hdr The buffer in which to return the PE32, PE32+, or TE header.
262 @return EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC - Image is PE32
263 @return EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC - Image is PE32+
267 InternalPeCoffGetPeHeaderMagicValue (
268 IN EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION Hdr
272 // NOTE: Some versions of Linux ELILO for Itanium have an incorrect magic value
273 // in the PE/COFF Header. If the MachineType is Itanium(IA64) and the
274 // Magic value in the OptionalHeader is EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
275 // then override the returned value to EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC
277 if (Hdr
.Pe32
->FileHeader
.Machine
== IMAGE_FILE_MACHINE_IA64
&& Hdr
.Pe32
->OptionalHeader
.Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
278 return EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC
;
281 // Return the magic value from the PC/COFF Optional Header
283 return Hdr
.Pe32
->OptionalHeader
.Magic
;
287 Retrieves and returns the Subsystem of a PE/COFF image that has been loaded into system memory.
288 If Pe32Data is NULL, then ASSERT().
290 @param Pe32Data The pointer to the PE/COFF image that is loaded in system memory.
292 @return The Subsystem of the PE/COFF image.
296 InternalPeCoffGetSubsystem (
300 EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION Hdr
;
301 EFI_IMAGE_DOS_HEADER
*DosHdr
;
304 ASSERT (Pe32Data
!= NULL
);
306 DosHdr
= (EFI_IMAGE_DOS_HEADER
*) Pe32Data
;
307 if (DosHdr
->e_magic
== EFI_IMAGE_DOS_SIGNATURE
) {
309 // DOS image header is present, so read the PE header after the DOS image header.
311 Hdr
.Pe32
= (EFI_IMAGE_NT_HEADERS32
*) ((UINTN
) Pe32Data
+ (UINTN
) ((DosHdr
->e_lfanew
) & 0x0ffff));
314 // DOS image header is not present, so PE header is at the image base.
316 Hdr
.Pe32
= (EFI_IMAGE_NT_HEADERS32
*) Pe32Data
;
319 if (Hdr
.Te
->Signature
== EFI_TE_IMAGE_HEADER_SIGNATURE
) {
320 return Hdr
.Te
->Subsystem
;
321 } else if (Hdr
.Pe32
->Signature
== EFI_IMAGE_NT_SIGNATURE
) {
322 Magic
= InternalPeCoffGetPeHeaderMagicValue (Hdr
);
323 if (Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
324 return Hdr
.Pe32
->OptionalHeader
.Subsystem
;
325 } else if (Magic
== EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC
) {
326 return Hdr
.Pe32Plus
->OptionalHeader
.Subsystem
;
334 Retrieves and returns a pointer to the entry point to a PE/COFF image that has been loaded
335 into system memory with the PE/COFF Loader Library functions.
337 Retrieves the entry point to the PE/COFF image specified by Pe32Data and returns this entry
338 point in EntryPoint. If the entry point could not be retrieved from the PE/COFF image, then
339 return RETURN_INVALID_PARAMETER. Otherwise return RETURN_SUCCESS.
340 If Pe32Data is NULL, then ASSERT().
341 If EntryPoint is NULL, then ASSERT().
343 @param Pe32Data The pointer to the PE/COFF image that is loaded in system memory.
344 @param EntryPoint The pointer to entry point to the PE/COFF image to return.
346 @retval RETURN_SUCCESS EntryPoint was returned.
347 @retval RETURN_INVALID_PARAMETER The entry point could not be found in the PE/COFF image.
351 InternalPeCoffGetEntryPoint (
353 OUT VOID
**EntryPoint
356 EFI_IMAGE_DOS_HEADER
*DosHdr
;
357 EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION Hdr
;
359 ASSERT (Pe32Data
!= NULL
);
360 ASSERT (EntryPoint
!= NULL
);
362 DosHdr
= (EFI_IMAGE_DOS_HEADER
*) Pe32Data
;
363 if (DosHdr
->e_magic
== EFI_IMAGE_DOS_SIGNATURE
) {
365 // DOS image header is present, so read the PE header after the DOS image header.
367 Hdr
.Pe32
= (EFI_IMAGE_NT_HEADERS32
*) ((UINTN
) Pe32Data
+ (UINTN
) ((DosHdr
->e_lfanew
) & 0x0ffff));
370 // DOS image header is not present, so PE header is at the image base.
372 Hdr
.Pe32
= (EFI_IMAGE_NT_HEADERS32
*) Pe32Data
;
376 // Calculate the entry point relative to the start of the image.
377 // AddressOfEntryPoint is common for PE32 & PE32+
379 if (Hdr
.Te
->Signature
== EFI_TE_IMAGE_HEADER_SIGNATURE
) {
380 *EntryPoint
= (VOID
*) ((UINTN
) Pe32Data
+ (UINTN
) (Hdr
.Te
->AddressOfEntryPoint
& 0x0ffffffff) + sizeof (EFI_TE_IMAGE_HEADER
) - Hdr
.Te
->StrippedSize
);
381 return RETURN_SUCCESS
;
382 } else if (Hdr
.Pe32
->Signature
== EFI_IMAGE_NT_SIGNATURE
) {
383 *EntryPoint
= (VOID
*) ((UINTN
) Pe32Data
+ (UINTN
) (Hdr
.Pe32
->OptionalHeader
.AddressOfEntryPoint
& 0x0ffffffff));
384 return RETURN_SUCCESS
;
387 return RETURN_UNSUPPORTED
;
393 @param ContextData Memory profile context.
394 @param FileName File name of the image.
395 @param ImageBase Image base address.
396 @param ImageSize Image size.
397 @param EntryPoint Entry point of the image.
398 @param ImageSubsystem Image subsystem of the image.
399 @param FileType File type of the image.
401 @return Pointer to memory profile driver info.
404 MEMORY_PROFILE_DRIVER_INFO_DATA
*
406 IN MEMORY_PROFILE_CONTEXT_DATA
*ContextData
,
407 IN EFI_GUID
*FileName
,
408 IN PHYSICAL_ADDRESS ImageBase
,
410 IN PHYSICAL_ADDRESS EntryPoint
,
411 IN UINT16 ImageSubsystem
,
412 IN EFI_FV_FILETYPE FileType
416 MEMORY_PROFILE_DRIVER_INFO
*DriverInfo
;
417 MEMORY_PROFILE_DRIVER_INFO_DATA
*DriverInfoData
;
418 VOID
*EntryPointInImage
;
421 UINTN PdbOccupiedSize
;
426 if (ImageBase
!= 0) {
427 PdbString
= PeCoffLoaderGetPdbPointer ((VOID
*) (UINTN
) ImageBase
);
428 if (PdbString
!= NULL
) {
429 PdbSize
= AsciiStrSize (PdbString
);
430 PdbOccupiedSize
= GET_OCCUPIED_SIZE (PdbSize
, sizeof (UINT64
));
435 // Use CoreInternalAllocatePool() that will not update profile for this AllocatePool action.
437 Status
= CoreInternalAllocatePool (
439 sizeof (*DriverInfoData
) + sizeof (LIST_ENTRY
) + PdbSize
,
440 (VOID
**) &DriverInfoData
442 if (EFI_ERROR (Status
)) {
446 ZeroMem (DriverInfoData
, sizeof (*DriverInfoData
));
448 DriverInfo
= &DriverInfoData
->DriverInfo
;
449 DriverInfoData
->Signature
= MEMORY_PROFILE_DRIVER_INFO_SIGNATURE
;
450 DriverInfo
->Header
.Signature
= MEMORY_PROFILE_DRIVER_INFO_SIGNATURE
;
451 DriverInfo
->Header
.Length
= (UINT16
) (sizeof (MEMORY_PROFILE_DRIVER_INFO
) + PdbOccupiedSize
);
452 DriverInfo
->Header
.Revision
= MEMORY_PROFILE_DRIVER_INFO_REVISION
;
453 if (FileName
!= NULL
) {
454 CopyMem (&DriverInfo
->FileName
, FileName
, sizeof (EFI_GUID
));
456 DriverInfo
->ImageBase
= ImageBase
;
457 DriverInfo
->ImageSize
= ImageSize
;
458 DriverInfo
->EntryPoint
= EntryPoint
;
459 DriverInfo
->ImageSubsystem
= ImageSubsystem
;
460 if ((EntryPoint
!= 0) && ((EntryPoint
< ImageBase
) || (EntryPoint
>= (ImageBase
+ ImageSize
)))) {
462 // If the EntryPoint is not in the range of image buffer, it should come from emulation environment.
463 // So patch ImageBuffer here to align the EntryPoint.
465 Status
= InternalPeCoffGetEntryPoint ((VOID
*) (UINTN
) ImageBase
, &EntryPointInImage
);
466 ASSERT_EFI_ERROR (Status
);
467 DriverInfo
->ImageBase
= ImageBase
+ EntryPoint
- (PHYSICAL_ADDRESS
) (UINTN
) EntryPointInImage
;
469 DriverInfo
->FileType
= FileType
;
470 DriverInfoData
->AllocInfoList
= (LIST_ENTRY
*) (DriverInfoData
+ 1);
471 InitializeListHead (DriverInfoData
->AllocInfoList
);
472 DriverInfo
->CurrentUsage
= 0;
473 DriverInfo
->PeakUsage
= 0;
474 DriverInfo
->AllocRecordCount
= 0;
476 DriverInfo
->PdbStringOffset
= (UINT16
) sizeof (MEMORY_PROFILE_DRIVER_INFO
);
477 DriverInfoData
->PdbString
= (CHAR8
*) (DriverInfoData
->AllocInfoList
+ 1);
478 CopyMem (DriverInfoData
->PdbString
, PdbString
, PdbSize
);
480 DriverInfo
->PdbStringOffset
= 0;
481 DriverInfoData
->PdbString
= NULL
;
484 InsertTailList (ContextData
->DriverInfoList
, &DriverInfoData
->Link
);
485 ContextData
->Context
.ImageCount
++;
486 ContextData
->Context
.TotalImageSize
+= DriverInfo
->ImageSize
;
488 return DriverInfoData
;
492 Return if record for this driver is needed..
494 @param DriverFilePath Driver file path.
496 @retval TRUE Record for this driver is needed.
497 @retval FALSE Record for this driver is not needed.
501 NeedRecordThisDriver (
502 IN EFI_DEVICE_PATH_PROTOCOL
*DriverFilePath
505 EFI_DEVICE_PATH_PROTOCOL
*TmpDevicePath
;
506 EFI_DEVICE_PATH_PROTOCOL
*DevicePathInstance
;
507 UINTN DevicePathSize
;
510 if (!IsDevicePathValid (mMemoryProfileDriverPath
, mMemoryProfileDriverPathSize
)) {
512 // Invalid Device Path means record all.
518 // Record FilePath without END node.
520 FilePathSize
= GetDevicePathSize (DriverFilePath
) - sizeof(EFI_DEVICE_PATH_PROTOCOL
);
522 DevicePathInstance
= mMemoryProfileDriverPath
;
525 // Find END node (it might be END_ENTIRE or END_INSTANCE).
527 TmpDevicePath
= DevicePathInstance
;
528 while (!IsDevicePathEndType (TmpDevicePath
)) {
529 TmpDevicePath
= NextDevicePathNode (TmpDevicePath
);
533 // Do not compare END node.
535 DevicePathSize
= (UINTN
)TmpDevicePath
- (UINTN
)DevicePathInstance
;
536 if ((FilePathSize
== DevicePathSize
) &&
537 (CompareMem (DriverFilePath
, DevicePathInstance
, DevicePathSize
) == 0)) {
542 // Get next instance.
544 DevicePathInstance
= (EFI_DEVICE_PATH_PROTOCOL
*)((UINTN
)DevicePathInstance
+ DevicePathSize
+ DevicePathNodeLength(TmpDevicePath
));
545 } while (DevicePathSubType (TmpDevicePath
) != END_ENTIRE_DEVICE_PATH_SUBTYPE
);
551 Register DXE Core to memory profile.
553 @param HobStart The start address of the HOB.
554 @param ContextData Memory profile context.
556 @retval TRUE Register success.
557 @retval FALSE Register fail.
563 IN MEMORY_PROFILE_CONTEXT_DATA
*ContextData
566 EFI_PEI_HOB_POINTERS DxeCoreHob
;
567 MEMORY_PROFILE_DRIVER_INFO_DATA
*DriverInfoData
;
568 PHYSICAL_ADDRESS ImageBase
;
569 UINT8 TempBuffer
[sizeof(MEDIA_FW_VOL_FILEPATH_DEVICE_PATH
) + sizeof(EFI_DEVICE_PATH_PROTOCOL
)];
570 MEDIA_FW_VOL_FILEPATH_DEVICE_PATH
*FilePath
;
572 ASSERT (ContextData
!= NULL
);
575 // Searching for image hob
577 DxeCoreHob
.Raw
= HobStart
;
578 while ((DxeCoreHob
.Raw
= GetNextHob (EFI_HOB_TYPE_MEMORY_ALLOCATION
, DxeCoreHob
.Raw
)) != NULL
) {
579 if (CompareGuid (&DxeCoreHob
.MemoryAllocationModule
->MemoryAllocationHeader
.Name
, &gEfiHobMemoryAllocModuleGuid
)) {
585 DxeCoreHob
.Raw
= GET_NEXT_HOB (DxeCoreHob
);
587 ASSERT (DxeCoreHob
.Raw
!= NULL
);
589 FilePath
= (MEDIA_FW_VOL_FILEPATH_DEVICE_PATH
*) TempBuffer
;
590 EfiInitializeFwVolDevicepathNode (FilePath
, &DxeCoreHob
.MemoryAllocationModule
->ModuleName
);
591 SetDevicePathEndNode (FilePath
+ 1);
593 if (!NeedRecordThisDriver ((EFI_DEVICE_PATH_PROTOCOL
*) FilePath
)) {
597 ImageBase
= DxeCoreHob
.MemoryAllocationModule
->MemoryAllocationHeader
.MemoryBaseAddress
;
598 DriverInfoData
= BuildDriverInfo (
600 &DxeCoreHob
.MemoryAllocationModule
->ModuleName
,
602 DxeCoreHob
.MemoryAllocationModule
->MemoryAllocationHeader
.MemoryLength
,
603 DxeCoreHob
.MemoryAllocationModule
->EntryPoint
,
604 InternalPeCoffGetSubsystem ((VOID
*) (UINTN
) ImageBase
),
605 EFI_FV_FILETYPE_DXE_CORE
607 if (DriverInfoData
== NULL
) {
615 Initialize memory profile.
617 @param HobStart The start address of the HOB.
625 MEMORY_PROFILE_CONTEXT_DATA
*ContextData
;
627 if (!IS_UEFI_MEMORY_PROFILE_ENABLED
) {
631 ContextData
= GetMemoryProfileContext ();
632 if (ContextData
!= NULL
) {
636 mMemoryProfileGettingStatus
= FALSE
;
637 if ((PcdGet8 (PcdMemoryProfilePropertyMask
) & BIT7
) != 0) {
638 mMemoryProfileRecordingEnable
= MEMORY_PROFILE_RECORDING_DISABLE
;
640 mMemoryProfileRecordingEnable
= MEMORY_PROFILE_RECORDING_ENABLE
;
642 mMemoryProfileDriverPathSize
= PcdGetSize (PcdMemoryProfileDriverPath
);
643 mMemoryProfileDriverPath
= AllocateCopyPool (mMemoryProfileDriverPathSize
, PcdGetPtr (PcdMemoryProfileDriverPath
));
644 mMemoryProfileContextPtr
= &mMemoryProfileContext
;
646 RegisterDxeCore (HobStart
, &mMemoryProfileContext
);
648 DEBUG ((EFI_D_INFO
, "MemoryProfileInit MemoryProfileContext - 0x%x\n", &mMemoryProfileContext
));
652 Install memory profile protocol.
656 MemoryProfileInstallProtocol (
663 if (!IS_UEFI_MEMORY_PROFILE_ENABLED
) {
668 Status
= CoreInstallMultipleProtocolInterfaces (
670 &gEdkiiMemoryProfileGuid
,
674 ASSERT_EFI_ERROR (Status
);
678 Get the GUID file name from the file path.
680 @param FilePath File path.
682 @return The GUID file name from the file path.
686 GetFileNameFromFilePath (
687 IN EFI_DEVICE_PATH_PROTOCOL
*FilePath
690 MEDIA_FW_VOL_FILEPATH_DEVICE_PATH
*ThisFilePath
;
694 if (FilePath
!= NULL
) {
695 ThisFilePath
= (MEDIA_FW_VOL_FILEPATH_DEVICE_PATH
*) FilePath
;
696 while (!IsDevicePathEnd (ThisFilePath
)) {
697 FileName
= EfiGetNameGuidFromFwVolDevicePathNode (ThisFilePath
);
698 if (FileName
!= NULL
) {
701 ThisFilePath
= (MEDIA_FW_VOL_FILEPATH_DEVICE_PATH
*) NextDevicePathNode (ThisFilePath
);
709 Register image to memory profile.
711 @param DriverEntry Image info.
712 @param FileType Image file type.
714 @return EFI_SUCCESS Register successfully.
715 @return EFI_UNSUPPORTED Memory profile is unsupported,
716 or memory profile for the image is not required.
717 @return EFI_OUT_OF_RESOURCES No enough resource for this register.
721 RegisterMemoryProfileImage (
722 IN LOADED_IMAGE_PRIVATE_DATA
*DriverEntry
,
723 IN EFI_FV_FILETYPE FileType
726 MEMORY_PROFILE_CONTEXT_DATA
*ContextData
;
727 MEMORY_PROFILE_DRIVER_INFO_DATA
*DriverInfoData
;
729 if (!IS_UEFI_MEMORY_PROFILE_ENABLED
) {
730 return EFI_UNSUPPORTED
;
733 if (!NeedRecordThisDriver (DriverEntry
->Info
.FilePath
)) {
734 return EFI_UNSUPPORTED
;
737 ContextData
= GetMemoryProfileContext ();
738 if (ContextData
== NULL
) {
739 return EFI_UNSUPPORTED
;
742 DriverInfoData
= BuildDriverInfo (
744 GetFileNameFromFilePath (DriverEntry
->Info
.FilePath
),
745 DriverEntry
->ImageContext
.ImageAddress
,
746 DriverEntry
->ImageContext
.ImageSize
,
747 DriverEntry
->ImageContext
.EntryPoint
,
748 DriverEntry
->ImageContext
.ImageType
,
751 if (DriverInfoData
== NULL
) {
752 return EFI_OUT_OF_RESOURCES
;
759 Search image from memory profile.
761 @param ContextData Memory profile context.
762 @param FileName Image file name.
763 @param Address Image Address.
765 @return Pointer to memory profile driver info.
768 MEMORY_PROFILE_DRIVER_INFO_DATA
*
769 GetMemoryProfileDriverInfoByFileNameAndAddress (
770 IN MEMORY_PROFILE_CONTEXT_DATA
*ContextData
,
771 IN EFI_GUID
*FileName
,
772 IN PHYSICAL_ADDRESS Address
775 MEMORY_PROFILE_DRIVER_INFO
*DriverInfo
;
776 MEMORY_PROFILE_DRIVER_INFO_DATA
*DriverInfoData
;
777 LIST_ENTRY
*DriverLink
;
778 LIST_ENTRY
*DriverInfoList
;
780 DriverInfoList
= ContextData
->DriverInfoList
;
782 for (DriverLink
= DriverInfoList
->ForwardLink
;
783 DriverLink
!= DriverInfoList
;
784 DriverLink
= DriverLink
->ForwardLink
) {
785 DriverInfoData
= CR (
787 MEMORY_PROFILE_DRIVER_INFO_DATA
,
789 MEMORY_PROFILE_DRIVER_INFO_SIGNATURE
791 DriverInfo
= &DriverInfoData
->DriverInfo
;
792 if ((CompareGuid (&DriverInfo
->FileName
, FileName
)) &&
793 (Address
>= DriverInfo
->ImageBase
) &&
794 (Address
< (DriverInfo
->ImageBase
+ DriverInfo
->ImageSize
))) {
795 return DriverInfoData
;
803 Search image from memory profile.
804 It will return image, if (Address >= ImageBuffer) AND (Address < ImageBuffer + ImageSize).
806 @param ContextData Memory profile context.
807 @param Address Image or Function address.
809 @return Pointer to memory profile driver info.
812 MEMORY_PROFILE_DRIVER_INFO_DATA
*
813 GetMemoryProfileDriverInfoFromAddress (
814 IN MEMORY_PROFILE_CONTEXT_DATA
*ContextData
,
815 IN PHYSICAL_ADDRESS Address
818 MEMORY_PROFILE_DRIVER_INFO
*DriverInfo
;
819 MEMORY_PROFILE_DRIVER_INFO_DATA
*DriverInfoData
;
820 LIST_ENTRY
*DriverLink
;
821 LIST_ENTRY
*DriverInfoList
;
823 DriverInfoList
= ContextData
->DriverInfoList
;
825 for (DriverLink
= DriverInfoList
->ForwardLink
;
826 DriverLink
!= DriverInfoList
;
827 DriverLink
= DriverLink
->ForwardLink
) {
828 DriverInfoData
= CR (
830 MEMORY_PROFILE_DRIVER_INFO_DATA
,
832 MEMORY_PROFILE_DRIVER_INFO_SIGNATURE
834 DriverInfo
= &DriverInfoData
->DriverInfo
;
835 if ((Address
>= DriverInfo
->ImageBase
) &&
836 (Address
< (DriverInfo
->ImageBase
+ DriverInfo
->ImageSize
))) {
837 return DriverInfoData
;
845 Unregister image from memory profile.
847 @param DriverEntry Image info.
849 @return EFI_SUCCESS Unregister successfully.
850 @return EFI_UNSUPPORTED Memory profile is unsupported,
851 or memory profile for the image is not required.
852 @return EFI_NOT_FOUND The image is not found.
856 UnregisterMemoryProfileImage (
857 IN LOADED_IMAGE_PRIVATE_DATA
*DriverEntry
861 MEMORY_PROFILE_CONTEXT_DATA
*ContextData
;
862 MEMORY_PROFILE_DRIVER_INFO_DATA
*DriverInfoData
;
864 PHYSICAL_ADDRESS ImageAddress
;
865 VOID
*EntryPointInImage
;
867 if (!IS_UEFI_MEMORY_PROFILE_ENABLED
) {
868 return EFI_UNSUPPORTED
;
871 if (!NeedRecordThisDriver (DriverEntry
->Info
.FilePath
)) {
872 return EFI_UNSUPPORTED
;
875 ContextData
= GetMemoryProfileContext ();
876 if (ContextData
== NULL
) {
877 return EFI_UNSUPPORTED
;
880 DriverInfoData
= NULL
;
881 FileName
= GetFileNameFromFilePath (DriverEntry
->Info
.FilePath
);
882 ImageAddress
= DriverEntry
->ImageContext
.ImageAddress
;
883 if ((DriverEntry
->ImageContext
.EntryPoint
< ImageAddress
) || (DriverEntry
->ImageContext
.EntryPoint
>= (ImageAddress
+ DriverEntry
->ImageContext
.ImageSize
))) {
885 // If the EntryPoint is not in the range of image buffer, it should come from emulation environment.
886 // So patch ImageAddress here to align the EntryPoint.
888 Status
= InternalPeCoffGetEntryPoint ((VOID
*) (UINTN
) ImageAddress
, &EntryPointInImage
);
889 ASSERT_EFI_ERROR (Status
);
890 ImageAddress
= ImageAddress
+ (UINTN
) DriverEntry
->ImageContext
.EntryPoint
- (UINTN
) EntryPointInImage
;
892 if (FileName
!= NULL
) {
893 DriverInfoData
= GetMemoryProfileDriverInfoByFileNameAndAddress (ContextData
, FileName
, ImageAddress
);
895 if (DriverInfoData
== NULL
) {
896 DriverInfoData
= GetMemoryProfileDriverInfoFromAddress (ContextData
, ImageAddress
);
898 if (DriverInfoData
== NULL
) {
899 return EFI_NOT_FOUND
;
902 ContextData
->Context
.TotalImageSize
-= DriverInfoData
->DriverInfo
.ImageSize
;
904 // Keep the ImageBase for RVA calculation in Application.
905 //DriverInfoData->DriverInfo.ImageBase = 0;
906 DriverInfoData
->DriverInfo
.ImageSize
= 0;
908 if (DriverInfoData
->DriverInfo
.PeakUsage
== 0) {
909 ContextData
->Context
.ImageCount
--;
910 RemoveEntryList (&DriverInfoData
->Link
);
912 // Use CoreInternalFreePool() that will not update profile for this FreePool action.
914 CoreInternalFreePool (DriverInfoData
, NULL
);
921 Return if this memory type needs to be recorded into memory profile.
922 If BIOS memory type (0 ~ EfiMaxMemoryType - 1), it checks bit (1 << MemoryType).
923 If OS memory type (0x80000000 ~ 0xFFFFFFFF), it checks bit63 - 0x8000000000000000.
924 If OEM memory type (0x70000000 ~ 0x7FFFFFFF), it checks bit62 - 0x4000000000000000.
926 @param MemoryType Memory type.
928 @retval TRUE This memory type need to be recorded.
929 @retval FALSE This memory type need not to be recorded.
933 CoreNeedRecordProfile (
934 IN EFI_MEMORY_TYPE MemoryType
939 if ((UINT32
) MemoryType
>= MEMORY_TYPE_OS_RESERVED_MIN
) {
941 } else if ((UINT32
) MemoryType
>= MEMORY_TYPE_OEM_RESERVED_MIN
) {
944 TestBit
= LShiftU64 (1, MemoryType
);
947 if ((PcdGet64 (PcdMemoryProfileMemoryType
) & TestBit
) != 0) {
955 Convert EFI memory type to profile memory index. The rule is:
956 If BIOS memory type (0 ~ EfiMaxMemoryType - 1), ProfileMemoryIndex = MemoryType.
957 If OS memory type (0x80000000 ~ 0xFFFFFFFF), ProfileMemoryIndex = EfiMaxMemoryType.
958 If OEM memory type (0x70000000 ~ 0x7FFFFFFF), ProfileMemoryIndex = EfiMaxMemoryType + 1.
960 @param MemoryType Memory type.
962 @return Profile memory index.
966 GetProfileMemoryIndex (
967 IN EFI_MEMORY_TYPE MemoryType
970 if ((UINT32
) MemoryType
>= MEMORY_TYPE_OS_RESERVED_MIN
) {
971 return EfiMaxMemoryType
;
972 } else if ((UINT32
) MemoryType
>= MEMORY_TYPE_OEM_RESERVED_MIN
) {
973 return EfiMaxMemoryType
+ 1;
980 Update memory profile Allocate information.
982 @param CallerAddress Address of caller who call Allocate.
983 @param Action This Allocate action.
984 @param MemoryType Memory type.
985 @param Size Buffer size.
986 @param Buffer Buffer address.
987 @param ActionString String for memory profile action.
989 @return EFI_SUCCESS Memory profile is updated.
990 @return EFI_UNSUPPORTED Memory profile is unsupported,
991 or memory profile for the image is not required.
992 @return EFI_OUT_OF_RESOURCES No enough resource to update memory profile for allocate action.
996 CoreUpdateProfileAllocate (
997 IN PHYSICAL_ADDRESS CallerAddress
,
998 IN MEMORY_PROFILE_ACTION Action
,
999 IN EFI_MEMORY_TYPE MemoryType
,
1002 IN CHAR8
*ActionString OPTIONAL
1006 MEMORY_PROFILE_CONTEXT
*Context
;
1007 MEMORY_PROFILE_DRIVER_INFO
*DriverInfo
;
1008 MEMORY_PROFILE_ALLOC_INFO
*AllocInfo
;
1009 MEMORY_PROFILE_CONTEXT_DATA
*ContextData
;
1010 MEMORY_PROFILE_DRIVER_INFO_DATA
*DriverInfoData
;
1011 MEMORY_PROFILE_ALLOC_INFO_DATA
*AllocInfoData
;
1012 UINTN ProfileMemoryIndex
;
1013 MEMORY_PROFILE_ACTION BasicAction
;
1014 UINTN ActionStringSize
;
1015 UINTN ActionStringOccupiedSize
;
1017 BasicAction
= Action
& MEMORY_PROFILE_ACTION_BASIC_MASK
;
1019 ContextData
= GetMemoryProfileContext ();
1020 if (ContextData
== NULL
) {
1021 return EFI_UNSUPPORTED
;
1024 DriverInfoData
= GetMemoryProfileDriverInfoFromAddress (ContextData
, CallerAddress
);
1025 if (DriverInfoData
== NULL
) {
1026 return EFI_UNSUPPORTED
;
1029 ActionStringSize
= 0;
1030 ActionStringOccupiedSize
= 0;
1031 if (ActionString
!= NULL
) {
1032 ActionStringSize
= AsciiStrSize (ActionString
);
1033 ActionStringOccupiedSize
= GET_OCCUPIED_SIZE (ActionStringSize
, sizeof (UINT64
));
1037 // Use CoreInternalAllocatePool() that will not update profile for this AllocatePool action.
1039 AllocInfoData
= NULL
;
1040 Status
= CoreInternalAllocatePool (
1041 EfiBootServicesData
,
1042 sizeof (*AllocInfoData
) + ActionStringSize
,
1043 (VOID
**) &AllocInfoData
1045 if (EFI_ERROR (Status
)) {
1046 return EFI_OUT_OF_RESOURCES
;
1048 ASSERT (AllocInfoData
!= NULL
);
1051 // Only update SequenceCount if and only if it is basic action.
1053 if (Action
== BasicAction
) {
1054 ContextData
->Context
.SequenceCount
++;
1057 AllocInfo
= &AllocInfoData
->AllocInfo
;
1058 AllocInfoData
->Signature
= MEMORY_PROFILE_ALLOC_INFO_SIGNATURE
;
1059 AllocInfo
->Header
.Signature
= MEMORY_PROFILE_ALLOC_INFO_SIGNATURE
;
1060 AllocInfo
->Header
.Length
= (UINT16
) (sizeof (MEMORY_PROFILE_ALLOC_INFO
) + ActionStringOccupiedSize
);
1061 AllocInfo
->Header
.Revision
= MEMORY_PROFILE_ALLOC_INFO_REVISION
;
1062 AllocInfo
->CallerAddress
= CallerAddress
;
1063 AllocInfo
->SequenceId
= ContextData
->Context
.SequenceCount
;
1064 AllocInfo
->Action
= Action
;
1065 AllocInfo
->MemoryType
= MemoryType
;
1066 AllocInfo
->Buffer
= (PHYSICAL_ADDRESS
) (UINTN
) Buffer
;
1067 AllocInfo
->Size
= Size
;
1068 if (ActionString
!= NULL
) {
1069 AllocInfo
->ActionStringOffset
= (UINT16
) sizeof (MEMORY_PROFILE_ALLOC_INFO
);
1070 AllocInfoData
->ActionString
= (CHAR8
*) (AllocInfoData
+ 1);
1071 CopyMem (AllocInfoData
->ActionString
, ActionString
, ActionStringSize
);
1073 AllocInfo
->ActionStringOffset
= 0;
1074 AllocInfoData
->ActionString
= NULL
;
1077 InsertTailList (DriverInfoData
->AllocInfoList
, &AllocInfoData
->Link
);
1079 Context
= &ContextData
->Context
;
1080 DriverInfo
= &DriverInfoData
->DriverInfo
;
1081 DriverInfo
->AllocRecordCount
++;
1084 // Update summary if and only if it is basic action.
1086 if (Action
== BasicAction
) {
1087 ProfileMemoryIndex
= GetProfileMemoryIndex (MemoryType
);
1089 DriverInfo
->CurrentUsage
+= Size
;
1090 if (DriverInfo
->PeakUsage
< DriverInfo
->CurrentUsage
) {
1091 DriverInfo
->PeakUsage
= DriverInfo
->CurrentUsage
;
1093 DriverInfo
->CurrentUsageByType
[ProfileMemoryIndex
] += Size
;
1094 if (DriverInfo
->PeakUsageByType
[ProfileMemoryIndex
] < DriverInfo
->CurrentUsageByType
[ProfileMemoryIndex
]) {
1095 DriverInfo
->PeakUsageByType
[ProfileMemoryIndex
] = DriverInfo
->CurrentUsageByType
[ProfileMemoryIndex
];
1098 Context
->CurrentTotalUsage
+= Size
;
1099 if (Context
->PeakTotalUsage
< Context
->CurrentTotalUsage
) {
1100 Context
->PeakTotalUsage
= Context
->CurrentTotalUsage
;
1102 Context
->CurrentTotalUsageByType
[ProfileMemoryIndex
] += Size
;
1103 if (Context
->PeakTotalUsageByType
[ProfileMemoryIndex
] < Context
->CurrentTotalUsageByType
[ProfileMemoryIndex
]) {
1104 Context
->PeakTotalUsageByType
[ProfileMemoryIndex
] = Context
->CurrentTotalUsageByType
[ProfileMemoryIndex
];
1112 Get memory profile alloc info from memory profile.
1114 @param DriverInfoData Driver info.
1115 @param BasicAction This Free basic action.
1116 @param Size Buffer size.
1117 @param Buffer Buffer address.
1119 @return Pointer to memory profile alloc info.
1122 MEMORY_PROFILE_ALLOC_INFO_DATA
*
1123 GetMemoryProfileAllocInfoFromAddress (
1124 IN MEMORY_PROFILE_DRIVER_INFO_DATA
*DriverInfoData
,
1125 IN MEMORY_PROFILE_ACTION BasicAction
,
1130 LIST_ENTRY
*AllocInfoList
;
1131 LIST_ENTRY
*AllocLink
;
1132 MEMORY_PROFILE_ALLOC_INFO
*AllocInfo
;
1133 MEMORY_PROFILE_ALLOC_INFO_DATA
*AllocInfoData
;
1135 AllocInfoList
= DriverInfoData
->AllocInfoList
;
1137 for (AllocLink
= AllocInfoList
->ForwardLink
;
1138 AllocLink
!= AllocInfoList
;
1139 AllocLink
= AllocLink
->ForwardLink
) {
1140 AllocInfoData
= CR (
1142 MEMORY_PROFILE_ALLOC_INFO_DATA
,
1144 MEMORY_PROFILE_ALLOC_INFO_SIGNATURE
1146 AllocInfo
= &AllocInfoData
->AllocInfo
;
1147 if ((AllocInfo
->Action
& MEMORY_PROFILE_ACTION_BASIC_MASK
) != BasicAction
) {
1150 switch (BasicAction
) {
1151 case MemoryProfileActionAllocatePages
:
1152 if ((AllocInfo
->Buffer
<= (PHYSICAL_ADDRESS
) (UINTN
) Buffer
) &&
1153 ((AllocInfo
->Buffer
+ AllocInfo
->Size
) >= ((PHYSICAL_ADDRESS
) (UINTN
) Buffer
+ Size
))) {
1154 return AllocInfoData
;
1157 case MemoryProfileActionAllocatePool
:
1158 if (AllocInfo
->Buffer
== (PHYSICAL_ADDRESS
) (UINTN
) Buffer
) {
1159 return AllocInfoData
;
1172 Update memory profile Free information.
1174 @param CallerAddress Address of caller who call Free.
1175 @param Action This Free action.
1176 @param Size Buffer size.
1177 @param Buffer Buffer address.
1179 @return EFI_SUCCESS Memory profile is updated.
1180 @return EFI_UNSUPPORTED Memory profile is unsupported.
1181 @return EFI_NOT_FOUND No matched allocate info found for free action.
1185 CoreUpdateProfileFree (
1186 IN PHYSICAL_ADDRESS CallerAddress
,
1187 IN MEMORY_PROFILE_ACTION Action
,
1192 MEMORY_PROFILE_CONTEXT
*Context
;
1193 MEMORY_PROFILE_DRIVER_INFO
*DriverInfo
;
1194 MEMORY_PROFILE_ALLOC_INFO
*AllocInfo
;
1195 MEMORY_PROFILE_CONTEXT_DATA
*ContextData
;
1196 MEMORY_PROFILE_DRIVER_INFO_DATA
*DriverInfoData
;
1197 LIST_ENTRY
*DriverLink
;
1198 LIST_ENTRY
*DriverInfoList
;
1199 MEMORY_PROFILE_DRIVER_INFO_DATA
*ThisDriverInfoData
;
1200 MEMORY_PROFILE_ALLOC_INFO_DATA
*AllocInfoData
;
1201 UINTN ProfileMemoryIndex
;
1202 MEMORY_PROFILE_ACTION BasicAction
;
1205 BasicAction
= Action
& MEMORY_PROFILE_ACTION_BASIC_MASK
;
1207 ContextData
= GetMemoryProfileContext ();
1208 if (ContextData
== NULL
) {
1209 return EFI_UNSUPPORTED
;
1212 DriverInfoData
= GetMemoryProfileDriverInfoFromAddress (ContextData
, CallerAddress
);
1215 // Do not return if DriverInfoData == NULL here,
1216 // because driver A might free memory allocated by driver B.
1220 // Need use do-while loop to find all possible records,
1221 // because one address might be recorded multiple times.
1224 AllocInfoData
= NULL
;
1226 if (DriverInfoData
!= NULL
) {
1227 switch (BasicAction
) {
1228 case MemoryProfileActionFreePages
:
1229 AllocInfoData
= GetMemoryProfileAllocInfoFromAddress (DriverInfoData
, MemoryProfileActionAllocatePages
, Size
, Buffer
);
1231 case MemoryProfileActionFreePool
:
1232 AllocInfoData
= GetMemoryProfileAllocInfoFromAddress (DriverInfoData
, MemoryProfileActionAllocatePool
, 0, Buffer
);
1236 AllocInfoData
= NULL
;
1240 if (AllocInfoData
== NULL
) {
1242 // Legal case, because driver A might free memory allocated by driver B, by some protocol.
1244 DriverInfoList
= ContextData
->DriverInfoList
;
1246 for (DriverLink
= DriverInfoList
->ForwardLink
;
1247 DriverLink
!= DriverInfoList
;
1248 DriverLink
= DriverLink
->ForwardLink
) {
1249 ThisDriverInfoData
= CR (
1251 MEMORY_PROFILE_DRIVER_INFO_DATA
,
1253 MEMORY_PROFILE_DRIVER_INFO_SIGNATURE
1255 switch (BasicAction
) {
1256 case MemoryProfileActionFreePages
:
1257 AllocInfoData
= GetMemoryProfileAllocInfoFromAddress (ThisDriverInfoData
, MemoryProfileActionAllocatePages
, Size
, Buffer
);
1259 case MemoryProfileActionFreePool
:
1260 AllocInfoData
= GetMemoryProfileAllocInfoFromAddress (ThisDriverInfoData
, MemoryProfileActionAllocatePool
, 0, Buffer
);
1264 AllocInfoData
= NULL
;
1267 if (AllocInfoData
!= NULL
) {
1268 DriverInfoData
= ThisDriverInfoData
;
1273 if (AllocInfoData
== NULL
) {
1275 // If (!Found), no matched allocate info is found for this free action.
1276 // It is because the specified memory type allocate actions have been filtered by
1277 // CoreNeedRecordProfile(), but free actions may have no memory type information,
1278 // they can not be filtered by CoreNeedRecordProfile(). Then, they will be
1281 // If (Found), it is normal exit path.
1282 return (Found
? EFI_SUCCESS
: EFI_NOT_FOUND
);
1288 Context
= &ContextData
->Context
;
1289 DriverInfo
= &DriverInfoData
->DriverInfo
;
1290 AllocInfo
= &AllocInfoData
->AllocInfo
;
1292 DriverInfo
->AllocRecordCount
--;
1294 // Update summary if and only if it is basic action.
1296 if (AllocInfo
->Action
== (AllocInfo
->Action
& MEMORY_PROFILE_ACTION_BASIC_MASK
)) {
1297 ProfileMemoryIndex
= GetProfileMemoryIndex (AllocInfo
->MemoryType
);
1299 Context
->CurrentTotalUsage
-= AllocInfo
->Size
;
1300 Context
->CurrentTotalUsageByType
[ProfileMemoryIndex
] -= AllocInfo
->Size
;
1302 DriverInfo
->CurrentUsage
-= AllocInfo
->Size
;
1303 DriverInfo
->CurrentUsageByType
[ProfileMemoryIndex
] -= AllocInfo
->Size
;
1306 RemoveEntryList (&AllocInfoData
->Link
);
1308 if (BasicAction
== MemoryProfileActionFreePages
) {
1309 if (AllocInfo
->Buffer
!= (PHYSICAL_ADDRESS
) (UINTN
) Buffer
) {
1310 CoreUpdateProfileAllocate (
1311 AllocInfo
->CallerAddress
,
1313 AllocInfo
->MemoryType
,
1314 (UINTN
) ((PHYSICAL_ADDRESS
) (UINTN
) Buffer
- AllocInfo
->Buffer
),
1315 (VOID
*) (UINTN
) AllocInfo
->Buffer
,
1316 AllocInfoData
->ActionString
1319 if (AllocInfo
->Buffer
+ AllocInfo
->Size
!= ((PHYSICAL_ADDRESS
) (UINTN
) Buffer
+ Size
)) {
1320 CoreUpdateProfileAllocate (
1321 AllocInfo
->CallerAddress
,
1323 AllocInfo
->MemoryType
,
1324 (UINTN
) ((AllocInfo
->Buffer
+ AllocInfo
->Size
) - ((PHYSICAL_ADDRESS
) (UINTN
) Buffer
+ Size
)),
1325 (VOID
*) ((UINTN
) Buffer
+ Size
),
1326 AllocInfoData
->ActionString
1332 // Use CoreInternalFreePool() that will not update profile for this FreePool action.
1334 CoreInternalFreePool (AllocInfoData
, NULL
);
1339 Update memory profile information.
1341 @param CallerAddress Address of caller who call Allocate or Free.
1342 @param Action This Allocate or Free action.
1343 @param MemoryType Memory type.
1344 EfiMaxMemoryType means the MemoryType is unknown.
1345 @param Size Buffer size.
1346 @param Buffer Buffer address.
1347 @param ActionString String for memory profile action.
1348 Only needed for user defined allocate action.
1350 @return EFI_SUCCESS Memory profile is updated.
1351 @return EFI_UNSUPPORTED Memory profile is unsupported,
1352 or memory profile for the image is not required,
1353 or memory profile for the memory type is not required.
1354 @return EFI_ACCESS_DENIED It is during memory profile data getting.
1355 @return EFI_ABORTED Memory profile recording is not enabled.
1356 @return EFI_OUT_OF_RESOURCES No enough resource to update memory profile for allocate action.
1357 @return EFI_NOT_FOUND No matched allocate info found for free action.
1363 IN PHYSICAL_ADDRESS CallerAddress
,
1364 IN MEMORY_PROFILE_ACTION Action
,
1365 IN EFI_MEMORY_TYPE MemoryType
,
1366 IN UINTN Size
, // Valid for AllocatePages/FreePages/AllocatePool
1368 IN CHAR8
*ActionString OPTIONAL
1372 MEMORY_PROFILE_CONTEXT_DATA
*ContextData
;
1373 MEMORY_PROFILE_ACTION BasicAction
;
1375 if (!IS_UEFI_MEMORY_PROFILE_ENABLED
) {
1376 return EFI_UNSUPPORTED
;
1379 if (mMemoryProfileGettingStatus
) {
1380 return EFI_ACCESS_DENIED
;
1383 if (!mMemoryProfileRecordingEnable
) {
1388 // Get the basic action to know how to process the record
1390 BasicAction
= Action
& MEMORY_PROFILE_ACTION_BASIC_MASK
;
1393 // EfiMaxMemoryType means the MemoryType is unknown.
1395 if (MemoryType
!= EfiMaxMemoryType
) {
1397 // Only record limited MemoryType.
1399 if (!CoreNeedRecordProfile (MemoryType
)) {
1400 return EFI_UNSUPPORTED
;
1404 ContextData
= GetMemoryProfileContext ();
1405 if (ContextData
== NULL
) {
1406 return EFI_UNSUPPORTED
;
1409 CoreAcquireMemoryProfileLock ();
1410 switch (BasicAction
) {
1411 case MemoryProfileActionAllocatePages
:
1412 Status
= CoreUpdateProfileAllocate (CallerAddress
, Action
, MemoryType
, Size
, Buffer
, ActionString
);
1414 case MemoryProfileActionFreePages
:
1415 Status
= CoreUpdateProfileFree (CallerAddress
, Action
, Size
, Buffer
);
1417 case MemoryProfileActionAllocatePool
:
1418 Status
= CoreUpdateProfileAllocate (CallerAddress
, Action
, MemoryType
, Size
, Buffer
, ActionString
);
1420 case MemoryProfileActionFreePool
:
1421 Status
= CoreUpdateProfileFree (CallerAddress
, Action
, 0, Buffer
);
1425 Status
= EFI_UNSUPPORTED
;
1428 CoreReleaseMemoryProfileLock ();
1433 ////////////////////
1436 Get memory profile data size.
1438 @return Memory profile data size.
1442 MemoryProfileGetDataSize (
1446 MEMORY_PROFILE_CONTEXT_DATA
*ContextData
;
1447 MEMORY_PROFILE_DRIVER_INFO_DATA
*DriverInfoData
;
1448 MEMORY_PROFILE_ALLOC_INFO_DATA
*AllocInfoData
;
1449 LIST_ENTRY
*DriverInfoList
;
1450 LIST_ENTRY
*DriverLink
;
1451 LIST_ENTRY
*AllocInfoList
;
1452 LIST_ENTRY
*AllocLink
;
1456 ContextData
= GetMemoryProfileContext ();
1457 if (ContextData
== NULL
) {
1461 TotalSize
= sizeof (MEMORY_PROFILE_CONTEXT
);
1463 DriverInfoList
= ContextData
->DriverInfoList
;
1464 for (DriverLink
= DriverInfoList
->ForwardLink
;
1465 DriverLink
!= DriverInfoList
;
1466 DriverLink
= DriverLink
->ForwardLink
) {
1467 DriverInfoData
= CR (
1469 MEMORY_PROFILE_DRIVER_INFO_DATA
,
1471 MEMORY_PROFILE_DRIVER_INFO_SIGNATURE
1473 TotalSize
+= DriverInfoData
->DriverInfo
.Header
.Length
;
1475 AllocInfoList
= DriverInfoData
->AllocInfoList
;
1476 for (AllocLink
= AllocInfoList
->ForwardLink
;
1477 AllocLink
!= AllocInfoList
;
1478 AllocLink
= AllocLink
->ForwardLink
) {
1479 AllocInfoData
= CR (
1481 MEMORY_PROFILE_ALLOC_INFO_DATA
,
1483 MEMORY_PROFILE_ALLOC_INFO_SIGNATURE
1485 TotalSize
+= AllocInfoData
->AllocInfo
.Header
.Length
;
1493 Copy memory profile data.
1495 @param ProfileBuffer The buffer to hold memory profile data.
1499 MemoryProfileCopyData (
1500 IN VOID
*ProfileBuffer
1503 MEMORY_PROFILE_CONTEXT
*Context
;
1504 MEMORY_PROFILE_DRIVER_INFO
*DriverInfo
;
1505 MEMORY_PROFILE_ALLOC_INFO
*AllocInfo
;
1506 MEMORY_PROFILE_CONTEXT_DATA
*ContextData
;
1507 MEMORY_PROFILE_DRIVER_INFO_DATA
*DriverInfoData
;
1508 MEMORY_PROFILE_ALLOC_INFO_DATA
*AllocInfoData
;
1509 LIST_ENTRY
*DriverInfoList
;
1510 LIST_ENTRY
*DriverLink
;
1511 LIST_ENTRY
*AllocInfoList
;
1512 LIST_ENTRY
*AllocLink
;
1514 UINTN ActionStringSize
;
1516 ContextData
= GetMemoryProfileContext ();
1517 if (ContextData
== NULL
) {
1521 Context
= ProfileBuffer
;
1522 CopyMem (Context
, &ContextData
->Context
, sizeof (MEMORY_PROFILE_CONTEXT
));
1523 DriverInfo
= (MEMORY_PROFILE_DRIVER_INFO
*) (Context
+ 1);
1525 DriverInfoList
= ContextData
->DriverInfoList
;
1526 for (DriverLink
= DriverInfoList
->ForwardLink
;
1527 DriverLink
!= DriverInfoList
;
1528 DriverLink
= DriverLink
->ForwardLink
) {
1529 DriverInfoData
= CR (
1531 MEMORY_PROFILE_DRIVER_INFO_DATA
,
1533 MEMORY_PROFILE_DRIVER_INFO_SIGNATURE
1535 CopyMem (DriverInfo
, &DriverInfoData
->DriverInfo
, sizeof (MEMORY_PROFILE_DRIVER_INFO
));
1536 if (DriverInfo
->PdbStringOffset
!= 0) {
1537 PdbSize
= AsciiStrSize (DriverInfoData
->PdbString
);
1538 CopyMem ((VOID
*) ((UINTN
) DriverInfo
+ DriverInfo
->PdbStringOffset
), DriverInfoData
->PdbString
, PdbSize
);
1540 AllocInfo
= (MEMORY_PROFILE_ALLOC_INFO
*) ((UINTN
) DriverInfo
+ DriverInfo
->Header
.Length
);
1542 AllocInfoList
= DriverInfoData
->AllocInfoList
;
1543 for (AllocLink
= AllocInfoList
->ForwardLink
;
1544 AllocLink
!= AllocInfoList
;
1545 AllocLink
= AllocLink
->ForwardLink
) {
1546 AllocInfoData
= CR (
1548 MEMORY_PROFILE_ALLOC_INFO_DATA
,
1550 MEMORY_PROFILE_ALLOC_INFO_SIGNATURE
1552 CopyMem (AllocInfo
, &AllocInfoData
->AllocInfo
, sizeof (MEMORY_PROFILE_ALLOC_INFO
));
1553 if (AllocInfo
->ActionStringOffset
!= 0) {
1554 ActionStringSize
= AsciiStrSize (AllocInfoData
->ActionString
);
1555 CopyMem ((VOID
*) ((UINTN
) AllocInfo
+ AllocInfo
->ActionStringOffset
), AllocInfoData
->ActionString
, ActionStringSize
);
1557 AllocInfo
= (MEMORY_PROFILE_ALLOC_INFO
*) ((UINTN
) AllocInfo
+ AllocInfo
->Header
.Length
);
1560 DriverInfo
= (MEMORY_PROFILE_DRIVER_INFO
*) AllocInfo
;
1565 Get memory profile data.
1567 @param[in] This The EDKII_MEMORY_PROFILE_PROTOCOL instance.
1568 @param[in, out] ProfileSize On entry, points to the size in bytes of the ProfileBuffer.
1569 On return, points to the size of the data returned in ProfileBuffer.
1570 @param[out] ProfileBuffer Profile buffer.
1572 @return EFI_SUCCESS Get the memory profile data successfully.
1573 @return EFI_UNSUPPORTED Memory profile is unsupported.
1574 @return EFI_BUFFER_TO_SMALL The ProfileSize is too small for the resulting data.
1575 ProfileSize is updated with the size required.
1580 ProfileProtocolGetData (
1581 IN EDKII_MEMORY_PROFILE_PROTOCOL
*This
,
1582 IN OUT UINT64
*ProfileSize
,
1583 OUT VOID
*ProfileBuffer
1587 MEMORY_PROFILE_CONTEXT_DATA
*ContextData
;
1588 BOOLEAN MemoryProfileGettingStatus
;
1590 ContextData
= GetMemoryProfileContext ();
1591 if (ContextData
== NULL
) {
1592 return EFI_UNSUPPORTED
;
1595 MemoryProfileGettingStatus
= mMemoryProfileGettingStatus
;
1596 mMemoryProfileGettingStatus
= TRUE
;
1598 Size
= MemoryProfileGetDataSize ();
1600 if (*ProfileSize
< Size
) {
1601 *ProfileSize
= Size
;
1602 mMemoryProfileGettingStatus
= MemoryProfileGettingStatus
;
1603 return EFI_BUFFER_TOO_SMALL
;
1606 *ProfileSize
= Size
;
1607 MemoryProfileCopyData (ProfileBuffer
);
1609 mMemoryProfileGettingStatus
= MemoryProfileGettingStatus
;
1614 Register image to memory profile.
1616 @param[in] This The EDKII_MEMORY_PROFILE_PROTOCOL instance.
1617 @param[in] FilePath File path of the image.
1618 @param[in] ImageBase Image base address.
1619 @param[in] ImageSize Image size.
1620 @param[in] FileType File type of the image.
1622 @return EFI_SUCCESS Register successfully.
1623 @return EFI_UNSUPPORTED Memory profile is unsupported,
1624 or memory profile for the image is not required.
1625 @return EFI_OUT_OF_RESOURCES No enough resource for this register.
1630 ProfileProtocolRegisterImage (
1631 IN EDKII_MEMORY_PROFILE_PROTOCOL
*This
,
1632 IN EFI_DEVICE_PATH_PROTOCOL
*FilePath
,
1633 IN PHYSICAL_ADDRESS ImageBase
,
1634 IN UINT64 ImageSize
,
1635 IN EFI_FV_FILETYPE FileType
1639 LOADED_IMAGE_PRIVATE_DATA DriverEntry
;
1640 VOID
*EntryPointInImage
;
1642 ZeroMem (&DriverEntry
, sizeof (DriverEntry
));
1643 DriverEntry
.Info
.FilePath
= FilePath
;
1644 DriverEntry
.ImageContext
.ImageAddress
= ImageBase
;
1645 DriverEntry
.ImageContext
.ImageSize
= ImageSize
;
1646 Status
= InternalPeCoffGetEntryPoint ((VOID
*) (UINTN
) ImageBase
, &EntryPointInImage
);
1647 ASSERT_EFI_ERROR (Status
);
1648 DriverEntry
.ImageContext
.EntryPoint
= (PHYSICAL_ADDRESS
) (UINTN
) EntryPointInImage
;
1649 DriverEntry
.ImageContext
.ImageType
= InternalPeCoffGetSubsystem ((VOID
*) (UINTN
) ImageBase
);
1651 return RegisterMemoryProfileImage (&DriverEntry
, FileType
);
1655 Unregister image from memory profile.
1657 @param[in] This The EDKII_MEMORY_PROFILE_PROTOCOL instance.
1658 @param[in] FilePath File path of the image.
1659 @param[in] ImageBase Image base address.
1660 @param[in] ImageSize Image size.
1662 @return EFI_SUCCESS Unregister successfully.
1663 @return EFI_UNSUPPORTED Memory profile is unsupported,
1664 or memory profile for the image is not required.
1665 @return EFI_NOT_FOUND The image is not found.
1670 ProfileProtocolUnregisterImage (
1671 IN EDKII_MEMORY_PROFILE_PROTOCOL
*This
,
1672 IN EFI_DEVICE_PATH_PROTOCOL
*FilePath
,
1673 IN PHYSICAL_ADDRESS ImageBase
,
1678 LOADED_IMAGE_PRIVATE_DATA DriverEntry
;
1679 VOID
*EntryPointInImage
;
1681 ZeroMem (&DriverEntry
, sizeof (DriverEntry
));
1682 DriverEntry
.Info
.FilePath
= FilePath
;
1683 DriverEntry
.ImageContext
.ImageAddress
= ImageBase
;
1684 DriverEntry
.ImageContext
.ImageSize
= ImageSize
;
1685 Status
= InternalPeCoffGetEntryPoint ((VOID
*) (UINTN
) ImageBase
, &EntryPointInImage
);
1686 ASSERT_EFI_ERROR (Status
);
1687 DriverEntry
.ImageContext
.EntryPoint
= (PHYSICAL_ADDRESS
) (UINTN
) EntryPointInImage
;
1689 return UnregisterMemoryProfileImage (&DriverEntry
);
1693 Get memory profile recording state.
1695 @param[in] This The EDKII_MEMORY_PROFILE_PROTOCOL instance.
1696 @param[out] RecordingState Recording state.
1698 @return EFI_SUCCESS Memory profile recording state is returned.
1699 @return EFI_UNSUPPORTED Memory profile is unsupported.
1700 @return EFI_INVALID_PARAMETER RecordingState is NULL.
1705 ProfileProtocolGetRecordingState (
1706 IN EDKII_MEMORY_PROFILE_PROTOCOL
*This
,
1707 OUT BOOLEAN
*RecordingState
1710 MEMORY_PROFILE_CONTEXT_DATA
*ContextData
;
1712 ContextData
= GetMemoryProfileContext ();
1713 if (ContextData
== NULL
) {
1714 return EFI_UNSUPPORTED
;
1717 if (RecordingState
== NULL
) {
1718 return EFI_INVALID_PARAMETER
;
1720 *RecordingState
= mMemoryProfileRecordingEnable
;
1725 Set memory profile recording state.
1727 @param[in] This The EDKII_MEMORY_PROFILE_PROTOCOL instance.
1728 @param[in] RecordingState Recording state.
1730 @return EFI_SUCCESS Set memory profile recording state successfully.
1731 @return EFI_UNSUPPORTED Memory profile is unsupported.
1736 ProfileProtocolSetRecordingState (
1737 IN EDKII_MEMORY_PROFILE_PROTOCOL
*This
,
1738 IN BOOLEAN RecordingState
1741 MEMORY_PROFILE_CONTEXT_DATA
*ContextData
;
1743 ContextData
= GetMemoryProfileContext ();
1744 if (ContextData
== NULL
) {
1745 return EFI_UNSUPPORTED
;
1748 mMemoryProfileRecordingEnable
= RecordingState
;
1753 Record memory profile of multilevel caller.
1755 @param[in] This The EDKII_MEMORY_PROFILE_PROTOCOL instance.
1756 @param[in] CallerAddress Address of caller.
1757 @param[in] Action Memory profile action.
1758 @param[in] MemoryType Memory type.
1759 EfiMaxMemoryType means the MemoryType is unknown.
1760 @param[in] Buffer Buffer address.
1761 @param[in] Size Buffer size.
1762 @param[in] ActionString String for memory profile action.
1763 Only needed for user defined allocate action.
1765 @return EFI_SUCCESS Memory profile is updated.
1766 @return EFI_UNSUPPORTED Memory profile is unsupported,
1767 or memory profile for the image is not required,
1768 or memory profile for the memory type is not required.
1769 @return EFI_ACCESS_DENIED It is during memory profile data getting.
1770 @return EFI_ABORTED Memory profile recording is not enabled.
1771 @return EFI_OUT_OF_RESOURCES No enough resource to update memory profile for allocate action.
1772 @return EFI_NOT_FOUND No matched allocate info found for free action.
1777 ProfileProtocolRecord (
1778 IN EDKII_MEMORY_PROFILE_PROTOCOL
*This
,
1779 IN PHYSICAL_ADDRESS CallerAddress
,
1780 IN MEMORY_PROFILE_ACTION Action
,
1781 IN EFI_MEMORY_TYPE MemoryType
,
1784 IN CHAR8
*ActionString OPTIONAL
1787 return CoreUpdateProfile (CallerAddress
, Action
, MemoryType
, Size
, Buffer
, ActionString
);
1790 ////////////////////