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 infromation.
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
)) {
411 ASSERT (DriverInfoData
!= NULL
);
413 ZeroMem (DriverInfoData
, sizeof (*DriverInfoData
));
415 DriverInfo
= &DriverInfoData
->DriverInfo
;
416 DriverInfoData
->Signature
= MEMORY_PROFILE_DRIVER_INFO_SIGNATURE
;
417 DriverInfo
->Header
.Signature
= MEMORY_PROFILE_DRIVER_INFO_SIGNATURE
;
418 DriverInfo
->Header
.Length
= (UINT16
) (sizeof (MEMORY_PROFILE_DRIVER_INFO
) + PdbOccupiedSize
);
419 DriverInfo
->Header
.Revision
= MEMORY_PROFILE_DRIVER_INFO_REVISION
;
420 if (FileName
!= NULL
) {
421 CopyMem (&DriverInfo
->FileName
, FileName
, sizeof (EFI_GUID
));
423 DriverInfo
->ImageBase
= ImageBase
;
424 DriverInfo
->ImageSize
= ImageSize
;
425 DriverInfo
->EntryPoint
= EntryPoint
;
426 DriverInfo
->ImageSubsystem
= ImageSubsystem
;
427 if ((EntryPoint
!= 0) && ((EntryPoint
< ImageBase
) || (EntryPoint
>= (ImageBase
+ ImageSize
)))) {
429 // If the EntryPoint is not in the range of image buffer, it should come from emulation environment.
430 // So patch ImageBuffer here to align the EntryPoint.
432 Status
= InternalPeCoffGetEntryPoint ((VOID
*) (UINTN
) ImageBase
, &EntryPointInImage
);
433 ASSERT_EFI_ERROR (Status
);
434 DriverInfo
->ImageBase
= ImageBase
+ EntryPoint
- (PHYSICAL_ADDRESS
) (UINTN
) EntryPointInImage
;
436 DriverInfo
->FileType
= FileType
;
437 DriverInfoData
->AllocInfoList
= (LIST_ENTRY
*) (DriverInfoData
+ 1);
438 InitializeListHead (DriverInfoData
->AllocInfoList
);
439 DriverInfo
->CurrentUsage
= 0;
440 DriverInfo
->PeakUsage
= 0;
441 DriverInfo
->AllocRecordCount
= 0;
443 DriverInfo
->PdbStringOffset
= (UINT16
) sizeof (MEMORY_PROFILE_DRIVER_INFO
);
444 DriverInfoData
->PdbString
= (CHAR8
*) (DriverInfoData
->AllocInfoList
+ 1);
445 CopyMem (DriverInfoData
->PdbString
, PdbString
, PdbSize
);
447 DriverInfo
->PdbStringOffset
= 0;
448 DriverInfoData
->PdbString
= NULL
;
451 InsertTailList (ContextData
->DriverInfoList
, &DriverInfoData
->Link
);
452 ContextData
->Context
.ImageCount
++;
453 ContextData
->Context
.TotalImageSize
+= DriverInfo
->ImageSize
;
455 return DriverInfoData
;
459 Register image to DXE.
461 @param FileName File name of the image.
462 @param ImageBase Image base address.
463 @param ImageSize Image size.
464 @param FileType File type of the image.
469 IN EFI_GUID
*FileName
,
470 IN PHYSICAL_ADDRESS ImageBase
,
472 IN EFI_FV_FILETYPE FileType
476 EDKII_MEMORY_PROFILE_PROTOCOL
*ProfileProtocol
;
477 MEDIA_FW_VOL_FILEPATH_DEVICE_PATH
*FilePath
;
478 UINT8 TempBuffer
[sizeof (MEDIA_FW_VOL_FILEPATH_DEVICE_PATH
) + sizeof (EFI_DEVICE_PATH_PROTOCOL
)];
480 if (IS_UEFI_MEMORY_PROFILE_ENABLED
) {
482 FilePath
= (MEDIA_FW_VOL_FILEPATH_DEVICE_PATH
*)TempBuffer
;
483 Status
= gBS
->LocateProtocol (&gEdkiiMemoryProfileGuid
, NULL
, (VOID
**) &ProfileProtocol
);
484 if (!EFI_ERROR (Status
)) {
485 EfiInitializeFwVolDevicepathNode (FilePath
, FileName
);
486 SetDevicePathEndNode (FilePath
+ 1);
488 Status
= ProfileProtocol
->RegisterImage (
490 (EFI_DEVICE_PATH_PROTOCOL
*) FilePath
,
500 Unregister image from DXE.
502 @param FileName File name of the image.
503 @param ImageBase Image base address.
504 @param ImageSize Image size.
508 UnregisterImageFromDxe (
509 IN EFI_GUID
*FileName
,
510 IN PHYSICAL_ADDRESS ImageBase
,
515 EDKII_MEMORY_PROFILE_PROTOCOL
*ProfileProtocol
;
516 MEDIA_FW_VOL_FILEPATH_DEVICE_PATH
*FilePath
;
517 UINT8 TempBuffer
[sizeof (MEDIA_FW_VOL_FILEPATH_DEVICE_PATH
) + sizeof (EFI_DEVICE_PATH_PROTOCOL
)];
519 if (IS_UEFI_MEMORY_PROFILE_ENABLED
) {
521 FilePath
= (MEDIA_FW_VOL_FILEPATH_DEVICE_PATH
*)TempBuffer
;
522 Status
= gBS
->LocateProtocol (&gEdkiiMemoryProfileGuid
, NULL
, (VOID
*) &ProfileProtocol
);
523 if (!EFI_ERROR (Status
)) {
524 EfiInitializeFwVolDevicepathNode (FilePath
, FileName
);
525 SetDevicePathEndNode (FilePath
+ 1);
527 Status
= ProfileProtocol
->UnregisterImage (
529 (EFI_DEVICE_PATH_PROTOCOL
*) FilePath
,
538 Return if record for this driver is needed..
540 @param DriverFilePath Driver file path.
542 @retval TRUE Record for this driver is needed.
543 @retval FALSE Record for this driver is not needed.
547 NeedRecordThisDriver (
548 IN EFI_DEVICE_PATH_PROTOCOL
*DriverFilePath
551 EFI_DEVICE_PATH_PROTOCOL
*TmpDevicePath
;
552 EFI_DEVICE_PATH_PROTOCOL
*DevicePathInstance
;
553 UINTN DevicePathSize
;
556 if (!IsDevicePathValid (mSmramProfileDriverPath
, mSmramProfileDriverPathSize
)) {
558 // Invalid Device Path means record all.
564 // Record FilePath without end node.
566 FilePathSize
= GetDevicePathSize (DriverFilePath
) - sizeof(EFI_DEVICE_PATH_PROTOCOL
);
568 DevicePathInstance
= mSmramProfileDriverPath
;
571 // Find End node (it might be END_ENTIRE or END_INSTANCE)
573 TmpDevicePath
= DevicePathInstance
;
574 while (!IsDevicePathEndType (TmpDevicePath
)) {
575 TmpDevicePath
= NextDevicePathNode (TmpDevicePath
);
579 // Do not compare END node
581 DevicePathSize
= (UINTN
)TmpDevicePath
- (UINTN
)DevicePathInstance
;
582 if ((FilePathSize
== DevicePathSize
) &&
583 (CompareMem (DriverFilePath
, DevicePathInstance
, DevicePathSize
) == 0)) {
590 DevicePathInstance
= (EFI_DEVICE_PATH_PROTOCOL
*)((UINTN
)DevicePathInstance
+ DevicePathSize
+ DevicePathNodeLength(TmpDevicePath
));
591 } while (DevicePathSubType (TmpDevicePath
) != END_ENTIRE_DEVICE_PATH_SUBTYPE
);
597 Register SMM Core to SMRAM profile.
599 @param ContextData SMRAM profile context.
601 @retval TRUE Register success.
602 @retval FALSE Register fail.
607 IN MEMORY_PROFILE_CONTEXT_DATA
*ContextData
610 MEMORY_PROFILE_DRIVER_INFO_DATA
*DriverInfoData
;
611 PHYSICAL_ADDRESS ImageBase
;
612 UINT8 TempBuffer
[sizeof(MEDIA_FW_VOL_FILEPATH_DEVICE_PATH
) + sizeof(EFI_DEVICE_PATH_PROTOCOL
)];
613 MEDIA_FW_VOL_FILEPATH_DEVICE_PATH
*FilePath
;
615 FilePath
= (MEDIA_FW_VOL_FILEPATH_DEVICE_PATH
*) TempBuffer
;
616 EfiInitializeFwVolDevicepathNode (FilePath
, &gEfiCallerIdGuid
);
617 SetDevicePathEndNode (FilePath
+ 1);
619 if (!NeedRecordThisDriver ((EFI_DEVICE_PATH_PROTOCOL
*) FilePath
)) {
623 ImageBase
= gSmmCorePrivate
->PiSmmCoreImageBase
;
624 DriverInfoData
= BuildDriverInfo (
628 gSmmCorePrivate
->PiSmmCoreImageSize
,
629 gSmmCorePrivate
->PiSmmCoreEntryPoint
,
630 InternalPeCoffGetSubsystem ((VOID
*) (UINTN
) ImageBase
),
631 EFI_FV_FILETYPE_SMM_CORE
633 if (DriverInfoData
== NULL
) {
641 Initialize SMRAM profile.
649 MEMORY_PROFILE_CONTEXT_DATA
*SmramProfileContext
;
653 gSmmCorePrivate
->PiSmmCoreImageBase
,
654 gSmmCorePrivate
->PiSmmCoreImageSize
,
655 EFI_FV_FILETYPE_SMM_CORE
658 if (!IS_SMRAM_PROFILE_ENABLED
) {
662 SmramProfileContext
= GetSmramProfileContext ();
663 if (SmramProfileContext
!= NULL
) {
667 mSmramProfileGettingStatus
= FALSE
;
668 if ((PcdGet8 (PcdMemoryProfilePropertyMask
) & BIT7
) != 0) {
669 mSmramProfileRecordingEnable
= MEMORY_PROFILE_RECORDING_DISABLE
;
671 mSmramProfileRecordingEnable
= MEMORY_PROFILE_RECORDING_ENABLE
;
673 mSmramProfileDriverPathSize
= PcdGetSize (PcdMemoryProfileDriverPath
);
674 mSmramProfileDriverPath
= AllocateCopyPool (mSmramProfileDriverPathSize
, PcdGetPtr (PcdMemoryProfileDriverPath
));
675 mSmramProfileContextPtr
= &mSmramProfileContext
;
677 RegisterSmmCore (&mSmramProfileContext
);
679 DEBUG ((EFI_D_INFO
, "SmramProfileInit SmramProfileContext - 0x%x\n", &mSmramProfileContext
));
683 Install SMRAM profile protocol.
687 SmramProfileInstallProtocol (
694 if (!IS_SMRAM_PROFILE_ENABLED
) {
699 Status
= SmmInstallProtocolInterface (
701 &gEdkiiSmmMemoryProfileGuid
,
702 EFI_NATIVE_INTERFACE
,
705 ASSERT_EFI_ERROR (Status
);
709 Get the GUID file name from the file path.
711 @param FilePath File path.
713 @return The GUID file name from the file path.
717 GetFileNameFromFilePath (
718 IN EFI_DEVICE_PATH_PROTOCOL
*FilePath
721 MEDIA_FW_VOL_FILEPATH_DEVICE_PATH
*ThisFilePath
;
725 if (FilePath
!= NULL
) {
726 ThisFilePath
= (MEDIA_FW_VOL_FILEPATH_DEVICE_PATH
*) FilePath
;
727 while (!IsDevicePathEnd (ThisFilePath
)) {
728 FileName
= EfiGetNameGuidFromFwVolDevicePathNode (ThisFilePath
);
729 if (FileName
!= NULL
) {
732 ThisFilePath
= (MEDIA_FW_VOL_FILEPATH_DEVICE_PATH
*) NextDevicePathNode (ThisFilePath
);
740 Register SMM image to SMRAM profile.
742 @param DriverEntry SMM image info.
743 @param RegisterToDxe Register image to DXE.
745 @return EFI_SUCCESS Register successfully.
746 @return EFI_UNSUPPORTED Memory profile is unsupported,
747 or memory profile for the image is not required.
748 @return EFI_OUT_OF_RESOURCES No enough resource for this register.
752 RegisterSmramProfileImage (
753 IN EFI_SMM_DRIVER_ENTRY
*DriverEntry
,
754 IN BOOLEAN RegisterToDxe
757 MEMORY_PROFILE_CONTEXT_DATA
*ContextData
;
758 MEMORY_PROFILE_DRIVER_INFO_DATA
*DriverInfoData
;
759 UINT8 TempBuffer
[sizeof(MEDIA_FW_VOL_FILEPATH_DEVICE_PATH
) + sizeof(EFI_DEVICE_PATH_PROTOCOL
)];
760 MEDIA_FW_VOL_FILEPATH_DEVICE_PATH
*FilePath
;
764 &DriverEntry
->FileName
,
765 DriverEntry
->ImageBuffer
,
766 EFI_PAGES_TO_SIZE (DriverEntry
->NumberOfPage
),
771 if (!IS_SMRAM_PROFILE_ENABLED
) {
772 return EFI_UNSUPPORTED
;
775 FilePath
= (MEDIA_FW_VOL_FILEPATH_DEVICE_PATH
*) TempBuffer
;
776 EfiInitializeFwVolDevicepathNode (FilePath
, &DriverEntry
->FileName
);
777 SetDevicePathEndNode (FilePath
+ 1);
779 if (!NeedRecordThisDriver ((EFI_DEVICE_PATH_PROTOCOL
*) FilePath
)) {
780 return EFI_UNSUPPORTED
;
783 ContextData
= GetSmramProfileContext ();
784 if (ContextData
== NULL
) {
785 return EFI_UNSUPPORTED
;
788 DriverInfoData
= BuildDriverInfo (
790 &DriverEntry
->FileName
,
791 DriverEntry
->ImageBuffer
,
792 EFI_PAGES_TO_SIZE (DriverEntry
->NumberOfPage
),
793 DriverEntry
->ImageEntryPoint
,
794 InternalPeCoffGetSubsystem ((VOID
*) (UINTN
) DriverEntry
->ImageBuffer
),
797 if (DriverInfoData
== NULL
) {
798 return EFI_OUT_OF_RESOURCES
;
805 Search image from memory profile.
807 @param ContextData Memory profile context.
808 @param FileName Image file name.
809 @param Address Image Address.
811 @return Pointer to memory profile driver info.
814 MEMORY_PROFILE_DRIVER_INFO_DATA
*
815 GetMemoryProfileDriverInfoByFileNameAndAddress (
816 IN MEMORY_PROFILE_CONTEXT_DATA
*ContextData
,
817 IN EFI_GUID
*FileName
,
818 IN PHYSICAL_ADDRESS Address
821 MEMORY_PROFILE_DRIVER_INFO
*DriverInfo
;
822 MEMORY_PROFILE_DRIVER_INFO_DATA
*DriverInfoData
;
823 LIST_ENTRY
*DriverLink
;
824 LIST_ENTRY
*DriverInfoList
;
826 DriverInfoList
= ContextData
->DriverInfoList
;
828 for (DriverLink
= DriverInfoList
->ForwardLink
;
829 DriverLink
!= DriverInfoList
;
830 DriverLink
= DriverLink
->ForwardLink
) {
831 DriverInfoData
= CR (
833 MEMORY_PROFILE_DRIVER_INFO_DATA
,
835 MEMORY_PROFILE_DRIVER_INFO_SIGNATURE
837 DriverInfo
= &DriverInfoData
->DriverInfo
;
838 if ((CompareGuid (&DriverInfo
->FileName
, FileName
)) &&
839 (Address
>= DriverInfo
->ImageBase
) &&
840 (Address
< (DriverInfo
->ImageBase
+ DriverInfo
->ImageSize
))) {
841 return DriverInfoData
;
849 Search image from memory profile.
850 It will return image, if (Address >= ImageBuffer) AND (Address < ImageBuffer + ImageSize)
852 @param ContextData Memory profile context.
853 @param Address Image or Function address.
855 @return Pointer to memory profile driver info.
858 MEMORY_PROFILE_DRIVER_INFO_DATA
*
859 GetMemoryProfileDriverInfoFromAddress (
860 IN MEMORY_PROFILE_CONTEXT_DATA
*ContextData
,
861 IN PHYSICAL_ADDRESS Address
864 MEMORY_PROFILE_DRIVER_INFO
*DriverInfo
;
865 MEMORY_PROFILE_DRIVER_INFO_DATA
*DriverInfoData
;
866 LIST_ENTRY
*DriverLink
;
867 LIST_ENTRY
*DriverInfoList
;
869 DriverInfoList
= ContextData
->DriverInfoList
;
871 for (DriverLink
= DriverInfoList
->ForwardLink
;
872 DriverLink
!= DriverInfoList
;
873 DriverLink
= DriverLink
->ForwardLink
) {
874 DriverInfoData
= CR (
876 MEMORY_PROFILE_DRIVER_INFO_DATA
,
878 MEMORY_PROFILE_DRIVER_INFO_SIGNATURE
880 DriverInfo
= &DriverInfoData
->DriverInfo
;
881 if ((Address
>= DriverInfo
->ImageBase
) &&
882 (Address
< (DriverInfo
->ImageBase
+ DriverInfo
->ImageSize
))) {
883 return DriverInfoData
;
891 Unregister image from SMRAM profile.
893 @param DriverEntry SMM image info.
894 @param UnregisterFromDxe Unregister image from DXE.
896 @return EFI_SUCCESS Unregister successfully.
897 @return EFI_UNSUPPORTED Memory profile is unsupported,
898 or memory profile for the image is not required.
899 @return EFI_NOT_FOUND The image is not found.
903 UnregisterSmramProfileImage (
904 IN EFI_SMM_DRIVER_ENTRY
*DriverEntry
,
905 IN BOOLEAN UnregisterFromDxe
909 MEMORY_PROFILE_CONTEXT_DATA
*ContextData
;
910 MEMORY_PROFILE_DRIVER_INFO_DATA
*DriverInfoData
;
912 PHYSICAL_ADDRESS ImageAddress
;
913 VOID
*EntryPointInImage
;
914 UINT8 TempBuffer
[sizeof(MEDIA_FW_VOL_FILEPATH_DEVICE_PATH
) + sizeof(EFI_DEVICE_PATH_PROTOCOL
)];
915 MEDIA_FW_VOL_FILEPATH_DEVICE_PATH
*FilePath
;
917 if (UnregisterFromDxe
) {
918 UnregisterImageFromDxe (
919 &DriverEntry
->FileName
,
920 DriverEntry
->ImageBuffer
,
921 EFI_PAGES_TO_SIZE (DriverEntry
->NumberOfPage
)
925 if (!IS_SMRAM_PROFILE_ENABLED
) {
926 return EFI_UNSUPPORTED
;
929 FilePath
= (MEDIA_FW_VOL_FILEPATH_DEVICE_PATH
*) TempBuffer
;
930 EfiInitializeFwVolDevicepathNode (FilePath
, &DriverEntry
->FileName
);
931 SetDevicePathEndNode (FilePath
+ 1);
933 if (!NeedRecordThisDriver ((EFI_DEVICE_PATH_PROTOCOL
*) FilePath
)) {
934 return EFI_UNSUPPORTED
;
937 ContextData
= GetSmramProfileContext ();
938 if (ContextData
== NULL
) {
939 return EFI_UNSUPPORTED
;
942 DriverInfoData
= NULL
;
943 FileName
= &DriverEntry
->FileName
;
944 ImageAddress
= DriverEntry
->ImageBuffer
;
945 if ((DriverEntry
->ImageEntryPoint
< ImageAddress
) || (DriverEntry
->ImageEntryPoint
>= (ImageAddress
+ EFI_PAGES_TO_SIZE (DriverEntry
->NumberOfPage
)))) {
947 // If the EntryPoint is not in the range of image buffer, it should come from emulation environment.
948 // So patch ImageAddress here to align the EntryPoint.
950 Status
= InternalPeCoffGetEntryPoint ((VOID
*) (UINTN
) ImageAddress
, &EntryPointInImage
);
951 ASSERT_EFI_ERROR (Status
);
952 ImageAddress
= ImageAddress
+ (UINTN
) DriverEntry
->ImageEntryPoint
- (UINTN
) EntryPointInImage
;
954 if (FileName
!= NULL
) {
955 DriverInfoData
= GetMemoryProfileDriverInfoByFileNameAndAddress (ContextData
, FileName
, ImageAddress
);
957 if (DriverInfoData
== NULL
) {
958 DriverInfoData
= GetMemoryProfileDriverInfoFromAddress (ContextData
, ImageAddress
);
960 if (DriverInfoData
== NULL
) {
961 return EFI_NOT_FOUND
;
964 ContextData
->Context
.TotalImageSize
-= DriverInfoData
->DriverInfo
.ImageSize
;
966 // Keep the ImageBase for RVA calculation in Application.
967 //DriverInfoData->DriverInfo.ImageBase = 0;
968 DriverInfoData
->DriverInfo
.ImageSize
= 0;
970 if (DriverInfoData
->DriverInfo
.PeakUsage
== 0) {
971 ContextData
->Context
.ImageCount
--;
972 RemoveEntryList (&DriverInfoData
->Link
);
974 // Use SmmInternalFreePool() that will not update profile for this FreePool action.
976 SmmInternalFreePool (DriverInfoData
);
983 Return if this memory type needs to be recorded into memory profile.
984 Only need to record EfiRuntimeServicesCode and EfiRuntimeServicesData for SMRAM profile.
986 @param MemoryType Memory type.
988 @retval TRUE This memory type need to be recorded.
989 @retval FALSE This memory type need not to be recorded.
993 SmmCoreNeedRecordProfile (
994 IN EFI_MEMORY_TYPE MemoryType
999 if (MemoryType
!= EfiRuntimeServicesCode
&&
1000 MemoryType
!= EfiRuntimeServicesData
) {
1004 TestBit
= LShiftU64 (1, MemoryType
);
1006 if ((PcdGet64 (PcdMemoryProfileMemoryType
) & TestBit
) != 0) {
1014 Convert EFI memory type to profile memory index. The rule is:
1015 If BIOS memory type (0 ~ EfiMaxMemoryType - 1), ProfileMemoryIndex = MemoryType.
1016 As SMRAM profile is only to record EfiRuntimeServicesCode and EfiRuntimeServicesData,
1017 so return input memory type directly.
1019 @param MemoryType Memory type.
1021 @return EFI memory type as profile memory index.
1025 GetProfileMemoryIndex (
1026 IN EFI_MEMORY_TYPE MemoryType
1033 Update SMRAM profile FreeMemoryPages information
1035 @param ContextData Memory profile context.
1039 SmramProfileUpdateFreePages (
1040 IN MEMORY_PROFILE_CONTEXT_DATA
*ContextData
1044 FREE_PAGE_LIST
*Pages
;
1045 LIST_ENTRY
*FreePageList
;
1046 UINTN NumberOfPages
;
1049 FreePageList
= &mSmmMemoryMap
;
1050 for (Node
= FreePageList
->BackLink
;
1051 Node
!= FreePageList
;
1052 Node
= Node
->BackLink
) {
1053 Pages
= BASE_CR (Node
, FREE_PAGE_LIST
, Link
);
1054 NumberOfPages
+= Pages
->NumberOfPages
;
1057 mSmramFreeMemory
.TotalFreeMemoryPages
= NumberOfPages
;
1059 if (NumberOfPages
<= SMRAM_INFO_DUMP_PAGE_THRESHOLD
) {
1065 Update SMRAM profile Allocate information.
1067 @param CallerAddress Address of caller who call Allocate.
1068 @param Action This Allocate action.
1069 @param MemoryType Memory type.
1070 @param Size Buffer size.
1071 @param Buffer Buffer address.
1072 @param ActionString String for memory profile action.
1074 @return EFI_SUCCESS Memory profile is updated.
1075 @return EFI_UNSUPPORTED Memory profile is unsupported,
1076 or memory profile for the image is not required.
1077 @return EFI_OUT_OF_RESOURCES No enough resource to update memory profile for allocate action.
1081 SmmCoreUpdateProfileAllocate (
1082 IN PHYSICAL_ADDRESS CallerAddress
,
1083 IN MEMORY_PROFILE_ACTION Action
,
1084 IN EFI_MEMORY_TYPE MemoryType
,
1087 IN CHAR8
*ActionString OPTIONAL
1091 MEMORY_PROFILE_CONTEXT
*Context
;
1092 MEMORY_PROFILE_DRIVER_INFO
*DriverInfo
;
1093 MEMORY_PROFILE_ALLOC_INFO
*AllocInfo
;
1094 MEMORY_PROFILE_CONTEXT_DATA
*ContextData
;
1095 MEMORY_PROFILE_DRIVER_INFO_DATA
*DriverInfoData
;
1096 MEMORY_PROFILE_ALLOC_INFO_DATA
*AllocInfoData
;
1097 EFI_MEMORY_TYPE ProfileMemoryIndex
;
1098 MEMORY_PROFILE_ACTION BasicAction
;
1099 UINTN ActionStringSize
;
1100 UINTN ActionStringOccupiedSize
;
1102 BasicAction
= Action
& MEMORY_PROFILE_ACTION_BASIC_MASK
;
1104 ContextData
= GetSmramProfileContext ();
1105 if (ContextData
== NULL
) {
1106 return EFI_UNSUPPORTED
;
1109 DriverInfoData
= GetMemoryProfileDriverInfoFromAddress (ContextData
, CallerAddress
);
1110 if (DriverInfoData
== NULL
) {
1111 return EFI_UNSUPPORTED
;
1114 ActionStringSize
= 0;
1115 ActionStringOccupiedSize
= 0;
1116 if (ActionString
!= NULL
) {
1117 ActionStringSize
= AsciiStrSize (ActionString
);
1118 ActionStringOccupiedSize
= GET_OCCUPIED_SIZE (ActionStringSize
, sizeof (UINT64
));
1122 // Use SmmInternalAllocatePool() that will not update profile for this AllocatePool action.
1124 AllocInfoData
= NULL
;
1125 Status
= SmmInternalAllocatePool (
1126 EfiRuntimeServicesData
,
1127 sizeof (*AllocInfoData
) + ActionStringSize
,
1128 (VOID
**) &AllocInfoData
1130 if (EFI_ERROR (Status
)) {
1131 return EFI_OUT_OF_RESOURCES
;
1133 ASSERT (AllocInfoData
!= NULL
);
1136 // Only update SequenceCount if and only if it is basic action.
1138 if (Action
== BasicAction
) {
1139 ContextData
->Context
.SequenceCount
++;
1142 AllocInfo
= &AllocInfoData
->AllocInfo
;
1143 AllocInfoData
->Signature
= MEMORY_PROFILE_ALLOC_INFO_SIGNATURE
;
1144 AllocInfo
->Header
.Signature
= MEMORY_PROFILE_ALLOC_INFO_SIGNATURE
;
1145 AllocInfo
->Header
.Length
= (UINT16
) (sizeof (MEMORY_PROFILE_ALLOC_INFO
) + ActionStringOccupiedSize
);
1146 AllocInfo
->Header
.Revision
= MEMORY_PROFILE_ALLOC_INFO_REVISION
;
1147 AllocInfo
->CallerAddress
= CallerAddress
;
1148 AllocInfo
->SequenceId
= ContextData
->Context
.SequenceCount
;
1149 AllocInfo
->Action
= Action
;
1150 AllocInfo
->MemoryType
= MemoryType
;
1151 AllocInfo
->Buffer
= (PHYSICAL_ADDRESS
) (UINTN
) Buffer
;
1152 AllocInfo
->Size
= Size
;
1153 if (ActionString
!= NULL
) {
1154 AllocInfo
->ActionStringOffset
= (UINT16
) sizeof (MEMORY_PROFILE_ALLOC_INFO
);
1155 AllocInfoData
->ActionString
= (CHAR8
*) (AllocInfoData
+ 1);
1156 CopyMem (AllocInfoData
->ActionString
, ActionString
, ActionStringSize
);
1158 AllocInfo
->ActionStringOffset
= 0;
1159 AllocInfoData
->ActionString
= NULL
;
1162 InsertTailList (DriverInfoData
->AllocInfoList
, &AllocInfoData
->Link
);
1164 Context
= &ContextData
->Context
;
1165 DriverInfo
= &DriverInfoData
->DriverInfo
;
1166 DriverInfo
->AllocRecordCount
++;
1169 // Update summary if and only if it is basic action.
1171 if (Action
== BasicAction
) {
1172 ProfileMemoryIndex
= GetProfileMemoryIndex (MemoryType
);
1174 DriverInfo
->CurrentUsage
+= Size
;
1175 if (DriverInfo
->PeakUsage
< DriverInfo
->CurrentUsage
) {
1176 DriverInfo
->PeakUsage
= DriverInfo
->CurrentUsage
;
1178 DriverInfo
->CurrentUsageByType
[ProfileMemoryIndex
] += Size
;
1179 if (DriverInfo
->PeakUsageByType
[ProfileMemoryIndex
] < DriverInfo
->CurrentUsageByType
[ProfileMemoryIndex
]) {
1180 DriverInfo
->PeakUsageByType
[ProfileMemoryIndex
] = DriverInfo
->CurrentUsageByType
[ProfileMemoryIndex
];
1183 Context
->CurrentTotalUsage
+= Size
;
1184 if (Context
->PeakTotalUsage
< Context
->CurrentTotalUsage
) {
1185 Context
->PeakTotalUsage
= Context
->CurrentTotalUsage
;
1187 Context
->CurrentTotalUsageByType
[ProfileMemoryIndex
] += Size
;
1188 if (Context
->PeakTotalUsageByType
[ProfileMemoryIndex
] < Context
->CurrentTotalUsageByType
[ProfileMemoryIndex
]) {
1189 Context
->PeakTotalUsageByType
[ProfileMemoryIndex
] = Context
->CurrentTotalUsageByType
[ProfileMemoryIndex
];
1192 SmramProfileUpdateFreePages (ContextData
);
1199 Get memory profile alloc info from memory profile
1201 @param DriverInfoData Driver info
1202 @param BasicAction This Free basic action
1203 @param Size Buffer size
1204 @param Buffer Buffer address
1206 @return Pointer to memory profile alloc info.
1208 MEMORY_PROFILE_ALLOC_INFO_DATA
*
1209 GetMemoryProfileAllocInfoFromAddress (
1210 IN MEMORY_PROFILE_DRIVER_INFO_DATA
*DriverInfoData
,
1211 IN MEMORY_PROFILE_ACTION BasicAction
,
1216 LIST_ENTRY
*AllocInfoList
;
1217 LIST_ENTRY
*AllocLink
;
1218 MEMORY_PROFILE_ALLOC_INFO
*AllocInfo
;
1219 MEMORY_PROFILE_ALLOC_INFO_DATA
*AllocInfoData
;
1221 AllocInfoList
= DriverInfoData
->AllocInfoList
;
1223 for (AllocLink
= AllocInfoList
->ForwardLink
;
1224 AllocLink
!= AllocInfoList
;
1225 AllocLink
= AllocLink
->ForwardLink
) {
1226 AllocInfoData
= CR (
1228 MEMORY_PROFILE_ALLOC_INFO_DATA
,
1230 MEMORY_PROFILE_ALLOC_INFO_SIGNATURE
1232 AllocInfo
= &AllocInfoData
->AllocInfo
;
1233 if ((AllocInfo
->Action
& MEMORY_PROFILE_ACTION_BASIC_MASK
) != BasicAction
) {
1236 switch (BasicAction
) {
1237 case MemoryProfileActionAllocatePages
:
1238 if ((AllocInfo
->Buffer
<= (PHYSICAL_ADDRESS
) (UINTN
) Buffer
) &&
1239 ((AllocInfo
->Buffer
+ AllocInfo
->Size
) >= ((PHYSICAL_ADDRESS
) (UINTN
) Buffer
+ Size
))) {
1240 return AllocInfoData
;
1243 case MemoryProfileActionAllocatePool
:
1244 if (AllocInfo
->Buffer
== (PHYSICAL_ADDRESS
) (UINTN
) Buffer
) {
1245 return AllocInfoData
;
1258 Update SMRAM profile Free information.
1260 @param CallerAddress Address of caller who call Free.
1261 @param Action This Free action.
1262 @param Size Buffer size.
1263 @param Buffer Buffer address.
1265 @return EFI_SUCCESS Memory profile is updated.
1266 @return EFI_UNSUPPORTED Memory profile is unsupported.
1267 @return EFI_NOT_FOUND No matched allocate info found for free action.
1271 SmmCoreUpdateProfileFree (
1272 IN PHYSICAL_ADDRESS CallerAddress
,
1273 IN MEMORY_PROFILE_ACTION Action
,
1278 MEMORY_PROFILE_CONTEXT
*Context
;
1279 MEMORY_PROFILE_DRIVER_INFO
*DriverInfo
;
1280 MEMORY_PROFILE_ALLOC_INFO
*AllocInfo
;
1281 MEMORY_PROFILE_CONTEXT_DATA
*ContextData
;
1282 MEMORY_PROFILE_DRIVER_INFO_DATA
*DriverInfoData
;
1283 LIST_ENTRY
*DriverLink
;
1284 LIST_ENTRY
*DriverInfoList
;
1285 MEMORY_PROFILE_DRIVER_INFO_DATA
*ThisDriverInfoData
;
1286 MEMORY_PROFILE_ALLOC_INFO_DATA
*AllocInfoData
;
1287 EFI_MEMORY_TYPE ProfileMemoryIndex
;
1288 MEMORY_PROFILE_ACTION BasicAction
;
1291 BasicAction
= Action
& MEMORY_PROFILE_ACTION_BASIC_MASK
;
1293 ContextData
= GetSmramProfileContext ();
1294 if (ContextData
== NULL
) {
1295 return EFI_UNSUPPORTED
;
1298 DriverInfoData
= GetMemoryProfileDriverInfoFromAddress (ContextData
, CallerAddress
);
1301 // Do not return if DriverInfoData == NULL here,
1302 // because driver A might free memory allocated by driver B.
1306 // Need use do-while loop to find all possible record,
1307 // because one address might be recorded multiple times.
1310 AllocInfoData
= NULL
;
1312 if (DriverInfoData
!= NULL
) {
1313 switch (BasicAction
) {
1314 case MemoryProfileActionFreePages
:
1315 AllocInfoData
= GetMemoryProfileAllocInfoFromAddress (DriverInfoData
, MemoryProfileActionAllocatePages
, Size
, Buffer
);
1317 case MemoryProfileActionFreePool
:
1318 AllocInfoData
= GetMemoryProfileAllocInfoFromAddress (DriverInfoData
, MemoryProfileActionAllocatePool
, 0, Buffer
);
1322 AllocInfoData
= NULL
;
1326 if (AllocInfoData
== NULL
) {
1328 // Legal case, because driver A might free memory allocated by driver B, by some protocol.
1330 DriverInfoList
= ContextData
->DriverInfoList
;
1332 for (DriverLink
= DriverInfoList
->ForwardLink
;
1333 DriverLink
!= DriverInfoList
;
1334 DriverLink
= DriverLink
->ForwardLink
) {
1335 ThisDriverInfoData
= CR (
1337 MEMORY_PROFILE_DRIVER_INFO_DATA
,
1339 MEMORY_PROFILE_DRIVER_INFO_SIGNATURE
1341 switch (BasicAction
) {
1342 case MemoryProfileActionFreePages
:
1343 AllocInfoData
= GetMemoryProfileAllocInfoFromAddress (ThisDriverInfoData
, MemoryProfileActionAllocatePages
, Size
, Buffer
);
1345 case MemoryProfileActionFreePool
:
1346 AllocInfoData
= GetMemoryProfileAllocInfoFromAddress (ThisDriverInfoData
, MemoryProfileActionAllocatePool
, 0, Buffer
);
1350 AllocInfoData
= NULL
;
1353 if (AllocInfoData
!= NULL
) {
1354 DriverInfoData
= ThisDriverInfoData
;
1359 if (AllocInfoData
== NULL
) {
1361 // If (!Found), no matched allocate info is found for this free action.
1362 // It is because the specified memory type allocate actions have been filtered by
1363 // CoreNeedRecordProfile(), but free actions have no memory type information,
1364 // they can not be filtered by CoreNeedRecordProfile(). Then, they will be
1367 // If (Found), it is normal exit path.
1368 return (Found
? EFI_SUCCESS
: EFI_NOT_FOUND
);
1372 ASSERT (DriverInfoData
!= NULL
);
1373 ASSERT (AllocInfoData
!= NULL
);
1377 Context
= &ContextData
->Context
;
1378 DriverInfo
= &DriverInfoData
->DriverInfo
;
1379 AllocInfo
= &AllocInfoData
->AllocInfo
;
1381 DriverInfo
->AllocRecordCount
--;
1383 // Update summary if and only if it is basic action.
1385 if (AllocInfo
->Action
== (AllocInfo
->Action
& MEMORY_PROFILE_ACTION_BASIC_MASK
)) {
1386 ProfileMemoryIndex
= GetProfileMemoryIndex (AllocInfo
->MemoryType
);
1388 Context
->CurrentTotalUsage
-= AllocInfo
->Size
;
1389 Context
->CurrentTotalUsageByType
[ProfileMemoryIndex
] -= AllocInfo
->Size
;
1391 DriverInfo
->CurrentUsage
-= AllocInfo
->Size
;
1392 DriverInfo
->CurrentUsageByType
[ProfileMemoryIndex
] -= AllocInfo
->Size
;
1395 RemoveEntryList (&AllocInfoData
->Link
);
1397 if (BasicAction
== MemoryProfileActionFreePages
) {
1398 if (AllocInfo
->Buffer
!= (PHYSICAL_ADDRESS
) (UINTN
) Buffer
) {
1399 SmmCoreUpdateProfileAllocate (
1400 AllocInfo
->CallerAddress
,
1402 AllocInfo
->MemoryType
,
1403 (UINTN
) ((PHYSICAL_ADDRESS
) (UINTN
) Buffer
- AllocInfo
->Buffer
),
1404 (VOID
*) (UINTN
) AllocInfo
->Buffer
,
1405 AllocInfoData
->ActionString
1408 if (AllocInfo
->Buffer
+ AllocInfo
->Size
!= ((PHYSICAL_ADDRESS
) (UINTN
) Buffer
+ Size
)) {
1409 SmmCoreUpdateProfileAllocate (
1410 AllocInfo
->CallerAddress
,
1412 AllocInfo
->MemoryType
,
1413 (UINTN
) ((AllocInfo
->Buffer
+ AllocInfo
->Size
) - ((PHYSICAL_ADDRESS
) (UINTN
) Buffer
+ Size
)),
1414 (VOID
*) ((UINTN
) Buffer
+ Size
),
1415 AllocInfoData
->ActionString
1421 // Use SmmInternalFreePool() that will not update profile for this FreePool action.
1423 SmmInternalFreePool (AllocInfoData
);
1428 Update SMRAM profile information.
1430 @param CallerAddress Address of caller who call Allocate or Free.
1431 @param Action This Allocate or Free action.
1432 @param MemoryType Memory type.
1433 EfiMaxMemoryType means the MemoryType is unknown.
1434 @param Size Buffer size.
1435 @param Buffer Buffer address.
1436 @param ActionString String for memory profile action.
1437 Only needed for user defined allocate action.
1439 @return EFI_SUCCESS Memory profile is updated.
1440 @return EFI_UNSUPPORTED Memory profile is unsupported,
1441 or memory profile for the image is not required,
1442 or memory profile for the memory type is not required.
1443 @return EFI_ACCESS_DENIED It is during memory profile data getting.
1444 @return EFI_ABORTED Memory profile recording is not enabled.
1445 @return EFI_OUT_OF_RESOURCES No enough resource to update memory profile for allocate action.
1446 @return EFI_NOT_FOUND No matched allocate info found for free action.
1451 SmmCoreUpdateProfile (
1452 IN PHYSICAL_ADDRESS CallerAddress
,
1453 IN MEMORY_PROFILE_ACTION Action
,
1454 IN EFI_MEMORY_TYPE MemoryType
, // Valid for AllocatePages/AllocatePool
1455 IN UINTN Size
, // Valid for AllocatePages/FreePages/AllocatePool
1457 IN CHAR8
*ActionString OPTIONAL
1461 MEMORY_PROFILE_CONTEXT_DATA
*ContextData
;
1462 MEMORY_PROFILE_ACTION BasicAction
;
1464 if (!IS_SMRAM_PROFILE_ENABLED
) {
1465 return EFI_UNSUPPORTED
;
1468 if (mSmramProfileGettingStatus
) {
1469 return EFI_ACCESS_DENIED
;
1472 if (!mSmramProfileRecordingEnable
) {
1477 // Get the basic action to know how to process the record
1479 BasicAction
= Action
& MEMORY_PROFILE_ACTION_BASIC_MASK
;
1482 // Free operations have no memory type information, so skip the check.
1484 if ((BasicAction
== MemoryProfileActionAllocatePages
) || (BasicAction
== MemoryProfileActionAllocatePool
)) {
1486 // Only record limited MemoryType.
1488 if (!SmmCoreNeedRecordProfile (MemoryType
)) {
1489 return EFI_UNSUPPORTED
;
1493 ContextData
= GetSmramProfileContext ();
1494 if (ContextData
== NULL
) {
1495 return EFI_UNSUPPORTED
;
1498 switch (BasicAction
) {
1499 case MemoryProfileActionAllocatePages
:
1500 Status
= SmmCoreUpdateProfileAllocate (CallerAddress
, Action
, MemoryType
, Size
, Buffer
, ActionString
);
1502 case MemoryProfileActionFreePages
:
1503 Status
= SmmCoreUpdateProfileFree (CallerAddress
, Action
, Size
, Buffer
);
1505 case MemoryProfileActionAllocatePool
:
1506 Status
= SmmCoreUpdateProfileAllocate (CallerAddress
, Action
, MemoryType
, Size
, Buffer
, ActionString
);
1508 case MemoryProfileActionFreePool
:
1509 Status
= SmmCoreUpdateProfileFree (CallerAddress
, Action
, 0, Buffer
);
1513 Status
= EFI_UNSUPPORTED
;
1521 SMRAM profile ready to lock callback function.
1525 SmramProfileReadyToLock (
1529 if (!IS_SMRAM_PROFILE_ENABLED
) {
1533 DEBUG ((EFI_D_INFO
, "SmramProfileReadyToLock\n"));
1534 mSmramReadyToLock
= TRUE
;
1537 ////////////////////
1540 Get SMRAM profile data size.
1542 @return SMRAM profile data size.
1546 SmramProfileGetDataSize (
1550 MEMORY_PROFILE_CONTEXT_DATA
*ContextData
;
1551 MEMORY_PROFILE_DRIVER_INFO_DATA
*DriverInfoData
;
1552 MEMORY_PROFILE_ALLOC_INFO_DATA
*AllocInfoData
;
1553 LIST_ENTRY
*DriverInfoList
;
1554 LIST_ENTRY
*DriverLink
;
1555 LIST_ENTRY
*AllocInfoList
;
1556 LIST_ENTRY
*AllocLink
;
1559 LIST_ENTRY
*FreePageList
;
1560 LIST_ENTRY
*FreePoolList
;
1561 FREE_POOL_HEADER
*Pool
;
1562 UINTN PoolListIndex
;
1564 UINTN SmmPoolTypeIndex
;
1566 ContextData
= GetSmramProfileContext ();
1567 if (ContextData
== NULL
) {
1571 TotalSize
= sizeof (MEMORY_PROFILE_CONTEXT
);
1573 DriverInfoList
= ContextData
->DriverInfoList
;
1574 for (DriverLink
= DriverInfoList
->ForwardLink
;
1575 DriverLink
!= DriverInfoList
;
1576 DriverLink
= DriverLink
->ForwardLink
) {
1577 DriverInfoData
= CR (
1579 MEMORY_PROFILE_DRIVER_INFO_DATA
,
1581 MEMORY_PROFILE_DRIVER_INFO_SIGNATURE
1583 TotalSize
+= DriverInfoData
->DriverInfo
.Header
.Length
;
1585 AllocInfoList
= DriverInfoData
->AllocInfoList
;
1586 for (AllocLink
= AllocInfoList
->ForwardLink
;
1587 AllocLink
!= AllocInfoList
;
1588 AllocLink
= AllocLink
->ForwardLink
) {
1589 AllocInfoData
= CR (
1591 MEMORY_PROFILE_ALLOC_INFO_DATA
,
1593 MEMORY_PROFILE_ALLOC_INFO_SIGNATURE
1595 TotalSize
+= AllocInfoData
->AllocInfo
.Header
.Length
;
1601 FreePageList
= &mSmmMemoryMap
;
1602 for (Node
= FreePageList
->BackLink
;
1603 Node
!= FreePageList
;
1604 Node
= Node
->BackLink
) {
1607 for (SmmPoolTypeIndex
= 0; SmmPoolTypeIndex
< SmmPoolTypeMax
; SmmPoolTypeIndex
++) {
1608 for (PoolListIndex
= 0; PoolListIndex
< MAX_POOL_INDEX
; PoolListIndex
++) {
1609 FreePoolList
= &mSmmPoolLists
[SmmPoolTypeIndex
][PoolListIndex
];
1610 for (Node
= FreePoolList
->BackLink
;
1611 Node
!= FreePoolList
;
1612 Node
= Node
->BackLink
) {
1613 Pool
= BASE_CR (Node
, FREE_POOL_HEADER
, Link
);
1614 if (Pool
->Header
.Available
) {
1621 TotalSize
+= (sizeof (MEMORY_PROFILE_FREE_MEMORY
) + Index
* sizeof (MEMORY_PROFILE_DESCRIPTOR
));
1622 TotalSize
+= (sizeof (MEMORY_PROFILE_MEMORY_RANGE
) + mFullSmramRangeCount
* sizeof (MEMORY_PROFILE_DESCRIPTOR
));
1628 Copy SMRAM profile data.
1630 @param ProfileBuffer The buffer to hold SMRAM profile data.
1631 @param ProfileSize On input, profile buffer size.
1632 On output, actual profile data size copied.
1633 @param ProfileOffset On input, profile buffer offset to copy.
1634 On output, next time profile buffer offset to copy.
1638 SmramProfileCopyData (
1639 OUT VOID
*ProfileBuffer
,
1640 IN OUT UINT64
*ProfileSize
,
1641 IN OUT UINT64
*ProfileOffset
1644 MEMORY_PROFILE_CONTEXT
*Context
;
1645 MEMORY_PROFILE_DRIVER_INFO
*DriverInfo
;
1646 MEMORY_PROFILE_ALLOC_INFO
*AllocInfo
;
1647 MEMORY_PROFILE_CONTEXT_DATA
*ContextData
;
1648 MEMORY_PROFILE_DRIVER_INFO_DATA
*DriverInfoData
;
1649 MEMORY_PROFILE_ALLOC_INFO_DATA
*AllocInfoData
;
1650 LIST_ENTRY
*DriverInfoList
;
1651 LIST_ENTRY
*DriverLink
;
1652 LIST_ENTRY
*AllocInfoList
;
1653 LIST_ENTRY
*AllocLink
;
1655 FREE_PAGE_LIST
*Pages
;
1656 LIST_ENTRY
*FreePageList
;
1657 LIST_ENTRY
*FreePoolList
;
1658 FREE_POOL_HEADER
*Pool
;
1659 UINTN PoolListIndex
;
1661 MEMORY_PROFILE_FREE_MEMORY
*FreeMemory
;
1662 MEMORY_PROFILE_MEMORY_RANGE
*MemoryRange
;
1663 MEMORY_PROFILE_DESCRIPTOR
*MemoryProfileDescriptor
;
1665 UINT64 RemainingSize
;
1667 UINTN ActionStringSize
;
1668 UINTN SmmPoolTypeIndex
;
1670 ContextData
= GetSmramProfileContext ();
1671 if (ContextData
== NULL
) {
1675 RemainingSize
= *ProfileSize
;
1678 if (*ProfileOffset
< sizeof (MEMORY_PROFILE_CONTEXT
)) {
1679 if (RemainingSize
>= sizeof (MEMORY_PROFILE_CONTEXT
)) {
1680 Context
= ProfileBuffer
;
1681 CopyMem (Context
, &ContextData
->Context
, sizeof (MEMORY_PROFILE_CONTEXT
));
1682 RemainingSize
-= sizeof (MEMORY_PROFILE_CONTEXT
);
1683 ProfileBuffer
= (UINT8
*) ProfileBuffer
+ sizeof (MEMORY_PROFILE_CONTEXT
);
1688 Offset
+= sizeof (MEMORY_PROFILE_CONTEXT
);
1690 DriverInfoList
= ContextData
->DriverInfoList
;
1691 for (DriverLink
= DriverInfoList
->ForwardLink
;
1692 DriverLink
!= DriverInfoList
;
1693 DriverLink
= DriverLink
->ForwardLink
) {
1694 DriverInfoData
= CR (
1696 MEMORY_PROFILE_DRIVER_INFO_DATA
,
1698 MEMORY_PROFILE_DRIVER_INFO_SIGNATURE
1700 if (*ProfileOffset
< (Offset
+ DriverInfoData
->DriverInfo
.Header
.Length
)) {
1701 if (RemainingSize
>= DriverInfoData
->DriverInfo
.Header
.Length
) {
1702 DriverInfo
= ProfileBuffer
;
1703 CopyMem (DriverInfo
, &DriverInfoData
->DriverInfo
, sizeof (MEMORY_PROFILE_DRIVER_INFO
));
1704 if (DriverInfo
->PdbStringOffset
!= 0) {
1705 PdbSize
= AsciiStrSize (DriverInfoData
->PdbString
);
1706 CopyMem ((VOID
*) ((UINTN
) DriverInfo
+ DriverInfo
->PdbStringOffset
), DriverInfoData
->PdbString
, PdbSize
);
1708 RemainingSize
-= DriverInfo
->Header
.Length
;
1709 ProfileBuffer
= (UINT8
*) ProfileBuffer
+ DriverInfo
->Header
.Length
;
1714 Offset
+= DriverInfoData
->DriverInfo
.Header
.Length
;
1716 AllocInfoList
= DriverInfoData
->AllocInfoList
;
1717 for (AllocLink
= AllocInfoList
->ForwardLink
;
1718 AllocLink
!= AllocInfoList
;
1719 AllocLink
= AllocLink
->ForwardLink
) {
1720 AllocInfoData
= CR (
1722 MEMORY_PROFILE_ALLOC_INFO_DATA
,
1724 MEMORY_PROFILE_ALLOC_INFO_SIGNATURE
1726 if (*ProfileOffset
< (Offset
+ AllocInfoData
->AllocInfo
.Header
.Length
)) {
1727 if (RemainingSize
>= AllocInfoData
->AllocInfo
.Header
.Length
) {
1728 AllocInfo
= ProfileBuffer
;
1729 CopyMem (AllocInfo
, &AllocInfoData
->AllocInfo
, sizeof (MEMORY_PROFILE_ALLOC_INFO
));
1730 if (AllocInfo
->ActionStringOffset
) {
1731 ActionStringSize
= AsciiStrSize (AllocInfoData
->ActionString
);
1732 CopyMem ((VOID
*) ((UINTN
) AllocInfo
+ AllocInfo
->ActionStringOffset
), AllocInfoData
->ActionString
, ActionStringSize
);
1734 RemainingSize
-= AllocInfo
->Header
.Length
;
1735 ProfileBuffer
= (UINT8
*) ProfileBuffer
+ AllocInfo
->Header
.Length
;
1740 Offset
+= AllocInfoData
->AllocInfo
.Header
.Length
;
1745 if (*ProfileOffset
< (Offset
+ sizeof (MEMORY_PROFILE_FREE_MEMORY
))) {
1746 if (RemainingSize
>= sizeof (MEMORY_PROFILE_FREE_MEMORY
)) {
1747 FreeMemory
= ProfileBuffer
;
1748 CopyMem (FreeMemory
, &mSmramFreeMemory
, sizeof (MEMORY_PROFILE_FREE_MEMORY
));
1750 FreePageList
= &mSmmMemoryMap
;
1751 for (Node
= FreePageList
->BackLink
;
1752 Node
!= FreePageList
;
1753 Node
= Node
->BackLink
) {
1756 for (SmmPoolTypeIndex
= 0; SmmPoolTypeIndex
< SmmPoolTypeMax
; SmmPoolTypeIndex
++) {
1757 for (PoolListIndex
= 0; PoolListIndex
< MAX_POOL_INDEX
; PoolListIndex
++) {
1758 FreePoolList
= &mSmmPoolLists
[SmmPoolTypeIndex
][MAX_POOL_INDEX
- PoolListIndex
- 1];
1759 for (Node
= FreePoolList
->BackLink
;
1760 Node
!= FreePoolList
;
1761 Node
= Node
->BackLink
) {
1762 Pool
= BASE_CR (Node
, FREE_POOL_HEADER
, Link
);
1763 if (Pool
->Header
.Available
) {
1769 FreeMemory
->FreeMemoryEntryCount
= Index
;
1771 RemainingSize
-= sizeof (MEMORY_PROFILE_FREE_MEMORY
);
1772 ProfileBuffer
= (UINT8
*) ProfileBuffer
+ sizeof (MEMORY_PROFILE_FREE_MEMORY
);
1777 Offset
+= sizeof (MEMORY_PROFILE_FREE_MEMORY
);
1778 FreePageList
= &mSmmMemoryMap
;
1779 for (Node
= FreePageList
->BackLink
;
1780 Node
!= FreePageList
;
1781 Node
= Node
->BackLink
) {
1782 if (*ProfileOffset
< (Offset
+ sizeof (MEMORY_PROFILE_DESCRIPTOR
))) {
1783 if (RemainingSize
>= sizeof (MEMORY_PROFILE_DESCRIPTOR
)) {
1784 Pages
= BASE_CR (Node
, FREE_PAGE_LIST
, Link
);
1785 MemoryProfileDescriptor
= ProfileBuffer
;
1786 MemoryProfileDescriptor
->Header
.Signature
= MEMORY_PROFILE_DESCRIPTOR_SIGNATURE
;
1787 MemoryProfileDescriptor
->Header
.Length
= sizeof (MEMORY_PROFILE_DESCRIPTOR
);
1788 MemoryProfileDescriptor
->Header
.Revision
= MEMORY_PROFILE_DESCRIPTOR_REVISION
;
1789 MemoryProfileDescriptor
->Address
= (PHYSICAL_ADDRESS
) (UINTN
) Pages
;
1790 MemoryProfileDescriptor
->Size
= EFI_PAGES_TO_SIZE (Pages
->NumberOfPages
);
1792 RemainingSize
-= sizeof (MEMORY_PROFILE_DESCRIPTOR
);
1793 ProfileBuffer
= (UINT8
*) ProfileBuffer
+ sizeof (MEMORY_PROFILE_DESCRIPTOR
);
1798 Offset
+= sizeof (MEMORY_PROFILE_DESCRIPTOR
);
1800 for (SmmPoolTypeIndex
= 0; SmmPoolTypeIndex
< SmmPoolTypeMax
; SmmPoolTypeIndex
++) {
1801 for (PoolListIndex
= 0; PoolListIndex
< MAX_POOL_INDEX
; PoolListIndex
++) {
1802 FreePoolList
= &mSmmPoolLists
[SmmPoolTypeIndex
][MAX_POOL_INDEX
- PoolListIndex
- 1];
1803 for (Node
= FreePoolList
->BackLink
;
1804 Node
!= FreePoolList
;
1805 Node
= Node
->BackLink
) {
1806 Pool
= BASE_CR (Node
, FREE_POOL_HEADER
, Link
);
1807 if (Pool
->Header
.Available
) {
1808 if (*ProfileOffset
< (Offset
+ sizeof (MEMORY_PROFILE_DESCRIPTOR
))) {
1809 if (RemainingSize
>= sizeof (MEMORY_PROFILE_DESCRIPTOR
)) {
1810 MemoryProfileDescriptor
= ProfileBuffer
;
1811 MemoryProfileDescriptor
->Header
.Signature
= MEMORY_PROFILE_DESCRIPTOR_SIGNATURE
;
1812 MemoryProfileDescriptor
->Header
.Length
= sizeof (MEMORY_PROFILE_DESCRIPTOR
);
1813 MemoryProfileDescriptor
->Header
.Revision
= MEMORY_PROFILE_DESCRIPTOR_REVISION
;
1814 MemoryProfileDescriptor
->Address
= (PHYSICAL_ADDRESS
) (UINTN
) Pool
;
1815 MemoryProfileDescriptor
->Size
= Pool
->Header
.Size
;
1817 RemainingSize
-= sizeof (MEMORY_PROFILE_DESCRIPTOR
);
1818 ProfileBuffer
= (UINT8
*) ProfileBuffer
+ sizeof (MEMORY_PROFILE_DESCRIPTOR
);
1823 Offset
+= sizeof (MEMORY_PROFILE_DESCRIPTOR
);
1829 if (*ProfileOffset
< (Offset
+ sizeof (MEMORY_PROFILE_MEMORY_RANGE
))) {
1830 if (RemainingSize
>= sizeof (MEMORY_PROFILE_MEMORY_RANGE
)) {
1831 MemoryRange
= ProfileBuffer
;
1832 MemoryRange
->Header
.Signature
= MEMORY_PROFILE_MEMORY_RANGE_SIGNATURE
;
1833 MemoryRange
->Header
.Length
= sizeof (MEMORY_PROFILE_MEMORY_RANGE
);
1834 MemoryRange
->Header
.Revision
= MEMORY_PROFILE_MEMORY_RANGE_REVISION
;
1835 MemoryRange
->MemoryRangeCount
= (UINT32
) mFullSmramRangeCount
;
1837 RemainingSize
-= sizeof (MEMORY_PROFILE_MEMORY_RANGE
);
1838 ProfileBuffer
= (UINT8
*) ProfileBuffer
+ sizeof (MEMORY_PROFILE_MEMORY_RANGE
);
1843 Offset
+= sizeof (MEMORY_PROFILE_MEMORY_RANGE
);
1844 for (Index
= 0; Index
< mFullSmramRangeCount
; Index
++) {
1845 if (*ProfileOffset
< (Offset
+ sizeof (MEMORY_PROFILE_DESCRIPTOR
))) {
1846 if (RemainingSize
>= sizeof (MEMORY_PROFILE_DESCRIPTOR
)) {
1847 MemoryProfileDescriptor
= ProfileBuffer
;
1848 MemoryProfileDescriptor
->Header
.Signature
= MEMORY_PROFILE_DESCRIPTOR_SIGNATURE
;
1849 MemoryProfileDescriptor
->Header
.Length
= sizeof (MEMORY_PROFILE_DESCRIPTOR
);
1850 MemoryProfileDescriptor
->Header
.Revision
= MEMORY_PROFILE_DESCRIPTOR_REVISION
;
1851 MemoryProfileDescriptor
->Address
= mFullSmramRanges
[Index
].PhysicalStart
;
1852 MemoryProfileDescriptor
->Size
= mFullSmramRanges
[Index
].PhysicalSize
;
1854 RemainingSize
-= sizeof (MEMORY_PROFILE_DESCRIPTOR
);
1855 ProfileBuffer
= (UINT8
*) ProfileBuffer
+ sizeof (MEMORY_PROFILE_DESCRIPTOR
);
1860 Offset
+= sizeof (MEMORY_PROFILE_DESCRIPTOR
);
1865 // On output, actual profile data size copied.
1867 *ProfileSize
-= RemainingSize
;
1869 // On output, next time profile buffer offset to copy.
1871 *ProfileOffset
= Offset
;
1875 Get memory profile data.
1877 @param[in] This The EDKII_SMM_MEMORY_PROFILE_PROTOCOL instance.
1878 @param[in, out] ProfileSize On entry, points to the size in bytes of the ProfileBuffer.
1879 On return, points to the size of the data returned in ProfileBuffer.
1880 @param[out] ProfileBuffer Profile buffer.
1882 @return EFI_SUCCESS Get the memory profile data successfully.
1883 @return EFI_UNSUPPORTED Memory profile is unsupported.
1884 @return EFI_BUFFER_TO_SMALL The ProfileSize is too small for the resulting data.
1885 ProfileSize is updated with the size required.
1890 SmramProfileProtocolGetData (
1891 IN EDKII_SMM_MEMORY_PROFILE_PROTOCOL
*This
,
1892 IN OUT UINT64
*ProfileSize
,
1893 OUT VOID
*ProfileBuffer
1898 MEMORY_PROFILE_CONTEXT_DATA
*ContextData
;
1899 BOOLEAN SmramProfileGettingStatus
;
1901 ContextData
= GetSmramProfileContext ();
1902 if (ContextData
== NULL
) {
1903 return EFI_UNSUPPORTED
;
1906 SmramProfileGettingStatus
= mSmramProfileGettingStatus
;
1907 mSmramProfileGettingStatus
= TRUE
;
1909 Size
= SmramProfileGetDataSize ();
1911 if (*ProfileSize
< Size
) {
1912 *ProfileSize
= Size
;
1913 mSmramProfileGettingStatus
= SmramProfileGettingStatus
;
1914 return EFI_BUFFER_TOO_SMALL
;
1918 SmramProfileCopyData (ProfileBuffer
, &Size
, &Offset
);
1919 *ProfileSize
= Size
;
1921 mSmramProfileGettingStatus
= SmramProfileGettingStatus
;
1926 Register image to memory profile.
1928 @param[in] This The EDKII_SMM_MEMORY_PROFILE_PROTOCOL instance.
1929 @param[in] FilePath File path of the image.
1930 @param[in] ImageBase Image base address.
1931 @param[in] ImageSize Image size.
1932 @param[in] FileType File type of the image.
1934 @return EFI_SUCCESS Register successfully.
1935 @return EFI_UNSUPPORTED Memory profile is unsupported,
1936 or memory profile for the image is not required.
1937 @return EFI_OUT_OF_RESOURCES No enough resource for this register.
1942 SmramProfileProtocolRegisterImage (
1943 IN EDKII_SMM_MEMORY_PROFILE_PROTOCOL
*This
,
1944 IN EFI_DEVICE_PATH_PROTOCOL
*FilePath
,
1945 IN PHYSICAL_ADDRESS ImageBase
,
1946 IN UINT64 ImageSize
,
1947 IN EFI_FV_FILETYPE FileType
1951 EFI_SMM_DRIVER_ENTRY DriverEntry
;
1952 VOID
*EntryPointInImage
;
1955 ZeroMem (&DriverEntry
, sizeof (DriverEntry
));
1956 Name
= GetFileNameFromFilePath (FilePath
);
1958 CopyMem (&DriverEntry
.FileName
, Name
, sizeof (EFI_GUID
));
1960 DriverEntry
.ImageBuffer
= ImageBase
;
1961 DriverEntry
.NumberOfPage
= EFI_SIZE_TO_PAGES ((UINTN
) ImageSize
);
1962 Status
= InternalPeCoffGetEntryPoint ((VOID
*) (UINTN
) DriverEntry
.ImageBuffer
, &EntryPointInImage
);
1963 ASSERT_EFI_ERROR (Status
);
1964 DriverEntry
.ImageEntryPoint
= (PHYSICAL_ADDRESS
) (UINTN
) EntryPointInImage
;
1966 return RegisterSmramProfileImage (&DriverEntry
, FALSE
);
1970 Unregister image from memory profile.
1972 @param[in] This The EDKII_SMM_MEMORY_PROFILE_PROTOCOL instance.
1973 @param[in] FilePath File path of the image.
1974 @param[in] ImageBase Image base address.
1975 @param[in] ImageSize Image size.
1977 @return EFI_SUCCESS Unregister successfully.
1978 @return EFI_UNSUPPORTED Memory profile is unsupported,
1979 or memory profile for the image is not required.
1980 @return EFI_NOT_FOUND The image is not found.
1985 SmramProfileProtocolUnregisterImage (
1986 IN EDKII_SMM_MEMORY_PROFILE_PROTOCOL
*This
,
1987 IN EFI_DEVICE_PATH_PROTOCOL
*FilePath
,
1988 IN PHYSICAL_ADDRESS ImageBase
,
1993 EFI_SMM_DRIVER_ENTRY DriverEntry
;
1994 VOID
*EntryPointInImage
;
1997 ZeroMem (&DriverEntry
, sizeof (DriverEntry
));
1998 Name
= GetFileNameFromFilePath (FilePath
);
2000 CopyMem (&DriverEntry
.FileName
, Name
, sizeof (EFI_GUID
));
2002 DriverEntry
.ImageBuffer
= ImageBase
;
2003 DriverEntry
.NumberOfPage
= EFI_SIZE_TO_PAGES ((UINTN
) ImageSize
);
2004 Status
= InternalPeCoffGetEntryPoint ((VOID
*) (UINTN
) DriverEntry
.ImageBuffer
, &EntryPointInImage
);
2005 ASSERT_EFI_ERROR (Status
);
2006 DriverEntry
.ImageEntryPoint
= (PHYSICAL_ADDRESS
) (UINTN
) EntryPointInImage
;
2008 return UnregisterSmramProfileImage (&DriverEntry
, FALSE
);
2012 Get memory profile recording state.
2014 @param[in] This The EDKII_SMM_MEMORY_PROFILE_PROTOCOL instance.
2015 @param[out] RecordingState Recording state.
2017 @return EFI_SUCCESS Memory profile recording state is returned.
2018 @return EFI_UNSUPPORTED Memory profile is unsupported.
2019 @return EFI_INVALID_PARAMETER RecordingState is NULL.
2024 SmramProfileProtocolGetRecordingState (
2025 IN EDKII_SMM_MEMORY_PROFILE_PROTOCOL
*This
,
2026 OUT BOOLEAN
*RecordingState
2029 MEMORY_PROFILE_CONTEXT_DATA
*ContextData
;
2031 ContextData
= GetSmramProfileContext ();
2032 if (ContextData
== NULL
) {
2033 return EFI_UNSUPPORTED
;
2036 if (RecordingState
== NULL
) {
2037 return EFI_INVALID_PARAMETER
;
2039 *RecordingState
= mSmramProfileRecordingEnable
;
2044 Set memory profile recording state.
2046 @param[in] This The EDKII_SMM_MEMORY_PROFILE_PROTOCOL instance.
2047 @param[in] RecordingState Recording state.
2049 @return EFI_SUCCESS Set memory profile recording state successfully.
2050 @return EFI_UNSUPPORTED Memory profile is unsupported.
2055 SmramProfileProtocolSetRecordingState (
2056 IN EDKII_SMM_MEMORY_PROFILE_PROTOCOL
*This
,
2057 IN BOOLEAN RecordingState
2060 MEMORY_PROFILE_CONTEXT_DATA
*ContextData
;
2062 ContextData
= GetSmramProfileContext ();
2063 if (ContextData
== NULL
) {
2064 return EFI_UNSUPPORTED
;
2067 mSmramProfileRecordingEnable
= RecordingState
;
2072 Record memory profile of multilevel caller.
2074 @param[in] This The EDKII_SMM_MEMORY_PROFILE_PROTOCOL instance.
2075 @param[in] CallerAddress Address of caller.
2076 @param[in] Action Memory profile action.
2077 @param[in] MemoryType Memory type.
2078 EfiMaxMemoryType means the MemoryType is unknown.
2079 @param[in] Buffer Buffer address.
2080 @param[in] Size Buffer size.
2081 @param[in] ActionString String for memory profile action.
2082 Only needed for user defined allocate action.
2084 @return EFI_SUCCESS Memory profile is updated.
2085 @return EFI_UNSUPPORTED Memory profile is unsupported,
2086 or memory profile for the image is not required,
2087 or memory profile for the memory type is not required.
2088 @return EFI_ACCESS_DENIED It is during memory profile data getting.
2089 @return EFI_ABORTED Memory profile recording is not enabled.
2090 @return EFI_OUT_OF_RESOURCES No enough resource to update memory profile for allocate action.
2091 @return EFI_NOT_FOUND No matched allocate info found for free action.
2096 SmramProfileProtocolRecord (
2097 IN EDKII_SMM_MEMORY_PROFILE_PROTOCOL
*This
,
2098 IN PHYSICAL_ADDRESS CallerAddress
,
2099 IN MEMORY_PROFILE_ACTION Action
,
2100 IN EFI_MEMORY_TYPE MemoryType
,
2103 IN CHAR8
*ActionString OPTIONAL
2106 return SmmCoreUpdateProfile (CallerAddress
, Action
, MemoryType
, Size
, Buffer
, ActionString
);
2110 SMRAM profile handler to get profile info.
2112 @param SmramProfileParameterGetInfo The parameter of SMM profile get size.
2116 SmramProfileHandlerGetInfo (
2117 IN SMRAM_PROFILE_PARAMETER_GET_PROFILE_INFO
*SmramProfileParameterGetInfo
2120 MEMORY_PROFILE_CONTEXT_DATA
*ContextData
;
2121 BOOLEAN SmramProfileGettingStatus
;
2123 ContextData
= GetSmramProfileContext ();
2124 if (ContextData
== NULL
) {
2128 SmramProfileGettingStatus
= mSmramProfileGettingStatus
;
2129 mSmramProfileGettingStatus
= TRUE
;
2131 SmramProfileParameterGetInfo
->ProfileSize
= SmramProfileGetDataSize();
2132 SmramProfileParameterGetInfo
->Header
.ReturnStatus
= 0;
2134 mSmramProfileGettingStatus
= SmramProfileGettingStatus
;
2138 SMRAM profile handler to get profile data.
2140 @param SmramProfileParameterGetData The parameter of SMM profile get data.
2144 SmramProfileHandlerGetData (
2145 IN SMRAM_PROFILE_PARAMETER_GET_PROFILE_DATA
*SmramProfileParameterGetData
2149 UINT64 ProfileOffset
;
2150 SMRAM_PROFILE_PARAMETER_GET_PROFILE_DATA SmramProfileGetData
;
2151 MEMORY_PROFILE_CONTEXT_DATA
*ContextData
;
2152 BOOLEAN SmramProfileGettingStatus
;
2154 ContextData
= GetSmramProfileContext ();
2155 if (ContextData
== NULL
) {
2159 SmramProfileGettingStatus
= mSmramProfileGettingStatus
;
2160 mSmramProfileGettingStatus
= TRUE
;
2163 CopyMem (&SmramProfileGetData
, SmramProfileParameterGetData
, sizeof (SmramProfileGetData
));
2165 ProfileSize
= SmramProfileGetDataSize();
2170 if (!SmmIsBufferOutsideSmmValid ((UINTN
) SmramProfileGetData
.ProfileBuffer
, (UINTN
) ProfileSize
)) {
2171 DEBUG ((EFI_D_ERROR
, "SmramProfileHandlerGetData: SMM ProfileBuffer in SMRAM or overflow!\n"));
2172 SmramProfileParameterGetData
->ProfileSize
= ProfileSize
;
2173 SmramProfileParameterGetData
->Header
.ReturnStatus
= (UINT64
) (INT64
) (INTN
) EFI_ACCESS_DENIED
;
2177 if (SmramProfileGetData
.ProfileSize
< ProfileSize
) {
2178 SmramProfileParameterGetData
->ProfileSize
= ProfileSize
;
2179 SmramProfileParameterGetData
->Header
.ReturnStatus
= (UINT64
) (INT64
) (INTN
) EFI_BUFFER_TOO_SMALL
;
2184 SmramProfileCopyData ((VOID
*) (UINTN
) SmramProfileGetData
.ProfileBuffer
, &ProfileSize
, &ProfileOffset
);
2185 SmramProfileParameterGetData
->ProfileSize
= ProfileSize
;
2186 SmramProfileParameterGetData
->Header
.ReturnStatus
= 0;
2189 mSmramProfileGettingStatus
= SmramProfileGettingStatus
;
2193 SMRAM profile handler to get profile data by offset.
2195 @param SmramProfileParameterGetDataByOffset The parameter of SMM profile get data by offset.
2199 SmramProfileHandlerGetDataByOffset (
2200 IN SMRAM_PROFILE_PARAMETER_GET_PROFILE_DATA_BY_OFFSET
*SmramProfileParameterGetDataByOffset
2203 SMRAM_PROFILE_PARAMETER_GET_PROFILE_DATA_BY_OFFSET SmramProfileGetDataByOffset
;
2204 MEMORY_PROFILE_CONTEXT_DATA
*ContextData
;
2205 BOOLEAN SmramProfileGettingStatus
;
2207 ContextData
= GetSmramProfileContext ();
2208 if (ContextData
== NULL
) {
2212 SmramProfileGettingStatus
= mSmramProfileGettingStatus
;
2213 mSmramProfileGettingStatus
= TRUE
;
2216 CopyMem (&SmramProfileGetDataByOffset
, SmramProfileParameterGetDataByOffset
, sizeof (SmramProfileGetDataByOffset
));
2221 if (!SmmIsBufferOutsideSmmValid ((UINTN
) SmramProfileGetDataByOffset
.ProfileBuffer
, (UINTN
) SmramProfileGetDataByOffset
.ProfileSize
)) {
2222 DEBUG ((EFI_D_ERROR
, "SmramProfileHandlerGetDataByOffset: SMM ProfileBuffer in SMRAM or overflow!\n"));
2223 SmramProfileParameterGetDataByOffset
->Header
.ReturnStatus
= (UINT64
) (INT64
) (INTN
) EFI_ACCESS_DENIED
;
2227 SmramProfileCopyData ((VOID
*) (UINTN
) SmramProfileGetDataByOffset
.ProfileBuffer
, &SmramProfileGetDataByOffset
.ProfileSize
, &SmramProfileGetDataByOffset
.ProfileOffset
);
2228 CopyMem (SmramProfileParameterGetDataByOffset
, &SmramProfileGetDataByOffset
, sizeof (SmramProfileGetDataByOffset
));
2229 SmramProfileParameterGetDataByOffset
->Header
.ReturnStatus
= 0;
2232 mSmramProfileGettingStatus
= SmramProfileGettingStatus
;
2236 SMRAM profile handler to register SMM image.
2238 @param SmramProfileParameterRegisterImage The parameter of SMM profile register image.
2242 SmramProfileHandlerRegisterImage (
2243 IN SMRAM_PROFILE_PARAMETER_REGISTER_IMAGE
*SmramProfileParameterRegisterImage
2247 EFI_SMM_DRIVER_ENTRY DriverEntry
;
2248 VOID
*EntryPointInImage
;
2250 ZeroMem (&DriverEntry
, sizeof (DriverEntry
));
2251 CopyMem (&DriverEntry
.FileName
, &SmramProfileParameterRegisterImage
->FileName
, sizeof(EFI_GUID
));
2252 DriverEntry
.ImageBuffer
= SmramProfileParameterRegisterImage
->ImageBuffer
;
2253 DriverEntry
.NumberOfPage
= (UINTN
) SmramProfileParameterRegisterImage
->NumberOfPage
;
2254 Status
= InternalPeCoffGetEntryPoint ((VOID
*) (UINTN
) DriverEntry
.ImageBuffer
, &EntryPointInImage
);
2255 ASSERT_EFI_ERROR (Status
);
2256 DriverEntry
.ImageEntryPoint
= (PHYSICAL_ADDRESS
) (UINTN
) EntryPointInImage
;
2258 Status
= RegisterSmramProfileImage (&DriverEntry
, FALSE
);
2259 if (!EFI_ERROR (Status
)) {
2260 SmramProfileParameterRegisterImage
->Header
.ReturnStatus
= 0;
2265 SMRAM profile handler to unregister SMM image.
2267 @param SmramProfileParameterUnregisterImage The parameter of SMM profile unregister image.
2271 SmramProfileHandlerUnregisterImage (
2272 IN SMRAM_PROFILE_PARAMETER_UNREGISTER_IMAGE
*SmramProfileParameterUnregisterImage
2276 EFI_SMM_DRIVER_ENTRY DriverEntry
;
2277 VOID
*EntryPointInImage
;
2279 ZeroMem (&DriverEntry
, sizeof (DriverEntry
));
2280 CopyMem (&DriverEntry
.FileName
, &SmramProfileParameterUnregisterImage
->FileName
, sizeof (EFI_GUID
));
2281 DriverEntry
.ImageBuffer
= SmramProfileParameterUnregisterImage
->ImageBuffer
;
2282 DriverEntry
.NumberOfPage
= (UINTN
) SmramProfileParameterUnregisterImage
->NumberOfPage
;
2283 Status
= InternalPeCoffGetEntryPoint ((VOID
*) (UINTN
) DriverEntry
.ImageBuffer
, &EntryPointInImage
);
2284 ASSERT_EFI_ERROR (Status
);
2285 DriverEntry
.ImageEntryPoint
= (PHYSICAL_ADDRESS
) (UINTN
) EntryPointInImage
;
2287 Status
= UnregisterSmramProfileImage (&DriverEntry
, FALSE
);
2288 if (!EFI_ERROR (Status
)) {
2289 SmramProfileParameterUnregisterImage
->Header
.ReturnStatus
= 0;
2294 Dispatch function for a Software SMI handler.
2296 Caution: This function may receive untrusted input.
2297 Communicate buffer and buffer size are external input, so this function will do basic validation.
2299 @param DispatchHandle The unique handle assigned to this handler by SmiHandlerRegister().
2300 @param Context Points to an optional handler context which was specified when the
2301 handler was registered.
2302 @param CommBuffer A pointer to a collection of data in memory that will
2303 be conveyed from a non-SMM environment into an SMM environment.
2304 @param CommBufferSize The size of the CommBuffer.
2306 @retval EFI_SUCCESS Command is handled successfully.
2311 SmramProfileHandler (
2312 IN EFI_HANDLE DispatchHandle
,
2313 IN CONST VOID
*Context OPTIONAL
,
2314 IN OUT VOID
*CommBuffer OPTIONAL
,
2315 IN OUT UINTN
*CommBufferSize OPTIONAL
2318 SMRAM_PROFILE_PARAMETER_HEADER
*SmramProfileParameterHeader
;
2319 UINTN TempCommBufferSize
;
2320 SMRAM_PROFILE_PARAMETER_RECORDING_STATE
*ParameterRecordingState
;
2322 DEBUG ((EFI_D_ERROR
, "SmramProfileHandler Enter\n"));
2325 // If input is invalid, stop processing this SMI
2327 if (CommBuffer
== NULL
|| CommBufferSize
== NULL
) {
2331 TempCommBufferSize
= *CommBufferSize
;
2333 if (TempCommBufferSize
< sizeof (SMRAM_PROFILE_PARAMETER_HEADER
)) {
2334 DEBUG ((EFI_D_ERROR
, "SmramProfileHandler: SMM communication buffer size invalid!\n"));
2338 if (mSmramReadyToLock
&& !SmmIsBufferOutsideSmmValid ((UINTN
)CommBuffer
, TempCommBufferSize
)) {
2339 DEBUG ((EFI_D_ERROR
, "SmramProfileHandler: SMM communication buffer in SMRAM or overflow!\n"));
2343 SmramProfileParameterHeader
= (SMRAM_PROFILE_PARAMETER_HEADER
*) ((UINTN
) CommBuffer
);
2345 SmramProfileParameterHeader
->ReturnStatus
= (UINT64
)-1;
2347 if (GetSmramProfileContext () == NULL
) {
2348 SmramProfileParameterHeader
->ReturnStatus
= (UINT64
) (INT64
) (INTN
) EFI_UNSUPPORTED
;
2352 switch (SmramProfileParameterHeader
->Command
) {
2353 case SMRAM_PROFILE_COMMAND_GET_PROFILE_INFO
:
2354 DEBUG ((EFI_D_ERROR
, "SmramProfileHandlerGetInfo\n"));
2355 if (TempCommBufferSize
!= sizeof (SMRAM_PROFILE_PARAMETER_GET_PROFILE_INFO
)) {
2356 DEBUG ((EFI_D_ERROR
, "SmramProfileHandler: SMM communication buffer size invalid!\n"));
2359 SmramProfileHandlerGetInfo ((SMRAM_PROFILE_PARAMETER_GET_PROFILE_INFO
*) (UINTN
) CommBuffer
);
2361 case SMRAM_PROFILE_COMMAND_GET_PROFILE_DATA
:
2362 DEBUG ((EFI_D_ERROR
, "SmramProfileHandlerGetData\n"));
2363 if (TempCommBufferSize
!= sizeof (SMRAM_PROFILE_PARAMETER_GET_PROFILE_DATA
)) {
2364 DEBUG ((EFI_D_ERROR
, "SmramProfileHandler: SMM communication buffer size invalid!\n"));
2367 SmramProfileHandlerGetData ((SMRAM_PROFILE_PARAMETER_GET_PROFILE_DATA
*) (UINTN
) CommBuffer
);
2369 case SMRAM_PROFILE_COMMAND_GET_PROFILE_DATA_BY_OFFSET
:
2370 DEBUG ((EFI_D_ERROR
, "SmramProfileHandlerGetDataByOffset\n"));
2371 if (TempCommBufferSize
!= sizeof (SMRAM_PROFILE_PARAMETER_GET_PROFILE_DATA_BY_OFFSET
)) {
2372 DEBUG ((EFI_D_ERROR
, "SmramProfileHandler: SMM communication buffer size invalid!\n"));
2375 SmramProfileHandlerGetDataByOffset ((SMRAM_PROFILE_PARAMETER_GET_PROFILE_DATA_BY_OFFSET
*) (UINTN
) CommBuffer
);
2377 case SMRAM_PROFILE_COMMAND_REGISTER_IMAGE
:
2378 DEBUG ((EFI_D_ERROR
, "SmramProfileHandlerRegisterImage\n"));
2379 if (TempCommBufferSize
!= sizeof (SMRAM_PROFILE_PARAMETER_REGISTER_IMAGE
)) {
2380 DEBUG ((EFI_D_ERROR
, "SmramProfileHandler: SMM communication buffer size invalid!\n"));
2383 if (mSmramReadyToLock
) {
2386 SmramProfileHandlerRegisterImage ((SMRAM_PROFILE_PARAMETER_REGISTER_IMAGE
*) (UINTN
) CommBuffer
);
2388 case SMRAM_PROFILE_COMMAND_UNREGISTER_IMAGE
:
2389 DEBUG ((EFI_D_ERROR
, "SmramProfileHandlerUnregisterImage\n"));
2390 if (TempCommBufferSize
!= sizeof (SMRAM_PROFILE_PARAMETER_UNREGISTER_IMAGE
)) {
2391 DEBUG ((EFI_D_ERROR
, "SmramProfileHandler: SMM communication buffer size invalid!\n"));
2394 if (mSmramReadyToLock
) {
2397 SmramProfileHandlerUnregisterImage ((SMRAM_PROFILE_PARAMETER_UNREGISTER_IMAGE
*) (UINTN
) CommBuffer
);
2399 case SMRAM_PROFILE_COMMAND_GET_RECORDING_STATE
:
2400 DEBUG ((EFI_D_ERROR
, "SmramProfileHandlerGetRecordingState\n"));
2401 if (TempCommBufferSize
!= sizeof (SMRAM_PROFILE_PARAMETER_RECORDING_STATE
)) {
2402 DEBUG ((EFI_D_ERROR
, "SmramProfileHandler: SMM communication buffer size invalid!\n"));
2405 ParameterRecordingState
= (SMRAM_PROFILE_PARAMETER_RECORDING_STATE
*) (UINTN
) CommBuffer
;
2406 ParameterRecordingState
->RecordingState
= mSmramProfileRecordingEnable
;
2407 ParameterRecordingState
->Header
.ReturnStatus
= 0;
2409 case SMRAM_PROFILE_COMMAND_SET_RECORDING_STATE
:
2410 DEBUG ((EFI_D_ERROR
, "SmramProfileHandlerSetRecordingState\n"));
2411 if (TempCommBufferSize
!= sizeof (SMRAM_PROFILE_PARAMETER_RECORDING_STATE
)) {
2412 DEBUG ((EFI_D_ERROR
, "SmramProfileHandler: SMM communication buffer size invalid!\n"));
2415 ParameterRecordingState
= (SMRAM_PROFILE_PARAMETER_RECORDING_STATE
*) (UINTN
) CommBuffer
;
2416 mSmramProfileRecordingEnable
= ParameterRecordingState
->RecordingState
;
2417 ParameterRecordingState
->Header
.ReturnStatus
= 0;
2424 DEBUG ((EFI_D_ERROR
, "SmramProfileHandler Exit\n"));
2430 Register SMRAM profile handler.
2434 RegisterSmramProfileHandler (
2439 EFI_HANDLE DispatchHandle
;
2441 if (!IS_SMRAM_PROFILE_ENABLED
) {
2445 Status
= SmiHandlerRegister (
2446 SmramProfileHandler
,
2447 &gEdkiiMemoryProfileGuid
,
2450 ASSERT_EFI_ERROR (Status
);
2453 ////////////////////
2465 MEMORY_PROFILE_CONTEXT_DATA
*ContextData
;
2466 BOOLEAN SmramProfileGettingStatus
;
2468 ContextData
= GetSmramProfileContext ();
2469 if (ContextData
== NULL
) {
2473 SmramProfileGettingStatus
= mSmramProfileGettingStatus
;
2474 mSmramProfileGettingStatus
= TRUE
;
2476 DEBUG ((EFI_D_INFO
, "FullSmramRange address - 0x%08x\n", mFullSmramRanges
));
2478 DEBUG ((EFI_D_INFO
, "======= SmramProfile begin =======\n"));
2480 DEBUG ((EFI_D_INFO
, "FullSmramRange:\n"));
2481 for (Index
= 0; Index
< mFullSmramRangeCount
; Index
++) {
2482 DEBUG ((EFI_D_INFO
, " FullSmramRange (0x%x)\n", Index
));
2483 DEBUG ((EFI_D_INFO
, " PhysicalStart - 0x%016lx\n", mFullSmramRanges
[Index
].PhysicalStart
));
2484 DEBUG ((EFI_D_INFO
, " CpuStart - 0x%016lx\n", mFullSmramRanges
[Index
].CpuStart
));
2485 DEBUG ((EFI_D_INFO
, " PhysicalSize - 0x%016lx\n", mFullSmramRanges
[Index
].PhysicalSize
));
2486 DEBUG ((EFI_D_INFO
, " RegionState - 0x%016lx\n", mFullSmramRanges
[Index
].RegionState
));
2489 DEBUG ((EFI_D_INFO
, "======= SmramProfile end =======\n"));
2491 mSmramProfileGettingStatus
= SmramProfileGettingStatus
;
2495 Dump SMRAM free page list.
2503 LIST_ENTRY
*FreePageList
;
2505 FREE_PAGE_LIST
*Pages
;
2507 MEMORY_PROFILE_CONTEXT_DATA
*ContextData
;
2508 BOOLEAN SmramProfileGettingStatus
;
2510 ContextData
= GetSmramProfileContext ();
2511 if (ContextData
== NULL
) {
2515 SmramProfileGettingStatus
= mSmramProfileGettingStatus
;
2516 mSmramProfileGettingStatus
= TRUE
;
2518 DEBUG ((EFI_D_INFO
, "======= SmramProfile begin =======\n"));
2520 DEBUG ((EFI_D_INFO
, "FreePagesList:\n"));
2521 FreePageList
= &mSmmMemoryMap
;
2522 for (Node
= FreePageList
->BackLink
, Index
= 0;
2523 Node
!= FreePageList
;
2524 Node
= Node
->BackLink
, Index
++) {
2525 Pages
= BASE_CR (Node
, FREE_PAGE_LIST
, Link
);
2526 DEBUG ((EFI_D_INFO
, " Index - 0x%x\n", Index
));
2527 DEBUG ((EFI_D_INFO
, " PhysicalStart - 0x%016lx\n", (PHYSICAL_ADDRESS
) (UINTN
) Pages
));
2528 DEBUG ((EFI_D_INFO
, " NumberOfPages - 0x%08x\n", Pages
->NumberOfPages
));
2531 DEBUG ((EFI_D_INFO
, "======= SmramProfile end =======\n"));
2533 mSmramProfileGettingStatus
= SmramProfileGettingStatus
;
2537 Dump SMRAM free pool list.
2545 LIST_ENTRY
*FreePoolList
;
2547 FREE_POOL_HEADER
*Pool
;
2549 UINTN PoolListIndex
;
2550 MEMORY_PROFILE_CONTEXT_DATA
*ContextData
;
2551 BOOLEAN SmramProfileGettingStatus
;
2552 UINTN SmmPoolTypeIndex
;
2554 ContextData
= GetSmramProfileContext ();
2555 if (ContextData
== NULL
) {
2559 SmramProfileGettingStatus
= mSmramProfileGettingStatus
;
2560 mSmramProfileGettingStatus
= TRUE
;
2562 DEBUG ((DEBUG_INFO
, "======= SmramProfile begin =======\n"));
2564 for (SmmPoolTypeIndex
= 0; SmmPoolTypeIndex
< SmmPoolTypeMax
; SmmPoolTypeIndex
++) {
2565 for (PoolListIndex
= 0; PoolListIndex
< MAX_POOL_INDEX
; PoolListIndex
++) {
2566 DEBUG ((DEBUG_INFO
, "FreePoolList(%d)(%d):\n", SmmPoolTypeIndex
, PoolListIndex
));
2567 FreePoolList
= &mSmmPoolLists
[SmmPoolTypeIndex
][PoolListIndex
];
2568 for (Node
= FreePoolList
->BackLink
, Index
= 0;
2569 Node
!= FreePoolList
;
2570 Node
= Node
->BackLink
, Index
++) {
2571 Pool
= BASE_CR (Node
, FREE_POOL_HEADER
, Link
);
2572 DEBUG ((DEBUG_INFO
, " Index - 0x%x\n", Index
));
2573 DEBUG ((DEBUG_INFO
, " PhysicalStart - 0x%016lx\n", (PHYSICAL_ADDRESS
) (UINTN
) Pool
));
2574 DEBUG ((DEBUG_INFO
, " Size - 0x%08x\n", Pool
->Header
.Size
));
2575 DEBUG ((DEBUG_INFO
, " Available - 0x%02x\n", Pool
->Header
.Available
));
2580 DEBUG ((DEBUG_INFO
, "======= SmramProfile end =======\n"));
2582 mSmramProfileGettingStatus
= SmramProfileGettingStatus
;
2585 GLOBAL_REMOVE_IF_UNREFERENCED CHAR8
*mSmmActionString
[] = {
2587 "gSmst->SmmAllocatePages",
2588 "gSmst->SmmFreePages",
2589 "gSmst->SmmAllocatePool",
2590 "gSmst->SmmFreePool",
2594 MEMORY_PROFILE_ACTION Action
;
2598 GLOBAL_REMOVE_IF_UNREFERENCED ACTION_STRING mExtActionString
[] = {
2599 {MEMORY_PROFILE_ACTION_LIB_ALLOCATE_PAGES
, "Lib:AllocatePages"},
2600 {MEMORY_PROFILE_ACTION_LIB_ALLOCATE_RUNTIME_PAGES
, "Lib:AllocateRuntimePages"},
2601 {MEMORY_PROFILE_ACTION_LIB_ALLOCATE_RESERVED_PAGES
, "Lib:AllocateReservedPages"},
2602 {MEMORY_PROFILE_ACTION_LIB_FREE_PAGES
, "Lib:FreePages"},
2603 {MEMORY_PROFILE_ACTION_LIB_ALLOCATE_ALIGNED_PAGES
, "Lib:AllocateAlignedPages"},
2604 {MEMORY_PROFILE_ACTION_LIB_ALLOCATE_ALIGNED_RUNTIME_PAGES
, "Lib:AllocateAlignedRuntimePages"},
2605 {MEMORY_PROFILE_ACTION_LIB_ALLOCATE_ALIGNED_RESERVED_PAGES
, "Lib:AllocateAlignedReservedPages"},
2606 {MEMORY_PROFILE_ACTION_LIB_FREE_ALIGNED_PAGES
, "Lib:FreeAlignedPages"},
2607 {MEMORY_PROFILE_ACTION_LIB_ALLOCATE_POOL
, "Lib:AllocatePool"},
2608 {MEMORY_PROFILE_ACTION_LIB_ALLOCATE_RUNTIME_POOL
, "Lib:AllocateRuntimePool"},
2609 {MEMORY_PROFILE_ACTION_LIB_ALLOCATE_RESERVED_POOL
, "Lib:AllocateReservedPool"},
2610 {MEMORY_PROFILE_ACTION_LIB_FREE_POOL
, "Lib:FreePool"},
2611 {MEMORY_PROFILE_ACTION_LIB_ALLOCATE_ZERO_POOL
, "Lib:AllocateZeroPool"},
2612 {MEMORY_PROFILE_ACTION_LIB_ALLOCATE_RUNTIME_ZERO_POOL
, "Lib:AllocateRuntimeZeroPool"},
2613 {MEMORY_PROFILE_ACTION_LIB_ALLOCATE_RESERVED_ZERO_POOL
, "Lib:AllocateReservedZeroPool"},
2614 {MEMORY_PROFILE_ACTION_LIB_ALLOCATE_COPY_POOL
, "Lib:AllocateCopyPool"},
2615 {MEMORY_PROFILE_ACTION_LIB_ALLOCATE_RUNTIME_COPY_POOL
, "Lib:AllocateRuntimeCopyPool"},
2616 {MEMORY_PROFILE_ACTION_LIB_ALLOCATE_RESERVED_COPY_POOL
, "Lib:AllocateReservedCopyPool"},
2617 {MEMORY_PROFILE_ACTION_LIB_REALLOCATE_POOL
, "Lib:ReallocatePool"},
2618 {MEMORY_PROFILE_ACTION_LIB_REALLOCATE_RUNTIME_POOL
, "Lib:ReallocateRuntimePool"},
2619 {MEMORY_PROFILE_ACTION_LIB_REALLOCATE_RESERVED_POOL
, "Lib:ReallocateReservedPool"},
2623 EFI_MEMORY_TYPE MemoryType
;
2624 CHAR8
*MemoryTypeStr
;
2625 } PROFILE_MEMORY_TYPE_STRING
;
2627 GLOBAL_REMOVE_IF_UNREFERENCED PROFILE_MEMORY_TYPE_STRING mMemoryTypeString
[] = {
2628 {EfiRuntimeServicesCode
, "EfiRuntimeServicesCode"},
2629 {EfiRuntimeServicesData
, "EfiRuntimeServicesData"}
2633 Memory type to string.
2635 @param[in] MemoryType Memory type.
2637 @return Pointer to string.
2641 ProfileMemoryTypeToStr (
2642 IN EFI_MEMORY_TYPE MemoryType
2646 for (Index
= 0; Index
< ARRAY_SIZE (mMemoryTypeString
); Index
++) {
2647 if (mMemoryTypeString
[Index
].MemoryType
== MemoryType
) {
2648 return mMemoryTypeString
[Index
].MemoryTypeStr
;
2652 return "UnexpectedMemoryType";
2658 @param[in] Action Profile action.
2660 @return Pointer to string.
2664 ProfileActionToStr (
2665 IN MEMORY_PROFILE_ACTION Action
2669 UINTN ActionStringCount
;
2670 CHAR8
**ActionString
;
2672 ActionString
= mSmmActionString
;
2673 ActionStringCount
= ARRAY_SIZE (mSmmActionString
);
2675 if ((UINTN
) (UINT32
) Action
< ActionStringCount
) {
2676 return ActionString
[Action
];
2678 for (Index
= 0; Index
< ARRAY_SIZE (mExtActionString
); Index
++) {
2679 if (mExtActionString
[Index
].Action
== Action
) {
2680 return mExtActionString
[Index
].String
;
2684 return ActionString
[0];
2696 MEMORY_PROFILE_CONTEXT
*Context
;
2697 MEMORY_PROFILE_DRIVER_INFO
*DriverInfo
;
2698 MEMORY_PROFILE_ALLOC_INFO
*AllocInfo
;
2699 MEMORY_PROFILE_CONTEXT_DATA
*ContextData
;
2700 MEMORY_PROFILE_DRIVER_INFO_DATA
*DriverInfoData
;
2701 MEMORY_PROFILE_ALLOC_INFO_DATA
*AllocInfoData
;
2702 LIST_ENTRY
*SmramDriverInfoList
;
2704 LIST_ENTRY
*DriverLink
;
2705 LIST_ENTRY
*AllocInfoList
;
2707 LIST_ENTRY
*AllocLink
;
2708 BOOLEAN SmramProfileGettingStatus
;
2711 ContextData
= GetSmramProfileContext ();
2712 if (ContextData
== NULL
) {
2716 SmramProfileGettingStatus
= mSmramProfileGettingStatus
;
2717 mSmramProfileGettingStatus
= TRUE
;
2719 Context
= &ContextData
->Context
;
2720 DEBUG ((EFI_D_INFO
, "======= SmramProfile begin =======\n"));
2721 DEBUG ((EFI_D_INFO
, "MEMORY_PROFILE_CONTEXT\n"));
2723 DEBUG ((EFI_D_INFO
, " CurrentTotalUsage - 0x%016lx\n", Context
->CurrentTotalUsage
));
2724 DEBUG ((EFI_D_INFO
, " PeakTotalUsage - 0x%016lx\n", Context
->PeakTotalUsage
));
2725 for (TypeIndex
= 0; TypeIndex
< sizeof (Context
->CurrentTotalUsageByType
) / sizeof (Context
->CurrentTotalUsageByType
[0]); TypeIndex
++) {
2726 if ((Context
->CurrentTotalUsageByType
[TypeIndex
] != 0) ||
2727 (Context
->PeakTotalUsageByType
[TypeIndex
] != 0)) {
2728 DEBUG ((EFI_D_INFO
, " CurrentTotalUsage[0x%02x] - 0x%016lx (%a)\n", TypeIndex
, Context
->CurrentTotalUsageByType
[TypeIndex
], ProfileMemoryTypeToStr (TypeIndex
)));
2729 DEBUG ((EFI_D_INFO
, " PeakTotalUsage[0x%02x] - 0x%016lx (%a)\n", TypeIndex
, Context
->PeakTotalUsageByType
[TypeIndex
], ProfileMemoryTypeToStr (TypeIndex
)));
2732 DEBUG ((EFI_D_INFO
, " TotalImageSize - 0x%016lx\n", Context
->TotalImageSize
));
2733 DEBUG ((EFI_D_INFO
, " ImageCount - 0x%08x\n", Context
->ImageCount
));
2734 DEBUG ((EFI_D_INFO
, " SequenceCount - 0x%08x\n", Context
->SequenceCount
));
2736 SmramDriverInfoList
= ContextData
->DriverInfoList
;
2737 for (DriverLink
= SmramDriverInfoList
->ForwardLink
, DriverIndex
= 0;
2738 DriverLink
!= SmramDriverInfoList
;
2739 DriverLink
= DriverLink
->ForwardLink
, DriverIndex
++) {
2740 DriverInfoData
= CR (
2742 MEMORY_PROFILE_DRIVER_INFO_DATA
,
2744 MEMORY_PROFILE_DRIVER_INFO_SIGNATURE
2746 DriverInfo
= &DriverInfoData
->DriverInfo
;
2747 DEBUG ((EFI_D_INFO
, " MEMORY_PROFILE_DRIVER_INFO (0x%x)\n", DriverIndex
));
2748 DEBUG ((EFI_D_INFO
, " FileName - %g\n", &DriverInfo
->FileName
));
2749 DEBUG ((EFI_D_INFO
, " ImageBase - 0x%016lx\n", DriverInfo
->ImageBase
));
2750 DEBUG ((EFI_D_INFO
, " ImageSize - 0x%016lx\n", DriverInfo
->ImageSize
));
2751 DEBUG ((EFI_D_INFO
, " EntryPoint - 0x%016lx\n", DriverInfo
->EntryPoint
));
2752 DEBUG ((EFI_D_INFO
, " ImageSubsystem - 0x%04x\n", DriverInfo
->ImageSubsystem
));
2753 DEBUG ((EFI_D_INFO
, " FileType - 0x%02x\n", DriverInfo
->FileType
));
2754 DEBUG ((EFI_D_INFO
, " CurrentUsage - 0x%016lx\n", DriverInfo
->CurrentUsage
));
2755 DEBUG ((EFI_D_INFO
, " PeakUsage - 0x%016lx\n", DriverInfo
->PeakUsage
));
2756 for (TypeIndex
= 0; TypeIndex
< sizeof (DriverInfo
->CurrentUsageByType
) / sizeof (DriverInfo
->CurrentUsageByType
[0]); TypeIndex
++) {
2757 if ((DriverInfo
->CurrentUsageByType
[TypeIndex
] != 0) ||
2758 (DriverInfo
->PeakUsageByType
[TypeIndex
] != 0)) {
2759 DEBUG ((EFI_D_INFO
, " CurrentUsage[0x%02x] - 0x%016lx (%a)\n", TypeIndex
, DriverInfo
->CurrentUsageByType
[TypeIndex
], ProfileMemoryTypeToStr (TypeIndex
)));
2760 DEBUG ((EFI_D_INFO
, " PeakUsage[0x%02x] - 0x%016lx (%a)\n", TypeIndex
, DriverInfo
->PeakUsageByType
[TypeIndex
], ProfileMemoryTypeToStr (TypeIndex
)));
2763 DEBUG ((EFI_D_INFO
, " AllocRecordCount - 0x%08x\n", DriverInfo
->AllocRecordCount
));
2765 AllocInfoList
= DriverInfoData
->AllocInfoList
;
2766 for (AllocLink
= AllocInfoList
->ForwardLink
, AllocIndex
= 0;
2767 AllocLink
!= AllocInfoList
;
2768 AllocLink
= AllocLink
->ForwardLink
, AllocIndex
++) {
2769 AllocInfoData
= CR (
2771 MEMORY_PROFILE_ALLOC_INFO_DATA
,
2773 MEMORY_PROFILE_ALLOC_INFO_SIGNATURE
2775 AllocInfo
= &AllocInfoData
->AllocInfo
;
2776 DEBUG ((EFI_D_INFO
, " MEMORY_PROFILE_ALLOC_INFO (0x%x)\n", AllocIndex
));
2777 DEBUG ((EFI_D_INFO
, " CallerAddress - 0x%016lx (Offset: 0x%08x)\n", AllocInfo
->CallerAddress
, AllocInfo
->CallerAddress
- DriverInfo
->ImageBase
));
2778 DEBUG ((EFI_D_INFO
, " SequenceId - 0x%08x\n", AllocInfo
->SequenceId
));
2779 if ((AllocInfo
->Action
& MEMORY_PROFILE_ACTION_USER_DEFINED_MASK
) != 0) {
2780 if (AllocInfoData
->ActionString
!= NULL
) {
2781 DEBUG ((EFI_D_INFO
, " Action - 0x%08x (%a)\n", AllocInfo
->Action
, AllocInfoData
->ActionString
));
2783 DEBUG ((EFI_D_INFO
, " Action - 0x%08x (UserDefined-0x%08x)\n", AllocInfo
->Action
, AllocInfo
->Action
));
2786 DEBUG ((EFI_D_INFO
, " Action - 0x%08x (%a)\n", AllocInfo
->Action
, ProfileActionToStr (AllocInfo
->Action
)));
2788 DEBUG ((EFI_D_INFO
, " MemoryType - 0x%08x (%a)\n", AllocInfo
->MemoryType
, ProfileMemoryTypeToStr (AllocInfo
->MemoryType
)));
2789 DEBUG ((EFI_D_INFO
, " Buffer - 0x%016lx\n", AllocInfo
->Buffer
));
2790 DEBUG ((EFI_D_INFO
, " Size - 0x%016lx\n", AllocInfo
->Size
));
2794 DEBUG ((EFI_D_INFO
, "======= SmramProfile end =======\n"));
2796 mSmramProfileGettingStatus
= SmramProfileGettingStatus
;
2800 Dump SMRAM infromation.
2809 if (IS_SMRAM_PROFILE_ENABLED
) {
2810 DumpSmramProfile ();
2811 DumpFreePagesList ();
2812 DumpFreePoolList ();