2 Support routines for SMRAM profile.
4 Copyright (c) 2014 - 2018, Intel Corporation. All rights reserved.<BR>
5 SPDX-License-Identifier: BSD-2-Clause-Patent
11 #define IS_SMRAM_PROFILE_ENABLED ((PcdGet8 (PcdMemoryProfilePropertyMask) & BIT1) != 0)
12 #define IS_UEFI_MEMORY_PROFILE_ENABLED ((PcdGet8 (PcdMemoryProfilePropertyMask) & BIT0) != 0)
14 #define GET_OCCUPIED_SIZE(ActualSize, Alignment) \
15 ((ActualSize) + (((Alignment) - ((ActualSize) & ((Alignment) - 1))) & ((Alignment) - 1)))
19 MEMORY_PROFILE_CONTEXT Context
;
20 LIST_ENTRY
*DriverInfoList
;
21 } MEMORY_PROFILE_CONTEXT_DATA
;
25 MEMORY_PROFILE_DRIVER_INFO DriverInfo
;
26 LIST_ENTRY
*AllocInfoList
;
29 } MEMORY_PROFILE_DRIVER_INFO_DATA
;
33 MEMORY_PROFILE_ALLOC_INFO AllocInfo
;
36 } MEMORY_PROFILE_ALLOC_INFO_DATA
;
39 // When free memory less than 4 pages, dump it.
41 #define SMRAM_INFO_DUMP_PAGE_THRESHOLD 4
43 GLOBAL_REMOVE_IF_UNREFERENCED MEMORY_PROFILE_FREE_MEMORY mSmramFreeMemory
= {
45 MEMORY_PROFILE_FREE_MEMORY_SIGNATURE
,
46 sizeof (MEMORY_PROFILE_FREE_MEMORY
),
47 MEMORY_PROFILE_FREE_MEMORY_REVISION
53 GLOBAL_REMOVE_IF_UNREFERENCED LIST_ENTRY mImageQueue
= INITIALIZE_LIST_HEAD_VARIABLE (mImageQueue
);
54 GLOBAL_REMOVE_IF_UNREFERENCED MEMORY_PROFILE_CONTEXT_DATA mSmramProfileContext
= {
55 MEMORY_PROFILE_CONTEXT_SIGNATURE
,
58 MEMORY_PROFILE_CONTEXT_SIGNATURE
,
59 sizeof (MEMORY_PROFILE_CONTEXT
),
60 MEMORY_PROFILE_CONTEXT_REVISION
72 GLOBAL_REMOVE_IF_UNREFERENCED MEMORY_PROFILE_CONTEXT_DATA
*mSmramProfileContextPtr
= NULL
;
74 GLOBAL_REMOVE_IF_UNREFERENCED BOOLEAN mSmramReadyToLock
;
75 GLOBAL_REMOVE_IF_UNREFERENCED BOOLEAN mSmramProfileGettingStatus
= FALSE
;
76 GLOBAL_REMOVE_IF_UNREFERENCED BOOLEAN mSmramProfileRecordingEnable
= MEMORY_PROFILE_RECORDING_DISABLE
;
77 GLOBAL_REMOVE_IF_UNREFERENCED EFI_DEVICE_PATH_PROTOCOL
*mSmramProfileDriverPath
;
78 GLOBAL_REMOVE_IF_UNREFERENCED UINTN mSmramProfileDriverPathSize
;
81 Dump SMRAM information.
90 Get memory profile data.
92 @param[in] This The EDKII_SMM_MEMORY_PROFILE_PROTOCOL instance.
93 @param[in, out] ProfileSize On entry, points to the size in bytes of the ProfileBuffer.
94 On return, points to the size of the data returned in ProfileBuffer.
95 @param[out] ProfileBuffer Profile buffer.
97 @return EFI_SUCCESS Get the memory profile data successfully.
98 @return EFI_UNSUPPORTED Memory profile is unsupported.
99 @return EFI_BUFFER_TO_SMALL The ProfileSize is too small for the resulting data.
100 ProfileSize is updated with the size required.
105 SmramProfileProtocolGetData (
106 IN EDKII_SMM_MEMORY_PROFILE_PROTOCOL
*This
,
107 IN OUT UINT64
*ProfileSize
,
108 OUT VOID
*ProfileBuffer
112 Register image to memory profile.
114 @param[in] This The EDKII_SMM_MEMORY_PROFILE_PROTOCOL instance.
115 @param[in] FilePath File path of the image.
116 @param[in] ImageBase Image base address.
117 @param[in] ImageSize Image size.
118 @param[in] FileType File type of the image.
120 @return EFI_SUCCESS Register successfully.
121 @return EFI_UNSUPPORTED Memory profile is unsupported,
122 or memory profile for the image is not required.
123 @return EFI_OUT_OF_RESOURCE No enough resource for this register.
128 SmramProfileProtocolRegisterImage (
129 IN EDKII_SMM_MEMORY_PROFILE_PROTOCOL
*This
,
130 IN EFI_DEVICE_PATH_PROTOCOL
*FilePath
,
131 IN PHYSICAL_ADDRESS ImageBase
,
133 IN EFI_FV_FILETYPE FileType
137 Unregister image from memory profile.
139 @param[in] This The EDKII_SMM_MEMORY_PROFILE_PROTOCOL instance.
140 @param[in] FilePath File path of the image.
141 @param[in] ImageBase Image base address.
142 @param[in] ImageSize Image size.
144 @return EFI_SUCCESS Unregister successfully.
145 @return EFI_UNSUPPORTED Memory profile is unsupported,
146 or memory profile for the image is not required.
147 @return EFI_NOT_FOUND The image is not found.
152 SmramProfileProtocolUnregisterImage (
153 IN EDKII_SMM_MEMORY_PROFILE_PROTOCOL
*This
,
154 IN EFI_DEVICE_PATH_PROTOCOL
*FilePath
,
155 IN PHYSICAL_ADDRESS ImageBase
,
160 Get memory profile recording state.
162 @param[in] This The EDKII_SMM_MEMORY_PROFILE_PROTOCOL instance.
163 @param[out] RecordingState Recording state.
165 @return EFI_SUCCESS Memory profile recording state is returned.
166 @return EFI_UNSUPPORTED Memory profile is unsupported.
167 @return EFI_INVALID_PARAMETER RecordingState is NULL.
172 SmramProfileProtocolGetRecordingState (
173 IN EDKII_SMM_MEMORY_PROFILE_PROTOCOL
*This
,
174 OUT BOOLEAN
*RecordingState
178 Set memory profile recording state.
180 @param[in] This The EDKII_SMM_MEMORY_PROFILE_PROTOCOL instance.
181 @param[in] RecordingState Recording state.
183 @return EFI_SUCCESS Set memory profile recording state successfully.
184 @return EFI_UNSUPPORTED Memory profile is unsupported.
189 SmramProfileProtocolSetRecordingState (
190 IN EDKII_SMM_MEMORY_PROFILE_PROTOCOL
*This
,
191 IN BOOLEAN RecordingState
195 Record memory profile of multilevel caller.
197 @param[in] This The EDKII_SMM_MEMORY_PROFILE_PROTOCOL instance.
198 @param[in] CallerAddress Address of caller.
199 @param[in] Action Memory profile action.
200 @param[in] MemoryType Memory type.
201 EfiMaxMemoryType means the MemoryType is unknown.
202 @param[in] Buffer Buffer address.
203 @param[in] Size Buffer size.
204 @param[in] ActionString String for memory profile action.
205 Only needed for user defined allocate action.
207 @return EFI_SUCCESS Memory profile is updated.
208 @return EFI_UNSUPPORTED Memory profile is unsupported,
209 or memory profile for the image is not required,
210 or memory profile for the memory type is not required.
211 @return EFI_ACCESS_DENIED It is during memory profile data getting.
212 @return EFI_ABORTED Memory profile recording is not enabled.
213 @return EFI_OUT_OF_RESOURCES No enough resource to update memory profile for allocate action.
214 @return EFI_NOT_FOUND No matched allocate info found for free action.
219 SmramProfileProtocolRecord (
220 IN EDKII_SMM_MEMORY_PROFILE_PROTOCOL
*This
,
221 IN PHYSICAL_ADDRESS CallerAddress
,
222 IN MEMORY_PROFILE_ACTION Action
,
223 IN EFI_MEMORY_TYPE MemoryType
,
226 IN CHAR8
*ActionString OPTIONAL
229 GLOBAL_REMOVE_IF_UNREFERENCED EDKII_SMM_MEMORY_PROFILE_PROTOCOL mSmmProfileProtocol
= {
230 SmramProfileProtocolGetData
,
231 SmramProfileProtocolRegisterImage
,
232 SmramProfileProtocolUnregisterImage
,
233 SmramProfileProtocolGetRecordingState
,
234 SmramProfileProtocolSetRecordingState
,
235 SmramProfileProtocolRecord
,
239 Return SMRAM profile context.
241 @return SMRAM profile context.
244 MEMORY_PROFILE_CONTEXT_DATA
*
245 GetSmramProfileContext (
249 return mSmramProfileContextPtr
;
253 Retrieves and returns the Subsystem of a PE/COFF image that has been loaded into system memory.
254 If Pe32Data is NULL, then ASSERT().
256 @param Pe32Data The pointer to the PE/COFF image that is loaded in system memory.
258 @return The Subsystem of the PE/COFF image.
262 InternalPeCoffGetSubsystem (
266 EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION Hdr
;
267 EFI_IMAGE_DOS_HEADER
*DosHdr
;
270 ASSERT (Pe32Data
!= NULL
);
272 DosHdr
= (EFI_IMAGE_DOS_HEADER
*)Pe32Data
;
273 if (DosHdr
->e_magic
== EFI_IMAGE_DOS_SIGNATURE
) {
275 // DOS image header is present, so read the PE header after the DOS image header.
277 Hdr
.Pe32
= (EFI_IMAGE_NT_HEADERS32
*)((UINTN
)Pe32Data
+ (UINTN
)((DosHdr
->e_lfanew
) & 0x0ffff));
280 // DOS image header is not present, so PE header is at the image base.
282 Hdr
.Pe32
= (EFI_IMAGE_NT_HEADERS32
*)Pe32Data
;
285 if (Hdr
.Te
->Signature
== EFI_TE_IMAGE_HEADER_SIGNATURE
) {
286 return Hdr
.Te
->Subsystem
;
287 } else if (Hdr
.Pe32
->Signature
== EFI_IMAGE_NT_SIGNATURE
) {
288 Magic
= Hdr
.Pe32
->OptionalHeader
.Magic
;
289 if (Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
290 return Hdr
.Pe32
->OptionalHeader
.Subsystem
;
291 } else if (Magic
== EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC
) {
292 return Hdr
.Pe32Plus
->OptionalHeader
.Subsystem
;
300 Retrieves and returns a pointer to the entry point to a PE/COFF image that has been loaded
301 into system memory with the PE/COFF Loader Library functions.
303 Retrieves the entry point to the PE/COFF image specified by Pe32Data and returns this entry
304 point in EntryPoint. If the entry point could not be retrieved from the PE/COFF image, then
305 return RETURN_INVALID_PARAMETER. Otherwise return RETURN_SUCCESS.
306 If Pe32Data is NULL, then ASSERT().
307 If EntryPoint is NULL, then ASSERT().
309 @param Pe32Data The pointer to the PE/COFF image that is loaded in system memory.
310 @param EntryPoint The pointer to entry point to the PE/COFF image to return.
312 @retval RETURN_SUCCESS EntryPoint was returned.
313 @retval RETURN_INVALID_PARAMETER The entry point could not be found in the PE/COFF image.
317 InternalPeCoffGetEntryPoint (
319 OUT VOID
**EntryPoint
322 EFI_IMAGE_DOS_HEADER
*DosHdr
;
323 EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION Hdr
;
325 ASSERT (Pe32Data
!= NULL
);
326 ASSERT (EntryPoint
!= NULL
);
328 DosHdr
= (EFI_IMAGE_DOS_HEADER
*)Pe32Data
;
329 if (DosHdr
->e_magic
== EFI_IMAGE_DOS_SIGNATURE
) {
331 // DOS image header is present, so read the PE header after the DOS image header.
333 Hdr
.Pe32
= (EFI_IMAGE_NT_HEADERS32
*)((UINTN
)Pe32Data
+ (UINTN
)((DosHdr
->e_lfanew
) & 0x0ffff));
336 // DOS image header is not present, so PE header is at the image base.
338 Hdr
.Pe32
= (EFI_IMAGE_NT_HEADERS32
*)Pe32Data
;
342 // Calculate the entry point relative to the start of the image.
343 // AddressOfEntryPoint is common for PE32 & PE32+
345 if (Hdr
.Te
->Signature
== EFI_TE_IMAGE_HEADER_SIGNATURE
) {
346 *EntryPoint
= (VOID
*)((UINTN
)Pe32Data
+ (UINTN
)(Hdr
.Te
->AddressOfEntryPoint
& 0x0ffffffff) + sizeof (EFI_TE_IMAGE_HEADER
) - Hdr
.Te
->StrippedSize
);
347 return RETURN_SUCCESS
;
348 } else if (Hdr
.Pe32
->Signature
== EFI_IMAGE_NT_SIGNATURE
) {
349 *EntryPoint
= (VOID
*)((UINTN
)Pe32Data
+ (UINTN
)(Hdr
.Pe32
->OptionalHeader
.AddressOfEntryPoint
& 0x0ffffffff));
350 return RETURN_SUCCESS
;
353 return RETURN_UNSUPPORTED
;
359 @param ContextData Memory profile context.
360 @param FileName File name of the image.
361 @param ImageBase Image base address.
362 @param ImageSize Image size.
363 @param EntryPoint Entry point of the image.
364 @param ImageSubsystem Image subsystem of the image.
365 @param FileType File type of the image.
367 @return Pointer to memory profile driver info.
370 MEMORY_PROFILE_DRIVER_INFO_DATA
*
372 IN MEMORY_PROFILE_CONTEXT_DATA
*ContextData
,
373 IN EFI_GUID
*FileName
,
374 IN PHYSICAL_ADDRESS ImageBase
,
376 IN PHYSICAL_ADDRESS EntryPoint
,
377 IN UINT16 ImageSubsystem
,
378 IN EFI_FV_FILETYPE FileType
382 MEMORY_PROFILE_DRIVER_INFO
*DriverInfo
;
383 MEMORY_PROFILE_DRIVER_INFO_DATA
*DriverInfoData
;
384 VOID
*EntryPointInImage
;
387 UINTN PdbOccupiedSize
;
392 if (ImageBase
!= 0) {
393 PdbString
= PeCoffLoaderGetPdbPointer ((VOID
*)(UINTN
)ImageBase
);
394 if (PdbString
!= NULL
) {
395 PdbSize
= AsciiStrSize (PdbString
);
396 PdbOccupiedSize
= GET_OCCUPIED_SIZE (PdbSize
, sizeof (UINT64
));
401 // Use SmmInternalAllocatePool() that will not update profile for this AllocatePool action.
403 Status
= SmmInternalAllocatePool (
404 EfiRuntimeServicesData
,
405 sizeof (*DriverInfoData
) + sizeof (LIST_ENTRY
) + PdbSize
,
406 (VOID
**)&DriverInfoData
408 if (EFI_ERROR (Status
)) {
412 ASSERT (DriverInfoData
!= NULL
);
414 ZeroMem (DriverInfoData
, sizeof (*DriverInfoData
));
416 DriverInfo
= &DriverInfoData
->DriverInfo
;
417 DriverInfoData
->Signature
= MEMORY_PROFILE_DRIVER_INFO_SIGNATURE
;
418 DriverInfo
->Header
.Signature
= MEMORY_PROFILE_DRIVER_INFO_SIGNATURE
;
419 DriverInfo
->Header
.Length
= (UINT16
)(sizeof (MEMORY_PROFILE_DRIVER_INFO
) + PdbOccupiedSize
);
420 DriverInfo
->Header
.Revision
= MEMORY_PROFILE_DRIVER_INFO_REVISION
;
421 if (FileName
!= NULL
) {
422 CopyMem (&DriverInfo
->FileName
, FileName
, sizeof (EFI_GUID
));
425 DriverInfo
->ImageBase
= ImageBase
;
426 DriverInfo
->ImageSize
= ImageSize
;
427 DriverInfo
->EntryPoint
= EntryPoint
;
428 DriverInfo
->ImageSubsystem
= ImageSubsystem
;
429 if ((EntryPoint
!= 0) && ((EntryPoint
< ImageBase
) || (EntryPoint
>= (ImageBase
+ ImageSize
)))) {
431 // If the EntryPoint is not in the range of image buffer, it should come from emulation environment.
432 // So patch ImageBuffer here to align the EntryPoint.
434 Status
= InternalPeCoffGetEntryPoint ((VOID
*)(UINTN
)ImageBase
, &EntryPointInImage
);
435 ASSERT_EFI_ERROR (Status
);
436 DriverInfo
->ImageBase
= ImageBase
+ EntryPoint
- (PHYSICAL_ADDRESS
)(UINTN
)EntryPointInImage
;
439 DriverInfo
->FileType
= FileType
;
440 DriverInfoData
->AllocInfoList
= (LIST_ENTRY
*)(DriverInfoData
+ 1);
441 InitializeListHead (DriverInfoData
->AllocInfoList
);
442 DriverInfo
->CurrentUsage
= 0;
443 DriverInfo
->PeakUsage
= 0;
444 DriverInfo
->AllocRecordCount
= 0;
446 DriverInfo
->PdbStringOffset
= (UINT16
)sizeof (MEMORY_PROFILE_DRIVER_INFO
);
447 DriverInfoData
->PdbString
= (CHAR8
*)(DriverInfoData
->AllocInfoList
+ 1);
448 CopyMem (DriverInfoData
->PdbString
, PdbString
, PdbSize
);
450 DriverInfo
->PdbStringOffset
= 0;
451 DriverInfoData
->PdbString
= NULL
;
454 InsertTailList (ContextData
->DriverInfoList
, &DriverInfoData
->Link
);
455 ContextData
->Context
.ImageCount
++;
456 ContextData
->Context
.TotalImageSize
+= DriverInfo
->ImageSize
;
458 return DriverInfoData
;
462 Register image to DXE.
464 @param FileName File name of the image.
465 @param ImageBase Image base address.
466 @param ImageSize Image size.
467 @param FileType File type of the image.
472 IN EFI_GUID
*FileName
,
473 IN PHYSICAL_ADDRESS ImageBase
,
475 IN EFI_FV_FILETYPE FileType
479 EDKII_MEMORY_PROFILE_PROTOCOL
*ProfileProtocol
;
480 MEDIA_FW_VOL_FILEPATH_DEVICE_PATH
*FilePath
;
481 UINT8 TempBuffer
[sizeof (MEDIA_FW_VOL_FILEPATH_DEVICE_PATH
) + sizeof (EFI_DEVICE_PATH_PROTOCOL
)];
483 if (IS_UEFI_MEMORY_PROFILE_ENABLED
) {
484 FilePath
= (MEDIA_FW_VOL_FILEPATH_DEVICE_PATH
*)TempBuffer
;
485 Status
= gBS
->LocateProtocol (&gEdkiiMemoryProfileGuid
, NULL
, (VOID
**)&ProfileProtocol
);
486 if (!EFI_ERROR (Status
)) {
487 EfiInitializeFwVolDevicepathNode (FilePath
, FileName
);
488 SetDevicePathEndNode (FilePath
+ 1);
490 Status
= ProfileProtocol
->RegisterImage (
492 (EFI_DEVICE_PATH_PROTOCOL
*)FilePath
,
502 Unregister image from DXE.
504 @param FileName File name of the image.
505 @param ImageBase Image base address.
506 @param ImageSize Image size.
510 UnregisterImageFromDxe (
511 IN EFI_GUID
*FileName
,
512 IN PHYSICAL_ADDRESS ImageBase
,
517 EDKII_MEMORY_PROFILE_PROTOCOL
*ProfileProtocol
;
518 MEDIA_FW_VOL_FILEPATH_DEVICE_PATH
*FilePath
;
519 UINT8 TempBuffer
[sizeof (MEDIA_FW_VOL_FILEPATH_DEVICE_PATH
) + sizeof (EFI_DEVICE_PATH_PROTOCOL
)];
521 if (IS_UEFI_MEMORY_PROFILE_ENABLED
) {
522 FilePath
= (MEDIA_FW_VOL_FILEPATH_DEVICE_PATH
*)TempBuffer
;
523 Status
= gBS
->LocateProtocol (&gEdkiiMemoryProfileGuid
, NULL
, (VOID
*)&ProfileProtocol
);
524 if (!EFI_ERROR (Status
)) {
525 EfiInitializeFwVolDevicepathNode (FilePath
, FileName
);
526 SetDevicePathEndNode (FilePath
+ 1);
528 Status
= ProfileProtocol
->UnregisterImage (
530 (EFI_DEVICE_PATH_PROTOCOL
*)FilePath
,
539 Return if record for this driver is needed..
541 @param DriverFilePath Driver file path.
543 @retval TRUE Record for this driver is needed.
544 @retval FALSE Record for this driver is not needed.
548 NeedRecordThisDriver (
549 IN EFI_DEVICE_PATH_PROTOCOL
*DriverFilePath
552 EFI_DEVICE_PATH_PROTOCOL
*TmpDevicePath
;
553 EFI_DEVICE_PATH_PROTOCOL
*DevicePathInstance
;
554 UINTN DevicePathSize
;
557 if (!IsDevicePathValid (mSmramProfileDriverPath
, mSmramProfileDriverPathSize
)) {
559 // Invalid Device Path means record all.
565 // Record FilePath without end node.
567 FilePathSize
= GetDevicePathSize (DriverFilePath
) - sizeof (EFI_DEVICE_PATH_PROTOCOL
);
569 DevicePathInstance
= mSmramProfileDriverPath
;
572 // Find End node (it might be END_ENTIRE or END_INSTANCE)
574 TmpDevicePath
= DevicePathInstance
;
575 while (!IsDevicePathEndType (TmpDevicePath
)) {
576 TmpDevicePath
= NextDevicePathNode (TmpDevicePath
);
580 // Do not compare END node
582 DevicePathSize
= (UINTN
)TmpDevicePath
- (UINTN
)DevicePathInstance
;
583 if ((FilePathSize
== DevicePathSize
) &&
584 (CompareMem (DriverFilePath
, DevicePathInstance
, DevicePathSize
) == 0))
592 DevicePathInstance
= (EFI_DEVICE_PATH_PROTOCOL
*)((UINTN
)DevicePathInstance
+ DevicePathSize
+ DevicePathNodeLength (TmpDevicePath
));
593 } while (DevicePathSubType (TmpDevicePath
) != END_ENTIRE_DEVICE_PATH_SUBTYPE
);
599 Register SMM Core to SMRAM profile.
601 @param ContextData SMRAM profile context.
603 @retval TRUE Register success.
604 @retval FALSE Register fail.
609 IN MEMORY_PROFILE_CONTEXT_DATA
*ContextData
612 MEMORY_PROFILE_DRIVER_INFO_DATA
*DriverInfoData
;
613 PHYSICAL_ADDRESS ImageBase
;
614 UINT8 TempBuffer
[sizeof (MEDIA_FW_VOL_FILEPATH_DEVICE_PATH
) + sizeof (EFI_DEVICE_PATH_PROTOCOL
)];
615 MEDIA_FW_VOL_FILEPATH_DEVICE_PATH
*FilePath
;
617 FilePath
= (MEDIA_FW_VOL_FILEPATH_DEVICE_PATH
*)TempBuffer
;
618 EfiInitializeFwVolDevicepathNode (FilePath
, &gEfiCallerIdGuid
);
619 SetDevicePathEndNode (FilePath
+ 1);
621 if (!NeedRecordThisDriver ((EFI_DEVICE_PATH_PROTOCOL
*)FilePath
)) {
625 ImageBase
= gSmmCorePrivate
->PiSmmCoreImageBase
;
626 DriverInfoData
= BuildDriverInfo (
630 gSmmCorePrivate
->PiSmmCoreImageSize
,
631 gSmmCorePrivate
->PiSmmCoreEntryPoint
,
632 InternalPeCoffGetSubsystem ((VOID
*)(UINTN
)ImageBase
),
633 EFI_FV_FILETYPE_SMM_CORE
635 if (DriverInfoData
== NULL
) {
643 Initialize SMRAM profile.
651 MEMORY_PROFILE_CONTEXT_DATA
*SmramProfileContext
;
655 gSmmCorePrivate
->PiSmmCoreImageBase
,
656 gSmmCorePrivate
->PiSmmCoreImageSize
,
657 EFI_FV_FILETYPE_SMM_CORE
660 if (!IS_SMRAM_PROFILE_ENABLED
) {
664 SmramProfileContext
= GetSmramProfileContext ();
665 if (SmramProfileContext
!= NULL
) {
669 mSmramProfileGettingStatus
= FALSE
;
670 if ((PcdGet8 (PcdMemoryProfilePropertyMask
) & BIT7
) != 0) {
671 mSmramProfileRecordingEnable
= MEMORY_PROFILE_RECORDING_DISABLE
;
673 mSmramProfileRecordingEnable
= MEMORY_PROFILE_RECORDING_ENABLE
;
676 mSmramProfileDriverPathSize
= PcdGetSize (PcdMemoryProfileDriverPath
);
677 mSmramProfileDriverPath
= AllocateCopyPool (mSmramProfileDriverPathSize
, PcdGetPtr (PcdMemoryProfileDriverPath
));
678 mSmramProfileContextPtr
= &mSmramProfileContext
;
680 RegisterSmmCore (&mSmramProfileContext
);
682 DEBUG ((DEBUG_INFO
, "SmramProfileInit SmramProfileContext - 0x%x\n", &mSmramProfileContext
));
686 Install SMRAM profile protocol.
690 SmramProfileInstallProtocol (
697 if (!IS_SMRAM_PROFILE_ENABLED
) {
702 Status
= SmmInstallProtocolInterface (
704 &gEdkiiSmmMemoryProfileGuid
,
705 EFI_NATIVE_INTERFACE
,
708 ASSERT_EFI_ERROR (Status
);
712 Get the GUID file name from the file path.
714 @param FilePath File path.
716 @return The GUID file name from the file path.
720 GetFileNameFromFilePath (
721 IN EFI_DEVICE_PATH_PROTOCOL
*FilePath
724 MEDIA_FW_VOL_FILEPATH_DEVICE_PATH
*ThisFilePath
;
728 if (FilePath
!= NULL
) {
729 ThisFilePath
= (MEDIA_FW_VOL_FILEPATH_DEVICE_PATH
*)FilePath
;
730 while (!IsDevicePathEnd (ThisFilePath
)) {
731 FileName
= EfiGetNameGuidFromFwVolDevicePathNode (ThisFilePath
);
732 if (FileName
!= NULL
) {
736 ThisFilePath
= (MEDIA_FW_VOL_FILEPATH_DEVICE_PATH
*)NextDevicePathNode (ThisFilePath
);
744 Register SMM image to SMRAM profile.
746 @param DriverEntry SMM image info.
747 @param RegisterToDxe Register image to DXE.
749 @return EFI_SUCCESS Register successfully.
750 @return EFI_UNSUPPORTED Memory profile is unsupported,
751 or memory profile for the image is not required.
752 @return EFI_OUT_OF_RESOURCES No enough resource for this register.
756 RegisterSmramProfileImage (
757 IN EFI_SMM_DRIVER_ENTRY
*DriverEntry
,
758 IN BOOLEAN RegisterToDxe
761 MEMORY_PROFILE_CONTEXT_DATA
*ContextData
;
762 MEMORY_PROFILE_DRIVER_INFO_DATA
*DriverInfoData
;
763 UINT8 TempBuffer
[sizeof (MEDIA_FW_VOL_FILEPATH_DEVICE_PATH
) + sizeof (EFI_DEVICE_PATH_PROTOCOL
)];
764 MEDIA_FW_VOL_FILEPATH_DEVICE_PATH
*FilePath
;
768 &DriverEntry
->FileName
,
769 DriverEntry
->ImageBuffer
,
770 EFI_PAGES_TO_SIZE (DriverEntry
->NumberOfPage
),
775 if (!IS_SMRAM_PROFILE_ENABLED
) {
776 return EFI_UNSUPPORTED
;
779 FilePath
= (MEDIA_FW_VOL_FILEPATH_DEVICE_PATH
*)TempBuffer
;
780 EfiInitializeFwVolDevicepathNode (FilePath
, &DriverEntry
->FileName
);
781 SetDevicePathEndNode (FilePath
+ 1);
783 if (!NeedRecordThisDriver ((EFI_DEVICE_PATH_PROTOCOL
*)FilePath
)) {
784 return EFI_UNSUPPORTED
;
787 ContextData
= GetSmramProfileContext ();
788 if (ContextData
== NULL
) {
789 return EFI_UNSUPPORTED
;
792 DriverInfoData
= BuildDriverInfo (
794 &DriverEntry
->FileName
,
795 DriverEntry
->ImageBuffer
,
796 EFI_PAGES_TO_SIZE (DriverEntry
->NumberOfPage
),
797 DriverEntry
->ImageEntryPoint
,
798 InternalPeCoffGetSubsystem ((VOID
*)(UINTN
)DriverEntry
->ImageBuffer
),
801 if (DriverInfoData
== NULL
) {
802 return EFI_OUT_OF_RESOURCES
;
809 Search image from memory profile.
811 @param ContextData Memory profile context.
812 @param FileName Image file name.
813 @param Address Image Address.
815 @return Pointer to memory profile driver info.
818 MEMORY_PROFILE_DRIVER_INFO_DATA
*
819 GetMemoryProfileDriverInfoByFileNameAndAddress (
820 IN MEMORY_PROFILE_CONTEXT_DATA
*ContextData
,
821 IN EFI_GUID
*FileName
,
822 IN PHYSICAL_ADDRESS Address
825 MEMORY_PROFILE_DRIVER_INFO
*DriverInfo
;
826 MEMORY_PROFILE_DRIVER_INFO_DATA
*DriverInfoData
;
827 LIST_ENTRY
*DriverLink
;
828 LIST_ENTRY
*DriverInfoList
;
830 DriverInfoList
= ContextData
->DriverInfoList
;
832 for (DriverLink
= DriverInfoList
->ForwardLink
;
833 DriverLink
!= DriverInfoList
;
834 DriverLink
= DriverLink
->ForwardLink
)
836 DriverInfoData
= CR (
838 MEMORY_PROFILE_DRIVER_INFO_DATA
,
840 MEMORY_PROFILE_DRIVER_INFO_SIGNATURE
842 DriverInfo
= &DriverInfoData
->DriverInfo
;
843 if ((CompareGuid (&DriverInfo
->FileName
, FileName
)) &&
844 (Address
>= DriverInfo
->ImageBase
) &&
845 (Address
< (DriverInfo
->ImageBase
+ DriverInfo
->ImageSize
)))
847 return DriverInfoData
;
855 Search image from memory profile.
856 It will return image, if (Address >= ImageBuffer) AND (Address < ImageBuffer + ImageSize)
858 @param ContextData Memory profile context.
859 @param Address Image or Function address.
861 @return Pointer to memory profile driver info.
864 MEMORY_PROFILE_DRIVER_INFO_DATA
*
865 GetMemoryProfileDriverInfoFromAddress (
866 IN MEMORY_PROFILE_CONTEXT_DATA
*ContextData
,
867 IN PHYSICAL_ADDRESS Address
870 MEMORY_PROFILE_DRIVER_INFO
*DriverInfo
;
871 MEMORY_PROFILE_DRIVER_INFO_DATA
*DriverInfoData
;
872 LIST_ENTRY
*DriverLink
;
873 LIST_ENTRY
*DriverInfoList
;
875 DriverInfoList
= ContextData
->DriverInfoList
;
877 for (DriverLink
= DriverInfoList
->ForwardLink
;
878 DriverLink
!= DriverInfoList
;
879 DriverLink
= DriverLink
->ForwardLink
)
881 DriverInfoData
= CR (
883 MEMORY_PROFILE_DRIVER_INFO_DATA
,
885 MEMORY_PROFILE_DRIVER_INFO_SIGNATURE
887 DriverInfo
= &DriverInfoData
->DriverInfo
;
888 if ((Address
>= DriverInfo
->ImageBase
) &&
889 (Address
< (DriverInfo
->ImageBase
+ DriverInfo
->ImageSize
)))
891 return DriverInfoData
;
899 Unregister image from SMRAM profile.
901 @param DriverEntry SMM image info.
902 @param UnregisterFromDxe Unregister image from DXE.
904 @return EFI_SUCCESS Unregister successfully.
905 @return EFI_UNSUPPORTED Memory profile is unsupported,
906 or memory profile for the image is not required.
907 @return EFI_NOT_FOUND The image is not found.
911 UnregisterSmramProfileImage (
912 IN EFI_SMM_DRIVER_ENTRY
*DriverEntry
,
913 IN BOOLEAN UnregisterFromDxe
917 MEMORY_PROFILE_CONTEXT_DATA
*ContextData
;
918 MEMORY_PROFILE_DRIVER_INFO_DATA
*DriverInfoData
;
920 PHYSICAL_ADDRESS ImageAddress
;
921 VOID
*EntryPointInImage
;
922 UINT8 TempBuffer
[sizeof (MEDIA_FW_VOL_FILEPATH_DEVICE_PATH
) + sizeof (EFI_DEVICE_PATH_PROTOCOL
)];
923 MEDIA_FW_VOL_FILEPATH_DEVICE_PATH
*FilePath
;
925 if (UnregisterFromDxe
) {
926 UnregisterImageFromDxe (
927 &DriverEntry
->FileName
,
928 DriverEntry
->ImageBuffer
,
929 EFI_PAGES_TO_SIZE (DriverEntry
->NumberOfPage
)
933 if (!IS_SMRAM_PROFILE_ENABLED
) {
934 return EFI_UNSUPPORTED
;
937 FilePath
= (MEDIA_FW_VOL_FILEPATH_DEVICE_PATH
*)TempBuffer
;
938 EfiInitializeFwVolDevicepathNode (FilePath
, &DriverEntry
->FileName
);
939 SetDevicePathEndNode (FilePath
+ 1);
941 if (!NeedRecordThisDriver ((EFI_DEVICE_PATH_PROTOCOL
*)FilePath
)) {
942 return EFI_UNSUPPORTED
;
945 ContextData
= GetSmramProfileContext ();
946 if (ContextData
== NULL
) {
947 return EFI_UNSUPPORTED
;
950 DriverInfoData
= NULL
;
951 FileName
= &DriverEntry
->FileName
;
952 ImageAddress
= DriverEntry
->ImageBuffer
;
953 if ((DriverEntry
->ImageEntryPoint
< ImageAddress
) || (DriverEntry
->ImageEntryPoint
>= (ImageAddress
+ EFI_PAGES_TO_SIZE (DriverEntry
->NumberOfPage
)))) {
955 // If the EntryPoint is not in the range of image buffer, it should come from emulation environment.
956 // So patch ImageAddress here to align the EntryPoint.
958 Status
= InternalPeCoffGetEntryPoint ((VOID
*)(UINTN
)ImageAddress
, &EntryPointInImage
);
959 ASSERT_EFI_ERROR (Status
);
960 ImageAddress
= ImageAddress
+ (UINTN
)DriverEntry
->ImageEntryPoint
- (UINTN
)EntryPointInImage
;
963 if (FileName
!= NULL
) {
964 DriverInfoData
= GetMemoryProfileDriverInfoByFileNameAndAddress (ContextData
, FileName
, ImageAddress
);
967 if (DriverInfoData
== NULL
) {
968 DriverInfoData
= GetMemoryProfileDriverInfoFromAddress (ContextData
, ImageAddress
);
971 if (DriverInfoData
== NULL
) {
972 return EFI_NOT_FOUND
;
975 ContextData
->Context
.TotalImageSize
-= DriverInfoData
->DriverInfo
.ImageSize
;
977 // Keep the ImageBase for RVA calculation in Application.
978 // DriverInfoData->DriverInfo.ImageBase = 0;
979 DriverInfoData
->DriverInfo
.ImageSize
= 0;
981 if (DriverInfoData
->DriverInfo
.PeakUsage
== 0) {
982 ContextData
->Context
.ImageCount
--;
983 RemoveEntryList (&DriverInfoData
->Link
);
985 // Use SmmInternalFreePool() that will not update profile for this FreePool action.
987 SmmInternalFreePool (DriverInfoData
);
994 Return if this memory type needs to be recorded into memory profile.
995 Only need to record EfiRuntimeServicesCode and EfiRuntimeServicesData for SMRAM profile.
997 @param MemoryType Memory type.
999 @retval TRUE This memory type need to be recorded.
1000 @retval FALSE This memory type need not to be recorded.
1004 SmmCoreNeedRecordProfile (
1005 IN EFI_MEMORY_TYPE MemoryType
1010 if ((MemoryType
!= EfiRuntimeServicesCode
) &&
1011 (MemoryType
!= EfiRuntimeServicesData
))
1016 TestBit
= LShiftU64 (1, MemoryType
);
1018 if ((PcdGet64 (PcdMemoryProfileMemoryType
) & TestBit
) != 0) {
1026 Convert EFI memory type to profile memory index. The rule is:
1027 If BIOS memory type (0 ~ EfiMaxMemoryType - 1), ProfileMemoryIndex = MemoryType.
1028 As SMRAM profile is only to record EfiRuntimeServicesCode and EfiRuntimeServicesData,
1029 so return input memory type directly.
1031 @param MemoryType Memory type.
1033 @return EFI memory type as profile memory index.
1037 GetProfileMemoryIndex (
1038 IN EFI_MEMORY_TYPE MemoryType
1045 Update SMRAM profile FreeMemoryPages information
1047 @param ContextData Memory profile context.
1051 SmramProfileUpdateFreePages (
1052 IN MEMORY_PROFILE_CONTEXT_DATA
*ContextData
1056 FREE_PAGE_LIST
*Pages
;
1057 LIST_ENTRY
*FreePageList
;
1058 UINTN NumberOfPages
;
1061 FreePageList
= &mSmmMemoryMap
;
1062 for (Node
= FreePageList
->BackLink
;
1063 Node
!= FreePageList
;
1064 Node
= Node
->BackLink
)
1066 Pages
= BASE_CR (Node
, FREE_PAGE_LIST
, Link
);
1067 NumberOfPages
+= Pages
->NumberOfPages
;
1070 mSmramFreeMemory
.TotalFreeMemoryPages
= NumberOfPages
;
1072 if (NumberOfPages
<= SMRAM_INFO_DUMP_PAGE_THRESHOLD
) {
1078 Update SMRAM profile Allocate information.
1080 @param CallerAddress Address of caller who call Allocate.
1081 @param Action This Allocate action.
1082 @param MemoryType Memory type.
1083 @param Size Buffer size.
1084 @param Buffer Buffer address.
1085 @param ActionString String for memory profile action.
1087 @return EFI_SUCCESS Memory profile is updated.
1088 @return EFI_UNSUPPORTED Memory profile is unsupported,
1089 or memory profile for the image is not required.
1090 @return EFI_OUT_OF_RESOURCES No enough resource to update memory profile for allocate action.
1094 SmmCoreUpdateProfileAllocate (
1095 IN PHYSICAL_ADDRESS CallerAddress
,
1096 IN MEMORY_PROFILE_ACTION Action
,
1097 IN EFI_MEMORY_TYPE MemoryType
,
1100 IN CHAR8
*ActionString OPTIONAL
1104 MEMORY_PROFILE_CONTEXT
*Context
;
1105 MEMORY_PROFILE_DRIVER_INFO
*DriverInfo
;
1106 MEMORY_PROFILE_ALLOC_INFO
*AllocInfo
;
1107 MEMORY_PROFILE_CONTEXT_DATA
*ContextData
;
1108 MEMORY_PROFILE_DRIVER_INFO_DATA
*DriverInfoData
;
1109 MEMORY_PROFILE_ALLOC_INFO_DATA
*AllocInfoData
;
1110 EFI_MEMORY_TYPE ProfileMemoryIndex
;
1111 MEMORY_PROFILE_ACTION BasicAction
;
1112 UINTN ActionStringSize
;
1113 UINTN ActionStringOccupiedSize
;
1115 BasicAction
= Action
& MEMORY_PROFILE_ACTION_BASIC_MASK
;
1117 ContextData
= GetSmramProfileContext ();
1118 if (ContextData
== NULL
) {
1119 return EFI_UNSUPPORTED
;
1122 DriverInfoData
= GetMemoryProfileDriverInfoFromAddress (ContextData
, CallerAddress
);
1123 if (DriverInfoData
== NULL
) {
1124 return EFI_UNSUPPORTED
;
1127 ActionStringSize
= 0;
1128 ActionStringOccupiedSize
= 0;
1129 if (ActionString
!= NULL
) {
1130 ActionStringSize
= AsciiStrSize (ActionString
);
1131 ActionStringOccupiedSize
= GET_OCCUPIED_SIZE (ActionStringSize
, sizeof (UINT64
));
1135 // Use SmmInternalAllocatePool() that will not update profile for this AllocatePool action.
1137 AllocInfoData
= NULL
;
1138 Status
= SmmInternalAllocatePool (
1139 EfiRuntimeServicesData
,
1140 sizeof (*AllocInfoData
) + ActionStringSize
,
1141 (VOID
**)&AllocInfoData
1143 if (EFI_ERROR (Status
)) {
1144 return EFI_OUT_OF_RESOURCES
;
1147 ASSERT (AllocInfoData
!= NULL
);
1150 // Only update SequenceCount if and only if it is basic action.
1152 if (Action
== BasicAction
) {
1153 ContextData
->Context
.SequenceCount
++;
1156 AllocInfo
= &AllocInfoData
->AllocInfo
;
1157 AllocInfoData
->Signature
= MEMORY_PROFILE_ALLOC_INFO_SIGNATURE
;
1158 AllocInfo
->Header
.Signature
= MEMORY_PROFILE_ALLOC_INFO_SIGNATURE
;
1159 AllocInfo
->Header
.Length
= (UINT16
)(sizeof (MEMORY_PROFILE_ALLOC_INFO
) + ActionStringOccupiedSize
);
1160 AllocInfo
->Header
.Revision
= MEMORY_PROFILE_ALLOC_INFO_REVISION
;
1161 AllocInfo
->CallerAddress
= CallerAddress
;
1162 AllocInfo
->SequenceId
= ContextData
->Context
.SequenceCount
;
1163 AllocInfo
->Action
= Action
;
1164 AllocInfo
->MemoryType
= MemoryType
;
1165 AllocInfo
->Buffer
= (PHYSICAL_ADDRESS
)(UINTN
)Buffer
;
1166 AllocInfo
->Size
= Size
;
1167 if (ActionString
!= NULL
) {
1168 AllocInfo
->ActionStringOffset
= (UINT16
)sizeof (MEMORY_PROFILE_ALLOC_INFO
);
1169 AllocInfoData
->ActionString
= (CHAR8
*)(AllocInfoData
+ 1);
1170 CopyMem (AllocInfoData
->ActionString
, ActionString
, ActionStringSize
);
1172 AllocInfo
->ActionStringOffset
= 0;
1173 AllocInfoData
->ActionString
= NULL
;
1176 InsertTailList (DriverInfoData
->AllocInfoList
, &AllocInfoData
->Link
);
1178 Context
= &ContextData
->Context
;
1179 DriverInfo
= &DriverInfoData
->DriverInfo
;
1180 DriverInfo
->AllocRecordCount
++;
1183 // Update summary if and only if it is basic action.
1185 if (Action
== BasicAction
) {
1186 ProfileMemoryIndex
= GetProfileMemoryIndex (MemoryType
);
1188 DriverInfo
->CurrentUsage
+= Size
;
1189 if (DriverInfo
->PeakUsage
< DriverInfo
->CurrentUsage
) {
1190 DriverInfo
->PeakUsage
= DriverInfo
->CurrentUsage
;
1193 DriverInfo
->CurrentUsageByType
[ProfileMemoryIndex
] += Size
;
1194 if (DriverInfo
->PeakUsageByType
[ProfileMemoryIndex
] < DriverInfo
->CurrentUsageByType
[ProfileMemoryIndex
]) {
1195 DriverInfo
->PeakUsageByType
[ProfileMemoryIndex
] = DriverInfo
->CurrentUsageByType
[ProfileMemoryIndex
];
1198 Context
->CurrentTotalUsage
+= Size
;
1199 if (Context
->PeakTotalUsage
< Context
->CurrentTotalUsage
) {
1200 Context
->PeakTotalUsage
= Context
->CurrentTotalUsage
;
1203 Context
->CurrentTotalUsageByType
[ProfileMemoryIndex
] += Size
;
1204 if (Context
->PeakTotalUsageByType
[ProfileMemoryIndex
] < Context
->CurrentTotalUsageByType
[ProfileMemoryIndex
]) {
1205 Context
->PeakTotalUsageByType
[ProfileMemoryIndex
] = Context
->CurrentTotalUsageByType
[ProfileMemoryIndex
];
1208 SmramProfileUpdateFreePages (ContextData
);
1215 Get memory profile alloc info from memory profile
1217 @param DriverInfoData Driver info
1218 @param BasicAction This Free basic action
1219 @param Size Buffer size
1220 @param Buffer Buffer address
1222 @return Pointer to memory profile alloc info.
1224 MEMORY_PROFILE_ALLOC_INFO_DATA
*
1225 GetMemoryProfileAllocInfoFromAddress (
1226 IN MEMORY_PROFILE_DRIVER_INFO_DATA
*DriverInfoData
,
1227 IN MEMORY_PROFILE_ACTION BasicAction
,
1232 LIST_ENTRY
*AllocInfoList
;
1233 LIST_ENTRY
*AllocLink
;
1234 MEMORY_PROFILE_ALLOC_INFO
*AllocInfo
;
1235 MEMORY_PROFILE_ALLOC_INFO_DATA
*AllocInfoData
;
1237 AllocInfoList
= DriverInfoData
->AllocInfoList
;
1239 for (AllocLink
= AllocInfoList
->ForwardLink
;
1240 AllocLink
!= AllocInfoList
;
1241 AllocLink
= AllocLink
->ForwardLink
)
1243 AllocInfoData
= CR (
1245 MEMORY_PROFILE_ALLOC_INFO_DATA
,
1247 MEMORY_PROFILE_ALLOC_INFO_SIGNATURE
1249 AllocInfo
= &AllocInfoData
->AllocInfo
;
1250 if ((AllocInfo
->Action
& MEMORY_PROFILE_ACTION_BASIC_MASK
) != BasicAction
) {
1254 switch (BasicAction
) {
1255 case MemoryProfileActionAllocatePages
:
1256 if ((AllocInfo
->Buffer
<= (PHYSICAL_ADDRESS
)(UINTN
)Buffer
) &&
1257 ((AllocInfo
->Buffer
+ AllocInfo
->Size
) >= ((PHYSICAL_ADDRESS
)(UINTN
)Buffer
+ Size
)))
1259 return AllocInfoData
;
1263 case MemoryProfileActionAllocatePool
:
1264 if (AllocInfo
->Buffer
== (PHYSICAL_ADDRESS
)(UINTN
)Buffer
) {
1265 return AllocInfoData
;
1279 Update SMRAM profile Free information.
1281 @param CallerAddress Address of caller who call Free.
1282 @param Action This Free action.
1283 @param Size Buffer size.
1284 @param Buffer Buffer address.
1286 @return EFI_SUCCESS Memory profile is updated.
1287 @return EFI_UNSUPPORTED Memory profile is unsupported.
1288 @return EFI_NOT_FOUND No matched allocate info found for free action.
1292 SmmCoreUpdateProfileFree (
1293 IN PHYSICAL_ADDRESS CallerAddress
,
1294 IN MEMORY_PROFILE_ACTION Action
,
1299 MEMORY_PROFILE_CONTEXT
*Context
;
1300 MEMORY_PROFILE_DRIVER_INFO
*DriverInfo
;
1301 MEMORY_PROFILE_ALLOC_INFO
*AllocInfo
;
1302 MEMORY_PROFILE_CONTEXT_DATA
*ContextData
;
1303 MEMORY_PROFILE_DRIVER_INFO_DATA
*DriverInfoData
;
1304 LIST_ENTRY
*DriverLink
;
1305 LIST_ENTRY
*DriverInfoList
;
1306 MEMORY_PROFILE_DRIVER_INFO_DATA
*ThisDriverInfoData
;
1307 MEMORY_PROFILE_ALLOC_INFO_DATA
*AllocInfoData
;
1308 EFI_MEMORY_TYPE ProfileMemoryIndex
;
1309 MEMORY_PROFILE_ACTION BasicAction
;
1312 BasicAction
= Action
& MEMORY_PROFILE_ACTION_BASIC_MASK
;
1314 ContextData
= GetSmramProfileContext ();
1315 if (ContextData
== NULL
) {
1316 return EFI_UNSUPPORTED
;
1319 DriverInfoData
= GetMemoryProfileDriverInfoFromAddress (ContextData
, CallerAddress
);
1322 // Do not return if DriverInfoData == NULL here,
1323 // because driver A might free memory allocated by driver B.
1327 // Need use do-while loop to find all possible record,
1328 // because one address might be recorded multiple times.
1331 AllocInfoData
= NULL
;
1333 if (DriverInfoData
!= NULL
) {
1334 switch (BasicAction
) {
1335 case MemoryProfileActionFreePages
:
1336 AllocInfoData
= GetMemoryProfileAllocInfoFromAddress (DriverInfoData
, MemoryProfileActionAllocatePages
, Size
, Buffer
);
1338 case MemoryProfileActionFreePool
:
1339 AllocInfoData
= GetMemoryProfileAllocInfoFromAddress (DriverInfoData
, MemoryProfileActionAllocatePool
, 0, Buffer
);
1343 AllocInfoData
= NULL
;
1348 if (AllocInfoData
== NULL
) {
1350 // Legal case, because driver A might free memory allocated by driver B, by some protocol.
1352 DriverInfoList
= ContextData
->DriverInfoList
;
1354 for (DriverLink
= DriverInfoList
->ForwardLink
;
1355 DriverLink
!= DriverInfoList
;
1356 DriverLink
= DriverLink
->ForwardLink
)
1358 ThisDriverInfoData
= CR (
1360 MEMORY_PROFILE_DRIVER_INFO_DATA
,
1362 MEMORY_PROFILE_DRIVER_INFO_SIGNATURE
1364 switch (BasicAction
) {
1365 case MemoryProfileActionFreePages
:
1366 AllocInfoData
= GetMemoryProfileAllocInfoFromAddress (ThisDriverInfoData
, MemoryProfileActionAllocatePages
, Size
, Buffer
);
1368 case MemoryProfileActionFreePool
:
1369 AllocInfoData
= GetMemoryProfileAllocInfoFromAddress (ThisDriverInfoData
, MemoryProfileActionAllocatePool
, 0, Buffer
);
1373 AllocInfoData
= NULL
;
1377 if (AllocInfoData
!= NULL
) {
1378 DriverInfoData
= ThisDriverInfoData
;
1383 if (AllocInfoData
== NULL
) {
1385 // If (!Found), no matched allocate info is found for this free action.
1386 // It is because the specified memory type allocate actions have been filtered by
1387 // CoreNeedRecordProfile(), but free actions have no memory type information,
1388 // they can not be filtered by CoreNeedRecordProfile(). Then, they will be
1391 // If (Found), it is normal exit path.
1392 return (Found
? EFI_SUCCESS
: EFI_NOT_FOUND
);
1396 ASSERT (DriverInfoData
!= NULL
);
1397 ASSERT (AllocInfoData
!= NULL
);
1401 Context
= &ContextData
->Context
;
1402 DriverInfo
= &DriverInfoData
->DriverInfo
;
1403 AllocInfo
= &AllocInfoData
->AllocInfo
;
1405 DriverInfo
->AllocRecordCount
--;
1407 // Update summary if and only if it is basic action.
1409 if (AllocInfo
->Action
== (AllocInfo
->Action
& MEMORY_PROFILE_ACTION_BASIC_MASK
)) {
1410 ProfileMemoryIndex
= GetProfileMemoryIndex (AllocInfo
->MemoryType
);
1412 Context
->CurrentTotalUsage
-= AllocInfo
->Size
;
1413 Context
->CurrentTotalUsageByType
[ProfileMemoryIndex
] -= AllocInfo
->Size
;
1415 DriverInfo
->CurrentUsage
-= AllocInfo
->Size
;
1416 DriverInfo
->CurrentUsageByType
[ProfileMemoryIndex
] -= AllocInfo
->Size
;
1419 RemoveEntryList (&AllocInfoData
->Link
);
1421 if (BasicAction
== MemoryProfileActionFreePages
) {
1422 if (AllocInfo
->Buffer
!= (PHYSICAL_ADDRESS
)(UINTN
)Buffer
) {
1423 SmmCoreUpdateProfileAllocate (
1424 AllocInfo
->CallerAddress
,
1426 AllocInfo
->MemoryType
,
1427 (UINTN
)((PHYSICAL_ADDRESS
)(UINTN
)Buffer
- AllocInfo
->Buffer
),
1428 (VOID
*)(UINTN
)AllocInfo
->Buffer
,
1429 AllocInfoData
->ActionString
1433 if (AllocInfo
->Buffer
+ AllocInfo
->Size
!= ((PHYSICAL_ADDRESS
)(UINTN
)Buffer
+ Size
)) {
1434 SmmCoreUpdateProfileAllocate (
1435 AllocInfo
->CallerAddress
,
1437 AllocInfo
->MemoryType
,
1438 (UINTN
)((AllocInfo
->Buffer
+ AllocInfo
->Size
) - ((PHYSICAL_ADDRESS
)(UINTN
)Buffer
+ Size
)),
1439 (VOID
*)((UINTN
)Buffer
+ Size
),
1440 AllocInfoData
->ActionString
1446 // Use SmmInternalFreePool() that will not update profile for this FreePool action.
1448 SmmInternalFreePool (AllocInfoData
);
1453 Update SMRAM profile information.
1455 @param CallerAddress Address of caller who call Allocate or Free.
1456 @param Action This Allocate or Free action.
1457 @param MemoryType Memory type.
1458 EfiMaxMemoryType means the MemoryType is unknown.
1459 @param Size Buffer size.
1460 @param Buffer Buffer address.
1461 @param ActionString String for memory profile action.
1462 Only needed for user defined allocate action.
1464 @return EFI_SUCCESS Memory profile is updated.
1465 @return EFI_UNSUPPORTED Memory profile is unsupported,
1466 or memory profile for the image is not required,
1467 or memory profile for the memory type is not required.
1468 @return EFI_ACCESS_DENIED It is during memory profile data getting.
1469 @return EFI_ABORTED Memory profile recording is not enabled.
1470 @return EFI_OUT_OF_RESOURCES No enough resource to update memory profile for allocate action.
1471 @return EFI_NOT_FOUND No matched allocate info found for free action.
1476 SmmCoreUpdateProfile (
1477 IN PHYSICAL_ADDRESS CallerAddress
,
1478 IN MEMORY_PROFILE_ACTION Action
,
1479 IN EFI_MEMORY_TYPE MemoryType
, // Valid for AllocatePages/AllocatePool
1480 IN UINTN Size
, // Valid for AllocatePages/FreePages/AllocatePool
1482 IN CHAR8
*ActionString OPTIONAL
1486 MEMORY_PROFILE_CONTEXT_DATA
*ContextData
;
1487 MEMORY_PROFILE_ACTION BasicAction
;
1489 if (!IS_SMRAM_PROFILE_ENABLED
) {
1490 return EFI_UNSUPPORTED
;
1493 if (mSmramProfileGettingStatus
) {
1494 return EFI_ACCESS_DENIED
;
1497 if (!mSmramProfileRecordingEnable
) {
1502 // Get the basic action to know how to process the record
1504 BasicAction
= Action
& MEMORY_PROFILE_ACTION_BASIC_MASK
;
1507 // Free operations have no memory type information, so skip the check.
1509 if ((BasicAction
== MemoryProfileActionAllocatePages
) || (BasicAction
== MemoryProfileActionAllocatePool
)) {
1511 // Only record limited MemoryType.
1513 if (!SmmCoreNeedRecordProfile (MemoryType
)) {
1514 return EFI_UNSUPPORTED
;
1518 ContextData
= GetSmramProfileContext ();
1519 if (ContextData
== NULL
) {
1520 return EFI_UNSUPPORTED
;
1523 switch (BasicAction
) {
1524 case MemoryProfileActionAllocatePages
:
1525 Status
= SmmCoreUpdateProfileAllocate (CallerAddress
, Action
, MemoryType
, Size
, Buffer
, ActionString
);
1527 case MemoryProfileActionFreePages
:
1528 Status
= SmmCoreUpdateProfileFree (CallerAddress
, Action
, Size
, Buffer
);
1530 case MemoryProfileActionAllocatePool
:
1531 Status
= SmmCoreUpdateProfileAllocate (CallerAddress
, Action
, MemoryType
, Size
, Buffer
, ActionString
);
1533 case MemoryProfileActionFreePool
:
1534 Status
= SmmCoreUpdateProfileFree (CallerAddress
, Action
, 0, Buffer
);
1538 Status
= EFI_UNSUPPORTED
;
1546 SMRAM profile ready to lock callback function.
1550 SmramProfileReadyToLock (
1554 if (!IS_SMRAM_PROFILE_ENABLED
) {
1558 DEBUG ((DEBUG_INFO
, "SmramProfileReadyToLock\n"));
1559 mSmramReadyToLock
= TRUE
;
1562 ////////////////////
1565 Get SMRAM profile data size.
1567 @return SMRAM profile data size.
1571 SmramProfileGetDataSize (
1575 MEMORY_PROFILE_CONTEXT_DATA
*ContextData
;
1576 MEMORY_PROFILE_DRIVER_INFO_DATA
*DriverInfoData
;
1577 MEMORY_PROFILE_ALLOC_INFO_DATA
*AllocInfoData
;
1578 LIST_ENTRY
*DriverInfoList
;
1579 LIST_ENTRY
*DriverLink
;
1580 LIST_ENTRY
*AllocInfoList
;
1581 LIST_ENTRY
*AllocLink
;
1584 LIST_ENTRY
*FreePageList
;
1585 LIST_ENTRY
*FreePoolList
;
1586 FREE_POOL_HEADER
*Pool
;
1587 UINTN PoolListIndex
;
1589 UINTN SmmPoolTypeIndex
;
1591 ContextData
= GetSmramProfileContext ();
1592 if (ContextData
== NULL
) {
1596 TotalSize
= sizeof (MEMORY_PROFILE_CONTEXT
);
1598 DriverInfoList
= ContextData
->DriverInfoList
;
1599 for (DriverLink
= DriverInfoList
->ForwardLink
;
1600 DriverLink
!= DriverInfoList
;
1601 DriverLink
= DriverLink
->ForwardLink
)
1603 DriverInfoData
= CR (
1605 MEMORY_PROFILE_DRIVER_INFO_DATA
,
1607 MEMORY_PROFILE_DRIVER_INFO_SIGNATURE
1609 TotalSize
+= DriverInfoData
->DriverInfo
.Header
.Length
;
1611 AllocInfoList
= DriverInfoData
->AllocInfoList
;
1612 for (AllocLink
= AllocInfoList
->ForwardLink
;
1613 AllocLink
!= AllocInfoList
;
1614 AllocLink
= AllocLink
->ForwardLink
)
1616 AllocInfoData
= CR (
1618 MEMORY_PROFILE_ALLOC_INFO_DATA
,
1620 MEMORY_PROFILE_ALLOC_INFO_SIGNATURE
1622 TotalSize
+= AllocInfoData
->AllocInfo
.Header
.Length
;
1627 FreePageList
= &mSmmMemoryMap
;
1628 for (Node
= FreePageList
->BackLink
;
1629 Node
!= FreePageList
;
1630 Node
= Node
->BackLink
)
1635 for (SmmPoolTypeIndex
= 0; SmmPoolTypeIndex
< SmmPoolTypeMax
; SmmPoolTypeIndex
++) {
1636 for (PoolListIndex
= 0; PoolListIndex
< MAX_POOL_INDEX
; PoolListIndex
++) {
1637 FreePoolList
= &mSmmPoolLists
[SmmPoolTypeIndex
][PoolListIndex
];
1638 for (Node
= FreePoolList
->BackLink
;
1639 Node
!= FreePoolList
;
1640 Node
= Node
->BackLink
)
1642 Pool
= BASE_CR (Node
, FREE_POOL_HEADER
, Link
);
1643 if (Pool
->Header
.Available
) {
1650 TotalSize
+= (sizeof (MEMORY_PROFILE_FREE_MEMORY
) + Index
* sizeof (MEMORY_PROFILE_DESCRIPTOR
));
1651 TotalSize
+= (sizeof (MEMORY_PROFILE_MEMORY_RANGE
) + mFullSmramRangeCount
* sizeof (MEMORY_PROFILE_DESCRIPTOR
));
1657 Copy SMRAM profile data.
1659 @param ProfileBuffer The buffer to hold SMRAM profile data.
1660 @param ProfileSize On input, profile buffer size.
1661 On output, actual profile data size copied.
1662 @param ProfileOffset On input, profile buffer offset to copy.
1663 On output, next time profile buffer offset to copy.
1667 SmramProfileCopyData (
1668 OUT VOID
*ProfileBuffer
,
1669 IN OUT UINT64
*ProfileSize
,
1670 IN OUT UINT64
*ProfileOffset
1673 MEMORY_PROFILE_CONTEXT
*Context
;
1674 MEMORY_PROFILE_DRIVER_INFO
*DriverInfo
;
1675 MEMORY_PROFILE_ALLOC_INFO
*AllocInfo
;
1676 MEMORY_PROFILE_CONTEXT_DATA
*ContextData
;
1677 MEMORY_PROFILE_DRIVER_INFO_DATA
*DriverInfoData
;
1678 MEMORY_PROFILE_ALLOC_INFO_DATA
*AllocInfoData
;
1679 LIST_ENTRY
*DriverInfoList
;
1680 LIST_ENTRY
*DriverLink
;
1681 LIST_ENTRY
*AllocInfoList
;
1682 LIST_ENTRY
*AllocLink
;
1684 FREE_PAGE_LIST
*Pages
;
1685 LIST_ENTRY
*FreePageList
;
1686 LIST_ENTRY
*FreePoolList
;
1687 FREE_POOL_HEADER
*Pool
;
1688 UINTN PoolListIndex
;
1690 MEMORY_PROFILE_FREE_MEMORY
*FreeMemory
;
1691 MEMORY_PROFILE_MEMORY_RANGE
*MemoryRange
;
1692 MEMORY_PROFILE_DESCRIPTOR
*MemoryProfileDescriptor
;
1694 UINT64 RemainingSize
;
1696 UINTN ActionStringSize
;
1697 UINTN SmmPoolTypeIndex
;
1699 ContextData
= GetSmramProfileContext ();
1700 if (ContextData
== NULL
) {
1704 RemainingSize
= *ProfileSize
;
1707 if (*ProfileOffset
< sizeof (MEMORY_PROFILE_CONTEXT
)) {
1708 if (RemainingSize
>= sizeof (MEMORY_PROFILE_CONTEXT
)) {
1709 Context
= ProfileBuffer
;
1710 CopyMem (Context
, &ContextData
->Context
, sizeof (MEMORY_PROFILE_CONTEXT
));
1711 RemainingSize
-= sizeof (MEMORY_PROFILE_CONTEXT
);
1712 ProfileBuffer
= (UINT8
*)ProfileBuffer
+ sizeof (MEMORY_PROFILE_CONTEXT
);
1718 Offset
+= sizeof (MEMORY_PROFILE_CONTEXT
);
1720 DriverInfoList
= ContextData
->DriverInfoList
;
1721 for (DriverLink
= DriverInfoList
->ForwardLink
;
1722 DriverLink
!= DriverInfoList
;
1723 DriverLink
= DriverLink
->ForwardLink
)
1725 DriverInfoData
= CR (
1727 MEMORY_PROFILE_DRIVER_INFO_DATA
,
1729 MEMORY_PROFILE_DRIVER_INFO_SIGNATURE
1731 if (*ProfileOffset
< (Offset
+ DriverInfoData
->DriverInfo
.Header
.Length
)) {
1732 if (RemainingSize
>= DriverInfoData
->DriverInfo
.Header
.Length
) {
1733 DriverInfo
= ProfileBuffer
;
1734 CopyMem (DriverInfo
, &DriverInfoData
->DriverInfo
, sizeof (MEMORY_PROFILE_DRIVER_INFO
));
1735 if (DriverInfo
->PdbStringOffset
!= 0) {
1736 PdbSize
= AsciiStrSize (DriverInfoData
->PdbString
);
1737 CopyMem ((VOID
*)((UINTN
)DriverInfo
+ DriverInfo
->PdbStringOffset
), DriverInfoData
->PdbString
, PdbSize
);
1740 RemainingSize
-= DriverInfo
->Header
.Length
;
1741 ProfileBuffer
= (UINT8
*)ProfileBuffer
+ DriverInfo
->Header
.Length
;
1747 Offset
+= DriverInfoData
->DriverInfo
.Header
.Length
;
1749 AllocInfoList
= DriverInfoData
->AllocInfoList
;
1750 for (AllocLink
= AllocInfoList
->ForwardLink
;
1751 AllocLink
!= AllocInfoList
;
1752 AllocLink
= AllocLink
->ForwardLink
)
1754 AllocInfoData
= CR (
1756 MEMORY_PROFILE_ALLOC_INFO_DATA
,
1758 MEMORY_PROFILE_ALLOC_INFO_SIGNATURE
1760 if (*ProfileOffset
< (Offset
+ AllocInfoData
->AllocInfo
.Header
.Length
)) {
1761 if (RemainingSize
>= AllocInfoData
->AllocInfo
.Header
.Length
) {
1762 AllocInfo
= ProfileBuffer
;
1763 CopyMem (AllocInfo
, &AllocInfoData
->AllocInfo
, sizeof (MEMORY_PROFILE_ALLOC_INFO
));
1764 if (AllocInfo
->ActionStringOffset
) {
1765 ActionStringSize
= AsciiStrSize (AllocInfoData
->ActionString
);
1766 CopyMem ((VOID
*)((UINTN
)AllocInfo
+ AllocInfo
->ActionStringOffset
), AllocInfoData
->ActionString
, ActionStringSize
);
1769 RemainingSize
-= AllocInfo
->Header
.Length
;
1770 ProfileBuffer
= (UINT8
*)ProfileBuffer
+ AllocInfo
->Header
.Length
;
1776 Offset
+= AllocInfoData
->AllocInfo
.Header
.Length
;
1780 if (*ProfileOffset
< (Offset
+ sizeof (MEMORY_PROFILE_FREE_MEMORY
))) {
1781 if (RemainingSize
>= sizeof (MEMORY_PROFILE_FREE_MEMORY
)) {
1782 FreeMemory
= ProfileBuffer
;
1783 CopyMem (FreeMemory
, &mSmramFreeMemory
, sizeof (MEMORY_PROFILE_FREE_MEMORY
));
1785 FreePageList
= &mSmmMemoryMap
;
1786 for (Node
= FreePageList
->BackLink
;
1787 Node
!= FreePageList
;
1788 Node
= Node
->BackLink
)
1793 for (SmmPoolTypeIndex
= 0; SmmPoolTypeIndex
< SmmPoolTypeMax
; SmmPoolTypeIndex
++) {
1794 for (PoolListIndex
= 0; PoolListIndex
< MAX_POOL_INDEX
; PoolListIndex
++) {
1795 FreePoolList
= &mSmmPoolLists
[SmmPoolTypeIndex
][MAX_POOL_INDEX
- PoolListIndex
- 1];
1796 for (Node
= FreePoolList
->BackLink
;
1797 Node
!= FreePoolList
;
1798 Node
= Node
->BackLink
)
1800 Pool
= BASE_CR (Node
, FREE_POOL_HEADER
, Link
);
1801 if (Pool
->Header
.Available
) {
1808 FreeMemory
->FreeMemoryEntryCount
= Index
;
1810 RemainingSize
-= sizeof (MEMORY_PROFILE_FREE_MEMORY
);
1811 ProfileBuffer
= (UINT8
*)ProfileBuffer
+ sizeof (MEMORY_PROFILE_FREE_MEMORY
);
1817 Offset
+= sizeof (MEMORY_PROFILE_FREE_MEMORY
);
1818 FreePageList
= &mSmmMemoryMap
;
1819 for (Node
= FreePageList
->BackLink
;
1820 Node
!= FreePageList
;
1821 Node
= Node
->BackLink
)
1823 if (*ProfileOffset
< (Offset
+ sizeof (MEMORY_PROFILE_DESCRIPTOR
))) {
1824 if (RemainingSize
>= sizeof (MEMORY_PROFILE_DESCRIPTOR
)) {
1825 Pages
= BASE_CR (Node
, FREE_PAGE_LIST
, Link
);
1826 MemoryProfileDescriptor
= ProfileBuffer
;
1827 MemoryProfileDescriptor
->Header
.Signature
= MEMORY_PROFILE_DESCRIPTOR_SIGNATURE
;
1828 MemoryProfileDescriptor
->Header
.Length
= sizeof (MEMORY_PROFILE_DESCRIPTOR
);
1829 MemoryProfileDescriptor
->Header
.Revision
= MEMORY_PROFILE_DESCRIPTOR_REVISION
;
1830 MemoryProfileDescriptor
->Address
= (PHYSICAL_ADDRESS
)(UINTN
)Pages
;
1831 MemoryProfileDescriptor
->Size
= EFI_PAGES_TO_SIZE (Pages
->NumberOfPages
);
1833 RemainingSize
-= sizeof (MEMORY_PROFILE_DESCRIPTOR
);
1834 ProfileBuffer
= (UINT8
*)ProfileBuffer
+ sizeof (MEMORY_PROFILE_DESCRIPTOR
);
1840 Offset
+= sizeof (MEMORY_PROFILE_DESCRIPTOR
);
1843 for (SmmPoolTypeIndex
= 0; SmmPoolTypeIndex
< SmmPoolTypeMax
; SmmPoolTypeIndex
++) {
1844 for (PoolListIndex
= 0; PoolListIndex
< MAX_POOL_INDEX
; PoolListIndex
++) {
1845 FreePoolList
= &mSmmPoolLists
[SmmPoolTypeIndex
][MAX_POOL_INDEX
- PoolListIndex
- 1];
1846 for (Node
= FreePoolList
->BackLink
;
1847 Node
!= FreePoolList
;
1848 Node
= Node
->BackLink
)
1850 Pool
= BASE_CR (Node
, FREE_POOL_HEADER
, Link
);
1851 if (Pool
->Header
.Available
) {
1852 if (*ProfileOffset
< (Offset
+ sizeof (MEMORY_PROFILE_DESCRIPTOR
))) {
1853 if (RemainingSize
>= sizeof (MEMORY_PROFILE_DESCRIPTOR
)) {
1854 MemoryProfileDescriptor
= ProfileBuffer
;
1855 MemoryProfileDescriptor
->Header
.Signature
= MEMORY_PROFILE_DESCRIPTOR_SIGNATURE
;
1856 MemoryProfileDescriptor
->Header
.Length
= sizeof (MEMORY_PROFILE_DESCRIPTOR
);
1857 MemoryProfileDescriptor
->Header
.Revision
= MEMORY_PROFILE_DESCRIPTOR_REVISION
;
1858 MemoryProfileDescriptor
->Address
= (PHYSICAL_ADDRESS
)(UINTN
)Pool
;
1859 MemoryProfileDescriptor
->Size
= Pool
->Header
.Size
;
1861 RemainingSize
-= sizeof (MEMORY_PROFILE_DESCRIPTOR
);
1862 ProfileBuffer
= (UINT8
*)ProfileBuffer
+ sizeof (MEMORY_PROFILE_DESCRIPTOR
);
1868 Offset
+= sizeof (MEMORY_PROFILE_DESCRIPTOR
);
1874 if (*ProfileOffset
< (Offset
+ sizeof (MEMORY_PROFILE_MEMORY_RANGE
))) {
1875 if (RemainingSize
>= sizeof (MEMORY_PROFILE_MEMORY_RANGE
)) {
1876 MemoryRange
= ProfileBuffer
;
1877 MemoryRange
->Header
.Signature
= MEMORY_PROFILE_MEMORY_RANGE_SIGNATURE
;
1878 MemoryRange
->Header
.Length
= sizeof (MEMORY_PROFILE_MEMORY_RANGE
);
1879 MemoryRange
->Header
.Revision
= MEMORY_PROFILE_MEMORY_RANGE_REVISION
;
1880 MemoryRange
->MemoryRangeCount
= (UINT32
)mFullSmramRangeCount
;
1882 RemainingSize
-= sizeof (MEMORY_PROFILE_MEMORY_RANGE
);
1883 ProfileBuffer
= (UINT8
*)ProfileBuffer
+ sizeof (MEMORY_PROFILE_MEMORY_RANGE
);
1889 Offset
+= sizeof (MEMORY_PROFILE_MEMORY_RANGE
);
1890 for (Index
= 0; Index
< mFullSmramRangeCount
; Index
++) {
1891 if (*ProfileOffset
< (Offset
+ sizeof (MEMORY_PROFILE_DESCRIPTOR
))) {
1892 if (RemainingSize
>= sizeof (MEMORY_PROFILE_DESCRIPTOR
)) {
1893 MemoryProfileDescriptor
= ProfileBuffer
;
1894 MemoryProfileDescriptor
->Header
.Signature
= MEMORY_PROFILE_DESCRIPTOR_SIGNATURE
;
1895 MemoryProfileDescriptor
->Header
.Length
= sizeof (MEMORY_PROFILE_DESCRIPTOR
);
1896 MemoryProfileDescriptor
->Header
.Revision
= MEMORY_PROFILE_DESCRIPTOR_REVISION
;
1897 MemoryProfileDescriptor
->Address
= mFullSmramRanges
[Index
].PhysicalStart
;
1898 MemoryProfileDescriptor
->Size
= mFullSmramRanges
[Index
].PhysicalSize
;
1900 RemainingSize
-= sizeof (MEMORY_PROFILE_DESCRIPTOR
);
1901 ProfileBuffer
= (UINT8
*)ProfileBuffer
+ sizeof (MEMORY_PROFILE_DESCRIPTOR
);
1907 Offset
+= sizeof (MEMORY_PROFILE_DESCRIPTOR
);
1912 // On output, actual profile data size copied.
1914 *ProfileSize
-= RemainingSize
;
1916 // On output, next time profile buffer offset to copy.
1918 *ProfileOffset
= Offset
;
1922 Get memory profile data.
1924 @param[in] This The EDKII_SMM_MEMORY_PROFILE_PROTOCOL instance.
1925 @param[in, out] ProfileSize On entry, points to the size in bytes of the ProfileBuffer.
1926 On return, points to the size of the data returned in ProfileBuffer.
1927 @param[out] ProfileBuffer Profile buffer.
1929 @return EFI_SUCCESS Get the memory profile data successfully.
1930 @return EFI_UNSUPPORTED Memory profile is unsupported.
1931 @return EFI_BUFFER_TO_SMALL The ProfileSize is too small for the resulting data.
1932 ProfileSize is updated with the size required.
1937 SmramProfileProtocolGetData (
1938 IN EDKII_SMM_MEMORY_PROFILE_PROTOCOL
*This
,
1939 IN OUT UINT64
*ProfileSize
,
1940 OUT VOID
*ProfileBuffer
1945 MEMORY_PROFILE_CONTEXT_DATA
*ContextData
;
1946 BOOLEAN SmramProfileGettingStatus
;
1948 ContextData
= GetSmramProfileContext ();
1949 if (ContextData
== NULL
) {
1950 return EFI_UNSUPPORTED
;
1953 SmramProfileGettingStatus
= mSmramProfileGettingStatus
;
1954 mSmramProfileGettingStatus
= TRUE
;
1956 Size
= SmramProfileGetDataSize ();
1958 if (*ProfileSize
< Size
) {
1959 *ProfileSize
= Size
;
1960 mSmramProfileGettingStatus
= SmramProfileGettingStatus
;
1961 return EFI_BUFFER_TOO_SMALL
;
1965 SmramProfileCopyData (ProfileBuffer
, &Size
, &Offset
);
1966 *ProfileSize
= Size
;
1968 mSmramProfileGettingStatus
= SmramProfileGettingStatus
;
1973 Register image to memory profile.
1975 @param[in] This The EDKII_SMM_MEMORY_PROFILE_PROTOCOL instance.
1976 @param[in] FilePath File path of the image.
1977 @param[in] ImageBase Image base address.
1978 @param[in] ImageSize Image size.
1979 @param[in] FileType File type of the image.
1981 @return EFI_SUCCESS Register successfully.
1982 @return EFI_UNSUPPORTED Memory profile is unsupported,
1983 or memory profile for the image is not required.
1984 @return EFI_OUT_OF_RESOURCES No enough resource for this register.
1989 SmramProfileProtocolRegisterImage (
1990 IN EDKII_SMM_MEMORY_PROFILE_PROTOCOL
*This
,
1991 IN EFI_DEVICE_PATH_PROTOCOL
*FilePath
,
1992 IN PHYSICAL_ADDRESS ImageBase
,
1993 IN UINT64 ImageSize
,
1994 IN EFI_FV_FILETYPE FileType
1998 EFI_SMM_DRIVER_ENTRY DriverEntry
;
1999 VOID
*EntryPointInImage
;
2002 ZeroMem (&DriverEntry
, sizeof (DriverEntry
));
2003 Name
= GetFileNameFromFilePath (FilePath
);
2005 CopyMem (&DriverEntry
.FileName
, Name
, sizeof (EFI_GUID
));
2008 DriverEntry
.ImageBuffer
= ImageBase
;
2009 DriverEntry
.NumberOfPage
= EFI_SIZE_TO_PAGES ((UINTN
)ImageSize
);
2010 Status
= InternalPeCoffGetEntryPoint ((VOID
*)(UINTN
)DriverEntry
.ImageBuffer
, &EntryPointInImage
);
2011 ASSERT_EFI_ERROR (Status
);
2012 DriverEntry
.ImageEntryPoint
= (PHYSICAL_ADDRESS
)(UINTN
)EntryPointInImage
;
2014 return RegisterSmramProfileImage (&DriverEntry
, FALSE
);
2018 Unregister image from memory profile.
2020 @param[in] This The EDKII_SMM_MEMORY_PROFILE_PROTOCOL instance.
2021 @param[in] FilePath File path of the image.
2022 @param[in] ImageBase Image base address.
2023 @param[in] ImageSize Image size.
2025 @return EFI_SUCCESS Unregister successfully.
2026 @return EFI_UNSUPPORTED Memory profile is unsupported,
2027 or memory profile for the image is not required.
2028 @return EFI_NOT_FOUND The image is not found.
2033 SmramProfileProtocolUnregisterImage (
2034 IN EDKII_SMM_MEMORY_PROFILE_PROTOCOL
*This
,
2035 IN EFI_DEVICE_PATH_PROTOCOL
*FilePath
,
2036 IN PHYSICAL_ADDRESS ImageBase
,
2041 EFI_SMM_DRIVER_ENTRY DriverEntry
;
2042 VOID
*EntryPointInImage
;
2045 ZeroMem (&DriverEntry
, sizeof (DriverEntry
));
2046 Name
= GetFileNameFromFilePath (FilePath
);
2048 CopyMem (&DriverEntry
.FileName
, Name
, sizeof (EFI_GUID
));
2051 DriverEntry
.ImageBuffer
= ImageBase
;
2052 DriverEntry
.NumberOfPage
= EFI_SIZE_TO_PAGES ((UINTN
)ImageSize
);
2053 Status
= InternalPeCoffGetEntryPoint ((VOID
*)(UINTN
)DriverEntry
.ImageBuffer
, &EntryPointInImage
);
2054 ASSERT_EFI_ERROR (Status
);
2055 DriverEntry
.ImageEntryPoint
= (PHYSICAL_ADDRESS
)(UINTN
)EntryPointInImage
;
2057 return UnregisterSmramProfileImage (&DriverEntry
, FALSE
);
2061 Get memory profile recording state.
2063 @param[in] This The EDKII_SMM_MEMORY_PROFILE_PROTOCOL instance.
2064 @param[out] RecordingState Recording state.
2066 @return EFI_SUCCESS Memory profile recording state is returned.
2067 @return EFI_UNSUPPORTED Memory profile is unsupported.
2068 @return EFI_INVALID_PARAMETER RecordingState is NULL.
2073 SmramProfileProtocolGetRecordingState (
2074 IN EDKII_SMM_MEMORY_PROFILE_PROTOCOL
*This
,
2075 OUT BOOLEAN
*RecordingState
2078 MEMORY_PROFILE_CONTEXT_DATA
*ContextData
;
2080 ContextData
= GetSmramProfileContext ();
2081 if (ContextData
== NULL
) {
2082 return EFI_UNSUPPORTED
;
2085 if (RecordingState
== NULL
) {
2086 return EFI_INVALID_PARAMETER
;
2089 *RecordingState
= mSmramProfileRecordingEnable
;
2094 Set memory profile recording state.
2096 @param[in] This The EDKII_SMM_MEMORY_PROFILE_PROTOCOL instance.
2097 @param[in] RecordingState Recording state.
2099 @return EFI_SUCCESS Set memory profile recording state successfully.
2100 @return EFI_UNSUPPORTED Memory profile is unsupported.
2105 SmramProfileProtocolSetRecordingState (
2106 IN EDKII_SMM_MEMORY_PROFILE_PROTOCOL
*This
,
2107 IN BOOLEAN RecordingState
2110 MEMORY_PROFILE_CONTEXT_DATA
*ContextData
;
2112 ContextData
= GetSmramProfileContext ();
2113 if (ContextData
== NULL
) {
2114 return EFI_UNSUPPORTED
;
2117 mSmramProfileRecordingEnable
= RecordingState
;
2122 Record memory profile of multilevel caller.
2124 @param[in] This The EDKII_SMM_MEMORY_PROFILE_PROTOCOL instance.
2125 @param[in] CallerAddress Address of caller.
2126 @param[in] Action Memory profile action.
2127 @param[in] MemoryType Memory type.
2128 EfiMaxMemoryType means the MemoryType is unknown.
2129 @param[in] Buffer Buffer address.
2130 @param[in] Size Buffer size.
2131 @param[in] ActionString String for memory profile action.
2132 Only needed for user defined allocate action.
2134 @return EFI_SUCCESS Memory profile is updated.
2135 @return EFI_UNSUPPORTED Memory profile is unsupported,
2136 or memory profile for the image is not required,
2137 or memory profile for the memory type is not required.
2138 @return EFI_ACCESS_DENIED It is during memory profile data getting.
2139 @return EFI_ABORTED Memory profile recording is not enabled.
2140 @return EFI_OUT_OF_RESOURCES No enough resource to update memory profile for allocate action.
2141 @return EFI_NOT_FOUND No matched allocate info found for free action.
2146 SmramProfileProtocolRecord (
2147 IN EDKII_SMM_MEMORY_PROFILE_PROTOCOL
*This
,
2148 IN PHYSICAL_ADDRESS CallerAddress
,
2149 IN MEMORY_PROFILE_ACTION Action
,
2150 IN EFI_MEMORY_TYPE MemoryType
,
2153 IN CHAR8
*ActionString OPTIONAL
2156 return SmmCoreUpdateProfile (CallerAddress
, Action
, MemoryType
, Size
, Buffer
, ActionString
);
2160 SMRAM profile handler to get profile info.
2162 @param SmramProfileParameterGetInfo The parameter of SMM profile get size.
2166 SmramProfileHandlerGetInfo (
2167 IN SMRAM_PROFILE_PARAMETER_GET_PROFILE_INFO
*SmramProfileParameterGetInfo
2170 MEMORY_PROFILE_CONTEXT_DATA
*ContextData
;
2171 BOOLEAN SmramProfileGettingStatus
;
2173 ContextData
= GetSmramProfileContext ();
2174 if (ContextData
== NULL
) {
2178 SmramProfileGettingStatus
= mSmramProfileGettingStatus
;
2179 mSmramProfileGettingStatus
= TRUE
;
2181 SmramProfileParameterGetInfo
->ProfileSize
= SmramProfileGetDataSize ();
2182 SmramProfileParameterGetInfo
->Header
.ReturnStatus
= 0;
2184 mSmramProfileGettingStatus
= SmramProfileGettingStatus
;
2188 SMRAM profile handler to get profile data.
2190 @param SmramProfileParameterGetData The parameter of SMM profile get data.
2194 SmramProfileHandlerGetData (
2195 IN SMRAM_PROFILE_PARAMETER_GET_PROFILE_DATA
*SmramProfileParameterGetData
2199 UINT64 ProfileOffset
;
2200 SMRAM_PROFILE_PARAMETER_GET_PROFILE_DATA SmramProfileGetData
;
2201 MEMORY_PROFILE_CONTEXT_DATA
*ContextData
;
2202 BOOLEAN SmramProfileGettingStatus
;
2204 ContextData
= GetSmramProfileContext ();
2205 if (ContextData
== NULL
) {
2209 SmramProfileGettingStatus
= mSmramProfileGettingStatus
;
2210 mSmramProfileGettingStatus
= TRUE
;
2212 CopyMem (&SmramProfileGetData
, SmramProfileParameterGetData
, sizeof (SmramProfileGetData
));
2214 ProfileSize
= SmramProfileGetDataSize ();
2219 if (!SmmIsBufferOutsideSmmValid ((UINTN
)SmramProfileGetData
.ProfileBuffer
, (UINTN
)ProfileSize
)) {
2220 DEBUG ((DEBUG_ERROR
, "SmramProfileHandlerGetData: SMM ProfileBuffer in SMRAM or overflow!\n"));
2221 SmramProfileParameterGetData
->ProfileSize
= ProfileSize
;
2222 SmramProfileParameterGetData
->Header
.ReturnStatus
= (UINT64
)(INT64
)(INTN
)EFI_ACCESS_DENIED
;
2226 if (SmramProfileGetData
.ProfileSize
< ProfileSize
) {
2227 SmramProfileParameterGetData
->ProfileSize
= ProfileSize
;
2228 SmramProfileParameterGetData
->Header
.ReturnStatus
= (UINT64
)(INT64
)(INTN
)EFI_BUFFER_TOO_SMALL
;
2233 SmramProfileCopyData ((VOID
*)(UINTN
)SmramProfileGetData
.ProfileBuffer
, &ProfileSize
, &ProfileOffset
);
2234 SmramProfileParameterGetData
->ProfileSize
= ProfileSize
;
2235 SmramProfileParameterGetData
->Header
.ReturnStatus
= 0;
2238 mSmramProfileGettingStatus
= SmramProfileGettingStatus
;
2242 SMRAM profile handler to get profile data by offset.
2244 @param SmramProfileParameterGetDataByOffset The parameter of SMM profile get data by offset.
2248 SmramProfileHandlerGetDataByOffset (
2249 IN SMRAM_PROFILE_PARAMETER_GET_PROFILE_DATA_BY_OFFSET
*SmramProfileParameterGetDataByOffset
2252 SMRAM_PROFILE_PARAMETER_GET_PROFILE_DATA_BY_OFFSET SmramProfileGetDataByOffset
;
2253 MEMORY_PROFILE_CONTEXT_DATA
*ContextData
;
2254 BOOLEAN SmramProfileGettingStatus
;
2256 ContextData
= GetSmramProfileContext ();
2257 if (ContextData
== NULL
) {
2261 SmramProfileGettingStatus
= mSmramProfileGettingStatus
;
2262 mSmramProfileGettingStatus
= TRUE
;
2264 CopyMem (&SmramProfileGetDataByOffset
, SmramProfileParameterGetDataByOffset
, sizeof (SmramProfileGetDataByOffset
));
2269 if (!SmmIsBufferOutsideSmmValid ((UINTN
)SmramProfileGetDataByOffset
.ProfileBuffer
, (UINTN
)SmramProfileGetDataByOffset
.ProfileSize
)) {
2270 DEBUG ((DEBUG_ERROR
, "SmramProfileHandlerGetDataByOffset: SMM ProfileBuffer in SMRAM or overflow!\n"));
2271 SmramProfileParameterGetDataByOffset
->Header
.ReturnStatus
= (UINT64
)(INT64
)(INTN
)EFI_ACCESS_DENIED
;
2275 SmramProfileCopyData ((VOID
*)(UINTN
)SmramProfileGetDataByOffset
.ProfileBuffer
, &SmramProfileGetDataByOffset
.ProfileSize
, &SmramProfileGetDataByOffset
.ProfileOffset
);
2276 CopyMem (SmramProfileParameterGetDataByOffset
, &SmramProfileGetDataByOffset
, sizeof (SmramProfileGetDataByOffset
));
2277 SmramProfileParameterGetDataByOffset
->Header
.ReturnStatus
= 0;
2280 mSmramProfileGettingStatus
= SmramProfileGettingStatus
;
2284 Dispatch function for a Software SMI handler.
2286 Caution: This function may receive untrusted input.
2287 Communicate buffer and buffer size are external input, so this function will do basic validation.
2289 @param DispatchHandle The unique handle assigned to this handler by SmiHandlerRegister().
2290 @param Context Points to an optional handler context which was specified when the
2291 handler was registered.
2292 @param CommBuffer A pointer to a collection of data in memory that will
2293 be conveyed from a non-SMM environment into an SMM environment.
2294 @param CommBufferSize The size of the CommBuffer.
2296 @retval EFI_SUCCESS Command is handled successfully.
2301 SmramProfileHandler (
2302 IN EFI_HANDLE DispatchHandle
,
2303 IN CONST VOID
*Context OPTIONAL
,
2304 IN OUT VOID
*CommBuffer OPTIONAL
,
2305 IN OUT UINTN
*CommBufferSize OPTIONAL
2308 SMRAM_PROFILE_PARAMETER_HEADER
*SmramProfileParameterHeader
;
2309 UINTN TempCommBufferSize
;
2310 SMRAM_PROFILE_PARAMETER_RECORDING_STATE
*ParameterRecordingState
;
2312 DEBUG ((DEBUG_ERROR
, "SmramProfileHandler Enter\n"));
2315 // If input is invalid, stop processing this SMI
2317 if ((CommBuffer
== NULL
) || (CommBufferSize
== NULL
)) {
2321 TempCommBufferSize
= *CommBufferSize
;
2323 if (TempCommBufferSize
< sizeof (SMRAM_PROFILE_PARAMETER_HEADER
)) {
2324 DEBUG ((DEBUG_ERROR
, "SmramProfileHandler: SMM communication buffer size invalid!\n"));
2328 if (mSmramReadyToLock
&& !SmmIsBufferOutsideSmmValid ((UINTN
)CommBuffer
, TempCommBufferSize
)) {
2329 DEBUG ((DEBUG_ERROR
, "SmramProfileHandler: SMM communication buffer in SMRAM or overflow!\n"));
2333 SmramProfileParameterHeader
= (SMRAM_PROFILE_PARAMETER_HEADER
*)((UINTN
)CommBuffer
);
2335 SmramProfileParameterHeader
->ReturnStatus
= (UINT64
)-1;
2337 if (GetSmramProfileContext () == NULL
) {
2338 SmramProfileParameterHeader
->ReturnStatus
= (UINT64
)(INT64
)(INTN
)EFI_UNSUPPORTED
;
2342 switch (SmramProfileParameterHeader
->Command
) {
2343 case SMRAM_PROFILE_COMMAND_GET_PROFILE_INFO
:
2344 DEBUG ((DEBUG_ERROR
, "SmramProfileHandlerGetInfo\n"));
2345 if (TempCommBufferSize
!= sizeof (SMRAM_PROFILE_PARAMETER_GET_PROFILE_INFO
)) {
2346 DEBUG ((DEBUG_ERROR
, "SmramProfileHandler: SMM communication buffer size invalid!\n"));
2350 SmramProfileHandlerGetInfo ((SMRAM_PROFILE_PARAMETER_GET_PROFILE_INFO
*)(UINTN
)CommBuffer
);
2352 case SMRAM_PROFILE_COMMAND_GET_PROFILE_DATA
:
2353 DEBUG ((DEBUG_ERROR
, "SmramProfileHandlerGetData\n"));
2354 if (TempCommBufferSize
!= sizeof (SMRAM_PROFILE_PARAMETER_GET_PROFILE_DATA
)) {
2355 DEBUG ((DEBUG_ERROR
, "SmramProfileHandler: SMM communication buffer size invalid!\n"));
2359 SmramProfileHandlerGetData ((SMRAM_PROFILE_PARAMETER_GET_PROFILE_DATA
*)(UINTN
)CommBuffer
);
2361 case SMRAM_PROFILE_COMMAND_GET_PROFILE_DATA_BY_OFFSET
:
2362 DEBUG ((DEBUG_ERROR
, "SmramProfileHandlerGetDataByOffset\n"));
2363 if (TempCommBufferSize
!= sizeof (SMRAM_PROFILE_PARAMETER_GET_PROFILE_DATA_BY_OFFSET
)) {
2364 DEBUG ((DEBUG_ERROR
, "SmramProfileHandler: SMM communication buffer size invalid!\n"));
2368 SmramProfileHandlerGetDataByOffset ((SMRAM_PROFILE_PARAMETER_GET_PROFILE_DATA_BY_OFFSET
*)(UINTN
)CommBuffer
);
2370 case SMRAM_PROFILE_COMMAND_GET_RECORDING_STATE
:
2371 DEBUG ((DEBUG_ERROR
, "SmramProfileHandlerGetRecordingState\n"));
2372 if (TempCommBufferSize
!= sizeof (SMRAM_PROFILE_PARAMETER_RECORDING_STATE
)) {
2373 DEBUG ((DEBUG_ERROR
, "SmramProfileHandler: SMM communication buffer size invalid!\n"));
2377 ParameterRecordingState
= (SMRAM_PROFILE_PARAMETER_RECORDING_STATE
*)(UINTN
)CommBuffer
;
2378 ParameterRecordingState
->RecordingState
= mSmramProfileRecordingEnable
;
2379 ParameterRecordingState
->Header
.ReturnStatus
= 0;
2381 case SMRAM_PROFILE_COMMAND_SET_RECORDING_STATE
:
2382 DEBUG ((DEBUG_ERROR
, "SmramProfileHandlerSetRecordingState\n"));
2383 if (TempCommBufferSize
!= sizeof (SMRAM_PROFILE_PARAMETER_RECORDING_STATE
)) {
2384 DEBUG ((DEBUG_ERROR
, "SmramProfileHandler: SMM communication buffer size invalid!\n"));
2388 ParameterRecordingState
= (SMRAM_PROFILE_PARAMETER_RECORDING_STATE
*)(UINTN
)CommBuffer
;
2389 mSmramProfileRecordingEnable
= ParameterRecordingState
->RecordingState
;
2390 ParameterRecordingState
->Header
.ReturnStatus
= 0;
2394 // Below 2 commands have been deprecated. They may not be (re-)used.
2396 case SMRAM_PROFILE_COMMAND_DEPRECATED1
:
2397 case SMRAM_PROFILE_COMMAND_DEPRECATED2
:
2400 // Fall-through to the default (unrecognized command) case.
2406 DEBUG ((DEBUG_ERROR
, "SmramProfileHandler Exit\n"));
2412 Register SMRAM profile handler.
2416 RegisterSmramProfileHandler (
2421 EFI_HANDLE DispatchHandle
;
2423 if (!IS_SMRAM_PROFILE_ENABLED
) {
2427 Status
= SmiHandlerRegister (
2428 SmramProfileHandler
,
2429 &gEdkiiMemoryProfileGuid
,
2432 ASSERT_EFI_ERROR (Status
);
2435 ////////////////////
2447 MEMORY_PROFILE_CONTEXT_DATA
*ContextData
;
2448 BOOLEAN SmramProfileGettingStatus
;
2450 ContextData
= GetSmramProfileContext ();
2451 if (ContextData
== NULL
) {
2455 SmramProfileGettingStatus
= mSmramProfileGettingStatus
;
2456 mSmramProfileGettingStatus
= TRUE
;
2458 DEBUG ((DEBUG_INFO
, "FullSmramRange address - 0x%08x\n", mFullSmramRanges
));
2460 DEBUG ((DEBUG_INFO
, "======= SmramProfile begin =======\n"));
2462 DEBUG ((DEBUG_INFO
, "FullSmramRange:\n"));
2463 for (Index
= 0; Index
< mFullSmramRangeCount
; Index
++) {
2464 DEBUG ((DEBUG_INFO
, " FullSmramRange (0x%x)\n", Index
));
2465 DEBUG ((DEBUG_INFO
, " PhysicalStart - 0x%016lx\n", mFullSmramRanges
[Index
].PhysicalStart
));
2466 DEBUG ((DEBUG_INFO
, " CpuStart - 0x%016lx\n", mFullSmramRanges
[Index
].CpuStart
));
2467 DEBUG ((DEBUG_INFO
, " PhysicalSize - 0x%016lx\n", mFullSmramRanges
[Index
].PhysicalSize
));
2468 DEBUG ((DEBUG_INFO
, " RegionState - 0x%016lx\n", mFullSmramRanges
[Index
].RegionState
));
2471 DEBUG ((DEBUG_INFO
, "======= SmramProfile end =======\n"));
2473 mSmramProfileGettingStatus
= SmramProfileGettingStatus
;
2477 Dump SMRAM free page list.
2485 LIST_ENTRY
*FreePageList
;
2487 FREE_PAGE_LIST
*Pages
;
2489 MEMORY_PROFILE_CONTEXT_DATA
*ContextData
;
2490 BOOLEAN SmramProfileGettingStatus
;
2492 ContextData
= GetSmramProfileContext ();
2493 if (ContextData
== NULL
) {
2497 SmramProfileGettingStatus
= mSmramProfileGettingStatus
;
2498 mSmramProfileGettingStatus
= TRUE
;
2500 DEBUG ((DEBUG_INFO
, "======= SmramProfile begin =======\n"));
2502 DEBUG ((DEBUG_INFO
, "FreePagesList:\n"));
2503 FreePageList
= &mSmmMemoryMap
;
2504 for (Node
= FreePageList
->BackLink
, Index
= 0;
2505 Node
!= FreePageList
;
2506 Node
= Node
->BackLink
, Index
++)
2508 Pages
= BASE_CR (Node
, FREE_PAGE_LIST
, Link
);
2509 DEBUG ((DEBUG_INFO
, " Index - 0x%x\n", Index
));
2510 DEBUG ((DEBUG_INFO
, " PhysicalStart - 0x%016lx\n", (PHYSICAL_ADDRESS
)(UINTN
)Pages
));
2511 DEBUG ((DEBUG_INFO
, " NumberOfPages - 0x%08x\n", Pages
->NumberOfPages
));
2514 DEBUG ((DEBUG_INFO
, "======= SmramProfile end =======\n"));
2516 mSmramProfileGettingStatus
= SmramProfileGettingStatus
;
2520 Dump SMRAM free pool list.
2528 LIST_ENTRY
*FreePoolList
;
2530 FREE_POOL_HEADER
*Pool
;
2532 UINTN PoolListIndex
;
2533 MEMORY_PROFILE_CONTEXT_DATA
*ContextData
;
2534 BOOLEAN SmramProfileGettingStatus
;
2535 UINTN SmmPoolTypeIndex
;
2537 ContextData
= GetSmramProfileContext ();
2538 if (ContextData
== NULL
) {
2542 SmramProfileGettingStatus
= mSmramProfileGettingStatus
;
2543 mSmramProfileGettingStatus
= TRUE
;
2545 DEBUG ((DEBUG_INFO
, "======= SmramProfile begin =======\n"));
2547 for (SmmPoolTypeIndex
= 0; SmmPoolTypeIndex
< SmmPoolTypeMax
; SmmPoolTypeIndex
++) {
2548 for (PoolListIndex
= 0; PoolListIndex
< MAX_POOL_INDEX
; PoolListIndex
++) {
2549 DEBUG ((DEBUG_INFO
, "FreePoolList(%d)(%d):\n", SmmPoolTypeIndex
, PoolListIndex
));
2550 FreePoolList
= &mSmmPoolLists
[SmmPoolTypeIndex
][PoolListIndex
];
2551 for (Node
= FreePoolList
->BackLink
, Index
= 0;
2552 Node
!= FreePoolList
;
2553 Node
= Node
->BackLink
, Index
++)
2555 Pool
= BASE_CR (Node
, FREE_POOL_HEADER
, Link
);
2556 DEBUG ((DEBUG_INFO
, " Index - 0x%x\n", Index
));
2557 DEBUG ((DEBUG_INFO
, " PhysicalStart - 0x%016lx\n", (PHYSICAL_ADDRESS
)(UINTN
)Pool
));
2558 DEBUG ((DEBUG_INFO
, " Size - 0x%08x\n", Pool
->Header
.Size
));
2559 DEBUG ((DEBUG_INFO
, " Available - 0x%02x\n", Pool
->Header
.Available
));
2564 DEBUG ((DEBUG_INFO
, "======= SmramProfile end =======\n"));
2566 mSmramProfileGettingStatus
= SmramProfileGettingStatus
;
2569 GLOBAL_REMOVE_IF_UNREFERENCED CHAR8
*mSmmActionString
[] = {
2571 "gSmst->SmmAllocatePages",
2572 "gSmst->SmmFreePages",
2573 "gSmst->SmmAllocatePool",
2574 "gSmst->SmmFreePool",
2578 MEMORY_PROFILE_ACTION Action
;
2582 GLOBAL_REMOVE_IF_UNREFERENCED ACTION_STRING mExtActionString
[] = {
2583 { MEMORY_PROFILE_ACTION_LIB_ALLOCATE_PAGES
, "Lib:AllocatePages" },
2584 { MEMORY_PROFILE_ACTION_LIB_ALLOCATE_RUNTIME_PAGES
, "Lib:AllocateRuntimePages" },
2585 { MEMORY_PROFILE_ACTION_LIB_ALLOCATE_RESERVED_PAGES
, "Lib:AllocateReservedPages" },
2586 { MEMORY_PROFILE_ACTION_LIB_FREE_PAGES
, "Lib:FreePages" },
2587 { MEMORY_PROFILE_ACTION_LIB_ALLOCATE_ALIGNED_PAGES
, "Lib:AllocateAlignedPages" },
2588 { MEMORY_PROFILE_ACTION_LIB_ALLOCATE_ALIGNED_RUNTIME_PAGES
, "Lib:AllocateAlignedRuntimePages" },
2589 { MEMORY_PROFILE_ACTION_LIB_ALLOCATE_ALIGNED_RESERVED_PAGES
, "Lib:AllocateAlignedReservedPages" },
2590 { MEMORY_PROFILE_ACTION_LIB_FREE_ALIGNED_PAGES
, "Lib:FreeAlignedPages" },
2591 { MEMORY_PROFILE_ACTION_LIB_ALLOCATE_POOL
, "Lib:AllocatePool" },
2592 { MEMORY_PROFILE_ACTION_LIB_ALLOCATE_RUNTIME_POOL
, "Lib:AllocateRuntimePool" },
2593 { MEMORY_PROFILE_ACTION_LIB_ALLOCATE_RESERVED_POOL
, "Lib:AllocateReservedPool" },
2594 { MEMORY_PROFILE_ACTION_LIB_FREE_POOL
, "Lib:FreePool" },
2595 { MEMORY_PROFILE_ACTION_LIB_ALLOCATE_ZERO_POOL
, "Lib:AllocateZeroPool" },
2596 { MEMORY_PROFILE_ACTION_LIB_ALLOCATE_RUNTIME_ZERO_POOL
, "Lib:AllocateRuntimeZeroPool" },
2597 { MEMORY_PROFILE_ACTION_LIB_ALLOCATE_RESERVED_ZERO_POOL
, "Lib:AllocateReservedZeroPool" },
2598 { MEMORY_PROFILE_ACTION_LIB_ALLOCATE_COPY_POOL
, "Lib:AllocateCopyPool" },
2599 { MEMORY_PROFILE_ACTION_LIB_ALLOCATE_RUNTIME_COPY_POOL
, "Lib:AllocateRuntimeCopyPool" },
2600 { MEMORY_PROFILE_ACTION_LIB_ALLOCATE_RESERVED_COPY_POOL
, "Lib:AllocateReservedCopyPool" },
2601 { MEMORY_PROFILE_ACTION_LIB_REALLOCATE_POOL
, "Lib:ReallocatePool" },
2602 { MEMORY_PROFILE_ACTION_LIB_REALLOCATE_RUNTIME_POOL
, "Lib:ReallocateRuntimePool" },
2603 { MEMORY_PROFILE_ACTION_LIB_REALLOCATE_RESERVED_POOL
, "Lib:ReallocateReservedPool" },
2607 EFI_MEMORY_TYPE MemoryType
;
2608 CHAR8
*MemoryTypeStr
;
2609 } PROFILE_MEMORY_TYPE_STRING
;
2611 GLOBAL_REMOVE_IF_UNREFERENCED PROFILE_MEMORY_TYPE_STRING mMemoryTypeString
[] = {
2612 { EfiRuntimeServicesCode
, "EfiRuntimeServicesCode" },
2613 { EfiRuntimeServicesData
, "EfiRuntimeServicesData" }
2617 Memory type to string.
2619 @param[in] MemoryType Memory type.
2621 @return Pointer to string.
2625 ProfileMemoryTypeToStr (
2626 IN EFI_MEMORY_TYPE MemoryType
2631 for (Index
= 0; Index
< ARRAY_SIZE (mMemoryTypeString
); Index
++) {
2632 if (mMemoryTypeString
[Index
].MemoryType
== MemoryType
) {
2633 return mMemoryTypeString
[Index
].MemoryTypeStr
;
2637 return "UnexpectedMemoryType";
2643 @param[in] Action Profile action.
2645 @return Pointer to string.
2649 ProfileActionToStr (
2650 IN MEMORY_PROFILE_ACTION Action
2654 UINTN ActionStringCount
;
2655 CHAR8
**ActionString
;
2657 ActionString
= mSmmActionString
;
2658 ActionStringCount
= ARRAY_SIZE (mSmmActionString
);
2660 if ((UINTN
)(UINT32
)Action
< ActionStringCount
) {
2661 return ActionString
[Action
];
2664 for (Index
= 0; Index
< ARRAY_SIZE (mExtActionString
); Index
++) {
2665 if (mExtActionString
[Index
].Action
== Action
) {
2666 return mExtActionString
[Index
].String
;
2670 return ActionString
[0];
2682 MEMORY_PROFILE_CONTEXT
*Context
;
2683 MEMORY_PROFILE_DRIVER_INFO
*DriverInfo
;
2684 MEMORY_PROFILE_ALLOC_INFO
*AllocInfo
;
2685 MEMORY_PROFILE_CONTEXT_DATA
*ContextData
;
2686 MEMORY_PROFILE_DRIVER_INFO_DATA
*DriverInfoData
;
2687 MEMORY_PROFILE_ALLOC_INFO_DATA
*AllocInfoData
;
2688 LIST_ENTRY
*SmramDriverInfoList
;
2690 LIST_ENTRY
*DriverLink
;
2691 LIST_ENTRY
*AllocInfoList
;
2693 LIST_ENTRY
*AllocLink
;
2694 BOOLEAN SmramProfileGettingStatus
;
2697 ContextData
= GetSmramProfileContext ();
2698 if (ContextData
== NULL
) {
2702 SmramProfileGettingStatus
= mSmramProfileGettingStatus
;
2703 mSmramProfileGettingStatus
= TRUE
;
2705 Context
= &ContextData
->Context
;
2706 DEBUG ((DEBUG_INFO
, "======= SmramProfile begin =======\n"));
2707 DEBUG ((DEBUG_INFO
, "MEMORY_PROFILE_CONTEXT\n"));
2709 DEBUG ((DEBUG_INFO
, " CurrentTotalUsage - 0x%016lx\n", Context
->CurrentTotalUsage
));
2710 DEBUG ((DEBUG_INFO
, " PeakTotalUsage - 0x%016lx\n", Context
->PeakTotalUsage
));
2711 for (TypeIndex
= 0; TypeIndex
< sizeof (Context
->CurrentTotalUsageByType
) / sizeof (Context
->CurrentTotalUsageByType
[0]); TypeIndex
++) {
2712 if ((Context
->CurrentTotalUsageByType
[TypeIndex
] != 0) ||
2713 (Context
->PeakTotalUsageByType
[TypeIndex
] != 0))
2715 DEBUG ((DEBUG_INFO
, " CurrentTotalUsage[0x%02x] - 0x%016lx (%a)\n", TypeIndex
, Context
->CurrentTotalUsageByType
[TypeIndex
], ProfileMemoryTypeToStr (TypeIndex
)));
2716 DEBUG ((DEBUG_INFO
, " PeakTotalUsage[0x%02x] - 0x%016lx (%a)\n", TypeIndex
, Context
->PeakTotalUsageByType
[TypeIndex
], ProfileMemoryTypeToStr (TypeIndex
)));
2720 DEBUG ((DEBUG_INFO
, " TotalImageSize - 0x%016lx\n", Context
->TotalImageSize
));
2721 DEBUG ((DEBUG_INFO
, " ImageCount - 0x%08x\n", Context
->ImageCount
));
2722 DEBUG ((DEBUG_INFO
, " SequenceCount - 0x%08x\n", Context
->SequenceCount
));
2724 SmramDriverInfoList
= ContextData
->DriverInfoList
;
2725 for (DriverLink
= SmramDriverInfoList
->ForwardLink
, DriverIndex
= 0;
2726 DriverLink
!= SmramDriverInfoList
;
2727 DriverLink
= DriverLink
->ForwardLink
, DriverIndex
++)
2729 DriverInfoData
= CR (
2731 MEMORY_PROFILE_DRIVER_INFO_DATA
,
2733 MEMORY_PROFILE_DRIVER_INFO_SIGNATURE
2735 DriverInfo
= &DriverInfoData
->DriverInfo
;
2736 DEBUG ((DEBUG_INFO
, " MEMORY_PROFILE_DRIVER_INFO (0x%x)\n", DriverIndex
));
2737 DEBUG ((DEBUG_INFO
, " FileName - %g\n", &DriverInfo
->FileName
));
2738 DEBUG ((DEBUG_INFO
, " ImageBase - 0x%016lx\n", DriverInfo
->ImageBase
));
2739 DEBUG ((DEBUG_INFO
, " ImageSize - 0x%016lx\n", DriverInfo
->ImageSize
));
2740 DEBUG ((DEBUG_INFO
, " EntryPoint - 0x%016lx\n", DriverInfo
->EntryPoint
));
2741 DEBUG ((DEBUG_INFO
, " ImageSubsystem - 0x%04x\n", DriverInfo
->ImageSubsystem
));
2742 DEBUG ((DEBUG_INFO
, " FileType - 0x%02x\n", DriverInfo
->FileType
));
2743 DEBUG ((DEBUG_INFO
, " CurrentUsage - 0x%016lx\n", DriverInfo
->CurrentUsage
));
2744 DEBUG ((DEBUG_INFO
, " PeakUsage - 0x%016lx\n", DriverInfo
->PeakUsage
));
2745 for (TypeIndex
= 0; TypeIndex
< sizeof (DriverInfo
->CurrentUsageByType
) / sizeof (DriverInfo
->CurrentUsageByType
[0]); TypeIndex
++) {
2746 if ((DriverInfo
->CurrentUsageByType
[TypeIndex
] != 0) ||
2747 (DriverInfo
->PeakUsageByType
[TypeIndex
] != 0))
2749 DEBUG ((DEBUG_INFO
, " CurrentUsage[0x%02x] - 0x%016lx (%a)\n", TypeIndex
, DriverInfo
->CurrentUsageByType
[TypeIndex
], ProfileMemoryTypeToStr (TypeIndex
)));
2750 DEBUG ((DEBUG_INFO
, " PeakUsage[0x%02x] - 0x%016lx (%a)\n", TypeIndex
, DriverInfo
->PeakUsageByType
[TypeIndex
], ProfileMemoryTypeToStr (TypeIndex
)));
2754 DEBUG ((DEBUG_INFO
, " AllocRecordCount - 0x%08x\n", DriverInfo
->AllocRecordCount
));
2756 AllocInfoList
= DriverInfoData
->AllocInfoList
;
2757 for (AllocLink
= AllocInfoList
->ForwardLink
, AllocIndex
= 0;
2758 AllocLink
!= AllocInfoList
;
2759 AllocLink
= AllocLink
->ForwardLink
, AllocIndex
++)
2761 AllocInfoData
= CR (
2763 MEMORY_PROFILE_ALLOC_INFO_DATA
,
2765 MEMORY_PROFILE_ALLOC_INFO_SIGNATURE
2767 AllocInfo
= &AllocInfoData
->AllocInfo
;
2768 DEBUG ((DEBUG_INFO
, " MEMORY_PROFILE_ALLOC_INFO (0x%x)\n", AllocIndex
));
2769 DEBUG ((DEBUG_INFO
, " CallerAddress - 0x%016lx (Offset: 0x%08x)\n", AllocInfo
->CallerAddress
, AllocInfo
->CallerAddress
- DriverInfo
->ImageBase
));
2770 DEBUG ((DEBUG_INFO
, " SequenceId - 0x%08x\n", AllocInfo
->SequenceId
));
2771 if ((AllocInfo
->Action
& MEMORY_PROFILE_ACTION_USER_DEFINED_MASK
) != 0) {
2772 if (AllocInfoData
->ActionString
!= NULL
) {
2773 DEBUG ((DEBUG_INFO
, " Action - 0x%08x (%a)\n", AllocInfo
->Action
, AllocInfoData
->ActionString
));
2775 DEBUG ((DEBUG_INFO
, " Action - 0x%08x (UserDefined-0x%08x)\n", AllocInfo
->Action
, AllocInfo
->Action
));
2778 DEBUG ((DEBUG_INFO
, " Action - 0x%08x (%a)\n", AllocInfo
->Action
, ProfileActionToStr (AllocInfo
->Action
)));
2781 DEBUG ((DEBUG_INFO
, " MemoryType - 0x%08x (%a)\n", AllocInfo
->MemoryType
, ProfileMemoryTypeToStr (AllocInfo
->MemoryType
)));
2782 DEBUG ((DEBUG_INFO
, " Buffer - 0x%016lx\n", AllocInfo
->Buffer
));
2783 DEBUG ((DEBUG_INFO
, " Size - 0x%016lx\n", AllocInfo
->Size
));
2787 DEBUG ((DEBUG_INFO
, "======= SmramProfile end =======\n"));
2789 mSmramProfileGettingStatus
= SmramProfileGettingStatus
;
2793 Dump SMRAM information.
2801 DEBUG_CODE_BEGIN ();
2802 if (IS_SMRAM_PROFILE_ENABLED
) {
2803 DumpSmramProfile ();
2804 DumpFreePagesList ();
2805 DumpFreePoolList ();