2 Support routines for SMRAM profile.
4 Copyright (c) 2014 - 2018, Intel Corporation. All rights reserved.<BR>
5 This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php.
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
15 #include "PiSmmCore.h"
17 #define IS_SMRAM_PROFILE_ENABLED ((PcdGet8 (PcdMemoryProfilePropertyMask) & BIT1) != 0)
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 // When free memory less than 4 pages, dump it.
47 #define SMRAM_INFO_DUMP_PAGE_THRESHOLD 4
49 GLOBAL_REMOVE_IF_UNREFERENCED MEMORY_PROFILE_FREE_MEMORY mSmramFreeMemory
= {
51 MEMORY_PROFILE_FREE_MEMORY_SIGNATURE
,
52 sizeof (MEMORY_PROFILE_FREE_MEMORY
),
53 MEMORY_PROFILE_FREE_MEMORY_REVISION
59 GLOBAL_REMOVE_IF_UNREFERENCED LIST_ENTRY mImageQueue
= INITIALIZE_LIST_HEAD_VARIABLE (mImageQueue
);
60 GLOBAL_REMOVE_IF_UNREFERENCED MEMORY_PROFILE_CONTEXT_DATA mSmramProfileContext
= {
61 MEMORY_PROFILE_CONTEXT_SIGNATURE
,
64 MEMORY_PROFILE_CONTEXT_SIGNATURE
,
65 sizeof (MEMORY_PROFILE_CONTEXT
),
66 MEMORY_PROFILE_CONTEXT_REVISION
78 GLOBAL_REMOVE_IF_UNREFERENCED MEMORY_PROFILE_CONTEXT_DATA
*mSmramProfileContextPtr
= NULL
;
80 GLOBAL_REMOVE_IF_UNREFERENCED BOOLEAN mSmramReadyToLock
;
81 GLOBAL_REMOVE_IF_UNREFERENCED BOOLEAN mSmramProfileGettingStatus
= FALSE
;
82 GLOBAL_REMOVE_IF_UNREFERENCED BOOLEAN mSmramProfileRecordingEnable
= MEMORY_PROFILE_RECORDING_DISABLE
;
83 GLOBAL_REMOVE_IF_UNREFERENCED EFI_DEVICE_PATH_PROTOCOL
*mSmramProfileDriverPath
;
84 GLOBAL_REMOVE_IF_UNREFERENCED UINTN mSmramProfileDriverPathSize
;
87 Dump SMRAM infromation.
96 Get memory profile data.
98 @param[in] This The EDKII_SMM_MEMORY_PROFILE_PROTOCOL instance.
99 @param[in, out] ProfileSize On entry, points to the size in bytes of the ProfileBuffer.
100 On return, points to the size of the data returned in ProfileBuffer.
101 @param[out] ProfileBuffer Profile buffer.
103 @return EFI_SUCCESS Get the memory profile data successfully.
104 @return EFI_UNSUPPORTED Memory profile is unsupported.
105 @return EFI_BUFFER_TO_SMALL The ProfileSize is too small for the resulting data.
106 ProfileSize is updated with the size required.
111 SmramProfileProtocolGetData (
112 IN EDKII_SMM_MEMORY_PROFILE_PROTOCOL
*This
,
113 IN OUT UINT64
*ProfileSize
,
114 OUT VOID
*ProfileBuffer
118 Register image to memory profile.
120 @param[in] This The EDKII_SMM_MEMORY_PROFILE_PROTOCOL instance.
121 @param[in] FilePath File path of the image.
122 @param[in] ImageBase Image base address.
123 @param[in] ImageSize Image size.
124 @param[in] FileType File type of the image.
126 @return EFI_SUCCESS Register successfully.
127 @return EFI_UNSUPPORTED Memory profile is unsupported,
128 or memory profile for the image is not required.
129 @return EFI_OUT_OF_RESOURCE No enough resource for this register.
134 SmramProfileProtocolRegisterImage (
135 IN EDKII_SMM_MEMORY_PROFILE_PROTOCOL
*This
,
136 IN EFI_DEVICE_PATH_PROTOCOL
*FilePath
,
137 IN PHYSICAL_ADDRESS ImageBase
,
139 IN EFI_FV_FILETYPE FileType
143 Unregister image from memory profile.
145 @param[in] This The EDKII_SMM_MEMORY_PROFILE_PROTOCOL instance.
146 @param[in] FilePath File path of the image.
147 @param[in] ImageBase Image base address.
148 @param[in] ImageSize Image size.
150 @return EFI_SUCCESS Unregister successfully.
151 @return EFI_UNSUPPORTED Memory profile is unsupported,
152 or memory profile for the image is not required.
153 @return EFI_NOT_FOUND The image is not found.
158 SmramProfileProtocolUnregisterImage (
159 IN EDKII_SMM_MEMORY_PROFILE_PROTOCOL
*This
,
160 IN EFI_DEVICE_PATH_PROTOCOL
*FilePath
,
161 IN PHYSICAL_ADDRESS ImageBase
,
166 Get memory profile recording state.
168 @param[in] This The EDKII_SMM_MEMORY_PROFILE_PROTOCOL instance.
169 @param[out] RecordingState Recording state.
171 @return EFI_SUCCESS Memory profile recording state is returned.
172 @return EFI_UNSUPPORTED Memory profile is unsupported.
173 @return EFI_INVALID_PARAMETER RecordingState is NULL.
178 SmramProfileProtocolGetRecordingState (
179 IN EDKII_SMM_MEMORY_PROFILE_PROTOCOL
*This
,
180 OUT BOOLEAN
*RecordingState
184 Set memory profile recording state.
186 @param[in] This The EDKII_SMM_MEMORY_PROFILE_PROTOCOL instance.
187 @param[in] RecordingState Recording state.
189 @return EFI_SUCCESS Set memory profile recording state successfully.
190 @return EFI_UNSUPPORTED Memory profile is unsupported.
195 SmramProfileProtocolSetRecordingState (
196 IN EDKII_SMM_MEMORY_PROFILE_PROTOCOL
*This
,
197 IN BOOLEAN RecordingState
201 Record memory profile of multilevel caller.
203 @param[in] This The EDKII_SMM_MEMORY_PROFILE_PROTOCOL instance.
204 @param[in] CallerAddress Address of caller.
205 @param[in] Action Memory profile action.
206 @param[in] MemoryType Memory type.
207 EfiMaxMemoryType means the MemoryType is unknown.
208 @param[in] Buffer Buffer address.
209 @param[in] Size Buffer size.
210 @param[in] ActionString String for memory profile action.
211 Only needed for user defined allocate action.
213 @return EFI_SUCCESS Memory profile is updated.
214 @return EFI_UNSUPPORTED Memory profile is unsupported,
215 or memory profile for the image is not required,
216 or memory profile for the memory type is not required.
217 @return EFI_ACCESS_DENIED It is during memory profile data getting.
218 @return EFI_ABORTED Memory profile recording is not enabled.
219 @return EFI_OUT_OF_RESOURCES No enough resource to update memory profile for allocate action.
220 @return EFI_NOT_FOUND No matched allocate info found for free action.
225 SmramProfileProtocolRecord (
226 IN EDKII_SMM_MEMORY_PROFILE_PROTOCOL
*This
,
227 IN PHYSICAL_ADDRESS CallerAddress
,
228 IN MEMORY_PROFILE_ACTION Action
,
229 IN EFI_MEMORY_TYPE MemoryType
,
232 IN CHAR8
*ActionString OPTIONAL
235 GLOBAL_REMOVE_IF_UNREFERENCED EDKII_SMM_MEMORY_PROFILE_PROTOCOL mSmmProfileProtocol
= {
236 SmramProfileProtocolGetData
,
237 SmramProfileProtocolRegisterImage
,
238 SmramProfileProtocolUnregisterImage
,
239 SmramProfileProtocolGetRecordingState
,
240 SmramProfileProtocolSetRecordingState
,
241 SmramProfileProtocolRecord
,
245 Return SMRAM profile context.
247 @return SMRAM profile context.
250 MEMORY_PROFILE_CONTEXT_DATA
*
251 GetSmramProfileContext (
255 return mSmramProfileContextPtr
;
259 Retrieves and returns the Subsystem of a PE/COFF image that has been loaded into system memory.
260 If Pe32Data is NULL, then ASSERT().
262 @param Pe32Data The pointer to the PE/COFF image that is loaded in system memory.
264 @return The Subsystem of the PE/COFF image.
268 InternalPeCoffGetSubsystem (
272 EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION Hdr
;
273 EFI_IMAGE_DOS_HEADER
*DosHdr
;
276 ASSERT (Pe32Data
!= NULL
);
278 DosHdr
= (EFI_IMAGE_DOS_HEADER
*) Pe32Data
;
279 if (DosHdr
->e_magic
== EFI_IMAGE_DOS_SIGNATURE
) {
281 // DOS image header is present, so read the PE header after the DOS image header.
283 Hdr
.Pe32
= (EFI_IMAGE_NT_HEADERS32
*) ((UINTN
) Pe32Data
+ (UINTN
) ((DosHdr
->e_lfanew
) & 0x0ffff));
286 // DOS image header is not present, so PE header is at the image base.
288 Hdr
.Pe32
= (EFI_IMAGE_NT_HEADERS32
*) Pe32Data
;
291 if (Hdr
.Te
->Signature
== EFI_TE_IMAGE_HEADER_SIGNATURE
) {
292 return Hdr
.Te
->Subsystem
;
293 } else if (Hdr
.Pe32
->Signature
== EFI_IMAGE_NT_SIGNATURE
) {
294 Magic
= Hdr
.Pe32
->OptionalHeader
.Magic
;
295 if (Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
296 return Hdr
.Pe32
->OptionalHeader
.Subsystem
;
297 } else if (Magic
== EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC
) {
298 return Hdr
.Pe32Plus
->OptionalHeader
.Subsystem
;
306 Retrieves and returns a pointer to the entry point to a PE/COFF image that has been loaded
307 into system memory with the PE/COFF Loader Library functions.
309 Retrieves the entry point to the PE/COFF image specified by Pe32Data and returns this entry
310 point in EntryPoint. If the entry point could not be retrieved from the PE/COFF image, then
311 return RETURN_INVALID_PARAMETER. Otherwise return RETURN_SUCCESS.
312 If Pe32Data is NULL, then ASSERT().
313 If EntryPoint is NULL, then ASSERT().
315 @param Pe32Data The pointer to the PE/COFF image that is loaded in system memory.
316 @param EntryPoint The pointer to entry point to the PE/COFF image to return.
318 @retval RETURN_SUCCESS EntryPoint was returned.
319 @retval RETURN_INVALID_PARAMETER The entry point could not be found in the PE/COFF image.
323 InternalPeCoffGetEntryPoint (
325 OUT VOID
**EntryPoint
328 EFI_IMAGE_DOS_HEADER
*DosHdr
;
329 EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION Hdr
;
331 ASSERT (Pe32Data
!= NULL
);
332 ASSERT (EntryPoint
!= NULL
);
334 DosHdr
= (EFI_IMAGE_DOS_HEADER
*) Pe32Data
;
335 if (DosHdr
->e_magic
== EFI_IMAGE_DOS_SIGNATURE
) {
337 // DOS image header is present, so read the PE header after the DOS image header.
339 Hdr
.Pe32
= (EFI_IMAGE_NT_HEADERS32
*) ((UINTN
) Pe32Data
+ (UINTN
) ((DosHdr
->e_lfanew
) & 0x0ffff));
342 // DOS image header is not present, so PE header is at the image base.
344 Hdr
.Pe32
= (EFI_IMAGE_NT_HEADERS32
*) Pe32Data
;
348 // Calculate the entry point relative to the start of the image.
349 // AddressOfEntryPoint is common for PE32 & PE32+
351 if (Hdr
.Te
->Signature
== EFI_TE_IMAGE_HEADER_SIGNATURE
) {
352 *EntryPoint
= (VOID
*) ((UINTN
) Pe32Data
+ (UINTN
) (Hdr
.Te
->AddressOfEntryPoint
& 0x0ffffffff) + sizeof (EFI_TE_IMAGE_HEADER
) - Hdr
.Te
->StrippedSize
);
353 return RETURN_SUCCESS
;
354 } else if (Hdr
.Pe32
->Signature
== EFI_IMAGE_NT_SIGNATURE
) {
355 *EntryPoint
= (VOID
*) ((UINTN
) Pe32Data
+ (UINTN
) (Hdr
.Pe32
->OptionalHeader
.AddressOfEntryPoint
& 0x0ffffffff));
356 return RETURN_SUCCESS
;
359 return RETURN_UNSUPPORTED
;
365 @param ContextData Memory profile context.
366 @param FileName File name of the image.
367 @param ImageBase Image base address.
368 @param ImageSize Image size.
369 @param EntryPoint Entry point of the image.
370 @param ImageSubsystem Image subsystem of the image.
371 @param FileType File type of the image.
373 @return Pointer to memory profile driver info.
376 MEMORY_PROFILE_DRIVER_INFO_DATA
*
378 IN MEMORY_PROFILE_CONTEXT_DATA
*ContextData
,
379 IN EFI_GUID
*FileName
,
380 IN PHYSICAL_ADDRESS ImageBase
,
382 IN PHYSICAL_ADDRESS EntryPoint
,
383 IN UINT16 ImageSubsystem
,
384 IN EFI_FV_FILETYPE FileType
388 MEMORY_PROFILE_DRIVER_INFO
*DriverInfo
;
389 MEMORY_PROFILE_DRIVER_INFO_DATA
*DriverInfoData
;
390 VOID
*EntryPointInImage
;
393 UINTN PdbOccupiedSize
;
398 if (ImageBase
!= 0) {
399 PdbString
= PeCoffLoaderGetPdbPointer ((VOID
*) (UINTN
) ImageBase
);
400 if (PdbString
!= NULL
) {
401 PdbSize
= AsciiStrSize (PdbString
);
402 PdbOccupiedSize
= GET_OCCUPIED_SIZE (PdbSize
, sizeof (UINT64
));
407 // Use SmmInternalAllocatePool() that will not update profile for this AllocatePool action.
409 Status
= SmmInternalAllocatePool (
410 EfiRuntimeServicesData
,
411 sizeof (*DriverInfoData
) + sizeof (LIST_ENTRY
) + PdbSize
,
412 (VOID
**) &DriverInfoData
414 if (EFI_ERROR (Status
)) {
417 ASSERT (DriverInfoData
!= NULL
);
419 ZeroMem (DriverInfoData
, sizeof (*DriverInfoData
));
421 DriverInfo
= &DriverInfoData
->DriverInfo
;
422 DriverInfoData
->Signature
= MEMORY_PROFILE_DRIVER_INFO_SIGNATURE
;
423 DriverInfo
->Header
.Signature
= MEMORY_PROFILE_DRIVER_INFO_SIGNATURE
;
424 DriverInfo
->Header
.Length
= (UINT16
) (sizeof (MEMORY_PROFILE_DRIVER_INFO
) + PdbOccupiedSize
);
425 DriverInfo
->Header
.Revision
= MEMORY_PROFILE_DRIVER_INFO_REVISION
;
426 if (FileName
!= NULL
) {
427 CopyMem (&DriverInfo
->FileName
, FileName
, sizeof (EFI_GUID
));
429 DriverInfo
->ImageBase
= ImageBase
;
430 DriverInfo
->ImageSize
= ImageSize
;
431 DriverInfo
->EntryPoint
= EntryPoint
;
432 DriverInfo
->ImageSubsystem
= ImageSubsystem
;
433 if ((EntryPoint
!= 0) && ((EntryPoint
< ImageBase
) || (EntryPoint
>= (ImageBase
+ ImageSize
)))) {
435 // If the EntryPoint is not in the range of image buffer, it should come from emulation environment.
436 // So patch ImageBuffer here to align the EntryPoint.
438 Status
= InternalPeCoffGetEntryPoint ((VOID
*) (UINTN
) ImageBase
, &EntryPointInImage
);
439 ASSERT_EFI_ERROR (Status
);
440 DriverInfo
->ImageBase
= ImageBase
+ EntryPoint
- (PHYSICAL_ADDRESS
) (UINTN
) EntryPointInImage
;
442 DriverInfo
->FileType
= FileType
;
443 DriverInfoData
->AllocInfoList
= (LIST_ENTRY
*) (DriverInfoData
+ 1);
444 InitializeListHead (DriverInfoData
->AllocInfoList
);
445 DriverInfo
->CurrentUsage
= 0;
446 DriverInfo
->PeakUsage
= 0;
447 DriverInfo
->AllocRecordCount
= 0;
449 DriverInfo
->PdbStringOffset
= (UINT16
) sizeof (MEMORY_PROFILE_DRIVER_INFO
);
450 DriverInfoData
->PdbString
= (CHAR8
*) (DriverInfoData
->AllocInfoList
+ 1);
451 CopyMem (DriverInfoData
->PdbString
, PdbString
, PdbSize
);
453 DriverInfo
->PdbStringOffset
= 0;
454 DriverInfoData
->PdbString
= NULL
;
457 InsertTailList (ContextData
->DriverInfoList
, &DriverInfoData
->Link
);
458 ContextData
->Context
.ImageCount
++;
459 ContextData
->Context
.TotalImageSize
+= DriverInfo
->ImageSize
;
461 return DriverInfoData
;
465 Register image to DXE.
467 @param FileName File name of the image.
468 @param ImageBase Image base address.
469 @param ImageSize Image size.
470 @param FileType File type of the image.
475 IN EFI_GUID
*FileName
,
476 IN PHYSICAL_ADDRESS ImageBase
,
478 IN EFI_FV_FILETYPE FileType
482 EDKII_MEMORY_PROFILE_PROTOCOL
*ProfileProtocol
;
483 MEDIA_FW_VOL_FILEPATH_DEVICE_PATH
*FilePath
;
484 UINT8 TempBuffer
[sizeof (MEDIA_FW_VOL_FILEPATH_DEVICE_PATH
) + sizeof (EFI_DEVICE_PATH_PROTOCOL
)];
486 if (IS_UEFI_MEMORY_PROFILE_ENABLED
) {
488 FilePath
= (MEDIA_FW_VOL_FILEPATH_DEVICE_PATH
*)TempBuffer
;
489 Status
= gBS
->LocateProtocol (&gEdkiiMemoryProfileGuid
, NULL
, (VOID
**) &ProfileProtocol
);
490 if (!EFI_ERROR (Status
)) {
491 EfiInitializeFwVolDevicepathNode (FilePath
, FileName
);
492 SetDevicePathEndNode (FilePath
+ 1);
494 Status
= ProfileProtocol
->RegisterImage (
496 (EFI_DEVICE_PATH_PROTOCOL
*) FilePath
,
506 Unregister image from DXE.
508 @param FileName File name of the image.
509 @param ImageBase Image base address.
510 @param ImageSize Image size.
514 UnregisterImageFromDxe (
515 IN EFI_GUID
*FileName
,
516 IN PHYSICAL_ADDRESS ImageBase
,
521 EDKII_MEMORY_PROFILE_PROTOCOL
*ProfileProtocol
;
522 MEDIA_FW_VOL_FILEPATH_DEVICE_PATH
*FilePath
;
523 UINT8 TempBuffer
[sizeof (MEDIA_FW_VOL_FILEPATH_DEVICE_PATH
) + sizeof (EFI_DEVICE_PATH_PROTOCOL
)];
525 if (IS_UEFI_MEMORY_PROFILE_ENABLED
) {
527 FilePath
= (MEDIA_FW_VOL_FILEPATH_DEVICE_PATH
*)TempBuffer
;
528 Status
= gBS
->LocateProtocol (&gEdkiiMemoryProfileGuid
, NULL
, (VOID
*) &ProfileProtocol
);
529 if (!EFI_ERROR (Status
)) {
530 EfiInitializeFwVolDevicepathNode (FilePath
, FileName
);
531 SetDevicePathEndNode (FilePath
+ 1);
533 Status
= ProfileProtocol
->UnregisterImage (
535 (EFI_DEVICE_PATH_PROTOCOL
*) FilePath
,
544 Return if record for this driver is needed..
546 @param DriverFilePath Driver file path.
548 @retval TRUE Record for this driver is needed.
549 @retval FALSE Record for this driver is not needed.
553 NeedRecordThisDriver (
554 IN EFI_DEVICE_PATH_PROTOCOL
*DriverFilePath
557 EFI_DEVICE_PATH_PROTOCOL
*TmpDevicePath
;
558 EFI_DEVICE_PATH_PROTOCOL
*DevicePathInstance
;
559 UINTN DevicePathSize
;
562 if (!IsDevicePathValid (mSmramProfileDriverPath
, mSmramProfileDriverPathSize
)) {
564 // Invalid Device Path means record all.
570 // Record FilePath without end node.
572 FilePathSize
= GetDevicePathSize (DriverFilePath
) - sizeof(EFI_DEVICE_PATH_PROTOCOL
);
574 DevicePathInstance
= mSmramProfileDriverPath
;
577 // Find End node (it might be END_ENTIRE or END_INSTANCE)
579 TmpDevicePath
= DevicePathInstance
;
580 while (!IsDevicePathEndType (TmpDevicePath
)) {
581 TmpDevicePath
= NextDevicePathNode (TmpDevicePath
);
585 // Do not compare END node
587 DevicePathSize
= (UINTN
)TmpDevicePath
- (UINTN
)DevicePathInstance
;
588 if ((FilePathSize
== DevicePathSize
) &&
589 (CompareMem (DriverFilePath
, DevicePathInstance
, DevicePathSize
) == 0)) {
596 DevicePathInstance
= (EFI_DEVICE_PATH_PROTOCOL
*)((UINTN
)DevicePathInstance
+ DevicePathSize
+ DevicePathNodeLength(TmpDevicePath
));
597 } while (DevicePathSubType (TmpDevicePath
) != END_ENTIRE_DEVICE_PATH_SUBTYPE
);
603 Register SMM Core to SMRAM profile.
605 @param ContextData SMRAM profile context.
607 @retval TRUE Register success.
608 @retval FALSE Register fail.
613 IN MEMORY_PROFILE_CONTEXT_DATA
*ContextData
616 MEMORY_PROFILE_DRIVER_INFO_DATA
*DriverInfoData
;
617 PHYSICAL_ADDRESS ImageBase
;
618 UINT8 TempBuffer
[sizeof(MEDIA_FW_VOL_FILEPATH_DEVICE_PATH
) + sizeof(EFI_DEVICE_PATH_PROTOCOL
)];
619 MEDIA_FW_VOL_FILEPATH_DEVICE_PATH
*FilePath
;
621 FilePath
= (MEDIA_FW_VOL_FILEPATH_DEVICE_PATH
*) TempBuffer
;
622 EfiInitializeFwVolDevicepathNode (FilePath
, &gEfiCallerIdGuid
);
623 SetDevicePathEndNode (FilePath
+ 1);
625 if (!NeedRecordThisDriver ((EFI_DEVICE_PATH_PROTOCOL
*) FilePath
)) {
629 ImageBase
= gSmmCorePrivate
->PiSmmCoreImageBase
;
630 DriverInfoData
= BuildDriverInfo (
634 gSmmCorePrivate
->PiSmmCoreImageSize
,
635 gSmmCorePrivate
->PiSmmCoreEntryPoint
,
636 InternalPeCoffGetSubsystem ((VOID
*) (UINTN
) ImageBase
),
637 EFI_FV_FILETYPE_SMM_CORE
639 if (DriverInfoData
== NULL
) {
647 Initialize SMRAM profile.
655 MEMORY_PROFILE_CONTEXT_DATA
*SmramProfileContext
;
659 gSmmCorePrivate
->PiSmmCoreImageBase
,
660 gSmmCorePrivate
->PiSmmCoreImageSize
,
661 EFI_FV_FILETYPE_SMM_CORE
664 if (!IS_SMRAM_PROFILE_ENABLED
) {
668 SmramProfileContext
= GetSmramProfileContext ();
669 if (SmramProfileContext
!= NULL
) {
673 mSmramProfileGettingStatus
= FALSE
;
674 if ((PcdGet8 (PcdMemoryProfilePropertyMask
) & BIT7
) != 0) {
675 mSmramProfileRecordingEnable
= MEMORY_PROFILE_RECORDING_DISABLE
;
677 mSmramProfileRecordingEnable
= MEMORY_PROFILE_RECORDING_ENABLE
;
679 mSmramProfileDriverPathSize
= PcdGetSize (PcdMemoryProfileDriverPath
);
680 mSmramProfileDriverPath
= AllocateCopyPool (mSmramProfileDriverPathSize
, PcdGetPtr (PcdMemoryProfileDriverPath
));
681 mSmramProfileContextPtr
= &mSmramProfileContext
;
683 RegisterSmmCore (&mSmramProfileContext
);
685 DEBUG ((EFI_D_INFO
, "SmramProfileInit SmramProfileContext - 0x%x\n", &mSmramProfileContext
));
689 Install SMRAM profile protocol.
693 SmramProfileInstallProtocol (
700 if (!IS_SMRAM_PROFILE_ENABLED
) {
705 Status
= SmmInstallProtocolInterface (
707 &gEdkiiSmmMemoryProfileGuid
,
708 EFI_NATIVE_INTERFACE
,
711 ASSERT_EFI_ERROR (Status
);
715 Get the GUID file name from the file path.
717 @param FilePath File path.
719 @return The GUID file name from the file path.
723 GetFileNameFromFilePath (
724 IN EFI_DEVICE_PATH_PROTOCOL
*FilePath
727 MEDIA_FW_VOL_FILEPATH_DEVICE_PATH
*ThisFilePath
;
731 if (FilePath
!= NULL
) {
732 ThisFilePath
= (MEDIA_FW_VOL_FILEPATH_DEVICE_PATH
*) FilePath
;
733 while (!IsDevicePathEnd (ThisFilePath
)) {
734 FileName
= EfiGetNameGuidFromFwVolDevicePathNode (ThisFilePath
);
735 if (FileName
!= NULL
) {
738 ThisFilePath
= (MEDIA_FW_VOL_FILEPATH_DEVICE_PATH
*) NextDevicePathNode (ThisFilePath
);
746 Register SMM image to SMRAM profile.
748 @param DriverEntry SMM image info.
749 @param RegisterToDxe Register image to DXE.
751 @return EFI_SUCCESS Register successfully.
752 @return EFI_UNSUPPORTED Memory profile is unsupported,
753 or memory profile for the image is not required.
754 @return EFI_OUT_OF_RESOURCES No enough resource for this register.
758 RegisterSmramProfileImage (
759 IN EFI_SMM_DRIVER_ENTRY
*DriverEntry
,
760 IN BOOLEAN RegisterToDxe
763 MEMORY_PROFILE_CONTEXT_DATA
*ContextData
;
764 MEMORY_PROFILE_DRIVER_INFO_DATA
*DriverInfoData
;
765 UINT8 TempBuffer
[sizeof(MEDIA_FW_VOL_FILEPATH_DEVICE_PATH
) + sizeof(EFI_DEVICE_PATH_PROTOCOL
)];
766 MEDIA_FW_VOL_FILEPATH_DEVICE_PATH
*FilePath
;
770 &DriverEntry
->FileName
,
771 DriverEntry
->ImageBuffer
,
772 EFI_PAGES_TO_SIZE (DriverEntry
->NumberOfPage
),
777 if (!IS_SMRAM_PROFILE_ENABLED
) {
778 return EFI_UNSUPPORTED
;
781 FilePath
= (MEDIA_FW_VOL_FILEPATH_DEVICE_PATH
*) TempBuffer
;
782 EfiInitializeFwVolDevicepathNode (FilePath
, &DriverEntry
->FileName
);
783 SetDevicePathEndNode (FilePath
+ 1);
785 if (!NeedRecordThisDriver ((EFI_DEVICE_PATH_PROTOCOL
*) FilePath
)) {
786 return EFI_UNSUPPORTED
;
789 ContextData
= GetSmramProfileContext ();
790 if (ContextData
== NULL
) {
791 return EFI_UNSUPPORTED
;
794 DriverInfoData
= BuildDriverInfo (
796 &DriverEntry
->FileName
,
797 DriverEntry
->ImageBuffer
,
798 EFI_PAGES_TO_SIZE (DriverEntry
->NumberOfPage
),
799 DriverEntry
->ImageEntryPoint
,
800 InternalPeCoffGetSubsystem ((VOID
*) (UINTN
) DriverEntry
->ImageBuffer
),
803 if (DriverInfoData
== NULL
) {
804 return EFI_OUT_OF_RESOURCES
;
811 Search image from memory profile.
813 @param ContextData Memory profile context.
814 @param FileName Image file name.
815 @param Address Image Address.
817 @return Pointer to memory profile driver info.
820 MEMORY_PROFILE_DRIVER_INFO_DATA
*
821 GetMemoryProfileDriverInfoByFileNameAndAddress (
822 IN MEMORY_PROFILE_CONTEXT_DATA
*ContextData
,
823 IN EFI_GUID
*FileName
,
824 IN PHYSICAL_ADDRESS Address
827 MEMORY_PROFILE_DRIVER_INFO
*DriverInfo
;
828 MEMORY_PROFILE_DRIVER_INFO_DATA
*DriverInfoData
;
829 LIST_ENTRY
*DriverLink
;
830 LIST_ENTRY
*DriverInfoList
;
832 DriverInfoList
= ContextData
->DriverInfoList
;
834 for (DriverLink
= DriverInfoList
->ForwardLink
;
835 DriverLink
!= DriverInfoList
;
836 DriverLink
= DriverLink
->ForwardLink
) {
837 DriverInfoData
= CR (
839 MEMORY_PROFILE_DRIVER_INFO_DATA
,
841 MEMORY_PROFILE_DRIVER_INFO_SIGNATURE
843 DriverInfo
= &DriverInfoData
->DriverInfo
;
844 if ((CompareGuid (&DriverInfo
->FileName
, FileName
)) &&
845 (Address
>= DriverInfo
->ImageBase
) &&
846 (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
) {
880 DriverInfoData
= CR (
882 MEMORY_PROFILE_DRIVER_INFO_DATA
,
884 MEMORY_PROFILE_DRIVER_INFO_SIGNATURE
886 DriverInfo
= &DriverInfoData
->DriverInfo
;
887 if ((Address
>= DriverInfo
->ImageBase
) &&
888 (Address
< (DriverInfo
->ImageBase
+ DriverInfo
->ImageSize
))) {
889 return DriverInfoData
;
897 Unregister image from SMRAM profile.
899 @param DriverEntry SMM image info.
900 @param UnregisterFromDxe Unregister image from DXE.
902 @return EFI_SUCCESS Unregister successfully.
903 @return EFI_UNSUPPORTED Memory profile is unsupported,
904 or memory profile for the image is not required.
905 @return EFI_NOT_FOUND The image is not found.
909 UnregisterSmramProfileImage (
910 IN EFI_SMM_DRIVER_ENTRY
*DriverEntry
,
911 IN BOOLEAN UnregisterFromDxe
915 MEMORY_PROFILE_CONTEXT_DATA
*ContextData
;
916 MEMORY_PROFILE_DRIVER_INFO_DATA
*DriverInfoData
;
918 PHYSICAL_ADDRESS ImageAddress
;
919 VOID
*EntryPointInImage
;
920 UINT8 TempBuffer
[sizeof(MEDIA_FW_VOL_FILEPATH_DEVICE_PATH
) + sizeof(EFI_DEVICE_PATH_PROTOCOL
)];
921 MEDIA_FW_VOL_FILEPATH_DEVICE_PATH
*FilePath
;
923 if (UnregisterFromDxe
) {
924 UnregisterImageFromDxe (
925 &DriverEntry
->FileName
,
926 DriverEntry
->ImageBuffer
,
927 EFI_PAGES_TO_SIZE (DriverEntry
->NumberOfPage
)
931 if (!IS_SMRAM_PROFILE_ENABLED
) {
932 return EFI_UNSUPPORTED
;
935 FilePath
= (MEDIA_FW_VOL_FILEPATH_DEVICE_PATH
*) TempBuffer
;
936 EfiInitializeFwVolDevicepathNode (FilePath
, &DriverEntry
->FileName
);
937 SetDevicePathEndNode (FilePath
+ 1);
939 if (!NeedRecordThisDriver ((EFI_DEVICE_PATH_PROTOCOL
*) FilePath
)) {
940 return EFI_UNSUPPORTED
;
943 ContextData
= GetSmramProfileContext ();
944 if (ContextData
== NULL
) {
945 return EFI_UNSUPPORTED
;
948 DriverInfoData
= NULL
;
949 FileName
= &DriverEntry
->FileName
;
950 ImageAddress
= DriverEntry
->ImageBuffer
;
951 if ((DriverEntry
->ImageEntryPoint
< ImageAddress
) || (DriverEntry
->ImageEntryPoint
>= (ImageAddress
+ EFI_PAGES_TO_SIZE (DriverEntry
->NumberOfPage
)))) {
953 // If the EntryPoint is not in the range of image buffer, it should come from emulation environment.
954 // So patch ImageAddress here to align the EntryPoint.
956 Status
= InternalPeCoffGetEntryPoint ((VOID
*) (UINTN
) ImageAddress
, &EntryPointInImage
);
957 ASSERT_EFI_ERROR (Status
);
958 ImageAddress
= ImageAddress
+ (UINTN
) DriverEntry
->ImageEntryPoint
- (UINTN
) EntryPointInImage
;
960 if (FileName
!= NULL
) {
961 DriverInfoData
= GetMemoryProfileDriverInfoByFileNameAndAddress (ContextData
, FileName
, ImageAddress
);
963 if (DriverInfoData
== NULL
) {
964 DriverInfoData
= GetMemoryProfileDriverInfoFromAddress (ContextData
, ImageAddress
);
966 if (DriverInfoData
== NULL
) {
967 return EFI_NOT_FOUND
;
970 ContextData
->Context
.TotalImageSize
-= DriverInfoData
->DriverInfo
.ImageSize
;
972 // Keep the ImageBase for RVA calculation in Application.
973 //DriverInfoData->DriverInfo.ImageBase = 0;
974 DriverInfoData
->DriverInfo
.ImageSize
= 0;
976 if (DriverInfoData
->DriverInfo
.PeakUsage
== 0) {
977 ContextData
->Context
.ImageCount
--;
978 RemoveEntryList (&DriverInfoData
->Link
);
980 // Use SmmInternalFreePool() that will not update profile for this FreePool action.
982 SmmInternalFreePool (DriverInfoData
);
989 Return if this memory type needs to be recorded into memory profile.
990 Only need to record EfiRuntimeServicesCode and EfiRuntimeServicesData for SMRAM profile.
992 @param MemoryType Memory type.
994 @retval TRUE This memory type need to be recorded.
995 @retval FALSE This memory type need not to be recorded.
999 SmmCoreNeedRecordProfile (
1000 IN EFI_MEMORY_TYPE MemoryType
1005 if (MemoryType
!= EfiRuntimeServicesCode
&&
1006 MemoryType
!= EfiRuntimeServicesData
) {
1010 TestBit
= LShiftU64 (1, MemoryType
);
1012 if ((PcdGet64 (PcdMemoryProfileMemoryType
) & TestBit
) != 0) {
1020 Convert EFI memory type to profile memory index. The rule is:
1021 If BIOS memory type (0 ~ EfiMaxMemoryType - 1), ProfileMemoryIndex = MemoryType.
1022 As SMRAM profile is only to record EfiRuntimeServicesCode and EfiRuntimeServicesData,
1023 so return input memory type directly.
1025 @param MemoryType Memory type.
1027 @return EFI memory type as profile memory index.
1031 GetProfileMemoryIndex (
1032 IN EFI_MEMORY_TYPE MemoryType
1039 Update SMRAM profile FreeMemoryPages information
1041 @param ContextData Memory profile context.
1045 SmramProfileUpdateFreePages (
1046 IN MEMORY_PROFILE_CONTEXT_DATA
*ContextData
1050 FREE_PAGE_LIST
*Pages
;
1051 LIST_ENTRY
*FreePageList
;
1052 UINTN NumberOfPages
;
1055 FreePageList
= &mSmmMemoryMap
;
1056 for (Node
= FreePageList
->BackLink
;
1057 Node
!= FreePageList
;
1058 Node
= Node
->BackLink
) {
1059 Pages
= BASE_CR (Node
, FREE_PAGE_LIST
, Link
);
1060 NumberOfPages
+= Pages
->NumberOfPages
;
1063 mSmramFreeMemory
.TotalFreeMemoryPages
= NumberOfPages
;
1065 if (NumberOfPages
<= SMRAM_INFO_DUMP_PAGE_THRESHOLD
) {
1071 Update SMRAM profile Allocate information.
1073 @param CallerAddress Address of caller who call Allocate.
1074 @param Action This Allocate action.
1075 @param MemoryType Memory type.
1076 @param Size Buffer size.
1077 @param Buffer Buffer address.
1078 @param ActionString String for memory profile action.
1080 @return EFI_SUCCESS Memory profile is updated.
1081 @return EFI_UNSUPPORTED Memory profile is unsupported,
1082 or memory profile for the image is not required.
1083 @return EFI_OUT_OF_RESOURCES No enough resource to update memory profile for allocate action.
1087 SmmCoreUpdateProfileAllocate (
1088 IN PHYSICAL_ADDRESS CallerAddress
,
1089 IN MEMORY_PROFILE_ACTION Action
,
1090 IN EFI_MEMORY_TYPE MemoryType
,
1093 IN CHAR8
*ActionString OPTIONAL
1097 MEMORY_PROFILE_CONTEXT
*Context
;
1098 MEMORY_PROFILE_DRIVER_INFO
*DriverInfo
;
1099 MEMORY_PROFILE_ALLOC_INFO
*AllocInfo
;
1100 MEMORY_PROFILE_CONTEXT_DATA
*ContextData
;
1101 MEMORY_PROFILE_DRIVER_INFO_DATA
*DriverInfoData
;
1102 MEMORY_PROFILE_ALLOC_INFO_DATA
*AllocInfoData
;
1103 EFI_MEMORY_TYPE ProfileMemoryIndex
;
1104 MEMORY_PROFILE_ACTION BasicAction
;
1105 UINTN ActionStringSize
;
1106 UINTN ActionStringOccupiedSize
;
1108 BasicAction
= Action
& MEMORY_PROFILE_ACTION_BASIC_MASK
;
1110 ContextData
= GetSmramProfileContext ();
1111 if (ContextData
== NULL
) {
1112 return EFI_UNSUPPORTED
;
1115 DriverInfoData
= GetMemoryProfileDriverInfoFromAddress (ContextData
, CallerAddress
);
1116 if (DriverInfoData
== NULL
) {
1117 return EFI_UNSUPPORTED
;
1120 ActionStringSize
= 0;
1121 ActionStringOccupiedSize
= 0;
1122 if (ActionString
!= NULL
) {
1123 ActionStringSize
= AsciiStrSize (ActionString
);
1124 ActionStringOccupiedSize
= GET_OCCUPIED_SIZE (ActionStringSize
, sizeof (UINT64
));
1128 // Use SmmInternalAllocatePool() that will not update profile for this AllocatePool action.
1130 AllocInfoData
= NULL
;
1131 Status
= SmmInternalAllocatePool (
1132 EfiRuntimeServicesData
,
1133 sizeof (*AllocInfoData
) + ActionStringSize
,
1134 (VOID
**) &AllocInfoData
1136 if (EFI_ERROR (Status
)) {
1137 return EFI_OUT_OF_RESOURCES
;
1139 ASSERT (AllocInfoData
!= NULL
);
1142 // Only update SequenceCount if and only if it is basic action.
1144 if (Action
== BasicAction
) {
1145 ContextData
->Context
.SequenceCount
++;
1148 AllocInfo
= &AllocInfoData
->AllocInfo
;
1149 AllocInfoData
->Signature
= MEMORY_PROFILE_ALLOC_INFO_SIGNATURE
;
1150 AllocInfo
->Header
.Signature
= MEMORY_PROFILE_ALLOC_INFO_SIGNATURE
;
1151 AllocInfo
->Header
.Length
= (UINT16
) (sizeof (MEMORY_PROFILE_ALLOC_INFO
) + ActionStringOccupiedSize
);
1152 AllocInfo
->Header
.Revision
= MEMORY_PROFILE_ALLOC_INFO_REVISION
;
1153 AllocInfo
->CallerAddress
= CallerAddress
;
1154 AllocInfo
->SequenceId
= ContextData
->Context
.SequenceCount
;
1155 AllocInfo
->Action
= Action
;
1156 AllocInfo
->MemoryType
= MemoryType
;
1157 AllocInfo
->Buffer
= (PHYSICAL_ADDRESS
) (UINTN
) Buffer
;
1158 AllocInfo
->Size
= Size
;
1159 if (ActionString
!= NULL
) {
1160 AllocInfo
->ActionStringOffset
= (UINT16
) sizeof (MEMORY_PROFILE_ALLOC_INFO
);
1161 AllocInfoData
->ActionString
= (CHAR8
*) (AllocInfoData
+ 1);
1162 CopyMem (AllocInfoData
->ActionString
, ActionString
, ActionStringSize
);
1164 AllocInfo
->ActionStringOffset
= 0;
1165 AllocInfoData
->ActionString
= NULL
;
1168 InsertTailList (DriverInfoData
->AllocInfoList
, &AllocInfoData
->Link
);
1170 Context
= &ContextData
->Context
;
1171 DriverInfo
= &DriverInfoData
->DriverInfo
;
1172 DriverInfo
->AllocRecordCount
++;
1175 // Update summary if and only if it is basic action.
1177 if (Action
== BasicAction
) {
1178 ProfileMemoryIndex
= GetProfileMemoryIndex (MemoryType
);
1180 DriverInfo
->CurrentUsage
+= Size
;
1181 if (DriverInfo
->PeakUsage
< DriverInfo
->CurrentUsage
) {
1182 DriverInfo
->PeakUsage
= DriverInfo
->CurrentUsage
;
1184 DriverInfo
->CurrentUsageByType
[ProfileMemoryIndex
] += Size
;
1185 if (DriverInfo
->PeakUsageByType
[ProfileMemoryIndex
] < DriverInfo
->CurrentUsageByType
[ProfileMemoryIndex
]) {
1186 DriverInfo
->PeakUsageByType
[ProfileMemoryIndex
] = DriverInfo
->CurrentUsageByType
[ProfileMemoryIndex
];
1189 Context
->CurrentTotalUsage
+= Size
;
1190 if (Context
->PeakTotalUsage
< Context
->CurrentTotalUsage
) {
1191 Context
->PeakTotalUsage
= Context
->CurrentTotalUsage
;
1193 Context
->CurrentTotalUsageByType
[ProfileMemoryIndex
] += Size
;
1194 if (Context
->PeakTotalUsageByType
[ProfileMemoryIndex
] < Context
->CurrentTotalUsageByType
[ProfileMemoryIndex
]) {
1195 Context
->PeakTotalUsageByType
[ProfileMemoryIndex
] = Context
->CurrentTotalUsageByType
[ProfileMemoryIndex
];
1198 SmramProfileUpdateFreePages (ContextData
);
1205 Get memory profile alloc info from memory profile
1207 @param DriverInfoData Driver info
1208 @param BasicAction This Free basic action
1209 @param Size Buffer size
1210 @param Buffer Buffer address
1212 @return Pointer to memory profile alloc info.
1214 MEMORY_PROFILE_ALLOC_INFO_DATA
*
1215 GetMemoryProfileAllocInfoFromAddress (
1216 IN MEMORY_PROFILE_DRIVER_INFO_DATA
*DriverInfoData
,
1217 IN MEMORY_PROFILE_ACTION BasicAction
,
1222 LIST_ENTRY
*AllocInfoList
;
1223 LIST_ENTRY
*AllocLink
;
1224 MEMORY_PROFILE_ALLOC_INFO
*AllocInfo
;
1225 MEMORY_PROFILE_ALLOC_INFO_DATA
*AllocInfoData
;
1227 AllocInfoList
= DriverInfoData
->AllocInfoList
;
1229 for (AllocLink
= AllocInfoList
->ForwardLink
;
1230 AllocLink
!= AllocInfoList
;
1231 AllocLink
= AllocLink
->ForwardLink
) {
1232 AllocInfoData
= CR (
1234 MEMORY_PROFILE_ALLOC_INFO_DATA
,
1236 MEMORY_PROFILE_ALLOC_INFO_SIGNATURE
1238 AllocInfo
= &AllocInfoData
->AllocInfo
;
1239 if ((AllocInfo
->Action
& MEMORY_PROFILE_ACTION_BASIC_MASK
) != BasicAction
) {
1242 switch (BasicAction
) {
1243 case MemoryProfileActionAllocatePages
:
1244 if ((AllocInfo
->Buffer
<= (PHYSICAL_ADDRESS
) (UINTN
) Buffer
) &&
1245 ((AllocInfo
->Buffer
+ AllocInfo
->Size
) >= ((PHYSICAL_ADDRESS
) (UINTN
) Buffer
+ Size
))) {
1246 return AllocInfoData
;
1249 case MemoryProfileActionAllocatePool
:
1250 if (AllocInfo
->Buffer
== (PHYSICAL_ADDRESS
) (UINTN
) Buffer
) {
1251 return AllocInfoData
;
1264 Update SMRAM profile Free information.
1266 @param CallerAddress Address of caller who call Free.
1267 @param Action This Free action.
1268 @param Size Buffer size.
1269 @param Buffer Buffer address.
1271 @return EFI_SUCCESS Memory profile is updated.
1272 @return EFI_UNSUPPORTED Memory profile is unsupported.
1273 @return EFI_NOT_FOUND No matched allocate info found for free action.
1277 SmmCoreUpdateProfileFree (
1278 IN PHYSICAL_ADDRESS CallerAddress
,
1279 IN MEMORY_PROFILE_ACTION Action
,
1284 MEMORY_PROFILE_CONTEXT
*Context
;
1285 MEMORY_PROFILE_DRIVER_INFO
*DriverInfo
;
1286 MEMORY_PROFILE_ALLOC_INFO
*AllocInfo
;
1287 MEMORY_PROFILE_CONTEXT_DATA
*ContextData
;
1288 MEMORY_PROFILE_DRIVER_INFO_DATA
*DriverInfoData
;
1289 LIST_ENTRY
*DriverLink
;
1290 LIST_ENTRY
*DriverInfoList
;
1291 MEMORY_PROFILE_DRIVER_INFO_DATA
*ThisDriverInfoData
;
1292 MEMORY_PROFILE_ALLOC_INFO_DATA
*AllocInfoData
;
1293 EFI_MEMORY_TYPE ProfileMemoryIndex
;
1294 MEMORY_PROFILE_ACTION BasicAction
;
1297 BasicAction
= Action
& MEMORY_PROFILE_ACTION_BASIC_MASK
;
1299 ContextData
= GetSmramProfileContext ();
1300 if (ContextData
== NULL
) {
1301 return EFI_UNSUPPORTED
;
1304 DriverInfoData
= GetMemoryProfileDriverInfoFromAddress (ContextData
, CallerAddress
);
1307 // Do not return if DriverInfoData == NULL here,
1308 // because driver A might free memory allocated by driver B.
1312 // Need use do-while loop to find all possible record,
1313 // because one address might be recorded multiple times.
1316 AllocInfoData
= NULL
;
1318 if (DriverInfoData
!= NULL
) {
1319 switch (BasicAction
) {
1320 case MemoryProfileActionFreePages
:
1321 AllocInfoData
= GetMemoryProfileAllocInfoFromAddress (DriverInfoData
, MemoryProfileActionAllocatePages
, Size
, Buffer
);
1323 case MemoryProfileActionFreePool
:
1324 AllocInfoData
= GetMemoryProfileAllocInfoFromAddress (DriverInfoData
, MemoryProfileActionAllocatePool
, 0, Buffer
);
1328 AllocInfoData
= NULL
;
1332 if (AllocInfoData
== NULL
) {
1334 // Legal case, because driver A might free memory allocated by driver B, by some protocol.
1336 DriverInfoList
= ContextData
->DriverInfoList
;
1338 for (DriverLink
= DriverInfoList
->ForwardLink
;
1339 DriverLink
!= DriverInfoList
;
1340 DriverLink
= DriverLink
->ForwardLink
) {
1341 ThisDriverInfoData
= CR (
1343 MEMORY_PROFILE_DRIVER_INFO_DATA
,
1345 MEMORY_PROFILE_DRIVER_INFO_SIGNATURE
1347 switch (BasicAction
) {
1348 case MemoryProfileActionFreePages
:
1349 AllocInfoData
= GetMemoryProfileAllocInfoFromAddress (ThisDriverInfoData
, MemoryProfileActionAllocatePages
, Size
, Buffer
);
1351 case MemoryProfileActionFreePool
:
1352 AllocInfoData
= GetMemoryProfileAllocInfoFromAddress (ThisDriverInfoData
, MemoryProfileActionAllocatePool
, 0, Buffer
);
1356 AllocInfoData
= NULL
;
1359 if (AllocInfoData
!= NULL
) {
1360 DriverInfoData
= ThisDriverInfoData
;
1365 if (AllocInfoData
== NULL
) {
1367 // If (!Found), no matched allocate info is found for this free action.
1368 // It is because the specified memory type allocate actions have been filtered by
1369 // CoreNeedRecordProfile(), but free actions have no memory type information,
1370 // they can not be filtered by CoreNeedRecordProfile(). Then, they will be
1373 // If (Found), it is normal exit path.
1374 return (Found
? EFI_SUCCESS
: EFI_NOT_FOUND
);
1378 ASSERT (DriverInfoData
!= NULL
);
1379 ASSERT (AllocInfoData
!= NULL
);
1383 Context
= &ContextData
->Context
;
1384 DriverInfo
= &DriverInfoData
->DriverInfo
;
1385 AllocInfo
= &AllocInfoData
->AllocInfo
;
1387 DriverInfo
->AllocRecordCount
--;
1389 // Update summary if and only if it is basic action.
1391 if (AllocInfo
->Action
== (AllocInfo
->Action
& MEMORY_PROFILE_ACTION_BASIC_MASK
)) {
1392 ProfileMemoryIndex
= GetProfileMemoryIndex (AllocInfo
->MemoryType
);
1394 Context
->CurrentTotalUsage
-= AllocInfo
->Size
;
1395 Context
->CurrentTotalUsageByType
[ProfileMemoryIndex
] -= AllocInfo
->Size
;
1397 DriverInfo
->CurrentUsage
-= AllocInfo
->Size
;
1398 DriverInfo
->CurrentUsageByType
[ProfileMemoryIndex
] -= AllocInfo
->Size
;
1401 RemoveEntryList (&AllocInfoData
->Link
);
1403 if (BasicAction
== MemoryProfileActionFreePages
) {
1404 if (AllocInfo
->Buffer
!= (PHYSICAL_ADDRESS
) (UINTN
) Buffer
) {
1405 SmmCoreUpdateProfileAllocate (
1406 AllocInfo
->CallerAddress
,
1408 AllocInfo
->MemoryType
,
1409 (UINTN
) ((PHYSICAL_ADDRESS
) (UINTN
) Buffer
- AllocInfo
->Buffer
),
1410 (VOID
*) (UINTN
) AllocInfo
->Buffer
,
1411 AllocInfoData
->ActionString
1414 if (AllocInfo
->Buffer
+ AllocInfo
->Size
!= ((PHYSICAL_ADDRESS
) (UINTN
) Buffer
+ Size
)) {
1415 SmmCoreUpdateProfileAllocate (
1416 AllocInfo
->CallerAddress
,
1418 AllocInfo
->MemoryType
,
1419 (UINTN
) ((AllocInfo
->Buffer
+ AllocInfo
->Size
) - ((PHYSICAL_ADDRESS
) (UINTN
) Buffer
+ Size
)),
1420 (VOID
*) ((UINTN
) Buffer
+ Size
),
1421 AllocInfoData
->ActionString
1427 // Use SmmInternalFreePool() that will not update profile for this FreePool action.
1429 SmmInternalFreePool (AllocInfoData
);
1434 Update SMRAM profile information.
1436 @param CallerAddress Address of caller who call Allocate or Free.
1437 @param Action This Allocate or Free action.
1438 @param MemoryType Memory type.
1439 EfiMaxMemoryType means the MemoryType is unknown.
1440 @param Size Buffer size.
1441 @param Buffer Buffer address.
1442 @param ActionString String for memory profile action.
1443 Only needed for user defined allocate action.
1445 @return EFI_SUCCESS Memory profile is updated.
1446 @return EFI_UNSUPPORTED Memory profile is unsupported,
1447 or memory profile for the image is not required,
1448 or memory profile for the memory type is not required.
1449 @return EFI_ACCESS_DENIED It is during memory profile data getting.
1450 @return EFI_ABORTED Memory profile recording is not enabled.
1451 @return EFI_OUT_OF_RESOURCES No enough resource to update memory profile for allocate action.
1452 @return EFI_NOT_FOUND No matched allocate info found for free action.
1457 SmmCoreUpdateProfile (
1458 IN PHYSICAL_ADDRESS CallerAddress
,
1459 IN MEMORY_PROFILE_ACTION Action
,
1460 IN EFI_MEMORY_TYPE MemoryType
, // Valid for AllocatePages/AllocatePool
1461 IN UINTN Size
, // Valid for AllocatePages/FreePages/AllocatePool
1463 IN CHAR8
*ActionString OPTIONAL
1467 MEMORY_PROFILE_CONTEXT_DATA
*ContextData
;
1468 MEMORY_PROFILE_ACTION BasicAction
;
1470 if (!IS_SMRAM_PROFILE_ENABLED
) {
1471 return EFI_UNSUPPORTED
;
1474 if (mSmramProfileGettingStatus
) {
1475 return EFI_ACCESS_DENIED
;
1478 if (!mSmramProfileRecordingEnable
) {
1483 // Get the basic action to know how to process the record
1485 BasicAction
= Action
& MEMORY_PROFILE_ACTION_BASIC_MASK
;
1488 // Free operations have no memory type information, so skip the check.
1490 if ((BasicAction
== MemoryProfileActionAllocatePages
) || (BasicAction
== MemoryProfileActionAllocatePool
)) {
1492 // Only record limited MemoryType.
1494 if (!SmmCoreNeedRecordProfile (MemoryType
)) {
1495 return EFI_UNSUPPORTED
;
1499 ContextData
= GetSmramProfileContext ();
1500 if (ContextData
== NULL
) {
1501 return EFI_UNSUPPORTED
;
1504 switch (BasicAction
) {
1505 case MemoryProfileActionAllocatePages
:
1506 Status
= SmmCoreUpdateProfileAllocate (CallerAddress
, Action
, MemoryType
, Size
, Buffer
, ActionString
);
1508 case MemoryProfileActionFreePages
:
1509 Status
= SmmCoreUpdateProfileFree (CallerAddress
, Action
, Size
, Buffer
);
1511 case MemoryProfileActionAllocatePool
:
1512 Status
= SmmCoreUpdateProfileAllocate (CallerAddress
, Action
, MemoryType
, Size
, Buffer
, ActionString
);
1514 case MemoryProfileActionFreePool
:
1515 Status
= SmmCoreUpdateProfileFree (CallerAddress
, Action
, 0, Buffer
);
1519 Status
= EFI_UNSUPPORTED
;
1527 SMRAM profile ready to lock callback function.
1531 SmramProfileReadyToLock (
1535 if (!IS_SMRAM_PROFILE_ENABLED
) {
1539 DEBUG ((EFI_D_INFO
, "SmramProfileReadyToLock\n"));
1540 mSmramReadyToLock
= TRUE
;
1543 ////////////////////
1546 Get SMRAM profile data size.
1548 @return SMRAM profile data size.
1552 SmramProfileGetDataSize (
1556 MEMORY_PROFILE_CONTEXT_DATA
*ContextData
;
1557 MEMORY_PROFILE_DRIVER_INFO_DATA
*DriverInfoData
;
1558 MEMORY_PROFILE_ALLOC_INFO_DATA
*AllocInfoData
;
1559 LIST_ENTRY
*DriverInfoList
;
1560 LIST_ENTRY
*DriverLink
;
1561 LIST_ENTRY
*AllocInfoList
;
1562 LIST_ENTRY
*AllocLink
;
1565 LIST_ENTRY
*FreePageList
;
1566 LIST_ENTRY
*FreePoolList
;
1567 FREE_POOL_HEADER
*Pool
;
1568 UINTN PoolListIndex
;
1570 UINTN SmmPoolTypeIndex
;
1572 ContextData
= GetSmramProfileContext ();
1573 if (ContextData
== NULL
) {
1577 TotalSize
= sizeof (MEMORY_PROFILE_CONTEXT
);
1579 DriverInfoList
= ContextData
->DriverInfoList
;
1580 for (DriverLink
= DriverInfoList
->ForwardLink
;
1581 DriverLink
!= DriverInfoList
;
1582 DriverLink
= DriverLink
->ForwardLink
) {
1583 DriverInfoData
= CR (
1585 MEMORY_PROFILE_DRIVER_INFO_DATA
,
1587 MEMORY_PROFILE_DRIVER_INFO_SIGNATURE
1589 TotalSize
+= DriverInfoData
->DriverInfo
.Header
.Length
;
1591 AllocInfoList
= DriverInfoData
->AllocInfoList
;
1592 for (AllocLink
= AllocInfoList
->ForwardLink
;
1593 AllocLink
!= AllocInfoList
;
1594 AllocLink
= AllocLink
->ForwardLink
) {
1595 AllocInfoData
= CR (
1597 MEMORY_PROFILE_ALLOC_INFO_DATA
,
1599 MEMORY_PROFILE_ALLOC_INFO_SIGNATURE
1601 TotalSize
+= AllocInfoData
->AllocInfo
.Header
.Length
;
1607 FreePageList
= &mSmmMemoryMap
;
1608 for (Node
= FreePageList
->BackLink
;
1609 Node
!= FreePageList
;
1610 Node
= Node
->BackLink
) {
1613 for (SmmPoolTypeIndex
= 0; SmmPoolTypeIndex
< SmmPoolTypeMax
; SmmPoolTypeIndex
++) {
1614 for (PoolListIndex
= 0; PoolListIndex
< MAX_POOL_INDEX
; PoolListIndex
++) {
1615 FreePoolList
= &mSmmPoolLists
[SmmPoolTypeIndex
][PoolListIndex
];
1616 for (Node
= FreePoolList
->BackLink
;
1617 Node
!= FreePoolList
;
1618 Node
= Node
->BackLink
) {
1619 Pool
= BASE_CR (Node
, FREE_POOL_HEADER
, Link
);
1620 if (Pool
->Header
.Available
) {
1627 TotalSize
+= (sizeof (MEMORY_PROFILE_FREE_MEMORY
) + Index
* sizeof (MEMORY_PROFILE_DESCRIPTOR
));
1628 TotalSize
+= (sizeof (MEMORY_PROFILE_MEMORY_RANGE
) + mFullSmramRangeCount
* sizeof (MEMORY_PROFILE_DESCRIPTOR
));
1634 Copy SMRAM profile data.
1636 @param ProfileBuffer The buffer to hold SMRAM profile data.
1637 @param ProfileSize On input, profile buffer size.
1638 On output, actual profile data size copied.
1639 @param ProfileOffset On input, profile buffer offset to copy.
1640 On output, next time profile buffer offset to copy.
1644 SmramProfileCopyData (
1645 OUT VOID
*ProfileBuffer
,
1646 IN OUT UINT64
*ProfileSize
,
1647 IN OUT UINT64
*ProfileOffset
1650 MEMORY_PROFILE_CONTEXT
*Context
;
1651 MEMORY_PROFILE_DRIVER_INFO
*DriverInfo
;
1652 MEMORY_PROFILE_ALLOC_INFO
*AllocInfo
;
1653 MEMORY_PROFILE_CONTEXT_DATA
*ContextData
;
1654 MEMORY_PROFILE_DRIVER_INFO_DATA
*DriverInfoData
;
1655 MEMORY_PROFILE_ALLOC_INFO_DATA
*AllocInfoData
;
1656 LIST_ENTRY
*DriverInfoList
;
1657 LIST_ENTRY
*DriverLink
;
1658 LIST_ENTRY
*AllocInfoList
;
1659 LIST_ENTRY
*AllocLink
;
1661 FREE_PAGE_LIST
*Pages
;
1662 LIST_ENTRY
*FreePageList
;
1663 LIST_ENTRY
*FreePoolList
;
1664 FREE_POOL_HEADER
*Pool
;
1665 UINTN PoolListIndex
;
1667 MEMORY_PROFILE_FREE_MEMORY
*FreeMemory
;
1668 MEMORY_PROFILE_MEMORY_RANGE
*MemoryRange
;
1669 MEMORY_PROFILE_DESCRIPTOR
*MemoryProfileDescriptor
;
1671 UINT64 RemainingSize
;
1673 UINTN ActionStringSize
;
1674 UINTN SmmPoolTypeIndex
;
1676 ContextData
= GetSmramProfileContext ();
1677 if (ContextData
== NULL
) {
1681 RemainingSize
= *ProfileSize
;
1684 if (*ProfileOffset
< sizeof (MEMORY_PROFILE_CONTEXT
)) {
1685 if (RemainingSize
>= sizeof (MEMORY_PROFILE_CONTEXT
)) {
1686 Context
= ProfileBuffer
;
1687 CopyMem (Context
, &ContextData
->Context
, sizeof (MEMORY_PROFILE_CONTEXT
));
1688 RemainingSize
-= sizeof (MEMORY_PROFILE_CONTEXT
);
1689 ProfileBuffer
= (UINT8
*) ProfileBuffer
+ sizeof (MEMORY_PROFILE_CONTEXT
);
1694 Offset
+= sizeof (MEMORY_PROFILE_CONTEXT
);
1696 DriverInfoList
= ContextData
->DriverInfoList
;
1697 for (DriverLink
= DriverInfoList
->ForwardLink
;
1698 DriverLink
!= DriverInfoList
;
1699 DriverLink
= DriverLink
->ForwardLink
) {
1700 DriverInfoData
= CR (
1702 MEMORY_PROFILE_DRIVER_INFO_DATA
,
1704 MEMORY_PROFILE_DRIVER_INFO_SIGNATURE
1706 if (*ProfileOffset
< (Offset
+ DriverInfoData
->DriverInfo
.Header
.Length
)) {
1707 if (RemainingSize
>= DriverInfoData
->DriverInfo
.Header
.Length
) {
1708 DriverInfo
= ProfileBuffer
;
1709 CopyMem (DriverInfo
, &DriverInfoData
->DriverInfo
, sizeof (MEMORY_PROFILE_DRIVER_INFO
));
1710 if (DriverInfo
->PdbStringOffset
!= 0) {
1711 PdbSize
= AsciiStrSize (DriverInfoData
->PdbString
);
1712 CopyMem ((VOID
*) ((UINTN
) DriverInfo
+ DriverInfo
->PdbStringOffset
), DriverInfoData
->PdbString
, PdbSize
);
1714 RemainingSize
-= DriverInfo
->Header
.Length
;
1715 ProfileBuffer
= (UINT8
*) ProfileBuffer
+ DriverInfo
->Header
.Length
;
1720 Offset
+= DriverInfoData
->DriverInfo
.Header
.Length
;
1722 AllocInfoList
= DriverInfoData
->AllocInfoList
;
1723 for (AllocLink
= AllocInfoList
->ForwardLink
;
1724 AllocLink
!= AllocInfoList
;
1725 AllocLink
= AllocLink
->ForwardLink
) {
1726 AllocInfoData
= CR (
1728 MEMORY_PROFILE_ALLOC_INFO_DATA
,
1730 MEMORY_PROFILE_ALLOC_INFO_SIGNATURE
1732 if (*ProfileOffset
< (Offset
+ AllocInfoData
->AllocInfo
.Header
.Length
)) {
1733 if (RemainingSize
>= AllocInfoData
->AllocInfo
.Header
.Length
) {
1734 AllocInfo
= ProfileBuffer
;
1735 CopyMem (AllocInfo
, &AllocInfoData
->AllocInfo
, sizeof (MEMORY_PROFILE_ALLOC_INFO
));
1736 if (AllocInfo
->ActionStringOffset
) {
1737 ActionStringSize
= AsciiStrSize (AllocInfoData
->ActionString
);
1738 CopyMem ((VOID
*) ((UINTN
) AllocInfo
+ AllocInfo
->ActionStringOffset
), AllocInfoData
->ActionString
, ActionStringSize
);
1740 RemainingSize
-= AllocInfo
->Header
.Length
;
1741 ProfileBuffer
= (UINT8
*) ProfileBuffer
+ AllocInfo
->Header
.Length
;
1746 Offset
+= AllocInfoData
->AllocInfo
.Header
.Length
;
1751 if (*ProfileOffset
< (Offset
+ sizeof (MEMORY_PROFILE_FREE_MEMORY
))) {
1752 if (RemainingSize
>= sizeof (MEMORY_PROFILE_FREE_MEMORY
)) {
1753 FreeMemory
= ProfileBuffer
;
1754 CopyMem (FreeMemory
, &mSmramFreeMemory
, sizeof (MEMORY_PROFILE_FREE_MEMORY
));
1756 FreePageList
= &mSmmMemoryMap
;
1757 for (Node
= FreePageList
->BackLink
;
1758 Node
!= FreePageList
;
1759 Node
= Node
->BackLink
) {
1762 for (SmmPoolTypeIndex
= 0; SmmPoolTypeIndex
< SmmPoolTypeMax
; SmmPoolTypeIndex
++) {
1763 for (PoolListIndex
= 0; PoolListIndex
< MAX_POOL_INDEX
; PoolListIndex
++) {
1764 FreePoolList
= &mSmmPoolLists
[SmmPoolTypeIndex
][MAX_POOL_INDEX
- PoolListIndex
- 1];
1765 for (Node
= FreePoolList
->BackLink
;
1766 Node
!= FreePoolList
;
1767 Node
= Node
->BackLink
) {
1768 Pool
= BASE_CR (Node
, FREE_POOL_HEADER
, Link
);
1769 if (Pool
->Header
.Available
) {
1775 FreeMemory
->FreeMemoryEntryCount
= Index
;
1777 RemainingSize
-= sizeof (MEMORY_PROFILE_FREE_MEMORY
);
1778 ProfileBuffer
= (UINT8
*) ProfileBuffer
+ sizeof (MEMORY_PROFILE_FREE_MEMORY
);
1783 Offset
+= sizeof (MEMORY_PROFILE_FREE_MEMORY
);
1784 FreePageList
= &mSmmMemoryMap
;
1785 for (Node
= FreePageList
->BackLink
;
1786 Node
!= FreePageList
;
1787 Node
= Node
->BackLink
) {
1788 if (*ProfileOffset
< (Offset
+ sizeof (MEMORY_PROFILE_DESCRIPTOR
))) {
1789 if (RemainingSize
>= sizeof (MEMORY_PROFILE_DESCRIPTOR
)) {
1790 Pages
= BASE_CR (Node
, FREE_PAGE_LIST
, Link
);
1791 MemoryProfileDescriptor
= ProfileBuffer
;
1792 MemoryProfileDescriptor
->Header
.Signature
= MEMORY_PROFILE_DESCRIPTOR_SIGNATURE
;
1793 MemoryProfileDescriptor
->Header
.Length
= sizeof (MEMORY_PROFILE_DESCRIPTOR
);
1794 MemoryProfileDescriptor
->Header
.Revision
= MEMORY_PROFILE_DESCRIPTOR_REVISION
;
1795 MemoryProfileDescriptor
->Address
= (PHYSICAL_ADDRESS
) (UINTN
) Pages
;
1796 MemoryProfileDescriptor
->Size
= EFI_PAGES_TO_SIZE (Pages
->NumberOfPages
);
1798 RemainingSize
-= sizeof (MEMORY_PROFILE_DESCRIPTOR
);
1799 ProfileBuffer
= (UINT8
*) ProfileBuffer
+ sizeof (MEMORY_PROFILE_DESCRIPTOR
);
1804 Offset
+= sizeof (MEMORY_PROFILE_DESCRIPTOR
);
1806 for (SmmPoolTypeIndex
= 0; SmmPoolTypeIndex
< SmmPoolTypeMax
; SmmPoolTypeIndex
++) {
1807 for (PoolListIndex
= 0; PoolListIndex
< MAX_POOL_INDEX
; PoolListIndex
++) {
1808 FreePoolList
= &mSmmPoolLists
[SmmPoolTypeIndex
][MAX_POOL_INDEX
- PoolListIndex
- 1];
1809 for (Node
= FreePoolList
->BackLink
;
1810 Node
!= FreePoolList
;
1811 Node
= Node
->BackLink
) {
1812 Pool
= BASE_CR (Node
, FREE_POOL_HEADER
, Link
);
1813 if (Pool
->Header
.Available
) {
1814 if (*ProfileOffset
< (Offset
+ sizeof (MEMORY_PROFILE_DESCRIPTOR
))) {
1815 if (RemainingSize
>= sizeof (MEMORY_PROFILE_DESCRIPTOR
)) {
1816 MemoryProfileDescriptor
= ProfileBuffer
;
1817 MemoryProfileDescriptor
->Header
.Signature
= MEMORY_PROFILE_DESCRIPTOR_SIGNATURE
;
1818 MemoryProfileDescriptor
->Header
.Length
= sizeof (MEMORY_PROFILE_DESCRIPTOR
);
1819 MemoryProfileDescriptor
->Header
.Revision
= MEMORY_PROFILE_DESCRIPTOR_REVISION
;
1820 MemoryProfileDescriptor
->Address
= (PHYSICAL_ADDRESS
) (UINTN
) Pool
;
1821 MemoryProfileDescriptor
->Size
= Pool
->Header
.Size
;
1823 RemainingSize
-= sizeof (MEMORY_PROFILE_DESCRIPTOR
);
1824 ProfileBuffer
= (UINT8
*) ProfileBuffer
+ sizeof (MEMORY_PROFILE_DESCRIPTOR
);
1829 Offset
+= sizeof (MEMORY_PROFILE_DESCRIPTOR
);
1835 if (*ProfileOffset
< (Offset
+ sizeof (MEMORY_PROFILE_MEMORY_RANGE
))) {
1836 if (RemainingSize
>= sizeof (MEMORY_PROFILE_MEMORY_RANGE
)) {
1837 MemoryRange
= ProfileBuffer
;
1838 MemoryRange
->Header
.Signature
= MEMORY_PROFILE_MEMORY_RANGE_SIGNATURE
;
1839 MemoryRange
->Header
.Length
= sizeof (MEMORY_PROFILE_MEMORY_RANGE
);
1840 MemoryRange
->Header
.Revision
= MEMORY_PROFILE_MEMORY_RANGE_REVISION
;
1841 MemoryRange
->MemoryRangeCount
= (UINT32
) mFullSmramRangeCount
;
1843 RemainingSize
-= sizeof (MEMORY_PROFILE_MEMORY_RANGE
);
1844 ProfileBuffer
= (UINT8
*) ProfileBuffer
+ sizeof (MEMORY_PROFILE_MEMORY_RANGE
);
1849 Offset
+= sizeof (MEMORY_PROFILE_MEMORY_RANGE
);
1850 for (Index
= 0; Index
< mFullSmramRangeCount
; Index
++) {
1851 if (*ProfileOffset
< (Offset
+ sizeof (MEMORY_PROFILE_DESCRIPTOR
))) {
1852 if (RemainingSize
>= sizeof (MEMORY_PROFILE_DESCRIPTOR
)) {
1853 MemoryProfileDescriptor
= ProfileBuffer
;
1854 MemoryProfileDescriptor
->Header
.Signature
= MEMORY_PROFILE_DESCRIPTOR_SIGNATURE
;
1855 MemoryProfileDescriptor
->Header
.Length
= sizeof (MEMORY_PROFILE_DESCRIPTOR
);
1856 MemoryProfileDescriptor
->Header
.Revision
= MEMORY_PROFILE_DESCRIPTOR_REVISION
;
1857 MemoryProfileDescriptor
->Address
= mFullSmramRanges
[Index
].PhysicalStart
;
1858 MemoryProfileDescriptor
->Size
= mFullSmramRanges
[Index
].PhysicalSize
;
1860 RemainingSize
-= sizeof (MEMORY_PROFILE_DESCRIPTOR
);
1861 ProfileBuffer
= (UINT8
*) ProfileBuffer
+ sizeof (MEMORY_PROFILE_DESCRIPTOR
);
1866 Offset
+= sizeof (MEMORY_PROFILE_DESCRIPTOR
);
1871 // On output, actual profile data size copied.
1873 *ProfileSize
-= RemainingSize
;
1875 // On output, next time profile buffer offset to copy.
1877 *ProfileOffset
= Offset
;
1881 Get memory profile data.
1883 @param[in] This The EDKII_SMM_MEMORY_PROFILE_PROTOCOL instance.
1884 @param[in, out] ProfileSize On entry, points to the size in bytes of the ProfileBuffer.
1885 On return, points to the size of the data returned in ProfileBuffer.
1886 @param[out] ProfileBuffer Profile buffer.
1888 @return EFI_SUCCESS Get the memory profile data successfully.
1889 @return EFI_UNSUPPORTED Memory profile is unsupported.
1890 @return EFI_BUFFER_TO_SMALL The ProfileSize is too small for the resulting data.
1891 ProfileSize is updated with the size required.
1896 SmramProfileProtocolGetData (
1897 IN EDKII_SMM_MEMORY_PROFILE_PROTOCOL
*This
,
1898 IN OUT UINT64
*ProfileSize
,
1899 OUT VOID
*ProfileBuffer
1904 MEMORY_PROFILE_CONTEXT_DATA
*ContextData
;
1905 BOOLEAN SmramProfileGettingStatus
;
1907 ContextData
= GetSmramProfileContext ();
1908 if (ContextData
== NULL
) {
1909 return EFI_UNSUPPORTED
;
1912 SmramProfileGettingStatus
= mSmramProfileGettingStatus
;
1913 mSmramProfileGettingStatus
= TRUE
;
1915 Size
= SmramProfileGetDataSize ();
1917 if (*ProfileSize
< Size
) {
1918 *ProfileSize
= Size
;
1919 mSmramProfileGettingStatus
= SmramProfileGettingStatus
;
1920 return EFI_BUFFER_TOO_SMALL
;
1924 SmramProfileCopyData (ProfileBuffer
, &Size
, &Offset
);
1925 *ProfileSize
= Size
;
1927 mSmramProfileGettingStatus
= SmramProfileGettingStatus
;
1932 Register image to memory profile.
1934 @param[in] This The EDKII_SMM_MEMORY_PROFILE_PROTOCOL instance.
1935 @param[in] FilePath File path of the image.
1936 @param[in] ImageBase Image base address.
1937 @param[in] ImageSize Image size.
1938 @param[in] FileType File type of the image.
1940 @return EFI_SUCCESS Register successfully.
1941 @return EFI_UNSUPPORTED Memory profile is unsupported,
1942 or memory profile for the image is not required.
1943 @return EFI_OUT_OF_RESOURCES No enough resource for this register.
1948 SmramProfileProtocolRegisterImage (
1949 IN EDKII_SMM_MEMORY_PROFILE_PROTOCOL
*This
,
1950 IN EFI_DEVICE_PATH_PROTOCOL
*FilePath
,
1951 IN PHYSICAL_ADDRESS ImageBase
,
1952 IN UINT64 ImageSize
,
1953 IN EFI_FV_FILETYPE FileType
1957 EFI_SMM_DRIVER_ENTRY DriverEntry
;
1958 VOID
*EntryPointInImage
;
1961 ZeroMem (&DriverEntry
, sizeof (DriverEntry
));
1962 Name
= GetFileNameFromFilePath (FilePath
);
1964 CopyMem (&DriverEntry
.FileName
, Name
, sizeof (EFI_GUID
));
1966 DriverEntry
.ImageBuffer
= ImageBase
;
1967 DriverEntry
.NumberOfPage
= EFI_SIZE_TO_PAGES ((UINTN
) ImageSize
);
1968 Status
= InternalPeCoffGetEntryPoint ((VOID
*) (UINTN
) DriverEntry
.ImageBuffer
, &EntryPointInImage
);
1969 ASSERT_EFI_ERROR (Status
);
1970 DriverEntry
.ImageEntryPoint
= (PHYSICAL_ADDRESS
) (UINTN
) EntryPointInImage
;
1972 return RegisterSmramProfileImage (&DriverEntry
, FALSE
);
1976 Unregister image from memory profile.
1978 @param[in] This The EDKII_SMM_MEMORY_PROFILE_PROTOCOL instance.
1979 @param[in] FilePath File path of the image.
1980 @param[in] ImageBase Image base address.
1981 @param[in] ImageSize Image size.
1983 @return EFI_SUCCESS Unregister successfully.
1984 @return EFI_UNSUPPORTED Memory profile is unsupported,
1985 or memory profile for the image is not required.
1986 @return EFI_NOT_FOUND The image is not found.
1991 SmramProfileProtocolUnregisterImage (
1992 IN EDKII_SMM_MEMORY_PROFILE_PROTOCOL
*This
,
1993 IN EFI_DEVICE_PATH_PROTOCOL
*FilePath
,
1994 IN PHYSICAL_ADDRESS ImageBase
,
1999 EFI_SMM_DRIVER_ENTRY DriverEntry
;
2000 VOID
*EntryPointInImage
;
2003 ZeroMem (&DriverEntry
, sizeof (DriverEntry
));
2004 Name
= GetFileNameFromFilePath (FilePath
);
2006 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 UnregisterSmramProfileImage (&DriverEntry
, FALSE
);
2018 Get memory profile recording state.
2020 @param[in] This The EDKII_SMM_MEMORY_PROFILE_PROTOCOL instance.
2021 @param[out] RecordingState Recording state.
2023 @return EFI_SUCCESS Memory profile recording state is returned.
2024 @return EFI_UNSUPPORTED Memory profile is unsupported.
2025 @return EFI_INVALID_PARAMETER RecordingState is NULL.
2030 SmramProfileProtocolGetRecordingState (
2031 IN EDKII_SMM_MEMORY_PROFILE_PROTOCOL
*This
,
2032 OUT BOOLEAN
*RecordingState
2035 MEMORY_PROFILE_CONTEXT_DATA
*ContextData
;
2037 ContextData
= GetSmramProfileContext ();
2038 if (ContextData
== NULL
) {
2039 return EFI_UNSUPPORTED
;
2042 if (RecordingState
== NULL
) {
2043 return EFI_INVALID_PARAMETER
;
2045 *RecordingState
= mSmramProfileRecordingEnable
;
2050 Set memory profile recording state.
2052 @param[in] This The EDKII_SMM_MEMORY_PROFILE_PROTOCOL instance.
2053 @param[in] RecordingState Recording state.
2055 @return EFI_SUCCESS Set memory profile recording state successfully.
2056 @return EFI_UNSUPPORTED Memory profile is unsupported.
2061 SmramProfileProtocolSetRecordingState (
2062 IN EDKII_SMM_MEMORY_PROFILE_PROTOCOL
*This
,
2063 IN BOOLEAN RecordingState
2066 MEMORY_PROFILE_CONTEXT_DATA
*ContextData
;
2068 ContextData
= GetSmramProfileContext ();
2069 if (ContextData
== NULL
) {
2070 return EFI_UNSUPPORTED
;
2073 mSmramProfileRecordingEnable
= RecordingState
;
2078 Record memory profile of multilevel caller.
2080 @param[in] This The EDKII_SMM_MEMORY_PROFILE_PROTOCOL instance.
2081 @param[in] CallerAddress Address of caller.
2082 @param[in] Action Memory profile action.
2083 @param[in] MemoryType Memory type.
2084 EfiMaxMemoryType means the MemoryType is unknown.
2085 @param[in] Buffer Buffer address.
2086 @param[in] Size Buffer size.
2087 @param[in] ActionString String for memory profile action.
2088 Only needed for user defined allocate action.
2090 @return EFI_SUCCESS Memory profile is updated.
2091 @return EFI_UNSUPPORTED Memory profile is unsupported,
2092 or memory profile for the image is not required,
2093 or memory profile for the memory type is not required.
2094 @return EFI_ACCESS_DENIED It is during memory profile data getting.
2095 @return EFI_ABORTED Memory profile recording is not enabled.
2096 @return EFI_OUT_OF_RESOURCES No enough resource to update memory profile for allocate action.
2097 @return EFI_NOT_FOUND No matched allocate info found for free action.
2102 SmramProfileProtocolRecord (
2103 IN EDKII_SMM_MEMORY_PROFILE_PROTOCOL
*This
,
2104 IN PHYSICAL_ADDRESS CallerAddress
,
2105 IN MEMORY_PROFILE_ACTION Action
,
2106 IN EFI_MEMORY_TYPE MemoryType
,
2109 IN CHAR8
*ActionString OPTIONAL
2112 return SmmCoreUpdateProfile (CallerAddress
, Action
, MemoryType
, Size
, Buffer
, ActionString
);
2116 SMRAM profile handler to get profile info.
2118 @param SmramProfileParameterGetInfo The parameter of SMM profile get size.
2122 SmramProfileHandlerGetInfo (
2123 IN SMRAM_PROFILE_PARAMETER_GET_PROFILE_INFO
*SmramProfileParameterGetInfo
2126 MEMORY_PROFILE_CONTEXT_DATA
*ContextData
;
2127 BOOLEAN SmramProfileGettingStatus
;
2129 ContextData
= GetSmramProfileContext ();
2130 if (ContextData
== NULL
) {
2134 SmramProfileGettingStatus
= mSmramProfileGettingStatus
;
2135 mSmramProfileGettingStatus
= TRUE
;
2137 SmramProfileParameterGetInfo
->ProfileSize
= SmramProfileGetDataSize();
2138 SmramProfileParameterGetInfo
->Header
.ReturnStatus
= 0;
2140 mSmramProfileGettingStatus
= SmramProfileGettingStatus
;
2144 SMRAM profile handler to get profile data.
2146 @param SmramProfileParameterGetData The parameter of SMM profile get data.
2150 SmramProfileHandlerGetData (
2151 IN SMRAM_PROFILE_PARAMETER_GET_PROFILE_DATA
*SmramProfileParameterGetData
2155 UINT64 ProfileOffset
;
2156 SMRAM_PROFILE_PARAMETER_GET_PROFILE_DATA SmramProfileGetData
;
2157 MEMORY_PROFILE_CONTEXT_DATA
*ContextData
;
2158 BOOLEAN SmramProfileGettingStatus
;
2160 ContextData
= GetSmramProfileContext ();
2161 if (ContextData
== NULL
) {
2165 SmramProfileGettingStatus
= mSmramProfileGettingStatus
;
2166 mSmramProfileGettingStatus
= TRUE
;
2169 CopyMem (&SmramProfileGetData
, SmramProfileParameterGetData
, sizeof (SmramProfileGetData
));
2171 ProfileSize
= SmramProfileGetDataSize();
2176 if (!SmmIsBufferOutsideSmmValid ((UINTN
) SmramProfileGetData
.ProfileBuffer
, (UINTN
) ProfileSize
)) {
2177 DEBUG ((EFI_D_ERROR
, "SmramProfileHandlerGetData: SMM ProfileBuffer in SMRAM or overflow!\n"));
2178 SmramProfileParameterGetData
->ProfileSize
= ProfileSize
;
2179 SmramProfileParameterGetData
->Header
.ReturnStatus
= (UINT64
) (INT64
) (INTN
) EFI_ACCESS_DENIED
;
2183 if (SmramProfileGetData
.ProfileSize
< ProfileSize
) {
2184 SmramProfileParameterGetData
->ProfileSize
= ProfileSize
;
2185 SmramProfileParameterGetData
->Header
.ReturnStatus
= (UINT64
) (INT64
) (INTN
) EFI_BUFFER_TOO_SMALL
;
2190 SmramProfileCopyData ((VOID
*) (UINTN
) SmramProfileGetData
.ProfileBuffer
, &ProfileSize
, &ProfileOffset
);
2191 SmramProfileParameterGetData
->ProfileSize
= ProfileSize
;
2192 SmramProfileParameterGetData
->Header
.ReturnStatus
= 0;
2195 mSmramProfileGettingStatus
= SmramProfileGettingStatus
;
2199 SMRAM profile handler to get profile data by offset.
2201 @param SmramProfileParameterGetDataByOffset The parameter of SMM profile get data by offset.
2205 SmramProfileHandlerGetDataByOffset (
2206 IN SMRAM_PROFILE_PARAMETER_GET_PROFILE_DATA_BY_OFFSET
*SmramProfileParameterGetDataByOffset
2209 SMRAM_PROFILE_PARAMETER_GET_PROFILE_DATA_BY_OFFSET SmramProfileGetDataByOffset
;
2210 MEMORY_PROFILE_CONTEXT_DATA
*ContextData
;
2211 BOOLEAN SmramProfileGettingStatus
;
2213 ContextData
= GetSmramProfileContext ();
2214 if (ContextData
== NULL
) {
2218 SmramProfileGettingStatus
= mSmramProfileGettingStatus
;
2219 mSmramProfileGettingStatus
= TRUE
;
2222 CopyMem (&SmramProfileGetDataByOffset
, SmramProfileParameterGetDataByOffset
, sizeof (SmramProfileGetDataByOffset
));
2227 if (!SmmIsBufferOutsideSmmValid ((UINTN
) SmramProfileGetDataByOffset
.ProfileBuffer
, (UINTN
) SmramProfileGetDataByOffset
.ProfileSize
)) {
2228 DEBUG ((EFI_D_ERROR
, "SmramProfileHandlerGetDataByOffset: SMM ProfileBuffer in SMRAM or overflow!\n"));
2229 SmramProfileParameterGetDataByOffset
->Header
.ReturnStatus
= (UINT64
) (INT64
) (INTN
) EFI_ACCESS_DENIED
;
2233 SmramProfileCopyData ((VOID
*) (UINTN
) SmramProfileGetDataByOffset
.ProfileBuffer
, &SmramProfileGetDataByOffset
.ProfileSize
, &SmramProfileGetDataByOffset
.ProfileOffset
);
2234 CopyMem (SmramProfileParameterGetDataByOffset
, &SmramProfileGetDataByOffset
, sizeof (SmramProfileGetDataByOffset
));
2235 SmramProfileParameterGetDataByOffset
->Header
.ReturnStatus
= 0;
2238 mSmramProfileGettingStatus
= SmramProfileGettingStatus
;
2242 SMRAM profile handler to register SMM image.
2244 @param SmramProfileParameterRegisterImage The parameter of SMM profile register image.
2248 SmramProfileHandlerRegisterImage (
2249 IN SMRAM_PROFILE_PARAMETER_REGISTER_IMAGE
*SmramProfileParameterRegisterImage
2253 EFI_SMM_DRIVER_ENTRY DriverEntry
;
2254 VOID
*EntryPointInImage
;
2256 ZeroMem (&DriverEntry
, sizeof (DriverEntry
));
2257 CopyMem (&DriverEntry
.FileName
, &SmramProfileParameterRegisterImage
->FileName
, sizeof(EFI_GUID
));
2258 DriverEntry
.ImageBuffer
= SmramProfileParameterRegisterImage
->ImageBuffer
;
2259 DriverEntry
.NumberOfPage
= (UINTN
) SmramProfileParameterRegisterImage
->NumberOfPage
;
2260 Status
= InternalPeCoffGetEntryPoint ((VOID
*) (UINTN
) DriverEntry
.ImageBuffer
, &EntryPointInImage
);
2261 ASSERT_EFI_ERROR (Status
);
2262 DriverEntry
.ImageEntryPoint
= (PHYSICAL_ADDRESS
) (UINTN
) EntryPointInImage
;
2264 Status
= RegisterSmramProfileImage (&DriverEntry
, FALSE
);
2265 if (!EFI_ERROR (Status
)) {
2266 SmramProfileParameterRegisterImage
->Header
.ReturnStatus
= 0;
2271 SMRAM profile handler to unregister SMM image.
2273 @param SmramProfileParameterUnregisterImage The parameter of SMM profile unregister image.
2277 SmramProfileHandlerUnregisterImage (
2278 IN SMRAM_PROFILE_PARAMETER_UNREGISTER_IMAGE
*SmramProfileParameterUnregisterImage
2282 EFI_SMM_DRIVER_ENTRY DriverEntry
;
2283 VOID
*EntryPointInImage
;
2285 ZeroMem (&DriverEntry
, sizeof (DriverEntry
));
2286 CopyMem (&DriverEntry
.FileName
, &SmramProfileParameterUnregisterImage
->FileName
, sizeof (EFI_GUID
));
2287 DriverEntry
.ImageBuffer
= SmramProfileParameterUnregisterImage
->ImageBuffer
;
2288 DriverEntry
.NumberOfPage
= (UINTN
) SmramProfileParameterUnregisterImage
->NumberOfPage
;
2289 Status
= InternalPeCoffGetEntryPoint ((VOID
*) (UINTN
) DriverEntry
.ImageBuffer
, &EntryPointInImage
);
2290 ASSERT_EFI_ERROR (Status
);
2291 DriverEntry
.ImageEntryPoint
= (PHYSICAL_ADDRESS
) (UINTN
) EntryPointInImage
;
2293 Status
= UnregisterSmramProfileImage (&DriverEntry
, FALSE
);
2294 if (!EFI_ERROR (Status
)) {
2295 SmramProfileParameterUnregisterImage
->Header
.ReturnStatus
= 0;
2300 Dispatch function for a Software SMI handler.
2302 Caution: This function may receive untrusted input.
2303 Communicate buffer and buffer size are external input, so this function will do basic validation.
2305 @param DispatchHandle The unique handle assigned to this handler by SmiHandlerRegister().
2306 @param Context Points to an optional handler context which was specified when the
2307 handler was registered.
2308 @param CommBuffer A pointer to a collection of data in memory that will
2309 be conveyed from a non-SMM environment into an SMM environment.
2310 @param CommBufferSize The size of the CommBuffer.
2312 @retval EFI_SUCCESS Command is handled successfully.
2317 SmramProfileHandler (
2318 IN EFI_HANDLE DispatchHandle
,
2319 IN CONST VOID
*Context OPTIONAL
,
2320 IN OUT VOID
*CommBuffer OPTIONAL
,
2321 IN OUT UINTN
*CommBufferSize OPTIONAL
2324 SMRAM_PROFILE_PARAMETER_HEADER
*SmramProfileParameterHeader
;
2325 UINTN TempCommBufferSize
;
2326 SMRAM_PROFILE_PARAMETER_RECORDING_STATE
*ParameterRecordingState
;
2328 DEBUG ((EFI_D_ERROR
, "SmramProfileHandler Enter\n"));
2331 // If input is invalid, stop processing this SMI
2333 if (CommBuffer
== NULL
|| CommBufferSize
== NULL
) {
2337 TempCommBufferSize
= *CommBufferSize
;
2339 if (TempCommBufferSize
< sizeof (SMRAM_PROFILE_PARAMETER_HEADER
)) {
2340 DEBUG ((EFI_D_ERROR
, "SmramProfileHandler: SMM communication buffer size invalid!\n"));
2344 if (mSmramReadyToLock
&& !SmmIsBufferOutsideSmmValid ((UINTN
)CommBuffer
, TempCommBufferSize
)) {
2345 DEBUG ((EFI_D_ERROR
, "SmramProfileHandler: SMM communication buffer in SMRAM or overflow!\n"));
2349 SmramProfileParameterHeader
= (SMRAM_PROFILE_PARAMETER_HEADER
*) ((UINTN
) CommBuffer
);
2351 SmramProfileParameterHeader
->ReturnStatus
= (UINT64
)-1;
2353 if (GetSmramProfileContext () == NULL
) {
2354 SmramProfileParameterHeader
->ReturnStatus
= (UINT64
) (INT64
) (INTN
) EFI_UNSUPPORTED
;
2358 switch (SmramProfileParameterHeader
->Command
) {
2359 case SMRAM_PROFILE_COMMAND_GET_PROFILE_INFO
:
2360 DEBUG ((EFI_D_ERROR
, "SmramProfileHandlerGetInfo\n"));
2361 if (TempCommBufferSize
!= sizeof (SMRAM_PROFILE_PARAMETER_GET_PROFILE_INFO
)) {
2362 DEBUG ((EFI_D_ERROR
, "SmramProfileHandler: SMM communication buffer size invalid!\n"));
2365 SmramProfileHandlerGetInfo ((SMRAM_PROFILE_PARAMETER_GET_PROFILE_INFO
*) (UINTN
) CommBuffer
);
2367 case SMRAM_PROFILE_COMMAND_GET_PROFILE_DATA
:
2368 DEBUG ((EFI_D_ERROR
, "SmramProfileHandlerGetData\n"));
2369 if (TempCommBufferSize
!= sizeof (SMRAM_PROFILE_PARAMETER_GET_PROFILE_DATA
)) {
2370 DEBUG ((EFI_D_ERROR
, "SmramProfileHandler: SMM communication buffer size invalid!\n"));
2373 SmramProfileHandlerGetData ((SMRAM_PROFILE_PARAMETER_GET_PROFILE_DATA
*) (UINTN
) CommBuffer
);
2375 case SMRAM_PROFILE_COMMAND_GET_PROFILE_DATA_BY_OFFSET
:
2376 DEBUG ((EFI_D_ERROR
, "SmramProfileHandlerGetDataByOffset\n"));
2377 if (TempCommBufferSize
!= sizeof (SMRAM_PROFILE_PARAMETER_GET_PROFILE_DATA_BY_OFFSET
)) {
2378 DEBUG ((EFI_D_ERROR
, "SmramProfileHandler: SMM communication buffer size invalid!\n"));
2381 SmramProfileHandlerGetDataByOffset ((SMRAM_PROFILE_PARAMETER_GET_PROFILE_DATA_BY_OFFSET
*) (UINTN
) CommBuffer
);
2383 case SMRAM_PROFILE_COMMAND_REGISTER_IMAGE
:
2384 DEBUG ((EFI_D_ERROR
, "SmramProfileHandlerRegisterImage\n"));
2385 if (TempCommBufferSize
!= sizeof (SMRAM_PROFILE_PARAMETER_REGISTER_IMAGE
)) {
2386 DEBUG ((EFI_D_ERROR
, "SmramProfileHandler: SMM communication buffer size invalid!\n"));
2389 if (mSmramReadyToLock
) {
2392 SmramProfileHandlerRegisterImage ((SMRAM_PROFILE_PARAMETER_REGISTER_IMAGE
*) (UINTN
) CommBuffer
);
2394 case SMRAM_PROFILE_COMMAND_UNREGISTER_IMAGE
:
2395 DEBUG ((EFI_D_ERROR
, "SmramProfileHandlerUnregisterImage\n"));
2396 if (TempCommBufferSize
!= sizeof (SMRAM_PROFILE_PARAMETER_UNREGISTER_IMAGE
)) {
2397 DEBUG ((EFI_D_ERROR
, "SmramProfileHandler: SMM communication buffer size invalid!\n"));
2400 if (mSmramReadyToLock
) {
2403 SmramProfileHandlerUnregisterImage ((SMRAM_PROFILE_PARAMETER_UNREGISTER_IMAGE
*) (UINTN
) CommBuffer
);
2405 case SMRAM_PROFILE_COMMAND_GET_RECORDING_STATE
:
2406 DEBUG ((EFI_D_ERROR
, "SmramProfileHandlerGetRecordingState\n"));
2407 if (TempCommBufferSize
!= sizeof (SMRAM_PROFILE_PARAMETER_RECORDING_STATE
)) {
2408 DEBUG ((EFI_D_ERROR
, "SmramProfileHandler: SMM communication buffer size invalid!\n"));
2411 ParameterRecordingState
= (SMRAM_PROFILE_PARAMETER_RECORDING_STATE
*) (UINTN
) CommBuffer
;
2412 ParameterRecordingState
->RecordingState
= mSmramProfileRecordingEnable
;
2413 ParameterRecordingState
->Header
.ReturnStatus
= 0;
2415 case SMRAM_PROFILE_COMMAND_SET_RECORDING_STATE
:
2416 DEBUG ((EFI_D_ERROR
, "SmramProfileHandlerSetRecordingState\n"));
2417 if (TempCommBufferSize
!= sizeof (SMRAM_PROFILE_PARAMETER_RECORDING_STATE
)) {
2418 DEBUG ((EFI_D_ERROR
, "SmramProfileHandler: SMM communication buffer size invalid!\n"));
2421 ParameterRecordingState
= (SMRAM_PROFILE_PARAMETER_RECORDING_STATE
*) (UINTN
) CommBuffer
;
2422 mSmramProfileRecordingEnable
= ParameterRecordingState
->RecordingState
;
2423 ParameterRecordingState
->Header
.ReturnStatus
= 0;
2430 DEBUG ((EFI_D_ERROR
, "SmramProfileHandler Exit\n"));
2436 Register SMRAM profile handler.
2440 RegisterSmramProfileHandler (
2445 EFI_HANDLE DispatchHandle
;
2447 if (!IS_SMRAM_PROFILE_ENABLED
) {
2451 Status
= SmiHandlerRegister (
2452 SmramProfileHandler
,
2453 &gEdkiiMemoryProfileGuid
,
2456 ASSERT_EFI_ERROR (Status
);
2459 ////////////////////
2471 MEMORY_PROFILE_CONTEXT_DATA
*ContextData
;
2472 BOOLEAN SmramProfileGettingStatus
;
2474 ContextData
= GetSmramProfileContext ();
2475 if (ContextData
== NULL
) {
2479 SmramProfileGettingStatus
= mSmramProfileGettingStatus
;
2480 mSmramProfileGettingStatus
= TRUE
;
2482 DEBUG ((EFI_D_INFO
, "FullSmramRange address - 0x%08x\n", mFullSmramRanges
));
2484 DEBUG ((EFI_D_INFO
, "======= SmramProfile begin =======\n"));
2486 DEBUG ((EFI_D_INFO
, "FullSmramRange:\n"));
2487 for (Index
= 0; Index
< mFullSmramRangeCount
; Index
++) {
2488 DEBUG ((EFI_D_INFO
, " FullSmramRange (0x%x)\n", Index
));
2489 DEBUG ((EFI_D_INFO
, " PhysicalStart - 0x%016lx\n", mFullSmramRanges
[Index
].PhysicalStart
));
2490 DEBUG ((EFI_D_INFO
, " CpuStart - 0x%016lx\n", mFullSmramRanges
[Index
].CpuStart
));
2491 DEBUG ((EFI_D_INFO
, " PhysicalSize - 0x%016lx\n", mFullSmramRanges
[Index
].PhysicalSize
));
2492 DEBUG ((EFI_D_INFO
, " RegionState - 0x%016lx\n", mFullSmramRanges
[Index
].RegionState
));
2495 DEBUG ((EFI_D_INFO
, "======= SmramProfile end =======\n"));
2497 mSmramProfileGettingStatus
= SmramProfileGettingStatus
;
2501 Dump SMRAM free page list.
2509 LIST_ENTRY
*FreePageList
;
2511 FREE_PAGE_LIST
*Pages
;
2513 MEMORY_PROFILE_CONTEXT_DATA
*ContextData
;
2514 BOOLEAN SmramProfileGettingStatus
;
2516 ContextData
= GetSmramProfileContext ();
2517 if (ContextData
== NULL
) {
2521 SmramProfileGettingStatus
= mSmramProfileGettingStatus
;
2522 mSmramProfileGettingStatus
= TRUE
;
2524 DEBUG ((EFI_D_INFO
, "======= SmramProfile begin =======\n"));
2526 DEBUG ((EFI_D_INFO
, "FreePagesList:\n"));
2527 FreePageList
= &mSmmMemoryMap
;
2528 for (Node
= FreePageList
->BackLink
, Index
= 0;
2529 Node
!= FreePageList
;
2530 Node
= Node
->BackLink
, Index
++) {
2531 Pages
= BASE_CR (Node
, FREE_PAGE_LIST
, Link
);
2532 DEBUG ((EFI_D_INFO
, " Index - 0x%x\n", Index
));
2533 DEBUG ((EFI_D_INFO
, " PhysicalStart - 0x%016lx\n", (PHYSICAL_ADDRESS
) (UINTN
) Pages
));
2534 DEBUG ((EFI_D_INFO
, " NumberOfPages - 0x%08x\n", Pages
->NumberOfPages
));
2537 DEBUG ((EFI_D_INFO
, "======= SmramProfile end =======\n"));
2539 mSmramProfileGettingStatus
= SmramProfileGettingStatus
;
2543 Dump SMRAM free pool list.
2551 LIST_ENTRY
*FreePoolList
;
2553 FREE_POOL_HEADER
*Pool
;
2555 UINTN PoolListIndex
;
2556 MEMORY_PROFILE_CONTEXT_DATA
*ContextData
;
2557 BOOLEAN SmramProfileGettingStatus
;
2558 UINTN SmmPoolTypeIndex
;
2560 ContextData
= GetSmramProfileContext ();
2561 if (ContextData
== NULL
) {
2565 SmramProfileGettingStatus
= mSmramProfileGettingStatus
;
2566 mSmramProfileGettingStatus
= TRUE
;
2568 DEBUG ((DEBUG_INFO
, "======= SmramProfile begin =======\n"));
2570 for (SmmPoolTypeIndex
= 0; SmmPoolTypeIndex
< SmmPoolTypeMax
; SmmPoolTypeIndex
++) {
2571 for (PoolListIndex
= 0; PoolListIndex
< MAX_POOL_INDEX
; PoolListIndex
++) {
2572 DEBUG ((DEBUG_INFO
, "FreePoolList(%d)(%d):\n", SmmPoolTypeIndex
, PoolListIndex
));
2573 FreePoolList
= &mSmmPoolLists
[SmmPoolTypeIndex
][PoolListIndex
];
2574 for (Node
= FreePoolList
->BackLink
, Index
= 0;
2575 Node
!= FreePoolList
;
2576 Node
= Node
->BackLink
, Index
++) {
2577 Pool
= BASE_CR (Node
, FREE_POOL_HEADER
, Link
);
2578 DEBUG ((DEBUG_INFO
, " Index - 0x%x\n", Index
));
2579 DEBUG ((DEBUG_INFO
, " PhysicalStart - 0x%016lx\n", (PHYSICAL_ADDRESS
) (UINTN
) Pool
));
2580 DEBUG ((DEBUG_INFO
, " Size - 0x%08x\n", Pool
->Header
.Size
));
2581 DEBUG ((DEBUG_INFO
, " Available - 0x%02x\n", Pool
->Header
.Available
));
2586 DEBUG ((DEBUG_INFO
, "======= SmramProfile end =======\n"));
2588 mSmramProfileGettingStatus
= SmramProfileGettingStatus
;
2591 GLOBAL_REMOVE_IF_UNREFERENCED CHAR8
*mSmmActionString
[] = {
2593 "gSmst->SmmAllocatePages",
2594 "gSmst->SmmFreePages",
2595 "gSmst->SmmAllocatePool",
2596 "gSmst->SmmFreePool",
2600 MEMORY_PROFILE_ACTION Action
;
2604 GLOBAL_REMOVE_IF_UNREFERENCED ACTION_STRING mExtActionString
[] = {
2605 {MEMORY_PROFILE_ACTION_LIB_ALLOCATE_PAGES
, "Lib:AllocatePages"},
2606 {MEMORY_PROFILE_ACTION_LIB_ALLOCATE_RUNTIME_PAGES
, "Lib:AllocateRuntimePages"},
2607 {MEMORY_PROFILE_ACTION_LIB_ALLOCATE_RESERVED_PAGES
, "Lib:AllocateReservedPages"},
2608 {MEMORY_PROFILE_ACTION_LIB_FREE_PAGES
, "Lib:FreePages"},
2609 {MEMORY_PROFILE_ACTION_LIB_ALLOCATE_ALIGNED_PAGES
, "Lib:AllocateAlignedPages"},
2610 {MEMORY_PROFILE_ACTION_LIB_ALLOCATE_ALIGNED_RUNTIME_PAGES
, "Lib:AllocateAlignedRuntimePages"},
2611 {MEMORY_PROFILE_ACTION_LIB_ALLOCATE_ALIGNED_RESERVED_PAGES
, "Lib:AllocateAlignedReservedPages"},
2612 {MEMORY_PROFILE_ACTION_LIB_FREE_ALIGNED_PAGES
, "Lib:FreeAlignedPages"},
2613 {MEMORY_PROFILE_ACTION_LIB_ALLOCATE_POOL
, "Lib:AllocatePool"},
2614 {MEMORY_PROFILE_ACTION_LIB_ALLOCATE_RUNTIME_POOL
, "Lib:AllocateRuntimePool"},
2615 {MEMORY_PROFILE_ACTION_LIB_ALLOCATE_RESERVED_POOL
, "Lib:AllocateReservedPool"},
2616 {MEMORY_PROFILE_ACTION_LIB_FREE_POOL
, "Lib:FreePool"},
2617 {MEMORY_PROFILE_ACTION_LIB_ALLOCATE_ZERO_POOL
, "Lib:AllocateZeroPool"},
2618 {MEMORY_PROFILE_ACTION_LIB_ALLOCATE_RUNTIME_ZERO_POOL
, "Lib:AllocateRuntimeZeroPool"},
2619 {MEMORY_PROFILE_ACTION_LIB_ALLOCATE_RESERVED_ZERO_POOL
, "Lib:AllocateReservedZeroPool"},
2620 {MEMORY_PROFILE_ACTION_LIB_ALLOCATE_COPY_POOL
, "Lib:AllocateCopyPool"},
2621 {MEMORY_PROFILE_ACTION_LIB_ALLOCATE_RUNTIME_COPY_POOL
, "Lib:AllocateRuntimeCopyPool"},
2622 {MEMORY_PROFILE_ACTION_LIB_ALLOCATE_RESERVED_COPY_POOL
, "Lib:AllocateReservedCopyPool"},
2623 {MEMORY_PROFILE_ACTION_LIB_REALLOCATE_POOL
, "Lib:ReallocatePool"},
2624 {MEMORY_PROFILE_ACTION_LIB_REALLOCATE_RUNTIME_POOL
, "Lib:ReallocateRuntimePool"},
2625 {MEMORY_PROFILE_ACTION_LIB_REALLOCATE_RESERVED_POOL
, "Lib:ReallocateReservedPool"},
2629 EFI_MEMORY_TYPE MemoryType
;
2630 CHAR8
*MemoryTypeStr
;
2631 } PROFILE_MEMORY_TYPE_STRING
;
2633 GLOBAL_REMOVE_IF_UNREFERENCED PROFILE_MEMORY_TYPE_STRING mMemoryTypeString
[] = {
2634 {EfiRuntimeServicesCode
, "EfiRuntimeServicesCode"},
2635 {EfiRuntimeServicesData
, "EfiRuntimeServicesData"}
2639 Memory type to string.
2641 @param[in] MemoryType Memory type.
2643 @return Pointer to string.
2647 ProfileMemoryTypeToStr (
2648 IN EFI_MEMORY_TYPE MemoryType
2652 for (Index
= 0; Index
< ARRAY_SIZE (mMemoryTypeString
); Index
++) {
2653 if (mMemoryTypeString
[Index
].MemoryType
== MemoryType
) {
2654 return mMemoryTypeString
[Index
].MemoryTypeStr
;
2658 return "UnexpectedMemoryType";
2664 @param[in] Action Profile action.
2666 @return Pointer to string.
2670 ProfileActionToStr (
2671 IN MEMORY_PROFILE_ACTION Action
2675 UINTN ActionStringCount
;
2676 CHAR8
**ActionString
;
2678 ActionString
= mSmmActionString
;
2679 ActionStringCount
= ARRAY_SIZE (mSmmActionString
);
2681 if ((UINTN
) (UINT32
) Action
< ActionStringCount
) {
2682 return ActionString
[Action
];
2684 for (Index
= 0; Index
< ARRAY_SIZE (mExtActionString
); Index
++) {
2685 if (mExtActionString
[Index
].Action
== Action
) {
2686 return mExtActionString
[Index
].String
;
2690 return ActionString
[0];
2702 MEMORY_PROFILE_CONTEXT
*Context
;
2703 MEMORY_PROFILE_DRIVER_INFO
*DriverInfo
;
2704 MEMORY_PROFILE_ALLOC_INFO
*AllocInfo
;
2705 MEMORY_PROFILE_CONTEXT_DATA
*ContextData
;
2706 MEMORY_PROFILE_DRIVER_INFO_DATA
*DriverInfoData
;
2707 MEMORY_PROFILE_ALLOC_INFO_DATA
*AllocInfoData
;
2708 LIST_ENTRY
*SmramDriverInfoList
;
2710 LIST_ENTRY
*DriverLink
;
2711 LIST_ENTRY
*AllocInfoList
;
2713 LIST_ENTRY
*AllocLink
;
2714 BOOLEAN SmramProfileGettingStatus
;
2717 ContextData
= GetSmramProfileContext ();
2718 if (ContextData
== NULL
) {
2722 SmramProfileGettingStatus
= mSmramProfileGettingStatus
;
2723 mSmramProfileGettingStatus
= TRUE
;
2725 Context
= &ContextData
->Context
;
2726 DEBUG ((EFI_D_INFO
, "======= SmramProfile begin =======\n"));
2727 DEBUG ((EFI_D_INFO
, "MEMORY_PROFILE_CONTEXT\n"));
2729 DEBUG ((EFI_D_INFO
, " CurrentTotalUsage - 0x%016lx\n", Context
->CurrentTotalUsage
));
2730 DEBUG ((EFI_D_INFO
, " PeakTotalUsage - 0x%016lx\n", Context
->PeakTotalUsage
));
2731 for (TypeIndex
= 0; TypeIndex
< sizeof (Context
->CurrentTotalUsageByType
) / sizeof (Context
->CurrentTotalUsageByType
[0]); TypeIndex
++) {
2732 if ((Context
->CurrentTotalUsageByType
[TypeIndex
] != 0) ||
2733 (Context
->PeakTotalUsageByType
[TypeIndex
] != 0)) {
2734 DEBUG ((EFI_D_INFO
, " CurrentTotalUsage[0x%02x] - 0x%016lx (%a)\n", TypeIndex
, Context
->CurrentTotalUsageByType
[TypeIndex
], ProfileMemoryTypeToStr (TypeIndex
)));
2735 DEBUG ((EFI_D_INFO
, " PeakTotalUsage[0x%02x] - 0x%016lx (%a)\n", TypeIndex
, Context
->PeakTotalUsageByType
[TypeIndex
], ProfileMemoryTypeToStr (TypeIndex
)));
2738 DEBUG ((EFI_D_INFO
, " TotalImageSize - 0x%016lx\n", Context
->TotalImageSize
));
2739 DEBUG ((EFI_D_INFO
, " ImageCount - 0x%08x\n", Context
->ImageCount
));
2740 DEBUG ((EFI_D_INFO
, " SequenceCount - 0x%08x\n", Context
->SequenceCount
));
2742 SmramDriverInfoList
= ContextData
->DriverInfoList
;
2743 for (DriverLink
= SmramDriverInfoList
->ForwardLink
, DriverIndex
= 0;
2744 DriverLink
!= SmramDriverInfoList
;
2745 DriverLink
= DriverLink
->ForwardLink
, DriverIndex
++) {
2746 DriverInfoData
= CR (
2748 MEMORY_PROFILE_DRIVER_INFO_DATA
,
2750 MEMORY_PROFILE_DRIVER_INFO_SIGNATURE
2752 DriverInfo
= &DriverInfoData
->DriverInfo
;
2753 DEBUG ((EFI_D_INFO
, " MEMORY_PROFILE_DRIVER_INFO (0x%x)\n", DriverIndex
));
2754 DEBUG ((EFI_D_INFO
, " FileName - %g\n", &DriverInfo
->FileName
));
2755 DEBUG ((EFI_D_INFO
, " ImageBase - 0x%016lx\n", DriverInfo
->ImageBase
));
2756 DEBUG ((EFI_D_INFO
, " ImageSize - 0x%016lx\n", DriverInfo
->ImageSize
));
2757 DEBUG ((EFI_D_INFO
, " EntryPoint - 0x%016lx\n", DriverInfo
->EntryPoint
));
2758 DEBUG ((EFI_D_INFO
, " ImageSubsystem - 0x%04x\n", DriverInfo
->ImageSubsystem
));
2759 DEBUG ((EFI_D_INFO
, " FileType - 0x%02x\n", DriverInfo
->FileType
));
2760 DEBUG ((EFI_D_INFO
, " CurrentUsage - 0x%016lx\n", DriverInfo
->CurrentUsage
));
2761 DEBUG ((EFI_D_INFO
, " PeakUsage - 0x%016lx\n", DriverInfo
->PeakUsage
));
2762 for (TypeIndex
= 0; TypeIndex
< sizeof (DriverInfo
->CurrentUsageByType
) / sizeof (DriverInfo
->CurrentUsageByType
[0]); TypeIndex
++) {
2763 if ((DriverInfo
->CurrentUsageByType
[TypeIndex
] != 0) ||
2764 (DriverInfo
->PeakUsageByType
[TypeIndex
] != 0)) {
2765 DEBUG ((EFI_D_INFO
, " CurrentUsage[0x%02x] - 0x%016lx (%a)\n", TypeIndex
, DriverInfo
->CurrentUsageByType
[TypeIndex
], ProfileMemoryTypeToStr (TypeIndex
)));
2766 DEBUG ((EFI_D_INFO
, " PeakUsage[0x%02x] - 0x%016lx (%a)\n", TypeIndex
, DriverInfo
->PeakUsageByType
[TypeIndex
], ProfileMemoryTypeToStr (TypeIndex
)));
2769 DEBUG ((EFI_D_INFO
, " AllocRecordCount - 0x%08x\n", DriverInfo
->AllocRecordCount
));
2771 AllocInfoList
= DriverInfoData
->AllocInfoList
;
2772 for (AllocLink
= AllocInfoList
->ForwardLink
, AllocIndex
= 0;
2773 AllocLink
!= AllocInfoList
;
2774 AllocLink
= AllocLink
->ForwardLink
, AllocIndex
++) {
2775 AllocInfoData
= CR (
2777 MEMORY_PROFILE_ALLOC_INFO_DATA
,
2779 MEMORY_PROFILE_ALLOC_INFO_SIGNATURE
2781 AllocInfo
= &AllocInfoData
->AllocInfo
;
2782 DEBUG ((EFI_D_INFO
, " MEMORY_PROFILE_ALLOC_INFO (0x%x)\n", AllocIndex
));
2783 DEBUG ((EFI_D_INFO
, " CallerAddress - 0x%016lx (Offset: 0x%08x)\n", AllocInfo
->CallerAddress
, AllocInfo
->CallerAddress
- DriverInfo
->ImageBase
));
2784 DEBUG ((EFI_D_INFO
, " SequenceId - 0x%08x\n", AllocInfo
->SequenceId
));
2785 if ((AllocInfo
->Action
& MEMORY_PROFILE_ACTION_USER_DEFINED_MASK
) != 0) {
2786 if (AllocInfoData
->ActionString
!= NULL
) {
2787 DEBUG ((EFI_D_INFO
, " Action - 0x%08x (%a)\n", AllocInfo
->Action
, AllocInfoData
->ActionString
));
2789 DEBUG ((EFI_D_INFO
, " Action - 0x%08x (UserDefined-0x%08x)\n", AllocInfo
->Action
, AllocInfo
->Action
));
2792 DEBUG ((EFI_D_INFO
, " Action - 0x%08x (%a)\n", AllocInfo
->Action
, ProfileActionToStr (AllocInfo
->Action
)));
2794 DEBUG ((EFI_D_INFO
, " MemoryType - 0x%08x (%a)\n", AllocInfo
->MemoryType
, ProfileMemoryTypeToStr (AllocInfo
->MemoryType
)));
2795 DEBUG ((EFI_D_INFO
, " Buffer - 0x%016lx\n", AllocInfo
->Buffer
));
2796 DEBUG ((EFI_D_INFO
, " Size - 0x%016lx\n", AllocInfo
->Size
));
2800 DEBUG ((EFI_D_INFO
, "======= SmramProfile end =======\n"));
2802 mSmramProfileGettingStatus
= SmramProfileGettingStatus
;
2806 Dump SMRAM infromation.
2815 if (IS_SMRAM_PROFILE_ENABLED
) {
2816 DumpSmramProfile ();
2817 DumpFreePagesList ();
2818 DumpFreePoolList ();