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
)) {
446 ASSERT (DriverInfoData
!= NULL
);
448 ZeroMem (DriverInfoData
, sizeof (*DriverInfoData
));
450 DriverInfo
= &DriverInfoData
->DriverInfo
;
451 DriverInfoData
->Signature
= MEMORY_PROFILE_DRIVER_INFO_SIGNATURE
;
452 DriverInfo
->Header
.Signature
= MEMORY_PROFILE_DRIVER_INFO_SIGNATURE
;
453 DriverInfo
->Header
.Length
= (UINT16
) (sizeof (MEMORY_PROFILE_DRIVER_INFO
) + PdbOccupiedSize
);
454 DriverInfo
->Header
.Revision
= MEMORY_PROFILE_DRIVER_INFO_REVISION
;
455 if (FileName
!= NULL
) {
456 CopyMem (&DriverInfo
->FileName
, FileName
, sizeof (EFI_GUID
));
458 DriverInfo
->ImageBase
= ImageBase
;
459 DriverInfo
->ImageSize
= ImageSize
;
460 DriverInfo
->EntryPoint
= EntryPoint
;
461 DriverInfo
->ImageSubsystem
= ImageSubsystem
;
462 if ((EntryPoint
!= 0) && ((EntryPoint
< ImageBase
) || (EntryPoint
>= (ImageBase
+ ImageSize
)))) {
464 // If the EntryPoint is not in the range of image buffer, it should come from emulation environment.
465 // So patch ImageBuffer here to align the EntryPoint.
467 Status
= InternalPeCoffGetEntryPoint ((VOID
*) (UINTN
) ImageBase
, &EntryPointInImage
);
468 ASSERT_EFI_ERROR (Status
);
469 DriverInfo
->ImageBase
= ImageBase
+ EntryPoint
- (PHYSICAL_ADDRESS
) (UINTN
) EntryPointInImage
;
471 DriverInfo
->FileType
= FileType
;
472 DriverInfoData
->AllocInfoList
= (LIST_ENTRY
*) (DriverInfoData
+ 1);
473 InitializeListHead (DriverInfoData
->AllocInfoList
);
474 DriverInfo
->CurrentUsage
= 0;
475 DriverInfo
->PeakUsage
= 0;
476 DriverInfo
->AllocRecordCount
= 0;
478 DriverInfo
->PdbStringOffset
= (UINT16
) sizeof (MEMORY_PROFILE_DRIVER_INFO
);
479 DriverInfoData
->PdbString
= (CHAR8
*) (DriverInfoData
->AllocInfoList
+ 1);
480 CopyMem (DriverInfoData
->PdbString
, PdbString
, PdbSize
);
482 DriverInfo
->PdbStringOffset
= 0;
483 DriverInfoData
->PdbString
= NULL
;
486 InsertTailList (ContextData
->DriverInfoList
, &DriverInfoData
->Link
);
487 ContextData
->Context
.ImageCount
++;
488 ContextData
->Context
.TotalImageSize
+= DriverInfo
->ImageSize
;
490 return DriverInfoData
;
494 Register image to DXE.
496 @param FileName File name of the image.
497 @param ImageBase Image base address.
498 @param ImageSize Image size.
499 @param FileType File type of the image.
504 IN EFI_GUID
*FileName
,
505 IN PHYSICAL_ADDRESS ImageBase
,
507 IN EFI_FV_FILETYPE FileType
511 EDKII_MEMORY_PROFILE_PROTOCOL
*ProfileProtocol
;
512 MEDIA_FW_VOL_FILEPATH_DEVICE_PATH
*FilePath
;
513 UINT8 TempBuffer
[sizeof (MEDIA_FW_VOL_FILEPATH_DEVICE_PATH
) + sizeof (EFI_DEVICE_PATH_PROTOCOL
)];
515 if (IS_UEFI_MEMORY_PROFILE_ENABLED
) {
517 FilePath
= (MEDIA_FW_VOL_FILEPATH_DEVICE_PATH
*)TempBuffer
;
518 Status
= gBS
->LocateProtocol (&gEdkiiMemoryProfileGuid
, NULL
, (VOID
**) &ProfileProtocol
);
519 if (!EFI_ERROR (Status
)) {
520 EfiInitializeFwVolDevicepathNode (FilePath
, FileName
);
521 SetDevicePathEndNode (FilePath
+ 1);
523 Status
= ProfileProtocol
->RegisterImage (
525 (EFI_DEVICE_PATH_PROTOCOL
*) FilePath
,
535 Unregister image from DXE.
537 @param FileName File name of the image.
538 @param ImageBase Image base address.
539 @param ImageSize Image size.
543 UnregisterImageFromDxe (
544 IN EFI_GUID
*FileName
,
545 IN PHYSICAL_ADDRESS ImageBase
,
550 EDKII_MEMORY_PROFILE_PROTOCOL
*ProfileProtocol
;
551 MEDIA_FW_VOL_FILEPATH_DEVICE_PATH
*FilePath
;
552 UINT8 TempBuffer
[sizeof (MEDIA_FW_VOL_FILEPATH_DEVICE_PATH
) + sizeof (EFI_DEVICE_PATH_PROTOCOL
)];
554 if (IS_UEFI_MEMORY_PROFILE_ENABLED
) {
556 FilePath
= (MEDIA_FW_VOL_FILEPATH_DEVICE_PATH
*)TempBuffer
;
557 Status
= gBS
->LocateProtocol (&gEdkiiMemoryProfileGuid
, NULL
, (VOID
*) &ProfileProtocol
);
558 if (!EFI_ERROR (Status
)) {
559 EfiInitializeFwVolDevicepathNode (FilePath
, FileName
);
560 SetDevicePathEndNode (FilePath
+ 1);
562 Status
= ProfileProtocol
->UnregisterImage (
564 (EFI_DEVICE_PATH_PROTOCOL
*) FilePath
,
573 Return if record for this driver is needed..
575 @param DriverFilePath Driver file path.
577 @retval TRUE Record for this driver is needed.
578 @retval FALSE Record for this driver is not needed.
582 NeedRecordThisDriver (
583 IN EFI_DEVICE_PATH_PROTOCOL
*DriverFilePath
586 EFI_DEVICE_PATH_PROTOCOL
*TmpDevicePath
;
587 EFI_DEVICE_PATH_PROTOCOL
*DevicePathInstance
;
588 UINTN DevicePathSize
;
591 if (!IsDevicePathValid (mSmramProfileDriverPath
, mSmramProfileDriverPathSize
)) {
593 // Invalid Device Path means record all.
599 // Record FilePath without end node.
601 FilePathSize
= GetDevicePathSize (DriverFilePath
) - sizeof(EFI_DEVICE_PATH_PROTOCOL
);
603 DevicePathInstance
= mSmramProfileDriverPath
;
606 // Find End node (it might be END_ENTIRE or END_INSTANCE)
608 TmpDevicePath
= DevicePathInstance
;
609 while (!IsDevicePathEndType (TmpDevicePath
)) {
610 TmpDevicePath
= NextDevicePathNode (TmpDevicePath
);
614 // Do not compare END node
616 DevicePathSize
= (UINTN
)TmpDevicePath
- (UINTN
)DevicePathInstance
;
617 if ((FilePathSize
== DevicePathSize
) &&
618 (CompareMem (DriverFilePath
, DevicePathInstance
, DevicePathSize
) == 0)) {
625 DevicePathInstance
= (EFI_DEVICE_PATH_PROTOCOL
*)((UINTN
)DevicePathInstance
+ DevicePathSize
+ DevicePathNodeLength(TmpDevicePath
));
626 } while (DevicePathSubType (TmpDevicePath
) != END_ENTIRE_DEVICE_PATH_SUBTYPE
);
632 Register SMM Core to SMRAM profile.
634 @param ContextData SMRAM profile context.
636 @retval TRUE Register success.
637 @retval FALSE Register fail.
642 IN MEMORY_PROFILE_CONTEXT_DATA
*ContextData
645 MEMORY_PROFILE_DRIVER_INFO_DATA
*DriverInfoData
;
646 PHYSICAL_ADDRESS ImageBase
;
647 UINT8 TempBuffer
[sizeof(MEDIA_FW_VOL_FILEPATH_DEVICE_PATH
) + sizeof(EFI_DEVICE_PATH_PROTOCOL
)];
648 MEDIA_FW_VOL_FILEPATH_DEVICE_PATH
*FilePath
;
650 FilePath
= (MEDIA_FW_VOL_FILEPATH_DEVICE_PATH
*) TempBuffer
;
651 EfiInitializeFwVolDevicepathNode (FilePath
, &gEfiCallerIdGuid
);
652 SetDevicePathEndNode (FilePath
+ 1);
654 if (!NeedRecordThisDriver ((EFI_DEVICE_PATH_PROTOCOL
*) FilePath
)) {
658 ImageBase
= gSmmCorePrivate
->PiSmmCoreImageBase
;
659 DriverInfoData
= BuildDriverInfo (
663 gSmmCorePrivate
->PiSmmCoreImageSize
,
664 gSmmCorePrivate
->PiSmmCoreEntryPoint
,
665 InternalPeCoffGetSubsystem ((VOID
*) (UINTN
) ImageBase
),
666 EFI_FV_FILETYPE_SMM_CORE
668 if (DriverInfoData
== NULL
) {
676 Initialize SMRAM profile.
684 MEMORY_PROFILE_CONTEXT_DATA
*SmramProfileContext
;
688 gSmmCorePrivate
->PiSmmCoreImageBase
,
689 gSmmCorePrivate
->PiSmmCoreImageSize
,
690 EFI_FV_FILETYPE_SMM_CORE
693 if (!IS_SMRAM_PROFILE_ENABLED
) {
697 SmramProfileContext
= GetSmramProfileContext ();
698 if (SmramProfileContext
!= NULL
) {
702 mSmramProfileGettingStatus
= FALSE
;
703 if ((PcdGet8 (PcdMemoryProfilePropertyMask
) & BIT7
) != 0) {
704 mSmramProfileRecordingEnable
= MEMORY_PROFILE_RECORDING_DISABLE
;
706 mSmramProfileRecordingEnable
= MEMORY_PROFILE_RECORDING_ENABLE
;
708 mSmramProfileDriverPathSize
= PcdGetSize (PcdMemoryProfileDriverPath
);
709 mSmramProfileDriverPath
= AllocateCopyPool (mSmramProfileDriverPathSize
, PcdGetPtr (PcdMemoryProfileDriverPath
));
710 mSmramProfileContextPtr
= &mSmramProfileContext
;
712 RegisterSmmCore (&mSmramProfileContext
);
714 DEBUG ((EFI_D_INFO
, "SmramProfileInit SmramProfileContext - 0x%x\n", &mSmramProfileContext
));
718 Install SMRAM profile protocol.
722 SmramProfileInstallProtocol (
729 if (!IS_SMRAM_PROFILE_ENABLED
) {
734 Status
= SmmInstallProtocolInterface (
736 &gEdkiiSmmMemoryProfileGuid
,
737 EFI_NATIVE_INTERFACE
,
740 ASSERT_EFI_ERROR (Status
);
744 Get the GUID file name from the file path.
746 @param FilePath File path.
748 @return The GUID file name from the file path.
752 GetFileNameFromFilePath (
753 IN EFI_DEVICE_PATH_PROTOCOL
*FilePath
756 MEDIA_FW_VOL_FILEPATH_DEVICE_PATH
*ThisFilePath
;
760 if (FilePath
!= NULL
) {
761 ThisFilePath
= (MEDIA_FW_VOL_FILEPATH_DEVICE_PATH
*) FilePath
;
762 while (!IsDevicePathEnd (ThisFilePath
)) {
763 FileName
= EfiGetNameGuidFromFwVolDevicePathNode (ThisFilePath
);
764 if (FileName
!= NULL
) {
767 ThisFilePath
= (MEDIA_FW_VOL_FILEPATH_DEVICE_PATH
*) NextDevicePathNode (ThisFilePath
);
775 Register SMM image to SMRAM profile.
777 @param DriverEntry SMM image info.
778 @param RegisterToDxe Register image to DXE.
780 @return EFI_SUCCESS Register successfully.
781 @return EFI_UNSUPPORTED Memory profile is unsupported,
782 or memory profile for the image is not required.
783 @return EFI_OUT_OF_RESOURCES No enough resource for this register.
787 RegisterSmramProfileImage (
788 IN EFI_SMM_DRIVER_ENTRY
*DriverEntry
,
789 IN BOOLEAN RegisterToDxe
792 MEMORY_PROFILE_CONTEXT_DATA
*ContextData
;
793 MEMORY_PROFILE_DRIVER_INFO_DATA
*DriverInfoData
;
794 UINT8 TempBuffer
[sizeof(MEDIA_FW_VOL_FILEPATH_DEVICE_PATH
) + sizeof(EFI_DEVICE_PATH_PROTOCOL
)];
795 MEDIA_FW_VOL_FILEPATH_DEVICE_PATH
*FilePath
;
799 &DriverEntry
->FileName
,
800 DriverEntry
->ImageBuffer
,
801 EFI_PAGES_TO_SIZE (DriverEntry
->NumberOfPage
),
806 if (!IS_SMRAM_PROFILE_ENABLED
) {
807 return EFI_UNSUPPORTED
;
810 FilePath
= (MEDIA_FW_VOL_FILEPATH_DEVICE_PATH
*) TempBuffer
;
811 EfiInitializeFwVolDevicepathNode (FilePath
, &DriverEntry
->FileName
);
812 SetDevicePathEndNode (FilePath
+ 1);
814 if (!NeedRecordThisDriver ((EFI_DEVICE_PATH_PROTOCOL
*) FilePath
)) {
815 return EFI_UNSUPPORTED
;
818 ContextData
= GetSmramProfileContext ();
819 if (ContextData
== NULL
) {
820 return EFI_UNSUPPORTED
;
823 DriverInfoData
= BuildDriverInfo (
825 &DriverEntry
->FileName
,
826 DriverEntry
->ImageBuffer
,
827 EFI_PAGES_TO_SIZE (DriverEntry
->NumberOfPage
),
828 DriverEntry
->ImageEntryPoint
,
829 InternalPeCoffGetSubsystem ((VOID
*) (UINTN
) DriverEntry
->ImageBuffer
),
832 if (DriverInfoData
== NULL
) {
833 return EFI_OUT_OF_RESOURCES
;
840 Search image from memory profile.
842 @param ContextData Memory profile context.
843 @param FileName Image file name.
844 @param Address Image Address.
846 @return Pointer to memory profile driver info.
849 MEMORY_PROFILE_DRIVER_INFO_DATA
*
850 GetMemoryProfileDriverInfoByFileNameAndAddress (
851 IN MEMORY_PROFILE_CONTEXT_DATA
*ContextData
,
852 IN EFI_GUID
*FileName
,
853 IN PHYSICAL_ADDRESS Address
856 MEMORY_PROFILE_DRIVER_INFO
*DriverInfo
;
857 MEMORY_PROFILE_DRIVER_INFO_DATA
*DriverInfoData
;
858 LIST_ENTRY
*DriverLink
;
859 LIST_ENTRY
*DriverInfoList
;
861 DriverInfoList
= ContextData
->DriverInfoList
;
863 for (DriverLink
= DriverInfoList
->ForwardLink
;
864 DriverLink
!= DriverInfoList
;
865 DriverLink
= DriverLink
->ForwardLink
) {
866 DriverInfoData
= CR (
868 MEMORY_PROFILE_DRIVER_INFO_DATA
,
870 MEMORY_PROFILE_DRIVER_INFO_SIGNATURE
872 DriverInfo
= &DriverInfoData
->DriverInfo
;
873 if ((CompareGuid (&DriverInfo
->FileName
, FileName
)) &&
874 (Address
>= DriverInfo
->ImageBase
) &&
875 (Address
< (DriverInfo
->ImageBase
+ DriverInfo
->ImageSize
))) {
876 return DriverInfoData
;
884 Search image from memory profile.
885 It will return image, if (Address >= ImageBuffer) AND (Address < ImageBuffer + ImageSize)
887 @param ContextData Memory profile context.
888 @param Address Image or Function address.
890 @return Pointer to memory profile driver info.
893 MEMORY_PROFILE_DRIVER_INFO_DATA
*
894 GetMemoryProfileDriverInfoFromAddress (
895 IN MEMORY_PROFILE_CONTEXT_DATA
*ContextData
,
896 IN PHYSICAL_ADDRESS Address
899 MEMORY_PROFILE_DRIVER_INFO
*DriverInfo
;
900 MEMORY_PROFILE_DRIVER_INFO_DATA
*DriverInfoData
;
901 LIST_ENTRY
*DriverLink
;
902 LIST_ENTRY
*DriverInfoList
;
904 DriverInfoList
= ContextData
->DriverInfoList
;
906 for (DriverLink
= DriverInfoList
->ForwardLink
;
907 DriverLink
!= DriverInfoList
;
908 DriverLink
= DriverLink
->ForwardLink
) {
909 DriverInfoData
= CR (
911 MEMORY_PROFILE_DRIVER_INFO_DATA
,
913 MEMORY_PROFILE_DRIVER_INFO_SIGNATURE
915 DriverInfo
= &DriverInfoData
->DriverInfo
;
916 if ((Address
>= DriverInfo
->ImageBase
) &&
917 (Address
< (DriverInfo
->ImageBase
+ DriverInfo
->ImageSize
))) {
918 return DriverInfoData
;
926 Unregister image from SMRAM profile.
928 @param DriverEntry SMM image info.
929 @param UnregisterFromDxe Unregister image from DXE.
931 @return EFI_SUCCESS Unregister successfully.
932 @return EFI_UNSUPPORTED Memory profile is unsupported,
933 or memory profile for the image is not required.
934 @return EFI_NOT_FOUND The image is not found.
938 UnregisterSmramProfileImage (
939 IN EFI_SMM_DRIVER_ENTRY
*DriverEntry
,
940 IN BOOLEAN UnregisterFromDxe
944 MEMORY_PROFILE_CONTEXT_DATA
*ContextData
;
945 MEMORY_PROFILE_DRIVER_INFO_DATA
*DriverInfoData
;
947 PHYSICAL_ADDRESS ImageAddress
;
948 VOID
*EntryPointInImage
;
949 UINT8 TempBuffer
[sizeof(MEDIA_FW_VOL_FILEPATH_DEVICE_PATH
) + sizeof(EFI_DEVICE_PATH_PROTOCOL
)];
950 MEDIA_FW_VOL_FILEPATH_DEVICE_PATH
*FilePath
;
952 if (UnregisterFromDxe
) {
953 UnregisterImageFromDxe (
954 &DriverEntry
->FileName
,
955 DriverEntry
->ImageBuffer
,
956 EFI_PAGES_TO_SIZE (DriverEntry
->NumberOfPage
)
960 if (!IS_SMRAM_PROFILE_ENABLED
) {
961 return EFI_UNSUPPORTED
;
964 FilePath
= (MEDIA_FW_VOL_FILEPATH_DEVICE_PATH
*) TempBuffer
;
965 EfiInitializeFwVolDevicepathNode (FilePath
, &DriverEntry
->FileName
);
966 SetDevicePathEndNode (FilePath
+ 1);
968 if (!NeedRecordThisDriver ((EFI_DEVICE_PATH_PROTOCOL
*) FilePath
)) {
969 return EFI_UNSUPPORTED
;
972 ContextData
= GetSmramProfileContext ();
973 if (ContextData
== NULL
) {
974 return EFI_UNSUPPORTED
;
977 DriverInfoData
= NULL
;
978 FileName
= &DriverEntry
->FileName
;
979 ImageAddress
= DriverEntry
->ImageBuffer
;
980 if ((DriverEntry
->ImageEntryPoint
< ImageAddress
) || (DriverEntry
->ImageEntryPoint
>= (ImageAddress
+ EFI_PAGES_TO_SIZE (DriverEntry
->NumberOfPage
)))) {
982 // If the EntryPoint is not in the range of image buffer, it should come from emulation environment.
983 // So patch ImageAddress here to align the EntryPoint.
985 Status
= InternalPeCoffGetEntryPoint ((VOID
*) (UINTN
) ImageAddress
, &EntryPointInImage
);
986 ASSERT_EFI_ERROR (Status
);
987 ImageAddress
= ImageAddress
+ (UINTN
) DriverEntry
->ImageEntryPoint
- (UINTN
) EntryPointInImage
;
989 if (FileName
!= NULL
) {
990 DriverInfoData
= GetMemoryProfileDriverInfoByFileNameAndAddress (ContextData
, FileName
, ImageAddress
);
992 if (DriverInfoData
== NULL
) {
993 DriverInfoData
= GetMemoryProfileDriverInfoFromAddress (ContextData
, ImageAddress
);
995 if (DriverInfoData
== NULL
) {
996 return EFI_NOT_FOUND
;
999 ContextData
->Context
.TotalImageSize
-= DriverInfoData
->DriverInfo
.ImageSize
;
1001 // Keep the ImageBase for RVA calculation in Application.
1002 //DriverInfoData->DriverInfo.ImageBase = 0;
1003 DriverInfoData
->DriverInfo
.ImageSize
= 0;
1005 if (DriverInfoData
->DriverInfo
.PeakUsage
== 0) {
1006 ContextData
->Context
.ImageCount
--;
1007 RemoveEntryList (&DriverInfoData
->Link
);
1009 // Use SmmInternalFreePool() that will not update profile for this FreePool action.
1011 SmmInternalFreePool (DriverInfoData
);
1018 Return if this memory type needs to be recorded into memory profile.
1019 Only need to record EfiRuntimeServicesCode and EfiRuntimeServicesData for SMRAM profile.
1021 @param MemoryType Memory type.
1023 @retval TRUE This memory type need to be recorded.
1024 @retval FALSE This memory type need not to be recorded.
1028 SmmCoreNeedRecordProfile (
1029 IN EFI_MEMORY_TYPE MemoryType
1034 if (MemoryType
!= EfiRuntimeServicesCode
&&
1035 MemoryType
!= EfiRuntimeServicesData
) {
1039 TestBit
= LShiftU64 (1, MemoryType
);
1041 if ((PcdGet64 (PcdMemoryProfileMemoryType
) & TestBit
) != 0) {
1049 Convert EFI memory type to profile memory index. The rule is:
1050 If BIOS memory type (0 ~ EfiMaxMemoryType - 1), ProfileMemoryIndex = MemoryType.
1051 As SMRAM profile is only to record EfiRuntimeServicesCode and EfiRuntimeServicesData,
1052 so return input memory type directly.
1054 @param MemoryType Memory type.
1056 @return EFI memory type as profile memory index.
1060 GetProfileMemoryIndex (
1061 IN EFI_MEMORY_TYPE MemoryType
1068 Update SMRAM profile FreeMemoryPages information
1070 @param ContextData Memory profile context.
1074 SmramProfileUpdateFreePages (
1075 IN MEMORY_PROFILE_CONTEXT_DATA
*ContextData
1079 FREE_PAGE_LIST
*Pages
;
1080 LIST_ENTRY
*FreePageList
;
1081 UINTN NumberOfPages
;
1084 FreePageList
= &mSmmMemoryMap
;
1085 for (Node
= FreePageList
->BackLink
;
1086 Node
!= FreePageList
;
1087 Node
= Node
->BackLink
) {
1088 Pages
= BASE_CR (Node
, FREE_PAGE_LIST
, Link
);
1089 NumberOfPages
+= Pages
->NumberOfPages
;
1092 mSmramFreeMemory
.TotalFreeMemoryPages
= NumberOfPages
;
1094 if (NumberOfPages
<= SMRAM_INFO_DUMP_PAGE_THRESHOLD
) {
1100 Update SMRAM profile Allocate information.
1102 @param CallerAddress Address of caller who call Allocate.
1103 @param Action This Allocate action.
1104 @param MemoryType Memory type.
1105 @param Size Buffer size.
1106 @param Buffer Buffer address.
1107 @param ActionString String for memory profile action.
1109 @return EFI_SUCCESS Memory profile is updated.
1110 @return EFI_UNSUPPORTED Memory profile is unsupported,
1111 or memory profile for the image is not required.
1112 @return EFI_OUT_OF_RESOURCES No enough resource to update memory profile for allocate action.
1116 SmmCoreUpdateProfileAllocate (
1117 IN PHYSICAL_ADDRESS CallerAddress
,
1118 IN MEMORY_PROFILE_ACTION Action
,
1119 IN EFI_MEMORY_TYPE MemoryType
,
1122 IN CHAR8
*ActionString OPTIONAL
1126 MEMORY_PROFILE_CONTEXT
*Context
;
1127 MEMORY_PROFILE_DRIVER_INFO
*DriverInfo
;
1128 MEMORY_PROFILE_ALLOC_INFO
*AllocInfo
;
1129 MEMORY_PROFILE_CONTEXT_DATA
*ContextData
;
1130 MEMORY_PROFILE_DRIVER_INFO_DATA
*DriverInfoData
;
1131 MEMORY_PROFILE_ALLOC_INFO_DATA
*AllocInfoData
;
1132 EFI_MEMORY_TYPE ProfileMemoryIndex
;
1133 MEMORY_PROFILE_ACTION BasicAction
;
1134 UINTN ActionStringSize
;
1135 UINTN ActionStringOccupiedSize
;
1137 BasicAction
= Action
& MEMORY_PROFILE_ACTION_BASIC_MASK
;
1139 ContextData
= GetSmramProfileContext ();
1140 if (ContextData
== NULL
) {
1141 return EFI_UNSUPPORTED
;
1144 DriverInfoData
= GetMemoryProfileDriverInfoFromAddress (ContextData
, CallerAddress
);
1145 if (DriverInfoData
== NULL
) {
1146 return EFI_UNSUPPORTED
;
1149 ActionStringSize
= 0;
1150 ActionStringOccupiedSize
= 0;
1151 if (ActionString
!= NULL
) {
1152 ActionStringSize
= AsciiStrSize (ActionString
);
1153 ActionStringOccupiedSize
= GET_OCCUPIED_SIZE (ActionStringSize
, sizeof (UINT64
));
1157 // Use SmmInternalAllocatePool() that will not update profile for this AllocatePool action.
1159 AllocInfoData
= NULL
;
1160 Status
= SmmInternalAllocatePool (
1161 EfiRuntimeServicesData
,
1162 sizeof (*AllocInfoData
) + ActionStringSize
,
1163 (VOID
**) &AllocInfoData
1165 if (EFI_ERROR (Status
)) {
1166 return EFI_OUT_OF_RESOURCES
;
1168 ASSERT (AllocInfoData
!= NULL
);
1171 // Only update SequenceCount if and only if it is basic action.
1173 if (Action
== BasicAction
) {
1174 ContextData
->Context
.SequenceCount
++;
1177 AllocInfo
= &AllocInfoData
->AllocInfo
;
1178 AllocInfoData
->Signature
= MEMORY_PROFILE_ALLOC_INFO_SIGNATURE
;
1179 AllocInfo
->Header
.Signature
= MEMORY_PROFILE_ALLOC_INFO_SIGNATURE
;
1180 AllocInfo
->Header
.Length
= (UINT16
) (sizeof (MEMORY_PROFILE_ALLOC_INFO
) + ActionStringOccupiedSize
);
1181 AllocInfo
->Header
.Revision
= MEMORY_PROFILE_ALLOC_INFO_REVISION
;
1182 AllocInfo
->CallerAddress
= CallerAddress
;
1183 AllocInfo
->SequenceId
= ContextData
->Context
.SequenceCount
;
1184 AllocInfo
->Action
= Action
;
1185 AllocInfo
->MemoryType
= MemoryType
;
1186 AllocInfo
->Buffer
= (PHYSICAL_ADDRESS
) (UINTN
) Buffer
;
1187 AllocInfo
->Size
= Size
;
1188 if (ActionString
!= NULL
) {
1189 AllocInfo
->ActionStringOffset
= (UINT16
) sizeof (MEMORY_PROFILE_ALLOC_INFO
);
1190 AllocInfoData
->ActionString
= (CHAR8
*) (AllocInfoData
+ 1);
1191 CopyMem (AllocInfoData
->ActionString
, ActionString
, ActionStringSize
);
1193 AllocInfo
->ActionStringOffset
= 0;
1194 AllocInfoData
->ActionString
= NULL
;
1197 InsertTailList (DriverInfoData
->AllocInfoList
, &AllocInfoData
->Link
);
1199 Context
= &ContextData
->Context
;
1200 DriverInfo
= &DriverInfoData
->DriverInfo
;
1201 DriverInfo
->AllocRecordCount
++;
1204 // Update summary if and only if it is basic action.
1206 if (Action
== BasicAction
) {
1207 ProfileMemoryIndex
= GetProfileMemoryIndex (MemoryType
);
1209 DriverInfo
->CurrentUsage
+= Size
;
1210 if (DriverInfo
->PeakUsage
< DriverInfo
->CurrentUsage
) {
1211 DriverInfo
->PeakUsage
= DriverInfo
->CurrentUsage
;
1213 DriverInfo
->CurrentUsageByType
[ProfileMemoryIndex
] += Size
;
1214 if (DriverInfo
->PeakUsageByType
[ProfileMemoryIndex
] < DriverInfo
->CurrentUsageByType
[ProfileMemoryIndex
]) {
1215 DriverInfo
->PeakUsageByType
[ProfileMemoryIndex
] = DriverInfo
->CurrentUsageByType
[ProfileMemoryIndex
];
1218 Context
->CurrentTotalUsage
+= Size
;
1219 if (Context
->PeakTotalUsage
< Context
->CurrentTotalUsage
) {
1220 Context
->PeakTotalUsage
= Context
->CurrentTotalUsage
;
1222 Context
->CurrentTotalUsageByType
[ProfileMemoryIndex
] += Size
;
1223 if (Context
->PeakTotalUsageByType
[ProfileMemoryIndex
] < Context
->CurrentTotalUsageByType
[ProfileMemoryIndex
]) {
1224 Context
->PeakTotalUsageByType
[ProfileMemoryIndex
] = Context
->CurrentTotalUsageByType
[ProfileMemoryIndex
];
1227 SmramProfileUpdateFreePages (ContextData
);
1234 Get memory profile alloc info from memory profile
1236 @param DriverInfoData Driver info
1237 @param BasicAction This Free basic action
1238 @param Size Buffer size
1239 @param Buffer Buffer address
1241 @return Pointer to memory profile alloc info.
1243 MEMORY_PROFILE_ALLOC_INFO_DATA
*
1244 GetMemoryProfileAllocInfoFromAddress (
1245 IN MEMORY_PROFILE_DRIVER_INFO_DATA
*DriverInfoData
,
1246 IN MEMORY_PROFILE_ACTION BasicAction
,
1251 LIST_ENTRY
*AllocInfoList
;
1252 LIST_ENTRY
*AllocLink
;
1253 MEMORY_PROFILE_ALLOC_INFO
*AllocInfo
;
1254 MEMORY_PROFILE_ALLOC_INFO_DATA
*AllocInfoData
;
1256 AllocInfoList
= DriverInfoData
->AllocInfoList
;
1258 for (AllocLink
= AllocInfoList
->ForwardLink
;
1259 AllocLink
!= AllocInfoList
;
1260 AllocLink
= AllocLink
->ForwardLink
) {
1261 AllocInfoData
= CR (
1263 MEMORY_PROFILE_ALLOC_INFO_DATA
,
1265 MEMORY_PROFILE_ALLOC_INFO_SIGNATURE
1267 AllocInfo
= &AllocInfoData
->AllocInfo
;
1268 if ((AllocInfo
->Action
& MEMORY_PROFILE_ACTION_BASIC_MASK
) != BasicAction
) {
1271 switch (BasicAction
) {
1272 case MemoryProfileActionAllocatePages
:
1273 if ((AllocInfo
->Buffer
<= (PHYSICAL_ADDRESS
) (UINTN
) Buffer
) &&
1274 ((AllocInfo
->Buffer
+ AllocInfo
->Size
) >= ((PHYSICAL_ADDRESS
) (UINTN
) Buffer
+ Size
))) {
1275 return AllocInfoData
;
1278 case MemoryProfileActionAllocatePool
:
1279 if (AllocInfo
->Buffer
== (PHYSICAL_ADDRESS
) (UINTN
) Buffer
) {
1280 return AllocInfoData
;
1293 Update SMRAM profile Free information.
1295 @param CallerAddress Address of caller who call Free.
1296 @param Action This Free action.
1297 @param Size Buffer size.
1298 @param Buffer Buffer address.
1300 @return EFI_SUCCESS Memory profile is updated.
1301 @return EFI_UNSUPPORTED Memory profile is unsupported.
1302 @return EFI_NOT_FOUND No matched allocate info found for free action.
1306 SmmCoreUpdateProfileFree (
1307 IN PHYSICAL_ADDRESS CallerAddress
,
1308 IN MEMORY_PROFILE_ACTION Action
,
1313 MEMORY_PROFILE_CONTEXT
*Context
;
1314 MEMORY_PROFILE_DRIVER_INFO
*DriverInfo
;
1315 MEMORY_PROFILE_ALLOC_INFO
*AllocInfo
;
1316 MEMORY_PROFILE_CONTEXT_DATA
*ContextData
;
1317 MEMORY_PROFILE_DRIVER_INFO_DATA
*DriverInfoData
;
1318 LIST_ENTRY
*DriverLink
;
1319 LIST_ENTRY
*DriverInfoList
;
1320 MEMORY_PROFILE_DRIVER_INFO_DATA
*ThisDriverInfoData
;
1321 MEMORY_PROFILE_ALLOC_INFO_DATA
*AllocInfoData
;
1322 EFI_MEMORY_TYPE ProfileMemoryIndex
;
1323 MEMORY_PROFILE_ACTION BasicAction
;
1326 BasicAction
= Action
& MEMORY_PROFILE_ACTION_BASIC_MASK
;
1328 ContextData
= GetSmramProfileContext ();
1329 if (ContextData
== NULL
) {
1330 return EFI_UNSUPPORTED
;
1333 DriverInfoData
= GetMemoryProfileDriverInfoFromAddress (ContextData
, CallerAddress
);
1336 // Do not return if DriverInfoData == NULL here,
1337 // because driver A might free memory allocated by driver B.
1341 // Need use do-while loop to find all possible record,
1342 // because one address might be recorded multiple times.
1345 AllocInfoData
= NULL
;
1347 if (DriverInfoData
!= NULL
) {
1348 switch (BasicAction
) {
1349 case MemoryProfileActionFreePages
:
1350 AllocInfoData
= GetMemoryProfileAllocInfoFromAddress (DriverInfoData
, MemoryProfileActionAllocatePages
, Size
, Buffer
);
1352 case MemoryProfileActionFreePool
:
1353 AllocInfoData
= GetMemoryProfileAllocInfoFromAddress (DriverInfoData
, MemoryProfileActionAllocatePool
, 0, Buffer
);
1357 AllocInfoData
= NULL
;
1361 if (AllocInfoData
== NULL
) {
1363 // Legal case, because driver A might free memory allocated by driver B, by some protocol.
1365 DriverInfoList
= ContextData
->DriverInfoList
;
1367 for (DriverLink
= DriverInfoList
->ForwardLink
;
1368 DriverLink
!= DriverInfoList
;
1369 DriverLink
= DriverLink
->ForwardLink
) {
1370 ThisDriverInfoData
= CR (
1372 MEMORY_PROFILE_DRIVER_INFO_DATA
,
1374 MEMORY_PROFILE_DRIVER_INFO_SIGNATURE
1376 switch (BasicAction
) {
1377 case MemoryProfileActionFreePages
:
1378 AllocInfoData
= GetMemoryProfileAllocInfoFromAddress (ThisDriverInfoData
, MemoryProfileActionAllocatePages
, Size
, Buffer
);
1380 case MemoryProfileActionFreePool
:
1381 AllocInfoData
= GetMemoryProfileAllocInfoFromAddress (ThisDriverInfoData
, MemoryProfileActionAllocatePool
, 0, Buffer
);
1385 AllocInfoData
= NULL
;
1388 if (AllocInfoData
!= NULL
) {
1389 DriverInfoData
= ThisDriverInfoData
;
1394 if (AllocInfoData
== NULL
) {
1396 // If (!Found), no matched allocate info is found for this free action.
1397 // It is because the specified memory type allocate actions have been filtered by
1398 // CoreNeedRecordProfile(), but free actions have no memory type information,
1399 // they can not be filtered by CoreNeedRecordProfile(). Then, they will be
1402 // If (Found), it is normal exit path.
1403 return (Found
? EFI_SUCCESS
: EFI_NOT_FOUND
);
1407 ASSERT (DriverInfoData
!= NULL
);
1408 ASSERT (AllocInfoData
!= NULL
);
1412 Context
= &ContextData
->Context
;
1413 DriverInfo
= &DriverInfoData
->DriverInfo
;
1414 AllocInfo
= &AllocInfoData
->AllocInfo
;
1416 DriverInfo
->AllocRecordCount
--;
1418 // Update summary if and only if it is basic action.
1420 if (AllocInfo
->Action
== (AllocInfo
->Action
& MEMORY_PROFILE_ACTION_BASIC_MASK
)) {
1421 ProfileMemoryIndex
= GetProfileMemoryIndex (AllocInfo
->MemoryType
);
1423 Context
->CurrentTotalUsage
-= AllocInfo
->Size
;
1424 Context
->CurrentTotalUsageByType
[ProfileMemoryIndex
] -= AllocInfo
->Size
;
1426 DriverInfo
->CurrentUsage
-= AllocInfo
->Size
;
1427 DriverInfo
->CurrentUsageByType
[ProfileMemoryIndex
] -= AllocInfo
->Size
;
1430 RemoveEntryList (&AllocInfoData
->Link
);
1432 if (BasicAction
== MemoryProfileActionFreePages
) {
1433 if (AllocInfo
->Buffer
!= (PHYSICAL_ADDRESS
) (UINTN
) Buffer
) {
1434 SmmCoreUpdateProfileAllocate (
1435 AllocInfo
->CallerAddress
,
1437 AllocInfo
->MemoryType
,
1438 (UINTN
) ((PHYSICAL_ADDRESS
) (UINTN
) Buffer
- AllocInfo
->Buffer
),
1439 (VOID
*) (UINTN
) AllocInfo
->Buffer
,
1440 AllocInfoData
->ActionString
1443 if (AllocInfo
->Buffer
+ AllocInfo
->Size
!= ((PHYSICAL_ADDRESS
) (UINTN
) Buffer
+ Size
)) {
1444 SmmCoreUpdateProfileAllocate (
1445 AllocInfo
->CallerAddress
,
1447 AllocInfo
->MemoryType
,
1448 (UINTN
) ((AllocInfo
->Buffer
+ AllocInfo
->Size
) - ((PHYSICAL_ADDRESS
) (UINTN
) Buffer
+ Size
)),
1449 (VOID
*) ((UINTN
) Buffer
+ Size
),
1450 AllocInfoData
->ActionString
1456 // Use SmmInternalFreePool() that will not update profile for this FreePool action.
1458 SmmInternalFreePool (AllocInfoData
);
1463 Update SMRAM profile information.
1465 @param CallerAddress Address of caller who call Allocate or Free.
1466 @param Action This Allocate or Free action.
1467 @param MemoryType Memory type.
1468 EfiMaxMemoryType means the MemoryType is unknown.
1469 @param Size Buffer size.
1470 @param Buffer Buffer address.
1471 @param ActionString String for memory profile action.
1472 Only needed for user defined allocate action.
1474 @return EFI_SUCCESS Memory profile is updated.
1475 @return EFI_UNSUPPORTED Memory profile is unsupported,
1476 or memory profile for the image is not required,
1477 or memory profile for the memory type is not required.
1478 @return EFI_ACCESS_DENIED It is during memory profile data getting.
1479 @return EFI_ABORTED Memory profile recording is not enabled.
1480 @return EFI_OUT_OF_RESOURCES No enough resource to update memory profile for allocate action.
1481 @return EFI_NOT_FOUND No matched allocate info found for free action.
1486 SmmCoreUpdateProfile (
1487 IN PHYSICAL_ADDRESS CallerAddress
,
1488 IN MEMORY_PROFILE_ACTION Action
,
1489 IN EFI_MEMORY_TYPE MemoryType
, // Valid for AllocatePages/AllocatePool
1490 IN UINTN Size
, // Valid for AllocatePages/FreePages/AllocatePool
1492 IN CHAR8
*ActionString OPTIONAL
1496 MEMORY_PROFILE_CONTEXT_DATA
*ContextData
;
1497 MEMORY_PROFILE_ACTION BasicAction
;
1499 if (!IS_SMRAM_PROFILE_ENABLED
) {
1500 return EFI_UNSUPPORTED
;
1503 if (mSmramProfileGettingStatus
) {
1504 return EFI_ACCESS_DENIED
;
1507 if (!mSmramProfileRecordingEnable
) {
1512 // Get the basic action to know how to process the record
1514 BasicAction
= Action
& MEMORY_PROFILE_ACTION_BASIC_MASK
;
1517 // Free operations have no memory type information, so skip the check.
1519 if ((BasicAction
== MemoryProfileActionAllocatePages
) || (BasicAction
== MemoryProfileActionAllocatePool
)) {
1521 // Only record limited MemoryType.
1523 if (!SmmCoreNeedRecordProfile (MemoryType
)) {
1524 return EFI_UNSUPPORTED
;
1528 ContextData
= GetSmramProfileContext ();
1529 if (ContextData
== NULL
) {
1530 return EFI_UNSUPPORTED
;
1533 switch (BasicAction
) {
1534 case MemoryProfileActionAllocatePages
:
1535 Status
= SmmCoreUpdateProfileAllocate (CallerAddress
, Action
, MemoryType
, Size
, Buffer
, ActionString
);
1537 case MemoryProfileActionFreePages
:
1538 Status
= SmmCoreUpdateProfileFree (CallerAddress
, Action
, Size
, Buffer
);
1540 case MemoryProfileActionAllocatePool
:
1541 Status
= SmmCoreUpdateProfileAllocate (CallerAddress
, Action
, MemoryType
, Size
, Buffer
, ActionString
);
1543 case MemoryProfileActionFreePool
:
1544 Status
= SmmCoreUpdateProfileFree (CallerAddress
, Action
, 0, Buffer
);
1548 Status
= EFI_UNSUPPORTED
;
1556 SMRAM profile ready to lock callback function.
1560 SmramProfileReadyToLock (
1564 if (!IS_SMRAM_PROFILE_ENABLED
) {
1568 DEBUG ((EFI_D_INFO
, "SmramProfileReadyToLock\n"));
1569 mSmramReadyToLock
= TRUE
;
1572 ////////////////////
1575 Get SMRAM profile data size.
1577 @return SMRAM profile data size.
1581 SmramProfileGetDataSize (
1585 MEMORY_PROFILE_CONTEXT_DATA
*ContextData
;
1586 MEMORY_PROFILE_DRIVER_INFO_DATA
*DriverInfoData
;
1587 MEMORY_PROFILE_ALLOC_INFO_DATA
*AllocInfoData
;
1588 LIST_ENTRY
*DriverInfoList
;
1589 LIST_ENTRY
*DriverLink
;
1590 LIST_ENTRY
*AllocInfoList
;
1591 LIST_ENTRY
*AllocLink
;
1594 LIST_ENTRY
*FreePageList
;
1595 LIST_ENTRY
*FreePoolList
;
1596 FREE_POOL_HEADER
*Pool
;
1597 UINTN PoolListIndex
;
1600 ContextData
= GetSmramProfileContext ();
1601 if (ContextData
== NULL
) {
1605 TotalSize
= sizeof (MEMORY_PROFILE_CONTEXT
);
1607 DriverInfoList
= ContextData
->DriverInfoList
;
1608 for (DriverLink
= DriverInfoList
->ForwardLink
;
1609 DriverLink
!= DriverInfoList
;
1610 DriverLink
= DriverLink
->ForwardLink
) {
1611 DriverInfoData
= CR (
1613 MEMORY_PROFILE_DRIVER_INFO_DATA
,
1615 MEMORY_PROFILE_DRIVER_INFO_SIGNATURE
1617 TotalSize
+= DriverInfoData
->DriverInfo
.Header
.Length
;
1619 AllocInfoList
= DriverInfoData
->AllocInfoList
;
1620 for (AllocLink
= AllocInfoList
->ForwardLink
;
1621 AllocLink
!= AllocInfoList
;
1622 AllocLink
= AllocLink
->ForwardLink
) {
1623 AllocInfoData
= CR (
1625 MEMORY_PROFILE_ALLOC_INFO_DATA
,
1627 MEMORY_PROFILE_ALLOC_INFO_SIGNATURE
1629 TotalSize
+= AllocInfoData
->AllocInfo
.Header
.Length
;
1635 FreePageList
= &mSmmMemoryMap
;
1636 for (Node
= FreePageList
->BackLink
;
1637 Node
!= FreePageList
;
1638 Node
= Node
->BackLink
) {
1641 for (PoolListIndex
= 0; PoolListIndex
< MAX_POOL_INDEX
; PoolListIndex
++) {
1642 FreePoolList
= &mSmmPoolLists
[PoolListIndex
];
1643 for (Node
= FreePoolList
->BackLink
;
1644 Node
!= FreePoolList
;
1645 Node
= Node
->BackLink
) {
1646 Pool
= BASE_CR (Node
, FREE_POOL_HEADER
, Link
);
1647 if (Pool
->Header
.Available
) {
1654 TotalSize
+= (sizeof (MEMORY_PROFILE_FREE_MEMORY
) + Index
* sizeof (MEMORY_PROFILE_DESCRIPTOR
));
1655 TotalSize
+= (sizeof (MEMORY_PROFILE_MEMORY_RANGE
) + mFullSmramRangeCount
* sizeof (MEMORY_PROFILE_DESCRIPTOR
));
1661 Copy SMRAM profile data.
1663 @param ProfileBuffer The buffer to hold SMRAM profile data.
1664 @param ProfileSize On input, profile buffer size.
1665 On output, actual profile data size copied.
1666 @param ProfileOffset On input, profile buffer offset to copy.
1667 On output, next time profile buffer offset to copy.
1671 SmramProfileCopyData (
1672 OUT VOID
*ProfileBuffer
,
1673 IN OUT UINT64
*ProfileSize
,
1674 IN OUT UINT64
*ProfileOffset
1677 MEMORY_PROFILE_CONTEXT
*Context
;
1678 MEMORY_PROFILE_DRIVER_INFO
*DriverInfo
;
1679 MEMORY_PROFILE_ALLOC_INFO
*AllocInfo
;
1680 MEMORY_PROFILE_CONTEXT_DATA
*ContextData
;
1681 MEMORY_PROFILE_DRIVER_INFO_DATA
*DriverInfoData
;
1682 MEMORY_PROFILE_ALLOC_INFO_DATA
*AllocInfoData
;
1683 LIST_ENTRY
*DriverInfoList
;
1684 LIST_ENTRY
*DriverLink
;
1685 LIST_ENTRY
*AllocInfoList
;
1686 LIST_ENTRY
*AllocLink
;
1688 FREE_PAGE_LIST
*Pages
;
1689 LIST_ENTRY
*FreePageList
;
1690 LIST_ENTRY
*FreePoolList
;
1691 FREE_POOL_HEADER
*Pool
;
1692 UINTN PoolListIndex
;
1694 MEMORY_PROFILE_FREE_MEMORY
*FreeMemory
;
1695 MEMORY_PROFILE_MEMORY_RANGE
*MemoryRange
;
1696 MEMORY_PROFILE_DESCRIPTOR
*MemoryProfileDescriptor
;
1698 UINT64 RemainingSize
;
1700 UINTN ActionStringSize
;
1702 ContextData
= GetSmramProfileContext ();
1703 if (ContextData
== NULL
) {
1707 RemainingSize
= *ProfileSize
;
1710 if (*ProfileOffset
< sizeof (MEMORY_PROFILE_CONTEXT
)) {
1711 if (RemainingSize
>= sizeof (MEMORY_PROFILE_CONTEXT
)) {
1712 Context
= ProfileBuffer
;
1713 CopyMem (Context
, &ContextData
->Context
, sizeof (MEMORY_PROFILE_CONTEXT
));
1714 RemainingSize
-= sizeof (MEMORY_PROFILE_CONTEXT
);
1715 ProfileBuffer
= (UINT8
*) ProfileBuffer
+ sizeof (MEMORY_PROFILE_CONTEXT
);
1720 Offset
+= sizeof (MEMORY_PROFILE_CONTEXT
);
1722 DriverInfoList
= ContextData
->DriverInfoList
;
1723 for (DriverLink
= DriverInfoList
->ForwardLink
;
1724 DriverLink
!= DriverInfoList
;
1725 DriverLink
= DriverLink
->ForwardLink
) {
1726 DriverInfoData
= CR (
1728 MEMORY_PROFILE_DRIVER_INFO_DATA
,
1730 MEMORY_PROFILE_DRIVER_INFO_SIGNATURE
1732 if (*ProfileOffset
< (Offset
+ DriverInfoData
->DriverInfo
.Header
.Length
)) {
1733 if (RemainingSize
>= DriverInfoData
->DriverInfo
.Header
.Length
) {
1734 DriverInfo
= ProfileBuffer
;
1735 CopyMem (DriverInfo
, &DriverInfoData
->DriverInfo
, sizeof (MEMORY_PROFILE_DRIVER_INFO
));
1736 if (DriverInfo
->PdbStringOffset
!= 0) {
1737 PdbSize
= AsciiStrSize (DriverInfoData
->PdbString
);
1738 CopyMem ((VOID
*) ((UINTN
) DriverInfo
+ DriverInfo
->PdbStringOffset
), DriverInfoData
->PdbString
, PdbSize
);
1740 RemainingSize
-= DriverInfo
->Header
.Length
;
1741 ProfileBuffer
= (UINT8
*) ProfileBuffer
+ DriverInfo
->Header
.Length
;
1746 Offset
+= DriverInfoData
->DriverInfo
.Header
.Length
;
1748 AllocInfoList
= DriverInfoData
->AllocInfoList
;
1749 for (AllocLink
= AllocInfoList
->ForwardLink
;
1750 AllocLink
!= AllocInfoList
;
1751 AllocLink
= AllocLink
->ForwardLink
) {
1752 AllocInfoData
= CR (
1754 MEMORY_PROFILE_ALLOC_INFO_DATA
,
1756 MEMORY_PROFILE_ALLOC_INFO_SIGNATURE
1758 if (*ProfileOffset
< (Offset
+ AllocInfoData
->AllocInfo
.Header
.Length
)) {
1759 if (RemainingSize
>= AllocInfoData
->AllocInfo
.Header
.Length
) {
1760 AllocInfo
= ProfileBuffer
;
1761 CopyMem (AllocInfo
, &AllocInfoData
->AllocInfo
, sizeof (MEMORY_PROFILE_ALLOC_INFO
));
1762 if (AllocInfo
->ActionStringOffset
) {
1763 ActionStringSize
= AsciiStrSize (AllocInfoData
->ActionString
);
1764 CopyMem ((VOID
*) ((UINTN
) AllocInfo
+ AllocInfo
->ActionStringOffset
), AllocInfoData
->ActionString
, ActionStringSize
);
1766 RemainingSize
-= AllocInfo
->Header
.Length
;
1767 ProfileBuffer
= (UINT8
*) ProfileBuffer
+ AllocInfo
->Header
.Length
;
1772 Offset
+= AllocInfoData
->AllocInfo
.Header
.Length
;
1777 if (*ProfileOffset
< (Offset
+ sizeof (MEMORY_PROFILE_FREE_MEMORY
))) {
1778 if (RemainingSize
>= sizeof (MEMORY_PROFILE_FREE_MEMORY
)) {
1779 FreeMemory
= ProfileBuffer
;
1780 CopyMem (FreeMemory
, &mSmramFreeMemory
, sizeof (MEMORY_PROFILE_FREE_MEMORY
));
1782 FreePageList
= &mSmmMemoryMap
;
1783 for (Node
= FreePageList
->BackLink
;
1784 Node
!= FreePageList
;
1785 Node
= Node
->BackLink
) {
1788 for (PoolListIndex
= 0; PoolListIndex
< MAX_POOL_INDEX
; PoolListIndex
++) {
1789 FreePoolList
= &mSmmPoolLists
[MAX_POOL_INDEX
- PoolListIndex
- 1];
1790 for (Node
= FreePoolList
->BackLink
;
1791 Node
!= FreePoolList
;
1792 Node
= Node
->BackLink
) {
1793 Pool
= BASE_CR (Node
, FREE_POOL_HEADER
, Link
);
1794 if (Pool
->Header
.Available
) {
1799 FreeMemory
->FreeMemoryEntryCount
= Index
;
1801 RemainingSize
-= sizeof (MEMORY_PROFILE_FREE_MEMORY
);
1802 ProfileBuffer
= (UINT8
*) ProfileBuffer
+ sizeof (MEMORY_PROFILE_FREE_MEMORY
);
1807 Offset
+= sizeof (MEMORY_PROFILE_FREE_MEMORY
);
1808 FreePageList
= &mSmmMemoryMap
;
1809 for (Node
= FreePageList
->BackLink
;
1810 Node
!= FreePageList
;
1811 Node
= Node
->BackLink
) {
1812 if (*ProfileOffset
< (Offset
+ sizeof (MEMORY_PROFILE_DESCRIPTOR
))) {
1813 if (RemainingSize
>= sizeof (MEMORY_PROFILE_DESCRIPTOR
)) {
1814 Pages
= BASE_CR (Node
, FREE_PAGE_LIST
, Link
);
1815 MemoryProfileDescriptor
= ProfileBuffer
;
1816 MemoryProfileDescriptor
->Header
.Signature
= MEMORY_PROFILE_DESCRIPTOR_SIGNATURE
;
1817 MemoryProfileDescriptor
->Header
.Length
= sizeof (MEMORY_PROFILE_DESCRIPTOR
);
1818 MemoryProfileDescriptor
->Header
.Revision
= MEMORY_PROFILE_DESCRIPTOR_REVISION
;
1819 MemoryProfileDescriptor
->Address
= (PHYSICAL_ADDRESS
) (UINTN
) Pages
;
1820 MemoryProfileDescriptor
->Size
= EFI_PAGES_TO_SIZE (Pages
->NumberOfPages
);
1822 RemainingSize
-= sizeof (MEMORY_PROFILE_DESCRIPTOR
);
1823 ProfileBuffer
= (UINT8
*) ProfileBuffer
+ sizeof (MEMORY_PROFILE_DESCRIPTOR
);
1828 Offset
+= sizeof (MEMORY_PROFILE_DESCRIPTOR
);
1830 for (PoolListIndex
= 0; PoolListIndex
< MAX_POOL_INDEX
; PoolListIndex
++) {
1831 FreePoolList
= &mSmmPoolLists
[MAX_POOL_INDEX
- PoolListIndex
- 1];
1832 for (Node
= FreePoolList
->BackLink
;
1833 Node
!= FreePoolList
;
1834 Node
= Node
->BackLink
) {
1835 Pool
= BASE_CR (Node
, FREE_POOL_HEADER
, Link
);
1836 if (Pool
->Header
.Available
) {
1837 if (*ProfileOffset
< (Offset
+ sizeof (MEMORY_PROFILE_DESCRIPTOR
))) {
1838 if (RemainingSize
>= sizeof (MEMORY_PROFILE_DESCRIPTOR
)) {
1839 MemoryProfileDescriptor
= ProfileBuffer
;
1840 MemoryProfileDescriptor
->Header
.Signature
= MEMORY_PROFILE_DESCRIPTOR_SIGNATURE
;
1841 MemoryProfileDescriptor
->Header
.Length
= sizeof (MEMORY_PROFILE_DESCRIPTOR
);
1842 MemoryProfileDescriptor
->Header
.Revision
= MEMORY_PROFILE_DESCRIPTOR_REVISION
;
1843 MemoryProfileDescriptor
->Address
= (PHYSICAL_ADDRESS
) (UINTN
) Pool
;
1844 MemoryProfileDescriptor
->Size
= Pool
->Header
.Size
;
1846 RemainingSize
-= sizeof (MEMORY_PROFILE_DESCRIPTOR
);
1847 ProfileBuffer
= (UINT8
*) ProfileBuffer
+ sizeof (MEMORY_PROFILE_DESCRIPTOR
);
1852 Offset
+= sizeof (MEMORY_PROFILE_DESCRIPTOR
);
1857 if (*ProfileOffset
< (Offset
+ sizeof (MEMORY_PROFILE_MEMORY_RANGE
))) {
1858 if (RemainingSize
>= sizeof (MEMORY_PROFILE_MEMORY_RANGE
)) {
1859 MemoryRange
= ProfileBuffer
;
1860 MemoryRange
->Header
.Signature
= MEMORY_PROFILE_MEMORY_RANGE_SIGNATURE
;
1861 MemoryRange
->Header
.Length
= sizeof (MEMORY_PROFILE_MEMORY_RANGE
);
1862 MemoryRange
->Header
.Revision
= MEMORY_PROFILE_MEMORY_RANGE_REVISION
;
1863 MemoryRange
->MemoryRangeCount
= (UINT32
) mFullSmramRangeCount
;
1865 RemainingSize
-= sizeof (MEMORY_PROFILE_MEMORY_RANGE
);
1866 ProfileBuffer
= (UINT8
*) ProfileBuffer
+ sizeof (MEMORY_PROFILE_MEMORY_RANGE
);
1871 Offset
+= sizeof (MEMORY_PROFILE_MEMORY_RANGE
);
1872 for (Index
= 0; Index
< mFullSmramRangeCount
; Index
++) {
1873 if (*ProfileOffset
< (Offset
+ sizeof (MEMORY_PROFILE_DESCRIPTOR
))) {
1874 if (RemainingSize
>= sizeof (MEMORY_PROFILE_DESCRIPTOR
)) {
1875 MemoryProfileDescriptor
= ProfileBuffer
;
1876 MemoryProfileDescriptor
->Header
.Signature
= MEMORY_PROFILE_DESCRIPTOR_SIGNATURE
;
1877 MemoryProfileDescriptor
->Header
.Length
= sizeof (MEMORY_PROFILE_DESCRIPTOR
);
1878 MemoryProfileDescriptor
->Header
.Revision
= MEMORY_PROFILE_DESCRIPTOR_REVISION
;
1879 MemoryProfileDescriptor
->Address
= mFullSmramRanges
[Index
].PhysicalStart
;
1880 MemoryProfileDescriptor
->Size
= mFullSmramRanges
[Index
].PhysicalSize
;
1882 RemainingSize
-= sizeof (MEMORY_PROFILE_DESCRIPTOR
);
1883 ProfileBuffer
= (UINT8
*) ProfileBuffer
+ sizeof (MEMORY_PROFILE_DESCRIPTOR
);
1888 Offset
+= sizeof (MEMORY_PROFILE_DESCRIPTOR
);
1893 // On output, actual profile data size copied.
1895 *ProfileSize
-= RemainingSize
;
1897 // On output, next time profile buffer offset to copy.
1899 *ProfileOffset
= Offset
;
1903 Get memory profile data.
1905 @param[in] This The EDKII_SMM_MEMORY_PROFILE_PROTOCOL instance.
1906 @param[in, out] ProfileSize On entry, points to the size in bytes of the ProfileBuffer.
1907 On return, points to the size of the data returned in ProfileBuffer.
1908 @param[out] ProfileBuffer Profile buffer.
1910 @return EFI_SUCCESS Get the memory profile data successfully.
1911 @return EFI_UNSUPPORTED Memory profile is unsupported.
1912 @return EFI_BUFFER_TO_SMALL The ProfileSize is too small for the resulting data.
1913 ProfileSize is updated with the size required.
1918 SmramProfileProtocolGetData (
1919 IN EDKII_SMM_MEMORY_PROFILE_PROTOCOL
*This
,
1920 IN OUT UINT64
*ProfileSize
,
1921 OUT VOID
*ProfileBuffer
1926 MEMORY_PROFILE_CONTEXT_DATA
*ContextData
;
1927 BOOLEAN SmramProfileGettingStatus
;
1929 ContextData
= GetSmramProfileContext ();
1930 if (ContextData
== NULL
) {
1931 return EFI_UNSUPPORTED
;
1934 SmramProfileGettingStatus
= mSmramProfileGettingStatus
;
1935 mSmramProfileGettingStatus
= TRUE
;
1937 Size
= SmramProfileGetDataSize ();
1939 if (*ProfileSize
< Size
) {
1940 *ProfileSize
= Size
;
1941 mSmramProfileGettingStatus
= SmramProfileGettingStatus
;
1942 return EFI_BUFFER_TOO_SMALL
;
1946 SmramProfileCopyData (ProfileBuffer
, &Size
, &Offset
);
1947 *ProfileSize
= Size
;
1949 mSmramProfileGettingStatus
= SmramProfileGettingStatus
;
1954 Register image to memory profile.
1956 @param[in] This The EDKII_SMM_MEMORY_PROFILE_PROTOCOL instance.
1957 @param[in] FilePath File path of the image.
1958 @param[in] ImageBase Image base address.
1959 @param[in] ImageSize Image size.
1960 @param[in] FileType File type of the image.
1962 @return EFI_SUCCESS Register successfully.
1963 @return EFI_UNSUPPORTED Memory profile is unsupported,
1964 or memory profile for the image is not required.
1965 @return EFI_OUT_OF_RESOURCES No enough resource for this register.
1970 SmramProfileProtocolRegisterImage (
1971 IN EDKII_SMM_MEMORY_PROFILE_PROTOCOL
*This
,
1972 IN EFI_DEVICE_PATH_PROTOCOL
*FilePath
,
1973 IN PHYSICAL_ADDRESS ImageBase
,
1974 IN UINT64 ImageSize
,
1975 IN EFI_FV_FILETYPE FileType
1979 EFI_SMM_DRIVER_ENTRY DriverEntry
;
1980 VOID
*EntryPointInImage
;
1983 ZeroMem (&DriverEntry
, sizeof (DriverEntry
));
1984 Name
= GetFileNameFromFilePath (FilePath
);
1986 CopyMem (&DriverEntry
.FileName
, Name
, sizeof (EFI_GUID
));
1988 DriverEntry
.ImageBuffer
= ImageBase
;
1989 DriverEntry
.NumberOfPage
= EFI_SIZE_TO_PAGES ((UINTN
) ImageSize
);
1990 Status
= InternalPeCoffGetEntryPoint ((VOID
*) (UINTN
) DriverEntry
.ImageBuffer
, &EntryPointInImage
);
1991 ASSERT_EFI_ERROR (Status
);
1992 DriverEntry
.ImageEntryPoint
= (PHYSICAL_ADDRESS
) (UINTN
) EntryPointInImage
;
1994 return RegisterSmramProfileImage (&DriverEntry
, FALSE
);
1998 Unregister image from memory profile.
2000 @param[in] This The EDKII_SMM_MEMORY_PROFILE_PROTOCOL instance.
2001 @param[in] FilePath File path of the image.
2002 @param[in] ImageBase Image base address.
2003 @param[in] ImageSize Image size.
2005 @return EFI_SUCCESS Unregister successfully.
2006 @return EFI_UNSUPPORTED Memory profile is unsupported,
2007 or memory profile for the image is not required.
2008 @return EFI_NOT_FOUND The image is not found.
2013 SmramProfileProtocolUnregisterImage (
2014 IN EDKII_SMM_MEMORY_PROFILE_PROTOCOL
*This
,
2015 IN EFI_DEVICE_PATH_PROTOCOL
*FilePath
,
2016 IN PHYSICAL_ADDRESS ImageBase
,
2021 EFI_SMM_DRIVER_ENTRY DriverEntry
;
2022 VOID
*EntryPointInImage
;
2025 ZeroMem (&DriverEntry
, sizeof (DriverEntry
));
2026 Name
= GetFileNameFromFilePath (FilePath
);
2028 CopyMem (&DriverEntry
.FileName
, Name
, sizeof (EFI_GUID
));
2030 DriverEntry
.ImageBuffer
= ImageBase
;
2031 DriverEntry
.NumberOfPage
= EFI_SIZE_TO_PAGES ((UINTN
) ImageSize
);
2032 Status
= InternalPeCoffGetEntryPoint ((VOID
*) (UINTN
) DriverEntry
.ImageBuffer
, &EntryPointInImage
);
2033 ASSERT_EFI_ERROR (Status
);
2034 DriverEntry
.ImageEntryPoint
= (PHYSICAL_ADDRESS
) (UINTN
) EntryPointInImage
;
2036 return UnregisterSmramProfileImage (&DriverEntry
, FALSE
);
2040 Get memory profile recording state.
2042 @param[in] This The EDKII_SMM_MEMORY_PROFILE_PROTOCOL instance.
2043 @param[out] RecordingState Recording state.
2045 @return EFI_SUCCESS Memory profile recording state is returned.
2046 @return EFI_UNSUPPORTED Memory profile is unsupported.
2047 @return EFI_INVALID_PARAMETER RecordingState is NULL.
2052 SmramProfileProtocolGetRecordingState (
2053 IN EDKII_SMM_MEMORY_PROFILE_PROTOCOL
*This
,
2054 OUT BOOLEAN
*RecordingState
2057 MEMORY_PROFILE_CONTEXT_DATA
*ContextData
;
2059 ContextData
= GetSmramProfileContext ();
2060 if (ContextData
== NULL
) {
2061 return EFI_UNSUPPORTED
;
2064 if (RecordingState
== NULL
) {
2065 return EFI_INVALID_PARAMETER
;
2067 *RecordingState
= mSmramProfileRecordingEnable
;
2072 Set memory profile recording state.
2074 @param[in] This The EDKII_SMM_MEMORY_PROFILE_PROTOCOL instance.
2075 @param[in] RecordingState Recording state.
2077 @return EFI_SUCCESS Set memory profile recording state successfully.
2078 @return EFI_UNSUPPORTED Memory profile is unsupported.
2083 SmramProfileProtocolSetRecordingState (
2084 IN EDKII_SMM_MEMORY_PROFILE_PROTOCOL
*This
,
2085 IN BOOLEAN RecordingState
2088 MEMORY_PROFILE_CONTEXT_DATA
*ContextData
;
2090 ContextData
= GetSmramProfileContext ();
2091 if (ContextData
== NULL
) {
2092 return EFI_UNSUPPORTED
;
2095 mSmramProfileRecordingEnable
= RecordingState
;
2100 Record memory profile of multilevel caller.
2102 @param[in] This The EDKII_SMM_MEMORY_PROFILE_PROTOCOL instance.
2103 @param[in] CallerAddress Address of caller.
2104 @param[in] Action Memory profile action.
2105 @param[in] MemoryType Memory type.
2106 EfiMaxMemoryType means the MemoryType is unknown.
2107 @param[in] Buffer Buffer address.
2108 @param[in] Size Buffer size.
2109 @param[in] ActionString String for memory profile action.
2110 Only needed for user defined allocate action.
2112 @return EFI_SUCCESS Memory profile is updated.
2113 @return EFI_UNSUPPORTED Memory profile is unsupported,
2114 or memory profile for the image is not required,
2115 or memory profile for the memory type is not required.
2116 @return EFI_ACCESS_DENIED It is during memory profile data getting.
2117 @return EFI_ABORTED Memory profile recording is not enabled.
2118 @return EFI_OUT_OF_RESOURCES No enough resource to update memory profile for allocate action.
2119 @return EFI_NOT_FOUND No matched allocate info found for free action.
2124 SmramProfileProtocolRecord (
2125 IN EDKII_SMM_MEMORY_PROFILE_PROTOCOL
*This
,
2126 IN PHYSICAL_ADDRESS CallerAddress
,
2127 IN MEMORY_PROFILE_ACTION Action
,
2128 IN EFI_MEMORY_TYPE MemoryType
,
2131 IN CHAR8
*ActionString OPTIONAL
2134 return SmmCoreUpdateProfile (CallerAddress
, Action
, MemoryType
, Size
, Buffer
, ActionString
);
2138 SMRAM profile handler to get profile info.
2140 @param SmramProfileParameterGetInfo The parameter of SMM profile get size.
2144 SmramProfileHandlerGetInfo (
2145 IN SMRAM_PROFILE_PARAMETER_GET_PROFILE_INFO
*SmramProfileParameterGetInfo
2148 MEMORY_PROFILE_CONTEXT_DATA
*ContextData
;
2149 BOOLEAN SmramProfileGettingStatus
;
2151 ContextData
= GetSmramProfileContext ();
2152 if (ContextData
== NULL
) {
2156 SmramProfileGettingStatus
= mSmramProfileGettingStatus
;
2157 mSmramProfileGettingStatus
= TRUE
;
2159 SmramProfileParameterGetInfo
->ProfileSize
= SmramProfileGetDataSize();
2160 SmramProfileParameterGetInfo
->Header
.ReturnStatus
= 0;
2162 mSmramProfileGettingStatus
= SmramProfileGettingStatus
;
2166 SMRAM profile handler to get profile data.
2168 @param SmramProfileParameterGetData The parameter of SMM profile get data.
2172 SmramProfileHandlerGetData (
2173 IN SMRAM_PROFILE_PARAMETER_GET_PROFILE_DATA
*SmramProfileParameterGetData
2177 UINT64 ProfileOffset
;
2178 SMRAM_PROFILE_PARAMETER_GET_PROFILE_DATA SmramProfileGetData
;
2179 MEMORY_PROFILE_CONTEXT_DATA
*ContextData
;
2180 BOOLEAN SmramProfileGettingStatus
;
2182 ContextData
= GetSmramProfileContext ();
2183 if (ContextData
== NULL
) {
2187 SmramProfileGettingStatus
= mSmramProfileGettingStatus
;
2188 mSmramProfileGettingStatus
= TRUE
;
2191 CopyMem (&SmramProfileGetData
, SmramProfileParameterGetData
, sizeof (SmramProfileGetData
));
2193 ProfileSize
= SmramProfileGetDataSize();
2198 if (!SmmIsBufferOutsideSmmValid ((UINTN
) SmramProfileGetData
.ProfileBuffer
, (UINTN
) ProfileSize
)) {
2199 DEBUG ((EFI_D_ERROR
, "SmramProfileHandlerGetData: SMM ProfileBuffer in SMRAM or overflow!\n"));
2200 SmramProfileParameterGetData
->ProfileSize
= ProfileSize
;
2201 SmramProfileParameterGetData
->Header
.ReturnStatus
= (UINT64
) (INT64
) (INTN
) EFI_ACCESS_DENIED
;
2205 if (SmramProfileGetData
.ProfileSize
< ProfileSize
) {
2206 SmramProfileParameterGetData
->ProfileSize
= ProfileSize
;
2207 SmramProfileParameterGetData
->Header
.ReturnStatus
= (UINT64
) (INT64
) (INTN
) EFI_BUFFER_TOO_SMALL
;
2212 SmramProfileCopyData ((VOID
*) (UINTN
) SmramProfileGetData
.ProfileBuffer
, &ProfileSize
, &ProfileOffset
);
2213 SmramProfileParameterGetData
->ProfileSize
= ProfileSize
;
2214 SmramProfileParameterGetData
->Header
.ReturnStatus
= 0;
2217 mSmramProfileGettingStatus
= SmramProfileGettingStatus
;
2221 SMRAM profile handler to get profile data by offset.
2223 @param SmramProfileParameterGetDataByOffset The parameter of SMM profile get data by offset.
2227 SmramProfileHandlerGetDataByOffset (
2228 IN SMRAM_PROFILE_PARAMETER_GET_PROFILE_DATA_BY_OFFSET
*SmramProfileParameterGetDataByOffset
2231 SMRAM_PROFILE_PARAMETER_GET_PROFILE_DATA_BY_OFFSET SmramProfileGetDataByOffset
;
2232 MEMORY_PROFILE_CONTEXT_DATA
*ContextData
;
2233 BOOLEAN SmramProfileGettingStatus
;
2235 ContextData
= GetSmramProfileContext ();
2236 if (ContextData
== NULL
) {
2240 SmramProfileGettingStatus
= mSmramProfileGettingStatus
;
2241 mSmramProfileGettingStatus
= TRUE
;
2244 CopyMem (&SmramProfileGetDataByOffset
, SmramProfileParameterGetDataByOffset
, sizeof (SmramProfileGetDataByOffset
));
2249 if (!SmmIsBufferOutsideSmmValid ((UINTN
) SmramProfileGetDataByOffset
.ProfileBuffer
, (UINTN
) SmramProfileGetDataByOffset
.ProfileSize
)) {
2250 DEBUG ((EFI_D_ERROR
, "SmramProfileHandlerGetDataByOffset: SMM ProfileBuffer in SMRAM or overflow!\n"));
2251 SmramProfileParameterGetDataByOffset
->Header
.ReturnStatus
= (UINT64
) (INT64
) (INTN
) EFI_ACCESS_DENIED
;
2255 SmramProfileCopyData ((VOID
*) (UINTN
) SmramProfileGetDataByOffset
.ProfileBuffer
, &SmramProfileGetDataByOffset
.ProfileSize
, &SmramProfileGetDataByOffset
.ProfileOffset
);
2256 CopyMem (SmramProfileParameterGetDataByOffset
, &SmramProfileGetDataByOffset
, sizeof (SmramProfileGetDataByOffset
));
2257 SmramProfileParameterGetDataByOffset
->Header
.ReturnStatus
= 0;
2260 mSmramProfileGettingStatus
= SmramProfileGettingStatus
;
2264 SMRAM profile handler to register SMM image.
2266 @param SmramProfileParameterRegisterImage The parameter of SMM profile register image.
2270 SmramProfileHandlerRegisterImage (
2271 IN SMRAM_PROFILE_PARAMETER_REGISTER_IMAGE
*SmramProfileParameterRegisterImage
2275 EFI_SMM_DRIVER_ENTRY DriverEntry
;
2276 VOID
*EntryPointInImage
;
2278 ZeroMem (&DriverEntry
, sizeof (DriverEntry
));
2279 CopyMem (&DriverEntry
.FileName
, &SmramProfileParameterRegisterImage
->FileName
, sizeof(EFI_GUID
));
2280 DriverEntry
.ImageBuffer
= SmramProfileParameterRegisterImage
->ImageBuffer
;
2281 DriverEntry
.NumberOfPage
= (UINTN
) SmramProfileParameterRegisterImage
->NumberOfPage
;
2282 Status
= InternalPeCoffGetEntryPoint ((VOID
*) (UINTN
) DriverEntry
.ImageBuffer
, &EntryPointInImage
);
2283 ASSERT_EFI_ERROR (Status
);
2284 DriverEntry
.ImageEntryPoint
= (PHYSICAL_ADDRESS
) (UINTN
) EntryPointInImage
;
2286 Status
= RegisterSmramProfileImage (&DriverEntry
, FALSE
);
2287 if (!EFI_ERROR (Status
)) {
2288 SmramProfileParameterRegisterImage
->Header
.ReturnStatus
= 0;
2293 SMRAM profile handler to unregister SMM image.
2295 @param SmramProfileParameterUnregisterImage The parameter of SMM profile unregister image.
2299 SmramProfileHandlerUnregisterImage (
2300 IN SMRAM_PROFILE_PARAMETER_UNREGISTER_IMAGE
*SmramProfileParameterUnregisterImage
2304 EFI_SMM_DRIVER_ENTRY DriverEntry
;
2305 VOID
*EntryPointInImage
;
2307 ZeroMem (&DriverEntry
, sizeof (DriverEntry
));
2308 CopyMem (&DriverEntry
.FileName
, &SmramProfileParameterUnregisterImage
->FileName
, sizeof (EFI_GUID
));
2309 DriverEntry
.ImageBuffer
= SmramProfileParameterUnregisterImage
->ImageBuffer
;
2310 DriverEntry
.NumberOfPage
= (UINTN
) SmramProfileParameterUnregisterImage
->NumberOfPage
;
2311 Status
= InternalPeCoffGetEntryPoint ((VOID
*) (UINTN
) DriverEntry
.ImageBuffer
, &EntryPointInImage
);
2312 ASSERT_EFI_ERROR (Status
);
2313 DriverEntry
.ImageEntryPoint
= (PHYSICAL_ADDRESS
) (UINTN
) EntryPointInImage
;
2315 Status
= UnregisterSmramProfileImage (&DriverEntry
, FALSE
);
2316 if (!EFI_ERROR (Status
)) {
2317 SmramProfileParameterUnregisterImage
->Header
.ReturnStatus
= 0;
2322 Dispatch function for a Software SMI handler.
2324 Caution: This function may receive untrusted input.
2325 Communicate buffer and buffer size are external input, so this function will do basic validation.
2327 @param DispatchHandle The unique handle assigned to this handler by SmiHandlerRegister().
2328 @param Context Points to an optional handler context which was specified when the
2329 handler was registered.
2330 @param CommBuffer A pointer to a collection of data in memory that will
2331 be conveyed from a non-SMM environment into an SMM environment.
2332 @param CommBufferSize The size of the CommBuffer.
2334 @retval EFI_SUCCESS Command is handled successfully.
2339 SmramProfileHandler (
2340 IN EFI_HANDLE DispatchHandle
,
2341 IN CONST VOID
*Context OPTIONAL
,
2342 IN OUT VOID
*CommBuffer OPTIONAL
,
2343 IN OUT UINTN
*CommBufferSize OPTIONAL
2346 SMRAM_PROFILE_PARAMETER_HEADER
*SmramProfileParameterHeader
;
2347 UINTN TempCommBufferSize
;
2348 SMRAM_PROFILE_PARAMETER_RECORDING_STATE
*ParameterRecordingState
;
2350 DEBUG ((EFI_D_ERROR
, "SmramProfileHandler Enter\n"));
2353 // If input is invalid, stop processing this SMI
2355 if (CommBuffer
== NULL
|| CommBufferSize
== NULL
) {
2359 TempCommBufferSize
= *CommBufferSize
;
2361 if (TempCommBufferSize
< sizeof (SMRAM_PROFILE_PARAMETER_HEADER
)) {
2362 DEBUG ((EFI_D_ERROR
, "SmramProfileHandler: SMM communication buffer size invalid!\n"));
2366 if (mSmramReadyToLock
&& !SmmIsBufferOutsideSmmValid ((UINTN
)CommBuffer
, TempCommBufferSize
)) {
2367 DEBUG ((EFI_D_ERROR
, "SmramProfileHandler: SMM communication buffer in SMRAM or overflow!\n"));
2371 SmramProfileParameterHeader
= (SMRAM_PROFILE_PARAMETER_HEADER
*) ((UINTN
) CommBuffer
);
2373 SmramProfileParameterHeader
->ReturnStatus
= (UINT64
)-1;
2375 if (GetSmramProfileContext () == NULL
) {
2376 SmramProfileParameterHeader
->ReturnStatus
= (UINT64
) (INT64
) (INTN
) EFI_UNSUPPORTED
;
2380 switch (SmramProfileParameterHeader
->Command
) {
2381 case SMRAM_PROFILE_COMMAND_GET_PROFILE_INFO
:
2382 DEBUG ((EFI_D_ERROR
, "SmramProfileHandlerGetInfo\n"));
2383 if (TempCommBufferSize
!= sizeof (SMRAM_PROFILE_PARAMETER_GET_PROFILE_INFO
)) {
2384 DEBUG ((EFI_D_ERROR
, "SmramProfileHandler: SMM communication buffer size invalid!\n"));
2387 SmramProfileHandlerGetInfo ((SMRAM_PROFILE_PARAMETER_GET_PROFILE_INFO
*) (UINTN
) CommBuffer
);
2389 case SMRAM_PROFILE_COMMAND_GET_PROFILE_DATA
:
2390 DEBUG ((EFI_D_ERROR
, "SmramProfileHandlerGetData\n"));
2391 if (TempCommBufferSize
!= sizeof (SMRAM_PROFILE_PARAMETER_GET_PROFILE_DATA
)) {
2392 DEBUG ((EFI_D_ERROR
, "SmramProfileHandler: SMM communication buffer size invalid!\n"));
2395 SmramProfileHandlerGetData ((SMRAM_PROFILE_PARAMETER_GET_PROFILE_DATA
*) (UINTN
) CommBuffer
);
2397 case SMRAM_PROFILE_COMMAND_GET_PROFILE_DATA_BY_OFFSET
:
2398 DEBUG ((EFI_D_ERROR
, "SmramProfileHandlerGetDataByOffset\n"));
2399 if (TempCommBufferSize
!= sizeof (SMRAM_PROFILE_PARAMETER_GET_PROFILE_DATA_BY_OFFSET
)) {
2400 DEBUG ((EFI_D_ERROR
, "SmramProfileHandler: SMM communication buffer size invalid!\n"));
2403 SmramProfileHandlerGetDataByOffset ((SMRAM_PROFILE_PARAMETER_GET_PROFILE_DATA_BY_OFFSET
*) (UINTN
) CommBuffer
);
2405 case SMRAM_PROFILE_COMMAND_REGISTER_IMAGE
:
2406 DEBUG ((EFI_D_ERROR
, "SmramProfileHandlerRegisterImage\n"));
2407 if (TempCommBufferSize
!= sizeof (SMRAM_PROFILE_PARAMETER_REGISTER_IMAGE
)) {
2408 DEBUG ((EFI_D_ERROR
, "SmramProfileHandler: SMM communication buffer size invalid!\n"));
2411 if (mSmramReadyToLock
) {
2414 SmramProfileHandlerRegisterImage ((SMRAM_PROFILE_PARAMETER_REGISTER_IMAGE
*) (UINTN
) CommBuffer
);
2416 case SMRAM_PROFILE_COMMAND_UNREGISTER_IMAGE
:
2417 DEBUG ((EFI_D_ERROR
, "SmramProfileHandlerUnregisterImage\n"));
2418 if (TempCommBufferSize
!= sizeof (SMRAM_PROFILE_PARAMETER_UNREGISTER_IMAGE
)) {
2419 DEBUG ((EFI_D_ERROR
, "SmramProfileHandler: SMM communication buffer size invalid!\n"));
2422 if (mSmramReadyToLock
) {
2425 SmramProfileHandlerUnregisterImage ((SMRAM_PROFILE_PARAMETER_UNREGISTER_IMAGE
*) (UINTN
) CommBuffer
);
2427 case SMRAM_PROFILE_COMMAND_GET_RECORDING_STATE
:
2428 DEBUG ((EFI_D_ERROR
, "SmramProfileHandlerGetRecordingState\n"));
2429 if (TempCommBufferSize
!= sizeof (SMRAM_PROFILE_PARAMETER_RECORDING_STATE
)) {
2430 DEBUG ((EFI_D_ERROR
, "SmramProfileHandler: SMM communication buffer size invalid!\n"));
2433 ParameterRecordingState
= (SMRAM_PROFILE_PARAMETER_RECORDING_STATE
*) (UINTN
) CommBuffer
;
2434 ParameterRecordingState
->RecordingState
= mSmramProfileRecordingEnable
;
2435 ParameterRecordingState
->Header
.ReturnStatus
= 0;
2437 case SMRAM_PROFILE_COMMAND_SET_RECORDING_STATE
:
2438 DEBUG ((EFI_D_ERROR
, "SmramProfileHandlerSetRecordingState\n"));
2439 if (TempCommBufferSize
!= sizeof (SMRAM_PROFILE_PARAMETER_RECORDING_STATE
)) {
2440 DEBUG ((EFI_D_ERROR
, "SmramProfileHandler: SMM communication buffer size invalid!\n"));
2443 ParameterRecordingState
= (SMRAM_PROFILE_PARAMETER_RECORDING_STATE
*) (UINTN
) CommBuffer
;
2444 mSmramProfileRecordingEnable
= ParameterRecordingState
->RecordingState
;
2445 ParameterRecordingState
->Header
.ReturnStatus
= 0;
2452 DEBUG ((EFI_D_ERROR
, "SmramProfileHandler Exit\n"));
2458 Register SMRAM profile handler.
2462 RegisterSmramProfileHandler (
2467 EFI_HANDLE DispatchHandle
;
2469 if (!IS_SMRAM_PROFILE_ENABLED
) {
2473 Status
= SmiHandlerRegister (
2474 SmramProfileHandler
,
2475 &gEdkiiMemoryProfileGuid
,
2478 ASSERT_EFI_ERROR (Status
);
2481 ////////////////////
2493 MEMORY_PROFILE_CONTEXT_DATA
*ContextData
;
2494 BOOLEAN SmramProfileGettingStatus
;
2496 ContextData
= GetSmramProfileContext ();
2497 if (ContextData
== NULL
) {
2501 SmramProfileGettingStatus
= mSmramProfileGettingStatus
;
2502 mSmramProfileGettingStatus
= TRUE
;
2504 DEBUG ((EFI_D_INFO
, "FullSmramRange address - 0x%08x\n", mFullSmramRanges
));
2506 DEBUG ((EFI_D_INFO
, "======= SmramProfile begin =======\n"));
2508 DEBUG ((EFI_D_INFO
, "FullSmramRange:\n"));
2509 for (Index
= 0; Index
< mFullSmramRangeCount
; Index
++) {
2510 DEBUG ((EFI_D_INFO
, " FullSmramRange (0x%x)\n", Index
));
2511 DEBUG ((EFI_D_INFO
, " PhysicalStart - 0x%016lx\n", mFullSmramRanges
[Index
].PhysicalStart
));
2512 DEBUG ((EFI_D_INFO
, " CpuStart - 0x%016lx\n", mFullSmramRanges
[Index
].CpuStart
));
2513 DEBUG ((EFI_D_INFO
, " PhysicalSize - 0x%016lx\n", mFullSmramRanges
[Index
].PhysicalSize
));
2514 DEBUG ((EFI_D_INFO
, " RegionState - 0x%016lx\n", mFullSmramRanges
[Index
].RegionState
));
2517 DEBUG ((EFI_D_INFO
, "======= SmramProfile end =======\n"));
2519 mSmramProfileGettingStatus
= SmramProfileGettingStatus
;
2523 Dump SMRAM free page list.
2531 LIST_ENTRY
*FreePageList
;
2533 FREE_PAGE_LIST
*Pages
;
2535 MEMORY_PROFILE_CONTEXT_DATA
*ContextData
;
2536 BOOLEAN SmramProfileGettingStatus
;
2538 ContextData
= GetSmramProfileContext ();
2539 if (ContextData
== NULL
) {
2543 SmramProfileGettingStatus
= mSmramProfileGettingStatus
;
2544 mSmramProfileGettingStatus
= TRUE
;
2546 DEBUG ((EFI_D_INFO
, "======= SmramProfile begin =======\n"));
2548 DEBUG ((EFI_D_INFO
, "FreePagesList:\n"));
2549 FreePageList
= &mSmmMemoryMap
;
2550 for (Node
= FreePageList
->BackLink
, Index
= 0;
2551 Node
!= FreePageList
;
2552 Node
= Node
->BackLink
, Index
++) {
2553 Pages
= BASE_CR (Node
, FREE_PAGE_LIST
, Link
);
2554 DEBUG ((EFI_D_INFO
, " Index - 0x%x\n", Index
));
2555 DEBUG ((EFI_D_INFO
, " PhysicalStart - 0x%016lx\n", (PHYSICAL_ADDRESS
) (UINTN
) Pages
));
2556 DEBUG ((EFI_D_INFO
, " NumberOfPages - 0x%08x\n", Pages
->NumberOfPages
));
2559 DEBUG ((EFI_D_INFO
, "======= SmramProfile end =======\n"));
2561 mSmramProfileGettingStatus
= SmramProfileGettingStatus
;
2565 Dump SMRAM free pool list.
2573 LIST_ENTRY
*FreePoolList
;
2575 FREE_POOL_HEADER
*Pool
;
2577 UINTN PoolListIndex
;
2578 MEMORY_PROFILE_CONTEXT_DATA
*ContextData
;
2579 BOOLEAN SmramProfileGettingStatus
;
2581 ContextData
= GetSmramProfileContext ();
2582 if (ContextData
== NULL
) {
2586 SmramProfileGettingStatus
= mSmramProfileGettingStatus
;
2587 mSmramProfileGettingStatus
= TRUE
;
2589 DEBUG ((EFI_D_INFO
, "======= SmramProfile begin =======\n"));
2591 for (PoolListIndex
= 0; PoolListIndex
< MAX_POOL_INDEX
; PoolListIndex
++) {
2592 DEBUG ((EFI_D_INFO
, "FreePoolList (%d):\n", PoolListIndex
));
2593 FreePoolList
= &mSmmPoolLists
[PoolListIndex
];
2594 for (Node
= FreePoolList
->BackLink
, Index
= 0;
2595 Node
!= FreePoolList
;
2596 Node
= Node
->BackLink
, Index
++) {
2597 Pool
= BASE_CR (Node
, FREE_POOL_HEADER
, Link
);
2598 DEBUG ((EFI_D_INFO
, " Index - 0x%x\n", Index
));
2599 DEBUG ((EFI_D_INFO
, " PhysicalStart - 0x%016lx\n", (PHYSICAL_ADDRESS
) (UINTN
) Pool
));
2600 DEBUG ((EFI_D_INFO
, " Size - 0x%08x\n", Pool
->Header
.Size
));
2601 DEBUG ((EFI_D_INFO
, " Available - 0x%02x\n", Pool
->Header
.Available
));
2605 DEBUG ((EFI_D_INFO
, "======= SmramProfile end =======\n"));
2607 mSmramProfileGettingStatus
= SmramProfileGettingStatus
;
2610 GLOBAL_REMOVE_IF_UNREFERENCED CHAR8
*mSmmActionString
[] = {
2612 "gSmst->SmmAllocatePages",
2613 "gSmst->SmmFreePages",
2614 "gSmst->SmmAllocatePool",
2615 "gSmst->SmmFreePool",
2619 MEMORY_PROFILE_ACTION Action
;
2623 ACTION_STRING mExtActionString
[] = {
2624 {MEMORY_PROFILE_ACTION_LIB_ALLOCATE_PAGES
, "Lib:AllocatePages"},
2625 {MEMORY_PROFILE_ACTION_LIB_ALLOCATE_RUNTIME_PAGES
, "Lib:AllocateRuntimePages"},
2626 {MEMORY_PROFILE_ACTION_LIB_ALLOCATE_RESERVED_PAGES
, "Lib:AllocateReservedPages"},
2627 {MEMORY_PROFILE_ACTION_LIB_FREE_PAGES
, "Lib:FreePages"},
2628 {MEMORY_PROFILE_ACTION_LIB_ALLOCATE_ALIGNED_PAGES
, "Lib:AllocateAlignedPages"},
2629 {MEMORY_PROFILE_ACTION_LIB_ALLOCATE_ALIGNED_RUNTIME_PAGES
, "Lib:AllocateAlignedRuntimePages"},
2630 {MEMORY_PROFILE_ACTION_LIB_ALLOCATE_ALIGNED_RESERVED_PAGES
, "Lib:AllocateAlignedReservedPages"},
2631 {MEMORY_PROFILE_ACTION_LIB_FREE_ALIGNED_PAGES
, "Lib:FreeAlignedPages"},
2632 {MEMORY_PROFILE_ACTION_LIB_ALLOCATE_POOL
, "Lib:AllocatePool"},
2633 {MEMORY_PROFILE_ACTION_LIB_ALLOCATE_RUNTIME_POOL
, "Lib:AllocateRuntimePool"},
2634 {MEMORY_PROFILE_ACTION_LIB_ALLOCATE_RESERVED_POOL
, "Lib:AllocateReservedPool"},
2635 {MEMORY_PROFILE_ACTION_LIB_FREE_POOL
, "Lib:FreePool"},
2636 {MEMORY_PROFILE_ACTION_LIB_ALLOCATE_ZERO_POOL
, "Lib:AllocateZeroPool"},
2637 {MEMORY_PROFILE_ACTION_LIB_ALLOCATE_RUNTIME_ZERO_POOL
, "Lib:AllocateRuntimeZeroPool"},
2638 {MEMORY_PROFILE_ACTION_LIB_ALLOCATE_RESERVED_ZERO_POOL
, "Lib:AllocateReservedZeroPool"},
2639 {MEMORY_PROFILE_ACTION_LIB_ALLOCATE_COPY_POOL
, "Lib:AllocateCopyPool"},
2640 {MEMORY_PROFILE_ACTION_LIB_ALLOCATE_RUNTIME_COPY_POOL
, "Lib:AllocateRuntimeCopyPool"},
2641 {MEMORY_PROFILE_ACTION_LIB_ALLOCATE_RESERVED_COPY_POOL
, "Lib:AllocateReservedCopyPool"},
2642 {MEMORY_PROFILE_ACTION_LIB_REALLOCATE_POOL
, "Lib:ReallocatePool"},
2643 {MEMORY_PROFILE_ACTION_LIB_REALLOCATE_RUNTIME_POOL
, "Lib:ReallocateRuntimePool"},
2644 {MEMORY_PROFILE_ACTION_LIB_REALLOCATE_RESERVED_POOL
, "Lib:ReallocateReservedPool"},
2647 GLOBAL_REMOVE_IF_UNREFERENCED CHAR8 mUserDefinedActionString
[] = {"UserDefined-0x80000000"};
2650 EFI_MEMORY_TYPE MemoryType
;
2651 CHAR8
*MemoryTypeStr
;
2652 } PROFILE_MEMORY_TYPE_STRING
;
2654 GLOBAL_REMOVE_IF_UNREFERENCED PROFILE_MEMORY_TYPE_STRING mMemoryTypeString
[] = {
2655 {EfiRuntimeServicesCode
, "EfiRuntimeServicesCode"},
2656 {EfiRuntimeServicesData
, "EfiRuntimeServicesData"}
2660 Memory type to string.
2662 @param[in] MemoryType Memory type.
2664 @return Pointer to string.
2668 ProfileMemoryTypeToStr (
2669 IN EFI_MEMORY_TYPE MemoryType
2673 for (Index
= 0; Index
< sizeof (mMemoryTypeString
) / sizeof (mMemoryTypeString
[0]); Index
++) {
2674 if (mMemoryTypeString
[Index
].MemoryType
== MemoryType
) {
2675 return mMemoryTypeString
[Index
].MemoryTypeStr
;
2679 return "UnexpectedMemoryType";
2685 @param[in] Action Profile action.
2687 @return Pointer to string.
2691 ProfileActionToStr (
2692 IN MEMORY_PROFILE_ACTION Action
2696 UINTN ActionStringCount
;
2697 CHAR8
**ActionString
;
2699 ActionString
= mSmmActionString
;
2700 ActionStringCount
= sizeof (mSmmActionString
) / sizeof (mSmmActionString
[0]);
2702 if ((UINTN
) (UINT32
) Action
< ActionStringCount
) {
2703 return ActionString
[Action
];
2705 for (Index
= 0; Index
< sizeof (mExtActionString
) / sizeof (mExtActionString
[0]); Index
++) {
2706 if (mExtActionString
[Index
].Action
== Action
) {
2707 return mExtActionString
[Index
].String
;
2711 return ActionString
[0];
2723 MEMORY_PROFILE_CONTEXT
*Context
;
2724 MEMORY_PROFILE_DRIVER_INFO
*DriverInfo
;
2725 MEMORY_PROFILE_ALLOC_INFO
*AllocInfo
;
2726 MEMORY_PROFILE_CONTEXT_DATA
*ContextData
;
2727 MEMORY_PROFILE_DRIVER_INFO_DATA
*DriverInfoData
;
2728 MEMORY_PROFILE_ALLOC_INFO_DATA
*AllocInfoData
;
2729 LIST_ENTRY
*SmramDriverInfoList
;
2731 LIST_ENTRY
*DriverLink
;
2732 LIST_ENTRY
*AllocInfoList
;
2734 LIST_ENTRY
*AllocLink
;
2735 BOOLEAN SmramProfileGettingStatus
;
2738 ContextData
= GetSmramProfileContext ();
2739 if (ContextData
== NULL
) {
2743 SmramProfileGettingStatus
= mSmramProfileGettingStatus
;
2744 mSmramProfileGettingStatus
= TRUE
;
2746 Context
= &ContextData
->Context
;
2747 DEBUG ((EFI_D_INFO
, "======= SmramProfile begin =======\n"));
2748 DEBUG ((EFI_D_INFO
, "MEMORY_PROFILE_CONTEXT\n"));
2750 DEBUG ((EFI_D_INFO
, " CurrentTotalUsage - 0x%016lx\n", Context
->CurrentTotalUsage
));
2751 DEBUG ((EFI_D_INFO
, " PeakTotalUsage - 0x%016lx\n", Context
->PeakTotalUsage
));
2752 for (TypeIndex
= 0; TypeIndex
< sizeof (Context
->CurrentTotalUsageByType
) / sizeof (Context
->CurrentTotalUsageByType
[0]); TypeIndex
++) {
2753 if ((Context
->CurrentTotalUsageByType
[TypeIndex
] != 0) ||
2754 (Context
->PeakTotalUsageByType
[TypeIndex
] != 0)) {
2755 DEBUG ((EFI_D_INFO
, " CurrentTotalUsage[0x%02x] - 0x%016lx (%a)\n", TypeIndex
, Context
->CurrentTotalUsageByType
[TypeIndex
], ProfileMemoryTypeToStr (TypeIndex
)));
2756 DEBUG ((EFI_D_INFO
, " PeakTotalUsage[0x%02x] - 0x%016lx (%a)\n", TypeIndex
, Context
->PeakTotalUsageByType
[TypeIndex
], ProfileMemoryTypeToStr (TypeIndex
)));
2759 DEBUG ((EFI_D_INFO
, " TotalImageSize - 0x%016lx\n", Context
->TotalImageSize
));
2760 DEBUG ((EFI_D_INFO
, " ImageCount - 0x%08x\n", Context
->ImageCount
));
2761 DEBUG ((EFI_D_INFO
, " SequenceCount - 0x%08x\n", Context
->SequenceCount
));
2763 SmramDriverInfoList
= ContextData
->DriverInfoList
;
2764 for (DriverLink
= SmramDriverInfoList
->ForwardLink
, DriverIndex
= 0;
2765 DriverLink
!= SmramDriverInfoList
;
2766 DriverLink
= DriverLink
->ForwardLink
, DriverIndex
++) {
2767 DriverInfoData
= CR (
2769 MEMORY_PROFILE_DRIVER_INFO_DATA
,
2771 MEMORY_PROFILE_DRIVER_INFO_SIGNATURE
2773 DriverInfo
= &DriverInfoData
->DriverInfo
;
2774 DEBUG ((EFI_D_INFO
, " MEMORY_PROFILE_DRIVER_INFO (0x%x)\n", DriverIndex
));
2775 DEBUG ((EFI_D_INFO
, " FileName - %g\n", &DriverInfo
->FileName
));
2776 DEBUG ((EFI_D_INFO
, " ImageBase - 0x%016lx\n", DriverInfo
->ImageBase
));
2777 DEBUG ((EFI_D_INFO
, " ImageSize - 0x%016lx\n", DriverInfo
->ImageSize
));
2778 DEBUG ((EFI_D_INFO
, " EntryPoint - 0x%016lx\n", DriverInfo
->EntryPoint
));
2779 DEBUG ((EFI_D_INFO
, " ImageSubsystem - 0x%04x\n", DriverInfo
->ImageSubsystem
));
2780 DEBUG ((EFI_D_INFO
, " FileType - 0x%02x\n", DriverInfo
->FileType
));
2781 DEBUG ((EFI_D_INFO
, " CurrentUsage - 0x%016lx\n", DriverInfo
->CurrentUsage
));
2782 DEBUG ((EFI_D_INFO
, " PeakUsage - 0x%016lx\n", DriverInfo
->PeakUsage
));
2783 for (TypeIndex
= 0; TypeIndex
< sizeof (DriverInfo
->CurrentUsageByType
) / sizeof (DriverInfo
->CurrentUsageByType
[0]); TypeIndex
++) {
2784 if ((DriverInfo
->CurrentUsageByType
[TypeIndex
] != 0) ||
2785 (DriverInfo
->PeakUsageByType
[TypeIndex
] != 0)) {
2786 DEBUG ((EFI_D_INFO
, " CurrentUsage[0x%02x] - 0x%016lx (%a)\n", TypeIndex
, DriverInfo
->CurrentUsageByType
[TypeIndex
], ProfileMemoryTypeToStr (TypeIndex
)));
2787 DEBUG ((EFI_D_INFO
, " PeakUsage[0x%02x] - 0x%016lx (%a)\n", TypeIndex
, DriverInfo
->PeakUsageByType
[TypeIndex
], ProfileMemoryTypeToStr (TypeIndex
)));
2790 DEBUG ((EFI_D_INFO
, " AllocRecordCount - 0x%08x\n", DriverInfo
->AllocRecordCount
));
2792 AllocInfoList
= DriverInfoData
->AllocInfoList
;
2793 for (AllocLink
= AllocInfoList
->ForwardLink
, AllocIndex
= 0;
2794 AllocLink
!= AllocInfoList
;
2795 AllocLink
= AllocLink
->ForwardLink
, AllocIndex
++) {
2796 AllocInfoData
= CR (
2798 MEMORY_PROFILE_ALLOC_INFO_DATA
,
2800 MEMORY_PROFILE_ALLOC_INFO_SIGNATURE
2802 AllocInfo
= &AllocInfoData
->AllocInfo
;
2803 DEBUG ((EFI_D_INFO
, " MEMORY_PROFILE_ALLOC_INFO (0x%x)\n", AllocIndex
));
2804 DEBUG ((EFI_D_INFO
, " CallerAddress - 0x%016lx (Offset: 0x%08x)\n", AllocInfo
->CallerAddress
, AllocInfo
->CallerAddress
- DriverInfo
->ImageBase
));
2805 DEBUG ((EFI_D_INFO
, " SequenceId - 0x%08x\n", AllocInfo
->SequenceId
));
2806 if ((AllocInfo
->Action
& MEMORY_PROFILE_ACTION_USER_DEFINED_MASK
) != 0) {
2807 if (AllocInfoData
->ActionString
!= NULL
) {
2808 DEBUG ((EFI_D_INFO
, " Action - 0x%08x (%a)\n", AllocInfo
->Action
, AllocInfoData
->ActionString
));
2810 DEBUG ((EFI_D_INFO
, " Action - 0x%08x (UserDefined-0x%08x)\n", AllocInfo
->Action
, AllocInfo
->Action
));
2813 DEBUG ((EFI_D_INFO
, " Action - 0x%08x (%a)\n", AllocInfo
->Action
, ProfileActionToStr (AllocInfo
->Action
)));
2815 DEBUG ((EFI_D_INFO
, " MemoryType - 0x%08x (%a)\n", AllocInfo
->MemoryType
, ProfileMemoryTypeToStr (AllocInfo
->MemoryType
)));
2816 DEBUG ((EFI_D_INFO
, " Buffer - 0x%016lx\n", AllocInfo
->Buffer
));
2817 DEBUG ((EFI_D_INFO
, " Size - 0x%016lx\n", AllocInfo
->Size
));
2821 DEBUG ((EFI_D_INFO
, "======= SmramProfile end =======\n"));
2823 mSmramProfileGettingStatus
= SmramProfileGettingStatus
;
2827 Dump SMRAM infromation.
2836 if (IS_SMRAM_PROFILE_ENABLED
) {
2837 DumpSmramProfile ();
2838 DumpFreePagesList ();
2839 DumpFreePoolList ();