MdeModulePkg DxeCore/PiSmmCore: Add UEFI memory and SMRAM profile support.

Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Star Zeng <star.zeng@intel.com>
Reviewed-by: Jiewen Yao <jiewen.yao@intel.com>

git-svn-id: https://svn.code.sf.net/p/edk2/code/trunk/edk2@16335 6f19259b-4bc3-4df7-8a09-765794883524
This commit is contained in:
Star Zeng 2014-11-12 03:27:48 +00:00 committed by lzeng14
parent dad83a8c12
commit 84edd20bd0
28 changed files with 5235 additions and 106 deletions

View File

@ -0,0 +1,712 @@
/** @file
Copyright (c) 2014, Intel Corporation. All rights reserved.<BR>
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
http://opensource.org/licenses/bsd-license.php
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
**/
#include <Uefi.h>
#include <PiDxe.h>
#include <Library/BaseLib.h>
#include <Library/BaseMemoryLib.h>
#include <Library/MemoryAllocationLib.h>
#include <Library/UefiLib.h>
#include <Library/UefiApplicationEntryPoint.h>
#include <Library/UefiBootServicesTableLib.h>
#include <Library/UefiRuntimeServicesTableLib.h>
#include <Library/DebugLib.h>
#include <Library/DxeServicesLib.h>
#include <Library/PeCoffGetEntryPointLib.h>
#include <Library/PrintLib.h>
#include <Protocol/SmmCommunication.h>
#include <Protocol/SmmAccess2.h>
#include <Guid/ZeroGuid.h>
#include <Guid/MemoryProfile.h>
CHAR16 *mActionString[] = {
L"Unknown",
L"AllocatePages",
L"FreePages",
L"AllocatePool",
L"FreePool",
};
CHAR16 *mMemoryTypeString[] = {
L"EfiReservedMemoryType",
L"EfiLoaderCode",
L"EfiLoaderData",
L"EfiBootServicesCode",
L"EfiBootServicesData",
L"EfiRuntimeServicesCode",
L"EfiRuntimeServicesData",
L"EfiConventionalMemory",
L"EfiUnusableMemory",
L"EfiACPIReclaimMemory",
L"EfiACPIMemoryNVS",
L"EfiMemoryMappedIO",
L"EfiMemoryMappedIOPortSpace",
L"EfiPalCode",
L"EfiOSReserved",
};
CHAR16 *mSubsystemString[] = {
L"Unknown",
L"NATIVE",
L"WINDOWS_GUI",
L"WINDOWS_CUI",
L"Unknown",
L"Unknown",
L"Unknown",
L"POSIX_CUI",
L"Unknown",
L"WINDOWS_CE_GUI",
L"EFI_APPLICATION",
L"EFI_BOOT_SERVICE_DRIVER",
L"EFI_RUNTIME_DRIVER",
L"EFI_ROM",
L"XBOX",
L"Unknown",
};
CHAR16 *mFileTypeString[] = {
L"Unknown",
L"RAW",
L"FREEFORM",
L"SECURITY_CORE",
L"PEI_CORE",
L"DXE_CORE",
L"PEIM",
L"DRIVER",
L"COMBINED_PEIM_DRIVER",
L"APPLICATION",
L"SMM",
L"FIRMWARE_VOLUME_IMAGE",
L"COMBINED_SMM_DXE",
L"SMM_CORE",
};
#define PROFILE_NAME_STRING_LENGTH 36
CHAR16 mNameString[PROFILE_NAME_STRING_LENGTH + 1];
/**
Get the file name portion of the Pdb File Name.
The portion of the Pdb File Name between the last backslash and
either a following period or the end of the string is converted
to Unicode and copied into UnicodeBuffer. The name is truncated,
if necessary, to ensure that UnicodeBuffer is not overrun.
@param[in] PdbFileName Pdb file name.
@param[out] UnicodeBuffer The resultant Unicode File Name.
**/
VOID
GetShortPdbFileName (
IN CHAR8 *PdbFileName,
OUT CHAR16 *UnicodeBuffer
)
{
UINTN IndexA; // Current work location within an ASCII string.
UINTN IndexU; // Current work location within a Unicode string.
UINTN StartIndex;
UINTN EndIndex;
ZeroMem (UnicodeBuffer, PROFILE_NAME_STRING_LENGTH * sizeof (CHAR16));
if (PdbFileName == NULL) {
StrnCpy (UnicodeBuffer, L" ", 1);
} else {
StartIndex = 0;
for (EndIndex = 0; PdbFileName[EndIndex] != 0; EndIndex++);
for (IndexA = 0; PdbFileName[IndexA] != 0; IndexA++) {
if (PdbFileName[IndexA] == '\\') {
StartIndex = IndexA + 1;
}
if (PdbFileName[IndexA] == '.') {
EndIndex = IndexA;
}
}
IndexU = 0;
for (IndexA = StartIndex; IndexA < EndIndex; IndexA++) {
UnicodeBuffer[IndexU] = (CHAR16) PdbFileName[IndexA];
IndexU++;
if (IndexU >= PROFILE_NAME_STRING_LENGTH) {
UnicodeBuffer[PROFILE_NAME_STRING_LENGTH] = 0;
break;
}
}
}
}
/**
Get a human readable name for an image.
The following methods will be tried orderly:
1. Image PDB
2. FFS UI section
3. Image GUID
@param[in] DriverInfo Pointer to memory profile driver info.
@post The resulting Unicode name string is stored in the mNameString global array.
**/
VOID
GetDriverNameString (
IN MEMORY_PROFILE_DRIVER_INFO *DriverInfo
)
{
EFI_STATUS Status;
CHAR8 *PdbFileName;
CHAR16 *NameString;
UINTN StringSize;
//
// Method 1: Get the name string from image PDB
//
if ((DriverInfo->ImageBase != 0) && (DriverInfo->FileType != EFI_FV_FILETYPE_SMM) && (DriverInfo->FileType != EFI_FV_FILETYPE_SMM_CORE)) {
PdbFileName = PeCoffLoaderGetPdbPointer ((VOID *) (UINTN) DriverInfo->ImageBase);
if (PdbFileName != NULL) {
GetShortPdbFileName (PdbFileName, mNameString);
return;
}
}
if (!CompareGuid (&DriverInfo->FileName, &gZeroGuid)) {
//
// Try to get the image's FFS UI section by image GUID
//
NameString = NULL;
StringSize = 0;
Status = GetSectionFromAnyFv (
&DriverInfo->FileName,
EFI_SECTION_USER_INTERFACE,
0,
(VOID **) &NameString,
&StringSize
);
if (!EFI_ERROR (Status)) {
//
// Method 2: Get the name string from FFS UI section
//
StrnCpy (mNameString, NameString, PROFILE_NAME_STRING_LENGTH);
mNameString[PROFILE_NAME_STRING_LENGTH] = 0;
FreePool (NameString);
return;
}
}
//
// Method 3: Get the name string from image GUID
//
UnicodeSPrint (mNameString, sizeof (mNameString), L"%g", &DriverInfo->FileName);
}
/**
Dump memory profile allocate information.
@param[in] DriverInfo Pointer to memory profile driver info.
@param[in] AllocIndex Memory profile alloc info index.
@param[in] AllocInfo Pointer to memory profile alloc info.
@return Pointer to next memory profile alloc info.
**/
MEMORY_PROFILE_ALLOC_INFO *
DumpMemoryProfileAllocInfo (
IN MEMORY_PROFILE_DRIVER_INFO *DriverInfo,
IN UINTN AllocIndex,
IN MEMORY_PROFILE_ALLOC_INFO *AllocInfo
)
{
if (AllocInfo->Header.Signature != MEMORY_PROFILE_ALLOC_INFO_SIGNATURE) {
return NULL;
}
Print (L" MEMORY_PROFILE_ALLOC_INFO (0x%x)\n", AllocIndex);
Print (L" Signature - 0x%08x\n", AllocInfo->Header.Signature);
Print (L" Length - 0x%04x\n", AllocInfo->Header.Length);
Print (L" Revision - 0x%04x\n", AllocInfo->Header.Revision);
Print (L" CallerAddress - 0x%016lx (Offset: 0x%08x)\n", AllocInfo->CallerAddress, (UINTN) (AllocInfo->CallerAddress - DriverInfo->ImageBase));
Print (L" SequenceId - 0x%08x\n", AllocInfo->SequenceId);
Print (L" Action - 0x%08x (%s)\n", AllocInfo->Action, mActionString[(AllocInfo->Action < sizeof(mActionString)/sizeof(mActionString[0])) ? AllocInfo->Action : 0]);
Print (L" MemoryType - 0x%08x (%s)\n", AllocInfo->MemoryType, mMemoryTypeString[(AllocInfo->MemoryType < sizeof(mMemoryTypeString)/sizeof(mMemoryTypeString[0])) ? AllocInfo->MemoryType : (sizeof(mMemoryTypeString)/sizeof(mMemoryTypeString[0]) - 1)]);
Print (L" Buffer - 0x%016lx\n", AllocInfo->Buffer);
Print (L" Size - 0x%016lx\n", AllocInfo->Size);
return (MEMORY_PROFILE_ALLOC_INFO *) ((UINTN) AllocInfo + AllocInfo->Header.Length);
}
/**
Dump memory profile driver information.
@param[in] DriverIndex Memory profile driver info index.
@param[in] DriverInfo Pointer to memory profile driver info.
@return Pointer to next memory profile driver info.
**/
MEMORY_PROFILE_DRIVER_INFO *
DumpMemoryProfileDriverInfo (
IN UINTN DriverIndex,
IN MEMORY_PROFILE_DRIVER_INFO *DriverInfo
)
{
UINTN TypeIndex;
MEMORY_PROFILE_ALLOC_INFO *AllocInfo;
UINTN AllocIndex;
if (DriverInfo->Header.Signature != MEMORY_PROFILE_DRIVER_INFO_SIGNATURE) {
return NULL;
}
Print (L" MEMORY_PROFILE_DRIVER_INFO (0x%x)\n", DriverIndex);
Print (L" Signature - 0x%08x\n", DriverInfo->Header.Signature);
Print (L" Length - 0x%04x\n", DriverInfo->Header.Length);
Print (L" Revision - 0x%04x\n", DriverInfo->Header.Revision);
GetDriverNameString (DriverInfo);
Print (L" FileName - %s\n", &mNameString);
Print (L" ImageBase - 0x%016lx\n", DriverInfo->ImageBase);
Print (L" ImageSize - 0x%016lx\n", DriverInfo->ImageSize);
Print (L" EntryPoint - 0x%016lx\n", DriverInfo->EntryPoint);
Print (L" ImageSubsystem - 0x%04x (%s)\n", DriverInfo->ImageSubsystem, mSubsystemString[(DriverInfo->ImageSubsystem < sizeof(mSubsystemString)/sizeof(mSubsystemString[0])) ? DriverInfo->ImageSubsystem : 0]);
Print (L" FileType - 0x%02x (%s)\n", DriverInfo->FileType, mFileTypeString[(DriverInfo->FileType < sizeof(mFileTypeString)/sizeof(mFileTypeString[0])) ? DriverInfo->FileType : 0]);
Print (L" CurrentUsage - 0x%016lx\n", DriverInfo->CurrentUsage);
Print (L" PeakUsage - 0x%016lx\n", DriverInfo->PeakUsage);
for (TypeIndex = 0; TypeIndex <= EfiMaxMemoryType; TypeIndex++) {
if ((DriverInfo->CurrentUsageByType[TypeIndex] != 0) ||
(DriverInfo->PeakUsageByType[TypeIndex] != 0)) {
Print (L" CurrentUsage[0x%02x] - 0x%016lx (%s)\n", TypeIndex, DriverInfo->CurrentUsageByType[TypeIndex], mMemoryTypeString[TypeIndex]);
Print (L" PeakUsage[0x%02x] - 0x%016lx (%s)\n", TypeIndex, DriverInfo->PeakUsageByType[TypeIndex], mMemoryTypeString[TypeIndex]);
}
}
Print (L" AllocRecordCount - 0x%08x\n", DriverInfo->AllocRecordCount);
AllocInfo = (MEMORY_PROFILE_ALLOC_INFO *) ((UINTN) DriverInfo + DriverInfo->Header.Length);
for (AllocIndex = 0; AllocIndex < DriverInfo->AllocRecordCount; AllocIndex++) {
AllocInfo = DumpMemoryProfileAllocInfo (DriverInfo, AllocIndex, AllocInfo);
if (AllocInfo == NULL) {
return NULL;
}
}
return (MEMORY_PROFILE_DRIVER_INFO *) AllocInfo;
}
/**
Dump memory profile context information.
@param[in] Context Pointer to memory profile context.
@return Pointer to the end of memory profile context buffer.
**/
VOID *
DumpMemoryProfileContext (
IN MEMORY_PROFILE_CONTEXT *Context
)
{
UINTN TypeIndex;
MEMORY_PROFILE_DRIVER_INFO *DriverInfo;
UINTN DriverIndex;
if (Context->Header.Signature != MEMORY_PROFILE_CONTEXT_SIGNATURE) {
return NULL;
}
Print (L"MEMORY_PROFILE_CONTEXT\n");
Print (L" Signature - 0x%08x\n", Context->Header.Signature);
Print (L" Length - 0x%04x\n", Context->Header.Length);
Print (L" Revision - 0x%04x\n", Context->Header.Revision);
Print (L" CurrentTotalUsage - 0x%016lx\n", Context->CurrentTotalUsage);
Print (L" PeakTotalUsage - 0x%016lx\n", Context->PeakTotalUsage);
for (TypeIndex = 0; TypeIndex <= EfiMaxMemoryType; TypeIndex++) {
if ((Context->CurrentTotalUsageByType[TypeIndex] != 0) ||
(Context->PeakTotalUsageByType[TypeIndex] != 0)) {
Print (L" CurrentTotalUsage[0x%02x] - 0x%016lx (%s)\n", TypeIndex, Context->CurrentTotalUsageByType[TypeIndex], mMemoryTypeString[TypeIndex]);
Print (L" PeakTotalUsage[0x%02x] - 0x%016lx (%s)\n", TypeIndex, Context->PeakTotalUsageByType[TypeIndex], mMemoryTypeString[TypeIndex]);
}
}
Print (L" TotalImageSize - 0x%016lx\n", Context->TotalImageSize);
Print (L" ImageCount - 0x%08x\n", Context->ImageCount);
Print (L" SequenceCount - 0x%08x\n", Context->SequenceCount);
DriverInfo = (MEMORY_PROFILE_DRIVER_INFO *) ((UINTN) Context + Context->Header.Length);
for (DriverIndex = 0; DriverIndex < Context->ImageCount; DriverIndex++) {
DriverInfo = DumpMemoryProfileDriverInfo (DriverIndex, DriverInfo);
if (DriverInfo == NULL) {
return NULL;
}
}
return (VOID *) DriverInfo;
}
/**
Dump memory profile descriptor information.
@param[in] DescriptorIndex Memory profile descriptor index.
@param[in] Descriptor Pointer to memory profile descriptor.
@return Pointer to next memory profile descriptor.
**/
MEMORY_PROFILE_DESCRIPTOR *
DumpMemoryProfileDescriptor (
IN UINTN DescriptorIndex,
IN MEMORY_PROFILE_DESCRIPTOR *Descriptor
)
{
if (Descriptor->Header.Signature != MEMORY_PROFILE_DESCRIPTOR_SIGNATURE) {
return NULL;
}
Print (L" MEMORY_PROFILE_DESCRIPTOR (0x%x)\n", DescriptorIndex);
Print (L" Signature - 0x%08x\n", Descriptor->Header.Signature);
Print (L" Length - 0x%04x\n", Descriptor->Header.Length);
Print (L" Revision - 0x%04x\n", Descriptor->Header.Revision);
Print (L" Address - 0x%016lx\n", Descriptor->Address);
Print (L" Size - 0x%016lx\n", Descriptor->Size);
return (MEMORY_PROFILE_DESCRIPTOR *) ((UINTN) Descriptor + Descriptor->Header.Length);
}
/**
Dump memory profile free memory information.
@param[in] FreeMemory Pointer to memory profile free memory.
@return Pointer to the end of memory profile free memory buffer.
**/
VOID *
DumpMemoryProfileFreeMemory (
IN MEMORY_PROFILE_FREE_MEMORY *FreeMemory
)
{
MEMORY_PROFILE_DESCRIPTOR *Descriptor;
UINTN DescriptorIndex;
if (FreeMemory->Header.Signature != MEMORY_PROFILE_FREE_MEMORY_SIGNATURE) {
return NULL;
}
Print (L"MEMORY_PROFILE_FREE_MEMORY\n");
Print (L" Signature - 0x%08x\n", FreeMemory->Header.Signature);
Print (L" Length - 0x%04x\n", FreeMemory->Header.Length);
Print (L" Revision - 0x%04x\n", FreeMemory->Header.Revision);
Print (L" TotalFreeMemoryPages - 0x%016lx\n", FreeMemory->TotalFreeMemoryPages);
Print (L" FreeMemoryEntryCount - 0x%08x\n", FreeMemory->FreeMemoryEntryCount);
Descriptor = (MEMORY_PROFILE_DESCRIPTOR *) ((UINTN) FreeMemory + FreeMemory->Header.Length);
for (DescriptorIndex = 0; DescriptorIndex < FreeMemory->FreeMemoryEntryCount; DescriptorIndex++) {
Descriptor = DumpMemoryProfileDescriptor (DescriptorIndex, Descriptor);
if (Descriptor == NULL) {
return NULL;
}
}
return (VOID *) Descriptor;
}
/**
Dump memory profile memory range information.
@param[in] MemoryRange Pointer to memory profile memory range.
@return Pointer to the end of memory profile memory range buffer.
**/
VOID *
DumpMemoryProfileMemoryRange (
IN MEMORY_PROFILE_MEMORY_RANGE *MemoryRange
)
{
MEMORY_PROFILE_DESCRIPTOR *Descriptor;
UINTN DescriptorIndex;
if (MemoryRange->Header.Signature != MEMORY_PROFILE_MEMORY_RANGE_SIGNATURE) {
return NULL;
}
Print (L"MEMORY_PROFILE_MEMORY_RANGE\n");
Print (L" Signature - 0x%08x\n", MemoryRange->Header.Signature);
Print (L" Length - 0x%04x\n", MemoryRange->Header.Length);
Print (L" Revision - 0x%04x\n", MemoryRange->Header.Revision);
Print (L" MemoryRangeCount - 0x%08x\n", MemoryRange->MemoryRangeCount);
Descriptor = (MEMORY_PROFILE_DESCRIPTOR *) ((UINTN) MemoryRange + MemoryRange->Header.Length);
for (DescriptorIndex = 0; DescriptorIndex < MemoryRange->MemoryRangeCount; DescriptorIndex++) {
Descriptor = DumpMemoryProfileDescriptor (DescriptorIndex, Descriptor);
if (Descriptor == NULL) {
return NULL;
}
}
return (VOID *) Descriptor;
}
/**
Scan memory profile by Signature.
@param[in] ProfileBuffer Memory profile base address.
@param[in] ProfileSize Memory profile size.
@param[in] Signature Signature.
@return Pointer to the stucture with the signature.
**/
VOID *
ScanMemoryProfileBySignature (
IN PHYSICAL_ADDRESS ProfileBuffer,
IN UINT64 ProfileSize,
IN UINT32 Signature
)
{
MEMORY_PROFILE_COMMON_HEADER *CommonHeader;
UINTN ProfileEnd;
ProfileEnd = (UINTN) (ProfileBuffer + ProfileSize);
CommonHeader = (MEMORY_PROFILE_COMMON_HEADER *) (UINTN) ProfileBuffer;
while ((UINTN) CommonHeader < ProfileEnd) {
if (CommonHeader->Signature == Signature) {
//
// Found it.
//
return (VOID *) CommonHeader;
}
CommonHeader = (MEMORY_PROFILE_COMMON_HEADER *) ((UINTN) CommonHeader + CommonHeader->Length);
}
return NULL;
}
/**
Dump memory profile information.
@param[in] ProfileBuffer Memory profile base address.
@param[in] ProfileSize Memory profile size.
**/
VOID
DumpMemoryProfile (
IN PHYSICAL_ADDRESS ProfileBuffer,
IN UINT64 ProfileSize
)
{
MEMORY_PROFILE_CONTEXT *Context;
MEMORY_PROFILE_FREE_MEMORY *FreeMemory;
MEMORY_PROFILE_MEMORY_RANGE *MemoryRange;
Context = (MEMORY_PROFILE_CONTEXT *) ScanMemoryProfileBySignature (ProfileBuffer, ProfileSize, MEMORY_PROFILE_CONTEXT_SIGNATURE);
if (Context != NULL) {
DumpMemoryProfileContext (Context);
}
FreeMemory = (MEMORY_PROFILE_FREE_MEMORY *) ScanMemoryProfileBySignature (ProfileBuffer, ProfileSize, MEMORY_PROFILE_FREE_MEMORY_SIGNATURE);
if (FreeMemory != NULL) {
DumpMemoryProfileFreeMemory (FreeMemory);
}
MemoryRange = (MEMORY_PROFILE_MEMORY_RANGE *) ScanMemoryProfileBySignature (ProfileBuffer, ProfileSize, MEMORY_PROFILE_MEMORY_RANGE_SIGNATURE);
if (MemoryRange != NULL) {
DumpMemoryProfileMemoryRange (MemoryRange);
}
}
/**
Get and dump UEFI memory profile data.
@return EFI_SUCCESS Get the memory profile data successfully.
@return other Fail to get the memory profile data.
**/
EFI_STATUS
GetUefiMemoryProfileData (
VOID
)
{
EFI_STATUS Status;
EDKII_MEMORY_PROFILE_PROTOCOL *ProfileProtocol;
VOID *Data;
UINT64 Size;
Status = gBS->LocateProtocol (&gEdkiiMemoryProfileGuid, NULL, (VOID **) &ProfileProtocol);
if (EFI_ERROR (Status)) {
DEBUG ((EFI_D_ERROR, "UefiMemoryProfile: Locate MemoryProfile protocol - %r\n", Status));
return Status;
}
Size = 0;
Data = NULL;
Status = ProfileProtocol->GetData (
ProfileProtocol,
&Size,
Data
);
if (Status != EFI_BUFFER_TOO_SMALL) {
Print (L"UefiMemoryProfile: GetData - %r\n", Status);
return Status;
}
//
// Add one sizeof (MEMORY_PROFILE_ALLOC_INFO) to Size for this AllocatePool action.
//
Size = Size + sizeof (MEMORY_PROFILE_ALLOC_INFO);
Data = AllocateZeroPool ((UINTN) Size);
if (Data == NULL) {
Print (L"UefiMemoryProfile: AllocateZeroPool (0x%x) - %r\n", Size, Status);
return Status;
}
Status = ProfileProtocol->GetData (
ProfileProtocol,
&Size,
Data
);
if (EFI_ERROR (Status)) {
FreePool (Data);
Print (L"UefiMemoryProfile: GetData - %r\n", Status);
return Status;
}
Print (L"UefiMemoryProfileSize - 0x%x\n", Size);
Print (L"======= UefiMemoryProfile begin =======\n");
DumpMemoryProfile ((PHYSICAL_ADDRESS) (UINTN) Data, Size);
Print (L"======= UefiMemoryProfile end =======\n\n\n");
FreePool (Data);
return EFI_SUCCESS;
}
/**
Get and dump SMRAM profile data.
@return EFI_SUCCESS Get the SMRAM profile data successfully.
@return other Fail to get the SMRAM profile data.
**/
EFI_STATUS
GetSmramProfileData (
VOID
)
{
EFI_STATUS Status;
UINTN CommSize;
UINT8 CommBuffer[sizeof (EFI_GUID) + sizeof (UINTN) + sizeof (SMRAM_PROFILE_PARAMETER_GET_PROFILE_DATA)];
EFI_SMM_COMMUNICATE_HEADER *CommHeader;
SMRAM_PROFILE_PARAMETER_GET_PROFILE_INFO *CommGetProfileInfo;
SMRAM_PROFILE_PARAMETER_GET_PROFILE_DATA *CommGetProfileData;
UINT64 ProfileSize;
PHYSICAL_ADDRESS ProfileBuffer;
EFI_SMM_COMMUNICATION_PROTOCOL *SmmCommunication;
Status = gBS->LocateProtocol (&gEfiSmmCommunicationProtocolGuid, NULL, (VOID **) &SmmCommunication);
if (EFI_ERROR (Status)) {
DEBUG ((EFI_D_ERROR, "SmramProfile: Locate SmmCommunication protocol - %r\n", Status));
return Status;
}
//
// Get Size
//
CommHeader = (EFI_SMM_COMMUNICATE_HEADER *) &CommBuffer[0];
CopyMem (&CommHeader->HeaderGuid, &gEdkiiMemoryProfileGuid, sizeof (gEdkiiMemoryProfileGuid));
CommHeader->MessageLength = sizeof (SMRAM_PROFILE_PARAMETER_GET_PROFILE_INFO);
CommGetProfileInfo = (SMRAM_PROFILE_PARAMETER_GET_PROFILE_INFO *) &CommBuffer[OFFSET_OF (EFI_SMM_COMMUNICATE_HEADER, Data)];
CommGetProfileInfo->Header.Command = SMRAM_PROFILE_COMMAND_GET_PROFILE_INFO;
CommGetProfileInfo->Header.DataLength = sizeof (*CommGetProfileInfo);
CommGetProfileInfo->Header.ReturnStatus = (UINT64)-1;
CommGetProfileInfo->ProfileSize = 0;
CommSize = sizeof (EFI_GUID) + sizeof (UINTN) + CommHeader->MessageLength;
Status = SmmCommunication->Communicate (SmmCommunication, CommBuffer, &CommSize);
if (EFI_ERROR (Status)) {
DEBUG ((EFI_D_ERROR, "SmramProfile: SmmCommunication - %r\n", Status));
return Status;
}
if (CommGetProfileInfo->Header.ReturnStatus != 0) {
Print (L"SmramProfile: GetProfileInfo - 0x%0x\n", CommGetProfileInfo->Header.ReturnStatus);
return EFI_SUCCESS;
}
ProfileSize = CommGetProfileInfo->ProfileSize;
//
// Get Data
//
ProfileBuffer = (PHYSICAL_ADDRESS) (UINTN) AllocateZeroPool ((UINTN) ProfileSize);
if (ProfileBuffer == 0) {
Print (L"UefiMemoryProfile: AllocateZeroPool (0x%x) - %r\n", (UINTN) ProfileSize, Status);
return EFI_SUCCESS;
}
CommHeader = (EFI_SMM_COMMUNICATE_HEADER *) &CommBuffer[0];
CopyMem (&CommHeader->HeaderGuid, &gEdkiiMemoryProfileGuid, sizeof(gEdkiiMemoryProfileGuid));
CommHeader->MessageLength = sizeof (SMRAM_PROFILE_PARAMETER_GET_PROFILE_DATA);
CommGetProfileData = (SMRAM_PROFILE_PARAMETER_GET_PROFILE_DATA *)&CommBuffer[OFFSET_OF (EFI_SMM_COMMUNICATE_HEADER, Data)];
CommGetProfileData->Header.Command = SMRAM_PROFILE_COMMAND_GET_PROFILE_DATA;
CommGetProfileData->Header.DataLength = sizeof (*CommGetProfileData);
CommGetProfileData->Header.ReturnStatus = (UINT64)-1;
CommGetProfileData->ProfileSize = ProfileSize;
CommGetProfileData->ProfileBuffer = ProfileBuffer;
CommSize = sizeof (EFI_GUID) + sizeof (UINTN) + CommHeader->MessageLength;
Status = SmmCommunication->Communicate (SmmCommunication, CommBuffer, &CommSize);
ASSERT_EFI_ERROR (Status);
if (CommGetProfileData->Header.ReturnStatus != 0) {
Print (L"GetProfileData - 0x%x\n", CommGetProfileData->Header.ReturnStatus);
return EFI_SUCCESS;
}
Print (L"SmramProfileSize - 0x%x\n", CommGetProfileData->ProfileSize);
Print (L"======= SmramProfile begin =======\n");
DumpMemoryProfile (CommGetProfileData->ProfileBuffer, CommGetProfileData->ProfileSize);
Print (L"======= SmramProfile end =======\n\n\n");
FreePool ((VOID *) (UINTN) CommGetProfileData->ProfileBuffer);
return EFI_SUCCESS;
}
/**
The user Entry Point for Application. The user code starts with this function
as the real entry point for the image goes into a library that calls this function.
@param[in] ImageHandle The firmware allocated handle for the EFI image.
@param[in] SystemTable A pointer to the EFI System Table.
@retval EFI_SUCCESS The entry point is executed successfully.
@retval other Some error occurs when executing this entry point.
**/
EFI_STATUS
EFIAPI
UefiMain (
IN EFI_HANDLE ImageHandle,
IN EFI_SYSTEM_TABLE *SystemTable
)
{
EFI_STATUS Status;
Status = GetUefiMemoryProfileData ();
if (EFI_ERROR (Status)) {
DEBUG ((EFI_D_ERROR, "GetUefiMemoryProfileData - %r\n", Status));
}
Status = GetSmramProfileData ();
if (EFI_ERROR (Status)) {
DEBUG ((EFI_D_ERROR, "GetSmramProfileData - %r\n", Status));
}
return EFI_SUCCESS;
}

View File

@ -0,0 +1,62 @@
## @file
# Shell application to dump UEFI memory and SMRAM profile information.
#
# Note that if the feature is not enabled by setting PcdMemoryProfilePropertyMask,
# the application will not display memory profile information.
#
# Copyright (c) 2014, Intel Corporation. All rights reserved.<BR>
# 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
# http://opensource.org/licenses/bsd-license.php
# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
#
##
[Defines]
INF_VERSION = 0x00010005
BASE_NAME = MemoryProfileInfo
MODULE_UNI_FILE = MemoryProfileInfo.uni
FILE_GUID = 21429B90-5F67-4e93-AF55-1D314D646E12
MODULE_TYPE = UEFI_APPLICATION
VERSION_STRING = 1.0
ENTRY_POINT = UefiMain
#
# The following information is for reference only and not required by the build tools.
#
# VALID_ARCHITECTURES = IA32 X64 IPF EBC
#
[Sources]
MemoryProfileInfo.c
[Packages]
MdePkg/MdePkg.dec
MdeModulePkg/MdeModulePkg.dec
[LibraryClasses]
UefiApplicationEntryPoint
BaseLib
BaseMemoryLib
UefiBootServicesTableLib
UefiRuntimeServicesTableLib
DebugLib
UefiLib
MemoryAllocationLib
DxeServicesLib
PeCoffGetEntryPointLib
PrintLib
[Guids]
## SOMETIMES_CONSUMES ## GUID # Locate protocol
## SOMETIMES_CONSUMES ## GUID # SmiHandlerRegister
gEdkiiMemoryProfileGuid
gZeroGuid ## SOMETIMES_CONSUMES ## GUID
[Protocols]
gEfiSmmCommunicationProtocolGuid ## SOMETIMES_CONSUMES
[UserExtensions.TianoCore."ExtraFiles"]
MemoryProfileInfoExtra.uni

View File

@ -69,6 +69,8 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
#include <Guid/IdleLoopEvent.h>
#include <Guid/VectorHandoffTable.h>
#include <Ppi/VectorHandoffInfo.h>
#include <Guid/ZeroGuid.h>
#include <Guid/MemoryProfile.h>
#include <Library/DxeCoreEntryPoint.h>
#include <Library/DebugLib.h>
@ -191,6 +193,56 @@ typedef struct {
EFI_HANDLE DeviceHandle;
} EFI_GCD_MAP_ENTRY;
#define LOADED_IMAGE_PRIVATE_DATA_SIGNATURE SIGNATURE_32('l','d','r','i')
typedef struct {
UINTN Signature;
/// Image handle
EFI_HANDLE Handle;
/// Image type
UINTN Type;
/// If entrypoint has been called
BOOLEAN Started;
/// The image's entry point
EFI_IMAGE_ENTRY_POINT EntryPoint;
/// loaded image protocol
EFI_LOADED_IMAGE_PROTOCOL Info;
/// Location in memory
EFI_PHYSICAL_ADDRESS ImageBasePage;
/// Number of pages
UINTN NumberOfPages;
/// Original fixup data
CHAR8 *FixupData;
/// Tpl of started image
EFI_TPL Tpl;
/// Status returned by started image
EFI_STATUS Status;
/// Size of ExitData from started image
UINTN ExitDataSize;
/// Pointer to exit data from started image
VOID *ExitData;
/// Pointer to pool allocation for context save/retore
VOID *JumpBuffer;
/// Pointer to buffer for context save/retore
BASE_LIBRARY_JUMP_BUFFER *JumpContext;
/// Machine type from PE image
UINT16 Machine;
/// EBC Protocol pointer
EFI_EBC_PROTOCOL *Ebc;
/// Runtime image list
EFI_RUNTIME_IMAGE_ENTRY *RuntimeData;
/// Pointer to Loaded Image Device Path Protocl
EFI_DEVICE_PATH_PROTOCOL *LoadedImageDevicePath;
/// PeCoffLoader ImageContext
PE_COFF_LOADER_IMAGE_CONTEXT ImageContext;
/// Status returned by LoadImage() service.
EFI_STATUS LoadImageStatus;
} LOADED_IMAGE_PRIVATE_DATA;
#define LOADED_IMAGE_PRIVATE_DATA_FROM_THIS(a) \
CR(a, LOADED_IMAGE_PRIVATE_DATA, Info, LOADED_IMAGE_PRIVATE_DATA_SIGNATURE)
//
// DXE Core Global Variables
//
@ -1192,7 +1244,32 @@ CoreAllocatePages (
IN OUT EFI_PHYSICAL_ADDRESS *Memory
);
/**
Allocates pages from the memory map.
@param Type The type of allocation to perform
@param MemoryType The type of memory to turn the allocated pages
into
@param NumberOfPages The number of pages to allocate
@param Memory A pointer to receive the base allocated memory
address
@return Status. On success, Memory is filled in with the base address allocated
@retval EFI_INVALID_PARAMETER Parameters violate checking rules defined in
spec.
@retval EFI_NOT_FOUND Could not allocate pages match the requirement.
@retval EFI_OUT_OF_RESOURCES No enough pages to allocate.
@retval EFI_SUCCESS Pages successfully allocated.
**/
EFI_STATUS
EFIAPI
CoreInternalAllocatePages (
IN EFI_ALLOCATE_TYPE Type,
IN EFI_MEMORY_TYPE MemoryType,
IN UINTN NumberOfPages,
IN OUT EFI_PHYSICAL_ADDRESS *Memory
);
/**
Frees previous allocated pages.
@ -1212,7 +1289,23 @@ CoreFreePages (
IN UINTN NumberOfPages
);
/**
Frees previous allocated pages.
@param Memory Base address of memory being freed
@param NumberOfPages The number of pages to free
@retval EFI_NOT_FOUND Could not find the entry that covers the range
@retval EFI_INVALID_PARAMETER Address not aligned
@return EFI_SUCCESS -Pages successfully freed.
**/
EFI_STATUS
EFIAPI
CoreInternalFreePages (
IN EFI_PHYSICAL_ADDRESS Memory,
IN UINTN NumberOfPages
);
/**
This function returns a copy of the current memory map. The map is an array of
@ -1277,7 +1370,26 @@ CoreAllocatePool (
OUT VOID **Buffer
);
/**
Allocate pool of a particular type.
@param PoolType Type of pool to allocate
@param Size The amount of pool to allocate
@param Buffer The address to return a pointer to the allocated
pool
@retval EFI_INVALID_PARAMETER PoolType not valid or Buffer is NULL
@retval EFI_OUT_OF_RESOURCES Size exceeds max pool size or allocation failed.
@retval EFI_SUCCESS Pool successfully allocated.
**/
EFI_STATUS
EFIAPI
CoreInternalAllocatePool (
IN EFI_MEMORY_TYPE PoolType,
IN UINTN Size,
OUT VOID **Buffer
);
/**
Frees pool.
@ -1294,7 +1406,20 @@ CoreFreePool (
IN VOID *Buffer
);
/**
Frees pool.
@param Buffer The allocated pool entry to free
@retval EFI_INVALID_PARAMETER Buffer is not a valid value.
@retval EFI_SUCCESS Pool successfully freed.
**/
EFI_STATUS
EFIAPI
CoreInternalFreePool (
IN VOID *Buffer
);
/**
Loads an EFI image into memory and returns a handle to the image.
@ -2619,4 +2744,76 @@ VerifyFvHeaderChecksum (
IN EFI_FIRMWARE_VOLUME_HEADER *FvHeader
);
/**
Initialize memory profile.
@param HobStart The start address of the HOB.
**/
VOID
MemoryProfileInit (
IN VOID *HobStart
);
/**
Install memory profile protocol.
**/
VOID
MemoryProfileInstallProtocol (
VOID
);
/**
Register image to memory profile.
@param DriverEntry Image info.
@param FileType Image file type.
@retval TRUE Register success.
@retval FALSE Register fail.
**/
BOOLEAN
RegisterMemoryProfileImage (
IN LOADED_IMAGE_PRIVATE_DATA *DriverEntry,
IN EFI_FV_FILETYPE FileType
);
/**
Unregister image from memory profile.
@param DriverEntry Image info.
@retval TRUE Unregister success.
@retval FALSE Unregister fail.
**/
BOOLEAN
UnregisterMemoryProfileImage (
IN LOADED_IMAGE_PRIVATE_DATA *DriverEntry
);
/**
Update memory profile information.
@param CallerAddress Address of caller who call Allocate or Free.
@param Action This Allocate or Free action.
@param MemoryType Memory type.
@param Size Buffer size.
@param Buffer Buffer address.
@retval TRUE Profile udpate success.
@retval FALSE Profile update fail.
**/
BOOLEAN
CoreUpdateProfile (
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
);
#endif

View File

@ -52,6 +52,7 @@
Mem/Page.c
Mem/MemData.c
Mem/Imem.h
Mem/MemoryProfileRecord.c
FwVolBlock/FwVolBlock.c
FwVolBlock/FwVolBlock.h
FwVol/FwVolWrite.c
@ -120,6 +121,8 @@
gIdleLoopEventGuid
gEventExitBootServicesFailedGuid ## SOMETIMES_PRODUCES ## Event
gEfiVectorHandoffTableGuid ## SOMETIMES_PRODUCES ## SystemTable
gEdkiiMemoryProfileGuid ## SOMETIMES_PRODUCES ## GUID # Install protocol
gZeroGuid ## SOMETIMES_CONSUMES ## GUID
[Ppis]
gEfiVectorHandoffInfoPpiGuid ## UNDEFINED # HOB
@ -177,6 +180,8 @@
gEfiMdeModulePkgTokenSpaceGuid.PcdLoadFixAddressRuntimeCodePageNumber ## SOMETIMES_CONSUMES
gEfiMdeModulePkgTokenSpaceGuid.PcdLoadModuleAtFixAddressEnable ## CONSUMES
gEfiMdeModulePkgTokenSpaceGuid.PcdMaxEfiSystemTablePointerAddress ## CONSUMES
gEfiMdeModulePkgTokenSpaceGuid.PcdMemoryProfileMemoryType ## CONSUMES
gEfiMdeModulePkgTokenSpaceGuid.PcdMemoryProfilePropertyMask ## CONSUMES
# [Hob]
# RESOURCE_DESCRIPTOR ## CONSUMES
@ -190,4 +195,4 @@
#
[UserExtensions.TianoCore."ExtraFiles"]
DxeCoreExtra.uni
DxeCoreExtra.uni

View File

@ -268,6 +268,8 @@ DxeMain (
//
CoreInitializeMemoryServices (&HobStart, &MemoryBaseAddress, &MemoryLength);
MemoryProfileInit (HobStart);
//
// Allocate the EFI System Table and EFI Runtime Service Table from EfiRuntimeServicesData
// Use the templates to initialize the contents of the EFI System Table and EFI Runtime Services Table
@ -382,6 +384,8 @@ DxeMain (
Status = CoreInitializeEventServices ();
ASSERT_EFI_ERROR (Status);
MemoryProfileInstallProtocol ();
//
// Get persisted vector hand-off info from GUIDeed HOB again due to HobStart may be updated,
// and install configuration table

View File

@ -1626,6 +1626,7 @@ CoreStartImage (
// Subsequent calls to LongJump() cause a non-zero value to be returned by SetJump().
//
if (SetJumpFlag == 0) {
RegisterMemoryProfileImage (Image, (Image->ImageContext.ImageType == EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION ? EFI_FV_FILETYPE_APPLICATION : EFI_FV_FILETYPE_DRIVER));
//
// Call the image's entry point
//
@ -1851,6 +1852,7 @@ CoreUnloadImage (
Status = EFI_INVALID_PARAMETER;
goto Done;
}
UnregisterMemoryProfileImage (Image);
if (Image->Started) {
//

View File

@ -16,56 +16,6 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
#ifndef _IMAGE_H_
#define _IMAGE_H_
#define LOADED_IMAGE_PRIVATE_DATA_SIGNATURE SIGNATURE_32('l','d','r','i')
typedef struct {
UINTN Signature;
/// Image handle
EFI_HANDLE Handle;
/// Image type
UINTN Type;
/// If entrypoint has been called
BOOLEAN Started;
/// The image's entry point
EFI_IMAGE_ENTRY_POINT EntryPoint;
/// loaded image protocol
EFI_LOADED_IMAGE_PROTOCOL Info;
/// Location in memory
EFI_PHYSICAL_ADDRESS ImageBasePage;
/// Number of pages
UINTN NumberOfPages;
/// Original fixup data
CHAR8 *FixupData;
/// Tpl of started image
EFI_TPL Tpl;
/// Status returned by started image
EFI_STATUS Status;
/// Size of ExitData from started image
UINTN ExitDataSize;
/// Pointer to exit data from started image
VOID *ExitData;
/// Pointer to pool allocation for context save/retore
VOID *JumpBuffer;
/// Pointer to buffer for context save/retore
BASE_LIBRARY_JUMP_BUFFER *JumpContext;
/// Machine type from PE image
UINT16 Machine;
/// EBC Protocol pointer
EFI_EBC_PROTOCOL *Ebc;
/// Runtime image list
EFI_RUNTIME_IMAGE_ENTRY *RuntimeData;
/// Pointer to Loaded Image Device Path Protocl
EFI_DEVICE_PATH_PROTOCOL *LoadedImageDevicePath;
/// PeCoffLoader ImageContext
PE_COFF_LOADER_IMAGE_CONTEXT ImageContext;
/// Status returned by LoadImage() service.
EFI_STATUS LoadImageStatus;
} LOADED_IMAGE_PRIVATE_DATA;
#define LOADED_IMAGE_PRIVATE_DATA_FROM_THIS(a) \
CR(a, LOADED_IMAGE_PRIVATE_DATA, Info, LOADED_IMAGE_PRIVATE_DATA_SIGNATURE)
#define LOAD_PE32_IMAGE_PRIVATE_DATA_SIGNATURE SIGNATURE_32('l','p','e','i')
typedef struct {

File diff suppressed because it is too large Load Diff

View File

@ -1106,7 +1106,7 @@ FindFreePages (
**/
EFI_STATUS
EFIAPI
CoreAllocatePages (
CoreInternalAllocatePages (
IN EFI_ALLOCATE_TYPE Type,
IN EFI_MEMORY_TYPE MemoryType,
IN UINTN NumberOfPages,
@ -1192,6 +1192,41 @@ Done:
return Status;
}
/**
Allocates pages from the memory map.
@param Type The type of allocation to perform
@param MemoryType The type of memory to turn the allocated pages
into
@param NumberOfPages The number of pages to allocate
@param Memory A pointer to receive the base allocated memory
address
@return Status. On success, Memory is filled in with the base address allocated
@retval EFI_INVALID_PARAMETER Parameters violate checking rules defined in
spec.
@retval EFI_NOT_FOUND Could not allocate pages match the requirement.
@retval EFI_OUT_OF_RESOURCES No enough pages to allocate.
@retval EFI_SUCCESS Pages successfully allocated.
**/
EFI_STATUS
EFIAPI
CoreAllocatePages (
IN EFI_ALLOCATE_TYPE Type,
IN EFI_MEMORY_TYPE MemoryType,
IN UINTN NumberOfPages,
OUT EFI_PHYSICAL_ADDRESS *Memory
)
{
EFI_STATUS Status;
Status = CoreInternalAllocatePages (Type, MemoryType, NumberOfPages, Memory);
if (!EFI_ERROR (Status)) {
CoreUpdateProfile ((EFI_PHYSICAL_ADDRESS) (UINTN) RETURN_ADDRESS (0), MemoryProfileActionAllocatePages, MemoryType, EFI_PAGES_TO_SIZE (NumberOfPages), (VOID *) (UINTN) *Memory);
}
return Status;
}
/**
Frees previous allocated pages.
@ -1206,7 +1241,7 @@ Done:
**/
EFI_STATUS
EFIAPI
CoreFreePages (
CoreInternalFreePages (
IN EFI_PHYSICAL_ADDRESS Memory,
IN UINTN NumberOfPages
)
@ -1267,6 +1302,33 @@ Done:
return Status;
}
/**
Frees previous allocated pages.
@param Memory Base address of memory being freed
@param NumberOfPages The number of pages to free
@retval EFI_NOT_FOUND Could not find the entry that covers the range
@retval EFI_INVALID_PARAMETER Address not aligned
@return EFI_SUCCESS -Pages successfully freed.
**/
EFI_STATUS
EFIAPI
CoreFreePages (
IN EFI_PHYSICAL_ADDRESS Memory,
IN UINTN NumberOfPages
)
{
EFI_STATUS Status;
Status = CoreInternalFreePages (Memory, NumberOfPages);
if (!EFI_ERROR (Status)) {
CoreUpdateProfile ((EFI_PHYSICAL_ADDRESS) (UINTN) RETURN_ADDRESS (0), MemoryProfileActionFreePages, 0, EFI_PAGES_TO_SIZE (NumberOfPages), (VOID *) (UINTN) Memory);
}
return Status;
}
/**
This function checks to see if the last memory map descriptor in a memory map
can be merged with any of the other memory map descriptors in a memorymap.

View File

@ -175,7 +175,7 @@ LookupPoolHead (
**/
EFI_STATUS
EFIAPI
CoreAllocatePool (
CoreInternalAllocatePool (
IN EFI_MEMORY_TYPE PoolType,
IN UINTN Size,
OUT VOID **Buffer
@ -218,7 +218,35 @@ CoreAllocatePool (
return (*Buffer != NULL) ? EFI_SUCCESS : EFI_OUT_OF_RESOURCES;
}
/**
Allocate pool of a particular type.
@param PoolType Type of pool to allocate
@param Size The amount of pool to allocate
@param Buffer The address to return a pointer to the allocated
pool
@retval EFI_INVALID_PARAMETER PoolType not valid or Buffer is NULL.
@retval EFI_OUT_OF_RESOURCES Size exceeds max pool size or allocation failed.
@retval EFI_SUCCESS Pool successfully allocated.
**/
EFI_STATUS
EFIAPI
CoreAllocatePool (
IN EFI_MEMORY_TYPE PoolType,
IN UINTN Size,
OUT VOID **Buffer
)
{
EFI_STATUS Status;
Status = CoreInternalAllocatePool (PoolType, Size, Buffer);
if (!EFI_ERROR (Status)) {
CoreUpdateProfile ((EFI_PHYSICAL_ADDRESS) (UINTN) RETURN_ADDRESS (0), MemoryProfileActionAllocatePool, PoolType, Size, *Buffer);
}
return Status;
}
/**
Internal function to allocate pool of a particular type.
@ -373,7 +401,7 @@ Done:
**/
EFI_STATUS
EFIAPI
CoreFreePool (
CoreInternalFreePool (
IN VOID *Buffer
)
{
@ -389,7 +417,29 @@ CoreFreePool (
return Status;
}
/**
Frees pool.
@param Buffer The allocated pool entry to free
@retval EFI_INVALID_PARAMETER Buffer is not a valid value.
@retval EFI_SUCCESS Pool successfully freed.
**/
EFI_STATUS
EFIAPI
CoreFreePool (
IN VOID *Buffer
)
{
EFI_STATUS Status;
Status = CoreInternalFreePool (Buffer);
if (!EFI_ERROR (Status)) {
CoreUpdateProfile ((EFI_PHYSICAL_ADDRESS) (UINTN) RETURN_ADDRESS (0), MemoryProfileActionFreePool, 0, 0, Buffer);
}
return Status;
}
/**
Internal function to free a pool entry.
@ -558,3 +608,4 @@ CoreFreePoolI (
return EFI_SUCCESS;
}

View File

@ -874,10 +874,12 @@ SmmDispatcher (
//
// For each SMM driver, pass NULL as ImageHandle
//
RegisterSmramProfileImage (DriverEntry, TRUE);
PERF_START (DriverEntry->ImageHandle, "StartImage:", NULL, 0);
Status = ((EFI_IMAGE_ENTRY_POINT)(UINTN)DriverEntry->ImageEntryPoint)(DriverEntry->ImageHandle, gST);
PERF_END (DriverEntry->ImageHandle, "StartImage:", NULL, 0);
if (EFI_ERROR(Status)){
UnregisterSmramProfileImage (DriverEntry, TRUE);
SmmFreePages(DriverEntry->ImageBuffer, DriverEntry->NumberOfPage);
}

View File

@ -1,7 +1,7 @@
/** @file
SMM Memory page management functions.
Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.<BR>
Copyright (c) 2009 - 2014, Intel Corporation. All rights reserved.<BR>
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
@ -16,11 +16,6 @@
#define TRUNCATE_TO_PAGES(a) ((a) >> EFI_PAGE_SHIFT)
typedef struct {
LIST_ENTRY Link;
UINTN NumberOfPages;
} FREE_PAGE_LIST;
LIST_ENTRY mSmmMemoryMap = INITIALIZE_LIST_HEAD_VARIABLE (mSmmMemoryMap);
/**
@ -151,7 +146,7 @@ InternalAllocAddress (
**/
EFI_STATUS
EFIAPI
SmmAllocatePages (
SmmInternalAllocatePages (
IN EFI_ALLOCATE_TYPE Type,
IN EFI_MEMORY_TYPE MemoryType,
IN UINTN NumberOfPages,
@ -202,6 +197,40 @@ SmmAllocatePages (
return EFI_SUCCESS;
}
/**
Allocates pages from the memory map.
@param Type The type of allocation to perform.
@param MemoryType The type of memory to turn the allocated pages
into.
@param NumberOfPages The number of pages to allocate.
@param Memory A pointer to receive the base allocated memory
address.
@retval EFI_INVALID_PARAMETER Parameters violate checking rules defined in spec.
@retval EFI_NOT_FOUND Could not allocate pages match the requirement.
@retval EFI_OUT_OF_RESOURCES No enough pages to allocate.
@retval EFI_SUCCESS Pages successfully allocated.
**/
EFI_STATUS
EFIAPI
SmmAllocatePages (
IN EFI_ALLOCATE_TYPE Type,
IN EFI_MEMORY_TYPE MemoryType,
IN UINTN NumberOfPages,
OUT EFI_PHYSICAL_ADDRESS *Memory
)
{
EFI_STATUS Status;
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);
}
return Status;
}
/**
Internal Function. Merge two adjacent nodes.
@ -242,7 +271,7 @@ InternalMergeNodes (
**/
EFI_STATUS
EFIAPI
SmmFreePages (
SmmInternalFreePages (
IN EFI_PHYSICAL_ADDRESS Memory,
IN UINTN NumberOfPages
)
@ -293,6 +322,33 @@ SmmFreePages (
return EFI_SUCCESS;
}
/**
Frees previous allocated pages.
@param Memory Base address of memory being freed.
@param NumberOfPages The number of pages to free.
@retval EFI_NOT_FOUND Could not find the entry that covers the range.
@retval EFI_INVALID_PARAMETER Address not aligned.
@return EFI_SUCCESS Pages successfully freed.
**/
EFI_STATUS
EFIAPI
SmmFreePages (
IN EFI_PHYSICAL_ADDRESS Memory,
IN UINTN NumberOfPages
)
{
EFI_STATUS Status;
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);
}
return Status;
}
/**
Add free SMRAM region for use by memory service.

View File

@ -1,7 +1,7 @@
/** @file
SMM Core Main Entry Point
Copyright (c) 2009 - 2012, Intel Corporation. All rights reserved.<BR>
Copyright (c) 2009 - 2014, Intel Corporation. All rights reserved.<BR>
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
@ -82,6 +82,9 @@ SMM_CORE_SMI_HANDLERS mSmmCoreSmiHandlers[] = {
{ NULL, NULL, NULL, FALSE }
};
UINTN mFullSmramRangeCount;
EFI_SMRAM_DESCRIPTOR *mFullSmramRanges;
/**
Place holder function until all the SMM System Table Service are available.
@ -226,6 +229,8 @@ SmmReadyToLockHandler (
gST = NULL;
gBS = NULL;
SmramProfileReadyToLock ();
return Status;
}
@ -401,6 +406,16 @@ SmmMain (
//
SmmInitializeMemoryServices (gSmmCorePrivate->SmramRangeCount, gSmmCorePrivate->SmramRanges);
SmramProfileInit ();
//
// Copy FullSmramRanges to SMRAM
//
mFullSmramRangeCount = gSmmCorePrivate->FullSmramRangeCount;
mFullSmramRanges = AllocatePool (mFullSmramRangeCount * sizeof (EFI_SMRAM_DESCRIPTOR));
ASSERT (mFullSmramRanges != NULL);
CopyMem (mFullSmramRanges, gSmmCorePrivate->FullSmramRanges, mFullSmramRangeCount * sizeof (EFI_SMRAM_DESCRIPTOR));
//
// Register all SMI Handlers required by the SMM Core
//
@ -412,6 +427,8 @@ SmmMain (
);
ASSERT_EFI_ERROR (Status);
}
RegisterSmramProfileHandler ();
return EFI_SUCCESS;
}

View File

@ -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 - 2012, Intel Corporation. All rights reserved.<BR>
Copyright (c) 2009 - 2014, Intel Corporation. All rights reserved.<BR>
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
@ -33,6 +33,8 @@
#include <Guid/Apriori.h>
#include <Guid/EventGroup.h>
#include <Guid/EventLegacyBios.h>
#include <Guid/ZeroGuid.h>
#include <Guid/MemoryProfile.h>
#include <Library/BaseLib.h>
#include <Library/BaseMemoryLib.h>
@ -271,6 +273,31 @@ SmmAllocatePages (
OUT EFI_PHYSICAL_ADDRESS *Memory
);
/**
Allocates pages from the memory map.
@param Type The type of allocation to perform
@param MemoryType The type of memory to turn the allocated pages
into
@param NumberOfPages The number of pages to allocate
@param Memory A pointer to receive the base allocated memory
address
@retval EFI_INVALID_PARAMETER Parameters violate checking rules defined in spec.
@retval EFI_NOT_FOUND Could not allocate pages match the requirement.
@retval EFI_OUT_OF_RESOURCES No enough pages to allocate.
@retval EFI_SUCCESS Pages successfully allocated.
**/
EFI_STATUS
EFIAPI
SmmInternalAllocatePages (
IN EFI_ALLOCATE_TYPE Type,
IN EFI_MEMORY_TYPE MemoryType,
IN UINTN NumberOfPages,
OUT EFI_PHYSICAL_ADDRESS *Memory
);
/**
Frees previous allocated pages.
@ -289,6 +316,24 @@ SmmFreePages (
IN UINTN NumberOfPages
);
/**
Frees previous allocated pages.
@param Memory Base address of memory being freed
@param NumberOfPages The number of pages to free
@retval EFI_NOT_FOUND Could not find the entry that covers the range
@retval EFI_INVALID_PARAMETER Address not aligned
@return EFI_SUCCESS Pages successfully freed.
**/
EFI_STATUS
EFIAPI
SmmInternalFreePages (
IN EFI_PHYSICAL_ADDRESS Memory,
IN UINTN NumberOfPages
);
/**
Allocate pool of a particular type.
@ -310,6 +355,27 @@ SmmAllocatePool (
OUT VOID **Buffer
);
/**
Allocate pool of a particular type.
@param PoolType Type of pool to allocate
@param Size The amount of pool to allocate
@param Buffer The address to return a pointer to the allocated
pool
@retval EFI_INVALID_PARAMETER PoolType not valid
@retval EFI_OUT_OF_RESOURCES Size exceeds max pool size or allocation failed.
@retval EFI_SUCCESS Pool successfully allocated.
**/
EFI_STATUS
EFIAPI
SmmInternalAllocatePool (
IN EFI_MEMORY_TYPE PoolType,
IN UINTN Size,
OUT VOID **Buffer
);
/**
Frees pool.
@ -325,6 +391,21 @@ SmmFreePool (
IN VOID *Buffer
);
/**
Frees pool.
@param Buffer The allocated pool entry to free
@retval EFI_INVALID_PARAMETER Buffer is not a valid value.
@retval EFI_SUCCESS Pool successfully freed.
**/
EFI_STATUS
EFIAPI
SmmInternalFreePool (
IN VOID *Buffer
);
/**
Installs a protocol interface into the boot services environment.
@ -741,4 +822,101 @@ SmmIsSchedulable (
IN EFI_SMM_DRIVER_ENTRY *DriverEntry
);
//
// SmramProfile
//
/**
Initialize SMRAM profile.
**/
VOID
SmramProfileInit (
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.
**/
BOOLEAN
RegisterSmramProfileImage (
IN EFI_SMM_DRIVER_ENTRY *DriverEntry,
IN BOOLEAN RegisterToDxe
);
/**
Unregister image from SMRAM profile.
@param DriverEntry SMM image info.
@param UnregisterToDxe Unregister image from DXE.
@retval TRUE Unregister success.
@retval FALSE Unregister fail.
**/
BOOLEAN
UnregisterSmramProfileImage (
IN EFI_SMM_DRIVER_ENTRY *DriverEntry,
IN BOOLEAN UnregisterToDxe
);
/**
Update SMRAM profile information.
@param CallerAddress Address of caller who call Allocate or Free.
@param Action This Allocate or Free action.
@param MemoryType Memory type.
@param Size Buffer size.
@param Buffer Buffer address.
@retval TRUE Profile udpate success.
@retval FALSE Profile update fail.
**/
BOOLEAN
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
);
/**
Register SMRAM profile handler.
**/
VOID
RegisterSmramProfileHandler (
VOID
);
/**
SMRAM profile ready to lock callback function.
**/
VOID
SmramProfileReadyToLock (
VOID
);
/**
Dump SMRAM infromation.
**/
VOID
DumpSmramInfo (
VOID
);
extern UINTN mFullSmramRangeCount;
extern EFI_SMRAM_DESCRIPTOR *mFullSmramRanges;
#endif

View File

@ -37,6 +37,7 @@
Dispatcher.c
Smi.c
InstallConfigurationTable.c
SmramProfileRecord.c
[Packages]
MdePkg/MdePkg.dec
@ -73,12 +74,18 @@
[Pcd]
gEfiMdeModulePkgTokenSpaceGuid.PcdLoadFixAddressSmmCodePageNumber ## SOMETIMES_CONSUMES
gEfiMdeModulePkgTokenSpaceGuid.PcdLoadModuleAtFixAddressEnable ## CONSUMES
gEfiMdeModulePkgTokenSpaceGuid.PcdMemoryProfileMemoryType ## CONSUMES
gEfiMdeModulePkgTokenSpaceGuid.PcdMemoryProfilePropertyMask ## CONSUMES
[Guids]
gAprioriGuid ## SOMETIMES_CONSUMES ## File
gEfiEventDxeDispatchGuid ## PRODUCES ## GUID # SmiHandlerRegister
gEfiEventLegacyBootGuid ## PRODUCES ## GUID # SmiHandlerRegister
gEfiEndOfDxeEventGroupGuid ## PRODUCES ## GUID # SmiHandlerRegister
## SOMETIMES_CONSUMES ## GUID # Locate protocol
## SOMETIMES_PRODUCES ## GUID # SmiHandlerRegister
gEdkiiMemoryProfileGuid
gZeroGuid ## SOMETIMES_CONSUMES ## GUID
[UserExtensions.TianoCore."ExtraFiles"]
PiSmmCoreExtra.uni

View File

@ -2,7 +2,7 @@
The internal header file that declared a data structure that is shared
between the SMM IPL and the SMM Core.
Copyright (c) 2009 - 2011, Intel Corporation. All rights reserved.<BR>
Copyright (c) 2009 - 2014, Intel Corporation. All rights reserved.<BR>
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
@ -116,6 +116,57 @@ typedef struct {
/// a software SMI handler back to the caller of the SMM Communication Protocol.
///
EFI_STATUS ReturnStatus;
EFI_PHYSICAL_ADDRESS PiSmmCoreImageBase;
UINT64 PiSmmCoreImageSize;
EFI_PHYSICAL_ADDRESS PiSmmCoreEntryPoint;
UINTN FullSmramRangeCount;
EFI_SMRAM_DESCRIPTOR *FullSmramRanges;
} SMM_CORE_PRIVATE_DATA;
//
// Page management
//
typedef struct {
LIST_ENTRY Link;
UINTN NumberOfPages;
} FREE_PAGE_LIST;
extern LIST_ENTRY mSmmMemoryMap;
//
// Pool management
//
//
// MIN_POOL_SHIFT must not be less than 5
//
#define MIN_POOL_SHIFT 6
#define MIN_POOL_SIZE (1 << MIN_POOL_SHIFT)
//
// MAX_POOL_SHIFT must not be less than EFI_PAGE_SHIFT - 1
//
#define MAX_POOL_SHIFT (EFI_PAGE_SHIFT - 1)
#define MAX_POOL_SIZE (1 << MAX_POOL_SHIFT)
//
// MAX_POOL_INDEX are calculated by maximum and minimum pool sizes
//
#define MAX_POOL_INDEX (MAX_POOL_SHIFT - MIN_POOL_SHIFT + 1)
typedef struct {
UINTN Size;
BOOLEAN Available;
} POOL_HEADER;
typedef struct {
POOL_HEADER Header;
LIST_ENTRY Link;
} FREE_POOL_HEADER;
extern LIST_ENTRY mSmmPoolLists[MAX_POOL_INDEX];
#endif

View File

@ -979,6 +979,13 @@ ExecuteSmmCoreFromSmram (
//
DEBUG ((DEBUG_INFO, "SMM IPL calling SMM Core at SMRAM address %p\n", (VOID *)(UINTN)ImageContext.EntryPoint));
gSmmCorePrivate->PiSmmCoreImageBase = ImageContext.ImageAddress;
gSmmCorePrivate->PiSmmCoreImageSize = ImageContext.ImageSize;
DEBUG ((DEBUG_INFO, "PiSmmCoreImageBase - 0x%016lx\n", gSmmCorePrivate->PiSmmCoreImageBase));
DEBUG ((DEBUG_INFO, "PiSmmCoreImageSize - 0x%016lx\n", gSmmCorePrivate->PiSmmCoreImageSize));
gSmmCorePrivate->PiSmmCoreEntryPoint = ImageContext.EntryPoint;
//
// Execute image
//
@ -1076,6 +1083,14 @@ SmmIplEntry (
gSmmCorePrivate->SmramRangeCount = Size / sizeof (EFI_SMRAM_DESCRIPTOR);
//
// Save a full copy
//
gSmmCorePrivate->FullSmramRangeCount = gSmmCorePrivate->SmramRangeCount;
gSmmCorePrivate->FullSmramRanges = (EFI_SMRAM_DESCRIPTOR *) AllocatePool (Size);
ASSERT (gSmmCorePrivate->FullSmramRanges != NULL);
CopyMem (gSmmCorePrivate->FullSmramRanges, gSmmCorePrivate->SmramRanges, Size);
//
// Open all SMRAM ranges
//

View File

@ -1,7 +1,7 @@
/** @file
SMM Memory pool management functions.
Copyright (c) 2009 - 2011, Intel Corporation. All rights reserved.<BR>
Copyright (c) 2009 - 2014, Intel Corporation. All rights reserved.<BR>
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
@ -14,33 +14,6 @@
#include "PiSmmCore.h"
//
// MIN_POOL_SHIFT must not be less than 5
//
#define MIN_POOL_SHIFT 6
#define MIN_POOL_SIZE (1 << MIN_POOL_SHIFT)
//
// MAX_POOL_SHIFT must not be less than EFI_PAGE_SHIFT - 1
//
#define MAX_POOL_SHIFT (EFI_PAGE_SHIFT - 1)
#define MAX_POOL_SIZE (1 << MAX_POOL_SHIFT)
//
// MAX_POOL_INDEX are calculated by maximum and minimum pool sizes
//
#define MAX_POOL_INDEX (MAX_POOL_SHIFT - MIN_POOL_SHIFT + 1)
typedef struct {
UINTN Size;
BOOLEAN Available;
} POOL_HEADER;
typedef struct {
POOL_HEADER Header;
LIST_ENTRY Link;
} FREE_POOL_HEADER;
LIST_ENTRY mSmmPoolLists[MAX_POOL_INDEX];
//
// To cache the SMRAM base since when Loading modules At fixed address feature is enabled,
@ -141,16 +114,18 @@ InternalAllocPoolByIndex (
OUT FREE_POOL_HEADER **FreePoolHdr
)
{
EFI_STATUS Status;
FREE_POOL_HEADER *Hdr;
EFI_STATUS Status;
FREE_POOL_HEADER *Hdr;
EFI_PHYSICAL_ADDRESS Address;
ASSERT (PoolIndex <= MAX_POOL_INDEX);
Status = EFI_SUCCESS;
if (PoolIndex == MAX_POOL_INDEX) {
Hdr = (FREE_POOL_HEADER *)AllocatePages (EFI_SIZE_TO_PAGES (MAX_POOL_SIZE << 1));
if (Hdr == NULL) {
Status = SmmInternalAllocatePages (AllocateAnyPages, EfiRuntimeServicesData, EFI_SIZE_TO_PAGES (MAX_POOL_SIZE << 1), &Address);
if (EFI_ERROR (Status)) {
return EFI_OUT_OF_RESOURCES;
}
Hdr = (FREE_POOL_HEADER *) (UINTN) Address;
} else if (!IsListEmpty (&mSmmPoolLists[PoolIndex])) {
Hdr = BASE_CR (GetFirstNode (&mSmmPoolLists[PoolIndex]), FREE_POOL_HEADER, Link);
RemoveEntryList (&Hdr->Link);
@ -214,7 +189,7 @@ InternalFreePoolByIndex (
**/
EFI_STATUS
EFIAPI
SmmAllocatePool (
SmmInternalAllocatePool (
IN EFI_MEMORY_TYPE PoolType,
IN UINTN Size,
OUT VOID **Buffer
@ -234,7 +209,7 @@ SmmAllocatePool (
Size += sizeof (*PoolHdr);
if (Size > MAX_POOL_SIZE) {
Size = EFI_SIZE_TO_PAGES (Size);
Status = SmmAllocatePages (AllocateAnyPages, PoolType, Size, &Address);
Status = SmmInternalAllocatePages (AllocateAnyPages, PoolType, Size, &Address);
if (EFI_ERROR (Status)) {
return Status;
}
@ -257,6 +232,36 @@ SmmAllocatePool (
return Status;
}
/**
Allocate pool of a particular type.
@param PoolType Type of pool to allocate.
@param Size The amount of pool to allocate.
@param Buffer The address to return a pointer to the allocated
pool.
@retval EFI_INVALID_PARAMETER PoolType not valid.
@retval EFI_OUT_OF_RESOURCES Size exceeds max pool size or allocation failed.
@retval EFI_SUCCESS Pool successfully allocated.
**/
EFI_STATUS
EFIAPI
SmmAllocatePool (
IN EFI_MEMORY_TYPE PoolType,
IN UINTN Size,
OUT VOID **Buffer
)
{
EFI_STATUS Status;
Status = SmmInternalAllocatePool (PoolType, Size, Buffer);
if (!EFI_ERROR (Status)) {
SmmCoreUpdateProfile ((EFI_PHYSICAL_ADDRESS) (UINTN) RETURN_ADDRESS (0), MemoryProfileActionAllocatePool, PoolType, Size, *Buffer);
}
return Status;
}
/**
Frees pool.
@ -268,7 +273,7 @@ SmmAllocatePool (
**/
EFI_STATUS
EFIAPI
SmmFreePool (
SmmInternalFreePool (
IN VOID *Buffer
)
{
@ -284,10 +289,34 @@ SmmFreePool (
if (FreePoolHdr->Header.Size > MAX_POOL_SIZE) {
ASSERT (((UINTN)FreePoolHdr & EFI_PAGE_MASK) == 0);
ASSERT ((FreePoolHdr->Header.Size & EFI_PAGE_MASK) == 0);
return SmmFreePages (
return SmmInternalFreePages (
(EFI_PHYSICAL_ADDRESS)(UINTN)FreePoolHdr,
EFI_SIZE_TO_PAGES (FreePoolHdr->Header.Size)
);
}
return InternalFreePoolByIndex (FreePoolHdr);
}
/**
Frees pool.
@param Buffer The allocated pool entry to free.
@retval EFI_INVALID_PARAMETER Buffer is not a valid value.
@retval EFI_SUCCESS Pool successfully freed.
**/
EFI_STATUS
EFIAPI
SmmFreePool (
IN VOID *Buffer
)
{
EFI_STATUS Status;
Status = SmmInternalFreePool (Buffer);
if (!EFI_ERROR (Status)) {
SmmCoreUpdateProfile ((EFI_PHYSICAL_ADDRESS) (UINTN) RETURN_ADDRESS (0), MemoryProfileActionFreePool, 0, 0, Buffer);
}
return Status;
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,286 @@
/** @file
Memory profile data structure.
Copyright (c) 2014, Intel Corporation. All rights reserved.<BR>
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
http://opensource.org/licenses/bsd-license.php
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
**/
#ifndef _MEMORY_PROFILE_H_
#define _MEMORY_PROFILE_H_
//
// For BIOS MemoryType (0 ~ EfiMaxMemoryType), it is recorded in UsageByType[MemoryType]. (Each valid entry has one entry)
// For OS MemoryType (0x80000000 ~ 0xFFFFFFFF), it is recorded in UsageByType[EfiMaxMemoryType]. (All types are combined into one entry)
//
typedef struct {
UINT32 Signature;
UINT16 Length;
UINT16 Revision;
} MEMORY_PROFILE_COMMON_HEADER;
#define MEMORY_PROFILE_CONTEXT_SIGNATURE SIGNATURE_32 ('M','P','C','T')
#define MEMORY_PROFILE_CONTEXT_REVISION 0x0001
typedef struct {
MEMORY_PROFILE_COMMON_HEADER Header;
UINT64 CurrentTotalUsage;
UINT64 PeakTotalUsage;
UINT64 CurrentTotalUsageByType[EfiMaxMemoryType + 1];
UINT64 PeakTotalUsageByType[EfiMaxMemoryType + 1];
UINT64 TotalImageSize;
UINT32 ImageCount;
UINT32 SequenceCount;
} MEMORY_PROFILE_CONTEXT;
#define MEMORY_PROFILE_DRIVER_INFO_SIGNATURE SIGNATURE_32 ('M','P','D','I')
#define MEMORY_PROFILE_DRIVER_INFO_REVISION 0x0001
typedef struct {
MEMORY_PROFILE_COMMON_HEADER Header;
EFI_GUID FileName;
PHYSICAL_ADDRESS ImageBase;
UINT64 ImageSize;
PHYSICAL_ADDRESS EntryPoint;
UINT16 ImageSubsystem;
EFI_FV_FILETYPE FileType;
UINT8 Reserved[1];
UINT32 AllocRecordCount;
UINT64 CurrentUsage;
UINT64 PeakUsage;
UINT64 CurrentUsageByType[EfiMaxMemoryType + 1];
UINT64 PeakUsageByType[EfiMaxMemoryType + 1];
} MEMORY_PROFILE_DRIVER_INFO;
typedef enum {
MemoryProfileActionAllocatePages = 1,
MemoryProfileActionFreePages = 2,
MemoryProfileActionAllocatePool = 3,
MemoryProfileActionFreePool = 4,
} MEMORY_PROFILE_ACTION;
#define MEMORY_PROFILE_ALLOC_INFO_SIGNATURE SIGNATURE_32 ('M','P','A','I')
#define MEMORY_PROFILE_ALLOC_INFO_REVISION 0x0001
typedef struct {
MEMORY_PROFILE_COMMON_HEADER Header;
PHYSICAL_ADDRESS CallerAddress;
UINT32 SequenceId;
UINT8 Reserved[4];
MEMORY_PROFILE_ACTION Action;
EFI_MEMORY_TYPE MemoryType;
PHYSICAL_ADDRESS Buffer;
UINT64 Size;
} MEMORY_PROFILE_ALLOC_INFO;
#define MEMORY_PROFILE_DESCRIPTOR_SIGNATURE SIGNATURE_32 ('M','P','D','R')
#define MEMORY_PROFILE_DESCRIPTOR_REVISION 0x0001
typedef struct {
MEMORY_PROFILE_COMMON_HEADER Header;
PHYSICAL_ADDRESS Address;
UINT64 Size;
} MEMORY_PROFILE_DESCRIPTOR;
#define MEMORY_PROFILE_FREE_MEMORY_SIGNATURE SIGNATURE_32 ('M','P','R','M')
#define MEMORY_PROFILE_FREE_MEMORY_REVISION 0x0001
typedef struct {
MEMORY_PROFILE_COMMON_HEADER Header;
UINT64 TotalFreeMemoryPages;
UINT32 FreeMemoryEntryCount;
UINT8 Reserved[4];
//MEMORY_PROFILE_DESCRIPTOR MemoryDescriptor[FreeMemoryEntryCount];
} MEMORY_PROFILE_FREE_MEMORY;
#define MEMORY_PROFILE_MEMORY_RANGE_SIGNATURE SIGNATURE_32 ('M','P','M','R')
#define MEMORY_PROFILE_MEMORY_RANGE_REVISION 0x0001
typedef struct {
MEMORY_PROFILE_COMMON_HEADER Header;
UINT32 MemoryRangeCount;
UINT8 Reserved[4];
//MEMORY_PROFILE_DESCRIPTOR MemoryDescriptor[MemoryRangeCount];
} MEMORY_PROFILE_MEMORY_RANGE;
//
// UEFI memory profile layout:
// +--------------------------------+
// | CONTEXT |
// +--------------------------------+
// | DRIVER_INFO(1) |
// +--------------------------------+
// | ALLOC_INFO(1, 1) |
// +--------------------------------+
// | ALLOC_INFO(1, m1) |
// +--------------------------------+
// | DRIVER_INFO(n) |
// +--------------------------------+
// | ALLOC_INFO(n, 1) |
// +--------------------------------+
// | ALLOC_INFO(n, mn) |
// +--------------------------------+
//
typedef struct _EDKII_MEMORY_PROFILE_PROTOCOL EDKII_MEMORY_PROFILE_PROTOCOL;
/**
Get memory profile data.
@param[in] This The EDKII_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_BUFFER_TO_SMALL The ProfileSize is too small for the resulting data.
ProfileSize is updated with the size required.
**/
typedef
EFI_STATUS
(EFIAPI *EDKII_MEMORY_PROFILE_GET_DATA)(
IN EDKII_MEMORY_PROFILE_PROTOCOL *This,
IN OUT UINT64 *ProfileSize,
OUT VOID *ProfileBuffer
);
/**
Register image to memory profile.
@param[in] This The EDKII_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 success.
@return EFI_OUT_OF_RESOURCE No enough resource for this register.
**/
typedef
EFI_STATUS
(EFIAPI *EDKII_MEMORY_PROFILE_REGISTER_IMAGE)(
IN EDKII_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_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 success.
@return EFI_NOT_FOUND The image is not found.
**/
typedef
EFI_STATUS
(EFIAPI *EDKII_MEMORY_PROFILE_UNREGISTER_IMAGE)(
IN EDKII_MEMORY_PROFILE_PROTOCOL *This,
IN EFI_DEVICE_PATH_PROTOCOL *FilePath,
IN PHYSICAL_ADDRESS ImageBase,
IN UINT64 ImageSize
);
struct _EDKII_MEMORY_PROFILE_PROTOCOL {
EDKII_MEMORY_PROFILE_GET_DATA GetData;
EDKII_MEMORY_PROFILE_REGISTER_IMAGE RegisterImage;
EDKII_MEMORY_PROFILE_UNREGISTER_IMAGE UnregisterImage;
};
//
// SMRAM profile layout:
// +--------------------------------+
// | CONTEXT |
// +--------------------------------+
// | DRIVER_INFO(1) |
// +--------------------------------+
// | ALLOC_INFO(1, 1) |
// +--------------------------------+
// | ALLOC_INFO(1, m1) |
// +--------------------------------+
// | DRIVER_INFO(n) |
// +--------------------------------+
// | ALLOC_INFO(n, 1) |
// +--------------------------------+
// | ALLOC_INFO(n, mn) |
// +--------------------------------+
// | FREE_MEMORY |
// +--------------------------------+
// | FREE MEMORY DESCRIPTOR(1) |
// +--------------------------------+
// | FREE MEMORY DESCRIPTOR(p) |
// +--------------------------------+
// | MEMORY_RANGE |
// +--------------------------------+
// | MEMORY RANGE DESCRIPTOR(1) |
// +--------------------------------+
// | MEMORY RANGE DESCRIPTOR(q) |
// +--------------------------------+
//
//
// SMRAM profile command
//
#define SMRAM_PROFILE_COMMAND_GET_PROFILE_INFO 0x1
#define SMRAM_PROFILE_COMMAND_GET_PROFILE_DATA 0x2
//
// Below 2 commands are now used by ECP only and only valid before SmmReadyToLock
//
#define SMRAM_PROFILE_COMMAND_REGISTER_IMAGE 0x3
#define SMRAM_PROFILE_COMMAND_UNREGISTER_IMAGE 0x4
typedef struct {
UINT32 Command;
UINT32 DataLength;
UINT64 ReturnStatus;
} SMRAM_PROFILE_PARAMETER_HEADER;
typedef struct {
SMRAM_PROFILE_PARAMETER_HEADER Header;
UINT64 ProfileSize;
} SMRAM_PROFILE_PARAMETER_GET_PROFILE_INFO;
typedef struct {
SMRAM_PROFILE_PARAMETER_HEADER Header;
UINT64 ProfileSize;
PHYSICAL_ADDRESS ProfileBuffer;
} SMRAM_PROFILE_PARAMETER_GET_PROFILE_DATA;
typedef struct {
SMRAM_PROFILE_PARAMETER_HEADER Header;
EFI_GUID FileName;
PHYSICAL_ADDRESS ImageBuffer;
UINT64 NumberOfPage;
} SMRAM_PROFILE_PARAMETER_REGISTER_IMAGE;
typedef struct {
SMRAM_PROFILE_PARAMETER_HEADER Header;
EFI_GUID FileName;
PHYSICAL_ADDRESS ImageBuffer;
UINT64 NumberOfPage;
} SMRAM_PROFILE_PARAMETER_UNREGISTER_IMAGE;
#define EDKII_MEMORY_PROFILE_GUID { \
0x821c9a09, 0x541a, 0x40f6, 0x9f, 0x43, 0xa, 0xd1, 0x93, 0xa1, 0x2c, 0xfe \
}
extern EFI_GUID gEdkiiMemoryProfileGuid;
#endif

View File

@ -272,6 +272,9 @@
## Include/Guid/StatusCodeDataTypeVariable.h
gEdkiiStatusCodeDataTypeVariableGuid = { 0xf6ee6dbb, 0xd67f, 0x4ea0, { 0x8b, 0x96, 0x6a, 0x71, 0xb1, 0x9d, 0x84, 0xad }}
## Include/Guid/MemoryProfile.h
gEdkiiMemoryProfileGuid = { 0x821c9a09, 0x541a, 0x40f6, { 0x9f, 0x43, 0xa, 0xd1, 0x93, 0xa1, 0x2c, 0xfe }}
[Ppis]
## Include/Ppi/AtaController.h
@ -812,6 +815,38 @@
# @Prompt Default Creator Revision for ACPI table creation.
gEfiMdeModulePkgTokenSpaceGuid.PcdAcpiDefaultCreatorRevision|0x01000013|UINT32|0x30001038
## The mask is used to control memory profile behavior.<BR><BR>
# BIT0 - Enable UEFI memory profile.<BR>
# BIT1 - Enable SMRAM profile.<BR>
# @Prompt Memory Profile Property.
# @Expression 0x80000002 | (gEfiMdeModulePkgTokenSpaceGuid.PcdMemoryProfilePropertyMask & 0xFC) == 0
gEfiMdeModulePkgTokenSpaceGuid.PcdMemoryProfilePropertyMask|0x0|UINT8|0x30001041
## This flag is to control which memory types of alloc info will be recorded by DxeCore & SmmCore.<BR><BR>
# For SmmCore, only EfiRuntimeServicesCode and EfiRuntimeServicesData are valid.<BR>
#
# Below is bit mask for this PCD: (Order is same as UEFI spec)<BR>
# EfiReservedMemoryType 0x0001<BR>
# EfiLoaderCode 0x0002<BR>
# EfiLoaderData 0x0004<BR>
# EfiBootServicesCode 0x0008<BR>
# EfiBootServicesData 0x0010<BR>
# EfiRuntimeServicesCode 0x0020<BR>
# EfiRuntimeServicesData 0x0040<BR>
# EfiConventionalMemory 0x0080<BR>
# EfiUnusableMemory 0x0100<BR>
# EfiACPIReclaimMemory 0x0200<BR>
# EfiACPIMemoryNVS 0x0400<BR>
# EfiMemoryMappedIO 0x0800<BR>
# EfiMemoryMappedIOPortSpace 0x1000<BR>
# EfiPalCode 0x2000<BR>
# OS Reserved 0x8000000000000000<BR>
#
# e.g. Reserved+ACPINvs+ACPIReclaim+RuntimeCode+RuntimeData are needed, 0x661 should be used.<BR>
#
# @Prompt Memory profile memory type.
gEfiMdeModulePkgTokenSpaceGuid.PcdMemoryProfileMemoryType|0x0|UINT64|0x30001042
## UART clock frequency is for the baud rate configuration.
# @Prompt Serial Port Clock Rate.
gEfiMdeModulePkgTokenSpaceGuid.PcdSerialClockRate|1843200|UINT32|0x00010066

View File

@ -194,6 +194,7 @@
[Components]
MdeModulePkg/Application/HelloWorld/HelloWorld.inf
MdeModulePkg/Application/MemoryProfileInfo/MemoryProfileInfo.inf
MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxe.inf
MdeModulePkg/Bus/Pci/IncompatiblePciDeviceSupportDxe/IncompatiblePciDeviceSupportDxe.inf

Binary file not shown.

View File

@ -64,10 +64,12 @@
DebugAgentLib
LockBoxLib
CpuExceptionHandlerLib
DevicePathLib
[Guids]
gEfiBootScriptExecutorVariableGuid ## PRODUCES ## UNDEFINED # SaveLockBox
gEfiBootScriptExecutorContextGuid ## PRODUCES ## UNDEFINED # SaveLockBox
gEdkiiMemoryProfileGuid ## SOMETIMES_CONSUMES ## GUID # Locate protocol
[Protocols]
## NOTIFY
@ -78,7 +80,8 @@
gEfiMdeModulePkgTokenSpaceGuid.PcdDxeIplSwitchToLongMode ## CONSUMES
[Pcd]
gEfiMdeModulePkgTokenSpaceGuid.PcdUse1GPageTable ## SOMETIMES_CONSUMES
gEfiMdeModulePkgTokenSpaceGuid.PcdUse1GPageTable ## SOMETIMES_CONSUMES
gEfiMdeModulePkgTokenSpaceGuid.PcdMemoryProfilePropertyMask ## CONSUMES
[Depex]
gEfiLockBoxProtocolGuid

View File

@ -208,6 +208,47 @@ S3BootScriptExecutorEntryFunction (
return EFI_UNSUPPORTED;
}
/**
Register image to memory profile.
@param FileName File name of the image.
@param ImageBase Image base address.
@param ImageSize Image size.
@param FileType File type of the image.
**/
VOID
RegisterMemoryProfileImage (
IN EFI_GUID *FileName,
IN PHYSICAL_ADDRESS ImageBase,
IN UINT64 ImageSize,
IN EFI_FV_FILETYPE FileType
)
{
EFI_STATUS Status;
EDKII_MEMORY_PROFILE_PROTOCOL *ProfileProtocol;
MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *FilePath;
UINT8 TempBuffer[sizeof (MEDIA_FW_VOL_FILEPATH_DEVICE_PATH) + sizeof (EFI_DEVICE_PATH_PROTOCOL)];
if ((PcdGet8 (PcdMemoryProfilePropertyMask) & BIT0) != 0) {
FilePath = (MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *)TempBuffer;
Status = gBS->LocateProtocol (&gEdkiiMemoryProfileGuid, NULL, (VOID **) &ProfileProtocol);
if (!EFI_ERROR (Status)) {
EfiInitializeFwVolDevicepathNode (FilePath, FileName);
SetDevicePathEndNode (FilePath + 1);
Status = ProfileProtocol->RegisterImage (
ProfileProtocol,
(EFI_DEVICE_PATH_PROTOCOL *) FilePath,
ImageBase,
ImageSize,
FileType
);
}
}
}
/**
This is the Event notification function to reload BootScriptExecutor image
to RESERVED mem and save it to LockBox.
@ -302,6 +343,14 @@ ReadyToLockEventNotify (
// Flush the instruction cache so the image data is written before we execute it
//
InvalidateInstructionCacheRange ((VOID *)(UINTN)ImageContext.ImageAddress, (UINTN)ImageContext.ImageSize);
RegisterMemoryProfileImage (
&gEfiCallerIdGuid,
ImageContext.ImageAddress,
ImageContext.ImageSize,
EFI_FV_FILETYPE_DRIVER
);
Status = ((EFI_IMAGE_ENTRY_POINT)(UINTN)(ImageContext.EntryPoint)) (NewImageHandle, gST);
ASSERT_EFI_ERROR (Status);

View File

@ -4,7 +4,7 @@
This driver is dispatched by Dxe core and the driver will reload itself to ACPI reserved memory
in the entry point. The functionality is to interpret and restore the S3 boot script
Copyright (c) 2006 - 2013, Intel Corporation. All rights reserved.<BR>
Copyright (c) 2006 - 2014, Intel Corporation. All rights reserved.<BR>
This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
@ -36,9 +36,12 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
#include <Library/DebugAgentLib.h>
#include <Library/LockBoxLib.h>
#include <Library/CpuExceptionHandlerLib.h>
#include <Library/DevicePathLib.h>
#include <Guid/AcpiS3Context.h>
#include <Guid/BootScriptExecutorVariable.h>
#include <Guid/MemoryProfile.h>
#include <Protocol/DxeSmmReadyToLock.h>
#include <IndustryStandard/Acpi.h>
/**