diff --git a/MdeModulePkg/Core/PiSmmCore/Page.c b/MdeModulePkg/Core/PiSmmCore/Page.c index 9cc2a4cabc..5c04e8c8bf 100644 --- a/MdeModulePkg/Core/PiSmmCore/Page.c +++ b/MdeModulePkg/Core/PiSmmCore/Page.c @@ -1,7 +1,7 @@ /** @file SMM Memory page management functions. - Copyright (c) 2009 - 2014, Intel Corporation. All rights reserved.
+ Copyright (c) 2009 - 2016, Intel Corporation. All rights reserved.
This program and the accompanying materials are licensed and made available under the terms and conditions of the BSD License which accompanies this distribution. The full text of the license may be found at @@ -226,7 +226,14 @@ SmmAllocatePages ( Status = SmmInternalAllocatePages (Type, MemoryType, NumberOfPages, Memory); if (!EFI_ERROR (Status)) { - SmmCoreUpdateProfile ((EFI_PHYSICAL_ADDRESS) (UINTN) RETURN_ADDRESS (0), MemoryProfileActionAllocatePages, MemoryType, EFI_PAGES_TO_SIZE (NumberOfPages), (VOID *) (UINTN) *Memory); + SmmCoreUpdateProfile ( + (EFI_PHYSICAL_ADDRESS) (UINTN) RETURN_ADDRESS (0), + MemoryProfileActionAllocatePages, + MemoryType, + EFI_PAGES_TO_SIZE (NumberOfPages), + (VOID *) (UINTN) *Memory, + NULL + ); } return Status; } @@ -344,7 +351,14 @@ SmmFreePages ( Status = SmmInternalFreePages (Memory, NumberOfPages); if (!EFI_ERROR (Status)) { - SmmCoreUpdateProfile ((EFI_PHYSICAL_ADDRESS) (UINTN) RETURN_ADDRESS (0), MemoryProfileActionFreePages, 0, EFI_PAGES_TO_SIZE (NumberOfPages), (VOID *) (UINTN) Memory); + SmmCoreUpdateProfile ( + (EFI_PHYSICAL_ADDRESS) (UINTN) RETURN_ADDRESS (0), + MemoryProfileActionFreePages, + EfiMaxMemoryType, + EFI_PAGES_TO_SIZE (NumberOfPages), + (VOID *) (UINTN) Memory, + NULL + ); } return Status; } diff --git a/MdeModulePkg/Core/PiSmmCore/PiSmmCore.c b/MdeModulePkg/Core/PiSmmCore/PiSmmCore.c index 7245f201fb..551560b1fc 100644 --- a/MdeModulePkg/Core/PiSmmCore/PiSmmCore.c +++ b/MdeModulePkg/Core/PiSmmCore/PiSmmCore.c @@ -1,7 +1,7 @@ /** @file SMM Core Main Entry Point - Copyright (c) 2009 - 2015, Intel Corporation. All rights reserved.
+ Copyright (c) 2009 - 2016, Intel Corporation. All rights reserved.
This program and the accompanying materials are licensed and made available under the terms and conditions of the BSD License which accompanies this distribution. The full text of the license may be found at @@ -632,6 +632,7 @@ SmmMain ( } RegisterSmramProfileHandler (); + SmramProfileInstallProtocol (); SmmCoreInstallLoadedImage (); diff --git a/MdeModulePkg/Core/PiSmmCore/PiSmmCore.h b/MdeModulePkg/Core/PiSmmCore/PiSmmCore.h index 0e9c92abef..000864d3aa 100644 --- a/MdeModulePkg/Core/PiSmmCore/PiSmmCore.h +++ b/MdeModulePkg/Core/PiSmmCore/PiSmmCore.h @@ -2,7 +2,7 @@ The internal header file includes the common header files, defines internal structure and functions used by SmmCore module. - Copyright (c) 2009 - 2015, Intel Corporation. All rights reserved.
+ Copyright (c) 2009 - 2016, Intel Corporation. All rights reserved.
This program and the accompanying materials are licensed and made available under the terms and conditions of the BSD License which accompanies this distribution. The full text of the license may be found at @@ -42,6 +42,7 @@ #include #include #include +#include #include #include #include @@ -884,17 +885,28 @@ SmramProfileInit ( VOID ); +/** + Install SMRAM profile protocol. + +**/ +VOID +SmramProfileInstallProtocol ( + VOID + ); + /** Register SMM image to SMRAM profile. @param DriverEntry SMM image info. @param RegisterToDxe Register image to DXE. - @retval TRUE Register success. - @retval FALSE Register fail. + @return EFI_SUCCESS Register successfully. + @return EFI_UNSUPPORTED Memory profile unsupported, + or memory profile for the image is not required. + @return EFI_OUT_OF_RESOURCES No enough resource for this register. **/ -BOOLEAN +EFI_STATUS RegisterSmramProfileImage ( IN EFI_SMM_DRIVER_ENTRY *DriverEntry, IN BOOLEAN RegisterToDxe @@ -906,11 +918,13 @@ RegisterSmramProfileImage ( @param DriverEntry SMM image info. @param UnregisterToDxe Unregister image from DXE. - @retval TRUE Unregister success. - @retval FALSE Unregister fail. + @return EFI_SUCCESS Unregister successfully. + @return EFI_UNSUPPORTED Memory profile unsupported, + or memory profile for the image is not required. + @return EFI_NOT_FOUND The image is not found. **/ -BOOLEAN +EFI_STATUS UnregisterSmramProfileImage ( IN EFI_SMM_DRIVER_ENTRY *DriverEntry, IN BOOLEAN UnregisterToDxe @@ -922,20 +936,31 @@ UnregisterSmramProfileImage ( @param CallerAddress Address of caller who call Allocate or Free. @param Action This Allocate or Free action. @param MemoryType Memory type. + EfiMaxMemoryType means the MemoryType is unknown. @param Size Buffer size. @param Buffer Buffer address. + @param ActionString String for memory profile action. + Only needed for user defined allocate action. - @retval TRUE Profile udpate success. - @retval FALSE Profile update fail. + @return EFI_SUCCESS Memory profile is updated. + @return EFI_UNSUPPORTED Memory profile is unsupported, + or memory profile for the image is not required, + or memory profile for the memory type is not required. + @return EFI_ACCESS_DENIED It is during memory profile data getting. + @return EFI_ABORTED Memory profile recording is not enabled. + @return EFI_OUT_OF_RESOURCES No enough resource to update memory profile for allocate action. + @return EFI_NOT_FOUND No matched allocate info found for free action. **/ -BOOLEAN +EFI_STATUS +EFIAPI SmmCoreUpdateProfile ( - IN EFI_PHYSICAL_ADDRESS CallerAddress, - IN MEMORY_PROFILE_ACTION Action, - IN EFI_MEMORY_TYPE MemoryType, // Valid for AllocatePages/AllocatePool - IN UINTN Size, // Valid for AllocatePages/FreePages/AllocatePool - IN VOID *Buffer + IN PHYSICAL_ADDRESS CallerAddress, + IN MEMORY_PROFILE_ACTION Action, + IN EFI_MEMORY_TYPE MemoryType, // Valid for AllocatePages/AllocatePool + IN UINTN Size, // Valid for AllocatePages/FreePages/AllocatePool + IN VOID *Buffer, + IN CHAR8 *ActionString OPTIONAL ); /** diff --git a/MdeModulePkg/Core/PiSmmCore/PiSmmCore.inf b/MdeModulePkg/Core/PiSmmCore/PiSmmCore.inf index 9c06b2ac2f..f7e32c4e09 100644 --- a/MdeModulePkg/Core/PiSmmCore/PiSmmCore.inf +++ b/MdeModulePkg/Core/PiSmmCore/PiSmmCore.inf @@ -1,7 +1,7 @@ ## @file # This module provide an SMM CIS compliant implementation of SMM Core. # -# Copyright (c) 2009 - 2015, Intel Corporation. All rights reserved.
+# Copyright (c) 2009 - 2016, Intel Corporation. All rights reserved.
# # This program and the accompanying materials # are licensed and made available under the terms and conditions of the BSD License @@ -48,6 +48,7 @@ BaseLib BaseMemoryLib PeCoffLib + PeCoffGetEntryPointLib CacheMaintenanceLib DebugLib ReportStatusCodeLib @@ -81,6 +82,7 @@ gEfiMdeModulePkgTokenSpaceGuid.PcdLoadModuleAtFixAddressEnable ## CONSUMES gEfiMdeModulePkgTokenSpaceGuid.PcdMemoryProfileMemoryType ## CONSUMES gEfiMdeModulePkgTokenSpaceGuid.PcdMemoryProfilePropertyMask ## CONSUMES + gEfiMdeModulePkgTokenSpaceGuid.PcdMemoryProfileDriverPath ## CONSUMES [Guids] gAprioriGuid ## SOMETIMES_CONSUMES ## File @@ -92,6 +94,8 @@ ## SOMETIMES_CONSUMES ## GUID # Locate protocol ## SOMETIMES_PRODUCES ## GUID # SmiHandlerRegister gEdkiiMemoryProfileGuid + ## SOMETIMES_PRODUCES ## GUID # Install protocol + gEdkiiSmmMemoryProfileGuid gZeroGuid ## SOMETIMES_CONSUMES ## GUID [UserExtensions.TianoCore."ExtraFiles"] diff --git a/MdeModulePkg/Core/PiSmmCore/Pool.c b/MdeModulePkg/Core/PiSmmCore/Pool.c index 79847b4bb6..53ef3e0779 100644 --- a/MdeModulePkg/Core/PiSmmCore/Pool.c +++ b/MdeModulePkg/Core/PiSmmCore/Pool.c @@ -1,7 +1,7 @@ /** @file SMM Memory pool management functions. - Copyright (c) 2009 - 2015, Intel Corporation. All rights reserved.
+ Copyright (c) 2009 - 2016, Intel Corporation. All rights reserved.
This program and the accompanying materials are licensed and made available under the terms and conditions of the BSD License which accompanies this distribution. The full text of the license may be found at @@ -260,7 +260,14 @@ SmmAllocatePool ( Status = SmmInternalAllocatePool (PoolType, Size, Buffer); if (!EFI_ERROR (Status)) { - SmmCoreUpdateProfile ((EFI_PHYSICAL_ADDRESS) (UINTN) RETURN_ADDRESS (0), MemoryProfileActionAllocatePool, PoolType, Size, *Buffer); + SmmCoreUpdateProfile ( + (EFI_PHYSICAL_ADDRESS) (UINTN) RETURN_ADDRESS (0), + MemoryProfileActionAllocatePool, + PoolType, + Size, + *Buffer, + NULL + ); } return Status; } @@ -319,7 +326,14 @@ SmmFreePool ( Status = SmmInternalFreePool (Buffer); if (!EFI_ERROR (Status)) { - SmmCoreUpdateProfile ((EFI_PHYSICAL_ADDRESS) (UINTN) RETURN_ADDRESS (0), MemoryProfileActionFreePool, 0, 0, Buffer); + SmmCoreUpdateProfile ( + (EFI_PHYSICAL_ADDRESS) (UINTN) RETURN_ADDRESS (0), + MemoryProfileActionFreePool, + EfiMaxMemoryType, + 0, + Buffer, + NULL + ); } return Status; } diff --git a/MdeModulePkg/Core/PiSmmCore/SmramProfileRecord.c b/MdeModulePkg/Core/PiSmmCore/SmramProfileRecord.c index 57b34a018d..281e382d5c 100644 --- a/MdeModulePkg/Core/PiSmmCore/SmramProfileRecord.c +++ b/MdeModulePkg/Core/PiSmmCore/SmramProfileRecord.c @@ -15,6 +15,10 @@ #include "PiSmmCore.h" #define IS_SMRAM_PROFILE_ENABLED ((PcdGet8 (PcdMemoryProfilePropertyMask) & BIT1) != 0) +#define IS_UEFI_MEMORY_PROFILE_ENABLED ((PcdGet8 (PcdMemoryProfilePropertyMask) & BIT0) != 0) + +#define GET_OCCUPIED_SIZE(ActualSize, Alignment) \ + ((ActualSize) + (((Alignment) - ((ActualSize) & ((Alignment) - 1))) & ((Alignment) - 1))) typedef struct { UINT32 Signature; @@ -26,12 +30,14 @@ typedef struct { UINT32 Signature; MEMORY_PROFILE_DRIVER_INFO DriverInfo; LIST_ENTRY *AllocInfoList; + CHAR8 *PdbString; LIST_ENTRY Link; } MEMORY_PROFILE_DRIVER_INFO_DATA; typedef struct { UINT32 Signature; MEMORY_PROFILE_ALLOC_INFO AllocInfo; + CHAR8 *ActionString; LIST_ENTRY Link; } MEMORY_PROFILE_ALLOC_INFO_DATA; @@ -72,7 +78,10 @@ GLOBAL_REMOVE_IF_UNREFERENCED MEMORY_PROFILE_CONTEXT_DATA mSmramProfileContext = GLOBAL_REMOVE_IF_UNREFERENCED MEMORY_PROFILE_CONTEXT_DATA *mSmramProfileContextPtr = NULL; BOOLEAN mSmramReadyToLock; -BOOLEAN mSmramProfileRecordingStatus = FALSE; +BOOLEAN mSmramProfileGettingStatus = FALSE; +BOOLEAN mSmramProfileRecordingEnable = MEMORY_PROFILE_RECORDING_DISABLE; +EFI_DEVICE_PATH_PROTOCOL *mSmramProfileDriverPath; +UINTN mSmramProfileDriverPathSize; /** Dump SMRAM infromation. @@ -83,6 +92,155 @@ DumpSmramInfo ( VOID ); +/** + Get memory profile data. + + @param[in] This The EDKII_SMM_MEMORY_PROFILE_PROTOCOL instance. + @param[in, out] ProfileSize On entry, points to the size in bytes of the ProfileBuffer. + On return, points to the size of the data returned in ProfileBuffer. + @param[out] ProfileBuffer Profile buffer. + + @return EFI_SUCCESS Get the memory profile data successfully. + @return EFI_UNSUPPORTED Memory profile is unsupported. + @return EFI_BUFFER_TO_SMALL The ProfileSize is too small for the resulting data. + ProfileSize is updated with the size required. + +**/ +EFI_STATUS +EFIAPI +SmramProfileProtocolGetData ( + IN EDKII_SMM_MEMORY_PROFILE_PROTOCOL *This, + IN OUT UINT64 *ProfileSize, + OUT VOID *ProfileBuffer + ); + +/** + Register image to memory profile. + + @param[in] This The EDKII_SMM_MEMORY_PROFILE_PROTOCOL instance. + @param[in] FilePath File path of the image. + @param[in] ImageBase Image base address. + @param[in] ImageSize Image size. + @param[in] FileType File type of the image. + + @return EFI_SUCCESS Register successfully. + @return EFI_UNSUPPORTED Memory profile is unsupported, + or memory profile for the image is not required. + @return EFI_OUT_OF_RESOURCE No enough resource for this register. + +**/ +EFI_STATUS +EFIAPI +SmramProfileProtocolRegisterImage ( + IN EDKII_SMM_MEMORY_PROFILE_PROTOCOL *This, + IN EFI_DEVICE_PATH_PROTOCOL *FilePath, + IN PHYSICAL_ADDRESS ImageBase, + IN UINT64 ImageSize, + IN EFI_FV_FILETYPE FileType + ); + +/** + Unregister image from memory profile. + + @param[in] This The EDKII_SMM_MEMORY_PROFILE_PROTOCOL instance. + @param[in] FilePath File path of the image. + @param[in] ImageBase Image base address. + @param[in] ImageSize Image size. + + @return EFI_SUCCESS Unregister successfully. + @return EFI_UNSUPPORTED Memory profile is unsupported, + or memory profile for the image is not required. + @return EFI_NOT_FOUND The image is not found. + +**/ +EFI_STATUS +EFIAPI +SmramProfileProtocolUnregisterImage ( + IN EDKII_SMM_MEMORY_PROFILE_PROTOCOL *This, + IN EFI_DEVICE_PATH_PROTOCOL *FilePath, + IN PHYSICAL_ADDRESS ImageBase, + IN UINT64 ImageSize + ); + +/** + Get memory profile recording state. + + @param[in] This The EDKII_SMM_MEMORY_PROFILE_PROTOCOL instance. + @param[out] RecordingState Recording state. + + @return EFI_SUCCESS Memory profile recording state is returned. + @return EFI_UNSUPPORTED Memory profile is unsupported. + @return EFI_INVALID_PARAMETER RecordingState is NULL. + +**/ +EFI_STATUS +EFIAPI +SmramProfileProtocolGetRecordingState ( + IN EDKII_SMM_MEMORY_PROFILE_PROTOCOL *This, + OUT BOOLEAN *RecordingState + ); + +/** + Set memory profile recording state. + + @param[in] This The EDKII_SMM_MEMORY_PROFILE_PROTOCOL instance. + @param[in] RecordingState Recording state. + + @return EFI_SUCCESS Set memory profile recording state successfully. + @return EFI_UNSUPPORTED Memory profile is unsupported. + +**/ +EFI_STATUS +EFIAPI +SmramProfileProtocolSetRecordingState ( + IN EDKII_SMM_MEMORY_PROFILE_PROTOCOL *This, + IN BOOLEAN RecordingState + ); + +/** + Record memory profile of multilevel caller. + + @param[in] This The EDKII_SMM_MEMORY_PROFILE_PROTOCOL instance. + @param[in] CallerAddress Address of caller. + @param[in] Action Memory profile action. + @param[in] MemoryType Memory type. + EfiMaxMemoryType means the MemoryType is unknown. + @param[in] Buffer Buffer address. + @param[in] Size Buffer size. + @param[in] ActionString String for memory profile action. + Only needed for user defined allocate action. + + @return EFI_SUCCESS Memory profile is updated. + @return EFI_UNSUPPORTED Memory profile is unsupported, + or memory profile for the image is not required, + or memory profile for the memory type is not required. + @return EFI_ACCESS_DENIED It is during memory profile data getting. + @return EFI_ABORTED Memory profile recording is not enabled. + @return EFI_OUT_OF_RESOURCES No enough resource to update memory profile for allocate action. + @return EFI_NOT_FOUND No matched allocate info found for free action. + +**/ +EFI_STATUS +EFIAPI +SmramProfileProtocolRecord ( + IN EDKII_SMM_MEMORY_PROFILE_PROTOCOL *This, + IN PHYSICAL_ADDRESS CallerAddress, + IN MEMORY_PROFILE_ACTION Action, + IN EFI_MEMORY_TYPE MemoryType, + IN VOID *Buffer, + IN UINTN Size, + IN CHAR8 *ActionString OPTIONAL + ); + +EDKII_SMM_MEMORY_PROFILE_PROTOCOL mSmmProfileProtocol = { + SmramProfileProtocolGetData, + SmramProfileProtocolRegisterImage, + SmramProfileProtocolUnregisterImage, + SmramProfileProtocolGetRecordingState, + SmramProfileProtocolSetRecordingState, + SmramProfileProtocolRecord, +}; + /** Return SMRAM profile context. @@ -239,7 +397,6 @@ InternalPeCoffGetEntryPoint ( @param ImageSize Image size. @param EntryPoint Entry point of the image. @param ImageSubsystem Image subsystem of the image. - @param FileType File type of the image. @return Pointer to memory profile driver info. @@ -260,13 +417,27 @@ BuildDriverInfo ( MEMORY_PROFILE_DRIVER_INFO *DriverInfo; MEMORY_PROFILE_DRIVER_INFO_DATA *DriverInfoData; VOID *EntryPointInImage; + CHAR8 *PdbString; + UINTN PdbSize; + UINTN PdbOccupiedSize; + + PdbSize = 0; + PdbOccupiedSize = 0; + PdbString = NULL; + if (ImageBase != 0) { + PdbString = PeCoffLoaderGetPdbPointer ((VOID*) (UINTN) ImageBase); + if (PdbString != NULL) { + PdbSize = AsciiStrSize (PdbString); + PdbOccupiedSize = GET_OCCUPIED_SIZE (PdbSize, sizeof (UINT64)); + } + } // // Use SmmInternalAllocatePool() that will not update profile for this AllocatePool action. // Status = SmmInternalAllocatePool ( EfiRuntimeServicesData, - sizeof (*DriverInfoData) + sizeof (LIST_ENTRY), + sizeof (*DriverInfoData) + sizeof (LIST_ENTRY) + PdbSize, (VOID **) &DriverInfoData ); if (EFI_ERROR (Status)) { @@ -278,7 +449,7 @@ BuildDriverInfo ( DriverInfo = &DriverInfoData->DriverInfo; DriverInfoData->Signature = MEMORY_PROFILE_DRIVER_INFO_SIGNATURE; DriverInfo->Header.Signature = MEMORY_PROFILE_DRIVER_INFO_SIGNATURE; - DriverInfo->Header.Length = sizeof (MEMORY_PROFILE_DRIVER_INFO); + DriverInfo->Header.Length = (UINT16) (sizeof (MEMORY_PROFILE_DRIVER_INFO) + PdbOccupiedSize); DriverInfo->Header.Revision = MEMORY_PROFILE_DRIVER_INFO_REVISION; if (FileName != NULL) { CopyMem (&DriverInfo->FileName, FileName, sizeof (EFI_GUID)); @@ -302,6 +473,14 @@ BuildDriverInfo ( DriverInfo->CurrentUsage = 0; DriverInfo->PeakUsage = 0; DriverInfo->AllocRecordCount = 0; + if (PdbSize != 0) { + DriverInfo->PdbStringOffset = (UINT16) sizeof (MEMORY_PROFILE_DRIVER_INFO); + DriverInfoData->PdbString = (CHAR8 *) (DriverInfoData->AllocInfoList + 1); + CopyMem (DriverInfoData->PdbString, PdbString, PdbSize); + } else { + DriverInfo->PdbStringOffset = 0; + DriverInfoData->PdbString = NULL; + } InsertTailList (ContextData->DriverInfoList, &DriverInfoData->Link); ContextData->Context.ImageCount ++; @@ -332,7 +511,7 @@ RegisterImageToDxe ( MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *FilePath; UINT8 TempBuffer[sizeof (MEDIA_FW_VOL_FILEPATH_DEVICE_PATH) + sizeof (EFI_DEVICE_PATH_PROTOCOL)]; - if (IS_SMRAM_PROFILE_ENABLED) { + if (IS_UEFI_MEMORY_PROFILE_ENABLED) { FilePath = (MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *)TempBuffer; Status = gBS->LocateProtocol (&gEdkiiMemoryProfileGuid, NULL, (VOID **) &ProfileProtocol); @@ -371,7 +550,7 @@ UnregisterImageFromDxe ( MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *FilePath; UINT8 TempBuffer[sizeof (MEDIA_FW_VOL_FILEPATH_DEVICE_PATH) + sizeof (EFI_DEVICE_PATH_PROTOCOL)]; - if (IS_SMRAM_PROFILE_ENABLED) { + if (IS_UEFI_MEMORY_PROFILE_ENABLED) { FilePath = (MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *)TempBuffer; Status = gBS->LocateProtocol (&gEdkiiMemoryProfileGuid, NULL, (VOID *) &ProfileProtocol); @@ -389,6 +568,65 @@ UnregisterImageFromDxe ( } } +/** + Return if record for this driver is needed.. + + @param DriverFilePath Driver file path. + + @retval TRUE Record for this driver is needed. + @retval FALSE Record for this driver is not needed. + +**/ +BOOLEAN +NeedRecordThisDriver ( + IN EFI_DEVICE_PATH_PROTOCOL *DriverFilePath + ) +{ + EFI_DEVICE_PATH_PROTOCOL *TmpDevicePath; + EFI_DEVICE_PATH_PROTOCOL *DevicePathInstance; + UINTN DevicePathSize; + UINTN FilePathSize; + + if (!IsDevicePathValid (mSmramProfileDriverPath, mSmramProfileDriverPathSize)) { + // + // Invalid Device Path means record all. + // + return TRUE; + } + + // + // Record FilePath without end node. + // + FilePathSize = GetDevicePathSize (DriverFilePath) - sizeof(EFI_DEVICE_PATH_PROTOCOL); + + DevicePathInstance = mSmramProfileDriverPath; + do { + // + // Find End node (it might be END_ENTIRE or END_INSTANCE) + // + TmpDevicePath = DevicePathInstance; + while (!IsDevicePathEndType (TmpDevicePath)) { + TmpDevicePath = NextDevicePathNode (TmpDevicePath); + } + + // + // Do not compare END node + // + DevicePathSize = (UINTN)TmpDevicePath - (UINTN)DevicePathInstance; + if ((FilePathSize == DevicePathSize) && + (CompareMem (DriverFilePath, DevicePathInstance, DevicePathSize) == 0)) { + return TRUE; + } + + // + // Get next instance + // + DevicePathInstance = (EFI_DEVICE_PATH_PROTOCOL *)((UINTN)DevicePathInstance + DevicePathSize + DevicePathNodeLength(TmpDevicePath)); + } while (DevicePathSubType (TmpDevicePath) != END_ENTIRE_DEVICE_PATH_SUBTYPE); + + return FALSE; +} + /** Register SMM Core to SMRAM profile. @@ -405,15 +643,16 @@ RegisterSmmCore ( { MEMORY_PROFILE_DRIVER_INFO_DATA *DriverInfoData; PHYSICAL_ADDRESS ImageBase; + UINT8 TempBuffer[sizeof(MEDIA_FW_VOL_FILEPATH_DEVICE_PATH) + sizeof(EFI_DEVICE_PATH_PROTOCOL)]; + MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *FilePath; - ASSERT (ContextData != NULL); + FilePath = (MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *) TempBuffer; + EfiInitializeFwVolDevicepathNode (FilePath, &gEfiCallerIdGuid); + SetDevicePathEndNode (FilePath + 1); - RegisterImageToDxe ( - &gEfiCallerIdGuid, - gSmmCorePrivate->PiSmmCoreImageBase, - gSmmCorePrivate->PiSmmCoreImageSize, - EFI_FV_FILETYPE_SMM_CORE - ); + if (!NeedRecordThisDriver ((EFI_DEVICE_PATH_PROTOCOL *) FilePath)) { + return FALSE; + } ImageBase = gSmmCorePrivate->PiSmmCoreImageBase; DriverInfoData = BuildDriverInfo ( @@ -443,6 +682,13 @@ SmramProfileInit ( { MEMORY_PROFILE_CONTEXT_DATA *SmramProfileContext; + RegisterImageToDxe ( + &gEfiCallerIdGuid, + gSmmCorePrivate->PiSmmCoreImageBase, + gSmmCorePrivate->PiSmmCoreImageSize, + EFI_FV_FILETYPE_SMM_CORE + ); + if (!IS_SMRAM_PROFILE_ENABLED) { return; } @@ -452,7 +698,14 @@ SmramProfileInit ( return; } - mSmramProfileRecordingStatus = TRUE; + mSmramProfileGettingStatus = FALSE; + if ((PcdGet8 (PcdMemoryProfilePropertyMask) & BIT7) != 0) { + mSmramProfileRecordingEnable = MEMORY_PROFILE_RECORDING_DISABLE; + } else { + mSmramProfileRecordingEnable = MEMORY_PROFILE_RECORDING_ENABLE; + } + mSmramProfileDriverPathSize = PcdGetSize (PcdMemoryProfileDriverPath); + mSmramProfileDriverPath = AllocateCopyPool (mSmramProfileDriverPathSize, PcdGetPtr (PcdMemoryProfileDriverPath)); mSmramProfileContextPtr = &mSmramProfileContext; RegisterSmmCore (&mSmramProfileContext); @@ -460,17 +713,76 @@ SmramProfileInit ( DEBUG ((EFI_D_INFO, "SmramProfileInit SmramProfileContext - 0x%x\n", &mSmramProfileContext)); } +/** + Install SMRAM profile protocol. + +**/ +VOID +SmramProfileInstallProtocol ( + VOID + ) +{ + EFI_HANDLE Handle; + EFI_STATUS Status; + + if (!IS_SMRAM_PROFILE_ENABLED) { + return; + } + + Handle = NULL; + Status = SmmInstallProtocolInterface ( + &Handle, + &gEdkiiSmmMemoryProfileGuid, + EFI_NATIVE_INTERFACE, + &mSmmProfileProtocol + ); + ASSERT_EFI_ERROR (Status); +} + +/** + Get the GUID file name from the file path. + + @param FilePath File path. + + @return The GUID file name from the file path. + +**/ +EFI_GUID * +GetFileNameFromFilePath ( + IN EFI_DEVICE_PATH_PROTOCOL *FilePath + ) +{ + MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *ThisFilePath; + EFI_GUID *FileName; + + FileName = NULL; + if (FilePath != NULL) { + ThisFilePath = (MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *) FilePath; + while (!IsDevicePathEnd (ThisFilePath)) { + FileName = EfiGetNameGuidFromFwVolDevicePathNode (ThisFilePath); + if (FileName != NULL) { + break; + } + ThisFilePath = (MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *) NextDevicePathNode (ThisFilePath); + } + } + + return FileName; +} + /** Register SMM image to SMRAM profile. @param DriverEntry SMM image info. @param RegisterToDxe Register image to DXE. - @retval TRUE Register success. - @retval FALSE Register fail. + @return EFI_SUCCESS Register successfully. + @return EFI_UNSUPPORTED Memory profile is unsupported, + or memory profile for the image is not required. + @return EFI_OUT_OF_RESOURCES No enough resource for this register. **/ -BOOLEAN +EFI_STATUS RegisterSmramProfileImage ( IN EFI_SMM_DRIVER_ENTRY *DriverEntry, IN BOOLEAN RegisterToDxe @@ -478,10 +790,8 @@ RegisterSmramProfileImage ( { MEMORY_PROFILE_CONTEXT_DATA *ContextData; MEMORY_PROFILE_DRIVER_INFO_DATA *DriverInfoData; - - if (!IS_SMRAM_PROFILE_ENABLED) { - return FALSE; - } + UINT8 TempBuffer[sizeof(MEDIA_FW_VOL_FILEPATH_DEVICE_PATH) + sizeof(EFI_DEVICE_PATH_PROTOCOL)]; + MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *FilePath; if (RegisterToDxe) { RegisterImageToDxe ( @@ -492,9 +802,21 @@ RegisterSmramProfileImage ( ); } + if (!IS_SMRAM_PROFILE_ENABLED) { + return EFI_UNSUPPORTED; + } + + FilePath = (MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *) TempBuffer; + EfiInitializeFwVolDevicepathNode (FilePath, &DriverEntry->FileName); + SetDevicePathEndNode (FilePath + 1); + + if (!NeedRecordThisDriver ((EFI_DEVICE_PATH_PROTOCOL *) FilePath)) { + return EFI_UNSUPPORTED; + } + ContextData = GetSmramProfileContext (); if (ContextData == NULL) { - return FALSE; + return EFI_UNSUPPORTED; } DriverInfoData = BuildDriverInfo ( @@ -507,10 +829,10 @@ RegisterSmramProfileImage ( EFI_FV_FILETYPE_SMM ); if (DriverInfoData == NULL) { - return FALSE; + return EFI_OUT_OF_RESOURCES; } - return TRUE; + return EFI_SUCCESS; } /** @@ -557,42 +879,6 @@ GetMemoryProfileDriverInfoByFileNameAndAddress ( return NULL; } -/** - Search dummy image from SMRAM profile. - - @param ContextData Memory profile context. - - @return Pointer to memory profile driver info. - -**/ -MEMORY_PROFILE_DRIVER_INFO_DATA * -FindDummyImage ( - IN MEMORY_PROFILE_CONTEXT_DATA *ContextData - ) -{ - MEMORY_PROFILE_DRIVER_INFO_DATA *DriverInfoData; - LIST_ENTRY *DriverLink; - LIST_ENTRY *DriverInfoList; - - DriverInfoList = ContextData->DriverInfoList; - - for (DriverLink = DriverInfoList->ForwardLink; - DriverLink != DriverInfoList; - DriverLink = DriverLink->ForwardLink) { - DriverInfoData = CR ( - DriverLink, - MEMORY_PROFILE_DRIVER_INFO_DATA, - Link, - MEMORY_PROFILE_DRIVER_INFO_SIGNATURE - ); - if (CompareGuid (&gZeroGuid, &DriverInfoData->DriverInfo.FileName)) { - return DriverInfoData; - } - } - - return BuildDriverInfo (ContextData, &gZeroGuid, 0, 0, 0, 0, 0); -} - /** Search image from memory profile. It will return image, if (Address >= ImageBuffer) AND (Address < ImageBuffer + ImageSize) @@ -632,10 +918,7 @@ GetMemoryProfileDriverInfoFromAddress ( } } - // - // Should never come here. - // - return FindDummyImage (ContextData); + return NULL; } /** @@ -644,11 +927,13 @@ GetMemoryProfileDriverInfoFromAddress ( @param DriverEntry SMM image info. @param UnregisterFromDxe Unregister image from DXE. - @retval TRUE Unregister success. - @retval FALSE Unregister fail. + @return EFI_SUCCESS Unregister successfully. + @return EFI_UNSUPPORTED Memory profile is unsupported, + or memory profile for the image is not required. + @return EFI_NOT_FOUND The image is not found. **/ -BOOLEAN +EFI_STATUS UnregisterSmramProfileImage ( IN EFI_SMM_DRIVER_ENTRY *DriverEntry, IN BOOLEAN UnregisterFromDxe @@ -660,10 +945,8 @@ UnregisterSmramProfileImage ( EFI_GUID *FileName; PHYSICAL_ADDRESS ImageAddress; VOID *EntryPointInImage; - - if (!IS_SMRAM_PROFILE_ENABLED) { - return FALSE; - } + UINT8 TempBuffer[sizeof(MEDIA_FW_VOL_FILEPATH_DEVICE_PATH) + sizeof(EFI_DEVICE_PATH_PROTOCOL)]; + MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *FilePath; if (UnregisterFromDxe) { UnregisterImageFromDxe ( @@ -673,9 +956,21 @@ UnregisterSmramProfileImage ( ); } + if (!IS_SMRAM_PROFILE_ENABLED) { + return EFI_UNSUPPORTED; + } + + FilePath = (MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *) TempBuffer; + EfiInitializeFwVolDevicepathNode (FilePath, &DriverEntry->FileName); + SetDevicePathEndNode (FilePath + 1); + + if (!NeedRecordThisDriver ((EFI_DEVICE_PATH_PROTOCOL *) FilePath)) { + return EFI_UNSUPPORTED; + } + ContextData = GetSmramProfileContext (); if (ContextData == NULL) { - return FALSE; + return EFI_UNSUPPORTED; } DriverInfoData = NULL; @@ -697,12 +992,13 @@ UnregisterSmramProfileImage ( DriverInfoData = GetMemoryProfileDriverInfoFromAddress (ContextData, ImageAddress); } if (DriverInfoData == NULL) { - return FALSE; + return EFI_NOT_FOUND; } ContextData->Context.TotalImageSize -= DriverInfoData->DriverInfo.ImageSize; - DriverInfoData->DriverInfo.ImageBase = 0; + // Keep the ImageBase for RVA calculation in Application. + //DriverInfoData->DriverInfo.ImageBase = 0; DriverInfoData->DriverInfo.ImageSize = 0; if (DriverInfoData->DriverInfo.PeakUsage == 0) { @@ -714,7 +1010,7 @@ UnregisterSmramProfileImage ( SmmInternalFreePool (DriverInfoData); } - return TRUE; + return EFI_SUCCESS; } /** @@ -807,54 +1103,80 @@ SmramProfileUpdateFreePages ( @param MemoryType Memory type. @param Size Buffer size. @param Buffer Buffer address. + @param ActionString String for memory profile action. - @retval TRUE Profile udpate success. - @retval FALSE Profile update fail. + @return EFI_SUCCESS Memory profile is updated. + @return EFI_UNSUPPORTED Memory profile is unsupported, + or memory profile for the image is not required. + @return EFI_OUT_OF_RESOURCES No enough resource to update memory profile for allocate action. **/ -BOOLEAN +EFI_STATUS SmmCoreUpdateProfileAllocate ( IN PHYSICAL_ADDRESS CallerAddress, IN MEMORY_PROFILE_ACTION Action, IN EFI_MEMORY_TYPE MemoryType, IN UINTN Size, - IN VOID *Buffer + IN VOID *Buffer, + IN CHAR8 *ActionString OPTIONAL ) { EFI_STATUS Status; - MEMORY_PROFILE_CONTEXT *Context; - MEMORY_PROFILE_DRIVER_INFO *DriverInfo; - MEMORY_PROFILE_ALLOC_INFO *AllocInfo; + MEMORY_PROFILE_CONTEXT *Context; + MEMORY_PROFILE_DRIVER_INFO *DriverInfo; + MEMORY_PROFILE_ALLOC_INFO *AllocInfo; MEMORY_PROFILE_CONTEXT_DATA *ContextData; MEMORY_PROFILE_DRIVER_INFO_DATA *DriverInfoData; MEMORY_PROFILE_ALLOC_INFO_DATA *AllocInfoData; EFI_MEMORY_TYPE ProfileMemoryIndex; + MEMORY_PROFILE_ACTION BasicAction; + UINTN ActionStringSize; + UINTN ActionStringOccupiedSize; - AllocInfoData = NULL; + BasicAction = Action & MEMORY_PROFILE_ACTION_BASIC_MASK; ContextData = GetSmramProfileContext (); if (ContextData == NULL) { - return FALSE; + return EFI_UNSUPPORTED; } DriverInfoData = GetMemoryProfileDriverInfoFromAddress (ContextData, CallerAddress); - ASSERT (DriverInfoData != NULL); + if (DriverInfoData == NULL) { + return EFI_UNSUPPORTED; + } + + ActionStringSize = 0; + ActionStringOccupiedSize = 0; + if (ActionString != NULL) { + ActionStringSize = AsciiStrSize (ActionString); + ActionStringOccupiedSize = GET_OCCUPIED_SIZE (ActionStringSize, sizeof (UINT64)); + } // // Use SmmInternalAllocatePool() that will not update profile for this AllocatePool action. // + AllocInfoData = NULL; Status = SmmInternalAllocatePool ( EfiRuntimeServicesData, - sizeof (*AllocInfoData), + sizeof (*AllocInfoData) + ActionStringSize, (VOID **) &AllocInfoData ); if (EFI_ERROR (Status)) { - return FALSE; + return EFI_OUT_OF_RESOURCES; } + ASSERT (AllocInfoData != NULL); + + // + // Only update SequenceCount if and only if it is basic action. + // + if (Action == BasicAction) { + ContextData->Context.SequenceCount ++; + } + AllocInfo = &AllocInfoData->AllocInfo; AllocInfoData->Signature = MEMORY_PROFILE_ALLOC_INFO_SIGNATURE; AllocInfo->Header.Signature = MEMORY_PROFILE_ALLOC_INFO_SIGNATURE; - AllocInfo->Header.Length = sizeof (MEMORY_PROFILE_ALLOC_INFO); + AllocInfo->Header.Length = (UINT16) (sizeof (MEMORY_PROFILE_ALLOC_INFO) + ActionStringOccupiedSize); AllocInfo->Header.Revision = MEMORY_PROFILE_ALLOC_INFO_REVISION; AllocInfo->CallerAddress = CallerAddress; AllocInfo->SequenceId = ContextData->Context.SequenceCount; @@ -862,42 +1184,56 @@ SmmCoreUpdateProfileAllocate ( AllocInfo->MemoryType = MemoryType; AllocInfo->Buffer = (PHYSICAL_ADDRESS) (UINTN) Buffer; AllocInfo->Size = Size; + if (ActionString != NULL) { + AllocInfo->ActionStringOffset = (UINT16) sizeof (MEMORY_PROFILE_ALLOC_INFO); + AllocInfoData->ActionString = (CHAR8 *) (AllocInfoData + 1); + CopyMem (AllocInfoData->ActionString, ActionString, ActionStringSize); + } else { + AllocInfo->ActionStringOffset = 0; + AllocInfoData->ActionString = NULL; + } InsertTailList (DriverInfoData->AllocInfoList, &AllocInfoData->Link); - ProfileMemoryIndex = GetProfileMemoryIndex (MemoryType); - + Context = &ContextData->Context; DriverInfo = &DriverInfoData->DriverInfo; - DriverInfo->CurrentUsage += Size; - if (DriverInfo->PeakUsage < DriverInfo->CurrentUsage) { - DriverInfo->PeakUsage = DriverInfo->CurrentUsage; - } - DriverInfo->CurrentUsageByType[ProfileMemoryIndex] += Size; - if (DriverInfo->PeakUsageByType[ProfileMemoryIndex] < DriverInfo->CurrentUsageByType[ProfileMemoryIndex]) { - DriverInfo->PeakUsageByType[ProfileMemoryIndex] = DriverInfo->CurrentUsageByType[ProfileMemoryIndex]; - } DriverInfo->AllocRecordCount ++; - Context = &ContextData->Context; - Context->CurrentTotalUsage += Size; - if (Context->PeakTotalUsage < Context->CurrentTotalUsage) { - Context->PeakTotalUsage = Context->CurrentTotalUsage; - } - Context->CurrentTotalUsageByType[ProfileMemoryIndex] += Size; - if (Context->PeakTotalUsageByType[ProfileMemoryIndex] < Context->CurrentTotalUsageByType[ProfileMemoryIndex]) { - Context->PeakTotalUsageByType[ProfileMemoryIndex] = Context->CurrentTotalUsageByType[ProfileMemoryIndex]; - } - Context->SequenceCount ++; + // + // Update summary if and only if it is basic action. + // + if (Action == BasicAction) { + ProfileMemoryIndex = GetProfileMemoryIndex (MemoryType); - SmramProfileUpdateFreePages (ContextData); - return TRUE; + DriverInfo->CurrentUsage += Size; + if (DriverInfo->PeakUsage < DriverInfo->CurrentUsage) { + DriverInfo->PeakUsage = DriverInfo->CurrentUsage; + } + DriverInfo->CurrentUsageByType[ProfileMemoryIndex] += Size; + if (DriverInfo->PeakUsageByType[ProfileMemoryIndex] < DriverInfo->CurrentUsageByType[ProfileMemoryIndex]) { + DriverInfo->PeakUsageByType[ProfileMemoryIndex] = DriverInfo->CurrentUsageByType[ProfileMemoryIndex]; + } + + Context->CurrentTotalUsage += Size; + if (Context->PeakTotalUsage < Context->CurrentTotalUsage) { + Context->PeakTotalUsage = Context->CurrentTotalUsage; + } + Context->CurrentTotalUsageByType[ProfileMemoryIndex] += Size; + if (Context->PeakTotalUsageByType[ProfileMemoryIndex] < Context->CurrentTotalUsageByType[ProfileMemoryIndex]) { + Context->PeakTotalUsageByType[ProfileMemoryIndex] = Context->CurrentTotalUsageByType[ProfileMemoryIndex]; + } + + SmramProfileUpdateFreePages (ContextData); + } + + return EFI_SUCCESS; } /** Get memory profile alloc info from memory profile @param DriverInfoData Driver info - @param Action This Free action + @param BasicAction This Free basic action @param Size Buffer size @param Buffer Buffer address @@ -906,7 +1242,7 @@ SmmCoreUpdateProfileAllocate ( MEMORY_PROFILE_ALLOC_INFO_DATA * GetMemoryProfileAllocInfoFromAddress ( IN MEMORY_PROFILE_DRIVER_INFO_DATA *DriverInfoData, - IN MEMORY_PROFILE_ACTION Action, + IN MEMORY_PROFILE_ACTION BasicAction, IN UINTN Size, IN VOID *Buffer ) @@ -928,10 +1264,10 @@ GetMemoryProfileAllocInfoFromAddress ( MEMORY_PROFILE_ALLOC_INFO_SIGNATURE ); AllocInfo = &AllocInfoData->AllocInfo; - if (AllocInfo->Action != Action) { + if ((AllocInfo->Action & MEMORY_PROFILE_ACTION_BASIC_MASK) != BasicAction) { continue; } - switch (Action) { + switch (BasicAction) { case MemoryProfileActionAllocatePages: if ((AllocInfo->Buffer <= (PHYSICAL_ADDRESS) (UINTN) Buffer) && ((AllocInfo->Buffer + AllocInfo->Size) >= ((PHYSICAL_ADDRESS) (UINTN) Buffer + Size))) { @@ -960,11 +1296,12 @@ GetMemoryProfileAllocInfoFromAddress ( @param Size Buffer size. @param Buffer Buffer address. - @retval TRUE Profile udpate success. - @retval FALSE Profile update fail. + @return EFI_SUCCESS Memory profile is updated. + @return EFI_UNSUPPORTED Memory profile is unsupported. + @return EFI_NOT_FOUND No matched allocate info found for free action. **/ -BOOLEAN +EFI_STATUS SmmCoreUpdateProfileFree ( IN PHYSICAL_ADDRESS CallerAddress, IN MEMORY_PROFILE_ACTION Action, @@ -982,114 +1319,140 @@ SmmCoreUpdateProfileFree ( MEMORY_PROFILE_DRIVER_INFO_DATA *ThisDriverInfoData; MEMORY_PROFILE_ALLOC_INFO_DATA *AllocInfoData; EFI_MEMORY_TYPE ProfileMemoryIndex; + MEMORY_PROFILE_ACTION BasicAction; + BOOLEAN Found; + + BasicAction = Action & MEMORY_PROFILE_ACTION_BASIC_MASK; ContextData = GetSmramProfileContext (); if (ContextData == NULL) { - return FALSE; + return EFI_UNSUPPORTED; } DriverInfoData = GetMemoryProfileDriverInfoFromAddress (ContextData, CallerAddress); - ASSERT (DriverInfoData != NULL); - switch (Action) { - case MemoryProfileActionFreePages: - AllocInfoData = GetMemoryProfileAllocInfoFromAddress (DriverInfoData, MemoryProfileActionAllocatePages, Size, Buffer); - break; - case MemoryProfileActionFreePool: - AllocInfoData = GetMemoryProfileAllocInfoFromAddress (DriverInfoData, MemoryProfileActionAllocatePool, 0, Buffer); - break; - default: - ASSERT (FALSE); - AllocInfoData = NULL; - break; - } - if (AllocInfoData == NULL) { - // - // Legal case, because driver A might free memory allocated by driver B, by some protocol. - // - DriverInfoList = ContextData->DriverInfoList; + // + // Do not return if DriverInfoData == NULL here, + // because driver A might free memory allocated by driver B. + // - for (DriverLink = DriverInfoList->ForwardLink; - DriverLink != DriverInfoList; - DriverLink = DriverLink->ForwardLink) { - ThisDriverInfoData = CR ( - DriverLink, - MEMORY_PROFILE_DRIVER_INFO_DATA, - Link, - MEMORY_PROFILE_DRIVER_INFO_SIGNATURE - ); - switch (Action) { + // + // Need use do-while loop to find all possible record, + // because one address might be recorded multiple times. + // + Found = FALSE; + AllocInfoData = NULL; + do { + if (DriverInfoData != NULL) { + switch (BasicAction) { case MemoryProfileActionFreePages: - AllocInfoData = GetMemoryProfileAllocInfoFromAddress (ThisDriverInfoData, MemoryProfileActionAllocatePages, Size, Buffer); + AllocInfoData = GetMemoryProfileAllocInfoFromAddress (DriverInfoData, MemoryProfileActionAllocatePages, Size, Buffer); break; case MemoryProfileActionFreePool: - AllocInfoData = GetMemoryProfileAllocInfoFromAddress (ThisDriverInfoData, MemoryProfileActionAllocatePool, 0, Buffer); + AllocInfoData = GetMemoryProfileAllocInfoFromAddress (DriverInfoData, MemoryProfileActionAllocatePool, 0, Buffer); break; default: ASSERT (FALSE); AllocInfoData = NULL; break; } - if (AllocInfoData != NULL) { - DriverInfoData = ThisDriverInfoData; - break; + } + if (AllocInfoData == NULL) { + // + // Legal case, because driver A might free memory allocated by driver B, by some protocol. + // + DriverInfoList = ContextData->DriverInfoList; + + for (DriverLink = DriverInfoList->ForwardLink; + DriverLink != DriverInfoList; + DriverLink = DriverLink->ForwardLink) { + ThisDriverInfoData = CR ( + DriverLink, + MEMORY_PROFILE_DRIVER_INFO_DATA, + Link, + MEMORY_PROFILE_DRIVER_INFO_SIGNATURE + ); + switch (BasicAction) { + case MemoryProfileActionFreePages: + AllocInfoData = GetMemoryProfileAllocInfoFromAddress (ThisDriverInfoData, MemoryProfileActionAllocatePages, Size, Buffer); + break; + case MemoryProfileActionFreePool: + AllocInfoData = GetMemoryProfileAllocInfoFromAddress (ThisDriverInfoData, MemoryProfileActionAllocatePool, 0, Buffer); + break; + default: + ASSERT (FALSE); + AllocInfoData = NULL; + break; + } + if (AllocInfoData != NULL) { + DriverInfoData = ThisDriverInfoData; + break; + } + } + + if (AllocInfoData == NULL) { + // + // If (!Found), no matched allocate info is found for this free action. + // It is because the specified memory type allocate actions have been filtered by + // CoreNeedRecordProfile(), but free actions have no memory type information, + // they can not be filtered by CoreNeedRecordProfile(). Then, they will be + // filtered here. + // + // If (Found), it is normal exit path. + return (Found ? EFI_SUCCESS : EFI_NOT_FOUND); } } - if (AllocInfoData == NULL) { - // - // No matched allocate operation is found for this free operation. - // It is because the specified memory type allocate operation has been - // filtered by CoreNeedRecordProfile(), but free operations have no - // memory type information, they can not be filtered by CoreNeedRecordProfile(). - // Then, they will be filtered here. - // - return FALSE; + Found = TRUE; + + Context = &ContextData->Context; + DriverInfo = &DriverInfoData->DriverInfo; + AllocInfo = &AllocInfoData->AllocInfo; + + DriverInfo->AllocRecordCount --; + // + // Update summary if and only if it is basic action. + // + if (AllocInfo->Action == (AllocInfo->Action & MEMORY_PROFILE_ACTION_BASIC_MASK)) { + ProfileMemoryIndex = GetProfileMemoryIndex (AllocInfo->MemoryType); + + Context->CurrentTotalUsage -= AllocInfo->Size; + Context->CurrentTotalUsageByType[ProfileMemoryIndex] -= AllocInfo->Size; + + DriverInfo->CurrentUsage -= AllocInfo->Size; + DriverInfo->CurrentUsageByType[ProfileMemoryIndex] -= AllocInfo->Size; } - } - Context = &ContextData->Context; - DriverInfo = &DriverInfoData->DriverInfo; - AllocInfo = &AllocInfoData->AllocInfo; + RemoveEntryList (&AllocInfoData->Link); - ProfileMemoryIndex = GetProfileMemoryIndex (AllocInfo->MemoryType); - - Context->CurrentTotalUsage -= AllocInfo->Size; - Context->CurrentTotalUsageByType[ProfileMemoryIndex] -= AllocInfo->Size; - - DriverInfo->CurrentUsage -= AllocInfo->Size; - DriverInfo->CurrentUsageByType[ProfileMemoryIndex] -= AllocInfo->Size; - DriverInfo->AllocRecordCount --; - - RemoveEntryList (&AllocInfoData->Link); - - if (Action == MemoryProfileActionFreePages) { - if (AllocInfo->Buffer != (PHYSICAL_ADDRESS) (UINTN) Buffer) { - SmmCoreUpdateProfileAllocate ( - AllocInfo->CallerAddress, - MemoryProfileActionAllocatePages, - AllocInfo->MemoryType, - (UINTN) ((PHYSICAL_ADDRESS) (UINTN) Buffer - AllocInfo->Buffer), - (VOID *) (UINTN) AllocInfo->Buffer - ); + if (BasicAction == MemoryProfileActionFreePages) { + if (AllocInfo->Buffer != (PHYSICAL_ADDRESS) (UINTN) Buffer) { + SmmCoreUpdateProfileAllocate ( + AllocInfo->CallerAddress, + AllocInfo->Action, + AllocInfo->MemoryType, + (UINTN) ((PHYSICAL_ADDRESS) (UINTN) Buffer - AllocInfo->Buffer), + (VOID *) (UINTN) AllocInfo->Buffer, + AllocInfoData->ActionString + ); + } + if (AllocInfo->Buffer + AllocInfo->Size != ((PHYSICAL_ADDRESS) (UINTN) Buffer + Size)) { + SmmCoreUpdateProfileAllocate ( + AllocInfo->CallerAddress, + AllocInfo->Action, + AllocInfo->MemoryType, + (UINTN) ((AllocInfo->Buffer + AllocInfo->Size) - ((PHYSICAL_ADDRESS) (UINTN) Buffer + Size)), + (VOID *) ((UINTN) Buffer + Size), + AllocInfoData->ActionString + ); + } } - if (AllocInfo->Buffer + AllocInfo->Size != ((PHYSICAL_ADDRESS) (UINTN) Buffer + Size)) { - SmmCoreUpdateProfileAllocate ( - AllocInfo->CallerAddress, - MemoryProfileActionAllocatePages, - AllocInfo->MemoryType, - (UINTN) ((AllocInfo->Buffer + AllocInfo->Size) - ((PHYSICAL_ADDRESS) (UINTN) Buffer + Size)), - (VOID *) ((UINTN) Buffer + Size) - ); - } - } - // - // Use SmmInternalFreePool() that will not update profile for this FreePool action. - // - SmmInternalFreePool (AllocInfoData); - - return TRUE; + // + // Use SmmInternalFreePool() that will not update profile for this FreePool action. + // + SmmInternalFreePool (AllocInfoData); + } while (TRUE); } /** @@ -1098,68 +1461,91 @@ SmmCoreUpdateProfileFree ( @param CallerAddress Address of caller who call Allocate or Free. @param Action This Allocate or Free action. @param MemoryType Memory type. + EfiMaxMemoryType means the MemoryType is unknown. @param Size Buffer size. @param Buffer Buffer address. + @param ActionString String for memory profile action. + Only needed for user defined allocate action. - @retval TRUE Profile udpate success. - @retval FALSE Profile update fail. + @return EFI_SUCCESS Memory profile is updated. + @return EFI_UNSUPPORTED Memory profile is unsupported, + or memory profile for the image is not required, + or memory profile for the memory type is not required. + @return EFI_ACCESS_DENIED It is during memory profile data getting. + @return EFI_ABORTED Memory profile recording is not enabled. + @return EFI_OUT_OF_RESOURCES No enough resource to update memory profile for allocate action. + @return EFI_NOT_FOUND No matched allocate info found for free action. **/ -BOOLEAN +EFI_STATUS +EFIAPI SmmCoreUpdateProfile ( IN PHYSICAL_ADDRESS CallerAddress, IN MEMORY_PROFILE_ACTION Action, IN EFI_MEMORY_TYPE MemoryType, // Valid for AllocatePages/AllocatePool IN UINTN Size, // Valid for AllocatePages/FreePages/AllocatePool - IN VOID *Buffer + IN VOID *Buffer, + IN CHAR8 *ActionString OPTIONAL ) { + EFI_STATUS Status; MEMORY_PROFILE_CONTEXT_DATA *ContextData; + MEMORY_PROFILE_ACTION BasicAction; if (!IS_SMRAM_PROFILE_ENABLED) { - return FALSE; + return EFI_UNSUPPORTED; } - if (!mSmramProfileRecordingStatus) { - return FALSE; + if (mSmramProfileGettingStatus) { + return EFI_ACCESS_DENIED; } + if (!mSmramProfileRecordingEnable) { + return EFI_ABORTED; + } + + // + // Get the basic action to know how to process the record + // + BasicAction = Action & MEMORY_PROFILE_ACTION_BASIC_MASK; + // // Free operations have no memory type information, so skip the check. // - if ((Action == MemoryProfileActionAllocatePages) || (Action == MemoryProfileActionAllocatePool)) { + if ((BasicAction == MemoryProfileActionAllocatePages) || (BasicAction == MemoryProfileActionAllocatePool)) { // // Only record limited MemoryType. // if (!SmmCoreNeedRecordProfile (MemoryType)) { - return FALSE; + return EFI_UNSUPPORTED; } } ContextData = GetSmramProfileContext (); if (ContextData == NULL) { - return FALSE; + return EFI_UNSUPPORTED; } - switch (Action) { + switch (BasicAction) { case MemoryProfileActionAllocatePages: - SmmCoreUpdateProfileAllocate (CallerAddress, Action, MemoryType, Size, Buffer); + Status = SmmCoreUpdateProfileAllocate (CallerAddress, Action, MemoryType, Size, Buffer, ActionString); break; case MemoryProfileActionFreePages: - SmmCoreUpdateProfileFree (CallerAddress, Action, Size, Buffer); + Status = SmmCoreUpdateProfileFree (CallerAddress, Action, Size, Buffer); break; case MemoryProfileActionAllocatePool: - SmmCoreUpdateProfileAllocate (CallerAddress, Action, MemoryType, Size, Buffer); + Status = SmmCoreUpdateProfileAllocate (CallerAddress, Action, MemoryType, Size, Buffer, ActionString); break; case MemoryProfileActionFreePool: - SmmCoreUpdateProfileFree (CallerAddress, Action, 0, Buffer); + Status = SmmCoreUpdateProfileFree (CallerAddress, Action, 0, Buffer); break; default: ASSERT (FALSE); + Status = EFI_UNSUPPORTED; break; } - return TRUE; + return Status; } /** @@ -1192,17 +1578,20 @@ SmramProfileGetDataSize ( VOID ) { - MEMORY_PROFILE_CONTEXT_DATA *ContextData; - MEMORY_PROFILE_DRIVER_INFO_DATA *DriverInfoData; - LIST_ENTRY *DriverInfoList; - LIST_ENTRY *DriverLink; - UINTN TotalSize; - LIST_ENTRY *Node; - LIST_ENTRY *FreePageList; - LIST_ENTRY *FreePoolList; - FREE_POOL_HEADER *Pool; - UINTN PoolListIndex; - UINTN Index; + MEMORY_PROFILE_CONTEXT_DATA *ContextData; + MEMORY_PROFILE_DRIVER_INFO_DATA *DriverInfoData; + MEMORY_PROFILE_ALLOC_INFO_DATA *AllocInfoData; + LIST_ENTRY *DriverInfoList; + LIST_ENTRY *DriverLink; + LIST_ENTRY *AllocInfoList; + LIST_ENTRY *AllocLink; + UINTN TotalSize; + LIST_ENTRY *Node; + LIST_ENTRY *FreePageList; + LIST_ENTRY *FreePoolList; + FREE_POOL_HEADER *Pool; + UINTN PoolListIndex; + UINTN Index; ContextData = GetSmramProfileContext (); if (ContextData == NULL) { @@ -1210,7 +1599,6 @@ SmramProfileGetDataSize ( } TotalSize = sizeof (MEMORY_PROFILE_CONTEXT); - TotalSize += sizeof (MEMORY_PROFILE_DRIVER_INFO) * (UINTN) ContextData->Context.ImageCount; DriverInfoList = ContextData->DriverInfoList; for (DriverLink = DriverInfoList->ForwardLink; @@ -1222,7 +1610,20 @@ SmramProfileGetDataSize ( Link, MEMORY_PROFILE_DRIVER_INFO_SIGNATURE ); - TotalSize += sizeof (MEMORY_PROFILE_ALLOC_INFO) * (UINTN) DriverInfoData->DriverInfo.AllocRecordCount; + TotalSize += DriverInfoData->DriverInfo.Header.Length; + + AllocInfoList = DriverInfoData->AllocInfoList; + for (AllocLink = AllocInfoList->ForwardLink; + AllocLink != AllocInfoList; + AllocLink = AllocLink->ForwardLink) { + AllocInfoData = CR ( + AllocLink, + MEMORY_PROFILE_ALLOC_INFO_DATA, + Link, + MEMORY_PROFILE_ALLOC_INFO_SIGNATURE + ); + TotalSize += AllocInfoData->AllocInfo.Header.Length; + } } @@ -1291,6 +1692,8 @@ SmramProfileCopyData ( MEMORY_PROFILE_DESCRIPTOR *MemoryProfileDescriptor; UINT64 Offset; UINT64 RemainingSize; + UINTN PdbSize; + UINTN ActionStringSize; ContextData = GetSmramProfileContext (); if (ContextData == NULL) { @@ -1322,17 +1725,21 @@ SmramProfileCopyData ( Link, MEMORY_PROFILE_DRIVER_INFO_SIGNATURE ); - if (*ProfileOffset < (Offset + sizeof (MEMORY_PROFILE_DRIVER_INFO))) { - if (RemainingSize >= sizeof (MEMORY_PROFILE_DRIVER_INFO)) { + if (*ProfileOffset < (Offset + DriverInfoData->DriverInfo.Header.Length)) { + if (RemainingSize >= DriverInfoData->DriverInfo.Header.Length) { DriverInfo = ProfileBuffer; CopyMem (DriverInfo, &DriverInfoData->DriverInfo, sizeof (MEMORY_PROFILE_DRIVER_INFO)); - RemainingSize -= sizeof (MEMORY_PROFILE_DRIVER_INFO); - ProfileBuffer = (UINT8 *) ProfileBuffer + sizeof (MEMORY_PROFILE_DRIVER_INFO); + if (DriverInfo->PdbStringOffset != 0) { + PdbSize = AsciiStrSize (DriverInfoData->PdbString); + CopyMem ((VOID *) ((UINTN) DriverInfo + DriverInfo->PdbStringOffset), DriverInfoData->PdbString, PdbSize); + } + RemainingSize -= DriverInfo->Header.Length; + ProfileBuffer = (UINT8 *) ProfileBuffer + DriverInfo->Header.Length; } else { goto Done; } } - Offset += sizeof (MEMORY_PROFILE_DRIVER_INFO); + Offset += DriverInfoData->DriverInfo.Header.Length; AllocInfoList = DriverInfoData->AllocInfoList; for (AllocLink = AllocInfoList->ForwardLink; @@ -1344,17 +1751,21 @@ SmramProfileCopyData ( Link, MEMORY_PROFILE_ALLOC_INFO_SIGNATURE ); - if (*ProfileOffset < (Offset + sizeof (MEMORY_PROFILE_ALLOC_INFO))) { - if (RemainingSize >= sizeof (MEMORY_PROFILE_ALLOC_INFO)) { + if (*ProfileOffset < (Offset + AllocInfoData->AllocInfo.Header.Length)) { + if (RemainingSize >= AllocInfoData->AllocInfo.Header.Length) { AllocInfo = ProfileBuffer; CopyMem (AllocInfo, &AllocInfoData->AllocInfo, sizeof (MEMORY_PROFILE_ALLOC_INFO)); - RemainingSize -= sizeof (MEMORY_PROFILE_ALLOC_INFO); - ProfileBuffer = (UINT8 *) ProfileBuffer + sizeof (MEMORY_PROFILE_ALLOC_INFO); + if (AllocInfo->ActionStringOffset) { + ActionStringSize = AsciiStrSize (AllocInfoData->ActionString); + CopyMem ((VOID *) ((UINTN) AllocInfo + AllocInfo->ActionStringOffset), AllocInfoData->ActionString, ActionStringSize); + } + RemainingSize -= AllocInfo->Header.Length; + ProfileBuffer = (UINT8 *) ProfileBuffer + AllocInfo->Header.Length; } else { goto Done; } } - Offset += sizeof (MEMORY_PROFILE_ALLOC_INFO); + Offset += AllocInfoData->AllocInfo.Header.Length; } } @@ -1484,6 +1895,241 @@ Done: *ProfileOffset = Offset; } +/** + Get memory profile data. + + @param[in] This The EDKII_SMM_MEMORY_PROFILE_PROTOCOL instance. + @param[in, out] ProfileSize On entry, points to the size in bytes of the ProfileBuffer. + On return, points to the size of the data returned in ProfileBuffer. + @param[out] ProfileBuffer Profile buffer. + + @return EFI_SUCCESS Get the memory profile data successfully. + @return EFI_UNSUPPORTED Memory profile is unsupported. + @return EFI_BUFFER_TO_SMALL The ProfileSize is too small for the resulting data. + ProfileSize is updated with the size required. + +**/ +EFI_STATUS +EFIAPI +SmramProfileProtocolGetData ( + IN EDKII_SMM_MEMORY_PROFILE_PROTOCOL *This, + IN OUT UINT64 *ProfileSize, + OUT VOID *ProfileBuffer + ) +{ + UINT64 Size; + UINT64 Offset; + MEMORY_PROFILE_CONTEXT_DATA *ContextData; + BOOLEAN SmramProfileGettingStatus; + + ContextData = GetSmramProfileContext (); + if (ContextData == NULL) { + return EFI_UNSUPPORTED; + } + + SmramProfileGettingStatus = mSmramProfileGettingStatus; + mSmramProfileGettingStatus = TRUE; + + Size = SmramProfileGetDataSize (); + + if (*ProfileSize < Size) { + *ProfileSize = Size; + mSmramProfileGettingStatus = SmramProfileGettingStatus; + return EFI_BUFFER_TOO_SMALL; + } + + Offset = 0; + SmramProfileCopyData (ProfileBuffer, &Size, &Offset); + *ProfileSize = Size; + + mSmramProfileGettingStatus = SmramProfileGettingStatus; + return EFI_SUCCESS; +} + +/** + Register image to memory profile. + + @param[in] This The EDKII_SMM_MEMORY_PROFILE_PROTOCOL instance. + @param[in] FilePath File path of the image. + @param[in] ImageBase Image base address. + @param[in] ImageSize Image size. + @param[in] FileType File type of the image. + + @return EFI_SUCCESS Register successfully. + @return EFI_UNSUPPORTED Memory profile is unsupported, + or memory profile for the image is not required. + @return EFI_OUT_OF_RESOURCES No enough resource for this register. + +**/ +EFI_STATUS +EFIAPI +SmramProfileProtocolRegisterImage ( + IN EDKII_SMM_MEMORY_PROFILE_PROTOCOL *This, + IN EFI_DEVICE_PATH_PROTOCOL *FilePath, + IN PHYSICAL_ADDRESS ImageBase, + IN UINT64 ImageSize, + IN EFI_FV_FILETYPE FileType + ) +{ + EFI_STATUS Status; + EFI_SMM_DRIVER_ENTRY DriverEntry; + VOID *EntryPointInImage; + EFI_GUID *Name; + + ZeroMem (&DriverEntry, sizeof (DriverEntry)); + Name = GetFileNameFromFilePath (FilePath); + if (Name != NULL) { + CopyMem (&DriverEntry.FileName, Name, sizeof (EFI_GUID)); + } + DriverEntry.ImageBuffer = ImageBase; + DriverEntry.NumberOfPage = EFI_SIZE_TO_PAGES ((UINTN) ImageSize); + Status = InternalPeCoffGetEntryPoint ((VOID *) (UINTN) DriverEntry.ImageBuffer, &EntryPointInImage); + ASSERT_EFI_ERROR (Status); + DriverEntry.ImageEntryPoint = (PHYSICAL_ADDRESS) (UINTN) EntryPointInImage; + + return RegisterSmramProfileImage (&DriverEntry, FALSE); +} + +/** + Unregister image from memory profile. + + @param[in] This The EDKII_SMM_MEMORY_PROFILE_PROTOCOL instance. + @param[in] FilePath File path of the image. + @param[in] ImageBase Image base address. + @param[in] ImageSize Image size. + + @return EFI_SUCCESS Unregister successfully. + @return EFI_UNSUPPORTED Memory profile is unsupported, + or memory profile for the image is not required. + @return EFI_NOT_FOUND The image is not found. + +**/ +EFI_STATUS +EFIAPI +SmramProfileProtocolUnregisterImage ( + IN EDKII_SMM_MEMORY_PROFILE_PROTOCOL *This, + IN EFI_DEVICE_PATH_PROTOCOL *FilePath, + IN PHYSICAL_ADDRESS ImageBase, + IN UINT64 ImageSize + ) +{ + EFI_STATUS Status; + EFI_SMM_DRIVER_ENTRY DriverEntry; + VOID *EntryPointInImage; + EFI_GUID *Name; + + ZeroMem (&DriverEntry, sizeof (DriverEntry)); + Name = GetFileNameFromFilePath (FilePath); + if (Name != NULL) { + CopyMem (&DriverEntry.FileName, Name, sizeof (EFI_GUID)); + } + DriverEntry.ImageBuffer = ImageBase; + DriverEntry.NumberOfPage = EFI_SIZE_TO_PAGES ((UINTN) ImageSize); + Status = InternalPeCoffGetEntryPoint ((VOID *) (UINTN) DriverEntry.ImageBuffer, &EntryPointInImage); + ASSERT_EFI_ERROR (Status); + DriverEntry.ImageEntryPoint = (PHYSICAL_ADDRESS) (UINTN) EntryPointInImage; + + return UnregisterSmramProfileImage (&DriverEntry, FALSE); +} + +/** + Get memory profile recording state. + + @param[in] This The EDKII_SMM_MEMORY_PROFILE_PROTOCOL instance. + @param[out] RecordingState Recording state. + + @return EFI_SUCCESS Memory profile recording state is returned. + @return EFI_UNSUPPORTED Memory profile is unsupported. + @return EFI_INVALID_PARAMETER RecordingState is NULL. + +**/ +EFI_STATUS +EFIAPI +SmramProfileProtocolGetRecordingState ( + IN EDKII_SMM_MEMORY_PROFILE_PROTOCOL *This, + OUT BOOLEAN *RecordingState + ) +{ + MEMORY_PROFILE_CONTEXT_DATA *ContextData; + + ContextData = GetSmramProfileContext (); + if (ContextData == NULL) { + return EFI_UNSUPPORTED; + } + + if (RecordingState == NULL) { + return EFI_INVALID_PARAMETER; + } + *RecordingState = mSmramProfileRecordingEnable; + return EFI_SUCCESS; +} + +/** + Set memory profile recording state. + + @param[in] This The EDKII_SMM_MEMORY_PROFILE_PROTOCOL instance. + @param[in] RecordingState Recording state. + + @return EFI_SUCCESS Set memory profile recording state successfully. + @return EFI_UNSUPPORTED Memory profile is unsupported. + +**/ +EFI_STATUS +EFIAPI +SmramProfileProtocolSetRecordingState ( + IN EDKII_SMM_MEMORY_PROFILE_PROTOCOL *This, + IN BOOLEAN RecordingState + ) +{ + MEMORY_PROFILE_CONTEXT_DATA *ContextData; + + ContextData = GetSmramProfileContext (); + if (ContextData == NULL) { + return EFI_UNSUPPORTED; + } + + mSmramProfileRecordingEnable = RecordingState; + return EFI_SUCCESS; +} + +/** + Record memory profile of multilevel caller. + + @param[in] This The EDKII_SMM_MEMORY_PROFILE_PROTOCOL instance. + @param[in] CallerAddress Address of caller. + @param[in] Action Memory profile action. + @param[in] MemoryType Memory type. + EfiMaxMemoryType means the MemoryType is unknown. + @param[in] Buffer Buffer address. + @param[in] Size Buffer size. + @param[in] ActionString String for memory profile action. + Only needed for user defined allocate action. + + @return EFI_SUCCESS Memory profile is updated. + @return EFI_UNSUPPORTED Memory profile is unsupported, + or memory profile for the image is not required, + or memory profile for the memory type is not required. + @return EFI_ACCESS_DENIED It is during memory profile data getting. + @return EFI_ABORTED Memory profile recording is not enabled. + @return EFI_OUT_OF_RESOURCES No enough resource to update memory profile for allocate action. + @return EFI_NOT_FOUND No matched allocate info found for free action. + +**/ +EFI_STATUS +EFIAPI +SmramProfileProtocolRecord ( + IN EDKII_SMM_MEMORY_PROFILE_PROTOCOL *This, + IN PHYSICAL_ADDRESS CallerAddress, + IN MEMORY_PROFILE_ACTION Action, + IN EFI_MEMORY_TYPE MemoryType, + IN VOID *Buffer, + IN UINTN Size, + IN CHAR8 *ActionString OPTIONAL + ) +{ + return SmmCoreUpdateProfile (CallerAddress, Action, MemoryType, Size, Buffer, ActionString); +} + /** SMRAM profile handler to get profile info. @@ -1496,20 +2142,20 @@ SmramProfileHandlerGetInfo ( ) { MEMORY_PROFILE_CONTEXT_DATA *ContextData; - BOOLEAN SmramProfileRecordingStatus; + BOOLEAN SmramProfileGettingStatus; ContextData = GetSmramProfileContext (); if (ContextData == NULL) { return ; } - SmramProfileRecordingStatus = mSmramProfileRecordingStatus; - mSmramProfileRecordingStatus = FALSE; + SmramProfileGettingStatus = mSmramProfileGettingStatus; + mSmramProfileGettingStatus = TRUE; SmramProfileParameterGetInfo->ProfileSize = SmramProfileGetDataSize(); SmramProfileParameterGetInfo->Header.ReturnStatus = 0; - mSmramProfileRecordingStatus = SmramProfileRecordingStatus; + mSmramProfileGettingStatus = SmramProfileGettingStatus; } /** @@ -1527,15 +2173,15 @@ SmramProfileHandlerGetData ( UINT64 ProfileOffset; SMRAM_PROFILE_PARAMETER_GET_PROFILE_DATA SmramProfileGetData; MEMORY_PROFILE_CONTEXT_DATA *ContextData; - BOOLEAN SmramProfileRecordingStatus; + BOOLEAN SmramProfileGettingStatus; ContextData = GetSmramProfileContext (); if (ContextData == NULL) { return ; } - SmramProfileRecordingStatus = mSmramProfileRecordingStatus; - mSmramProfileRecordingStatus = FALSE; + SmramProfileGettingStatus = mSmramProfileGettingStatus; + mSmramProfileGettingStatus = TRUE; CopyMem (&SmramProfileGetData, SmramProfileParameterGetData, sizeof (SmramProfileGetData)); @@ -1564,7 +2210,7 @@ SmramProfileHandlerGetData ( SmramProfileParameterGetData->Header.ReturnStatus = 0; Done: - mSmramProfileRecordingStatus = SmramProfileRecordingStatus; + mSmramProfileGettingStatus = SmramProfileGettingStatus; } /** @@ -1580,15 +2226,15 @@ SmramProfileHandlerGetDataByOffset ( { SMRAM_PROFILE_PARAMETER_GET_PROFILE_DATA_BY_OFFSET SmramProfileGetDataByOffset; MEMORY_PROFILE_CONTEXT_DATA *ContextData; - BOOLEAN SmramProfileRecordingStatus; + BOOLEAN SmramProfileGettingStatus; ContextData = GetSmramProfileContext (); if (ContextData == NULL) { return ; } - SmramProfileRecordingStatus = mSmramProfileRecordingStatus; - mSmramProfileRecordingStatus = FALSE; + SmramProfileGettingStatus = mSmramProfileGettingStatus; + mSmramProfileGettingStatus = TRUE; CopyMem (&SmramProfileGetDataByOffset, SmramProfileParameterGetDataByOffset, sizeof (SmramProfileGetDataByOffset)); @@ -1607,7 +2253,7 @@ SmramProfileHandlerGetDataByOffset ( SmramProfileParameterGetDataByOffset->Header.ReturnStatus = 0; Done: - mSmramProfileRecordingStatus = SmramProfileRecordingStatus; + mSmramProfileGettingStatus = SmramProfileGettingStatus; } /** @@ -1624,7 +2270,6 @@ SmramProfileHandlerRegisterImage ( EFI_STATUS Status; EFI_SMM_DRIVER_ENTRY DriverEntry; VOID *EntryPointInImage; - BOOLEAN Ret; ZeroMem (&DriverEntry, sizeof (DriverEntry)); CopyMem (&DriverEntry.FileName, &SmramProfileParameterRegisterImage->FileName, sizeof(EFI_GUID)); @@ -1634,8 +2279,8 @@ SmramProfileHandlerRegisterImage ( ASSERT_EFI_ERROR (Status); DriverEntry.ImageEntryPoint = (PHYSICAL_ADDRESS) (UINTN) EntryPointInImage; - Ret = RegisterSmramProfileImage (&DriverEntry, FALSE); - if (Ret) { + Status = RegisterSmramProfileImage (&DriverEntry, FALSE); + if (!EFI_ERROR (Status)) { SmramProfileParameterRegisterImage->Header.ReturnStatus = 0; } } @@ -1654,7 +2299,6 @@ SmramProfileHandlerUnregisterImage ( EFI_STATUS Status; EFI_SMM_DRIVER_ENTRY DriverEntry; VOID *EntryPointInImage; - BOOLEAN Ret; ZeroMem (&DriverEntry, sizeof (DriverEntry)); CopyMem (&DriverEntry.FileName, &SmramProfileParameterUnregisterImage->FileName, sizeof (EFI_GUID)); @@ -1664,8 +2308,8 @@ SmramProfileHandlerUnregisterImage ( ASSERT_EFI_ERROR (Status); DriverEntry.ImageEntryPoint = (PHYSICAL_ADDRESS) (UINTN) EntryPointInImage; - Ret = UnregisterSmramProfileImage (&DriverEntry, FALSE); - if (Ret) { + Status = UnregisterSmramProfileImage (&DriverEntry, FALSE); + if (!EFI_ERROR (Status)) { SmramProfileParameterUnregisterImage->Header.ReturnStatus = 0; } } @@ -1697,6 +2341,7 @@ SmramProfileHandler ( { SMRAM_PROFILE_PARAMETER_HEADER *SmramProfileParameterHeader; UINTN TempCommBufferSize; + SMRAM_PROFILE_PARAMETER_RECORDING_STATE *ParameterRecordingState; DEBUG ((EFI_D_ERROR, "SmramProfileHandler Enter\n")); @@ -1775,6 +2420,27 @@ SmramProfileHandler ( } SmramProfileHandlerUnregisterImage ((SMRAM_PROFILE_PARAMETER_UNREGISTER_IMAGE *) (UINTN) CommBuffer); break; + case SMRAM_PROFILE_COMMAND_GET_RECORDING_STATE: + DEBUG ((EFI_D_ERROR, "SmramProfileHandlerGetRecordingState\n")); + if (TempCommBufferSize != sizeof (SMRAM_PROFILE_PARAMETER_RECORDING_STATE)) { + DEBUG ((EFI_D_ERROR, "SmramProfileHandler: SMM communication buffer size invalid!\n")); + return EFI_SUCCESS; + } + ParameterRecordingState = (SMRAM_PROFILE_PARAMETER_RECORDING_STATE *) (UINTN) CommBuffer; + ParameterRecordingState->RecordingState = mSmramProfileRecordingEnable; + ParameterRecordingState->Header.ReturnStatus = 0; + break; + case SMRAM_PROFILE_COMMAND_SET_RECORDING_STATE: + DEBUG ((EFI_D_ERROR, "SmramProfileHandlerSetRecordingState\n")); + if (TempCommBufferSize != sizeof (SMRAM_PROFILE_PARAMETER_RECORDING_STATE)) { + DEBUG ((EFI_D_ERROR, "SmramProfileHandler: SMM communication buffer size invalid!\n")); + return EFI_SUCCESS; + } + ParameterRecordingState = (SMRAM_PROFILE_PARAMETER_RECORDING_STATE *) (UINTN) CommBuffer; + mSmramProfileRecordingEnable = ParameterRecordingState->RecordingState; + ParameterRecordingState->Header.ReturnStatus = 0; + break; + default: break; } @@ -1821,15 +2487,15 @@ DumpSmramRange ( { UINTN Index; MEMORY_PROFILE_CONTEXT_DATA *ContextData; - BOOLEAN SmramProfileRecordingStatus; + BOOLEAN SmramProfileGettingStatus; ContextData = GetSmramProfileContext (); if (ContextData == NULL) { return ; } - SmramProfileRecordingStatus = mSmramProfileRecordingStatus; - mSmramProfileRecordingStatus = FALSE; + SmramProfileGettingStatus = mSmramProfileGettingStatus; + mSmramProfileGettingStatus = TRUE; DEBUG ((EFI_D_INFO, "FullSmramRange address - 0x%08x\n", mFullSmramRanges)); @@ -1846,7 +2512,7 @@ DumpSmramRange ( DEBUG ((EFI_D_INFO, "======= SmramProfile end =======\n")); - mSmramProfileRecordingStatus = SmramProfileRecordingStatus; + mSmramProfileGettingStatus = SmramProfileGettingStatus; } /** @@ -1863,15 +2529,15 @@ DumpFreePagesList ( FREE_PAGE_LIST *Pages; UINTN Index; MEMORY_PROFILE_CONTEXT_DATA *ContextData; - BOOLEAN SmramProfileRecordingStatus; + BOOLEAN SmramProfileGettingStatus; ContextData = GetSmramProfileContext (); if (ContextData == NULL) { return ; } - SmramProfileRecordingStatus = mSmramProfileRecordingStatus; - mSmramProfileRecordingStatus = FALSE; + SmramProfileGettingStatus = mSmramProfileGettingStatus; + mSmramProfileGettingStatus = TRUE; DEBUG ((EFI_D_INFO, "======= SmramProfile begin =======\n")); @@ -1888,7 +2554,7 @@ DumpFreePagesList ( DEBUG ((EFI_D_INFO, "======= SmramProfile end =======\n")); - mSmramProfileRecordingStatus = SmramProfileRecordingStatus; + mSmramProfileGettingStatus = SmramProfileGettingStatus; } /** @@ -1900,21 +2566,21 @@ DumpFreePoolList ( VOID ) { - LIST_ENTRY *FreePoolList; - LIST_ENTRY *Node; - FREE_POOL_HEADER *Pool; - UINTN Index; - UINTN PoolListIndex; + LIST_ENTRY *FreePoolList; + LIST_ENTRY *Node; + FREE_POOL_HEADER *Pool; + UINTN Index; + UINTN PoolListIndex; MEMORY_PROFILE_CONTEXT_DATA *ContextData; - BOOLEAN SmramProfileRecordingStatus; + BOOLEAN SmramProfileGettingStatus; ContextData = GetSmramProfileContext (); if (ContextData == NULL) { return ; } - SmramProfileRecordingStatus = mSmramProfileRecordingStatus; - mSmramProfileRecordingStatus = FALSE; + SmramProfileGettingStatus = mSmramProfileGettingStatus; + mSmramProfileGettingStatus = TRUE; DEBUG ((EFI_D_INFO, "======= SmramProfile begin =======\n")); @@ -1934,25 +2600,56 @@ DumpFreePoolList ( DEBUG ((EFI_D_INFO, "======= SmramProfile end =======\n")); - mSmramProfileRecordingStatus = SmramProfileRecordingStatus; + mSmramProfileGettingStatus = SmramProfileGettingStatus; } -GLOBAL_REMOVE_IF_UNREFERENCED CHAR16 *mActionString[] = { - L"Unknown", - L"AllocatePages", - L"FreePages", - L"AllocatePool", - L"FreePool", +GLOBAL_REMOVE_IF_UNREFERENCED CHAR8 *mSmmActionString[] = { + "SmmUnknown", + "gSmst->SmmAllocatePages", + "gSmst->SmmFreePages", + "gSmst->SmmAllocatePool", + "gSmst->SmmFreePool", }; +typedef struct { + MEMORY_PROFILE_ACTION Action; + CHAR8 *String; +} ACTION_STRING; + +ACTION_STRING mExtActionString[] = { + {MEMORY_PROFILE_ACTION_LIB_ALLOCATE_PAGES, "Lib:AllocatePages"}, + {MEMORY_PROFILE_ACTION_LIB_ALLOCATE_RUNTIME_PAGES, "Lib:AllocateRuntimePages"}, + {MEMORY_PROFILE_ACTION_LIB_ALLOCATE_RESERVED_PAGES, "Lib:AllocateReservedPages"}, + {MEMORY_PROFILE_ACTION_LIB_FREE_PAGES, "Lib:FreePages"}, + {MEMORY_PROFILE_ACTION_LIB_ALLOCATE_ALIGNED_PAGES, "Lib:AllocateAlignedPages"}, + {MEMORY_PROFILE_ACTION_LIB_ALLOCATE_ALIGNED_RUNTIME_PAGES, "Lib:AllocateAlignedRuntimePages"}, + {MEMORY_PROFILE_ACTION_LIB_ALLOCATE_ALIGNED_RESERVED_PAGES, "Lib:AllocateAlignedReservedPages"}, + {MEMORY_PROFILE_ACTION_LIB_FREE_ALIGNED_PAGES, "Lib:FreeAlignedPages"}, + {MEMORY_PROFILE_ACTION_LIB_ALLOCATE_POOL, "Lib:AllocatePool"}, + {MEMORY_PROFILE_ACTION_LIB_ALLOCATE_RUNTIME_POOL, "Lib:AllocateRuntimePool"}, + {MEMORY_PROFILE_ACTION_LIB_ALLOCATE_RESERVED_POOL, "Lib:AllocateReservedPool"}, + {MEMORY_PROFILE_ACTION_LIB_FREE_POOL, "Lib:FreePool"}, + {MEMORY_PROFILE_ACTION_LIB_ALLOCATE_ZERO_POOL, "Lib:AllocateZeroPool"}, + {MEMORY_PROFILE_ACTION_LIB_ALLOCATE_RUNTIME_ZERO_POOL, "Lib:AllocateRuntimeZeroPool"}, + {MEMORY_PROFILE_ACTION_LIB_ALLOCATE_RESERVED_ZERO_POOL, "Lib:AllocateReservedZeroPool"}, + {MEMORY_PROFILE_ACTION_LIB_ALLOCATE_COPY_POOL, "Lib:AllocateCopyPool"}, + {MEMORY_PROFILE_ACTION_LIB_ALLOCATE_RUNTIME_COPY_POOL, "Lib:AllocateRuntimeCopyPool"}, + {MEMORY_PROFILE_ACTION_LIB_ALLOCATE_RESERVED_COPY_POOL, "Lib:AllocateReservedCopyPool"}, + {MEMORY_PROFILE_ACTION_LIB_REALLOCATE_POOL, "Lib:ReallocatePool"}, + {MEMORY_PROFILE_ACTION_LIB_REALLOCATE_RUNTIME_POOL, "Lib:ReallocateRuntimePool"}, + {MEMORY_PROFILE_ACTION_LIB_REALLOCATE_RESERVED_POOL, "Lib:ReallocateReservedPool"}, +}; + +GLOBAL_REMOVE_IF_UNREFERENCED CHAR8 mUserDefinedActionString[] = {"UserDefined-0x80000000"}; + typedef struct { EFI_MEMORY_TYPE MemoryType; - CHAR16 *MemoryTypeStr; + CHAR8 *MemoryTypeStr; } PROFILE_MEMORY_TYPE_STRING; GLOBAL_REMOVE_IF_UNREFERENCED PROFILE_MEMORY_TYPE_STRING mMemoryTypeString[] = { - {EfiRuntimeServicesCode, L"EfiRuntimeServicesCode"}, - {EfiRuntimeServicesData, L"EfiRuntimeServicesData"} + {EfiRuntimeServicesCode, "EfiRuntimeServicesCode"}, + {EfiRuntimeServicesData, "EfiRuntimeServicesData"} }; /** @@ -1963,7 +2660,7 @@ GLOBAL_REMOVE_IF_UNREFERENCED PROFILE_MEMORY_TYPE_STRING mMemoryTypeString[] = { @return Pointer to string. **/ -CHAR16 * +CHAR8 * ProfileMemoryTypeToStr ( IN EFI_MEMORY_TYPE MemoryType ) @@ -1975,7 +2672,39 @@ ProfileMemoryTypeToStr ( } } - return L"UnexpectedMemoryType"; + return "UnexpectedMemoryType"; +} + +/** + Action to string. + + @param[in] Action Profile action. + + @return Pointer to string. + +**/ +CHAR8 * +ProfileActionToStr ( + IN MEMORY_PROFILE_ACTION Action + ) +{ + UINTN Index; + UINTN ActionStringCount; + CHAR8 **ActionString; + + ActionString = mSmmActionString; + ActionStringCount = sizeof (mSmmActionString) / sizeof (mSmmActionString[0]); + + if ((UINTN) (UINT32) Action < ActionStringCount) { + return ActionString[Action]; + } + for (Index = 0; Index < sizeof (mExtActionString) / sizeof (mExtActionString[0]); Index++) { + if (mExtActionString[Index].Action == Action) { + return mExtActionString[Index].String; + } + } + + return ActionString[0]; } /** @@ -1999,7 +2728,7 @@ DumpSmramProfile ( LIST_ENTRY *AllocInfoList; UINTN AllocIndex; LIST_ENTRY *AllocLink; - BOOLEAN SmramProfileRecordingStatus; + BOOLEAN SmramProfileGettingStatus; UINTN TypeIndex; ContextData = GetSmramProfileContext (); @@ -2007,8 +2736,8 @@ DumpSmramProfile ( return ; } - SmramProfileRecordingStatus = mSmramProfileRecordingStatus; - mSmramProfileRecordingStatus = FALSE; + SmramProfileGettingStatus = mSmramProfileGettingStatus; + mSmramProfileGettingStatus = TRUE; Context = &ContextData->Context; DEBUG ((EFI_D_INFO, "======= SmramProfile begin =======\n")); @@ -2019,8 +2748,8 @@ DumpSmramProfile ( for (TypeIndex = 0; TypeIndex < sizeof (Context->CurrentTotalUsageByType) / sizeof (Context->CurrentTotalUsageByType[0]); TypeIndex++) { if ((Context->CurrentTotalUsageByType[TypeIndex] != 0) || (Context->PeakTotalUsageByType[TypeIndex] != 0)) { - DEBUG ((EFI_D_INFO, " CurrentTotalUsage[0x%02x] - 0x%016lx (%s)\n", TypeIndex, Context->CurrentTotalUsageByType[TypeIndex], ProfileMemoryTypeToStr (TypeIndex))); - DEBUG ((EFI_D_INFO, " PeakTotalUsage[0x%02x] - 0x%016lx (%s)\n", TypeIndex, Context->PeakTotalUsageByType[TypeIndex], ProfileMemoryTypeToStr (TypeIndex))); + DEBUG ((EFI_D_INFO, " CurrentTotalUsage[0x%02x] - 0x%016lx (%a)\n", TypeIndex, Context->CurrentTotalUsageByType[TypeIndex], ProfileMemoryTypeToStr (TypeIndex))); + DEBUG ((EFI_D_INFO, " PeakTotalUsage[0x%02x] - 0x%016lx (%a)\n", TypeIndex, Context->PeakTotalUsageByType[TypeIndex], ProfileMemoryTypeToStr (TypeIndex))); } } DEBUG ((EFI_D_INFO, " TotalImageSize - 0x%016lx\n", Context->TotalImageSize)); @@ -2050,8 +2779,8 @@ DumpSmramProfile ( for (TypeIndex = 0; TypeIndex < sizeof (DriverInfo->CurrentUsageByType) / sizeof (DriverInfo->CurrentUsageByType[0]); TypeIndex++) { if ((DriverInfo->CurrentUsageByType[TypeIndex] != 0) || (DriverInfo->PeakUsageByType[TypeIndex] != 0)) { - DEBUG ((EFI_D_INFO, " CurrentUsage[0x%02x] - 0x%016lx (%s)\n", TypeIndex, DriverInfo->CurrentUsageByType[TypeIndex], ProfileMemoryTypeToStr (TypeIndex))); - DEBUG ((EFI_D_INFO, " PeakUsage[0x%02x] - 0x%016lx (%s)\n", TypeIndex, DriverInfo->PeakUsageByType[TypeIndex], ProfileMemoryTypeToStr (TypeIndex))); + DEBUG ((EFI_D_INFO, " CurrentUsage[0x%02x] - 0x%016lx (%a)\n", TypeIndex, DriverInfo->CurrentUsageByType[TypeIndex], ProfileMemoryTypeToStr (TypeIndex))); + DEBUG ((EFI_D_INFO, " PeakUsage[0x%02x] - 0x%016lx (%a)\n", TypeIndex, DriverInfo->PeakUsageByType[TypeIndex], ProfileMemoryTypeToStr (TypeIndex))); } } DEBUG ((EFI_D_INFO, " AllocRecordCount - 0x%08x\n", DriverInfo->AllocRecordCount)); @@ -2070,8 +2799,16 @@ DumpSmramProfile ( DEBUG ((EFI_D_INFO, " MEMORY_PROFILE_ALLOC_INFO (0x%x)\n", AllocIndex)); DEBUG ((EFI_D_INFO, " CallerAddress - 0x%016lx (Offset: 0x%08x)\n", AllocInfo->CallerAddress, AllocInfo->CallerAddress - DriverInfo->ImageBase)); DEBUG ((EFI_D_INFO, " SequenceId - 0x%08x\n", AllocInfo->SequenceId)); - DEBUG ((EFI_D_INFO, " Action - 0x%08x (%s)\n", AllocInfo->Action, mActionString[(AllocInfo->Action < sizeof(mActionString)/sizeof(mActionString[0])) ? AllocInfo->Action : 0])); - DEBUG ((EFI_D_INFO, " MemoryType - 0x%08x\n", AllocInfo->MemoryType)); + if ((AllocInfo->Action & MEMORY_PROFILE_ACTION_USER_DEFINED_MASK) != 0) { + if (AllocInfoData->ActionString != NULL) { + DEBUG ((EFI_D_INFO, " Action - 0x%08x (%a)\n", AllocInfo->Action, AllocInfoData->ActionString)); + } else { + DEBUG ((EFI_D_INFO, " Action - 0x%08x (UserDefined-0x%08x)\n", AllocInfo->Action, AllocInfo->Action)); + } + } else { + DEBUG ((EFI_D_INFO, " Action - 0x%08x (%a)\n", AllocInfo->Action, ProfileActionToStr (AllocInfo->Action))); + } + DEBUG ((EFI_D_INFO, " MemoryType - 0x%08x (%a)\n", AllocInfo->MemoryType, ProfileMemoryTypeToStr (AllocInfo->MemoryType))); DEBUG ((EFI_D_INFO, " Buffer - 0x%016lx\n", AllocInfo->Buffer)); DEBUG ((EFI_D_INFO, " Size - 0x%016lx\n", AllocInfo->Size)); } @@ -2079,7 +2816,7 @@ DumpSmramProfile ( DEBUG ((EFI_D_INFO, "======= SmramProfile end =======\n")); - mSmramProfileRecordingStatus = SmramProfileRecordingStatus; + mSmramProfileGettingStatus = SmramProfileGettingStatus; } /**