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
);
1406 ASSERT (DriverInfoData
!= NULL
);
1407 ASSERT (AllocInfoData
!= NULL
);
1411 Context
= &ContextData
->Context
;
1412 DriverInfo
= &DriverInfoData
->DriverInfo
;
1413 AllocInfo
= &AllocInfoData
->AllocInfo
;
1415 DriverInfo
->AllocRecordCount
--;
1417 // Update summary if and only if it is basic action.
1419 if (AllocInfo
->Action
== (AllocInfo
->Action
& MEMORY_PROFILE_ACTION_BASIC_MASK
)) {
1420 ProfileMemoryIndex
= GetProfileMemoryIndex (AllocInfo
->MemoryType
);
1422 Context
->CurrentTotalUsage
-= AllocInfo
->Size
;
1423 Context
->CurrentTotalUsageByType
[ProfileMemoryIndex
] -= AllocInfo
->Size
;
1425 DriverInfo
->CurrentUsage
-= AllocInfo
->Size
;
1426 DriverInfo
->CurrentUsageByType
[ProfileMemoryIndex
] -= AllocInfo
->Size
;
1429 RemoveEntryList (&AllocInfoData
->Link
);
1431 if (BasicAction
== MemoryProfileActionFreePages
) {
1432 if (AllocInfo
->Buffer
!= (PHYSICAL_ADDRESS
) (UINTN
) Buffer
) {
1433 SmmCoreUpdateProfileAllocate (
1434 AllocInfo
->CallerAddress
,
1436 AllocInfo
->MemoryType
,
1437 (UINTN
) ((PHYSICAL_ADDRESS
) (UINTN
) Buffer
- AllocInfo
->Buffer
),
1438 (VOID
*) (UINTN
) AllocInfo
->Buffer
,
1439 AllocInfoData
->ActionString
1442 if (AllocInfo
->Buffer
+ AllocInfo
->Size
!= ((PHYSICAL_ADDRESS
) (UINTN
) Buffer
+ Size
)) {
1443 SmmCoreUpdateProfileAllocate (
1444 AllocInfo
->CallerAddress
,
1446 AllocInfo
->MemoryType
,
1447 (UINTN
) ((AllocInfo
->Buffer
+ AllocInfo
->Size
) - ((PHYSICAL_ADDRESS
) (UINTN
) Buffer
+ Size
)),
1448 (VOID
*) ((UINTN
) Buffer
+ Size
),
1449 AllocInfoData
->ActionString
1455 // Use SmmInternalFreePool() that will not update profile for this FreePool action.
1457 SmmInternalFreePool (AllocInfoData
);
1462 Update SMRAM profile information.
1464 @param CallerAddress Address of caller who call Allocate or Free.
1465 @param Action This Allocate or Free action.
1466 @param MemoryType Memory type.
1467 EfiMaxMemoryType means the MemoryType is unknown.
1468 @param Size Buffer size.
1469 @param Buffer Buffer address.
1470 @param ActionString String for memory profile action.
1471 Only needed for user defined allocate action.
1473 @return EFI_SUCCESS Memory profile is updated.
1474 @return EFI_UNSUPPORTED Memory profile is unsupported,
1475 or memory profile for the image is not required,
1476 or memory profile for the memory type is not required.
1477 @return EFI_ACCESS_DENIED It is during memory profile data getting.
1478 @return EFI_ABORTED Memory profile recording is not enabled.
1479 @return EFI_OUT_OF_RESOURCES No enough resource to update memory profile for allocate action.
1480 @return EFI_NOT_FOUND No matched allocate info found for free action.
1485 SmmCoreUpdateProfile (
1486 IN PHYSICAL_ADDRESS CallerAddress
,
1487 IN MEMORY_PROFILE_ACTION Action
,
1488 IN EFI_MEMORY_TYPE MemoryType
, // Valid for AllocatePages/AllocatePool
1489 IN UINTN Size
, // Valid for AllocatePages/FreePages/AllocatePool
1491 IN CHAR8
*ActionString OPTIONAL
1495 MEMORY_PROFILE_CONTEXT_DATA
*ContextData
;
1496 MEMORY_PROFILE_ACTION BasicAction
;
1498 if (!IS_SMRAM_PROFILE_ENABLED
) {
1499 return EFI_UNSUPPORTED
;
1502 if (mSmramProfileGettingStatus
) {
1503 return EFI_ACCESS_DENIED
;
1506 if (!mSmramProfileRecordingEnable
) {
1511 // Get the basic action to know how to process the record
1513 BasicAction
= Action
& MEMORY_PROFILE_ACTION_BASIC_MASK
;
1516 // Free operations have no memory type information, so skip the check.
1518 if ((BasicAction
== MemoryProfileActionAllocatePages
) || (BasicAction
== MemoryProfileActionAllocatePool
)) {
1520 // Only record limited MemoryType.
1522 if (!SmmCoreNeedRecordProfile (MemoryType
)) {
1523 return EFI_UNSUPPORTED
;
1527 ContextData
= GetSmramProfileContext ();
1528 if (ContextData
== NULL
) {
1529 return EFI_UNSUPPORTED
;
1532 switch (BasicAction
) {
1533 case MemoryProfileActionAllocatePages
:
1534 Status
= SmmCoreUpdateProfileAllocate (CallerAddress
, Action
, MemoryType
, Size
, Buffer
, ActionString
);
1536 case MemoryProfileActionFreePages
:
1537 Status
= SmmCoreUpdateProfileFree (CallerAddress
, Action
, Size
, Buffer
);
1539 case MemoryProfileActionAllocatePool
:
1540 Status
= SmmCoreUpdateProfileAllocate (CallerAddress
, Action
, MemoryType
, Size
, Buffer
, ActionString
);
1542 case MemoryProfileActionFreePool
:
1543 Status
= SmmCoreUpdateProfileFree (CallerAddress
, Action
, 0, Buffer
);
1547 Status
= EFI_UNSUPPORTED
;
1555 SMRAM profile ready to lock callback function.
1559 SmramProfileReadyToLock (
1563 if (!IS_SMRAM_PROFILE_ENABLED
) {
1567 DEBUG ((EFI_D_INFO
, "SmramProfileReadyToLock\n"));
1568 mSmramReadyToLock
= TRUE
;
1571 ////////////////////
1574 Get SMRAM profile data size.
1576 @return SMRAM profile data size.
1580 SmramProfileGetDataSize (
1584 MEMORY_PROFILE_CONTEXT_DATA
*ContextData
;
1585 MEMORY_PROFILE_DRIVER_INFO_DATA
*DriverInfoData
;
1586 MEMORY_PROFILE_ALLOC_INFO_DATA
*AllocInfoData
;
1587 LIST_ENTRY
*DriverInfoList
;
1588 LIST_ENTRY
*DriverLink
;
1589 LIST_ENTRY
*AllocInfoList
;
1590 LIST_ENTRY
*AllocLink
;
1593 LIST_ENTRY
*FreePageList
;
1594 LIST_ENTRY
*FreePoolList
;
1595 FREE_POOL_HEADER
*Pool
;
1596 UINTN PoolListIndex
;
1599 ContextData
= GetSmramProfileContext ();
1600 if (ContextData
== NULL
) {
1604 TotalSize
= sizeof (MEMORY_PROFILE_CONTEXT
);
1606 DriverInfoList
= ContextData
->DriverInfoList
;
1607 for (DriverLink
= DriverInfoList
->ForwardLink
;
1608 DriverLink
!= DriverInfoList
;
1609 DriverLink
= DriverLink
->ForwardLink
) {
1610 DriverInfoData
= CR (
1612 MEMORY_PROFILE_DRIVER_INFO_DATA
,
1614 MEMORY_PROFILE_DRIVER_INFO_SIGNATURE
1616 TotalSize
+= DriverInfoData
->DriverInfo
.Header
.Length
;
1618 AllocInfoList
= DriverInfoData
->AllocInfoList
;
1619 for (AllocLink
= AllocInfoList
->ForwardLink
;
1620 AllocLink
!= AllocInfoList
;
1621 AllocLink
= AllocLink
->ForwardLink
) {
1622 AllocInfoData
= CR (
1624 MEMORY_PROFILE_ALLOC_INFO_DATA
,
1626 MEMORY_PROFILE_ALLOC_INFO_SIGNATURE
1628 TotalSize
+= AllocInfoData
->AllocInfo
.Header
.Length
;
1634 FreePageList
= &mSmmMemoryMap
;
1635 for (Node
= FreePageList
->BackLink
;
1636 Node
!= FreePageList
;
1637 Node
= Node
->BackLink
) {
1640 for (PoolListIndex
= 0; PoolListIndex
< MAX_POOL_INDEX
; PoolListIndex
++) {
1641 FreePoolList
= &mSmmPoolLists
[PoolListIndex
];
1642 for (Node
= FreePoolList
->BackLink
;
1643 Node
!= FreePoolList
;
1644 Node
= Node
->BackLink
) {
1645 Pool
= BASE_CR (Node
, FREE_POOL_HEADER
, Link
);
1646 if (Pool
->Header
.Available
) {
1653 TotalSize
+= (sizeof (MEMORY_PROFILE_FREE_MEMORY
) + Index
* sizeof (MEMORY_PROFILE_DESCRIPTOR
));
1654 TotalSize
+= (sizeof (MEMORY_PROFILE_MEMORY_RANGE
) + mFullSmramRangeCount
* sizeof (MEMORY_PROFILE_DESCRIPTOR
));
1660 Copy SMRAM profile data.
1662 @param ProfileBuffer The buffer to hold SMRAM profile data.
1663 @param ProfileSize On input, profile buffer size.
1664 On output, actual profile data size copied.
1665 @param ProfileOffset On input, profile buffer offset to copy.
1666 On output, next time profile buffer offset to copy.
1670 SmramProfileCopyData (
1671 OUT VOID
*ProfileBuffer
,
1672 IN OUT UINT64
*ProfileSize
,
1673 IN OUT UINT64
*ProfileOffset
1676 MEMORY_PROFILE_CONTEXT
*Context
;
1677 MEMORY_PROFILE_DRIVER_INFO
*DriverInfo
;
1678 MEMORY_PROFILE_ALLOC_INFO
*AllocInfo
;
1679 MEMORY_PROFILE_CONTEXT_DATA
*ContextData
;
1680 MEMORY_PROFILE_DRIVER_INFO_DATA
*DriverInfoData
;
1681 MEMORY_PROFILE_ALLOC_INFO_DATA
*AllocInfoData
;
1682 LIST_ENTRY
*DriverInfoList
;
1683 LIST_ENTRY
*DriverLink
;
1684 LIST_ENTRY
*AllocInfoList
;
1685 LIST_ENTRY
*AllocLink
;
1687 FREE_PAGE_LIST
*Pages
;
1688 LIST_ENTRY
*FreePageList
;
1689 LIST_ENTRY
*FreePoolList
;
1690 FREE_POOL_HEADER
*Pool
;
1691 UINTN PoolListIndex
;
1693 MEMORY_PROFILE_FREE_MEMORY
*FreeMemory
;
1694 MEMORY_PROFILE_MEMORY_RANGE
*MemoryRange
;
1695 MEMORY_PROFILE_DESCRIPTOR
*MemoryProfileDescriptor
;
1697 UINT64 RemainingSize
;
1699 UINTN ActionStringSize
;
1701 ContextData
= GetSmramProfileContext ();
1702 if (ContextData
== NULL
) {
1706 RemainingSize
= *ProfileSize
;
1709 if (*ProfileOffset
< sizeof (MEMORY_PROFILE_CONTEXT
)) {
1710 if (RemainingSize
>= sizeof (MEMORY_PROFILE_CONTEXT
)) {
1711 Context
= ProfileBuffer
;
1712 CopyMem (Context
, &ContextData
->Context
, sizeof (MEMORY_PROFILE_CONTEXT
));
1713 RemainingSize
-= sizeof (MEMORY_PROFILE_CONTEXT
);
1714 ProfileBuffer
= (UINT8
*) ProfileBuffer
+ sizeof (MEMORY_PROFILE_CONTEXT
);
1719 Offset
+= sizeof (MEMORY_PROFILE_CONTEXT
);
1721 DriverInfoList
= ContextData
->DriverInfoList
;
1722 for (DriverLink
= DriverInfoList
->ForwardLink
;
1723 DriverLink
!= DriverInfoList
;
1724 DriverLink
= DriverLink
->ForwardLink
) {
1725 DriverInfoData
= CR (
1727 MEMORY_PROFILE_DRIVER_INFO_DATA
,
1729 MEMORY_PROFILE_DRIVER_INFO_SIGNATURE
1731 if (*ProfileOffset
< (Offset
+ DriverInfoData
->DriverInfo
.Header
.Length
)) {
1732 if (RemainingSize
>= DriverInfoData
->DriverInfo
.Header
.Length
) {
1733 DriverInfo
= ProfileBuffer
;
1734 CopyMem (DriverInfo
, &DriverInfoData
->DriverInfo
, sizeof (MEMORY_PROFILE_DRIVER_INFO
));
1735 if (DriverInfo
->PdbStringOffset
!= 0) {
1736 PdbSize
= AsciiStrSize (DriverInfoData
->PdbString
);
1737 CopyMem ((VOID
*) ((UINTN
) DriverInfo
+ DriverInfo
->PdbStringOffset
), DriverInfoData
->PdbString
, PdbSize
);
1739 RemainingSize
-= DriverInfo
->Header
.Length
;
1740 ProfileBuffer
= (UINT8
*) ProfileBuffer
+ DriverInfo
->Header
.Length
;
1745 Offset
+= DriverInfoData
->DriverInfo
.Header
.Length
;
1747 AllocInfoList
= DriverInfoData
->AllocInfoList
;
1748 for (AllocLink
= AllocInfoList
->ForwardLink
;
1749 AllocLink
!= AllocInfoList
;
1750 AllocLink
= AllocLink
->ForwardLink
) {
1751 AllocInfoData
= CR (
1753 MEMORY_PROFILE_ALLOC_INFO_DATA
,
1755 MEMORY_PROFILE_ALLOC_INFO_SIGNATURE
1757 if (*ProfileOffset
< (Offset
+ AllocInfoData
->AllocInfo
.Header
.Length
)) {
1758 if (RemainingSize
>= AllocInfoData
->AllocInfo
.Header
.Length
) {
1759 AllocInfo
= ProfileBuffer
;
1760 CopyMem (AllocInfo
, &AllocInfoData
->AllocInfo
, sizeof (MEMORY_PROFILE_ALLOC_INFO
));
1761 if (AllocInfo
->ActionStringOffset
) {
1762 ActionStringSize
= AsciiStrSize (AllocInfoData
->ActionString
);
1763 CopyMem ((VOID
*) ((UINTN
) AllocInfo
+ AllocInfo
->ActionStringOffset
), AllocInfoData
->ActionString
, ActionStringSize
);
1765 RemainingSize
-= AllocInfo
->Header
.Length
;
1766 ProfileBuffer
= (UINT8
*) ProfileBuffer
+ AllocInfo
->Header
.Length
;
1771 Offset
+= AllocInfoData
->AllocInfo
.Header
.Length
;
1776 if (*ProfileOffset
< (Offset
+ sizeof (MEMORY_PROFILE_FREE_MEMORY
))) {
1777 if (RemainingSize
>= sizeof (MEMORY_PROFILE_FREE_MEMORY
)) {
1778 FreeMemory
= ProfileBuffer
;
1779 CopyMem (FreeMemory
, &mSmramFreeMemory
, sizeof (MEMORY_PROFILE_FREE_MEMORY
));
1781 FreePageList
= &mSmmMemoryMap
;
1782 for (Node
= FreePageList
->BackLink
;
1783 Node
!= FreePageList
;
1784 Node
= Node
->BackLink
) {
1787 for (PoolListIndex
= 0; PoolListIndex
< MAX_POOL_INDEX
; PoolListIndex
++) {
1788 FreePoolList
= &mSmmPoolLists
[MAX_POOL_INDEX
- PoolListIndex
- 1];
1789 for (Node
= FreePoolList
->BackLink
;
1790 Node
!= FreePoolList
;
1791 Node
= Node
->BackLink
) {
1792 Pool
= BASE_CR (Node
, FREE_POOL_HEADER
, Link
);
1793 if (Pool
->Header
.Available
) {
1798 FreeMemory
->FreeMemoryEntryCount
= Index
;
1800 RemainingSize
-= sizeof (MEMORY_PROFILE_FREE_MEMORY
);
1801 ProfileBuffer
= (UINT8
*) ProfileBuffer
+ sizeof (MEMORY_PROFILE_FREE_MEMORY
);
1806 Offset
+= sizeof (MEMORY_PROFILE_FREE_MEMORY
);
1807 FreePageList
= &mSmmMemoryMap
;
1808 for (Node
= FreePageList
->BackLink
;
1809 Node
!= FreePageList
;
1810 Node
= Node
->BackLink
) {
1811 if (*ProfileOffset
< (Offset
+ sizeof (MEMORY_PROFILE_DESCRIPTOR
))) {
1812 if (RemainingSize
>= sizeof (MEMORY_PROFILE_DESCRIPTOR
)) {
1813 Pages
= BASE_CR (Node
, FREE_PAGE_LIST
, Link
);
1814 MemoryProfileDescriptor
= ProfileBuffer
;
1815 MemoryProfileDescriptor
->Header
.Signature
= MEMORY_PROFILE_DESCRIPTOR_SIGNATURE
;
1816 MemoryProfileDescriptor
->Header
.Length
= sizeof (MEMORY_PROFILE_DESCRIPTOR
);
1817 MemoryProfileDescriptor
->Header
.Revision
= MEMORY_PROFILE_DESCRIPTOR_REVISION
;
1818 MemoryProfileDescriptor
->Address
= (PHYSICAL_ADDRESS
) (UINTN
) Pages
;
1819 MemoryProfileDescriptor
->Size
= EFI_PAGES_TO_SIZE (Pages
->NumberOfPages
);
1821 RemainingSize
-= sizeof (MEMORY_PROFILE_DESCRIPTOR
);
1822 ProfileBuffer
= (UINT8
*) ProfileBuffer
+ sizeof (MEMORY_PROFILE_DESCRIPTOR
);
1827 Offset
+= sizeof (MEMORY_PROFILE_DESCRIPTOR
);
1829 for (PoolListIndex
= 0; PoolListIndex
< MAX_POOL_INDEX
; PoolListIndex
++) {
1830 FreePoolList
= &mSmmPoolLists
[MAX_POOL_INDEX
- PoolListIndex
- 1];
1831 for (Node
= FreePoolList
->BackLink
;
1832 Node
!= FreePoolList
;
1833 Node
= Node
->BackLink
) {
1834 Pool
= BASE_CR (Node
, FREE_POOL_HEADER
, Link
);
1835 if (Pool
->Header
.Available
) {
1836 if (*ProfileOffset
< (Offset
+ sizeof (MEMORY_PROFILE_DESCRIPTOR
))) {
1837 if (RemainingSize
>= sizeof (MEMORY_PROFILE_DESCRIPTOR
)) {
1838 MemoryProfileDescriptor
= ProfileBuffer
;
1839 MemoryProfileDescriptor
->Header
.Signature
= MEMORY_PROFILE_DESCRIPTOR_SIGNATURE
;
1840 MemoryProfileDescriptor
->Header
.Length
= sizeof (MEMORY_PROFILE_DESCRIPTOR
);
1841 MemoryProfileDescriptor
->Header
.Revision
= MEMORY_PROFILE_DESCRIPTOR_REVISION
;
1842 MemoryProfileDescriptor
->Address
= (PHYSICAL_ADDRESS
) (UINTN
) Pool
;
1843 MemoryProfileDescriptor
->Size
= Pool
->Header
.Size
;
1845 RemainingSize
-= sizeof (MEMORY_PROFILE_DESCRIPTOR
);
1846 ProfileBuffer
= (UINT8
*) ProfileBuffer
+ sizeof (MEMORY_PROFILE_DESCRIPTOR
);
1851 Offset
+= sizeof (MEMORY_PROFILE_DESCRIPTOR
);
1856 if (*ProfileOffset
< (Offset
+ sizeof (MEMORY_PROFILE_MEMORY_RANGE
))) {
1857 if (RemainingSize
>= sizeof (MEMORY_PROFILE_MEMORY_RANGE
)) {
1858 MemoryRange
= ProfileBuffer
;
1859 MemoryRange
->Header
.Signature
= MEMORY_PROFILE_MEMORY_RANGE_SIGNATURE
;
1860 MemoryRange
->Header
.Length
= sizeof (MEMORY_PROFILE_MEMORY_RANGE
);
1861 MemoryRange
->Header
.Revision
= MEMORY_PROFILE_MEMORY_RANGE_REVISION
;
1862 MemoryRange
->MemoryRangeCount
= (UINT32
) mFullSmramRangeCount
;
1864 RemainingSize
-= sizeof (MEMORY_PROFILE_MEMORY_RANGE
);
1865 ProfileBuffer
= (UINT8
*) ProfileBuffer
+ sizeof (MEMORY_PROFILE_MEMORY_RANGE
);
1870 Offset
+= sizeof (MEMORY_PROFILE_MEMORY_RANGE
);
1871 for (Index
= 0; Index
< mFullSmramRangeCount
; Index
++) {
1872 if (*ProfileOffset
< (Offset
+ sizeof (MEMORY_PROFILE_DESCRIPTOR
))) {
1873 if (RemainingSize
>= sizeof (MEMORY_PROFILE_DESCRIPTOR
)) {
1874 MemoryProfileDescriptor
= ProfileBuffer
;
1875 MemoryProfileDescriptor
->Header
.Signature
= MEMORY_PROFILE_DESCRIPTOR_SIGNATURE
;
1876 MemoryProfileDescriptor
->Header
.Length
= sizeof (MEMORY_PROFILE_DESCRIPTOR
);
1877 MemoryProfileDescriptor
->Header
.Revision
= MEMORY_PROFILE_DESCRIPTOR_REVISION
;
1878 MemoryProfileDescriptor
->Address
= mFullSmramRanges
[Index
].PhysicalStart
;
1879 MemoryProfileDescriptor
->Size
= mFullSmramRanges
[Index
].PhysicalSize
;
1881 RemainingSize
-= sizeof (MEMORY_PROFILE_DESCRIPTOR
);
1882 ProfileBuffer
= (UINT8
*) ProfileBuffer
+ sizeof (MEMORY_PROFILE_DESCRIPTOR
);
1887 Offset
+= sizeof (MEMORY_PROFILE_DESCRIPTOR
);
1892 // On output, actual profile data size copied.
1894 *ProfileSize
-= RemainingSize
;
1896 // On output, next time profile buffer offset to copy.
1898 *ProfileOffset
= Offset
;
1902 Get memory profile data.
1904 @param[in] This The EDKII_SMM_MEMORY_PROFILE_PROTOCOL instance.
1905 @param[in, out] ProfileSize On entry, points to the size in bytes of the ProfileBuffer.
1906 On return, points to the size of the data returned in ProfileBuffer.
1907 @param[out] ProfileBuffer Profile buffer.
1909 @return EFI_SUCCESS Get the memory profile data successfully.
1910 @return EFI_UNSUPPORTED Memory profile is unsupported.
1911 @return EFI_BUFFER_TO_SMALL The ProfileSize is too small for the resulting data.
1912 ProfileSize is updated with the size required.
1917 SmramProfileProtocolGetData (
1918 IN EDKII_SMM_MEMORY_PROFILE_PROTOCOL
*This
,
1919 IN OUT UINT64
*ProfileSize
,
1920 OUT VOID
*ProfileBuffer
1925 MEMORY_PROFILE_CONTEXT_DATA
*ContextData
;
1926 BOOLEAN SmramProfileGettingStatus
;
1928 ContextData
= GetSmramProfileContext ();
1929 if (ContextData
== NULL
) {
1930 return EFI_UNSUPPORTED
;
1933 SmramProfileGettingStatus
= mSmramProfileGettingStatus
;
1934 mSmramProfileGettingStatus
= TRUE
;
1936 Size
= SmramProfileGetDataSize ();
1938 if (*ProfileSize
< Size
) {
1939 *ProfileSize
= Size
;
1940 mSmramProfileGettingStatus
= SmramProfileGettingStatus
;
1941 return EFI_BUFFER_TOO_SMALL
;
1945 SmramProfileCopyData (ProfileBuffer
, &Size
, &Offset
);
1946 *ProfileSize
= Size
;
1948 mSmramProfileGettingStatus
= SmramProfileGettingStatus
;
1953 Register image to memory profile.
1955 @param[in] This The EDKII_SMM_MEMORY_PROFILE_PROTOCOL instance.
1956 @param[in] FilePath File path of the image.
1957 @param[in] ImageBase Image base address.
1958 @param[in] ImageSize Image size.
1959 @param[in] FileType File type of the image.
1961 @return EFI_SUCCESS Register successfully.
1962 @return EFI_UNSUPPORTED Memory profile is unsupported,
1963 or memory profile for the image is not required.
1964 @return EFI_OUT_OF_RESOURCES No enough resource for this register.
1969 SmramProfileProtocolRegisterImage (
1970 IN EDKII_SMM_MEMORY_PROFILE_PROTOCOL
*This
,
1971 IN EFI_DEVICE_PATH_PROTOCOL
*FilePath
,
1972 IN PHYSICAL_ADDRESS ImageBase
,
1973 IN UINT64 ImageSize
,
1974 IN EFI_FV_FILETYPE FileType
1978 EFI_SMM_DRIVER_ENTRY DriverEntry
;
1979 VOID
*EntryPointInImage
;
1982 ZeroMem (&DriverEntry
, sizeof (DriverEntry
));
1983 Name
= GetFileNameFromFilePath (FilePath
);
1985 CopyMem (&DriverEntry
.FileName
, Name
, sizeof (EFI_GUID
));
1987 DriverEntry
.ImageBuffer
= ImageBase
;
1988 DriverEntry
.NumberOfPage
= EFI_SIZE_TO_PAGES ((UINTN
) ImageSize
);
1989 Status
= InternalPeCoffGetEntryPoint ((VOID
*) (UINTN
) DriverEntry
.ImageBuffer
, &EntryPointInImage
);
1990 ASSERT_EFI_ERROR (Status
);
1991 DriverEntry
.ImageEntryPoint
= (PHYSICAL_ADDRESS
) (UINTN
) EntryPointInImage
;
1993 return RegisterSmramProfileImage (&DriverEntry
, FALSE
);
1997 Unregister image from memory profile.
1999 @param[in] This The EDKII_SMM_MEMORY_PROFILE_PROTOCOL instance.
2000 @param[in] FilePath File path of the image.
2001 @param[in] ImageBase Image base address.
2002 @param[in] ImageSize Image size.
2004 @return EFI_SUCCESS Unregister successfully.
2005 @return EFI_UNSUPPORTED Memory profile is unsupported,
2006 or memory profile for the image is not required.
2007 @return EFI_NOT_FOUND The image is not found.
2012 SmramProfileProtocolUnregisterImage (
2013 IN EDKII_SMM_MEMORY_PROFILE_PROTOCOL
*This
,
2014 IN EFI_DEVICE_PATH_PROTOCOL
*FilePath
,
2015 IN PHYSICAL_ADDRESS ImageBase
,
2020 EFI_SMM_DRIVER_ENTRY DriverEntry
;
2021 VOID
*EntryPointInImage
;
2024 ZeroMem (&DriverEntry
, sizeof (DriverEntry
));
2025 Name
= GetFileNameFromFilePath (FilePath
);
2027 CopyMem (&DriverEntry
.FileName
, Name
, sizeof (EFI_GUID
));
2029 DriverEntry
.ImageBuffer
= ImageBase
;
2030 DriverEntry
.NumberOfPage
= EFI_SIZE_TO_PAGES ((UINTN
) ImageSize
);
2031 Status
= InternalPeCoffGetEntryPoint ((VOID
*) (UINTN
) DriverEntry
.ImageBuffer
, &EntryPointInImage
);
2032 ASSERT_EFI_ERROR (Status
);
2033 DriverEntry
.ImageEntryPoint
= (PHYSICAL_ADDRESS
) (UINTN
) EntryPointInImage
;
2035 return UnregisterSmramProfileImage (&DriverEntry
, FALSE
);
2039 Get memory profile recording state.
2041 @param[in] This The EDKII_SMM_MEMORY_PROFILE_PROTOCOL instance.
2042 @param[out] RecordingState Recording state.
2044 @return EFI_SUCCESS Memory profile recording state is returned.
2045 @return EFI_UNSUPPORTED Memory profile is unsupported.
2046 @return EFI_INVALID_PARAMETER RecordingState is NULL.
2051 SmramProfileProtocolGetRecordingState (
2052 IN EDKII_SMM_MEMORY_PROFILE_PROTOCOL
*This
,
2053 OUT BOOLEAN
*RecordingState
2056 MEMORY_PROFILE_CONTEXT_DATA
*ContextData
;
2058 ContextData
= GetSmramProfileContext ();
2059 if (ContextData
== NULL
) {
2060 return EFI_UNSUPPORTED
;
2063 if (RecordingState
== NULL
) {
2064 return EFI_INVALID_PARAMETER
;
2066 *RecordingState
= mSmramProfileRecordingEnable
;
2071 Set memory profile recording state.
2073 @param[in] This The EDKII_SMM_MEMORY_PROFILE_PROTOCOL instance.
2074 @param[in] RecordingState Recording state.
2076 @return EFI_SUCCESS Set memory profile recording state successfully.
2077 @return EFI_UNSUPPORTED Memory profile is unsupported.
2082 SmramProfileProtocolSetRecordingState (
2083 IN EDKII_SMM_MEMORY_PROFILE_PROTOCOL
*This
,
2084 IN BOOLEAN RecordingState
2087 MEMORY_PROFILE_CONTEXT_DATA
*ContextData
;
2089 ContextData
= GetSmramProfileContext ();
2090 if (ContextData
== NULL
) {
2091 return EFI_UNSUPPORTED
;
2094 mSmramProfileRecordingEnable
= RecordingState
;
2099 Record memory profile of multilevel caller.
2101 @param[in] This The EDKII_SMM_MEMORY_PROFILE_PROTOCOL instance.
2102 @param[in] CallerAddress Address of caller.
2103 @param[in] Action Memory profile action.
2104 @param[in] MemoryType Memory type.
2105 EfiMaxMemoryType means the MemoryType is unknown.
2106 @param[in] Buffer Buffer address.
2107 @param[in] Size Buffer size.
2108 @param[in] ActionString String for memory profile action.
2109 Only needed for user defined allocate action.
2111 @return EFI_SUCCESS Memory profile is updated.
2112 @return EFI_UNSUPPORTED Memory profile is unsupported,
2113 or memory profile for the image is not required,
2114 or memory profile for the memory type is not required.
2115 @return EFI_ACCESS_DENIED It is during memory profile data getting.
2116 @return EFI_ABORTED Memory profile recording is not enabled.
2117 @return EFI_OUT_OF_RESOURCES No enough resource to update memory profile for allocate action.
2118 @return EFI_NOT_FOUND No matched allocate info found for free action.
2123 SmramProfileProtocolRecord (
2124 IN EDKII_SMM_MEMORY_PROFILE_PROTOCOL
*This
,
2125 IN PHYSICAL_ADDRESS CallerAddress
,
2126 IN MEMORY_PROFILE_ACTION Action
,
2127 IN EFI_MEMORY_TYPE MemoryType
,
2130 IN CHAR8
*ActionString OPTIONAL
2133 return SmmCoreUpdateProfile (CallerAddress
, Action
, MemoryType
, Size
, Buffer
, ActionString
);
2137 SMRAM profile handler to get profile info.
2139 @param SmramProfileParameterGetInfo The parameter of SMM profile get size.
2143 SmramProfileHandlerGetInfo (
2144 IN SMRAM_PROFILE_PARAMETER_GET_PROFILE_INFO
*SmramProfileParameterGetInfo
2147 MEMORY_PROFILE_CONTEXT_DATA
*ContextData
;
2148 BOOLEAN SmramProfileGettingStatus
;
2150 ContextData
= GetSmramProfileContext ();
2151 if (ContextData
== NULL
) {
2155 SmramProfileGettingStatus
= mSmramProfileGettingStatus
;
2156 mSmramProfileGettingStatus
= TRUE
;
2158 SmramProfileParameterGetInfo
->ProfileSize
= SmramProfileGetDataSize();
2159 SmramProfileParameterGetInfo
->Header
.ReturnStatus
= 0;
2161 mSmramProfileGettingStatus
= SmramProfileGettingStatus
;
2165 SMRAM profile handler to get profile data.
2167 @param SmramProfileParameterGetData The parameter of SMM profile get data.
2171 SmramProfileHandlerGetData (
2172 IN SMRAM_PROFILE_PARAMETER_GET_PROFILE_DATA
*SmramProfileParameterGetData
2176 UINT64 ProfileOffset
;
2177 SMRAM_PROFILE_PARAMETER_GET_PROFILE_DATA SmramProfileGetData
;
2178 MEMORY_PROFILE_CONTEXT_DATA
*ContextData
;
2179 BOOLEAN SmramProfileGettingStatus
;
2181 ContextData
= GetSmramProfileContext ();
2182 if (ContextData
== NULL
) {
2186 SmramProfileGettingStatus
= mSmramProfileGettingStatus
;
2187 mSmramProfileGettingStatus
= TRUE
;
2190 CopyMem (&SmramProfileGetData
, SmramProfileParameterGetData
, sizeof (SmramProfileGetData
));
2192 ProfileSize
= SmramProfileGetDataSize();
2197 if (!SmmIsBufferOutsideSmmValid ((UINTN
) SmramProfileGetData
.ProfileBuffer
, (UINTN
) ProfileSize
)) {
2198 DEBUG ((EFI_D_ERROR
, "SmramProfileHandlerGetData: SMM ProfileBuffer in SMRAM or overflow!\n"));
2199 SmramProfileParameterGetData
->ProfileSize
= ProfileSize
;
2200 SmramProfileParameterGetData
->Header
.ReturnStatus
= (UINT64
) (INT64
) (INTN
) EFI_ACCESS_DENIED
;
2204 if (SmramProfileGetData
.ProfileSize
< ProfileSize
) {
2205 SmramProfileParameterGetData
->ProfileSize
= ProfileSize
;
2206 SmramProfileParameterGetData
->Header
.ReturnStatus
= (UINT64
) (INT64
) (INTN
) EFI_BUFFER_TOO_SMALL
;
2211 SmramProfileCopyData ((VOID
*) (UINTN
) SmramProfileGetData
.ProfileBuffer
, &ProfileSize
, &ProfileOffset
);
2212 SmramProfileParameterGetData
->ProfileSize
= ProfileSize
;
2213 SmramProfileParameterGetData
->Header
.ReturnStatus
= 0;
2216 mSmramProfileGettingStatus
= SmramProfileGettingStatus
;
2220 SMRAM profile handler to get profile data by offset.
2222 @param SmramProfileParameterGetDataByOffset The parameter of SMM profile get data by offset.
2226 SmramProfileHandlerGetDataByOffset (
2227 IN SMRAM_PROFILE_PARAMETER_GET_PROFILE_DATA_BY_OFFSET
*SmramProfileParameterGetDataByOffset
2230 SMRAM_PROFILE_PARAMETER_GET_PROFILE_DATA_BY_OFFSET SmramProfileGetDataByOffset
;
2231 MEMORY_PROFILE_CONTEXT_DATA
*ContextData
;
2232 BOOLEAN SmramProfileGettingStatus
;
2234 ContextData
= GetSmramProfileContext ();
2235 if (ContextData
== NULL
) {
2239 SmramProfileGettingStatus
= mSmramProfileGettingStatus
;
2240 mSmramProfileGettingStatus
= TRUE
;
2243 CopyMem (&SmramProfileGetDataByOffset
, SmramProfileParameterGetDataByOffset
, sizeof (SmramProfileGetDataByOffset
));
2248 if (!SmmIsBufferOutsideSmmValid ((UINTN
) SmramProfileGetDataByOffset
.ProfileBuffer
, (UINTN
) SmramProfileGetDataByOffset
.ProfileSize
)) {
2249 DEBUG ((EFI_D_ERROR
, "SmramProfileHandlerGetDataByOffset: SMM ProfileBuffer in SMRAM or overflow!\n"));
2250 SmramProfileParameterGetDataByOffset
->Header
.ReturnStatus
= (UINT64
) (INT64
) (INTN
) EFI_ACCESS_DENIED
;
2254 SmramProfileCopyData ((VOID
*) (UINTN
) SmramProfileGetDataByOffset
.ProfileBuffer
, &SmramProfileGetDataByOffset
.ProfileSize
, &SmramProfileGetDataByOffset
.ProfileOffset
);
2255 CopyMem (SmramProfileParameterGetDataByOffset
, &SmramProfileGetDataByOffset
, sizeof (SmramProfileGetDataByOffset
));
2256 SmramProfileParameterGetDataByOffset
->Header
.ReturnStatus
= 0;
2259 mSmramProfileGettingStatus
= SmramProfileGettingStatus
;
2263 SMRAM profile handler to register SMM image.
2265 @param SmramProfileParameterRegisterImage The parameter of SMM profile register image.
2269 SmramProfileHandlerRegisterImage (
2270 IN SMRAM_PROFILE_PARAMETER_REGISTER_IMAGE
*SmramProfileParameterRegisterImage
2274 EFI_SMM_DRIVER_ENTRY DriverEntry
;
2275 VOID
*EntryPointInImage
;
2277 ZeroMem (&DriverEntry
, sizeof (DriverEntry
));
2278 CopyMem (&DriverEntry
.FileName
, &SmramProfileParameterRegisterImage
->FileName
, sizeof(EFI_GUID
));
2279 DriverEntry
.ImageBuffer
= SmramProfileParameterRegisterImage
->ImageBuffer
;
2280 DriverEntry
.NumberOfPage
= (UINTN
) SmramProfileParameterRegisterImage
->NumberOfPage
;
2281 Status
= InternalPeCoffGetEntryPoint ((VOID
*) (UINTN
) DriverEntry
.ImageBuffer
, &EntryPointInImage
);
2282 ASSERT_EFI_ERROR (Status
);
2283 DriverEntry
.ImageEntryPoint
= (PHYSICAL_ADDRESS
) (UINTN
) EntryPointInImage
;
2285 Status
= RegisterSmramProfileImage (&DriverEntry
, FALSE
);
2286 if (!EFI_ERROR (Status
)) {
2287 SmramProfileParameterRegisterImage
->Header
.ReturnStatus
= 0;
2292 SMRAM profile handler to unregister SMM image.
2294 @param SmramProfileParameterUnregisterImage The parameter of SMM profile unregister image.
2298 SmramProfileHandlerUnregisterImage (
2299 IN SMRAM_PROFILE_PARAMETER_UNREGISTER_IMAGE
*SmramProfileParameterUnregisterImage
2303 EFI_SMM_DRIVER_ENTRY DriverEntry
;
2304 VOID
*EntryPointInImage
;
2306 ZeroMem (&DriverEntry
, sizeof (DriverEntry
));
2307 CopyMem (&DriverEntry
.FileName
, &SmramProfileParameterUnregisterImage
->FileName
, sizeof (EFI_GUID
));
2308 DriverEntry
.ImageBuffer
= SmramProfileParameterUnregisterImage
->ImageBuffer
;
2309 DriverEntry
.NumberOfPage
= (UINTN
) SmramProfileParameterUnregisterImage
->NumberOfPage
;
2310 Status
= InternalPeCoffGetEntryPoint ((VOID
*) (UINTN
) DriverEntry
.ImageBuffer
, &EntryPointInImage
);
2311 ASSERT_EFI_ERROR (Status
);
2312 DriverEntry
.ImageEntryPoint
= (PHYSICAL_ADDRESS
) (UINTN
) EntryPointInImage
;
2314 Status
= UnregisterSmramProfileImage (&DriverEntry
, FALSE
);
2315 if (!EFI_ERROR (Status
)) {
2316 SmramProfileParameterUnregisterImage
->Header
.ReturnStatus
= 0;
2321 Dispatch function for a Software SMI handler.
2323 Caution: This function may receive untrusted input.
2324 Communicate buffer and buffer size are external input, so this function will do basic validation.
2326 @param DispatchHandle The unique handle assigned to this handler by SmiHandlerRegister().
2327 @param Context Points to an optional handler context which was specified when the
2328 handler was registered.
2329 @param CommBuffer A pointer to a collection of data in memory that will
2330 be conveyed from a non-SMM environment into an SMM environment.
2331 @param CommBufferSize The size of the CommBuffer.
2333 @retval EFI_SUCCESS Command is handled successfully.
2338 SmramProfileHandler (
2339 IN EFI_HANDLE DispatchHandle
,
2340 IN CONST VOID
*Context OPTIONAL
,
2341 IN OUT VOID
*CommBuffer OPTIONAL
,
2342 IN OUT UINTN
*CommBufferSize OPTIONAL
2345 SMRAM_PROFILE_PARAMETER_HEADER
*SmramProfileParameterHeader
;
2346 UINTN TempCommBufferSize
;
2347 SMRAM_PROFILE_PARAMETER_RECORDING_STATE
*ParameterRecordingState
;
2349 DEBUG ((EFI_D_ERROR
, "SmramProfileHandler Enter\n"));
2352 // If input is invalid, stop processing this SMI
2354 if (CommBuffer
== NULL
|| CommBufferSize
== NULL
) {
2358 TempCommBufferSize
= *CommBufferSize
;
2360 if (TempCommBufferSize
< sizeof (SMRAM_PROFILE_PARAMETER_HEADER
)) {
2361 DEBUG ((EFI_D_ERROR
, "SmramProfileHandler: SMM communication buffer size invalid!\n"));
2365 if (mSmramReadyToLock
&& !SmmIsBufferOutsideSmmValid ((UINTN
)CommBuffer
, TempCommBufferSize
)) {
2366 DEBUG ((EFI_D_ERROR
, "SmramProfileHandler: SMM communication buffer in SMRAM or overflow!\n"));
2370 SmramProfileParameterHeader
= (SMRAM_PROFILE_PARAMETER_HEADER
*) ((UINTN
) CommBuffer
);
2372 SmramProfileParameterHeader
->ReturnStatus
= (UINT64
)-1;
2374 if (GetSmramProfileContext () == NULL
) {
2375 SmramProfileParameterHeader
->ReturnStatus
= (UINT64
) (INT64
) (INTN
) EFI_UNSUPPORTED
;
2379 switch (SmramProfileParameterHeader
->Command
) {
2380 case SMRAM_PROFILE_COMMAND_GET_PROFILE_INFO
:
2381 DEBUG ((EFI_D_ERROR
, "SmramProfileHandlerGetInfo\n"));
2382 if (TempCommBufferSize
!= sizeof (SMRAM_PROFILE_PARAMETER_GET_PROFILE_INFO
)) {
2383 DEBUG ((EFI_D_ERROR
, "SmramProfileHandler: SMM communication buffer size invalid!\n"));
2386 SmramProfileHandlerGetInfo ((SMRAM_PROFILE_PARAMETER_GET_PROFILE_INFO
*) (UINTN
) CommBuffer
);
2388 case SMRAM_PROFILE_COMMAND_GET_PROFILE_DATA
:
2389 DEBUG ((EFI_D_ERROR
, "SmramProfileHandlerGetData\n"));
2390 if (TempCommBufferSize
!= sizeof (SMRAM_PROFILE_PARAMETER_GET_PROFILE_DATA
)) {
2391 DEBUG ((EFI_D_ERROR
, "SmramProfileHandler: SMM communication buffer size invalid!\n"));
2394 SmramProfileHandlerGetData ((SMRAM_PROFILE_PARAMETER_GET_PROFILE_DATA
*) (UINTN
) CommBuffer
);
2396 case SMRAM_PROFILE_COMMAND_GET_PROFILE_DATA_BY_OFFSET
:
2397 DEBUG ((EFI_D_ERROR
, "SmramProfileHandlerGetDataByOffset\n"));
2398 if (TempCommBufferSize
!= sizeof (SMRAM_PROFILE_PARAMETER_GET_PROFILE_DATA_BY_OFFSET
)) {
2399 DEBUG ((EFI_D_ERROR
, "SmramProfileHandler: SMM communication buffer size invalid!\n"));
2402 SmramProfileHandlerGetDataByOffset ((SMRAM_PROFILE_PARAMETER_GET_PROFILE_DATA_BY_OFFSET
*) (UINTN
) CommBuffer
);
2404 case SMRAM_PROFILE_COMMAND_REGISTER_IMAGE
:
2405 DEBUG ((EFI_D_ERROR
, "SmramProfileHandlerRegisterImage\n"));
2406 if (TempCommBufferSize
!= sizeof (SMRAM_PROFILE_PARAMETER_REGISTER_IMAGE
)) {
2407 DEBUG ((EFI_D_ERROR
, "SmramProfileHandler: SMM communication buffer size invalid!\n"));
2410 if (mSmramReadyToLock
) {
2413 SmramProfileHandlerRegisterImage ((SMRAM_PROFILE_PARAMETER_REGISTER_IMAGE
*) (UINTN
) CommBuffer
);
2415 case SMRAM_PROFILE_COMMAND_UNREGISTER_IMAGE
:
2416 DEBUG ((EFI_D_ERROR
, "SmramProfileHandlerUnregisterImage\n"));
2417 if (TempCommBufferSize
!= sizeof (SMRAM_PROFILE_PARAMETER_UNREGISTER_IMAGE
)) {
2418 DEBUG ((EFI_D_ERROR
, "SmramProfileHandler: SMM communication buffer size invalid!\n"));
2421 if (mSmramReadyToLock
) {
2424 SmramProfileHandlerUnregisterImage ((SMRAM_PROFILE_PARAMETER_UNREGISTER_IMAGE
*) (UINTN
) CommBuffer
);
2426 case SMRAM_PROFILE_COMMAND_GET_RECORDING_STATE
:
2427 DEBUG ((EFI_D_ERROR
, "SmramProfileHandlerGetRecordingState\n"));
2428 if (TempCommBufferSize
!= sizeof (SMRAM_PROFILE_PARAMETER_RECORDING_STATE
)) {
2429 DEBUG ((EFI_D_ERROR
, "SmramProfileHandler: SMM communication buffer size invalid!\n"));
2432 ParameterRecordingState
= (SMRAM_PROFILE_PARAMETER_RECORDING_STATE
*) (UINTN
) CommBuffer
;
2433 ParameterRecordingState
->RecordingState
= mSmramProfileRecordingEnable
;
2434 ParameterRecordingState
->Header
.ReturnStatus
= 0;
2436 case SMRAM_PROFILE_COMMAND_SET_RECORDING_STATE
:
2437 DEBUG ((EFI_D_ERROR
, "SmramProfileHandlerSetRecordingState\n"));
2438 if (TempCommBufferSize
!= sizeof (SMRAM_PROFILE_PARAMETER_RECORDING_STATE
)) {
2439 DEBUG ((EFI_D_ERROR
, "SmramProfileHandler: SMM communication buffer size invalid!\n"));
2442 ParameterRecordingState
= (SMRAM_PROFILE_PARAMETER_RECORDING_STATE
*) (UINTN
) CommBuffer
;
2443 mSmramProfileRecordingEnable
= ParameterRecordingState
->RecordingState
;
2444 ParameterRecordingState
->Header
.ReturnStatus
= 0;
2451 DEBUG ((EFI_D_ERROR
, "SmramProfileHandler Exit\n"));
2457 Register SMRAM profile handler.
2461 RegisterSmramProfileHandler (
2466 EFI_HANDLE DispatchHandle
;
2468 if (!IS_SMRAM_PROFILE_ENABLED
) {
2472 Status
= SmiHandlerRegister (
2473 SmramProfileHandler
,
2474 &gEdkiiMemoryProfileGuid
,
2477 ASSERT_EFI_ERROR (Status
);
2480 ////////////////////
2492 MEMORY_PROFILE_CONTEXT_DATA
*ContextData
;
2493 BOOLEAN SmramProfileGettingStatus
;
2495 ContextData
= GetSmramProfileContext ();
2496 if (ContextData
== NULL
) {
2500 SmramProfileGettingStatus
= mSmramProfileGettingStatus
;
2501 mSmramProfileGettingStatus
= TRUE
;
2503 DEBUG ((EFI_D_INFO
, "FullSmramRange address - 0x%08x\n", mFullSmramRanges
));
2505 DEBUG ((EFI_D_INFO
, "======= SmramProfile begin =======\n"));
2507 DEBUG ((EFI_D_INFO
, "FullSmramRange:\n"));
2508 for (Index
= 0; Index
< mFullSmramRangeCount
; Index
++) {
2509 DEBUG ((EFI_D_INFO
, " FullSmramRange (0x%x)\n", Index
));
2510 DEBUG ((EFI_D_INFO
, " PhysicalStart - 0x%016lx\n", mFullSmramRanges
[Index
].PhysicalStart
));
2511 DEBUG ((EFI_D_INFO
, " CpuStart - 0x%016lx\n", mFullSmramRanges
[Index
].CpuStart
));
2512 DEBUG ((EFI_D_INFO
, " PhysicalSize - 0x%016lx\n", mFullSmramRanges
[Index
].PhysicalSize
));
2513 DEBUG ((EFI_D_INFO
, " RegionState - 0x%016lx\n", mFullSmramRanges
[Index
].RegionState
));
2516 DEBUG ((EFI_D_INFO
, "======= SmramProfile end =======\n"));
2518 mSmramProfileGettingStatus
= SmramProfileGettingStatus
;
2522 Dump SMRAM free page list.
2530 LIST_ENTRY
*FreePageList
;
2532 FREE_PAGE_LIST
*Pages
;
2534 MEMORY_PROFILE_CONTEXT_DATA
*ContextData
;
2535 BOOLEAN SmramProfileGettingStatus
;
2537 ContextData
= GetSmramProfileContext ();
2538 if (ContextData
== NULL
) {
2542 SmramProfileGettingStatus
= mSmramProfileGettingStatus
;
2543 mSmramProfileGettingStatus
= TRUE
;
2545 DEBUG ((EFI_D_INFO
, "======= SmramProfile begin =======\n"));
2547 DEBUG ((EFI_D_INFO
, "FreePagesList:\n"));
2548 FreePageList
= &mSmmMemoryMap
;
2549 for (Node
= FreePageList
->BackLink
, Index
= 0;
2550 Node
!= FreePageList
;
2551 Node
= Node
->BackLink
, Index
++) {
2552 Pages
= BASE_CR (Node
, FREE_PAGE_LIST
, Link
);
2553 DEBUG ((EFI_D_INFO
, " Index - 0x%x\n", Index
));
2554 DEBUG ((EFI_D_INFO
, " PhysicalStart - 0x%016lx\n", (PHYSICAL_ADDRESS
) (UINTN
) Pages
));
2555 DEBUG ((EFI_D_INFO
, " NumberOfPages - 0x%08x\n", Pages
->NumberOfPages
));
2558 DEBUG ((EFI_D_INFO
, "======= SmramProfile end =======\n"));
2560 mSmramProfileGettingStatus
= SmramProfileGettingStatus
;
2564 Dump SMRAM free pool list.
2572 LIST_ENTRY
*FreePoolList
;
2574 FREE_POOL_HEADER
*Pool
;
2576 UINTN PoolListIndex
;
2577 MEMORY_PROFILE_CONTEXT_DATA
*ContextData
;
2578 BOOLEAN SmramProfileGettingStatus
;
2580 ContextData
= GetSmramProfileContext ();
2581 if (ContextData
== NULL
) {
2585 SmramProfileGettingStatus
= mSmramProfileGettingStatus
;
2586 mSmramProfileGettingStatus
= TRUE
;
2588 DEBUG ((EFI_D_INFO
, "======= SmramProfile begin =======\n"));
2590 for (PoolListIndex
= 0; PoolListIndex
< MAX_POOL_INDEX
; PoolListIndex
++) {
2591 DEBUG ((EFI_D_INFO
, "FreePoolList (%d):\n", PoolListIndex
));
2592 FreePoolList
= &mSmmPoolLists
[PoolListIndex
];
2593 for (Node
= FreePoolList
->BackLink
, Index
= 0;
2594 Node
!= FreePoolList
;
2595 Node
= Node
->BackLink
, Index
++) {
2596 Pool
= BASE_CR (Node
, FREE_POOL_HEADER
, Link
);
2597 DEBUG ((EFI_D_INFO
, " Index - 0x%x\n", Index
));
2598 DEBUG ((EFI_D_INFO
, " PhysicalStart - 0x%016lx\n", (PHYSICAL_ADDRESS
) (UINTN
) Pool
));
2599 DEBUG ((EFI_D_INFO
, " Size - 0x%08x\n", Pool
->Header
.Size
));
2600 DEBUG ((EFI_D_INFO
, " Available - 0x%02x\n", Pool
->Header
.Available
));
2604 DEBUG ((EFI_D_INFO
, "======= SmramProfile end =======\n"));
2606 mSmramProfileGettingStatus
= SmramProfileGettingStatus
;
2609 GLOBAL_REMOVE_IF_UNREFERENCED CHAR8
*mSmmActionString
[] = {
2611 "gSmst->SmmAllocatePages",
2612 "gSmst->SmmFreePages",
2613 "gSmst->SmmAllocatePool",
2614 "gSmst->SmmFreePool",
2618 MEMORY_PROFILE_ACTION Action
;
2622 ACTION_STRING mExtActionString
[] = {
2623 {MEMORY_PROFILE_ACTION_LIB_ALLOCATE_PAGES
, "Lib:AllocatePages"},
2624 {MEMORY_PROFILE_ACTION_LIB_ALLOCATE_RUNTIME_PAGES
, "Lib:AllocateRuntimePages"},
2625 {MEMORY_PROFILE_ACTION_LIB_ALLOCATE_RESERVED_PAGES
, "Lib:AllocateReservedPages"},
2626 {MEMORY_PROFILE_ACTION_LIB_FREE_PAGES
, "Lib:FreePages"},
2627 {MEMORY_PROFILE_ACTION_LIB_ALLOCATE_ALIGNED_PAGES
, "Lib:AllocateAlignedPages"},
2628 {MEMORY_PROFILE_ACTION_LIB_ALLOCATE_ALIGNED_RUNTIME_PAGES
, "Lib:AllocateAlignedRuntimePages"},
2629 {MEMORY_PROFILE_ACTION_LIB_ALLOCATE_ALIGNED_RESERVED_PAGES
, "Lib:AllocateAlignedReservedPages"},
2630 {MEMORY_PROFILE_ACTION_LIB_FREE_ALIGNED_PAGES
, "Lib:FreeAlignedPages"},
2631 {MEMORY_PROFILE_ACTION_LIB_ALLOCATE_POOL
, "Lib:AllocatePool"},
2632 {MEMORY_PROFILE_ACTION_LIB_ALLOCATE_RUNTIME_POOL
, "Lib:AllocateRuntimePool"},
2633 {MEMORY_PROFILE_ACTION_LIB_ALLOCATE_RESERVED_POOL
, "Lib:AllocateReservedPool"},
2634 {MEMORY_PROFILE_ACTION_LIB_FREE_POOL
, "Lib:FreePool"},
2635 {MEMORY_PROFILE_ACTION_LIB_ALLOCATE_ZERO_POOL
, "Lib:AllocateZeroPool"},
2636 {MEMORY_PROFILE_ACTION_LIB_ALLOCATE_RUNTIME_ZERO_POOL
, "Lib:AllocateRuntimeZeroPool"},
2637 {MEMORY_PROFILE_ACTION_LIB_ALLOCATE_RESERVED_ZERO_POOL
, "Lib:AllocateReservedZeroPool"},
2638 {MEMORY_PROFILE_ACTION_LIB_ALLOCATE_COPY_POOL
, "Lib:AllocateCopyPool"},
2639 {MEMORY_PROFILE_ACTION_LIB_ALLOCATE_RUNTIME_COPY_POOL
, "Lib:AllocateRuntimeCopyPool"},
2640 {MEMORY_PROFILE_ACTION_LIB_ALLOCATE_RESERVED_COPY_POOL
, "Lib:AllocateReservedCopyPool"},
2641 {MEMORY_PROFILE_ACTION_LIB_REALLOCATE_POOL
, "Lib:ReallocatePool"},
2642 {MEMORY_PROFILE_ACTION_LIB_REALLOCATE_RUNTIME_POOL
, "Lib:ReallocateRuntimePool"},
2643 {MEMORY_PROFILE_ACTION_LIB_REALLOCATE_RESERVED_POOL
, "Lib:ReallocateReservedPool"},
2646 GLOBAL_REMOVE_IF_UNREFERENCED CHAR8 mUserDefinedActionString
[] = {"UserDefined-0x80000000"};
2649 EFI_MEMORY_TYPE MemoryType
;
2650 CHAR8
*MemoryTypeStr
;
2651 } PROFILE_MEMORY_TYPE_STRING
;
2653 GLOBAL_REMOVE_IF_UNREFERENCED PROFILE_MEMORY_TYPE_STRING mMemoryTypeString
[] = {
2654 {EfiRuntimeServicesCode
, "EfiRuntimeServicesCode"},
2655 {EfiRuntimeServicesData
, "EfiRuntimeServicesData"}
2659 Memory type to string.
2661 @param[in] MemoryType Memory type.
2663 @return Pointer to string.
2667 ProfileMemoryTypeToStr (
2668 IN EFI_MEMORY_TYPE MemoryType
2672 for (Index
= 0; Index
< sizeof (mMemoryTypeString
) / sizeof (mMemoryTypeString
[0]); Index
++) {
2673 if (mMemoryTypeString
[Index
].MemoryType
== MemoryType
) {
2674 return mMemoryTypeString
[Index
].MemoryTypeStr
;
2678 return "UnexpectedMemoryType";
2684 @param[in] Action Profile action.
2686 @return Pointer to string.
2690 ProfileActionToStr (
2691 IN MEMORY_PROFILE_ACTION Action
2695 UINTN ActionStringCount
;
2696 CHAR8
**ActionString
;
2698 ActionString
= mSmmActionString
;
2699 ActionStringCount
= sizeof (mSmmActionString
) / sizeof (mSmmActionString
[0]);
2701 if ((UINTN
) (UINT32
) Action
< ActionStringCount
) {
2702 return ActionString
[Action
];
2704 for (Index
= 0; Index
< sizeof (mExtActionString
) / sizeof (mExtActionString
[0]); Index
++) {
2705 if (mExtActionString
[Index
].Action
== Action
) {
2706 return mExtActionString
[Index
].String
;
2710 return ActionString
[0];
2722 MEMORY_PROFILE_CONTEXT
*Context
;
2723 MEMORY_PROFILE_DRIVER_INFO
*DriverInfo
;
2724 MEMORY_PROFILE_ALLOC_INFO
*AllocInfo
;
2725 MEMORY_PROFILE_CONTEXT_DATA
*ContextData
;
2726 MEMORY_PROFILE_DRIVER_INFO_DATA
*DriverInfoData
;
2727 MEMORY_PROFILE_ALLOC_INFO_DATA
*AllocInfoData
;
2728 LIST_ENTRY
*SmramDriverInfoList
;
2730 LIST_ENTRY
*DriverLink
;
2731 LIST_ENTRY
*AllocInfoList
;
2733 LIST_ENTRY
*AllocLink
;
2734 BOOLEAN SmramProfileGettingStatus
;
2737 ContextData
= GetSmramProfileContext ();
2738 if (ContextData
== NULL
) {
2742 SmramProfileGettingStatus
= mSmramProfileGettingStatus
;
2743 mSmramProfileGettingStatus
= TRUE
;
2745 Context
= &ContextData
->Context
;
2746 DEBUG ((EFI_D_INFO
, "======= SmramProfile begin =======\n"));
2747 DEBUG ((EFI_D_INFO
, "MEMORY_PROFILE_CONTEXT\n"));
2749 DEBUG ((EFI_D_INFO
, " CurrentTotalUsage - 0x%016lx\n", Context
->CurrentTotalUsage
));
2750 DEBUG ((EFI_D_INFO
, " PeakTotalUsage - 0x%016lx\n", Context
->PeakTotalUsage
));
2751 for (TypeIndex
= 0; TypeIndex
< sizeof (Context
->CurrentTotalUsageByType
) / sizeof (Context
->CurrentTotalUsageByType
[0]); TypeIndex
++) {
2752 if ((Context
->CurrentTotalUsageByType
[TypeIndex
] != 0) ||
2753 (Context
->PeakTotalUsageByType
[TypeIndex
] != 0)) {
2754 DEBUG ((EFI_D_INFO
, " CurrentTotalUsage[0x%02x] - 0x%016lx (%a)\n", TypeIndex
, Context
->CurrentTotalUsageByType
[TypeIndex
], ProfileMemoryTypeToStr (TypeIndex
)));
2755 DEBUG ((EFI_D_INFO
, " PeakTotalUsage[0x%02x] - 0x%016lx (%a)\n", TypeIndex
, Context
->PeakTotalUsageByType
[TypeIndex
], ProfileMemoryTypeToStr (TypeIndex
)));
2758 DEBUG ((EFI_D_INFO
, " TotalImageSize - 0x%016lx\n", Context
->TotalImageSize
));
2759 DEBUG ((EFI_D_INFO
, " ImageCount - 0x%08x\n", Context
->ImageCount
));
2760 DEBUG ((EFI_D_INFO
, " SequenceCount - 0x%08x\n", Context
->SequenceCount
));
2762 SmramDriverInfoList
= ContextData
->DriverInfoList
;
2763 for (DriverLink
= SmramDriverInfoList
->ForwardLink
, DriverIndex
= 0;
2764 DriverLink
!= SmramDriverInfoList
;
2765 DriverLink
= DriverLink
->ForwardLink
, DriverIndex
++) {
2766 DriverInfoData
= CR (
2768 MEMORY_PROFILE_DRIVER_INFO_DATA
,
2770 MEMORY_PROFILE_DRIVER_INFO_SIGNATURE
2772 DriverInfo
= &DriverInfoData
->DriverInfo
;
2773 DEBUG ((EFI_D_INFO
, " MEMORY_PROFILE_DRIVER_INFO (0x%x)\n", DriverIndex
));
2774 DEBUG ((EFI_D_INFO
, " FileName - %g\n", &DriverInfo
->FileName
));
2775 DEBUG ((EFI_D_INFO
, " ImageBase - 0x%016lx\n", DriverInfo
->ImageBase
));
2776 DEBUG ((EFI_D_INFO
, " ImageSize - 0x%016lx\n", DriverInfo
->ImageSize
));
2777 DEBUG ((EFI_D_INFO
, " EntryPoint - 0x%016lx\n", DriverInfo
->EntryPoint
));
2778 DEBUG ((EFI_D_INFO
, " ImageSubsystem - 0x%04x\n", DriverInfo
->ImageSubsystem
));
2779 DEBUG ((EFI_D_INFO
, " FileType - 0x%02x\n", DriverInfo
->FileType
));
2780 DEBUG ((EFI_D_INFO
, " CurrentUsage - 0x%016lx\n", DriverInfo
->CurrentUsage
));
2781 DEBUG ((EFI_D_INFO
, " PeakUsage - 0x%016lx\n", DriverInfo
->PeakUsage
));
2782 for (TypeIndex
= 0; TypeIndex
< sizeof (DriverInfo
->CurrentUsageByType
) / sizeof (DriverInfo
->CurrentUsageByType
[0]); TypeIndex
++) {
2783 if ((DriverInfo
->CurrentUsageByType
[TypeIndex
] != 0) ||
2784 (DriverInfo
->PeakUsageByType
[TypeIndex
] != 0)) {
2785 DEBUG ((EFI_D_INFO
, " CurrentUsage[0x%02x] - 0x%016lx (%a)\n", TypeIndex
, DriverInfo
->CurrentUsageByType
[TypeIndex
], ProfileMemoryTypeToStr (TypeIndex
)));
2786 DEBUG ((EFI_D_INFO
, " PeakUsage[0x%02x] - 0x%016lx (%a)\n", TypeIndex
, DriverInfo
->PeakUsageByType
[TypeIndex
], ProfileMemoryTypeToStr (TypeIndex
)));
2789 DEBUG ((EFI_D_INFO
, " AllocRecordCount - 0x%08x\n", DriverInfo
->AllocRecordCount
));
2791 AllocInfoList
= DriverInfoData
->AllocInfoList
;
2792 for (AllocLink
= AllocInfoList
->ForwardLink
, AllocIndex
= 0;
2793 AllocLink
!= AllocInfoList
;
2794 AllocLink
= AllocLink
->ForwardLink
, AllocIndex
++) {
2795 AllocInfoData
= CR (
2797 MEMORY_PROFILE_ALLOC_INFO_DATA
,
2799 MEMORY_PROFILE_ALLOC_INFO_SIGNATURE
2801 AllocInfo
= &AllocInfoData
->AllocInfo
;
2802 DEBUG ((EFI_D_INFO
, " MEMORY_PROFILE_ALLOC_INFO (0x%x)\n", AllocIndex
));
2803 DEBUG ((EFI_D_INFO
, " CallerAddress - 0x%016lx (Offset: 0x%08x)\n", AllocInfo
->CallerAddress
, AllocInfo
->CallerAddress
- DriverInfo
->ImageBase
));
2804 DEBUG ((EFI_D_INFO
, " SequenceId - 0x%08x\n", AllocInfo
->SequenceId
));
2805 if ((AllocInfo
->Action
& MEMORY_PROFILE_ACTION_USER_DEFINED_MASK
) != 0) {
2806 if (AllocInfoData
->ActionString
!= NULL
) {
2807 DEBUG ((EFI_D_INFO
, " Action - 0x%08x (%a)\n", AllocInfo
->Action
, AllocInfoData
->ActionString
));
2809 DEBUG ((EFI_D_INFO
, " Action - 0x%08x (UserDefined-0x%08x)\n", AllocInfo
->Action
, AllocInfo
->Action
));
2812 DEBUG ((EFI_D_INFO
, " Action - 0x%08x (%a)\n", AllocInfo
->Action
, ProfileActionToStr (AllocInfo
->Action
)));
2814 DEBUG ((EFI_D_INFO
, " MemoryType - 0x%08x (%a)\n", AllocInfo
->MemoryType
, ProfileMemoryTypeToStr (AllocInfo
->MemoryType
)));
2815 DEBUG ((EFI_D_INFO
, " Buffer - 0x%016lx\n", AllocInfo
->Buffer
));
2816 DEBUG ((EFI_D_INFO
, " Size - 0x%016lx\n", AllocInfo
->Size
));
2820 DEBUG ((EFI_D_INFO
, "======= SmramProfile end =======\n"));
2822 mSmramProfileGettingStatus
= SmramProfileGettingStatus
;
2826 Dump SMRAM infromation.
2835 if (IS_SMRAM_PROFILE_ENABLED
) {
2836 DumpSmramProfile ();
2837 DumpFreePagesList ();
2838 DumpFreePoolList ();