2 Support routines for SMRAM profile.
4 Copyright (c) 2014 - 2016, Intel Corporation. All rights reserved.<BR>
5 This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php.
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
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 BOOLEAN mSmramReadyToLock
;
81 BOOLEAN mSmramProfileGettingStatus
= FALSE
;
82 BOOLEAN mSmramProfileRecordingEnable
= MEMORY_PROFILE_RECORDING_DISABLE
;
83 EFI_DEVICE_PATH_PROTOCOL
*mSmramProfileDriverPath
;
84 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 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 the magic value from the PE/COFF header.
261 @param Hdr The buffer in which to return the PE32, PE32+, or TE header.
263 @return EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC - Image is PE32
264 @return EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC - Image is PE32+
268 InternalPeCoffGetPeHeaderMagicValue (
269 IN EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION Hdr
273 // NOTE: Some versions of Linux ELILO for Itanium have an incorrect magic value
274 // in the PE/COFF Header. If the MachineType is Itanium(IA64) and the
275 // Magic value in the OptionalHeader is EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
276 // then override the returned value to EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC
278 if (Hdr
.Pe32
->FileHeader
.Machine
== IMAGE_FILE_MACHINE_IA64
&& Hdr
.Pe32
->OptionalHeader
.Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
279 return EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC
;
282 // Return the magic value from the PC/COFF Optional Header
284 return Hdr
.Pe32
->OptionalHeader
.Magic
;
288 Retrieves and returns the Subsystem of a PE/COFF image that has been loaded into system memory.
289 If Pe32Data is NULL, then ASSERT().
291 @param Pe32Data The pointer to the PE/COFF image that is loaded in system memory.
293 @return The Subsystem of the PE/COFF image.
297 InternalPeCoffGetSubsystem (
301 EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION Hdr
;
302 EFI_IMAGE_DOS_HEADER
*DosHdr
;
305 ASSERT (Pe32Data
!= NULL
);
307 DosHdr
= (EFI_IMAGE_DOS_HEADER
*) Pe32Data
;
308 if (DosHdr
->e_magic
== EFI_IMAGE_DOS_SIGNATURE
) {
310 // DOS image header is present, so read the PE header after the DOS image header.
312 Hdr
.Pe32
= (EFI_IMAGE_NT_HEADERS32
*) ((UINTN
) Pe32Data
+ (UINTN
) ((DosHdr
->e_lfanew
) & 0x0ffff));
315 // DOS image header is not present, so PE header is at the image base.
317 Hdr
.Pe32
= (EFI_IMAGE_NT_HEADERS32
*) Pe32Data
;
320 if (Hdr
.Te
->Signature
== EFI_TE_IMAGE_HEADER_SIGNATURE
) {
321 return Hdr
.Te
->Subsystem
;
322 } else if (Hdr
.Pe32
->Signature
== EFI_IMAGE_NT_SIGNATURE
) {
323 Magic
= InternalPeCoffGetPeHeaderMagicValue (Hdr
);
324 if (Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
325 return Hdr
.Pe32
->OptionalHeader
.Subsystem
;
326 } else if (Magic
== EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC
) {
327 return Hdr
.Pe32Plus
->OptionalHeader
.Subsystem
;
335 Retrieves and returns a pointer to the entry point to a PE/COFF image that has been loaded
336 into system memory with the PE/COFF Loader Library functions.
338 Retrieves the entry point to the PE/COFF image specified by Pe32Data and returns this entry
339 point in EntryPoint. If the entry point could not be retrieved from the PE/COFF image, then
340 return RETURN_INVALID_PARAMETER. Otherwise return RETURN_SUCCESS.
341 If Pe32Data is NULL, then ASSERT().
342 If EntryPoint is NULL, then ASSERT().
344 @param Pe32Data The pointer to the PE/COFF image that is loaded in system memory.
345 @param EntryPoint The pointer to entry point to the PE/COFF image to return.
347 @retval RETURN_SUCCESS EntryPoint was returned.
348 @retval RETURN_INVALID_PARAMETER The entry point could not be found in the PE/COFF image.
352 InternalPeCoffGetEntryPoint (
354 OUT VOID
**EntryPoint
357 EFI_IMAGE_DOS_HEADER
*DosHdr
;
358 EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION Hdr
;
360 ASSERT (Pe32Data
!= NULL
);
361 ASSERT (EntryPoint
!= NULL
);
363 DosHdr
= (EFI_IMAGE_DOS_HEADER
*) Pe32Data
;
364 if (DosHdr
->e_magic
== EFI_IMAGE_DOS_SIGNATURE
) {
366 // DOS image header is present, so read the PE header after the DOS image header.
368 Hdr
.Pe32
= (EFI_IMAGE_NT_HEADERS32
*) ((UINTN
) Pe32Data
+ (UINTN
) ((DosHdr
->e_lfanew
) & 0x0ffff));
371 // DOS image header is not present, so PE header is at the image base.
373 Hdr
.Pe32
= (EFI_IMAGE_NT_HEADERS32
*) Pe32Data
;
377 // Calculate the entry point relative to the start of the image.
378 // AddressOfEntryPoint is common for PE32 & PE32+
380 if (Hdr
.Te
->Signature
== EFI_TE_IMAGE_HEADER_SIGNATURE
) {
381 *EntryPoint
= (VOID
*) ((UINTN
) Pe32Data
+ (UINTN
) (Hdr
.Te
->AddressOfEntryPoint
& 0x0ffffffff) + sizeof (EFI_TE_IMAGE_HEADER
) - Hdr
.Te
->StrippedSize
);
382 return RETURN_SUCCESS
;
383 } else if (Hdr
.Pe32
->Signature
== EFI_IMAGE_NT_SIGNATURE
) {
384 *EntryPoint
= (VOID
*) ((UINTN
) Pe32Data
+ (UINTN
) (Hdr
.Pe32
->OptionalHeader
.AddressOfEntryPoint
& 0x0ffffffff));
385 return RETURN_SUCCESS
;
388 return RETURN_UNSUPPORTED
;
394 @param ContextData Memory profile context.
395 @param FileName File name of the image.
396 @param ImageBase Image base address.
397 @param ImageSize Image size.
398 @param EntryPoint Entry point of the image.
399 @param ImageSubsystem Image subsystem of the image.
400 @param FileType File type of the image.
402 @return Pointer to memory profile driver info.
405 MEMORY_PROFILE_DRIVER_INFO_DATA
*
407 IN MEMORY_PROFILE_CONTEXT_DATA
*ContextData
,
408 IN EFI_GUID
*FileName
,
409 IN PHYSICAL_ADDRESS ImageBase
,
411 IN PHYSICAL_ADDRESS EntryPoint
,
412 IN UINT16 ImageSubsystem
,
413 IN EFI_FV_FILETYPE FileType
417 MEMORY_PROFILE_DRIVER_INFO
*DriverInfo
;
418 MEMORY_PROFILE_DRIVER_INFO_DATA
*DriverInfoData
;
419 VOID
*EntryPointInImage
;
422 UINTN PdbOccupiedSize
;
427 if (ImageBase
!= 0) {
428 PdbString
= PeCoffLoaderGetPdbPointer ((VOID
*) (UINTN
) ImageBase
);
429 if (PdbString
!= NULL
) {
430 PdbSize
= AsciiStrSize (PdbString
);
431 PdbOccupiedSize
= GET_OCCUPIED_SIZE (PdbSize
, sizeof (UINT64
));
436 // Use SmmInternalAllocatePool() that will not update profile for this AllocatePool action.
438 Status
= SmmInternalAllocatePool (
439 EfiRuntimeServicesData
,
440 sizeof (*DriverInfoData
) + sizeof (LIST_ENTRY
) + PdbSize
,
441 (VOID
**) &DriverInfoData
443 if (EFI_ERROR (Status
)) {
447 ZeroMem (DriverInfoData
, sizeof (*DriverInfoData
));
449 DriverInfo
= &DriverInfoData
->DriverInfo
;
450 DriverInfoData
->Signature
= MEMORY_PROFILE_DRIVER_INFO_SIGNATURE
;
451 DriverInfo
->Header
.Signature
= MEMORY_PROFILE_DRIVER_INFO_SIGNATURE
;
452 DriverInfo
->Header
.Length
= (UINT16
) (sizeof (MEMORY_PROFILE_DRIVER_INFO
) + PdbOccupiedSize
);
453 DriverInfo
->Header
.Revision
= MEMORY_PROFILE_DRIVER_INFO_REVISION
;
454 if (FileName
!= NULL
) {
455 CopyMem (&DriverInfo
->FileName
, FileName
, sizeof (EFI_GUID
));
457 DriverInfo
->ImageBase
= ImageBase
;
458 DriverInfo
->ImageSize
= ImageSize
;
459 DriverInfo
->EntryPoint
= EntryPoint
;
460 DriverInfo
->ImageSubsystem
= ImageSubsystem
;
461 if ((EntryPoint
!= 0) && ((EntryPoint
< ImageBase
) || (EntryPoint
>= (ImageBase
+ ImageSize
)))) {
463 // If the EntryPoint is not in the range of image buffer, it should come from emulation environment.
464 // So patch ImageBuffer here to align the EntryPoint.
466 Status
= InternalPeCoffGetEntryPoint ((VOID
*) (UINTN
) ImageBase
, &EntryPointInImage
);
467 ASSERT_EFI_ERROR (Status
);
468 DriverInfo
->ImageBase
= ImageBase
+ EntryPoint
- (PHYSICAL_ADDRESS
) (UINTN
) EntryPointInImage
;
470 DriverInfo
->FileType
= FileType
;
471 DriverInfoData
->AllocInfoList
= (LIST_ENTRY
*) (DriverInfoData
+ 1);
472 InitializeListHead (DriverInfoData
->AllocInfoList
);
473 DriverInfo
->CurrentUsage
= 0;
474 DriverInfo
->PeakUsage
= 0;
475 DriverInfo
->AllocRecordCount
= 0;
477 DriverInfo
->PdbStringOffset
= (UINT16
) sizeof (MEMORY_PROFILE_DRIVER_INFO
);
478 DriverInfoData
->PdbString
= (CHAR8
*) (DriverInfoData
->AllocInfoList
+ 1);
479 CopyMem (DriverInfoData
->PdbString
, PdbString
, PdbSize
);
481 DriverInfo
->PdbStringOffset
= 0;
482 DriverInfoData
->PdbString
= NULL
;
485 InsertTailList (ContextData
->DriverInfoList
, &DriverInfoData
->Link
);
486 ContextData
->Context
.ImageCount
++;
487 ContextData
->Context
.TotalImageSize
+= DriverInfo
->ImageSize
;
489 return DriverInfoData
;
493 Register image to DXE.
495 @param FileName File name of the image.
496 @param ImageBase Image base address.
497 @param ImageSize Image size.
498 @param FileType File type of the image.
503 IN EFI_GUID
*FileName
,
504 IN PHYSICAL_ADDRESS ImageBase
,
506 IN EFI_FV_FILETYPE FileType
510 EDKII_MEMORY_PROFILE_PROTOCOL
*ProfileProtocol
;
511 MEDIA_FW_VOL_FILEPATH_DEVICE_PATH
*FilePath
;
512 UINT8 TempBuffer
[sizeof (MEDIA_FW_VOL_FILEPATH_DEVICE_PATH
) + sizeof (EFI_DEVICE_PATH_PROTOCOL
)];
514 if (IS_UEFI_MEMORY_PROFILE_ENABLED
) {
516 FilePath
= (MEDIA_FW_VOL_FILEPATH_DEVICE_PATH
*)TempBuffer
;
517 Status
= gBS
->LocateProtocol (&gEdkiiMemoryProfileGuid
, NULL
, (VOID
**) &ProfileProtocol
);
518 if (!EFI_ERROR (Status
)) {
519 EfiInitializeFwVolDevicepathNode (FilePath
, FileName
);
520 SetDevicePathEndNode (FilePath
+ 1);
522 Status
= ProfileProtocol
->RegisterImage (
524 (EFI_DEVICE_PATH_PROTOCOL
*) FilePath
,
534 Unregister image from DXE.
536 @param FileName File name of the image.
537 @param ImageBase Image base address.
538 @param ImageSize Image size.
542 UnregisterImageFromDxe (
543 IN EFI_GUID
*FileName
,
544 IN PHYSICAL_ADDRESS ImageBase
,
549 EDKII_MEMORY_PROFILE_PROTOCOL
*ProfileProtocol
;
550 MEDIA_FW_VOL_FILEPATH_DEVICE_PATH
*FilePath
;
551 UINT8 TempBuffer
[sizeof (MEDIA_FW_VOL_FILEPATH_DEVICE_PATH
) + sizeof (EFI_DEVICE_PATH_PROTOCOL
)];
553 if (IS_UEFI_MEMORY_PROFILE_ENABLED
) {
555 FilePath
= (MEDIA_FW_VOL_FILEPATH_DEVICE_PATH
*)TempBuffer
;
556 Status
= gBS
->LocateProtocol (&gEdkiiMemoryProfileGuid
, NULL
, (VOID
*) &ProfileProtocol
);
557 if (!EFI_ERROR (Status
)) {
558 EfiInitializeFwVolDevicepathNode (FilePath
, FileName
);
559 SetDevicePathEndNode (FilePath
+ 1);
561 Status
= ProfileProtocol
->UnregisterImage (
563 (EFI_DEVICE_PATH_PROTOCOL
*) FilePath
,
572 Return if record for this driver is needed..
574 @param DriverFilePath Driver file path.
576 @retval TRUE Record for this driver is needed.
577 @retval FALSE Record for this driver is not needed.
581 NeedRecordThisDriver (
582 IN EFI_DEVICE_PATH_PROTOCOL
*DriverFilePath
585 EFI_DEVICE_PATH_PROTOCOL
*TmpDevicePath
;
586 EFI_DEVICE_PATH_PROTOCOL
*DevicePathInstance
;
587 UINTN DevicePathSize
;
590 if (!IsDevicePathValid (mSmramProfileDriverPath
, mSmramProfileDriverPathSize
)) {
592 // Invalid Device Path means record all.
598 // Record FilePath without end node.
600 FilePathSize
= GetDevicePathSize (DriverFilePath
) - sizeof(EFI_DEVICE_PATH_PROTOCOL
);
602 DevicePathInstance
= mSmramProfileDriverPath
;
605 // Find End node (it might be END_ENTIRE or END_INSTANCE)
607 TmpDevicePath
= DevicePathInstance
;
608 while (!IsDevicePathEndType (TmpDevicePath
)) {
609 TmpDevicePath
= NextDevicePathNode (TmpDevicePath
);
613 // Do not compare END node
615 DevicePathSize
= (UINTN
)TmpDevicePath
- (UINTN
)DevicePathInstance
;
616 if ((FilePathSize
== DevicePathSize
) &&
617 (CompareMem (DriverFilePath
, DevicePathInstance
, DevicePathSize
) == 0)) {
624 DevicePathInstance
= (EFI_DEVICE_PATH_PROTOCOL
*)((UINTN
)DevicePathInstance
+ DevicePathSize
+ DevicePathNodeLength(TmpDevicePath
));
625 } while (DevicePathSubType (TmpDevicePath
) != END_ENTIRE_DEVICE_PATH_SUBTYPE
);
631 Register SMM Core to SMRAM profile.
633 @param ContextData SMRAM profile context.
635 @retval TRUE Register success.
636 @retval FALSE Register fail.
641 IN MEMORY_PROFILE_CONTEXT_DATA
*ContextData
644 MEMORY_PROFILE_DRIVER_INFO_DATA
*DriverInfoData
;
645 PHYSICAL_ADDRESS ImageBase
;
646 UINT8 TempBuffer
[sizeof(MEDIA_FW_VOL_FILEPATH_DEVICE_PATH
) + sizeof(EFI_DEVICE_PATH_PROTOCOL
)];
647 MEDIA_FW_VOL_FILEPATH_DEVICE_PATH
*FilePath
;
649 FilePath
= (MEDIA_FW_VOL_FILEPATH_DEVICE_PATH
*) TempBuffer
;
650 EfiInitializeFwVolDevicepathNode (FilePath
, &gEfiCallerIdGuid
);
651 SetDevicePathEndNode (FilePath
+ 1);
653 if (!NeedRecordThisDriver ((EFI_DEVICE_PATH_PROTOCOL
*) FilePath
)) {
657 ImageBase
= gSmmCorePrivate
->PiSmmCoreImageBase
;
658 DriverInfoData
= BuildDriverInfo (
662 gSmmCorePrivate
->PiSmmCoreImageSize
,
663 gSmmCorePrivate
->PiSmmCoreEntryPoint
,
664 InternalPeCoffGetSubsystem ((VOID
*) (UINTN
) ImageBase
),
665 EFI_FV_FILETYPE_SMM_CORE
667 if (DriverInfoData
== NULL
) {
675 Initialize SMRAM profile.
683 MEMORY_PROFILE_CONTEXT_DATA
*SmramProfileContext
;
687 gSmmCorePrivate
->PiSmmCoreImageBase
,
688 gSmmCorePrivate
->PiSmmCoreImageSize
,
689 EFI_FV_FILETYPE_SMM_CORE
692 if (!IS_SMRAM_PROFILE_ENABLED
) {
696 SmramProfileContext
= GetSmramProfileContext ();
697 if (SmramProfileContext
!= NULL
) {
701 mSmramProfileGettingStatus
= FALSE
;
702 if ((PcdGet8 (PcdMemoryProfilePropertyMask
) & BIT7
) != 0) {
703 mSmramProfileRecordingEnable
= MEMORY_PROFILE_RECORDING_DISABLE
;
705 mSmramProfileRecordingEnable
= MEMORY_PROFILE_RECORDING_ENABLE
;
707 mSmramProfileDriverPathSize
= PcdGetSize (PcdMemoryProfileDriverPath
);
708 mSmramProfileDriverPath
= AllocateCopyPool (mSmramProfileDriverPathSize
, PcdGetPtr (PcdMemoryProfileDriverPath
));
709 mSmramProfileContextPtr
= &mSmramProfileContext
;
711 RegisterSmmCore (&mSmramProfileContext
);
713 DEBUG ((EFI_D_INFO
, "SmramProfileInit SmramProfileContext - 0x%x\n", &mSmramProfileContext
));
717 Install SMRAM profile protocol.
721 SmramProfileInstallProtocol (
728 if (!IS_SMRAM_PROFILE_ENABLED
) {
733 Status
= SmmInstallProtocolInterface (
735 &gEdkiiSmmMemoryProfileGuid
,
736 EFI_NATIVE_INTERFACE
,
739 ASSERT_EFI_ERROR (Status
);
743 Get the GUID file name from the file path.
745 @param FilePath File path.
747 @return The GUID file name from the file path.
751 GetFileNameFromFilePath (
752 IN EFI_DEVICE_PATH_PROTOCOL
*FilePath
755 MEDIA_FW_VOL_FILEPATH_DEVICE_PATH
*ThisFilePath
;
759 if (FilePath
!= NULL
) {
760 ThisFilePath
= (MEDIA_FW_VOL_FILEPATH_DEVICE_PATH
*) FilePath
;
761 while (!IsDevicePathEnd (ThisFilePath
)) {
762 FileName
= EfiGetNameGuidFromFwVolDevicePathNode (ThisFilePath
);
763 if (FileName
!= NULL
) {
766 ThisFilePath
= (MEDIA_FW_VOL_FILEPATH_DEVICE_PATH
*) NextDevicePathNode (ThisFilePath
);
774 Register SMM image to SMRAM profile.
776 @param DriverEntry SMM image info.
777 @param RegisterToDxe Register image to DXE.
779 @return EFI_SUCCESS Register successfully.
780 @return EFI_UNSUPPORTED Memory profile is unsupported,
781 or memory profile for the image is not required.
782 @return EFI_OUT_OF_RESOURCES No enough resource for this register.
786 RegisterSmramProfileImage (
787 IN EFI_SMM_DRIVER_ENTRY
*DriverEntry
,
788 IN BOOLEAN RegisterToDxe
791 MEMORY_PROFILE_CONTEXT_DATA
*ContextData
;
792 MEMORY_PROFILE_DRIVER_INFO_DATA
*DriverInfoData
;
793 UINT8 TempBuffer
[sizeof(MEDIA_FW_VOL_FILEPATH_DEVICE_PATH
) + sizeof(EFI_DEVICE_PATH_PROTOCOL
)];
794 MEDIA_FW_VOL_FILEPATH_DEVICE_PATH
*FilePath
;
798 &DriverEntry
->FileName
,
799 DriverEntry
->ImageBuffer
,
800 EFI_PAGES_TO_SIZE (DriverEntry
->NumberOfPage
),
805 if (!IS_SMRAM_PROFILE_ENABLED
) {
806 return EFI_UNSUPPORTED
;
809 FilePath
= (MEDIA_FW_VOL_FILEPATH_DEVICE_PATH
*) TempBuffer
;
810 EfiInitializeFwVolDevicepathNode (FilePath
, &DriverEntry
->FileName
);
811 SetDevicePathEndNode (FilePath
+ 1);
813 if (!NeedRecordThisDriver ((EFI_DEVICE_PATH_PROTOCOL
*) FilePath
)) {
814 return EFI_UNSUPPORTED
;
817 ContextData
= GetSmramProfileContext ();
818 if (ContextData
== NULL
) {
819 return EFI_UNSUPPORTED
;
822 DriverInfoData
= BuildDriverInfo (
824 &DriverEntry
->FileName
,
825 DriverEntry
->ImageBuffer
,
826 EFI_PAGES_TO_SIZE (DriverEntry
->NumberOfPage
),
827 DriverEntry
->ImageEntryPoint
,
828 InternalPeCoffGetSubsystem ((VOID
*) (UINTN
) DriverEntry
->ImageBuffer
),
831 if (DriverInfoData
== NULL
) {
832 return EFI_OUT_OF_RESOURCES
;
839 Search image from memory profile.
841 @param ContextData Memory profile context.
842 @param FileName Image file name.
843 @param Address Image Address.
845 @return Pointer to memory profile driver info.
848 MEMORY_PROFILE_DRIVER_INFO_DATA
*
849 GetMemoryProfileDriverInfoByFileNameAndAddress (
850 IN MEMORY_PROFILE_CONTEXT_DATA
*ContextData
,
851 IN EFI_GUID
*FileName
,
852 IN PHYSICAL_ADDRESS Address
855 MEMORY_PROFILE_DRIVER_INFO
*DriverInfo
;
856 MEMORY_PROFILE_DRIVER_INFO_DATA
*DriverInfoData
;
857 LIST_ENTRY
*DriverLink
;
858 LIST_ENTRY
*DriverInfoList
;
860 DriverInfoList
= ContextData
->DriverInfoList
;
862 for (DriverLink
= DriverInfoList
->ForwardLink
;
863 DriverLink
!= DriverInfoList
;
864 DriverLink
= DriverLink
->ForwardLink
) {
865 DriverInfoData
= CR (
867 MEMORY_PROFILE_DRIVER_INFO_DATA
,
869 MEMORY_PROFILE_DRIVER_INFO_SIGNATURE
871 DriverInfo
= &DriverInfoData
->DriverInfo
;
872 if ((CompareGuid (&DriverInfo
->FileName
, FileName
)) &&
873 (Address
>= DriverInfo
->ImageBase
) &&
874 (Address
< (DriverInfo
->ImageBase
+ DriverInfo
->ImageSize
))) {
875 return DriverInfoData
;
883 Search image from memory profile.
884 It will return image, if (Address >= ImageBuffer) AND (Address < ImageBuffer + ImageSize)
886 @param ContextData Memory profile context.
887 @param Address Image or Function address.
889 @return Pointer to memory profile driver info.
892 MEMORY_PROFILE_DRIVER_INFO_DATA
*
893 GetMemoryProfileDriverInfoFromAddress (
894 IN MEMORY_PROFILE_CONTEXT_DATA
*ContextData
,
895 IN PHYSICAL_ADDRESS Address
898 MEMORY_PROFILE_DRIVER_INFO
*DriverInfo
;
899 MEMORY_PROFILE_DRIVER_INFO_DATA
*DriverInfoData
;
900 LIST_ENTRY
*DriverLink
;
901 LIST_ENTRY
*DriverInfoList
;
903 DriverInfoList
= ContextData
->DriverInfoList
;
905 for (DriverLink
= DriverInfoList
->ForwardLink
;
906 DriverLink
!= DriverInfoList
;
907 DriverLink
= DriverLink
->ForwardLink
) {
908 DriverInfoData
= CR (
910 MEMORY_PROFILE_DRIVER_INFO_DATA
,
912 MEMORY_PROFILE_DRIVER_INFO_SIGNATURE
914 DriverInfo
= &DriverInfoData
->DriverInfo
;
915 if ((Address
>= DriverInfo
->ImageBase
) &&
916 (Address
< (DriverInfo
->ImageBase
+ DriverInfo
->ImageSize
))) {
917 return DriverInfoData
;
925 Unregister image from SMRAM profile.
927 @param DriverEntry SMM image info.
928 @param UnregisterFromDxe Unregister image from DXE.
930 @return EFI_SUCCESS Unregister successfully.
931 @return EFI_UNSUPPORTED Memory profile is unsupported,
932 or memory profile for the image is not required.
933 @return EFI_NOT_FOUND The image is not found.
937 UnregisterSmramProfileImage (
938 IN EFI_SMM_DRIVER_ENTRY
*DriverEntry
,
939 IN BOOLEAN UnregisterFromDxe
943 MEMORY_PROFILE_CONTEXT_DATA
*ContextData
;
944 MEMORY_PROFILE_DRIVER_INFO_DATA
*DriverInfoData
;
946 PHYSICAL_ADDRESS ImageAddress
;
947 VOID
*EntryPointInImage
;
948 UINT8 TempBuffer
[sizeof(MEDIA_FW_VOL_FILEPATH_DEVICE_PATH
) + sizeof(EFI_DEVICE_PATH_PROTOCOL
)];
949 MEDIA_FW_VOL_FILEPATH_DEVICE_PATH
*FilePath
;
951 if (UnregisterFromDxe
) {
952 UnregisterImageFromDxe (
953 &DriverEntry
->FileName
,
954 DriverEntry
->ImageBuffer
,
955 EFI_PAGES_TO_SIZE (DriverEntry
->NumberOfPage
)
959 if (!IS_SMRAM_PROFILE_ENABLED
) {
960 return EFI_UNSUPPORTED
;
963 FilePath
= (MEDIA_FW_VOL_FILEPATH_DEVICE_PATH
*) TempBuffer
;
964 EfiInitializeFwVolDevicepathNode (FilePath
, &DriverEntry
->FileName
);
965 SetDevicePathEndNode (FilePath
+ 1);
967 if (!NeedRecordThisDriver ((EFI_DEVICE_PATH_PROTOCOL
*) FilePath
)) {
968 return EFI_UNSUPPORTED
;
971 ContextData
= GetSmramProfileContext ();
972 if (ContextData
== NULL
) {
973 return EFI_UNSUPPORTED
;
976 DriverInfoData
= NULL
;
977 FileName
= &DriverEntry
->FileName
;
978 ImageAddress
= DriverEntry
->ImageBuffer
;
979 if ((DriverEntry
->ImageEntryPoint
< ImageAddress
) || (DriverEntry
->ImageEntryPoint
>= (ImageAddress
+ EFI_PAGES_TO_SIZE (DriverEntry
->NumberOfPage
)))) {
981 // If the EntryPoint is not in the range of image buffer, it should come from emulation environment.
982 // So patch ImageAddress here to align the EntryPoint.
984 Status
= InternalPeCoffGetEntryPoint ((VOID
*) (UINTN
) ImageAddress
, &EntryPointInImage
);
985 ASSERT_EFI_ERROR (Status
);
986 ImageAddress
= ImageAddress
+ (UINTN
) DriverEntry
->ImageEntryPoint
- (UINTN
) EntryPointInImage
;
988 if (FileName
!= NULL
) {
989 DriverInfoData
= GetMemoryProfileDriverInfoByFileNameAndAddress (ContextData
, FileName
, ImageAddress
);
991 if (DriverInfoData
== NULL
) {
992 DriverInfoData
= GetMemoryProfileDriverInfoFromAddress (ContextData
, ImageAddress
);
994 if (DriverInfoData
== NULL
) {
995 return EFI_NOT_FOUND
;
998 ContextData
->Context
.TotalImageSize
-= DriverInfoData
->DriverInfo
.ImageSize
;
1000 // Keep the ImageBase for RVA calculation in Application.
1001 //DriverInfoData->DriverInfo.ImageBase = 0;
1002 DriverInfoData
->DriverInfo
.ImageSize
= 0;
1004 if (DriverInfoData
->DriverInfo
.PeakUsage
== 0) {
1005 ContextData
->Context
.ImageCount
--;
1006 RemoveEntryList (&DriverInfoData
->Link
);
1008 // Use SmmInternalFreePool() that will not update profile for this FreePool action.
1010 SmmInternalFreePool (DriverInfoData
);
1017 Return if this memory type needs to be recorded into memory profile.
1018 Only need to record EfiRuntimeServicesCode and EfiRuntimeServicesData for SMRAM profile.
1020 @param MemoryType Memory type.
1022 @retval TRUE This memory type need to be recorded.
1023 @retval FALSE This memory type need not to be recorded.
1027 SmmCoreNeedRecordProfile (
1028 IN EFI_MEMORY_TYPE MemoryType
1033 if (MemoryType
!= EfiRuntimeServicesCode
&&
1034 MemoryType
!= EfiRuntimeServicesData
) {
1038 TestBit
= LShiftU64 (1, MemoryType
);
1040 if ((PcdGet64 (PcdMemoryProfileMemoryType
) & TestBit
) != 0) {
1048 Convert EFI memory type to profile memory index. The rule is:
1049 If BIOS memory type (0 ~ EfiMaxMemoryType - 1), ProfileMemoryIndex = MemoryType.
1050 As SMRAM profile is only to record EfiRuntimeServicesCode and EfiRuntimeServicesData,
1051 so return input memory type directly.
1053 @param MemoryType Memory type.
1055 @return EFI memory type as profile memory index.
1059 GetProfileMemoryIndex (
1060 IN EFI_MEMORY_TYPE MemoryType
1067 Update SMRAM profile FreeMemoryPages information
1069 @param ContextData Memory profile context.
1073 SmramProfileUpdateFreePages (
1074 IN MEMORY_PROFILE_CONTEXT_DATA
*ContextData
1078 FREE_PAGE_LIST
*Pages
;
1079 LIST_ENTRY
*FreePageList
;
1080 UINTN NumberOfPages
;
1083 FreePageList
= &mSmmMemoryMap
;
1084 for (Node
= FreePageList
->BackLink
;
1085 Node
!= FreePageList
;
1086 Node
= Node
->BackLink
) {
1087 Pages
= BASE_CR (Node
, FREE_PAGE_LIST
, Link
);
1088 NumberOfPages
+= Pages
->NumberOfPages
;
1091 mSmramFreeMemory
.TotalFreeMemoryPages
= NumberOfPages
;
1093 if (NumberOfPages
<= SMRAM_INFO_DUMP_PAGE_THRESHOLD
) {
1099 Update SMRAM profile Allocate information.
1101 @param CallerAddress Address of caller who call Allocate.
1102 @param Action This Allocate action.
1103 @param MemoryType Memory type.
1104 @param Size Buffer size.
1105 @param Buffer Buffer address.
1106 @param ActionString String for memory profile action.
1108 @return EFI_SUCCESS Memory profile is updated.
1109 @return EFI_UNSUPPORTED Memory profile is unsupported,
1110 or memory profile for the image is not required.
1111 @return EFI_OUT_OF_RESOURCES No enough resource to update memory profile for allocate action.
1115 SmmCoreUpdateProfileAllocate (
1116 IN PHYSICAL_ADDRESS CallerAddress
,
1117 IN MEMORY_PROFILE_ACTION Action
,
1118 IN EFI_MEMORY_TYPE MemoryType
,
1121 IN CHAR8
*ActionString OPTIONAL
1125 MEMORY_PROFILE_CONTEXT
*Context
;
1126 MEMORY_PROFILE_DRIVER_INFO
*DriverInfo
;
1127 MEMORY_PROFILE_ALLOC_INFO
*AllocInfo
;
1128 MEMORY_PROFILE_CONTEXT_DATA
*ContextData
;
1129 MEMORY_PROFILE_DRIVER_INFO_DATA
*DriverInfoData
;
1130 MEMORY_PROFILE_ALLOC_INFO_DATA
*AllocInfoData
;
1131 EFI_MEMORY_TYPE ProfileMemoryIndex
;
1132 MEMORY_PROFILE_ACTION BasicAction
;
1133 UINTN ActionStringSize
;
1134 UINTN ActionStringOccupiedSize
;
1136 BasicAction
= Action
& MEMORY_PROFILE_ACTION_BASIC_MASK
;
1138 ContextData
= GetSmramProfileContext ();
1139 if (ContextData
== NULL
) {
1140 return EFI_UNSUPPORTED
;
1143 DriverInfoData
= GetMemoryProfileDriverInfoFromAddress (ContextData
, CallerAddress
);
1144 if (DriverInfoData
== NULL
) {
1145 return EFI_UNSUPPORTED
;
1148 ActionStringSize
= 0;
1149 ActionStringOccupiedSize
= 0;
1150 if (ActionString
!= NULL
) {
1151 ActionStringSize
= AsciiStrSize (ActionString
);
1152 ActionStringOccupiedSize
= GET_OCCUPIED_SIZE (ActionStringSize
, sizeof (UINT64
));
1156 // Use SmmInternalAllocatePool() that will not update profile for this AllocatePool action.
1158 AllocInfoData
= NULL
;
1159 Status
= SmmInternalAllocatePool (
1160 EfiRuntimeServicesData
,
1161 sizeof (*AllocInfoData
) + ActionStringSize
,
1162 (VOID
**) &AllocInfoData
1164 if (EFI_ERROR (Status
)) {
1165 return EFI_OUT_OF_RESOURCES
;
1167 ASSERT (AllocInfoData
!= NULL
);
1170 // Only update SequenceCount if and only if it is basic action.
1172 if (Action
== BasicAction
) {
1173 ContextData
->Context
.SequenceCount
++;
1176 AllocInfo
= &AllocInfoData
->AllocInfo
;
1177 AllocInfoData
->Signature
= MEMORY_PROFILE_ALLOC_INFO_SIGNATURE
;
1178 AllocInfo
->Header
.Signature
= MEMORY_PROFILE_ALLOC_INFO_SIGNATURE
;
1179 AllocInfo
->Header
.Length
= (UINT16
) (sizeof (MEMORY_PROFILE_ALLOC_INFO
) + ActionStringOccupiedSize
);
1180 AllocInfo
->Header
.Revision
= MEMORY_PROFILE_ALLOC_INFO_REVISION
;
1181 AllocInfo
->CallerAddress
= CallerAddress
;
1182 AllocInfo
->SequenceId
= ContextData
->Context
.SequenceCount
;
1183 AllocInfo
->Action
= Action
;
1184 AllocInfo
->MemoryType
= MemoryType
;
1185 AllocInfo
->Buffer
= (PHYSICAL_ADDRESS
) (UINTN
) Buffer
;
1186 AllocInfo
->Size
= Size
;
1187 if (ActionString
!= NULL
) {
1188 AllocInfo
->ActionStringOffset
= (UINT16
) sizeof (MEMORY_PROFILE_ALLOC_INFO
);
1189 AllocInfoData
->ActionString
= (CHAR8
*) (AllocInfoData
+ 1);
1190 CopyMem (AllocInfoData
->ActionString
, ActionString
, ActionStringSize
);
1192 AllocInfo
->ActionStringOffset
= 0;
1193 AllocInfoData
->ActionString
= NULL
;
1196 InsertTailList (DriverInfoData
->AllocInfoList
, &AllocInfoData
->Link
);
1198 Context
= &ContextData
->Context
;
1199 DriverInfo
= &DriverInfoData
->DriverInfo
;
1200 DriverInfo
->AllocRecordCount
++;
1203 // Update summary if and only if it is basic action.
1205 if (Action
== BasicAction
) {
1206 ProfileMemoryIndex
= GetProfileMemoryIndex (MemoryType
);
1208 DriverInfo
->CurrentUsage
+= Size
;
1209 if (DriverInfo
->PeakUsage
< DriverInfo
->CurrentUsage
) {
1210 DriverInfo
->PeakUsage
= DriverInfo
->CurrentUsage
;
1212 DriverInfo
->CurrentUsageByType
[ProfileMemoryIndex
] += Size
;
1213 if (DriverInfo
->PeakUsageByType
[ProfileMemoryIndex
] < DriverInfo
->CurrentUsageByType
[ProfileMemoryIndex
]) {
1214 DriverInfo
->PeakUsageByType
[ProfileMemoryIndex
] = DriverInfo
->CurrentUsageByType
[ProfileMemoryIndex
];
1217 Context
->CurrentTotalUsage
+= Size
;
1218 if (Context
->PeakTotalUsage
< Context
->CurrentTotalUsage
) {
1219 Context
->PeakTotalUsage
= Context
->CurrentTotalUsage
;
1221 Context
->CurrentTotalUsageByType
[ProfileMemoryIndex
] += Size
;
1222 if (Context
->PeakTotalUsageByType
[ProfileMemoryIndex
] < Context
->CurrentTotalUsageByType
[ProfileMemoryIndex
]) {
1223 Context
->PeakTotalUsageByType
[ProfileMemoryIndex
] = Context
->CurrentTotalUsageByType
[ProfileMemoryIndex
];
1226 SmramProfileUpdateFreePages (ContextData
);
1233 Get memory profile alloc info from memory profile
1235 @param DriverInfoData Driver info
1236 @param BasicAction This Free basic action
1237 @param Size Buffer size
1238 @param Buffer Buffer address
1240 @return Pointer to memory profile alloc info.
1242 MEMORY_PROFILE_ALLOC_INFO_DATA
*
1243 GetMemoryProfileAllocInfoFromAddress (
1244 IN MEMORY_PROFILE_DRIVER_INFO_DATA
*DriverInfoData
,
1245 IN MEMORY_PROFILE_ACTION BasicAction
,
1250 LIST_ENTRY
*AllocInfoList
;
1251 LIST_ENTRY
*AllocLink
;
1252 MEMORY_PROFILE_ALLOC_INFO
*AllocInfo
;
1253 MEMORY_PROFILE_ALLOC_INFO_DATA
*AllocInfoData
;
1255 AllocInfoList
= DriverInfoData
->AllocInfoList
;
1257 for (AllocLink
= AllocInfoList
->ForwardLink
;
1258 AllocLink
!= AllocInfoList
;
1259 AllocLink
= AllocLink
->ForwardLink
) {
1260 AllocInfoData
= CR (
1262 MEMORY_PROFILE_ALLOC_INFO_DATA
,
1264 MEMORY_PROFILE_ALLOC_INFO_SIGNATURE
1266 AllocInfo
= &AllocInfoData
->AllocInfo
;
1267 if ((AllocInfo
->Action
& MEMORY_PROFILE_ACTION_BASIC_MASK
) != BasicAction
) {
1270 switch (BasicAction
) {
1271 case MemoryProfileActionAllocatePages
:
1272 if ((AllocInfo
->Buffer
<= (PHYSICAL_ADDRESS
) (UINTN
) Buffer
) &&
1273 ((AllocInfo
->Buffer
+ AllocInfo
->Size
) >= ((PHYSICAL_ADDRESS
) (UINTN
) Buffer
+ Size
))) {
1274 return AllocInfoData
;
1277 case MemoryProfileActionAllocatePool
:
1278 if (AllocInfo
->Buffer
== (PHYSICAL_ADDRESS
) (UINTN
) Buffer
) {
1279 return AllocInfoData
;
1292 Update SMRAM profile Free information.
1294 @param CallerAddress Address of caller who call Free.
1295 @param Action This Free action.
1296 @param Size Buffer size.
1297 @param Buffer Buffer address.
1299 @return EFI_SUCCESS Memory profile is updated.
1300 @return EFI_UNSUPPORTED Memory profile is unsupported.
1301 @return EFI_NOT_FOUND No matched allocate info found for free action.
1305 SmmCoreUpdateProfileFree (
1306 IN PHYSICAL_ADDRESS CallerAddress
,
1307 IN MEMORY_PROFILE_ACTION Action
,
1312 MEMORY_PROFILE_CONTEXT
*Context
;
1313 MEMORY_PROFILE_DRIVER_INFO
*DriverInfo
;
1314 MEMORY_PROFILE_ALLOC_INFO
*AllocInfo
;
1315 MEMORY_PROFILE_CONTEXT_DATA
*ContextData
;
1316 MEMORY_PROFILE_DRIVER_INFO_DATA
*DriverInfoData
;
1317 LIST_ENTRY
*DriverLink
;
1318 LIST_ENTRY
*DriverInfoList
;
1319 MEMORY_PROFILE_DRIVER_INFO_DATA
*ThisDriverInfoData
;
1320 MEMORY_PROFILE_ALLOC_INFO_DATA
*AllocInfoData
;
1321 EFI_MEMORY_TYPE ProfileMemoryIndex
;
1322 MEMORY_PROFILE_ACTION BasicAction
;
1325 BasicAction
= Action
& MEMORY_PROFILE_ACTION_BASIC_MASK
;
1327 ContextData
= GetSmramProfileContext ();
1328 if (ContextData
== NULL
) {
1329 return EFI_UNSUPPORTED
;
1332 DriverInfoData
= GetMemoryProfileDriverInfoFromAddress (ContextData
, CallerAddress
);
1335 // Do not return if DriverInfoData == NULL here,
1336 // because driver A might free memory allocated by driver B.
1340 // Need use do-while loop to find all possible record,
1341 // because one address might be recorded multiple times.
1344 AllocInfoData
= NULL
;
1346 if (DriverInfoData
!= NULL
) {
1347 switch (BasicAction
) {
1348 case MemoryProfileActionFreePages
:
1349 AllocInfoData
= GetMemoryProfileAllocInfoFromAddress (DriverInfoData
, MemoryProfileActionAllocatePages
, Size
, Buffer
);
1351 case MemoryProfileActionFreePool
:
1352 AllocInfoData
= GetMemoryProfileAllocInfoFromAddress (DriverInfoData
, MemoryProfileActionAllocatePool
, 0, Buffer
);
1356 AllocInfoData
= NULL
;
1360 if (AllocInfoData
== NULL
) {
1362 // Legal case, because driver A might free memory allocated by driver B, by some protocol.
1364 DriverInfoList
= ContextData
->DriverInfoList
;
1366 for (DriverLink
= DriverInfoList
->ForwardLink
;
1367 DriverLink
!= DriverInfoList
;
1368 DriverLink
= DriverLink
->ForwardLink
) {
1369 ThisDriverInfoData
= CR (
1371 MEMORY_PROFILE_DRIVER_INFO_DATA
,
1373 MEMORY_PROFILE_DRIVER_INFO_SIGNATURE
1375 switch (BasicAction
) {
1376 case MemoryProfileActionFreePages
:
1377 AllocInfoData
= GetMemoryProfileAllocInfoFromAddress (ThisDriverInfoData
, MemoryProfileActionAllocatePages
, Size
, Buffer
);
1379 case MemoryProfileActionFreePool
:
1380 AllocInfoData
= GetMemoryProfileAllocInfoFromAddress (ThisDriverInfoData
, MemoryProfileActionAllocatePool
, 0, Buffer
);
1384 AllocInfoData
= NULL
;
1387 if (AllocInfoData
!= NULL
) {
1388 DriverInfoData
= ThisDriverInfoData
;
1393 if (AllocInfoData
== NULL
) {
1395 // If (!Found), no matched allocate info is found for this free action.
1396 // It is because the specified memory type allocate actions have been filtered by
1397 // CoreNeedRecordProfile(), but free actions have no memory type information,
1398 // they can not be filtered by CoreNeedRecordProfile(). Then, they will be
1401 // If (Found), it is normal exit path.
1402 return (Found
? EFI_SUCCESS
: EFI_NOT_FOUND
);
1408 Context
= &ContextData
->Context
;
1409 DriverInfo
= &DriverInfoData
->DriverInfo
;
1410 AllocInfo
= &AllocInfoData
->AllocInfo
;
1412 DriverInfo
->AllocRecordCount
--;
1414 // Update summary if and only if it is basic action.
1416 if (AllocInfo
->Action
== (AllocInfo
->Action
& MEMORY_PROFILE_ACTION_BASIC_MASK
)) {
1417 ProfileMemoryIndex
= GetProfileMemoryIndex (AllocInfo
->MemoryType
);
1419 Context
->CurrentTotalUsage
-= AllocInfo
->Size
;
1420 Context
->CurrentTotalUsageByType
[ProfileMemoryIndex
] -= AllocInfo
->Size
;
1422 DriverInfo
->CurrentUsage
-= AllocInfo
->Size
;
1423 DriverInfo
->CurrentUsageByType
[ProfileMemoryIndex
] -= AllocInfo
->Size
;
1426 RemoveEntryList (&AllocInfoData
->Link
);
1428 if (BasicAction
== MemoryProfileActionFreePages
) {
1429 if (AllocInfo
->Buffer
!= (PHYSICAL_ADDRESS
) (UINTN
) Buffer
) {
1430 SmmCoreUpdateProfileAllocate (
1431 AllocInfo
->CallerAddress
,
1433 AllocInfo
->MemoryType
,
1434 (UINTN
) ((PHYSICAL_ADDRESS
) (UINTN
) Buffer
- AllocInfo
->Buffer
),
1435 (VOID
*) (UINTN
) AllocInfo
->Buffer
,
1436 AllocInfoData
->ActionString
1439 if (AllocInfo
->Buffer
+ AllocInfo
->Size
!= ((PHYSICAL_ADDRESS
) (UINTN
) Buffer
+ Size
)) {
1440 SmmCoreUpdateProfileAllocate (
1441 AllocInfo
->CallerAddress
,
1443 AllocInfo
->MemoryType
,
1444 (UINTN
) ((AllocInfo
->Buffer
+ AllocInfo
->Size
) - ((PHYSICAL_ADDRESS
) (UINTN
) Buffer
+ Size
)),
1445 (VOID
*) ((UINTN
) Buffer
+ Size
),
1446 AllocInfoData
->ActionString
1452 // Use SmmInternalFreePool() that will not update profile for this FreePool action.
1454 SmmInternalFreePool (AllocInfoData
);
1459 Update SMRAM profile information.
1461 @param CallerAddress Address of caller who call Allocate or Free.
1462 @param Action This Allocate or Free action.
1463 @param MemoryType Memory type.
1464 EfiMaxMemoryType means the MemoryType is unknown.
1465 @param Size Buffer size.
1466 @param Buffer Buffer address.
1467 @param ActionString String for memory profile action.
1468 Only needed for user defined allocate action.
1470 @return EFI_SUCCESS Memory profile is updated.
1471 @return EFI_UNSUPPORTED Memory profile is unsupported,
1472 or memory profile for the image is not required,
1473 or memory profile for the memory type is not required.
1474 @return EFI_ACCESS_DENIED It is during memory profile data getting.
1475 @return EFI_ABORTED Memory profile recording is not enabled.
1476 @return EFI_OUT_OF_RESOURCES No enough resource to update memory profile for allocate action.
1477 @return EFI_NOT_FOUND No matched allocate info found for free action.
1482 SmmCoreUpdateProfile (
1483 IN PHYSICAL_ADDRESS CallerAddress
,
1484 IN MEMORY_PROFILE_ACTION Action
,
1485 IN EFI_MEMORY_TYPE MemoryType
, // Valid for AllocatePages/AllocatePool
1486 IN UINTN Size
, // Valid for AllocatePages/FreePages/AllocatePool
1488 IN CHAR8
*ActionString OPTIONAL
1492 MEMORY_PROFILE_CONTEXT_DATA
*ContextData
;
1493 MEMORY_PROFILE_ACTION BasicAction
;
1495 if (!IS_SMRAM_PROFILE_ENABLED
) {
1496 return EFI_UNSUPPORTED
;
1499 if (mSmramProfileGettingStatus
) {
1500 return EFI_ACCESS_DENIED
;
1503 if (!mSmramProfileRecordingEnable
) {
1508 // Get the basic action to know how to process the record
1510 BasicAction
= Action
& MEMORY_PROFILE_ACTION_BASIC_MASK
;
1513 // Free operations have no memory type information, so skip the check.
1515 if ((BasicAction
== MemoryProfileActionAllocatePages
) || (BasicAction
== MemoryProfileActionAllocatePool
)) {
1517 // Only record limited MemoryType.
1519 if (!SmmCoreNeedRecordProfile (MemoryType
)) {
1520 return EFI_UNSUPPORTED
;
1524 ContextData
= GetSmramProfileContext ();
1525 if (ContextData
== NULL
) {
1526 return EFI_UNSUPPORTED
;
1529 switch (BasicAction
) {
1530 case MemoryProfileActionAllocatePages
:
1531 Status
= SmmCoreUpdateProfileAllocate (CallerAddress
, Action
, MemoryType
, Size
, Buffer
, ActionString
);
1533 case MemoryProfileActionFreePages
:
1534 Status
= SmmCoreUpdateProfileFree (CallerAddress
, Action
, Size
, Buffer
);
1536 case MemoryProfileActionAllocatePool
:
1537 Status
= SmmCoreUpdateProfileAllocate (CallerAddress
, Action
, MemoryType
, Size
, Buffer
, ActionString
);
1539 case MemoryProfileActionFreePool
:
1540 Status
= SmmCoreUpdateProfileFree (CallerAddress
, Action
, 0, Buffer
);
1544 Status
= EFI_UNSUPPORTED
;
1552 SMRAM profile ready to lock callback function.
1556 SmramProfileReadyToLock (
1560 if (!IS_SMRAM_PROFILE_ENABLED
) {
1564 DEBUG ((EFI_D_INFO
, "SmramProfileReadyToLock\n"));
1565 mSmramReadyToLock
= TRUE
;
1568 ////////////////////
1571 Get SMRAM profile data size.
1573 @return SMRAM profile data size.
1577 SmramProfileGetDataSize (
1581 MEMORY_PROFILE_CONTEXT_DATA
*ContextData
;
1582 MEMORY_PROFILE_DRIVER_INFO_DATA
*DriverInfoData
;
1583 MEMORY_PROFILE_ALLOC_INFO_DATA
*AllocInfoData
;
1584 LIST_ENTRY
*DriverInfoList
;
1585 LIST_ENTRY
*DriverLink
;
1586 LIST_ENTRY
*AllocInfoList
;
1587 LIST_ENTRY
*AllocLink
;
1590 LIST_ENTRY
*FreePageList
;
1591 LIST_ENTRY
*FreePoolList
;
1592 FREE_POOL_HEADER
*Pool
;
1593 UINTN PoolListIndex
;
1596 ContextData
= GetSmramProfileContext ();
1597 if (ContextData
== NULL
) {
1601 TotalSize
= sizeof (MEMORY_PROFILE_CONTEXT
);
1603 DriverInfoList
= ContextData
->DriverInfoList
;
1604 for (DriverLink
= DriverInfoList
->ForwardLink
;
1605 DriverLink
!= DriverInfoList
;
1606 DriverLink
= DriverLink
->ForwardLink
) {
1607 DriverInfoData
= CR (
1609 MEMORY_PROFILE_DRIVER_INFO_DATA
,
1611 MEMORY_PROFILE_DRIVER_INFO_SIGNATURE
1613 TotalSize
+= DriverInfoData
->DriverInfo
.Header
.Length
;
1615 AllocInfoList
= DriverInfoData
->AllocInfoList
;
1616 for (AllocLink
= AllocInfoList
->ForwardLink
;
1617 AllocLink
!= AllocInfoList
;
1618 AllocLink
= AllocLink
->ForwardLink
) {
1619 AllocInfoData
= CR (
1621 MEMORY_PROFILE_ALLOC_INFO_DATA
,
1623 MEMORY_PROFILE_ALLOC_INFO_SIGNATURE
1625 TotalSize
+= AllocInfoData
->AllocInfo
.Header
.Length
;
1631 FreePageList
= &mSmmMemoryMap
;
1632 for (Node
= FreePageList
->BackLink
;
1633 Node
!= FreePageList
;
1634 Node
= Node
->BackLink
) {
1637 for (PoolListIndex
= 0; PoolListIndex
< MAX_POOL_INDEX
; PoolListIndex
++) {
1638 FreePoolList
= &mSmmPoolLists
[PoolListIndex
];
1639 for (Node
= FreePoolList
->BackLink
;
1640 Node
!= FreePoolList
;
1641 Node
= Node
->BackLink
) {
1642 Pool
= BASE_CR (Node
, FREE_POOL_HEADER
, Link
);
1643 if (Pool
->Header
.Available
) {
1650 TotalSize
+= (sizeof (MEMORY_PROFILE_FREE_MEMORY
) + Index
* sizeof (MEMORY_PROFILE_DESCRIPTOR
));
1651 TotalSize
+= (sizeof (MEMORY_PROFILE_MEMORY_RANGE
) + mFullSmramRangeCount
* sizeof (MEMORY_PROFILE_DESCRIPTOR
));
1657 Copy SMRAM profile data.
1659 @param ProfileBuffer The buffer to hold SMRAM profile data.
1660 @param ProfileSize On input, profile buffer size.
1661 On output, actual profile data size copied.
1662 @param ProfileOffset On input, profile buffer offset to copy.
1663 On output, next time profile buffer offset to copy.
1667 SmramProfileCopyData (
1668 OUT VOID
*ProfileBuffer
,
1669 IN OUT UINT64
*ProfileSize
,
1670 IN OUT UINT64
*ProfileOffset
1673 MEMORY_PROFILE_CONTEXT
*Context
;
1674 MEMORY_PROFILE_DRIVER_INFO
*DriverInfo
;
1675 MEMORY_PROFILE_ALLOC_INFO
*AllocInfo
;
1676 MEMORY_PROFILE_CONTEXT_DATA
*ContextData
;
1677 MEMORY_PROFILE_DRIVER_INFO_DATA
*DriverInfoData
;
1678 MEMORY_PROFILE_ALLOC_INFO_DATA
*AllocInfoData
;
1679 LIST_ENTRY
*DriverInfoList
;
1680 LIST_ENTRY
*DriverLink
;
1681 LIST_ENTRY
*AllocInfoList
;
1682 LIST_ENTRY
*AllocLink
;
1684 FREE_PAGE_LIST
*Pages
;
1685 LIST_ENTRY
*FreePageList
;
1686 LIST_ENTRY
*FreePoolList
;
1687 FREE_POOL_HEADER
*Pool
;
1688 UINTN PoolListIndex
;
1690 MEMORY_PROFILE_FREE_MEMORY
*FreeMemory
;
1691 MEMORY_PROFILE_MEMORY_RANGE
*MemoryRange
;
1692 MEMORY_PROFILE_DESCRIPTOR
*MemoryProfileDescriptor
;
1694 UINT64 RemainingSize
;
1696 UINTN ActionStringSize
;
1698 ContextData
= GetSmramProfileContext ();
1699 if (ContextData
== NULL
) {
1703 RemainingSize
= *ProfileSize
;
1706 if (*ProfileOffset
< sizeof (MEMORY_PROFILE_CONTEXT
)) {
1707 if (RemainingSize
>= sizeof (MEMORY_PROFILE_CONTEXT
)) {
1708 Context
= ProfileBuffer
;
1709 CopyMem (Context
, &ContextData
->Context
, sizeof (MEMORY_PROFILE_CONTEXT
));
1710 RemainingSize
-= sizeof (MEMORY_PROFILE_CONTEXT
);
1711 ProfileBuffer
= (UINT8
*) ProfileBuffer
+ sizeof (MEMORY_PROFILE_CONTEXT
);
1716 Offset
+= sizeof (MEMORY_PROFILE_CONTEXT
);
1718 DriverInfoList
= ContextData
->DriverInfoList
;
1719 for (DriverLink
= DriverInfoList
->ForwardLink
;
1720 DriverLink
!= DriverInfoList
;
1721 DriverLink
= DriverLink
->ForwardLink
) {
1722 DriverInfoData
= CR (
1724 MEMORY_PROFILE_DRIVER_INFO_DATA
,
1726 MEMORY_PROFILE_DRIVER_INFO_SIGNATURE
1728 if (*ProfileOffset
< (Offset
+ DriverInfoData
->DriverInfo
.Header
.Length
)) {
1729 if (RemainingSize
>= DriverInfoData
->DriverInfo
.Header
.Length
) {
1730 DriverInfo
= ProfileBuffer
;
1731 CopyMem (DriverInfo
, &DriverInfoData
->DriverInfo
, sizeof (MEMORY_PROFILE_DRIVER_INFO
));
1732 if (DriverInfo
->PdbStringOffset
!= 0) {
1733 PdbSize
= AsciiStrSize (DriverInfoData
->PdbString
);
1734 CopyMem ((VOID
*) ((UINTN
) DriverInfo
+ DriverInfo
->PdbStringOffset
), DriverInfoData
->PdbString
, PdbSize
);
1736 RemainingSize
-= DriverInfo
->Header
.Length
;
1737 ProfileBuffer
= (UINT8
*) ProfileBuffer
+ DriverInfo
->Header
.Length
;
1742 Offset
+= DriverInfoData
->DriverInfo
.Header
.Length
;
1744 AllocInfoList
= DriverInfoData
->AllocInfoList
;
1745 for (AllocLink
= AllocInfoList
->ForwardLink
;
1746 AllocLink
!= AllocInfoList
;
1747 AllocLink
= AllocLink
->ForwardLink
) {
1748 AllocInfoData
= CR (
1750 MEMORY_PROFILE_ALLOC_INFO_DATA
,
1752 MEMORY_PROFILE_ALLOC_INFO_SIGNATURE
1754 if (*ProfileOffset
< (Offset
+ AllocInfoData
->AllocInfo
.Header
.Length
)) {
1755 if (RemainingSize
>= AllocInfoData
->AllocInfo
.Header
.Length
) {
1756 AllocInfo
= ProfileBuffer
;
1757 CopyMem (AllocInfo
, &AllocInfoData
->AllocInfo
, sizeof (MEMORY_PROFILE_ALLOC_INFO
));
1758 if (AllocInfo
->ActionStringOffset
) {
1759 ActionStringSize
= AsciiStrSize (AllocInfoData
->ActionString
);
1760 CopyMem ((VOID
*) ((UINTN
) AllocInfo
+ AllocInfo
->ActionStringOffset
), AllocInfoData
->ActionString
, ActionStringSize
);
1762 RemainingSize
-= AllocInfo
->Header
.Length
;
1763 ProfileBuffer
= (UINT8
*) ProfileBuffer
+ AllocInfo
->Header
.Length
;
1768 Offset
+= AllocInfoData
->AllocInfo
.Header
.Length
;
1773 if (*ProfileOffset
< (Offset
+ sizeof (MEMORY_PROFILE_FREE_MEMORY
))) {
1774 if (RemainingSize
>= sizeof (MEMORY_PROFILE_FREE_MEMORY
)) {
1775 FreeMemory
= ProfileBuffer
;
1776 CopyMem (FreeMemory
, &mSmramFreeMemory
, sizeof (MEMORY_PROFILE_FREE_MEMORY
));
1778 FreePageList
= &mSmmMemoryMap
;
1779 for (Node
= FreePageList
->BackLink
;
1780 Node
!= FreePageList
;
1781 Node
= Node
->BackLink
) {
1784 for (PoolListIndex
= 0; PoolListIndex
< MAX_POOL_INDEX
; PoolListIndex
++) {
1785 FreePoolList
= &mSmmPoolLists
[MAX_POOL_INDEX
- PoolListIndex
- 1];
1786 for (Node
= FreePoolList
->BackLink
;
1787 Node
!= FreePoolList
;
1788 Node
= Node
->BackLink
) {
1789 Pool
= BASE_CR (Node
, FREE_POOL_HEADER
, Link
);
1790 if (Pool
->Header
.Available
) {
1795 FreeMemory
->FreeMemoryEntryCount
= Index
;
1797 RemainingSize
-= sizeof (MEMORY_PROFILE_FREE_MEMORY
);
1798 ProfileBuffer
= (UINT8
*) ProfileBuffer
+ sizeof (MEMORY_PROFILE_FREE_MEMORY
);
1803 Offset
+= sizeof (MEMORY_PROFILE_FREE_MEMORY
);
1804 FreePageList
= &mSmmMemoryMap
;
1805 for (Node
= FreePageList
->BackLink
;
1806 Node
!= FreePageList
;
1807 Node
= Node
->BackLink
) {
1808 if (*ProfileOffset
< (Offset
+ sizeof (MEMORY_PROFILE_DESCRIPTOR
))) {
1809 if (RemainingSize
>= sizeof (MEMORY_PROFILE_DESCRIPTOR
)) {
1810 Pages
= BASE_CR (Node
, FREE_PAGE_LIST
, Link
);
1811 MemoryProfileDescriptor
= ProfileBuffer
;
1812 MemoryProfileDescriptor
->Header
.Signature
= MEMORY_PROFILE_DESCRIPTOR_SIGNATURE
;
1813 MemoryProfileDescriptor
->Header
.Length
= sizeof (MEMORY_PROFILE_DESCRIPTOR
);
1814 MemoryProfileDescriptor
->Header
.Revision
= MEMORY_PROFILE_DESCRIPTOR_REVISION
;
1815 MemoryProfileDescriptor
->Address
= (PHYSICAL_ADDRESS
) (UINTN
) Pages
;
1816 MemoryProfileDescriptor
->Size
= EFI_PAGES_TO_SIZE (Pages
->NumberOfPages
);
1818 RemainingSize
-= sizeof (MEMORY_PROFILE_DESCRIPTOR
);
1819 ProfileBuffer
= (UINT8
*) ProfileBuffer
+ sizeof (MEMORY_PROFILE_DESCRIPTOR
);
1824 Offset
+= sizeof (MEMORY_PROFILE_DESCRIPTOR
);
1826 for (PoolListIndex
= 0; PoolListIndex
< MAX_POOL_INDEX
; PoolListIndex
++) {
1827 FreePoolList
= &mSmmPoolLists
[MAX_POOL_INDEX
- PoolListIndex
- 1];
1828 for (Node
= FreePoolList
->BackLink
;
1829 Node
!= FreePoolList
;
1830 Node
= Node
->BackLink
) {
1831 Pool
= BASE_CR (Node
, FREE_POOL_HEADER
, Link
);
1832 if (Pool
->Header
.Available
) {
1833 if (*ProfileOffset
< (Offset
+ sizeof (MEMORY_PROFILE_DESCRIPTOR
))) {
1834 if (RemainingSize
>= sizeof (MEMORY_PROFILE_DESCRIPTOR
)) {
1835 MemoryProfileDescriptor
= ProfileBuffer
;
1836 MemoryProfileDescriptor
->Header
.Signature
= MEMORY_PROFILE_DESCRIPTOR_SIGNATURE
;
1837 MemoryProfileDescriptor
->Header
.Length
= sizeof (MEMORY_PROFILE_DESCRIPTOR
);
1838 MemoryProfileDescriptor
->Header
.Revision
= MEMORY_PROFILE_DESCRIPTOR_REVISION
;
1839 MemoryProfileDescriptor
->Address
= (PHYSICAL_ADDRESS
) (UINTN
) Pool
;
1840 MemoryProfileDescriptor
->Size
= Pool
->Header
.Size
;
1842 RemainingSize
-= sizeof (MEMORY_PROFILE_DESCRIPTOR
);
1843 ProfileBuffer
= (UINT8
*) ProfileBuffer
+ sizeof (MEMORY_PROFILE_DESCRIPTOR
);
1848 Offset
+= sizeof (MEMORY_PROFILE_DESCRIPTOR
);
1853 if (*ProfileOffset
< (Offset
+ sizeof (MEMORY_PROFILE_MEMORY_RANGE
))) {
1854 if (RemainingSize
>= sizeof (MEMORY_PROFILE_MEMORY_RANGE
)) {
1855 MemoryRange
= ProfileBuffer
;
1856 MemoryRange
->Header
.Signature
= MEMORY_PROFILE_MEMORY_RANGE_SIGNATURE
;
1857 MemoryRange
->Header
.Length
= sizeof (MEMORY_PROFILE_MEMORY_RANGE
);
1858 MemoryRange
->Header
.Revision
= MEMORY_PROFILE_MEMORY_RANGE_REVISION
;
1859 MemoryRange
->MemoryRangeCount
= (UINT32
) mFullSmramRangeCount
;
1861 RemainingSize
-= sizeof (MEMORY_PROFILE_MEMORY_RANGE
);
1862 ProfileBuffer
= (UINT8
*) ProfileBuffer
+ sizeof (MEMORY_PROFILE_MEMORY_RANGE
);
1867 Offset
+= sizeof (MEMORY_PROFILE_MEMORY_RANGE
);
1868 for (Index
= 0; Index
< mFullSmramRangeCount
; Index
++) {
1869 if (*ProfileOffset
< (Offset
+ sizeof (MEMORY_PROFILE_DESCRIPTOR
))) {
1870 if (RemainingSize
>= sizeof (MEMORY_PROFILE_DESCRIPTOR
)) {
1871 MemoryProfileDescriptor
= ProfileBuffer
;
1872 MemoryProfileDescriptor
->Header
.Signature
= MEMORY_PROFILE_DESCRIPTOR_SIGNATURE
;
1873 MemoryProfileDescriptor
->Header
.Length
= sizeof (MEMORY_PROFILE_DESCRIPTOR
);
1874 MemoryProfileDescriptor
->Header
.Revision
= MEMORY_PROFILE_DESCRIPTOR_REVISION
;
1875 MemoryProfileDescriptor
->Address
= mFullSmramRanges
[Index
].PhysicalStart
;
1876 MemoryProfileDescriptor
->Size
= mFullSmramRanges
[Index
].PhysicalSize
;
1878 RemainingSize
-= sizeof (MEMORY_PROFILE_DESCRIPTOR
);
1879 ProfileBuffer
= (UINT8
*) ProfileBuffer
+ sizeof (MEMORY_PROFILE_DESCRIPTOR
);
1884 Offset
+= sizeof (MEMORY_PROFILE_DESCRIPTOR
);
1889 // On output, actual profile data size copied.
1891 *ProfileSize
-= RemainingSize
;
1893 // On output, next time profile buffer offset to copy.
1895 *ProfileOffset
= Offset
;
1899 Get memory profile data.
1901 @param[in] This The EDKII_SMM_MEMORY_PROFILE_PROTOCOL instance.
1902 @param[in, out] ProfileSize On entry, points to the size in bytes of the ProfileBuffer.
1903 On return, points to the size of the data returned in ProfileBuffer.
1904 @param[out] ProfileBuffer Profile buffer.
1906 @return EFI_SUCCESS Get the memory profile data successfully.
1907 @return EFI_UNSUPPORTED Memory profile is unsupported.
1908 @return EFI_BUFFER_TO_SMALL The ProfileSize is too small for the resulting data.
1909 ProfileSize is updated with the size required.
1914 SmramProfileProtocolGetData (
1915 IN EDKII_SMM_MEMORY_PROFILE_PROTOCOL
*This
,
1916 IN OUT UINT64
*ProfileSize
,
1917 OUT VOID
*ProfileBuffer
1922 MEMORY_PROFILE_CONTEXT_DATA
*ContextData
;
1923 BOOLEAN SmramProfileGettingStatus
;
1925 ContextData
= GetSmramProfileContext ();
1926 if (ContextData
== NULL
) {
1927 return EFI_UNSUPPORTED
;
1930 SmramProfileGettingStatus
= mSmramProfileGettingStatus
;
1931 mSmramProfileGettingStatus
= TRUE
;
1933 Size
= SmramProfileGetDataSize ();
1935 if (*ProfileSize
< Size
) {
1936 *ProfileSize
= Size
;
1937 mSmramProfileGettingStatus
= SmramProfileGettingStatus
;
1938 return EFI_BUFFER_TOO_SMALL
;
1942 SmramProfileCopyData (ProfileBuffer
, &Size
, &Offset
);
1943 *ProfileSize
= Size
;
1945 mSmramProfileGettingStatus
= SmramProfileGettingStatus
;
1950 Register image to memory profile.
1952 @param[in] This The EDKII_SMM_MEMORY_PROFILE_PROTOCOL instance.
1953 @param[in] FilePath File path of the image.
1954 @param[in] ImageBase Image base address.
1955 @param[in] ImageSize Image size.
1956 @param[in] FileType File type of the image.
1958 @return EFI_SUCCESS Register successfully.
1959 @return EFI_UNSUPPORTED Memory profile is unsupported,
1960 or memory profile for the image is not required.
1961 @return EFI_OUT_OF_RESOURCES No enough resource for this register.
1966 SmramProfileProtocolRegisterImage (
1967 IN EDKII_SMM_MEMORY_PROFILE_PROTOCOL
*This
,
1968 IN EFI_DEVICE_PATH_PROTOCOL
*FilePath
,
1969 IN PHYSICAL_ADDRESS ImageBase
,
1970 IN UINT64 ImageSize
,
1971 IN EFI_FV_FILETYPE FileType
1975 EFI_SMM_DRIVER_ENTRY DriverEntry
;
1976 VOID
*EntryPointInImage
;
1979 ZeroMem (&DriverEntry
, sizeof (DriverEntry
));
1980 Name
= GetFileNameFromFilePath (FilePath
);
1982 CopyMem (&DriverEntry
.FileName
, Name
, sizeof (EFI_GUID
));
1984 DriverEntry
.ImageBuffer
= ImageBase
;
1985 DriverEntry
.NumberOfPage
= EFI_SIZE_TO_PAGES ((UINTN
) ImageSize
);
1986 Status
= InternalPeCoffGetEntryPoint ((VOID
*) (UINTN
) DriverEntry
.ImageBuffer
, &EntryPointInImage
);
1987 ASSERT_EFI_ERROR (Status
);
1988 DriverEntry
.ImageEntryPoint
= (PHYSICAL_ADDRESS
) (UINTN
) EntryPointInImage
;
1990 return RegisterSmramProfileImage (&DriverEntry
, FALSE
);
1994 Unregister image from memory profile.
1996 @param[in] This The EDKII_SMM_MEMORY_PROFILE_PROTOCOL instance.
1997 @param[in] FilePath File path of the image.
1998 @param[in] ImageBase Image base address.
1999 @param[in] ImageSize Image size.
2001 @return EFI_SUCCESS Unregister successfully.
2002 @return EFI_UNSUPPORTED Memory profile is unsupported,
2003 or memory profile for the image is not required.
2004 @return EFI_NOT_FOUND The image is not found.
2009 SmramProfileProtocolUnregisterImage (
2010 IN EDKII_SMM_MEMORY_PROFILE_PROTOCOL
*This
,
2011 IN EFI_DEVICE_PATH_PROTOCOL
*FilePath
,
2012 IN PHYSICAL_ADDRESS ImageBase
,
2017 EFI_SMM_DRIVER_ENTRY DriverEntry
;
2018 VOID
*EntryPointInImage
;
2021 ZeroMem (&DriverEntry
, sizeof (DriverEntry
));
2022 Name
= GetFileNameFromFilePath (FilePath
);
2024 CopyMem (&DriverEntry
.FileName
, Name
, sizeof (EFI_GUID
));
2026 DriverEntry
.ImageBuffer
= ImageBase
;
2027 DriverEntry
.NumberOfPage
= EFI_SIZE_TO_PAGES ((UINTN
) ImageSize
);
2028 Status
= InternalPeCoffGetEntryPoint ((VOID
*) (UINTN
) DriverEntry
.ImageBuffer
, &EntryPointInImage
);
2029 ASSERT_EFI_ERROR (Status
);
2030 DriverEntry
.ImageEntryPoint
= (PHYSICAL_ADDRESS
) (UINTN
) EntryPointInImage
;
2032 return UnregisterSmramProfileImage (&DriverEntry
, FALSE
);
2036 Get memory profile recording state.
2038 @param[in] This The EDKII_SMM_MEMORY_PROFILE_PROTOCOL instance.
2039 @param[out] RecordingState Recording state.
2041 @return EFI_SUCCESS Memory profile recording state is returned.
2042 @return EFI_UNSUPPORTED Memory profile is unsupported.
2043 @return EFI_INVALID_PARAMETER RecordingState is NULL.
2048 SmramProfileProtocolGetRecordingState (
2049 IN EDKII_SMM_MEMORY_PROFILE_PROTOCOL
*This
,
2050 OUT BOOLEAN
*RecordingState
2053 MEMORY_PROFILE_CONTEXT_DATA
*ContextData
;
2055 ContextData
= GetSmramProfileContext ();
2056 if (ContextData
== NULL
) {
2057 return EFI_UNSUPPORTED
;
2060 if (RecordingState
== NULL
) {
2061 return EFI_INVALID_PARAMETER
;
2063 *RecordingState
= mSmramProfileRecordingEnable
;
2068 Set memory profile recording state.
2070 @param[in] This The EDKII_SMM_MEMORY_PROFILE_PROTOCOL instance.
2071 @param[in] RecordingState Recording state.
2073 @return EFI_SUCCESS Set memory profile recording state successfully.
2074 @return EFI_UNSUPPORTED Memory profile is unsupported.
2079 SmramProfileProtocolSetRecordingState (
2080 IN EDKII_SMM_MEMORY_PROFILE_PROTOCOL
*This
,
2081 IN BOOLEAN RecordingState
2084 MEMORY_PROFILE_CONTEXT_DATA
*ContextData
;
2086 ContextData
= GetSmramProfileContext ();
2087 if (ContextData
== NULL
) {
2088 return EFI_UNSUPPORTED
;
2091 mSmramProfileRecordingEnable
= RecordingState
;
2096 Record memory profile of multilevel caller.
2098 @param[in] This The EDKII_SMM_MEMORY_PROFILE_PROTOCOL instance.
2099 @param[in] CallerAddress Address of caller.
2100 @param[in] Action Memory profile action.
2101 @param[in] MemoryType Memory type.
2102 EfiMaxMemoryType means the MemoryType is unknown.
2103 @param[in] Buffer Buffer address.
2104 @param[in] Size Buffer size.
2105 @param[in] ActionString String for memory profile action.
2106 Only needed for user defined allocate action.
2108 @return EFI_SUCCESS Memory profile is updated.
2109 @return EFI_UNSUPPORTED Memory profile is unsupported,
2110 or memory profile for the image is not required,
2111 or memory profile for the memory type is not required.
2112 @return EFI_ACCESS_DENIED It is during memory profile data getting.
2113 @return EFI_ABORTED Memory profile recording is not enabled.
2114 @return EFI_OUT_OF_RESOURCES No enough resource to update memory profile for allocate action.
2115 @return EFI_NOT_FOUND No matched allocate info found for free action.
2120 SmramProfileProtocolRecord (
2121 IN EDKII_SMM_MEMORY_PROFILE_PROTOCOL
*This
,
2122 IN PHYSICAL_ADDRESS CallerAddress
,
2123 IN MEMORY_PROFILE_ACTION Action
,
2124 IN EFI_MEMORY_TYPE MemoryType
,
2127 IN CHAR8
*ActionString OPTIONAL
2130 return SmmCoreUpdateProfile (CallerAddress
, Action
, MemoryType
, Size
, Buffer
, ActionString
);
2134 SMRAM profile handler to get profile info.
2136 @param SmramProfileParameterGetInfo The parameter of SMM profile get size.
2140 SmramProfileHandlerGetInfo (
2141 IN SMRAM_PROFILE_PARAMETER_GET_PROFILE_INFO
*SmramProfileParameterGetInfo
2144 MEMORY_PROFILE_CONTEXT_DATA
*ContextData
;
2145 BOOLEAN SmramProfileGettingStatus
;
2147 ContextData
= GetSmramProfileContext ();
2148 if (ContextData
== NULL
) {
2152 SmramProfileGettingStatus
= mSmramProfileGettingStatus
;
2153 mSmramProfileGettingStatus
= TRUE
;
2155 SmramProfileParameterGetInfo
->ProfileSize
= SmramProfileGetDataSize();
2156 SmramProfileParameterGetInfo
->Header
.ReturnStatus
= 0;
2158 mSmramProfileGettingStatus
= SmramProfileGettingStatus
;
2162 SMRAM profile handler to get profile data.
2164 @param SmramProfileParameterGetData The parameter of SMM profile get data.
2168 SmramProfileHandlerGetData (
2169 IN SMRAM_PROFILE_PARAMETER_GET_PROFILE_DATA
*SmramProfileParameterGetData
2173 UINT64 ProfileOffset
;
2174 SMRAM_PROFILE_PARAMETER_GET_PROFILE_DATA SmramProfileGetData
;
2175 MEMORY_PROFILE_CONTEXT_DATA
*ContextData
;
2176 BOOLEAN SmramProfileGettingStatus
;
2178 ContextData
= GetSmramProfileContext ();
2179 if (ContextData
== NULL
) {
2183 SmramProfileGettingStatus
= mSmramProfileGettingStatus
;
2184 mSmramProfileGettingStatus
= TRUE
;
2187 CopyMem (&SmramProfileGetData
, SmramProfileParameterGetData
, sizeof (SmramProfileGetData
));
2189 ProfileSize
= SmramProfileGetDataSize();
2194 if (!SmmIsBufferOutsideSmmValid ((UINTN
) SmramProfileGetData
.ProfileBuffer
, (UINTN
) ProfileSize
)) {
2195 DEBUG ((EFI_D_ERROR
, "SmramProfileHandlerGetData: SMM ProfileBuffer in SMRAM or overflow!\n"));
2196 SmramProfileParameterGetData
->ProfileSize
= ProfileSize
;
2197 SmramProfileParameterGetData
->Header
.ReturnStatus
= (UINT64
) (INT64
) (INTN
) EFI_ACCESS_DENIED
;
2201 if (SmramProfileGetData
.ProfileSize
< ProfileSize
) {
2202 SmramProfileParameterGetData
->ProfileSize
= ProfileSize
;
2203 SmramProfileParameterGetData
->Header
.ReturnStatus
= (UINT64
) (INT64
) (INTN
) EFI_BUFFER_TOO_SMALL
;
2208 SmramProfileCopyData ((VOID
*) (UINTN
) SmramProfileGetData
.ProfileBuffer
, &ProfileSize
, &ProfileOffset
);
2209 SmramProfileParameterGetData
->ProfileSize
= ProfileSize
;
2210 SmramProfileParameterGetData
->Header
.ReturnStatus
= 0;
2213 mSmramProfileGettingStatus
= SmramProfileGettingStatus
;
2217 SMRAM profile handler to get profile data by offset.
2219 @param SmramProfileParameterGetDataByOffset The parameter of SMM profile get data by offset.
2223 SmramProfileHandlerGetDataByOffset (
2224 IN SMRAM_PROFILE_PARAMETER_GET_PROFILE_DATA_BY_OFFSET
*SmramProfileParameterGetDataByOffset
2227 SMRAM_PROFILE_PARAMETER_GET_PROFILE_DATA_BY_OFFSET SmramProfileGetDataByOffset
;
2228 MEMORY_PROFILE_CONTEXT_DATA
*ContextData
;
2229 BOOLEAN SmramProfileGettingStatus
;
2231 ContextData
= GetSmramProfileContext ();
2232 if (ContextData
== NULL
) {
2236 SmramProfileGettingStatus
= mSmramProfileGettingStatus
;
2237 mSmramProfileGettingStatus
= TRUE
;
2240 CopyMem (&SmramProfileGetDataByOffset
, SmramProfileParameterGetDataByOffset
, sizeof (SmramProfileGetDataByOffset
));
2245 if (!SmmIsBufferOutsideSmmValid ((UINTN
) SmramProfileGetDataByOffset
.ProfileBuffer
, (UINTN
) SmramProfileGetDataByOffset
.ProfileSize
)) {
2246 DEBUG ((EFI_D_ERROR
, "SmramProfileHandlerGetDataByOffset: SMM ProfileBuffer in SMRAM or overflow!\n"));
2247 SmramProfileParameterGetDataByOffset
->Header
.ReturnStatus
= (UINT64
) (INT64
) (INTN
) EFI_ACCESS_DENIED
;
2251 SmramProfileCopyData ((VOID
*) (UINTN
) SmramProfileGetDataByOffset
.ProfileBuffer
, &SmramProfileGetDataByOffset
.ProfileSize
, &SmramProfileGetDataByOffset
.ProfileOffset
);
2252 CopyMem (SmramProfileParameterGetDataByOffset
, &SmramProfileGetDataByOffset
, sizeof (SmramProfileGetDataByOffset
));
2253 SmramProfileParameterGetDataByOffset
->Header
.ReturnStatus
= 0;
2256 mSmramProfileGettingStatus
= SmramProfileGettingStatus
;
2260 SMRAM profile handler to register SMM image.
2262 @param SmramProfileParameterRegisterImage The parameter of SMM profile register image.
2266 SmramProfileHandlerRegisterImage (
2267 IN SMRAM_PROFILE_PARAMETER_REGISTER_IMAGE
*SmramProfileParameterRegisterImage
2271 EFI_SMM_DRIVER_ENTRY DriverEntry
;
2272 VOID
*EntryPointInImage
;
2274 ZeroMem (&DriverEntry
, sizeof (DriverEntry
));
2275 CopyMem (&DriverEntry
.FileName
, &SmramProfileParameterRegisterImage
->FileName
, sizeof(EFI_GUID
));
2276 DriverEntry
.ImageBuffer
= SmramProfileParameterRegisterImage
->ImageBuffer
;
2277 DriverEntry
.NumberOfPage
= (UINTN
) SmramProfileParameterRegisterImage
->NumberOfPage
;
2278 Status
= InternalPeCoffGetEntryPoint ((VOID
*) (UINTN
) DriverEntry
.ImageBuffer
, &EntryPointInImage
);
2279 ASSERT_EFI_ERROR (Status
);
2280 DriverEntry
.ImageEntryPoint
= (PHYSICAL_ADDRESS
) (UINTN
) EntryPointInImage
;
2282 Status
= RegisterSmramProfileImage (&DriverEntry
, FALSE
);
2283 if (!EFI_ERROR (Status
)) {
2284 SmramProfileParameterRegisterImage
->Header
.ReturnStatus
= 0;
2289 SMRAM profile handler to unregister SMM image.
2291 @param SmramProfileParameterUnregisterImage The parameter of SMM profile unregister image.
2295 SmramProfileHandlerUnregisterImage (
2296 IN SMRAM_PROFILE_PARAMETER_UNREGISTER_IMAGE
*SmramProfileParameterUnregisterImage
2300 EFI_SMM_DRIVER_ENTRY DriverEntry
;
2301 VOID
*EntryPointInImage
;
2303 ZeroMem (&DriverEntry
, sizeof (DriverEntry
));
2304 CopyMem (&DriverEntry
.FileName
, &SmramProfileParameterUnregisterImage
->FileName
, sizeof (EFI_GUID
));
2305 DriverEntry
.ImageBuffer
= SmramProfileParameterUnregisterImage
->ImageBuffer
;
2306 DriverEntry
.NumberOfPage
= (UINTN
) SmramProfileParameterUnregisterImage
->NumberOfPage
;
2307 Status
= InternalPeCoffGetEntryPoint ((VOID
*) (UINTN
) DriverEntry
.ImageBuffer
, &EntryPointInImage
);
2308 ASSERT_EFI_ERROR (Status
);
2309 DriverEntry
.ImageEntryPoint
= (PHYSICAL_ADDRESS
) (UINTN
) EntryPointInImage
;
2311 Status
= UnregisterSmramProfileImage (&DriverEntry
, FALSE
);
2312 if (!EFI_ERROR (Status
)) {
2313 SmramProfileParameterUnregisterImage
->Header
.ReturnStatus
= 0;
2318 Dispatch function for a Software SMI handler.
2320 Caution: This function may receive untrusted input.
2321 Communicate buffer and buffer size are external input, so this function will do basic validation.
2323 @param DispatchHandle The unique handle assigned to this handler by SmiHandlerRegister().
2324 @param Context Points to an optional handler context which was specified when the
2325 handler was registered.
2326 @param CommBuffer A pointer to a collection of data in memory that will
2327 be conveyed from a non-SMM environment into an SMM environment.
2328 @param CommBufferSize The size of the CommBuffer.
2330 @retval EFI_SUCCESS Command is handled successfully.
2335 SmramProfileHandler (
2336 IN EFI_HANDLE DispatchHandle
,
2337 IN CONST VOID
*Context OPTIONAL
,
2338 IN OUT VOID
*CommBuffer OPTIONAL
,
2339 IN OUT UINTN
*CommBufferSize OPTIONAL
2342 SMRAM_PROFILE_PARAMETER_HEADER
*SmramProfileParameterHeader
;
2343 UINTN TempCommBufferSize
;
2344 SMRAM_PROFILE_PARAMETER_RECORDING_STATE
*ParameterRecordingState
;
2346 DEBUG ((EFI_D_ERROR
, "SmramProfileHandler Enter\n"));
2349 // If input is invalid, stop processing this SMI
2351 if (CommBuffer
== NULL
|| CommBufferSize
== NULL
) {
2355 TempCommBufferSize
= *CommBufferSize
;
2357 if (TempCommBufferSize
< sizeof (SMRAM_PROFILE_PARAMETER_HEADER
)) {
2358 DEBUG ((EFI_D_ERROR
, "SmramProfileHandler: SMM communication buffer size invalid!\n"));
2362 if (mSmramReadyToLock
&& !SmmIsBufferOutsideSmmValid ((UINTN
)CommBuffer
, TempCommBufferSize
)) {
2363 DEBUG ((EFI_D_ERROR
, "SmramProfileHandler: SMM communication buffer in SMRAM or overflow!\n"));
2367 SmramProfileParameterHeader
= (SMRAM_PROFILE_PARAMETER_HEADER
*) ((UINTN
) CommBuffer
);
2369 SmramProfileParameterHeader
->ReturnStatus
= (UINT64
)-1;
2371 if (GetSmramProfileContext () == NULL
) {
2372 SmramProfileParameterHeader
->ReturnStatus
= (UINT64
) (INT64
) (INTN
) EFI_UNSUPPORTED
;
2376 switch (SmramProfileParameterHeader
->Command
) {
2377 case SMRAM_PROFILE_COMMAND_GET_PROFILE_INFO
:
2378 DEBUG ((EFI_D_ERROR
, "SmramProfileHandlerGetInfo\n"));
2379 if (TempCommBufferSize
!= sizeof (SMRAM_PROFILE_PARAMETER_GET_PROFILE_INFO
)) {
2380 DEBUG ((EFI_D_ERROR
, "SmramProfileHandler: SMM communication buffer size invalid!\n"));
2383 SmramProfileHandlerGetInfo ((SMRAM_PROFILE_PARAMETER_GET_PROFILE_INFO
*) (UINTN
) CommBuffer
);
2385 case SMRAM_PROFILE_COMMAND_GET_PROFILE_DATA
:
2386 DEBUG ((EFI_D_ERROR
, "SmramProfileHandlerGetData\n"));
2387 if (TempCommBufferSize
!= sizeof (SMRAM_PROFILE_PARAMETER_GET_PROFILE_DATA
)) {
2388 DEBUG ((EFI_D_ERROR
, "SmramProfileHandler: SMM communication buffer size invalid!\n"));
2391 SmramProfileHandlerGetData ((SMRAM_PROFILE_PARAMETER_GET_PROFILE_DATA
*) (UINTN
) CommBuffer
);
2393 case SMRAM_PROFILE_COMMAND_GET_PROFILE_DATA_BY_OFFSET
:
2394 DEBUG ((EFI_D_ERROR
, "SmramProfileHandlerGetDataByOffset\n"));
2395 if (TempCommBufferSize
!= sizeof (SMRAM_PROFILE_PARAMETER_GET_PROFILE_DATA_BY_OFFSET
)) {
2396 DEBUG ((EFI_D_ERROR
, "SmramProfileHandler: SMM communication buffer size invalid!\n"));
2399 SmramProfileHandlerGetDataByOffset ((SMRAM_PROFILE_PARAMETER_GET_PROFILE_DATA_BY_OFFSET
*) (UINTN
) CommBuffer
);
2401 case SMRAM_PROFILE_COMMAND_REGISTER_IMAGE
:
2402 DEBUG ((EFI_D_ERROR
, "SmramProfileHandlerRegisterImage\n"));
2403 if (TempCommBufferSize
!= sizeof (SMRAM_PROFILE_PARAMETER_REGISTER_IMAGE
)) {
2404 DEBUG ((EFI_D_ERROR
, "SmramProfileHandler: SMM communication buffer size invalid!\n"));
2407 if (mSmramReadyToLock
) {
2410 SmramProfileHandlerRegisterImage ((SMRAM_PROFILE_PARAMETER_REGISTER_IMAGE
*) (UINTN
) CommBuffer
);
2412 case SMRAM_PROFILE_COMMAND_UNREGISTER_IMAGE
:
2413 DEBUG ((EFI_D_ERROR
, "SmramProfileHandlerUnregisterImage\n"));
2414 if (TempCommBufferSize
!= sizeof (SMRAM_PROFILE_PARAMETER_UNREGISTER_IMAGE
)) {
2415 DEBUG ((EFI_D_ERROR
, "SmramProfileHandler: SMM communication buffer size invalid!\n"));
2418 if (mSmramReadyToLock
) {
2421 SmramProfileHandlerUnregisterImage ((SMRAM_PROFILE_PARAMETER_UNREGISTER_IMAGE
*) (UINTN
) CommBuffer
);
2423 case SMRAM_PROFILE_COMMAND_GET_RECORDING_STATE
:
2424 DEBUG ((EFI_D_ERROR
, "SmramProfileHandlerGetRecordingState\n"));
2425 if (TempCommBufferSize
!= sizeof (SMRAM_PROFILE_PARAMETER_RECORDING_STATE
)) {
2426 DEBUG ((EFI_D_ERROR
, "SmramProfileHandler: SMM communication buffer size invalid!\n"));
2429 ParameterRecordingState
= (SMRAM_PROFILE_PARAMETER_RECORDING_STATE
*) (UINTN
) CommBuffer
;
2430 ParameterRecordingState
->RecordingState
= mSmramProfileRecordingEnable
;
2431 ParameterRecordingState
->Header
.ReturnStatus
= 0;
2433 case SMRAM_PROFILE_COMMAND_SET_RECORDING_STATE
:
2434 DEBUG ((EFI_D_ERROR
, "SmramProfileHandlerSetRecordingState\n"));
2435 if (TempCommBufferSize
!= sizeof (SMRAM_PROFILE_PARAMETER_RECORDING_STATE
)) {
2436 DEBUG ((EFI_D_ERROR
, "SmramProfileHandler: SMM communication buffer size invalid!\n"));
2439 ParameterRecordingState
= (SMRAM_PROFILE_PARAMETER_RECORDING_STATE
*) (UINTN
) CommBuffer
;
2440 mSmramProfileRecordingEnable
= ParameterRecordingState
->RecordingState
;
2441 ParameterRecordingState
->Header
.ReturnStatus
= 0;
2448 DEBUG ((EFI_D_ERROR
, "SmramProfileHandler Exit\n"));
2454 Register SMRAM profile handler.
2458 RegisterSmramProfileHandler (
2463 EFI_HANDLE DispatchHandle
;
2465 if (!IS_SMRAM_PROFILE_ENABLED
) {
2469 Status
= SmiHandlerRegister (
2470 SmramProfileHandler
,
2471 &gEdkiiMemoryProfileGuid
,
2474 ASSERT_EFI_ERROR (Status
);
2477 ////////////////////
2489 MEMORY_PROFILE_CONTEXT_DATA
*ContextData
;
2490 BOOLEAN SmramProfileGettingStatus
;
2492 ContextData
= GetSmramProfileContext ();
2493 if (ContextData
== NULL
) {
2497 SmramProfileGettingStatus
= mSmramProfileGettingStatus
;
2498 mSmramProfileGettingStatus
= TRUE
;
2500 DEBUG ((EFI_D_INFO
, "FullSmramRange address - 0x%08x\n", mFullSmramRanges
));
2502 DEBUG ((EFI_D_INFO
, "======= SmramProfile begin =======\n"));
2504 DEBUG ((EFI_D_INFO
, "FullSmramRange:\n"));
2505 for (Index
= 0; Index
< mFullSmramRangeCount
; Index
++) {
2506 DEBUG ((EFI_D_INFO
, " FullSmramRange (0x%x)\n", Index
));
2507 DEBUG ((EFI_D_INFO
, " PhysicalStart - 0x%016lx\n", mFullSmramRanges
[Index
].PhysicalStart
));
2508 DEBUG ((EFI_D_INFO
, " CpuStart - 0x%016lx\n", mFullSmramRanges
[Index
].CpuStart
));
2509 DEBUG ((EFI_D_INFO
, " PhysicalSize - 0x%016lx\n", mFullSmramRanges
[Index
].PhysicalSize
));
2510 DEBUG ((EFI_D_INFO
, " RegionState - 0x%016lx\n", mFullSmramRanges
[Index
].RegionState
));
2513 DEBUG ((EFI_D_INFO
, "======= SmramProfile end =======\n"));
2515 mSmramProfileGettingStatus
= SmramProfileGettingStatus
;
2519 Dump SMRAM free page list.
2527 LIST_ENTRY
*FreePageList
;
2529 FREE_PAGE_LIST
*Pages
;
2531 MEMORY_PROFILE_CONTEXT_DATA
*ContextData
;
2532 BOOLEAN SmramProfileGettingStatus
;
2534 ContextData
= GetSmramProfileContext ();
2535 if (ContextData
== NULL
) {
2539 SmramProfileGettingStatus
= mSmramProfileGettingStatus
;
2540 mSmramProfileGettingStatus
= TRUE
;
2542 DEBUG ((EFI_D_INFO
, "======= SmramProfile begin =======\n"));
2544 DEBUG ((EFI_D_INFO
, "FreePagesList:\n"));
2545 FreePageList
= &mSmmMemoryMap
;
2546 for (Node
= FreePageList
->BackLink
, Index
= 0;
2547 Node
!= FreePageList
;
2548 Node
= Node
->BackLink
, Index
++) {
2549 Pages
= BASE_CR (Node
, FREE_PAGE_LIST
, Link
);
2550 DEBUG ((EFI_D_INFO
, " Index - 0x%x\n", Index
));
2551 DEBUG ((EFI_D_INFO
, " PhysicalStart - 0x%016lx\n", (PHYSICAL_ADDRESS
) (UINTN
) Pages
));
2552 DEBUG ((EFI_D_INFO
, " NumberOfPages - 0x%08x\n", Pages
->NumberOfPages
));
2555 DEBUG ((EFI_D_INFO
, "======= SmramProfile end =======\n"));
2557 mSmramProfileGettingStatus
= SmramProfileGettingStatus
;
2561 Dump SMRAM free pool list.
2569 LIST_ENTRY
*FreePoolList
;
2571 FREE_POOL_HEADER
*Pool
;
2573 UINTN PoolListIndex
;
2574 MEMORY_PROFILE_CONTEXT_DATA
*ContextData
;
2575 BOOLEAN SmramProfileGettingStatus
;
2577 ContextData
= GetSmramProfileContext ();
2578 if (ContextData
== NULL
) {
2582 SmramProfileGettingStatus
= mSmramProfileGettingStatus
;
2583 mSmramProfileGettingStatus
= TRUE
;
2585 DEBUG ((EFI_D_INFO
, "======= SmramProfile begin =======\n"));
2587 for (PoolListIndex
= 0; PoolListIndex
< MAX_POOL_INDEX
; PoolListIndex
++) {
2588 DEBUG ((EFI_D_INFO
, "FreePoolList (%d):\n", PoolListIndex
));
2589 FreePoolList
= &mSmmPoolLists
[PoolListIndex
];
2590 for (Node
= FreePoolList
->BackLink
, Index
= 0;
2591 Node
!= FreePoolList
;
2592 Node
= Node
->BackLink
, Index
++) {
2593 Pool
= BASE_CR (Node
, FREE_POOL_HEADER
, Link
);
2594 DEBUG ((EFI_D_INFO
, " Index - 0x%x\n", Index
));
2595 DEBUG ((EFI_D_INFO
, " PhysicalStart - 0x%016lx\n", (PHYSICAL_ADDRESS
) (UINTN
) Pool
));
2596 DEBUG ((EFI_D_INFO
, " Size - 0x%08x\n", Pool
->Header
.Size
));
2597 DEBUG ((EFI_D_INFO
, " Available - 0x%02x\n", Pool
->Header
.Available
));
2601 DEBUG ((EFI_D_INFO
, "======= SmramProfile end =======\n"));
2603 mSmramProfileGettingStatus
= SmramProfileGettingStatus
;
2606 GLOBAL_REMOVE_IF_UNREFERENCED CHAR8
*mSmmActionString
[] = {
2608 "gSmst->SmmAllocatePages",
2609 "gSmst->SmmFreePages",
2610 "gSmst->SmmAllocatePool",
2611 "gSmst->SmmFreePool",
2615 MEMORY_PROFILE_ACTION Action
;
2619 ACTION_STRING mExtActionString
[] = {
2620 {MEMORY_PROFILE_ACTION_LIB_ALLOCATE_PAGES
, "Lib:AllocatePages"},
2621 {MEMORY_PROFILE_ACTION_LIB_ALLOCATE_RUNTIME_PAGES
, "Lib:AllocateRuntimePages"},
2622 {MEMORY_PROFILE_ACTION_LIB_ALLOCATE_RESERVED_PAGES
, "Lib:AllocateReservedPages"},
2623 {MEMORY_PROFILE_ACTION_LIB_FREE_PAGES
, "Lib:FreePages"},
2624 {MEMORY_PROFILE_ACTION_LIB_ALLOCATE_ALIGNED_PAGES
, "Lib:AllocateAlignedPages"},
2625 {MEMORY_PROFILE_ACTION_LIB_ALLOCATE_ALIGNED_RUNTIME_PAGES
, "Lib:AllocateAlignedRuntimePages"},
2626 {MEMORY_PROFILE_ACTION_LIB_ALLOCATE_ALIGNED_RESERVED_PAGES
, "Lib:AllocateAlignedReservedPages"},
2627 {MEMORY_PROFILE_ACTION_LIB_FREE_ALIGNED_PAGES
, "Lib:FreeAlignedPages"},
2628 {MEMORY_PROFILE_ACTION_LIB_ALLOCATE_POOL
, "Lib:AllocatePool"},
2629 {MEMORY_PROFILE_ACTION_LIB_ALLOCATE_RUNTIME_POOL
, "Lib:AllocateRuntimePool"},
2630 {MEMORY_PROFILE_ACTION_LIB_ALLOCATE_RESERVED_POOL
, "Lib:AllocateReservedPool"},
2631 {MEMORY_PROFILE_ACTION_LIB_FREE_POOL
, "Lib:FreePool"},
2632 {MEMORY_PROFILE_ACTION_LIB_ALLOCATE_ZERO_POOL
, "Lib:AllocateZeroPool"},
2633 {MEMORY_PROFILE_ACTION_LIB_ALLOCATE_RUNTIME_ZERO_POOL
, "Lib:AllocateRuntimeZeroPool"},
2634 {MEMORY_PROFILE_ACTION_LIB_ALLOCATE_RESERVED_ZERO_POOL
, "Lib:AllocateReservedZeroPool"},
2635 {MEMORY_PROFILE_ACTION_LIB_ALLOCATE_COPY_POOL
, "Lib:AllocateCopyPool"},
2636 {MEMORY_PROFILE_ACTION_LIB_ALLOCATE_RUNTIME_COPY_POOL
, "Lib:AllocateRuntimeCopyPool"},
2637 {MEMORY_PROFILE_ACTION_LIB_ALLOCATE_RESERVED_COPY_POOL
, "Lib:AllocateReservedCopyPool"},
2638 {MEMORY_PROFILE_ACTION_LIB_REALLOCATE_POOL
, "Lib:ReallocatePool"},
2639 {MEMORY_PROFILE_ACTION_LIB_REALLOCATE_RUNTIME_POOL
, "Lib:ReallocateRuntimePool"},
2640 {MEMORY_PROFILE_ACTION_LIB_REALLOCATE_RESERVED_POOL
, "Lib:ReallocateReservedPool"},
2643 GLOBAL_REMOVE_IF_UNREFERENCED CHAR8 mUserDefinedActionString
[] = {"UserDefined-0x80000000"};
2646 EFI_MEMORY_TYPE MemoryType
;
2647 CHAR8
*MemoryTypeStr
;
2648 } PROFILE_MEMORY_TYPE_STRING
;
2650 GLOBAL_REMOVE_IF_UNREFERENCED PROFILE_MEMORY_TYPE_STRING mMemoryTypeString
[] = {
2651 {EfiRuntimeServicesCode
, "EfiRuntimeServicesCode"},
2652 {EfiRuntimeServicesData
, "EfiRuntimeServicesData"}
2656 Memory type to string.
2658 @param[in] MemoryType Memory type.
2660 @return Pointer to string.
2664 ProfileMemoryTypeToStr (
2665 IN EFI_MEMORY_TYPE MemoryType
2669 for (Index
= 0; Index
< sizeof (mMemoryTypeString
) / sizeof (mMemoryTypeString
[0]); Index
++) {
2670 if (mMemoryTypeString
[Index
].MemoryType
== MemoryType
) {
2671 return mMemoryTypeString
[Index
].MemoryTypeStr
;
2675 return "UnexpectedMemoryType";
2681 @param[in] Action Profile action.
2683 @return Pointer to string.
2687 ProfileActionToStr (
2688 IN MEMORY_PROFILE_ACTION Action
2692 UINTN ActionStringCount
;
2693 CHAR8
**ActionString
;
2695 ActionString
= mSmmActionString
;
2696 ActionStringCount
= sizeof (mSmmActionString
) / sizeof (mSmmActionString
[0]);
2698 if ((UINTN
) (UINT32
) Action
< ActionStringCount
) {
2699 return ActionString
[Action
];
2701 for (Index
= 0; Index
< sizeof (mExtActionString
) / sizeof (mExtActionString
[0]); Index
++) {
2702 if (mExtActionString
[Index
].Action
== Action
) {
2703 return mExtActionString
[Index
].String
;
2707 return ActionString
[0];
2719 MEMORY_PROFILE_CONTEXT
*Context
;
2720 MEMORY_PROFILE_DRIVER_INFO
*DriverInfo
;
2721 MEMORY_PROFILE_ALLOC_INFO
*AllocInfo
;
2722 MEMORY_PROFILE_CONTEXT_DATA
*ContextData
;
2723 MEMORY_PROFILE_DRIVER_INFO_DATA
*DriverInfoData
;
2724 MEMORY_PROFILE_ALLOC_INFO_DATA
*AllocInfoData
;
2725 LIST_ENTRY
*SmramDriverInfoList
;
2727 LIST_ENTRY
*DriverLink
;
2728 LIST_ENTRY
*AllocInfoList
;
2730 LIST_ENTRY
*AllocLink
;
2731 BOOLEAN SmramProfileGettingStatus
;
2734 ContextData
= GetSmramProfileContext ();
2735 if (ContextData
== NULL
) {
2739 SmramProfileGettingStatus
= mSmramProfileGettingStatus
;
2740 mSmramProfileGettingStatus
= TRUE
;
2742 Context
= &ContextData
->Context
;
2743 DEBUG ((EFI_D_INFO
, "======= SmramProfile begin =======\n"));
2744 DEBUG ((EFI_D_INFO
, "MEMORY_PROFILE_CONTEXT\n"));
2746 DEBUG ((EFI_D_INFO
, " CurrentTotalUsage - 0x%016lx\n", Context
->CurrentTotalUsage
));
2747 DEBUG ((EFI_D_INFO
, " PeakTotalUsage - 0x%016lx\n", Context
->PeakTotalUsage
));
2748 for (TypeIndex
= 0; TypeIndex
< sizeof (Context
->CurrentTotalUsageByType
) / sizeof (Context
->CurrentTotalUsageByType
[0]); TypeIndex
++) {
2749 if ((Context
->CurrentTotalUsageByType
[TypeIndex
] != 0) ||
2750 (Context
->PeakTotalUsageByType
[TypeIndex
] != 0)) {
2751 DEBUG ((EFI_D_INFO
, " CurrentTotalUsage[0x%02x] - 0x%016lx (%a)\n", TypeIndex
, Context
->CurrentTotalUsageByType
[TypeIndex
], ProfileMemoryTypeToStr (TypeIndex
)));
2752 DEBUG ((EFI_D_INFO
, " PeakTotalUsage[0x%02x] - 0x%016lx (%a)\n", TypeIndex
, Context
->PeakTotalUsageByType
[TypeIndex
], ProfileMemoryTypeToStr (TypeIndex
)));
2755 DEBUG ((EFI_D_INFO
, " TotalImageSize - 0x%016lx\n", Context
->TotalImageSize
));
2756 DEBUG ((EFI_D_INFO
, " ImageCount - 0x%08x\n", Context
->ImageCount
));
2757 DEBUG ((EFI_D_INFO
, " SequenceCount - 0x%08x\n", Context
->SequenceCount
));
2759 SmramDriverInfoList
= ContextData
->DriverInfoList
;
2760 for (DriverLink
= SmramDriverInfoList
->ForwardLink
, DriverIndex
= 0;
2761 DriverLink
!= SmramDriverInfoList
;
2762 DriverLink
= DriverLink
->ForwardLink
, DriverIndex
++) {
2763 DriverInfoData
= CR (
2765 MEMORY_PROFILE_DRIVER_INFO_DATA
,
2767 MEMORY_PROFILE_DRIVER_INFO_SIGNATURE
2769 DriverInfo
= &DriverInfoData
->DriverInfo
;
2770 DEBUG ((EFI_D_INFO
, " MEMORY_PROFILE_DRIVER_INFO (0x%x)\n", DriverIndex
));
2771 DEBUG ((EFI_D_INFO
, " FileName - %g\n", &DriverInfo
->FileName
));
2772 DEBUG ((EFI_D_INFO
, " ImageBase - 0x%016lx\n", DriverInfo
->ImageBase
));
2773 DEBUG ((EFI_D_INFO
, " ImageSize - 0x%016lx\n", DriverInfo
->ImageSize
));
2774 DEBUG ((EFI_D_INFO
, " EntryPoint - 0x%016lx\n", DriverInfo
->EntryPoint
));
2775 DEBUG ((EFI_D_INFO
, " ImageSubsystem - 0x%04x\n", DriverInfo
->ImageSubsystem
));
2776 DEBUG ((EFI_D_INFO
, " FileType - 0x%02x\n", DriverInfo
->FileType
));
2777 DEBUG ((EFI_D_INFO
, " CurrentUsage - 0x%016lx\n", DriverInfo
->CurrentUsage
));
2778 DEBUG ((EFI_D_INFO
, " PeakUsage - 0x%016lx\n", DriverInfo
->PeakUsage
));
2779 for (TypeIndex
= 0; TypeIndex
< sizeof (DriverInfo
->CurrentUsageByType
) / sizeof (DriverInfo
->CurrentUsageByType
[0]); TypeIndex
++) {
2780 if ((DriverInfo
->CurrentUsageByType
[TypeIndex
] != 0) ||
2781 (DriverInfo
->PeakUsageByType
[TypeIndex
] != 0)) {
2782 DEBUG ((EFI_D_INFO
, " CurrentUsage[0x%02x] - 0x%016lx (%a)\n", TypeIndex
, DriverInfo
->CurrentUsageByType
[TypeIndex
], ProfileMemoryTypeToStr (TypeIndex
)));
2783 DEBUG ((EFI_D_INFO
, " PeakUsage[0x%02x] - 0x%016lx (%a)\n", TypeIndex
, DriverInfo
->PeakUsageByType
[TypeIndex
], ProfileMemoryTypeToStr (TypeIndex
)));
2786 DEBUG ((EFI_D_INFO
, " AllocRecordCount - 0x%08x\n", DriverInfo
->AllocRecordCount
));
2788 AllocInfoList
= DriverInfoData
->AllocInfoList
;
2789 for (AllocLink
= AllocInfoList
->ForwardLink
, AllocIndex
= 0;
2790 AllocLink
!= AllocInfoList
;
2791 AllocLink
= AllocLink
->ForwardLink
, AllocIndex
++) {
2792 AllocInfoData
= CR (
2794 MEMORY_PROFILE_ALLOC_INFO_DATA
,
2796 MEMORY_PROFILE_ALLOC_INFO_SIGNATURE
2798 AllocInfo
= &AllocInfoData
->AllocInfo
;
2799 DEBUG ((EFI_D_INFO
, " MEMORY_PROFILE_ALLOC_INFO (0x%x)\n", AllocIndex
));
2800 DEBUG ((EFI_D_INFO
, " CallerAddress - 0x%016lx (Offset: 0x%08x)\n", AllocInfo
->CallerAddress
, AllocInfo
->CallerAddress
- DriverInfo
->ImageBase
));
2801 DEBUG ((EFI_D_INFO
, " SequenceId - 0x%08x\n", AllocInfo
->SequenceId
));
2802 if ((AllocInfo
->Action
& MEMORY_PROFILE_ACTION_USER_DEFINED_MASK
) != 0) {
2803 if (AllocInfoData
->ActionString
!= NULL
) {
2804 DEBUG ((EFI_D_INFO
, " Action - 0x%08x (%a)\n", AllocInfo
->Action
, AllocInfoData
->ActionString
));
2806 DEBUG ((EFI_D_INFO
, " Action - 0x%08x (UserDefined-0x%08x)\n", AllocInfo
->Action
, AllocInfo
->Action
));
2809 DEBUG ((EFI_D_INFO
, " Action - 0x%08x (%a)\n", AllocInfo
->Action
, ProfileActionToStr (AllocInfo
->Action
)));
2811 DEBUG ((EFI_D_INFO
, " MemoryType - 0x%08x (%a)\n", AllocInfo
->MemoryType
, ProfileMemoryTypeToStr (AllocInfo
->MemoryType
)));
2812 DEBUG ((EFI_D_INFO
, " Buffer - 0x%016lx\n", AllocInfo
->Buffer
));
2813 DEBUG ((EFI_D_INFO
, " Size - 0x%016lx\n", AllocInfo
->Size
));
2817 DEBUG ((EFI_D_INFO
, "======= SmramProfile end =======\n"));
2819 mSmramProfileGettingStatus
= SmramProfileGettingStatus
;
2823 Dump SMRAM infromation.
2832 if (IS_SMRAM_PROFILE_ENABLED
) {
2833 DumpSmramProfile ();
2834 DumpFreePagesList ();
2835 DumpFreePoolList ();