2 Support routines for SMRAM profile.
4 Copyright (c) 2014 - 2017, Intel Corporation. All rights reserved.<BR>
5 This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php.
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
15 #include "PiSmmCore.h"
17 #define IS_SMRAM_PROFILE_ENABLED ((PcdGet8 (PcdMemoryProfilePropertyMask) & BIT1) != 0)
18 #define IS_UEFI_MEMORY_PROFILE_ENABLED ((PcdGet8 (PcdMemoryProfilePropertyMask) & BIT0) != 0)
20 #define GET_OCCUPIED_SIZE(ActualSize, Alignment) \
21 ((ActualSize) + (((Alignment) - ((ActualSize) & ((Alignment) - 1))) & ((Alignment) - 1)))
25 MEMORY_PROFILE_CONTEXT Context
;
26 LIST_ENTRY
*DriverInfoList
;
27 } MEMORY_PROFILE_CONTEXT_DATA
;
31 MEMORY_PROFILE_DRIVER_INFO DriverInfo
;
32 LIST_ENTRY
*AllocInfoList
;
35 } MEMORY_PROFILE_DRIVER_INFO_DATA
;
39 MEMORY_PROFILE_ALLOC_INFO AllocInfo
;
42 } MEMORY_PROFILE_ALLOC_INFO_DATA
;
45 // When free memory less than 4 pages, dump it.
47 #define SMRAM_INFO_DUMP_PAGE_THRESHOLD 4
49 GLOBAL_REMOVE_IF_UNREFERENCED MEMORY_PROFILE_FREE_MEMORY mSmramFreeMemory
= {
51 MEMORY_PROFILE_FREE_MEMORY_SIGNATURE
,
52 sizeof (MEMORY_PROFILE_FREE_MEMORY
),
53 MEMORY_PROFILE_FREE_MEMORY_REVISION
59 GLOBAL_REMOVE_IF_UNREFERENCED LIST_ENTRY mImageQueue
= INITIALIZE_LIST_HEAD_VARIABLE (mImageQueue
);
60 GLOBAL_REMOVE_IF_UNREFERENCED MEMORY_PROFILE_CONTEXT_DATA mSmramProfileContext
= {
61 MEMORY_PROFILE_CONTEXT_SIGNATURE
,
64 MEMORY_PROFILE_CONTEXT_SIGNATURE
,
65 sizeof (MEMORY_PROFILE_CONTEXT
),
66 MEMORY_PROFILE_CONTEXT_REVISION
78 GLOBAL_REMOVE_IF_UNREFERENCED MEMORY_PROFILE_CONTEXT_DATA
*mSmramProfileContextPtr
= NULL
;
80 GLOBAL_REMOVE_IF_UNREFERENCED BOOLEAN mSmramReadyToLock
;
81 GLOBAL_REMOVE_IF_UNREFERENCED BOOLEAN mSmramProfileGettingStatus
= FALSE
;
82 GLOBAL_REMOVE_IF_UNREFERENCED BOOLEAN mSmramProfileRecordingEnable
= MEMORY_PROFILE_RECORDING_DISABLE
;
83 GLOBAL_REMOVE_IF_UNREFERENCED EFI_DEVICE_PATH_PROTOCOL
*mSmramProfileDriverPath
;
84 GLOBAL_REMOVE_IF_UNREFERENCED UINTN mSmramProfileDriverPathSize
;
87 Dump SMRAM infromation.
96 Get memory profile data.
98 @param[in] This The EDKII_SMM_MEMORY_PROFILE_PROTOCOL instance.
99 @param[in, out] ProfileSize On entry, points to the size in bytes of the ProfileBuffer.
100 On return, points to the size of the data returned in ProfileBuffer.
101 @param[out] ProfileBuffer Profile buffer.
103 @return EFI_SUCCESS Get the memory profile data successfully.
104 @return EFI_UNSUPPORTED Memory profile is unsupported.
105 @return EFI_BUFFER_TO_SMALL The ProfileSize is too small for the resulting data.
106 ProfileSize is updated with the size required.
111 SmramProfileProtocolGetData (
112 IN EDKII_SMM_MEMORY_PROFILE_PROTOCOL
*This
,
113 IN OUT UINT64
*ProfileSize
,
114 OUT VOID
*ProfileBuffer
118 Register image to memory profile.
120 @param[in] This The EDKII_SMM_MEMORY_PROFILE_PROTOCOL instance.
121 @param[in] FilePath File path of the image.
122 @param[in] ImageBase Image base address.
123 @param[in] ImageSize Image size.
124 @param[in] FileType File type of the image.
126 @return EFI_SUCCESS Register successfully.
127 @return EFI_UNSUPPORTED Memory profile is unsupported,
128 or memory profile for the image is not required.
129 @return EFI_OUT_OF_RESOURCE No enough resource for this register.
134 SmramProfileProtocolRegisterImage (
135 IN EDKII_SMM_MEMORY_PROFILE_PROTOCOL
*This
,
136 IN EFI_DEVICE_PATH_PROTOCOL
*FilePath
,
137 IN PHYSICAL_ADDRESS ImageBase
,
139 IN EFI_FV_FILETYPE FileType
143 Unregister image from memory profile.
145 @param[in] This The EDKII_SMM_MEMORY_PROFILE_PROTOCOL instance.
146 @param[in] FilePath File path of the image.
147 @param[in] ImageBase Image base address.
148 @param[in] ImageSize Image size.
150 @return EFI_SUCCESS Unregister successfully.
151 @return EFI_UNSUPPORTED Memory profile is unsupported,
152 or memory profile for the image is not required.
153 @return EFI_NOT_FOUND The image is not found.
158 SmramProfileProtocolUnregisterImage (
159 IN EDKII_SMM_MEMORY_PROFILE_PROTOCOL
*This
,
160 IN EFI_DEVICE_PATH_PROTOCOL
*FilePath
,
161 IN PHYSICAL_ADDRESS ImageBase
,
166 Get memory profile recording state.
168 @param[in] This The EDKII_SMM_MEMORY_PROFILE_PROTOCOL instance.
169 @param[out] RecordingState Recording state.
171 @return EFI_SUCCESS Memory profile recording state is returned.
172 @return EFI_UNSUPPORTED Memory profile is unsupported.
173 @return EFI_INVALID_PARAMETER RecordingState is NULL.
178 SmramProfileProtocolGetRecordingState (
179 IN EDKII_SMM_MEMORY_PROFILE_PROTOCOL
*This
,
180 OUT BOOLEAN
*RecordingState
184 Set memory profile recording state.
186 @param[in] This The EDKII_SMM_MEMORY_PROFILE_PROTOCOL instance.
187 @param[in] RecordingState Recording state.
189 @return EFI_SUCCESS Set memory profile recording state successfully.
190 @return EFI_UNSUPPORTED Memory profile is unsupported.
195 SmramProfileProtocolSetRecordingState (
196 IN EDKII_SMM_MEMORY_PROFILE_PROTOCOL
*This
,
197 IN BOOLEAN RecordingState
201 Record memory profile of multilevel caller.
203 @param[in] This The EDKII_SMM_MEMORY_PROFILE_PROTOCOL instance.
204 @param[in] CallerAddress Address of caller.
205 @param[in] Action Memory profile action.
206 @param[in] MemoryType Memory type.
207 EfiMaxMemoryType means the MemoryType is unknown.
208 @param[in] Buffer Buffer address.
209 @param[in] Size Buffer size.
210 @param[in] ActionString String for memory profile action.
211 Only needed for user defined allocate action.
213 @return EFI_SUCCESS Memory profile is updated.
214 @return EFI_UNSUPPORTED Memory profile is unsupported,
215 or memory profile for the image is not required,
216 or memory profile for the memory type is not required.
217 @return EFI_ACCESS_DENIED It is during memory profile data getting.
218 @return EFI_ABORTED Memory profile recording is not enabled.
219 @return EFI_OUT_OF_RESOURCES No enough resource to update memory profile for allocate action.
220 @return EFI_NOT_FOUND No matched allocate info found for free action.
225 SmramProfileProtocolRecord (
226 IN EDKII_SMM_MEMORY_PROFILE_PROTOCOL
*This
,
227 IN PHYSICAL_ADDRESS CallerAddress
,
228 IN MEMORY_PROFILE_ACTION Action
,
229 IN EFI_MEMORY_TYPE MemoryType
,
232 IN CHAR8
*ActionString OPTIONAL
235 GLOBAL_REMOVE_IF_UNREFERENCED EDKII_SMM_MEMORY_PROFILE_PROTOCOL mSmmProfileProtocol
= {
236 SmramProfileProtocolGetData
,
237 SmramProfileProtocolRegisterImage
,
238 SmramProfileProtocolUnregisterImage
,
239 SmramProfileProtocolGetRecordingState
,
240 SmramProfileProtocolSetRecordingState
,
241 SmramProfileProtocolRecord
,
245 Return SMRAM profile context.
247 @return SMRAM profile context.
250 MEMORY_PROFILE_CONTEXT_DATA
*
251 GetSmramProfileContext (
255 return mSmramProfileContextPtr
;
259 Retrieves 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
;
1599 UINTN SmmPoolTypeIndex
;
1601 ContextData
= GetSmramProfileContext ();
1602 if (ContextData
== NULL
) {
1606 TotalSize
= sizeof (MEMORY_PROFILE_CONTEXT
);
1608 DriverInfoList
= ContextData
->DriverInfoList
;
1609 for (DriverLink
= DriverInfoList
->ForwardLink
;
1610 DriverLink
!= DriverInfoList
;
1611 DriverLink
= DriverLink
->ForwardLink
) {
1612 DriverInfoData
= CR (
1614 MEMORY_PROFILE_DRIVER_INFO_DATA
,
1616 MEMORY_PROFILE_DRIVER_INFO_SIGNATURE
1618 TotalSize
+= DriverInfoData
->DriverInfo
.Header
.Length
;
1620 AllocInfoList
= DriverInfoData
->AllocInfoList
;
1621 for (AllocLink
= AllocInfoList
->ForwardLink
;
1622 AllocLink
!= AllocInfoList
;
1623 AllocLink
= AllocLink
->ForwardLink
) {
1624 AllocInfoData
= CR (
1626 MEMORY_PROFILE_ALLOC_INFO_DATA
,
1628 MEMORY_PROFILE_ALLOC_INFO_SIGNATURE
1630 TotalSize
+= AllocInfoData
->AllocInfo
.Header
.Length
;
1636 FreePageList
= &mSmmMemoryMap
;
1637 for (Node
= FreePageList
->BackLink
;
1638 Node
!= FreePageList
;
1639 Node
= Node
->BackLink
) {
1642 for (SmmPoolTypeIndex
= 0; SmmPoolTypeIndex
< SmmPoolTypeMax
; SmmPoolTypeIndex
++) {
1643 for (PoolListIndex
= 0; PoolListIndex
< MAX_POOL_INDEX
; PoolListIndex
++) {
1644 FreePoolList
= &mSmmPoolLists
[SmmPoolTypeIndex
][PoolListIndex
];
1645 for (Node
= FreePoolList
->BackLink
;
1646 Node
!= FreePoolList
;
1647 Node
= Node
->BackLink
) {
1648 Pool
= BASE_CR (Node
, FREE_POOL_HEADER
, Link
);
1649 if (Pool
->Header
.Available
) {
1656 TotalSize
+= (sizeof (MEMORY_PROFILE_FREE_MEMORY
) + Index
* sizeof (MEMORY_PROFILE_DESCRIPTOR
));
1657 TotalSize
+= (sizeof (MEMORY_PROFILE_MEMORY_RANGE
) + mFullSmramRangeCount
* sizeof (MEMORY_PROFILE_DESCRIPTOR
));
1663 Copy SMRAM profile data.
1665 @param ProfileBuffer The buffer to hold SMRAM profile data.
1666 @param ProfileSize On input, profile buffer size.
1667 On output, actual profile data size copied.
1668 @param ProfileOffset On input, profile buffer offset to copy.
1669 On output, next time profile buffer offset to copy.
1673 SmramProfileCopyData (
1674 OUT VOID
*ProfileBuffer
,
1675 IN OUT UINT64
*ProfileSize
,
1676 IN OUT UINT64
*ProfileOffset
1679 MEMORY_PROFILE_CONTEXT
*Context
;
1680 MEMORY_PROFILE_DRIVER_INFO
*DriverInfo
;
1681 MEMORY_PROFILE_ALLOC_INFO
*AllocInfo
;
1682 MEMORY_PROFILE_CONTEXT_DATA
*ContextData
;
1683 MEMORY_PROFILE_DRIVER_INFO_DATA
*DriverInfoData
;
1684 MEMORY_PROFILE_ALLOC_INFO_DATA
*AllocInfoData
;
1685 LIST_ENTRY
*DriverInfoList
;
1686 LIST_ENTRY
*DriverLink
;
1687 LIST_ENTRY
*AllocInfoList
;
1688 LIST_ENTRY
*AllocLink
;
1690 FREE_PAGE_LIST
*Pages
;
1691 LIST_ENTRY
*FreePageList
;
1692 LIST_ENTRY
*FreePoolList
;
1693 FREE_POOL_HEADER
*Pool
;
1694 UINTN PoolListIndex
;
1696 MEMORY_PROFILE_FREE_MEMORY
*FreeMemory
;
1697 MEMORY_PROFILE_MEMORY_RANGE
*MemoryRange
;
1698 MEMORY_PROFILE_DESCRIPTOR
*MemoryProfileDescriptor
;
1700 UINT64 RemainingSize
;
1702 UINTN ActionStringSize
;
1703 UINTN SmmPoolTypeIndex
;
1705 ContextData
= GetSmramProfileContext ();
1706 if (ContextData
== NULL
) {
1710 RemainingSize
= *ProfileSize
;
1713 if (*ProfileOffset
< sizeof (MEMORY_PROFILE_CONTEXT
)) {
1714 if (RemainingSize
>= sizeof (MEMORY_PROFILE_CONTEXT
)) {
1715 Context
= ProfileBuffer
;
1716 CopyMem (Context
, &ContextData
->Context
, sizeof (MEMORY_PROFILE_CONTEXT
));
1717 RemainingSize
-= sizeof (MEMORY_PROFILE_CONTEXT
);
1718 ProfileBuffer
= (UINT8
*) ProfileBuffer
+ sizeof (MEMORY_PROFILE_CONTEXT
);
1723 Offset
+= sizeof (MEMORY_PROFILE_CONTEXT
);
1725 DriverInfoList
= ContextData
->DriverInfoList
;
1726 for (DriverLink
= DriverInfoList
->ForwardLink
;
1727 DriverLink
!= DriverInfoList
;
1728 DriverLink
= DriverLink
->ForwardLink
) {
1729 DriverInfoData
= CR (
1731 MEMORY_PROFILE_DRIVER_INFO_DATA
,
1733 MEMORY_PROFILE_DRIVER_INFO_SIGNATURE
1735 if (*ProfileOffset
< (Offset
+ DriverInfoData
->DriverInfo
.Header
.Length
)) {
1736 if (RemainingSize
>= DriverInfoData
->DriverInfo
.Header
.Length
) {
1737 DriverInfo
= ProfileBuffer
;
1738 CopyMem (DriverInfo
, &DriverInfoData
->DriverInfo
, sizeof (MEMORY_PROFILE_DRIVER_INFO
));
1739 if (DriverInfo
->PdbStringOffset
!= 0) {
1740 PdbSize
= AsciiStrSize (DriverInfoData
->PdbString
);
1741 CopyMem ((VOID
*) ((UINTN
) DriverInfo
+ DriverInfo
->PdbStringOffset
), DriverInfoData
->PdbString
, PdbSize
);
1743 RemainingSize
-= DriverInfo
->Header
.Length
;
1744 ProfileBuffer
= (UINT8
*) ProfileBuffer
+ DriverInfo
->Header
.Length
;
1749 Offset
+= DriverInfoData
->DriverInfo
.Header
.Length
;
1751 AllocInfoList
= DriverInfoData
->AllocInfoList
;
1752 for (AllocLink
= AllocInfoList
->ForwardLink
;
1753 AllocLink
!= AllocInfoList
;
1754 AllocLink
= AllocLink
->ForwardLink
) {
1755 AllocInfoData
= CR (
1757 MEMORY_PROFILE_ALLOC_INFO_DATA
,
1759 MEMORY_PROFILE_ALLOC_INFO_SIGNATURE
1761 if (*ProfileOffset
< (Offset
+ AllocInfoData
->AllocInfo
.Header
.Length
)) {
1762 if (RemainingSize
>= AllocInfoData
->AllocInfo
.Header
.Length
) {
1763 AllocInfo
= ProfileBuffer
;
1764 CopyMem (AllocInfo
, &AllocInfoData
->AllocInfo
, sizeof (MEMORY_PROFILE_ALLOC_INFO
));
1765 if (AllocInfo
->ActionStringOffset
) {
1766 ActionStringSize
= AsciiStrSize (AllocInfoData
->ActionString
);
1767 CopyMem ((VOID
*) ((UINTN
) AllocInfo
+ AllocInfo
->ActionStringOffset
), AllocInfoData
->ActionString
, ActionStringSize
);
1769 RemainingSize
-= AllocInfo
->Header
.Length
;
1770 ProfileBuffer
= (UINT8
*) ProfileBuffer
+ AllocInfo
->Header
.Length
;
1775 Offset
+= AllocInfoData
->AllocInfo
.Header
.Length
;
1780 if (*ProfileOffset
< (Offset
+ sizeof (MEMORY_PROFILE_FREE_MEMORY
))) {
1781 if (RemainingSize
>= sizeof (MEMORY_PROFILE_FREE_MEMORY
)) {
1782 FreeMemory
= ProfileBuffer
;
1783 CopyMem (FreeMemory
, &mSmramFreeMemory
, sizeof (MEMORY_PROFILE_FREE_MEMORY
));
1785 FreePageList
= &mSmmMemoryMap
;
1786 for (Node
= FreePageList
->BackLink
;
1787 Node
!= FreePageList
;
1788 Node
= Node
->BackLink
) {
1791 for (SmmPoolTypeIndex
= 0; SmmPoolTypeIndex
< SmmPoolTypeMax
; SmmPoolTypeIndex
++) {
1792 for (PoolListIndex
= 0; PoolListIndex
< MAX_POOL_INDEX
; PoolListIndex
++) {
1793 FreePoolList
= &mSmmPoolLists
[SmmPoolTypeIndex
][MAX_POOL_INDEX
- PoolListIndex
- 1];
1794 for (Node
= FreePoolList
->BackLink
;
1795 Node
!= FreePoolList
;
1796 Node
= Node
->BackLink
) {
1797 Pool
= BASE_CR (Node
, FREE_POOL_HEADER
, Link
);
1798 if (Pool
->Header
.Available
) {
1804 FreeMemory
->FreeMemoryEntryCount
= Index
;
1806 RemainingSize
-= sizeof (MEMORY_PROFILE_FREE_MEMORY
);
1807 ProfileBuffer
= (UINT8
*) ProfileBuffer
+ sizeof (MEMORY_PROFILE_FREE_MEMORY
);
1812 Offset
+= sizeof (MEMORY_PROFILE_FREE_MEMORY
);
1813 FreePageList
= &mSmmMemoryMap
;
1814 for (Node
= FreePageList
->BackLink
;
1815 Node
!= FreePageList
;
1816 Node
= Node
->BackLink
) {
1817 if (*ProfileOffset
< (Offset
+ sizeof (MEMORY_PROFILE_DESCRIPTOR
))) {
1818 if (RemainingSize
>= sizeof (MEMORY_PROFILE_DESCRIPTOR
)) {
1819 Pages
= BASE_CR (Node
, FREE_PAGE_LIST
, Link
);
1820 MemoryProfileDescriptor
= ProfileBuffer
;
1821 MemoryProfileDescriptor
->Header
.Signature
= MEMORY_PROFILE_DESCRIPTOR_SIGNATURE
;
1822 MemoryProfileDescriptor
->Header
.Length
= sizeof (MEMORY_PROFILE_DESCRIPTOR
);
1823 MemoryProfileDescriptor
->Header
.Revision
= MEMORY_PROFILE_DESCRIPTOR_REVISION
;
1824 MemoryProfileDescriptor
->Address
= (PHYSICAL_ADDRESS
) (UINTN
) Pages
;
1825 MemoryProfileDescriptor
->Size
= EFI_PAGES_TO_SIZE (Pages
->NumberOfPages
);
1827 RemainingSize
-= sizeof (MEMORY_PROFILE_DESCRIPTOR
);
1828 ProfileBuffer
= (UINT8
*) ProfileBuffer
+ sizeof (MEMORY_PROFILE_DESCRIPTOR
);
1833 Offset
+= sizeof (MEMORY_PROFILE_DESCRIPTOR
);
1835 for (SmmPoolTypeIndex
= 0; SmmPoolTypeIndex
< SmmPoolTypeMax
; SmmPoolTypeIndex
++) {
1836 for (PoolListIndex
= 0; PoolListIndex
< MAX_POOL_INDEX
; PoolListIndex
++) {
1837 FreePoolList
= &mSmmPoolLists
[SmmPoolTypeIndex
][MAX_POOL_INDEX
- PoolListIndex
- 1];
1838 for (Node
= FreePoolList
->BackLink
;
1839 Node
!= FreePoolList
;
1840 Node
= Node
->BackLink
) {
1841 Pool
= BASE_CR (Node
, FREE_POOL_HEADER
, Link
);
1842 if (Pool
->Header
.Available
) {
1843 if (*ProfileOffset
< (Offset
+ sizeof (MEMORY_PROFILE_DESCRIPTOR
))) {
1844 if (RemainingSize
>= sizeof (MEMORY_PROFILE_DESCRIPTOR
)) {
1845 MemoryProfileDescriptor
= ProfileBuffer
;
1846 MemoryProfileDescriptor
->Header
.Signature
= MEMORY_PROFILE_DESCRIPTOR_SIGNATURE
;
1847 MemoryProfileDescriptor
->Header
.Length
= sizeof (MEMORY_PROFILE_DESCRIPTOR
);
1848 MemoryProfileDescriptor
->Header
.Revision
= MEMORY_PROFILE_DESCRIPTOR_REVISION
;
1849 MemoryProfileDescriptor
->Address
= (PHYSICAL_ADDRESS
) (UINTN
) Pool
;
1850 MemoryProfileDescriptor
->Size
= Pool
->Header
.Size
;
1852 RemainingSize
-= sizeof (MEMORY_PROFILE_DESCRIPTOR
);
1853 ProfileBuffer
= (UINT8
*) ProfileBuffer
+ sizeof (MEMORY_PROFILE_DESCRIPTOR
);
1858 Offset
+= sizeof (MEMORY_PROFILE_DESCRIPTOR
);
1864 if (*ProfileOffset
< (Offset
+ sizeof (MEMORY_PROFILE_MEMORY_RANGE
))) {
1865 if (RemainingSize
>= sizeof (MEMORY_PROFILE_MEMORY_RANGE
)) {
1866 MemoryRange
= ProfileBuffer
;
1867 MemoryRange
->Header
.Signature
= MEMORY_PROFILE_MEMORY_RANGE_SIGNATURE
;
1868 MemoryRange
->Header
.Length
= sizeof (MEMORY_PROFILE_MEMORY_RANGE
);
1869 MemoryRange
->Header
.Revision
= MEMORY_PROFILE_MEMORY_RANGE_REVISION
;
1870 MemoryRange
->MemoryRangeCount
= (UINT32
) mFullSmramRangeCount
;
1872 RemainingSize
-= sizeof (MEMORY_PROFILE_MEMORY_RANGE
);
1873 ProfileBuffer
= (UINT8
*) ProfileBuffer
+ sizeof (MEMORY_PROFILE_MEMORY_RANGE
);
1878 Offset
+= sizeof (MEMORY_PROFILE_MEMORY_RANGE
);
1879 for (Index
= 0; Index
< mFullSmramRangeCount
; Index
++) {
1880 if (*ProfileOffset
< (Offset
+ sizeof (MEMORY_PROFILE_DESCRIPTOR
))) {
1881 if (RemainingSize
>= sizeof (MEMORY_PROFILE_DESCRIPTOR
)) {
1882 MemoryProfileDescriptor
= ProfileBuffer
;
1883 MemoryProfileDescriptor
->Header
.Signature
= MEMORY_PROFILE_DESCRIPTOR_SIGNATURE
;
1884 MemoryProfileDescriptor
->Header
.Length
= sizeof (MEMORY_PROFILE_DESCRIPTOR
);
1885 MemoryProfileDescriptor
->Header
.Revision
= MEMORY_PROFILE_DESCRIPTOR_REVISION
;
1886 MemoryProfileDescriptor
->Address
= mFullSmramRanges
[Index
].PhysicalStart
;
1887 MemoryProfileDescriptor
->Size
= mFullSmramRanges
[Index
].PhysicalSize
;
1889 RemainingSize
-= sizeof (MEMORY_PROFILE_DESCRIPTOR
);
1890 ProfileBuffer
= (UINT8
*) ProfileBuffer
+ sizeof (MEMORY_PROFILE_DESCRIPTOR
);
1895 Offset
+= sizeof (MEMORY_PROFILE_DESCRIPTOR
);
1900 // On output, actual profile data size copied.
1902 *ProfileSize
-= RemainingSize
;
1904 // On output, next time profile buffer offset to copy.
1906 *ProfileOffset
= Offset
;
1910 Get memory profile data.
1912 @param[in] This The EDKII_SMM_MEMORY_PROFILE_PROTOCOL instance.
1913 @param[in, out] ProfileSize On entry, points to the size in bytes of the ProfileBuffer.
1914 On return, points to the size of the data returned in ProfileBuffer.
1915 @param[out] ProfileBuffer Profile buffer.
1917 @return EFI_SUCCESS Get the memory profile data successfully.
1918 @return EFI_UNSUPPORTED Memory profile is unsupported.
1919 @return EFI_BUFFER_TO_SMALL The ProfileSize is too small for the resulting data.
1920 ProfileSize is updated with the size required.
1925 SmramProfileProtocolGetData (
1926 IN EDKII_SMM_MEMORY_PROFILE_PROTOCOL
*This
,
1927 IN OUT UINT64
*ProfileSize
,
1928 OUT VOID
*ProfileBuffer
1933 MEMORY_PROFILE_CONTEXT_DATA
*ContextData
;
1934 BOOLEAN SmramProfileGettingStatus
;
1936 ContextData
= GetSmramProfileContext ();
1937 if (ContextData
== NULL
) {
1938 return EFI_UNSUPPORTED
;
1941 SmramProfileGettingStatus
= mSmramProfileGettingStatus
;
1942 mSmramProfileGettingStatus
= TRUE
;
1944 Size
= SmramProfileGetDataSize ();
1946 if (*ProfileSize
< Size
) {
1947 *ProfileSize
= Size
;
1948 mSmramProfileGettingStatus
= SmramProfileGettingStatus
;
1949 return EFI_BUFFER_TOO_SMALL
;
1953 SmramProfileCopyData (ProfileBuffer
, &Size
, &Offset
);
1954 *ProfileSize
= Size
;
1956 mSmramProfileGettingStatus
= SmramProfileGettingStatus
;
1961 Register image to memory profile.
1963 @param[in] This The EDKII_SMM_MEMORY_PROFILE_PROTOCOL instance.
1964 @param[in] FilePath File path of the image.
1965 @param[in] ImageBase Image base address.
1966 @param[in] ImageSize Image size.
1967 @param[in] FileType File type of the image.
1969 @return EFI_SUCCESS Register successfully.
1970 @return EFI_UNSUPPORTED Memory profile is unsupported,
1971 or memory profile for the image is not required.
1972 @return EFI_OUT_OF_RESOURCES No enough resource for this register.
1977 SmramProfileProtocolRegisterImage (
1978 IN EDKII_SMM_MEMORY_PROFILE_PROTOCOL
*This
,
1979 IN EFI_DEVICE_PATH_PROTOCOL
*FilePath
,
1980 IN PHYSICAL_ADDRESS ImageBase
,
1981 IN UINT64 ImageSize
,
1982 IN EFI_FV_FILETYPE FileType
1986 EFI_SMM_DRIVER_ENTRY DriverEntry
;
1987 VOID
*EntryPointInImage
;
1990 ZeroMem (&DriverEntry
, sizeof (DriverEntry
));
1991 Name
= GetFileNameFromFilePath (FilePath
);
1993 CopyMem (&DriverEntry
.FileName
, Name
, sizeof (EFI_GUID
));
1995 DriverEntry
.ImageBuffer
= ImageBase
;
1996 DriverEntry
.NumberOfPage
= EFI_SIZE_TO_PAGES ((UINTN
) ImageSize
);
1997 Status
= InternalPeCoffGetEntryPoint ((VOID
*) (UINTN
) DriverEntry
.ImageBuffer
, &EntryPointInImage
);
1998 ASSERT_EFI_ERROR (Status
);
1999 DriverEntry
.ImageEntryPoint
= (PHYSICAL_ADDRESS
) (UINTN
) EntryPointInImage
;
2001 return RegisterSmramProfileImage (&DriverEntry
, FALSE
);
2005 Unregister image from memory profile.
2007 @param[in] This The EDKII_SMM_MEMORY_PROFILE_PROTOCOL instance.
2008 @param[in] FilePath File path of the image.
2009 @param[in] ImageBase Image base address.
2010 @param[in] ImageSize Image size.
2012 @return EFI_SUCCESS Unregister successfully.
2013 @return EFI_UNSUPPORTED Memory profile is unsupported,
2014 or memory profile for the image is not required.
2015 @return EFI_NOT_FOUND The image is not found.
2020 SmramProfileProtocolUnregisterImage (
2021 IN EDKII_SMM_MEMORY_PROFILE_PROTOCOL
*This
,
2022 IN EFI_DEVICE_PATH_PROTOCOL
*FilePath
,
2023 IN PHYSICAL_ADDRESS ImageBase
,
2028 EFI_SMM_DRIVER_ENTRY DriverEntry
;
2029 VOID
*EntryPointInImage
;
2032 ZeroMem (&DriverEntry
, sizeof (DriverEntry
));
2033 Name
= GetFileNameFromFilePath (FilePath
);
2035 CopyMem (&DriverEntry
.FileName
, Name
, sizeof (EFI_GUID
));
2037 DriverEntry
.ImageBuffer
= ImageBase
;
2038 DriverEntry
.NumberOfPage
= EFI_SIZE_TO_PAGES ((UINTN
) ImageSize
);
2039 Status
= InternalPeCoffGetEntryPoint ((VOID
*) (UINTN
) DriverEntry
.ImageBuffer
, &EntryPointInImage
);
2040 ASSERT_EFI_ERROR (Status
);
2041 DriverEntry
.ImageEntryPoint
= (PHYSICAL_ADDRESS
) (UINTN
) EntryPointInImage
;
2043 return UnregisterSmramProfileImage (&DriverEntry
, FALSE
);
2047 Get memory profile recording state.
2049 @param[in] This The EDKII_SMM_MEMORY_PROFILE_PROTOCOL instance.
2050 @param[out] RecordingState Recording state.
2052 @return EFI_SUCCESS Memory profile recording state is returned.
2053 @return EFI_UNSUPPORTED Memory profile is unsupported.
2054 @return EFI_INVALID_PARAMETER RecordingState is NULL.
2059 SmramProfileProtocolGetRecordingState (
2060 IN EDKII_SMM_MEMORY_PROFILE_PROTOCOL
*This
,
2061 OUT BOOLEAN
*RecordingState
2064 MEMORY_PROFILE_CONTEXT_DATA
*ContextData
;
2066 ContextData
= GetSmramProfileContext ();
2067 if (ContextData
== NULL
) {
2068 return EFI_UNSUPPORTED
;
2071 if (RecordingState
== NULL
) {
2072 return EFI_INVALID_PARAMETER
;
2074 *RecordingState
= mSmramProfileRecordingEnable
;
2079 Set memory profile recording state.
2081 @param[in] This The EDKII_SMM_MEMORY_PROFILE_PROTOCOL instance.
2082 @param[in] RecordingState Recording state.
2084 @return EFI_SUCCESS Set memory profile recording state successfully.
2085 @return EFI_UNSUPPORTED Memory profile is unsupported.
2090 SmramProfileProtocolSetRecordingState (
2091 IN EDKII_SMM_MEMORY_PROFILE_PROTOCOL
*This
,
2092 IN BOOLEAN RecordingState
2095 MEMORY_PROFILE_CONTEXT_DATA
*ContextData
;
2097 ContextData
= GetSmramProfileContext ();
2098 if (ContextData
== NULL
) {
2099 return EFI_UNSUPPORTED
;
2102 mSmramProfileRecordingEnable
= RecordingState
;
2107 Record memory profile of multilevel caller.
2109 @param[in] This The EDKII_SMM_MEMORY_PROFILE_PROTOCOL instance.
2110 @param[in] CallerAddress Address of caller.
2111 @param[in] Action Memory profile action.
2112 @param[in] MemoryType Memory type.
2113 EfiMaxMemoryType means the MemoryType is unknown.
2114 @param[in] Buffer Buffer address.
2115 @param[in] Size Buffer size.
2116 @param[in] ActionString String for memory profile action.
2117 Only needed for user defined allocate action.
2119 @return EFI_SUCCESS Memory profile is updated.
2120 @return EFI_UNSUPPORTED Memory profile is unsupported,
2121 or memory profile for the image is not required,
2122 or memory profile for the memory type is not required.
2123 @return EFI_ACCESS_DENIED It is during memory profile data getting.
2124 @return EFI_ABORTED Memory profile recording is not enabled.
2125 @return EFI_OUT_OF_RESOURCES No enough resource to update memory profile for allocate action.
2126 @return EFI_NOT_FOUND No matched allocate info found for free action.
2131 SmramProfileProtocolRecord (
2132 IN EDKII_SMM_MEMORY_PROFILE_PROTOCOL
*This
,
2133 IN PHYSICAL_ADDRESS CallerAddress
,
2134 IN MEMORY_PROFILE_ACTION Action
,
2135 IN EFI_MEMORY_TYPE MemoryType
,
2138 IN CHAR8
*ActionString OPTIONAL
2141 return SmmCoreUpdateProfile (CallerAddress
, Action
, MemoryType
, Size
, Buffer
, ActionString
);
2145 SMRAM profile handler to get profile info.
2147 @param SmramProfileParameterGetInfo The parameter of SMM profile get size.
2151 SmramProfileHandlerGetInfo (
2152 IN SMRAM_PROFILE_PARAMETER_GET_PROFILE_INFO
*SmramProfileParameterGetInfo
2155 MEMORY_PROFILE_CONTEXT_DATA
*ContextData
;
2156 BOOLEAN SmramProfileGettingStatus
;
2158 ContextData
= GetSmramProfileContext ();
2159 if (ContextData
== NULL
) {
2163 SmramProfileGettingStatus
= mSmramProfileGettingStatus
;
2164 mSmramProfileGettingStatus
= TRUE
;
2166 SmramProfileParameterGetInfo
->ProfileSize
= SmramProfileGetDataSize();
2167 SmramProfileParameterGetInfo
->Header
.ReturnStatus
= 0;
2169 mSmramProfileGettingStatus
= SmramProfileGettingStatus
;
2173 SMRAM profile handler to get profile data.
2175 @param SmramProfileParameterGetData The parameter of SMM profile get data.
2179 SmramProfileHandlerGetData (
2180 IN SMRAM_PROFILE_PARAMETER_GET_PROFILE_DATA
*SmramProfileParameterGetData
2184 UINT64 ProfileOffset
;
2185 SMRAM_PROFILE_PARAMETER_GET_PROFILE_DATA SmramProfileGetData
;
2186 MEMORY_PROFILE_CONTEXT_DATA
*ContextData
;
2187 BOOLEAN SmramProfileGettingStatus
;
2189 ContextData
= GetSmramProfileContext ();
2190 if (ContextData
== NULL
) {
2194 SmramProfileGettingStatus
= mSmramProfileGettingStatus
;
2195 mSmramProfileGettingStatus
= TRUE
;
2198 CopyMem (&SmramProfileGetData
, SmramProfileParameterGetData
, sizeof (SmramProfileGetData
));
2200 ProfileSize
= SmramProfileGetDataSize();
2205 if (!SmmIsBufferOutsideSmmValid ((UINTN
) SmramProfileGetData
.ProfileBuffer
, (UINTN
) ProfileSize
)) {
2206 DEBUG ((EFI_D_ERROR
, "SmramProfileHandlerGetData: SMM ProfileBuffer in SMRAM or overflow!\n"));
2207 SmramProfileParameterGetData
->ProfileSize
= ProfileSize
;
2208 SmramProfileParameterGetData
->Header
.ReturnStatus
= (UINT64
) (INT64
) (INTN
) EFI_ACCESS_DENIED
;
2212 if (SmramProfileGetData
.ProfileSize
< ProfileSize
) {
2213 SmramProfileParameterGetData
->ProfileSize
= ProfileSize
;
2214 SmramProfileParameterGetData
->Header
.ReturnStatus
= (UINT64
) (INT64
) (INTN
) EFI_BUFFER_TOO_SMALL
;
2219 SmramProfileCopyData ((VOID
*) (UINTN
) SmramProfileGetData
.ProfileBuffer
, &ProfileSize
, &ProfileOffset
);
2220 SmramProfileParameterGetData
->ProfileSize
= ProfileSize
;
2221 SmramProfileParameterGetData
->Header
.ReturnStatus
= 0;
2224 mSmramProfileGettingStatus
= SmramProfileGettingStatus
;
2228 SMRAM profile handler to get profile data by offset.
2230 @param SmramProfileParameterGetDataByOffset The parameter of SMM profile get data by offset.
2234 SmramProfileHandlerGetDataByOffset (
2235 IN SMRAM_PROFILE_PARAMETER_GET_PROFILE_DATA_BY_OFFSET
*SmramProfileParameterGetDataByOffset
2238 SMRAM_PROFILE_PARAMETER_GET_PROFILE_DATA_BY_OFFSET SmramProfileGetDataByOffset
;
2239 MEMORY_PROFILE_CONTEXT_DATA
*ContextData
;
2240 BOOLEAN SmramProfileGettingStatus
;
2242 ContextData
= GetSmramProfileContext ();
2243 if (ContextData
== NULL
) {
2247 SmramProfileGettingStatus
= mSmramProfileGettingStatus
;
2248 mSmramProfileGettingStatus
= TRUE
;
2251 CopyMem (&SmramProfileGetDataByOffset
, SmramProfileParameterGetDataByOffset
, sizeof (SmramProfileGetDataByOffset
));
2256 if (!SmmIsBufferOutsideSmmValid ((UINTN
) SmramProfileGetDataByOffset
.ProfileBuffer
, (UINTN
) SmramProfileGetDataByOffset
.ProfileSize
)) {
2257 DEBUG ((EFI_D_ERROR
, "SmramProfileHandlerGetDataByOffset: SMM ProfileBuffer in SMRAM or overflow!\n"));
2258 SmramProfileParameterGetDataByOffset
->Header
.ReturnStatus
= (UINT64
) (INT64
) (INTN
) EFI_ACCESS_DENIED
;
2262 SmramProfileCopyData ((VOID
*) (UINTN
) SmramProfileGetDataByOffset
.ProfileBuffer
, &SmramProfileGetDataByOffset
.ProfileSize
, &SmramProfileGetDataByOffset
.ProfileOffset
);
2263 CopyMem (SmramProfileParameterGetDataByOffset
, &SmramProfileGetDataByOffset
, sizeof (SmramProfileGetDataByOffset
));
2264 SmramProfileParameterGetDataByOffset
->Header
.ReturnStatus
= 0;
2267 mSmramProfileGettingStatus
= SmramProfileGettingStatus
;
2271 SMRAM profile handler to register SMM image.
2273 @param SmramProfileParameterRegisterImage The parameter of SMM profile register image.
2277 SmramProfileHandlerRegisterImage (
2278 IN SMRAM_PROFILE_PARAMETER_REGISTER_IMAGE
*SmramProfileParameterRegisterImage
2282 EFI_SMM_DRIVER_ENTRY DriverEntry
;
2283 VOID
*EntryPointInImage
;
2285 ZeroMem (&DriverEntry
, sizeof (DriverEntry
));
2286 CopyMem (&DriverEntry
.FileName
, &SmramProfileParameterRegisterImage
->FileName
, sizeof(EFI_GUID
));
2287 DriverEntry
.ImageBuffer
= SmramProfileParameterRegisterImage
->ImageBuffer
;
2288 DriverEntry
.NumberOfPage
= (UINTN
) SmramProfileParameterRegisterImage
->NumberOfPage
;
2289 Status
= InternalPeCoffGetEntryPoint ((VOID
*) (UINTN
) DriverEntry
.ImageBuffer
, &EntryPointInImage
);
2290 ASSERT_EFI_ERROR (Status
);
2291 DriverEntry
.ImageEntryPoint
= (PHYSICAL_ADDRESS
) (UINTN
) EntryPointInImage
;
2293 Status
= RegisterSmramProfileImage (&DriverEntry
, FALSE
);
2294 if (!EFI_ERROR (Status
)) {
2295 SmramProfileParameterRegisterImage
->Header
.ReturnStatus
= 0;
2300 SMRAM profile handler to unregister SMM image.
2302 @param SmramProfileParameterUnregisterImage The parameter of SMM profile unregister image.
2306 SmramProfileHandlerUnregisterImage (
2307 IN SMRAM_PROFILE_PARAMETER_UNREGISTER_IMAGE
*SmramProfileParameterUnregisterImage
2311 EFI_SMM_DRIVER_ENTRY DriverEntry
;
2312 VOID
*EntryPointInImage
;
2314 ZeroMem (&DriverEntry
, sizeof (DriverEntry
));
2315 CopyMem (&DriverEntry
.FileName
, &SmramProfileParameterUnregisterImage
->FileName
, sizeof (EFI_GUID
));
2316 DriverEntry
.ImageBuffer
= SmramProfileParameterUnregisterImage
->ImageBuffer
;
2317 DriverEntry
.NumberOfPage
= (UINTN
) SmramProfileParameterUnregisterImage
->NumberOfPage
;
2318 Status
= InternalPeCoffGetEntryPoint ((VOID
*) (UINTN
) DriverEntry
.ImageBuffer
, &EntryPointInImage
);
2319 ASSERT_EFI_ERROR (Status
);
2320 DriverEntry
.ImageEntryPoint
= (PHYSICAL_ADDRESS
) (UINTN
) EntryPointInImage
;
2322 Status
= UnregisterSmramProfileImage (&DriverEntry
, FALSE
);
2323 if (!EFI_ERROR (Status
)) {
2324 SmramProfileParameterUnregisterImage
->Header
.ReturnStatus
= 0;
2329 Dispatch function for a Software SMI handler.
2331 Caution: This function may receive untrusted input.
2332 Communicate buffer and buffer size are external input, so this function will do basic validation.
2334 @param DispatchHandle The unique handle assigned to this handler by SmiHandlerRegister().
2335 @param Context Points to an optional handler context which was specified when the
2336 handler was registered.
2337 @param CommBuffer A pointer to a collection of data in memory that will
2338 be conveyed from a non-SMM environment into an SMM environment.
2339 @param CommBufferSize The size of the CommBuffer.
2341 @retval EFI_SUCCESS Command is handled successfully.
2346 SmramProfileHandler (
2347 IN EFI_HANDLE DispatchHandle
,
2348 IN CONST VOID
*Context OPTIONAL
,
2349 IN OUT VOID
*CommBuffer OPTIONAL
,
2350 IN OUT UINTN
*CommBufferSize OPTIONAL
2353 SMRAM_PROFILE_PARAMETER_HEADER
*SmramProfileParameterHeader
;
2354 UINTN TempCommBufferSize
;
2355 SMRAM_PROFILE_PARAMETER_RECORDING_STATE
*ParameterRecordingState
;
2357 DEBUG ((EFI_D_ERROR
, "SmramProfileHandler Enter\n"));
2360 // If input is invalid, stop processing this SMI
2362 if (CommBuffer
== NULL
|| CommBufferSize
== NULL
) {
2366 TempCommBufferSize
= *CommBufferSize
;
2368 if (TempCommBufferSize
< sizeof (SMRAM_PROFILE_PARAMETER_HEADER
)) {
2369 DEBUG ((EFI_D_ERROR
, "SmramProfileHandler: SMM communication buffer size invalid!\n"));
2373 if (mSmramReadyToLock
&& !SmmIsBufferOutsideSmmValid ((UINTN
)CommBuffer
, TempCommBufferSize
)) {
2374 DEBUG ((EFI_D_ERROR
, "SmramProfileHandler: SMM communication buffer in SMRAM or overflow!\n"));
2378 SmramProfileParameterHeader
= (SMRAM_PROFILE_PARAMETER_HEADER
*) ((UINTN
) CommBuffer
);
2380 SmramProfileParameterHeader
->ReturnStatus
= (UINT64
)-1;
2382 if (GetSmramProfileContext () == NULL
) {
2383 SmramProfileParameterHeader
->ReturnStatus
= (UINT64
) (INT64
) (INTN
) EFI_UNSUPPORTED
;
2387 switch (SmramProfileParameterHeader
->Command
) {
2388 case SMRAM_PROFILE_COMMAND_GET_PROFILE_INFO
:
2389 DEBUG ((EFI_D_ERROR
, "SmramProfileHandlerGetInfo\n"));
2390 if (TempCommBufferSize
!= sizeof (SMRAM_PROFILE_PARAMETER_GET_PROFILE_INFO
)) {
2391 DEBUG ((EFI_D_ERROR
, "SmramProfileHandler: SMM communication buffer size invalid!\n"));
2394 SmramProfileHandlerGetInfo ((SMRAM_PROFILE_PARAMETER_GET_PROFILE_INFO
*) (UINTN
) CommBuffer
);
2396 case SMRAM_PROFILE_COMMAND_GET_PROFILE_DATA
:
2397 DEBUG ((EFI_D_ERROR
, "SmramProfileHandlerGetData\n"));
2398 if (TempCommBufferSize
!= sizeof (SMRAM_PROFILE_PARAMETER_GET_PROFILE_DATA
)) {
2399 DEBUG ((EFI_D_ERROR
, "SmramProfileHandler: SMM communication buffer size invalid!\n"));
2402 SmramProfileHandlerGetData ((SMRAM_PROFILE_PARAMETER_GET_PROFILE_DATA
*) (UINTN
) CommBuffer
);
2404 case SMRAM_PROFILE_COMMAND_GET_PROFILE_DATA_BY_OFFSET
:
2405 DEBUG ((EFI_D_ERROR
, "SmramProfileHandlerGetDataByOffset\n"));
2406 if (TempCommBufferSize
!= sizeof (SMRAM_PROFILE_PARAMETER_GET_PROFILE_DATA_BY_OFFSET
)) {
2407 DEBUG ((EFI_D_ERROR
, "SmramProfileHandler: SMM communication buffer size invalid!\n"));
2410 SmramProfileHandlerGetDataByOffset ((SMRAM_PROFILE_PARAMETER_GET_PROFILE_DATA_BY_OFFSET
*) (UINTN
) CommBuffer
);
2412 case SMRAM_PROFILE_COMMAND_REGISTER_IMAGE
:
2413 DEBUG ((EFI_D_ERROR
, "SmramProfileHandlerRegisterImage\n"));
2414 if (TempCommBufferSize
!= sizeof (SMRAM_PROFILE_PARAMETER_REGISTER_IMAGE
)) {
2415 DEBUG ((EFI_D_ERROR
, "SmramProfileHandler: SMM communication buffer size invalid!\n"));
2418 if (mSmramReadyToLock
) {
2421 SmramProfileHandlerRegisterImage ((SMRAM_PROFILE_PARAMETER_REGISTER_IMAGE
*) (UINTN
) CommBuffer
);
2423 case SMRAM_PROFILE_COMMAND_UNREGISTER_IMAGE
:
2424 DEBUG ((EFI_D_ERROR
, "SmramProfileHandlerUnregisterImage\n"));
2425 if (TempCommBufferSize
!= sizeof (SMRAM_PROFILE_PARAMETER_UNREGISTER_IMAGE
)) {
2426 DEBUG ((EFI_D_ERROR
, "SmramProfileHandler: SMM communication buffer size invalid!\n"));
2429 if (mSmramReadyToLock
) {
2432 SmramProfileHandlerUnregisterImage ((SMRAM_PROFILE_PARAMETER_UNREGISTER_IMAGE
*) (UINTN
) CommBuffer
);
2434 case SMRAM_PROFILE_COMMAND_GET_RECORDING_STATE
:
2435 DEBUG ((EFI_D_ERROR
, "SmramProfileHandlerGetRecordingState\n"));
2436 if (TempCommBufferSize
!= sizeof (SMRAM_PROFILE_PARAMETER_RECORDING_STATE
)) {
2437 DEBUG ((EFI_D_ERROR
, "SmramProfileHandler: SMM communication buffer size invalid!\n"));
2440 ParameterRecordingState
= (SMRAM_PROFILE_PARAMETER_RECORDING_STATE
*) (UINTN
) CommBuffer
;
2441 ParameterRecordingState
->RecordingState
= mSmramProfileRecordingEnable
;
2442 ParameterRecordingState
->Header
.ReturnStatus
= 0;
2444 case SMRAM_PROFILE_COMMAND_SET_RECORDING_STATE
:
2445 DEBUG ((EFI_D_ERROR
, "SmramProfileHandlerSetRecordingState\n"));
2446 if (TempCommBufferSize
!= sizeof (SMRAM_PROFILE_PARAMETER_RECORDING_STATE
)) {
2447 DEBUG ((EFI_D_ERROR
, "SmramProfileHandler: SMM communication buffer size invalid!\n"));
2450 ParameterRecordingState
= (SMRAM_PROFILE_PARAMETER_RECORDING_STATE
*) (UINTN
) CommBuffer
;
2451 mSmramProfileRecordingEnable
= ParameterRecordingState
->RecordingState
;
2452 ParameterRecordingState
->Header
.ReturnStatus
= 0;
2459 DEBUG ((EFI_D_ERROR
, "SmramProfileHandler Exit\n"));
2465 Register SMRAM profile handler.
2469 RegisterSmramProfileHandler (
2474 EFI_HANDLE DispatchHandle
;
2476 if (!IS_SMRAM_PROFILE_ENABLED
) {
2480 Status
= SmiHandlerRegister (
2481 SmramProfileHandler
,
2482 &gEdkiiMemoryProfileGuid
,
2485 ASSERT_EFI_ERROR (Status
);
2488 ////////////////////
2500 MEMORY_PROFILE_CONTEXT_DATA
*ContextData
;
2501 BOOLEAN SmramProfileGettingStatus
;
2503 ContextData
= GetSmramProfileContext ();
2504 if (ContextData
== NULL
) {
2508 SmramProfileGettingStatus
= mSmramProfileGettingStatus
;
2509 mSmramProfileGettingStatus
= TRUE
;
2511 DEBUG ((EFI_D_INFO
, "FullSmramRange address - 0x%08x\n", mFullSmramRanges
));
2513 DEBUG ((EFI_D_INFO
, "======= SmramProfile begin =======\n"));
2515 DEBUG ((EFI_D_INFO
, "FullSmramRange:\n"));
2516 for (Index
= 0; Index
< mFullSmramRangeCount
; Index
++) {
2517 DEBUG ((EFI_D_INFO
, " FullSmramRange (0x%x)\n", Index
));
2518 DEBUG ((EFI_D_INFO
, " PhysicalStart - 0x%016lx\n", mFullSmramRanges
[Index
].PhysicalStart
));
2519 DEBUG ((EFI_D_INFO
, " CpuStart - 0x%016lx\n", mFullSmramRanges
[Index
].CpuStart
));
2520 DEBUG ((EFI_D_INFO
, " PhysicalSize - 0x%016lx\n", mFullSmramRanges
[Index
].PhysicalSize
));
2521 DEBUG ((EFI_D_INFO
, " RegionState - 0x%016lx\n", mFullSmramRanges
[Index
].RegionState
));
2524 DEBUG ((EFI_D_INFO
, "======= SmramProfile end =======\n"));
2526 mSmramProfileGettingStatus
= SmramProfileGettingStatus
;
2530 Dump SMRAM free page list.
2538 LIST_ENTRY
*FreePageList
;
2540 FREE_PAGE_LIST
*Pages
;
2542 MEMORY_PROFILE_CONTEXT_DATA
*ContextData
;
2543 BOOLEAN SmramProfileGettingStatus
;
2545 ContextData
= GetSmramProfileContext ();
2546 if (ContextData
== NULL
) {
2550 SmramProfileGettingStatus
= mSmramProfileGettingStatus
;
2551 mSmramProfileGettingStatus
= TRUE
;
2553 DEBUG ((EFI_D_INFO
, "======= SmramProfile begin =======\n"));
2555 DEBUG ((EFI_D_INFO
, "FreePagesList:\n"));
2556 FreePageList
= &mSmmMemoryMap
;
2557 for (Node
= FreePageList
->BackLink
, Index
= 0;
2558 Node
!= FreePageList
;
2559 Node
= Node
->BackLink
, Index
++) {
2560 Pages
= BASE_CR (Node
, FREE_PAGE_LIST
, Link
);
2561 DEBUG ((EFI_D_INFO
, " Index - 0x%x\n", Index
));
2562 DEBUG ((EFI_D_INFO
, " PhysicalStart - 0x%016lx\n", (PHYSICAL_ADDRESS
) (UINTN
) Pages
));
2563 DEBUG ((EFI_D_INFO
, " NumberOfPages - 0x%08x\n", Pages
->NumberOfPages
));
2566 DEBUG ((EFI_D_INFO
, "======= SmramProfile end =======\n"));
2568 mSmramProfileGettingStatus
= SmramProfileGettingStatus
;
2572 Dump SMRAM free pool list.
2580 LIST_ENTRY
*FreePoolList
;
2582 FREE_POOL_HEADER
*Pool
;
2584 UINTN PoolListIndex
;
2585 MEMORY_PROFILE_CONTEXT_DATA
*ContextData
;
2586 BOOLEAN SmramProfileGettingStatus
;
2587 UINTN SmmPoolTypeIndex
;
2589 ContextData
= GetSmramProfileContext ();
2590 if (ContextData
== NULL
) {
2594 SmramProfileGettingStatus
= mSmramProfileGettingStatus
;
2595 mSmramProfileGettingStatus
= TRUE
;
2597 DEBUG ((DEBUG_INFO
, "======= SmramProfile begin =======\n"));
2599 for (SmmPoolTypeIndex
= 0; SmmPoolTypeIndex
< SmmPoolTypeMax
; SmmPoolTypeIndex
++) {
2600 for (PoolListIndex
= 0; PoolListIndex
< MAX_POOL_INDEX
; PoolListIndex
++) {
2601 DEBUG ((DEBUG_INFO
, "FreePoolList(%d)(%d):\n", SmmPoolTypeIndex
, PoolListIndex
));
2602 FreePoolList
= &mSmmPoolLists
[SmmPoolTypeIndex
][PoolListIndex
];
2603 for (Node
= FreePoolList
->BackLink
, Index
= 0;
2604 Node
!= FreePoolList
;
2605 Node
= Node
->BackLink
, Index
++) {
2606 Pool
= BASE_CR (Node
, FREE_POOL_HEADER
, Link
);
2607 DEBUG ((DEBUG_INFO
, " Index - 0x%x\n", Index
));
2608 DEBUG ((DEBUG_INFO
, " PhysicalStart - 0x%016lx\n", (PHYSICAL_ADDRESS
) (UINTN
) Pool
));
2609 DEBUG ((DEBUG_INFO
, " Size - 0x%08x\n", Pool
->Header
.Size
));
2610 DEBUG ((DEBUG_INFO
, " Available - 0x%02x\n", Pool
->Header
.Available
));
2615 DEBUG ((DEBUG_INFO
, "======= SmramProfile end =======\n"));
2617 mSmramProfileGettingStatus
= SmramProfileGettingStatus
;
2620 GLOBAL_REMOVE_IF_UNREFERENCED CHAR8
*mSmmActionString
[] = {
2622 "gSmst->SmmAllocatePages",
2623 "gSmst->SmmFreePages",
2624 "gSmst->SmmAllocatePool",
2625 "gSmst->SmmFreePool",
2629 MEMORY_PROFILE_ACTION Action
;
2633 GLOBAL_REMOVE_IF_UNREFERENCED ACTION_STRING mExtActionString
[] = {
2634 {MEMORY_PROFILE_ACTION_LIB_ALLOCATE_PAGES
, "Lib:AllocatePages"},
2635 {MEMORY_PROFILE_ACTION_LIB_ALLOCATE_RUNTIME_PAGES
, "Lib:AllocateRuntimePages"},
2636 {MEMORY_PROFILE_ACTION_LIB_ALLOCATE_RESERVED_PAGES
, "Lib:AllocateReservedPages"},
2637 {MEMORY_PROFILE_ACTION_LIB_FREE_PAGES
, "Lib:FreePages"},
2638 {MEMORY_PROFILE_ACTION_LIB_ALLOCATE_ALIGNED_PAGES
, "Lib:AllocateAlignedPages"},
2639 {MEMORY_PROFILE_ACTION_LIB_ALLOCATE_ALIGNED_RUNTIME_PAGES
, "Lib:AllocateAlignedRuntimePages"},
2640 {MEMORY_PROFILE_ACTION_LIB_ALLOCATE_ALIGNED_RESERVED_PAGES
, "Lib:AllocateAlignedReservedPages"},
2641 {MEMORY_PROFILE_ACTION_LIB_FREE_ALIGNED_PAGES
, "Lib:FreeAlignedPages"},
2642 {MEMORY_PROFILE_ACTION_LIB_ALLOCATE_POOL
, "Lib:AllocatePool"},
2643 {MEMORY_PROFILE_ACTION_LIB_ALLOCATE_RUNTIME_POOL
, "Lib:AllocateRuntimePool"},
2644 {MEMORY_PROFILE_ACTION_LIB_ALLOCATE_RESERVED_POOL
, "Lib:AllocateReservedPool"},
2645 {MEMORY_PROFILE_ACTION_LIB_FREE_POOL
, "Lib:FreePool"},
2646 {MEMORY_PROFILE_ACTION_LIB_ALLOCATE_ZERO_POOL
, "Lib:AllocateZeroPool"},
2647 {MEMORY_PROFILE_ACTION_LIB_ALLOCATE_RUNTIME_ZERO_POOL
, "Lib:AllocateRuntimeZeroPool"},
2648 {MEMORY_PROFILE_ACTION_LIB_ALLOCATE_RESERVED_ZERO_POOL
, "Lib:AllocateReservedZeroPool"},
2649 {MEMORY_PROFILE_ACTION_LIB_ALLOCATE_COPY_POOL
, "Lib:AllocateCopyPool"},
2650 {MEMORY_PROFILE_ACTION_LIB_ALLOCATE_RUNTIME_COPY_POOL
, "Lib:AllocateRuntimeCopyPool"},
2651 {MEMORY_PROFILE_ACTION_LIB_ALLOCATE_RESERVED_COPY_POOL
, "Lib:AllocateReservedCopyPool"},
2652 {MEMORY_PROFILE_ACTION_LIB_REALLOCATE_POOL
, "Lib:ReallocatePool"},
2653 {MEMORY_PROFILE_ACTION_LIB_REALLOCATE_RUNTIME_POOL
, "Lib:ReallocateRuntimePool"},
2654 {MEMORY_PROFILE_ACTION_LIB_REALLOCATE_RESERVED_POOL
, "Lib:ReallocateReservedPool"},
2658 EFI_MEMORY_TYPE MemoryType
;
2659 CHAR8
*MemoryTypeStr
;
2660 } PROFILE_MEMORY_TYPE_STRING
;
2662 GLOBAL_REMOVE_IF_UNREFERENCED PROFILE_MEMORY_TYPE_STRING mMemoryTypeString
[] = {
2663 {EfiRuntimeServicesCode
, "EfiRuntimeServicesCode"},
2664 {EfiRuntimeServicesData
, "EfiRuntimeServicesData"}
2668 Memory type to string.
2670 @param[in] MemoryType Memory type.
2672 @return Pointer to string.
2676 ProfileMemoryTypeToStr (
2677 IN EFI_MEMORY_TYPE MemoryType
2681 for (Index
= 0; Index
< ARRAY_SIZE (mMemoryTypeString
); Index
++) {
2682 if (mMemoryTypeString
[Index
].MemoryType
== MemoryType
) {
2683 return mMemoryTypeString
[Index
].MemoryTypeStr
;
2687 return "UnexpectedMemoryType";
2693 @param[in] Action Profile action.
2695 @return Pointer to string.
2699 ProfileActionToStr (
2700 IN MEMORY_PROFILE_ACTION Action
2704 UINTN ActionStringCount
;
2705 CHAR8
**ActionString
;
2707 ActionString
= mSmmActionString
;
2708 ActionStringCount
= ARRAY_SIZE (mSmmActionString
);
2710 if ((UINTN
) (UINT32
) Action
< ActionStringCount
) {
2711 return ActionString
[Action
];
2713 for (Index
= 0; Index
< ARRAY_SIZE (mExtActionString
); Index
++) {
2714 if (mExtActionString
[Index
].Action
== Action
) {
2715 return mExtActionString
[Index
].String
;
2719 return ActionString
[0];
2731 MEMORY_PROFILE_CONTEXT
*Context
;
2732 MEMORY_PROFILE_DRIVER_INFO
*DriverInfo
;
2733 MEMORY_PROFILE_ALLOC_INFO
*AllocInfo
;
2734 MEMORY_PROFILE_CONTEXT_DATA
*ContextData
;
2735 MEMORY_PROFILE_DRIVER_INFO_DATA
*DriverInfoData
;
2736 MEMORY_PROFILE_ALLOC_INFO_DATA
*AllocInfoData
;
2737 LIST_ENTRY
*SmramDriverInfoList
;
2739 LIST_ENTRY
*DriverLink
;
2740 LIST_ENTRY
*AllocInfoList
;
2742 LIST_ENTRY
*AllocLink
;
2743 BOOLEAN SmramProfileGettingStatus
;
2746 ContextData
= GetSmramProfileContext ();
2747 if (ContextData
== NULL
) {
2751 SmramProfileGettingStatus
= mSmramProfileGettingStatus
;
2752 mSmramProfileGettingStatus
= TRUE
;
2754 Context
= &ContextData
->Context
;
2755 DEBUG ((EFI_D_INFO
, "======= SmramProfile begin =======\n"));
2756 DEBUG ((EFI_D_INFO
, "MEMORY_PROFILE_CONTEXT\n"));
2758 DEBUG ((EFI_D_INFO
, " CurrentTotalUsage - 0x%016lx\n", Context
->CurrentTotalUsage
));
2759 DEBUG ((EFI_D_INFO
, " PeakTotalUsage - 0x%016lx\n", Context
->PeakTotalUsage
));
2760 for (TypeIndex
= 0; TypeIndex
< sizeof (Context
->CurrentTotalUsageByType
) / sizeof (Context
->CurrentTotalUsageByType
[0]); TypeIndex
++) {
2761 if ((Context
->CurrentTotalUsageByType
[TypeIndex
] != 0) ||
2762 (Context
->PeakTotalUsageByType
[TypeIndex
] != 0)) {
2763 DEBUG ((EFI_D_INFO
, " CurrentTotalUsage[0x%02x] - 0x%016lx (%a)\n", TypeIndex
, Context
->CurrentTotalUsageByType
[TypeIndex
], ProfileMemoryTypeToStr (TypeIndex
)));
2764 DEBUG ((EFI_D_INFO
, " PeakTotalUsage[0x%02x] - 0x%016lx (%a)\n", TypeIndex
, Context
->PeakTotalUsageByType
[TypeIndex
], ProfileMemoryTypeToStr (TypeIndex
)));
2767 DEBUG ((EFI_D_INFO
, " TotalImageSize - 0x%016lx\n", Context
->TotalImageSize
));
2768 DEBUG ((EFI_D_INFO
, " ImageCount - 0x%08x\n", Context
->ImageCount
));
2769 DEBUG ((EFI_D_INFO
, " SequenceCount - 0x%08x\n", Context
->SequenceCount
));
2771 SmramDriverInfoList
= ContextData
->DriverInfoList
;
2772 for (DriverLink
= SmramDriverInfoList
->ForwardLink
, DriverIndex
= 0;
2773 DriverLink
!= SmramDriverInfoList
;
2774 DriverLink
= DriverLink
->ForwardLink
, DriverIndex
++) {
2775 DriverInfoData
= CR (
2777 MEMORY_PROFILE_DRIVER_INFO_DATA
,
2779 MEMORY_PROFILE_DRIVER_INFO_SIGNATURE
2781 DriverInfo
= &DriverInfoData
->DriverInfo
;
2782 DEBUG ((EFI_D_INFO
, " MEMORY_PROFILE_DRIVER_INFO (0x%x)\n", DriverIndex
));
2783 DEBUG ((EFI_D_INFO
, " FileName - %g\n", &DriverInfo
->FileName
));
2784 DEBUG ((EFI_D_INFO
, " ImageBase - 0x%016lx\n", DriverInfo
->ImageBase
));
2785 DEBUG ((EFI_D_INFO
, " ImageSize - 0x%016lx\n", DriverInfo
->ImageSize
));
2786 DEBUG ((EFI_D_INFO
, " EntryPoint - 0x%016lx\n", DriverInfo
->EntryPoint
));
2787 DEBUG ((EFI_D_INFO
, " ImageSubsystem - 0x%04x\n", DriverInfo
->ImageSubsystem
));
2788 DEBUG ((EFI_D_INFO
, " FileType - 0x%02x\n", DriverInfo
->FileType
));
2789 DEBUG ((EFI_D_INFO
, " CurrentUsage - 0x%016lx\n", DriverInfo
->CurrentUsage
));
2790 DEBUG ((EFI_D_INFO
, " PeakUsage - 0x%016lx\n", DriverInfo
->PeakUsage
));
2791 for (TypeIndex
= 0; TypeIndex
< sizeof (DriverInfo
->CurrentUsageByType
) / sizeof (DriverInfo
->CurrentUsageByType
[0]); TypeIndex
++) {
2792 if ((DriverInfo
->CurrentUsageByType
[TypeIndex
] != 0) ||
2793 (DriverInfo
->PeakUsageByType
[TypeIndex
] != 0)) {
2794 DEBUG ((EFI_D_INFO
, " CurrentUsage[0x%02x] - 0x%016lx (%a)\n", TypeIndex
, DriverInfo
->CurrentUsageByType
[TypeIndex
], ProfileMemoryTypeToStr (TypeIndex
)));
2795 DEBUG ((EFI_D_INFO
, " PeakUsage[0x%02x] - 0x%016lx (%a)\n", TypeIndex
, DriverInfo
->PeakUsageByType
[TypeIndex
], ProfileMemoryTypeToStr (TypeIndex
)));
2798 DEBUG ((EFI_D_INFO
, " AllocRecordCount - 0x%08x\n", DriverInfo
->AllocRecordCount
));
2800 AllocInfoList
= DriverInfoData
->AllocInfoList
;
2801 for (AllocLink
= AllocInfoList
->ForwardLink
, AllocIndex
= 0;
2802 AllocLink
!= AllocInfoList
;
2803 AllocLink
= AllocLink
->ForwardLink
, AllocIndex
++) {
2804 AllocInfoData
= CR (
2806 MEMORY_PROFILE_ALLOC_INFO_DATA
,
2808 MEMORY_PROFILE_ALLOC_INFO_SIGNATURE
2810 AllocInfo
= &AllocInfoData
->AllocInfo
;
2811 DEBUG ((EFI_D_INFO
, " MEMORY_PROFILE_ALLOC_INFO (0x%x)\n", AllocIndex
));
2812 DEBUG ((EFI_D_INFO
, " CallerAddress - 0x%016lx (Offset: 0x%08x)\n", AllocInfo
->CallerAddress
, AllocInfo
->CallerAddress
- DriverInfo
->ImageBase
));
2813 DEBUG ((EFI_D_INFO
, " SequenceId - 0x%08x\n", AllocInfo
->SequenceId
));
2814 if ((AllocInfo
->Action
& MEMORY_PROFILE_ACTION_USER_DEFINED_MASK
) != 0) {
2815 if (AllocInfoData
->ActionString
!= NULL
) {
2816 DEBUG ((EFI_D_INFO
, " Action - 0x%08x (%a)\n", AllocInfo
->Action
, AllocInfoData
->ActionString
));
2818 DEBUG ((EFI_D_INFO
, " Action - 0x%08x (UserDefined-0x%08x)\n", AllocInfo
->Action
, AllocInfo
->Action
));
2821 DEBUG ((EFI_D_INFO
, " Action - 0x%08x (%a)\n", AllocInfo
->Action
, ProfileActionToStr (AllocInfo
->Action
)));
2823 DEBUG ((EFI_D_INFO
, " MemoryType - 0x%08x (%a)\n", AllocInfo
->MemoryType
, ProfileMemoryTypeToStr (AllocInfo
->MemoryType
)));
2824 DEBUG ((EFI_D_INFO
, " Buffer - 0x%016lx\n", AllocInfo
->Buffer
));
2825 DEBUG ((EFI_D_INFO
, " Size - 0x%016lx\n", AllocInfo
->Size
));
2829 DEBUG ((EFI_D_INFO
, "======= SmramProfile end =======\n"));
2831 mSmramProfileGettingStatus
= SmramProfileGettingStatus
;
2835 Dump SMRAM infromation.
2844 if (IS_SMRAM_PROFILE_ENABLED
) {
2845 DumpSmramProfile ();
2846 DumpFreePagesList ();
2847 DumpFreePoolList ();