From: david wei Date: Fri, 1 Jul 2016 07:05:48 +0000 (+0800) Subject: Merge branch 'master' of https://github.com/tianocore/edk2 X-Git-Tag: edk2-stable201903~6410 X-Git-Url: https://git.proxmox.com/?p=mirror_edk2.git;a=commitdiff_plain;h=87f66b63d409fde7d2ea018b65a63986ba413f1f;hp=ba53301f509fcd092f9d52b7c6e1f7428ec00176 Merge branch 'master' of https://github.com/tianocore/edk2 --- diff --git a/BaseTools/Scripts/MemoryProfileSymbolGen.py b/BaseTools/Scripts/MemoryProfileSymbolGen.py new file mode 100644 index 0000000000..a9790d8883 --- /dev/null +++ b/BaseTools/Scripts/MemoryProfileSymbolGen.py @@ -0,0 +1,281 @@ +## +# Generate symbal for memory profile info. +# +# This tool depends on DIA2Dump.exe (VS) or nm (gcc) to parse debug entry. +# +# Copyright (c) 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 that 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. +# +## + +import os +import re +import sys +from optparse import OptionParser + +versionNumber = "1.0" +__copyright__ = "Copyright (c) 2016, Intel Corporation. All rights reserved." + +class Symbols: + def __init__(self): + self.listLineAddress = [] + self.pdbName = "" + # Cache for function + self.functionName = "" + # Cache for line + self.sourceName = "" + + + def getSymbol (self, rva): + index = 0 + lineName = 0 + sourceName = "??" + while index + 1 < self.lineCount : + if self.listLineAddress[index][0] <= rva and self.listLineAddress[index + 1][0] > rva : + offset = rva - self.listLineAddress[index][0] + functionName = self.listLineAddress[index][1] + lineName = self.listLineAddress[index][2] + sourceName = self.listLineAddress[index][3] + if lineName == 0 : + return " (" + self.listLineAddress[index][1] + "() - " + ")" + else : + return " (" + self.listLineAddress[index][1] + "() - " + sourceName + ":" + str(lineName) + ")" + index += 1 + + return " (unknown)" + + def parse_debug_file(self, driverName, pdbName): + if cmp (pdbName, "") == 0 : + return + self.pdbName = pdbName; + + try: + nmCommand = "nm" + nmLineOption = "-l" + print "parsing (debug) - " + pdbName + os.system ('%s %s %s > nmDump.line.log' % (nmCommand, nmLineOption, pdbName)) + except : + print 'ERROR: nm command not available. Please verify PATH' + return + + # + # parse line + # + linefile = open("nmDump.line.log") + reportLines = linefile.readlines() + linefile.close() + + # 000113ca T AllocatePool c:\home\edk-ii\MdePkg\Library\UefiMemoryAllocationLib\MemoryAllocationLib.c:399 + patchLineFileMatchString = "([0-9a-fA-F]{8})\s+[T|D|t|d]\s+(\w+)\s*((?:[a-zA-Z]:)?[\w+\-./_a-zA-Z0-9\\\\]*):?([0-9]*)" + + for reportLine in reportLines: + #print "check - " + reportLine + match = re.match(patchLineFileMatchString, reportLine) + if match is not None: + #print "match - " + reportLine[:-1] + #print "0 - " + match.group(0) + #print "1 - " + match.group(1) + #print "2 - " + match.group(2) + #print "3 - " + match.group(3) + #print "4 - " + match.group(4) + + rva = int (match.group(1), 16) + functionName = match.group(2) + sourceName = match.group(3) + if cmp (match.group(4), "") != 0 : + lineName = int (match.group(4)) + else : + lineName = 0 + self.listLineAddress.append ([rva, functionName, lineName, sourceName]) + + self.lineCount = len (self.listLineAddress) + + self.listLineAddress = sorted(self.listLineAddress, key=lambda symbolAddress:symbolAddress[0]) + + #for key in self.listLineAddress : + #print "rva - " + "%x"%(key[0]) + ", func - " + key[1] + ", line - " + str(key[2]) + ", source - " + key[3] + + def parse_pdb_file(self, driverName, pdbName): + if cmp (pdbName, "") == 0 : + return + self.pdbName = pdbName; + + try: + #DIA2DumpCommand = "\"C:\\Program Files (x86)\Microsoft Visual Studio 14.0\\DIA SDK\\Samples\\DIA2Dump\\x64\\Debug\\Dia2Dump.exe\"" + DIA2DumpCommand = "Dia2Dump.exe" + #DIA2SymbolOption = "-p" + DIA2LinesOption = "-l" + print "parsing (pdb) - " + pdbName + #os.system ('%s %s %s > DIA2Dump.symbol.log' % (DIA2DumpCommand, DIA2SymbolOption, pdbName)) + os.system ('%s %s %s > DIA2Dump.line.log' % (DIA2DumpCommand, DIA2LinesOption, pdbName)) + except : + print 'ERROR: DIA2Dump command not available. Please verify PATH' + return + + # + # parse line + # + linefile = open("DIA2Dump.line.log") + reportLines = linefile.readlines() + linefile.close() + + # ** GetDebugPrintErrorLevel + # line 32 at [0000C790][0001:0000B790], len = 0x3 c:\home\edk-ii\mdepkg\library\basedebugprinterrorlevellib\basedebugprinterrorlevellib.c (MD5: 687C0AE564079D35D56ED5D84A6164CC) + # line 36 at [0000C793][0001:0000B793], len = 0x5 + # line 37 at [0000C798][0001:0000B798], len = 0x2 + + patchLineFileMatchString = "\s+line ([0-9]+) at \[([0-9a-fA-F]{8})\]\[[0-9a-fA-F]{4}\:[0-9a-fA-F]{8}\], len = 0x[0-9a-fA-F]+\s*([\w+\-\:./_a-zA-Z0-9\\\\]*)\s*" + patchLineFileMatchStringFunc = "\*\*\s+(\w+)\s*" + + for reportLine in reportLines: + #print "check line - " + reportLine + match = re.match(patchLineFileMatchString, reportLine) + if match is not None: + #print "match - " + reportLine[:-1] + #print "0 - " + match.group(0) + #print "1 - " + match.group(1) + #print "2 - " + match.group(2) + if cmp (match.group(3), "") != 0 : + self.sourceName = match.group(3) + sourceName = self.sourceName + functionName = self.functionName + + rva = int (match.group(2), 16) + lineName = int (match.group(1)) + self.listLineAddress.append ([rva, functionName, lineName, sourceName]) + else : + match = re.match(patchLineFileMatchStringFunc, reportLine) + if match is not None: + self.functionName = match.group(1) + + self.lineCount = len (self.listLineAddress) + self.listLineAddress = sorted(self.listLineAddress, key=lambda symbolAddress:symbolAddress[0]) + + #for key in self.listLineAddress : + #print "rva - " + "%x"%(key[0]) + ", func - " + key[1] + ", line - " + str(key[2]) + ", source - " + key[3] + +class SymbolsFile: + def __init__(self): + self.symbolsTable = {} + +symbolsFile = "" + +driverName = "" +rvaName = "" +symbolName = "" + +def getSymbolName(driverName, rva): + global symbolsFile + + #print "driverName - " + driverName + + try : + symbolList = symbolsFile.symbolsTable[driverName] + if symbolList is not None: + return symbolList.getSymbol (rva) + else: + return " (???)" + except Exception: + return " (???)" + +def processLine(newline): + global driverName + global rvaName + + driverPrefixLen = len("Driver - ") + # get driver name + if cmp(newline[0:driverPrefixLen],"Driver - ") == 0 : + driverlineList = newline.split(" ") + driverName = driverlineList[2] + #print "Checking : ", driverName + + # EDKII application output + pdbMatchString = "Driver - \w* \(Usage - 0x[0-9a-fA-F]+\) \(Pdb - ([:\-.\w\\\\/]*)\)\s*" + pdbName = "" + match = re.match(pdbMatchString, newline) + if match is not None: + #print "match - " + newline + #print "0 - " + match.group(0) + #print "1 - " + match.group(1) + pdbName = match.group(1) + #print "PDB - " + pdbName + + symbolsFile.symbolsTable[driverName] = Symbols() + + if cmp (pdbName[-3:], "pdb") == 0 : + symbolsFile.symbolsTable[driverName].parse_pdb_file (driverName, pdbName) + else : + symbolsFile.symbolsTable[driverName].parse_debug_file (driverName, pdbName) + + elif cmp(newline,"") == 0 : + driverName = "" + + # check entry line + if newline.find ("<==") != -1 : + entry_list = newline.split(" ") + rvaName = entry_list[4] + #print "rva : ", rvaName + symbolName = getSymbolName (driverName, int(rvaName, 16)) + else : + rvaName = "" + symbolName = "" + + if cmp(rvaName,"") == 0 : + return newline + else : + return newline + symbolName + +def myOptionParser(): + usage = "%prog [--version] [-h] [--help] [-i inputfile [-o outputfile]]" + Parser = OptionParser(usage=usage, description=__copyright__, version="%prog " + str(versionNumber)) + Parser.add_option("-i", "--inputfile", dest="inputfilename", type="string", help="The input memory profile info file output from MemoryProfileInfo application in MdeModulePkg") + Parser.add_option("-o", "--outputfile", dest="outputfilename", type="string", help="The output memory profile info file with symbol, MemoryProfileInfoSymbol.txt will be used if it is not specified") + + (Options, args) = Parser.parse_args() + if Options.inputfilename is None: + Parser.error("no input file specified") + if Options.outputfilename is None: + Options.outputfilename = "MemoryProfileInfoSymbol.txt" + return Options + +def main(): + global symbolsFile + global Options + Options = myOptionParser() + + symbolsFile = SymbolsFile() + + try : + file = open(Options.inputfilename) + except Exception: + print "fail to open " + Options.inputfilename + return 1 + try : + newfile = open(Options.outputfilename, "w") + except Exception: + print "fail to open " + Options.outputfilename + return 1 + + try: + while 1: + line = file.readline() + if not line: + break + newline = line[:-1] + + newline = processLine(newline) + + newfile.write(newline) + newfile.write("\n") + finally: + file.close() + newfile.close() + +if __name__ == '__main__': + sys.exit(main()) diff --git a/EdkCompatibilityPkg/Compatibility/FrameworkHiiOnUefiHiiThunk/HiiDatabase.c b/EdkCompatibilityPkg/Compatibility/FrameworkHiiOnUefiHiiThunk/HiiDatabase.c index 386ff327f8..2d456da303 100644 --- a/EdkCompatibilityPkg/Compatibility/FrameworkHiiOnUefiHiiThunk/HiiDatabase.c +++ b/EdkCompatibilityPkg/Compatibility/FrameworkHiiOnUefiHiiThunk/HiiDatabase.c @@ -494,7 +494,7 @@ HiiGetSecondaryLanguages ( UnicodeStrToAsciiStr (PrimaryLanguage, PrimaryLang639); PrimaryLang4646 = ConvertLanguagesIso639ToRfc4646 (PrimaryLang639); - ASSERT_EFI_ERROR (PrimaryLang4646 != NULL); + ASSERT (PrimaryLang4646 != NULL); SecLangCodes4646 = HiiGetSupportedSecondaryLanguages (UefiHiiHandle, PrimaryLang4646); diff --git a/EdkCompatibilityPkg/Compatibility/FrameworkHiiOnUefiHiiThunk/Utility.c b/EdkCompatibilityPkg/Compatibility/FrameworkHiiOnUefiHiiThunk/Utility.c index f6d97f6344..d269b8e4d6 100644 --- a/EdkCompatibilityPkg/Compatibility/FrameworkHiiOnUefiHiiThunk/Utility.c +++ b/EdkCompatibilityPkg/Compatibility/FrameworkHiiOnUefiHiiThunk/Utility.c @@ -153,7 +153,7 @@ ExportPackageLists ( &Size, PackageListHdr ); - ASSERT_EFI_ERROR (Status != EFI_BUFFER_TOO_SMALL); + ASSERT (Status != EFI_BUFFER_TOO_SMALL); if (Status == EFI_BUFFER_TOO_SMALL) { PackageListHdr = AllocateZeroPool (Size); diff --git a/IntelFrameworkModulePkg/Universal/StatusCode/RuntimeDxe/StatusCodeRuntimeDxe.h b/IntelFrameworkModulePkg/Universal/StatusCode/RuntimeDxe/StatusCodeRuntimeDxe.h index 9d0ed19c4a..ae20f5b226 100644 --- a/IntelFrameworkModulePkg/Universal/StatusCode/RuntimeDxe/StatusCodeRuntimeDxe.h +++ b/IntelFrameworkModulePkg/Universal/StatusCode/RuntimeDxe/StatusCodeRuntimeDxe.h @@ -53,15 +53,6 @@ typedef struct { } DATAHUB_STATUSCODE_RECORD; -// -// Runtime memory status code worker definition -// -typedef struct { - UINT32 RecordIndex; - UINT32 NumberOfRecords; - UINT32 MaxRecordsNumber; -} RUNTIME_MEMORY_STATUSCODE_HEADER; - extern RUNTIME_MEMORY_STATUSCODE_HEADER *mRtMemoryStatusCodeTable; /** diff --git a/IntelFsp2WrapperPkg/FspmWrapperPeim/FspmWrapperPeim.c b/IntelFsp2WrapperPkg/FspmWrapperPeim/FspmWrapperPeim.c index 6144ad7f41..c98513e41b 100644 --- a/IntelFsp2WrapperPkg/FspmWrapperPeim/FspmWrapperPeim.c +++ b/IntelFsp2WrapperPkg/FspmWrapperPeim/FspmWrapperPeim.c @@ -68,6 +68,11 @@ PeiFspMemoryInit ( // Copy default FSP-M UPD data from Flash // FspmHeaderPtr = (FSP_INFO_HEADER *)FspFindFspHeader (PcdGet32 (PcdFspmBaseAddress)); + DEBUG ((DEBUG_INFO, "FspmHeaderPtr - 0x%x\n", FspmHeaderPtr)); + if (FspmHeaderPtr == NULL) { + return EFI_DEVICE_ERROR; + } + FspmUpdDataPtr = (FSPM_UPD_COMMON *)AllocateZeroPool ((UINTN)FspmHeaderPtr->CfgRegionSize); ASSERT (FspmUpdDataPtr != NULL); SourceData = (UINTN *)((UINTN)FspmHeaderPtr->ImageBase + (UINTN)FspmHeaderPtr->CfgRegionOffset); diff --git a/IntelFsp2WrapperPkg/FspsWrapperPeim/FspsWrapperPeim.c b/IntelFsp2WrapperPkg/FspsWrapperPeim/FspsWrapperPeim.c index 7a65ad7f61..c9236908c8 100644 --- a/IntelFsp2WrapperPkg/FspsWrapperPeim/FspsWrapperPeim.c +++ b/IntelFsp2WrapperPkg/FspsWrapperPeim/FspsWrapperPeim.c @@ -241,6 +241,11 @@ PeiMemoryDiscoveredNotify ( // Copy default FSP-S UPD data from Flash // FspsHeaderPtr = (FSP_INFO_HEADER *)FspFindFspHeader (PcdGet32 (PcdFspsBaseAddress)); + DEBUG ((DEBUG_INFO, "FspsHeaderPtr - 0x%x\n", FspsHeaderPtr)); + if (FspsHeaderPtr == NULL) { + return EFI_DEVICE_ERROR; + } + FspsUpdDataPtr = (FSPS_UPD_COMMON *)AllocateZeroPool ((UINTN)FspsHeaderPtr->CfgRegionSize); ASSERT (FspsUpdDataPtr != NULL); SourceData = (UINTN *)((UINTN)FspsHeaderPtr->ImageBase + (UINTN)FspsHeaderPtr->CfgRegionOffset); diff --git a/MdeModulePkg/Application/MemoryProfileInfo/MemoryProfileInfo.c b/MdeModulePkg/Application/MemoryProfileInfo/MemoryProfileInfo.c index ea2a00bd83..48d8f4657b 100644 --- a/MdeModulePkg/Application/MemoryProfileInfo/MemoryProfileInfo.c +++ b/MdeModulePkg/Application/MemoryProfileInfo/MemoryProfileInfo.c @@ -1,17 +1,16 @@ /** @file - + Copyright (c) 2014 - 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 - http://opensource.org/licenses/bsd-license.php + 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. + 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 #include #include #include @@ -23,7 +22,6 @@ #include #include #include -#include #include #include @@ -33,126 +31,202 @@ #include #include -CHAR16 *mActionString[] = { - L"Unknown", - L"AllocatePages", - L"FreePages", - L"AllocatePool", - L"FreePool", +CHAR8 *mActionString[] = { + "Unknown", + "gBS->AllocatePages", + "gBS->FreePages", + "gBS->AllocatePool", + "gBS->FreePool", +}; + +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"}, }; -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"EfiPersistentMemory", - L"EfiOSReserved", - L"EfiOemReserved", +CHAR8 mUserDefinedActionString[] = {"UserDefined-0x80000000"}; + +CHAR8 *mMemoryTypeString[] = { + "EfiReservedMemoryType", + "EfiLoaderCode", + "EfiLoaderData", + "EfiBootServicesCode", + "EfiBootServicesData", + "EfiRuntimeServicesCode", + "EfiRuntimeServicesData", + "EfiConventionalMemory", + "EfiUnusableMemory", + "EfiACPIReclaimMemory", + "EfiACPIMemoryNVS", + "EfiMemoryMappedIO", + "EfiMemoryMappedIOPortSpace", + "EfiPalCode", + "EfiPersistentMemory", + "EfiOSReserved", + "EfiOemReserved", }; -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", +CHAR8 *mSubsystemString[] = { + "Unknown", + "NATIVE", + "WINDOWS_GUI", + "WINDOWS_CUI", + "Unknown", + "Unknown", + "Unknown", + "POSIX_CUI", + "Unknown", + "WINDOWS_CE_GUI", + "EFI_APPLICATION", + "EFI_BOOT_SERVICE_DRIVER", + "EFI_RUNTIME_DRIVER", + "EFI_ROM", + "XBOX", + "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", +CHAR8 *mFileTypeString[] = { + "Unknown", + "RAW", + "FREEFORM", + "SECURITY_CORE", + "PEI_CORE", + "DXE_CORE", + "PEIM", + "DRIVER", + "COMBINED_PEIM_DRIVER", + "APPLICATION", + "SMM", + "FIRMWARE_VOLUME_IMAGE", + "COMBINED_SMM_DXE", + "SMM_CORE", }; -#define PROFILE_NAME_STRING_LENGTH 36 -CHAR16 mNameString[PROFILE_NAME_STRING_LENGTH + 1]; +#define PROFILE_NAME_STRING_LENGTH 64 +CHAR8 mNameString[PROFILE_NAME_STRING_LENGTH + 1]; + +// +// Profile summary information +// +#define MEMORY_PROFILE_ALLOC_SUMMARY_INFO_SIGNATURE SIGNATURE_32 ('M','P','A','S') +#define MEMORY_PROFILE_ALLOC_SUMMARY_INFO_REVISION 0x0001 + +typedef struct { + MEMORY_PROFILE_COMMON_HEADER Header; + PHYSICAL_ADDRESS CallerAddress; + MEMORY_PROFILE_ACTION Action; + CHAR8 *ActionString; + UINT32 AllocateCount; + UINT64 TotalSize; +} MEMORY_PROFILE_ALLOC_SUMMARY_INFO; + +typedef struct { + UINT32 Signature; + MEMORY_PROFILE_ALLOC_SUMMARY_INFO AllocSummaryInfo; + LIST_ENTRY Link; +} MEMORY_PROFILE_ALLOC_SUMMARY_INFO_DATA; + +typedef struct { + UINT32 Signature; + MEMORY_PROFILE_DRIVER_INFO *DriverInfo; + LIST_ENTRY *AllocSummaryInfoList; + LIST_ENTRY Link; +} MEMORY_PROFILE_DRIVER_SUMMARY_INFO_DATA; + +typedef struct { + UINT32 Signature; + MEMORY_PROFILE_CONTEXT *Context; + LIST_ENTRY *DriverSummaryInfoList; +} MEMORY_PROFILE_CONTEXT_SUMMARY_DATA; -/** +LIST_ENTRY mImageSummaryQueue = INITIALIZE_LIST_HEAD_VARIABLE (mImageSummaryQueue); +MEMORY_PROFILE_CONTEXT_SUMMARY_DATA mMemoryProfileContextSummary; + +/** 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. - + either a following period or the end of the string is copied into + AsciiBuffer. The name is truncated, if necessary, to ensure that + AsciiBuffer is not overrun. + @param[in] PdbFileName Pdb file name. - @param[out] UnicodeBuffer The resultant Unicode File Name. - + @param[out] AsciiBuffer The resultant Ascii File Name. + **/ VOID GetShortPdbFileName ( IN CHAR8 *PdbFileName, - OUT CHAR16 *UnicodeBuffer + OUT CHAR8 *AsciiBuffer ) { - UINTN IndexA; // Current work location within an ASCII string. - UINTN IndexU; // Current work location within a Unicode string. + UINTN IndexPdb; // Current work location within a Pdb string. + UINTN IndexBuffer; // Current work location within a Buffer string. UINTN StartIndex; UINTN EndIndex; - ZeroMem (UnicodeBuffer, (PROFILE_NAME_STRING_LENGTH + 1) * sizeof (CHAR16)); + ZeroMem (AsciiBuffer, PROFILE_NAME_STRING_LENGTH + 1); if (PdbFileName == NULL) { - StrnCpyS (UnicodeBuffer, PROFILE_NAME_STRING_LENGTH + 1, L" ", 1); + AsciiStrnCpyS (AsciiBuffer, PROFILE_NAME_STRING_LENGTH + 1, " ", 1); } else { StartIndex = 0; for (EndIndex = 0; PdbFileName[EndIndex] != 0; EndIndex++); - for (IndexA = 0; PdbFileName[IndexA] != 0; IndexA++) { - if (PdbFileName[IndexA] == '\\') { - StartIndex = IndexA + 1; + for (IndexPdb = 0; PdbFileName[IndexPdb] != 0; IndexPdb++) { + if (PdbFileName[IndexPdb] == '\\') { + StartIndex = IndexPdb + 1; } - if (PdbFileName[IndexA] == '.') { - EndIndex = IndexA; + if (PdbFileName[IndexPdb] == '.') { + EndIndex = IndexPdb; } } - 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; + IndexBuffer = 0; + for (IndexPdb = StartIndex; IndexPdb < EndIndex; IndexPdb++) { + AsciiBuffer[IndexBuffer] = PdbFileName[IndexPdb]; + IndexBuffer++; + if (IndexBuffer >= PROFILE_NAME_STRING_LENGTH) { + AsciiBuffer[PROFILE_NAME_STRING_LENGTH] = 0; break; } } } } -/** +/** Get a human readable name for an image. The following methods will be tried orderly: 1. Image PDB @@ -161,29 +235,24 @@ GetShortPdbFileName ( @param[in] DriverInfo Pointer to memory profile driver info. - @post The resulting Unicode name string is stored in the mNameString global array. + @return The resulting Ascii name string is stored in the mNameString global array. **/ -VOID +CHAR8 * 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 (DriverInfo->Header.Length > sizeof (MEMORY_PROFILE_DRIVER_INFO)) { + GetShortPdbFileName ((CHAR8 *) (DriverInfo + 1), mNameString); + return mNameString; } if (!CompareGuid (&DriverInfo->FileName, &gZeroGuid)) { @@ -203,17 +272,20 @@ GetDriverNameString ( // // Method 2: Get the name string from FFS UI section // - StrnCpyS (mNameString, PROFILE_NAME_STRING_LENGTH + 1, NameString, PROFILE_NAME_STRING_LENGTH); - mNameString[PROFILE_NAME_STRING_LENGTH] = 0; + if (StrLen (NameString) > PROFILE_NAME_STRING_LENGTH) { + NameString[PROFILE_NAME_STRING_LENGTH] = 0; + } + UnicodeStrToAsciiStrS (NameString, mNameString, sizeof (mNameString)); FreePool (NameString); - return; + return mNameString; } } // // Method 3: Get the name string from image GUID // - UnicodeSPrint (mNameString, sizeof (mNameString), L"%g", &DriverInfo->FileName); + AsciiSPrint (mNameString, sizeof (mNameString), "%g", &DriverInfo->FileName); + return mNameString; } /** @@ -224,7 +296,7 @@ GetDriverNameString ( @return Pointer to string. **/ -CHAR16 * +CHAR8 * ProfileMemoryTypeToStr ( IN EFI_MEMORY_TYPE MemoryType ) @@ -248,12 +320,63 @@ ProfileMemoryTypeToStr ( return mMemoryTypeString[Index]; } +/** + Action to string. + + @param[in] Action Profile action. + @param[in] UserDefinedActionString Pointer to user defined action string. + @param[in] IsForSmm TRUE - SMRAM profile. + FALSE - UEFI memory profile. + + @return Pointer to string. + +**/ +CHAR8 * +ProfileActionToStr ( + IN MEMORY_PROFILE_ACTION Action, + IN CHAR8 *UserDefinedActionString, + IN BOOLEAN IsForSmm + ) +{ + UINTN Index; + UINTN ActionStringCount; + CHAR8 **ActionString; + + if (IsForSmm) { + ActionString = mSmmActionString; + ActionStringCount = sizeof (mSmmActionString) / sizeof (mSmmActionString[0]); + } else { + ActionString = mActionString; + ActionStringCount = sizeof (mActionString) / sizeof (mActionString[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; + } + } + if ((Action & MEMORY_PROFILE_ACTION_USER_DEFINED_MASK) != 0) { + if (UserDefinedActionString != NULL) { + return UserDefinedActionString; + } + AsciiSPrint (mUserDefinedActionString, sizeof (mUserDefinedActionString), "UserDefined-0x%08x", Action); + return mUserDefinedActionString; + } + + return ActionString[0]; +} + /** 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. + @param[in] IsForSmm TRUE - SMRAM profile. + FALSE - UEFI memory profile. @return Pointer to next memory profile alloc info. @@ -262,20 +385,30 @@ MEMORY_PROFILE_ALLOC_INFO * DumpMemoryProfileAllocInfo ( IN MEMORY_PROFILE_DRIVER_INFO *DriverInfo, IN UINTN AllocIndex, - IN MEMORY_PROFILE_ALLOC_INFO *AllocInfo + IN MEMORY_PROFILE_ALLOC_INFO *AllocInfo, + IN BOOLEAN IsForSmm ) { + CHAR8 *ActionString; + if (AllocInfo->Header.Signature != MEMORY_PROFILE_ALLOC_INFO_SIGNATURE) { return NULL; } + + if (AllocInfo->ActionStringOffset != 0) { + ActionString = (CHAR8 *) ((UINTN) AllocInfo + AllocInfo->ActionStringOffset); + } else { + ActionString = 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" 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, ProfileMemoryTypeToStr (AllocInfo->MemoryType)); + Print (L" Action - 0x%08x (%a)\n", AllocInfo->Action, ProfileActionToStr (AllocInfo->Action, ActionString, IsForSmm)); + Print (L" MemoryType - 0x%08x (%a)\n", AllocInfo->MemoryType, ProfileMemoryTypeToStr (AllocInfo->MemoryType)); Print (L" Buffer - 0x%016lx\n", AllocInfo->Buffer); Print (L" Size - 0x%016lx\n", AllocInfo->Size); @@ -287,6 +420,8 @@ DumpMemoryProfileAllocInfo ( @param[in] DriverIndex Memory profile driver info index. @param[in] DriverInfo Pointer to memory profile driver info. + @param[in] IsForSmm TRUE - SMRAM profile. + FALSE - UEFI memory profile. @return Pointer to next memory profile driver info. @@ -294,12 +429,14 @@ DumpMemoryProfileAllocInfo ( MEMORY_PROFILE_DRIVER_INFO * DumpMemoryProfileDriverInfo ( IN UINTN DriverIndex, - IN MEMORY_PROFILE_DRIVER_INFO *DriverInfo + IN MEMORY_PROFILE_DRIVER_INFO *DriverInfo, + IN BOOLEAN IsForSmm ) { UINTN TypeIndex; MEMORY_PROFILE_ALLOC_INFO *AllocInfo; UINTN AllocIndex; + CHAR8 *NameString; if (DriverInfo->Header.Signature != MEMORY_PROFILE_DRIVER_INFO_SIGNATURE) { return NULL; @@ -307,28 +444,31 @@ DumpMemoryProfileDriverInfo ( 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" Revision - 0x%04x\n", DriverInfo->Header.Revision); + NameString = GetDriverNameString (DriverInfo); + Print (L" FileName - %a\n", NameString); + if (DriverInfo->PdbStringOffset != 0) { + Print (L" Pdb - %a\n", (CHAR8 *) ((UINTN) DriverInfo + DriverInfo->PdbStringOffset)); + } 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" ImageSubsystem - 0x%04x (%a)\n", DriverInfo->ImageSubsystem, mSubsystemString[(DriverInfo->ImageSubsystem < sizeof(mSubsystemString)/sizeof(mSubsystemString[0])) ? DriverInfo->ImageSubsystem : 0]); + Print (L" FileType - 0x%02x (%a)\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 < sizeof (DriverInfo->CurrentUsageByType) / sizeof (DriverInfo->CurrentUsageByType[0]); 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" CurrentUsage[0x%02x] - 0x%016lx (%a)\n", TypeIndex, DriverInfo->CurrentUsageByType[TypeIndex], mMemoryTypeString[TypeIndex]); + Print (L" PeakUsage[0x%02x] - 0x%016lx (%a)\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); + AllocInfo = DumpMemoryProfileAllocInfo (DriverInfo, AllocIndex, AllocInfo, IsForSmm); if (AllocInfo == NULL) { return NULL; } @@ -340,13 +480,16 @@ DumpMemoryProfileDriverInfo ( Dump memory profile context information. @param[in] Context Pointer to memory profile context. + @param[in] IsForSmm TRUE - SMRAM profile. + FALSE - UEFI memory profile. @return Pointer to the end of memory profile context buffer. **/ VOID * DumpMemoryProfileContext ( - IN MEMORY_PROFILE_CONTEXT *Context + IN MEMORY_PROFILE_CONTEXT *Context, + IN BOOLEAN IsForSmm ) { UINTN TypeIndex; @@ -359,14 +502,14 @@ DumpMemoryProfileContext ( 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" 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 < sizeof (Context->CurrentTotalUsageByType) / sizeof (Context->CurrentTotalUsageByType[0]); 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" CurrentTotalUsage[0x%02x] - 0x%016lx (%a)\n", TypeIndex, Context->CurrentTotalUsageByType[TypeIndex], mMemoryTypeString[TypeIndex]); + Print (L" PeakTotalUsage[0x%02x] - 0x%016lx (%a)\n", TypeIndex, Context->PeakTotalUsageByType[TypeIndex], mMemoryTypeString[TypeIndex]); } } Print (L" TotalImageSize - 0x%016lx\n", Context->TotalImageSize); @@ -375,7 +518,7 @@ DumpMemoryProfileContext ( DriverInfo = (MEMORY_PROFILE_DRIVER_INFO *) ((UINTN) Context + Context->Header.Length); for (DriverIndex = 0; DriverIndex < Context->ImageCount; DriverIndex++) { - DriverInfo = DumpMemoryProfileDriverInfo (DriverIndex, DriverInfo); + DriverInfo = DumpMemoryProfileDriverInfo (DriverIndex, DriverInfo, IsForSmm); if (DriverInfo == NULL) { return NULL; } @@ -404,7 +547,7 @@ DumpMemoryProfileDescriptor ( 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" Revision - 0x%04x\n", Descriptor->Header.Revision); Print (L" Address - 0x%016lx\n", Descriptor->Address); Print (L" Size - 0x%016lx\n", Descriptor->Size); @@ -433,7 +576,7 @@ DumpMemoryProfileFreeMemory ( 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" Revision - 0x%04x\n", FreeMemory->Header.Revision); Print (L" TotalFreeMemoryPages - 0x%016lx\n", FreeMemory->TotalFreeMemoryPages); Print (L" FreeMemoryEntryCount - 0x%08x\n", FreeMemory->FreeMemoryEntryCount); @@ -470,7 +613,7 @@ DumpMemoryProfileMemoryRange ( 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" Revision - 0x%04x\n", MemoryRange->Header.Revision); Print (L" MemoryRangeCount - 0x%08x\n", MemoryRange->MemoryRangeCount); Descriptor = (MEMORY_PROFILE_DESCRIPTOR *) ((UINTN) MemoryRange + MemoryRange->Header.Length); @@ -513,6 +656,10 @@ ScanMemoryProfileBySignature ( // return (VOID *) CommonHeader; } + if (CommonHeader->Length == 0) { + ASSERT (FALSE); + return NULL; + } CommonHeader = (MEMORY_PROFILE_COMMON_HEADER *) ((UINTN) CommonHeader + CommonHeader->Length); } @@ -524,12 +671,15 @@ ScanMemoryProfileBySignature ( @param[in] ProfileBuffer Memory profile base address. @param[in] ProfileSize Memory profile size. + @param[in] IsForSmm TRUE - SMRAM profile. + FALSE - UEFI memory profile. **/ VOID DumpMemoryProfile ( IN PHYSICAL_ADDRESS ProfileBuffer, - IN UINT64 ProfileSize + IN UINT64 ProfileSize, + IN BOOLEAN IsForSmm ) { MEMORY_PROFILE_CONTEXT *Context; @@ -538,7 +688,7 @@ DumpMemoryProfile ( Context = (MEMORY_PROFILE_CONTEXT *) ScanMemoryProfileBySignature (ProfileBuffer, ProfileSize, MEMORY_PROFILE_CONTEXT_SIGNATURE); if (Context != NULL) { - DumpMemoryProfileContext (Context); + DumpMemoryProfileContext (Context, IsForSmm); } FreeMemory = (MEMORY_PROFILE_FREE_MEMORY *) ScanMemoryProfileBySignature (ProfileBuffer, ProfileSize, MEMORY_PROFILE_FREE_MEMORY_SIGNATURE); @@ -552,6 +702,317 @@ DumpMemoryProfile ( } } +/** + Get Allocate summary information structure by caller address. + + @param[in] CallerAddress Caller address. + @param[in] DriverSummaryInfoData Driver summary information data structure. + + @return Allocate summary information structure by caller address. + +**/ +MEMORY_PROFILE_ALLOC_SUMMARY_INFO_DATA * +GetAllocSummaryInfoByCallerAddress ( + IN PHYSICAL_ADDRESS CallerAddress, + IN MEMORY_PROFILE_DRIVER_SUMMARY_INFO_DATA *DriverSummaryInfoData + ) +{ + LIST_ENTRY *AllocSummaryInfoList; + LIST_ENTRY *AllocSummaryLink; + MEMORY_PROFILE_ALLOC_SUMMARY_INFO *AllocSummaryInfo; + MEMORY_PROFILE_ALLOC_SUMMARY_INFO_DATA *AllocSummaryInfoData; + + AllocSummaryInfoList = DriverSummaryInfoData->AllocSummaryInfoList; + + for (AllocSummaryLink = AllocSummaryInfoList->ForwardLink; + AllocSummaryLink != AllocSummaryInfoList; + AllocSummaryLink = AllocSummaryLink->ForwardLink) { + AllocSummaryInfoData = CR ( + AllocSummaryLink, + MEMORY_PROFILE_ALLOC_SUMMARY_INFO_DATA, + Link, + MEMORY_PROFILE_ALLOC_SUMMARY_INFO_SIGNATURE + ); + AllocSummaryInfo = &AllocSummaryInfoData->AllocSummaryInfo; + if (AllocSummaryInfo->CallerAddress == CallerAddress) { + return AllocSummaryInfoData; + } + } + return NULL; +} + +/** + Create Allocate summary information structure and + link to Driver summary information data structure. + + @param[in, out] DriverSummaryInfoData Driver summary information data structure. + @param[in] AllocInfo Pointer to memory profile alloc info. + + @return Pointer to next memory profile alloc info. + +**/ +MEMORY_PROFILE_ALLOC_INFO * +CreateAllocSummaryInfo ( + IN OUT MEMORY_PROFILE_DRIVER_SUMMARY_INFO_DATA *DriverSummaryInfoData, + IN MEMORY_PROFILE_ALLOC_INFO *AllocInfo + ) +{ + MEMORY_PROFILE_ALLOC_SUMMARY_INFO_DATA *AllocSummaryInfoData; + MEMORY_PROFILE_ALLOC_SUMMARY_INFO *AllocSummaryInfo; + + if (AllocInfo->Header.Signature != MEMORY_PROFILE_ALLOC_INFO_SIGNATURE) { + return NULL; + } + + AllocSummaryInfoData = GetAllocSummaryInfoByCallerAddress (AllocInfo->CallerAddress, DriverSummaryInfoData); + if (AllocSummaryInfoData == NULL) { + AllocSummaryInfoData = AllocatePool (sizeof (*AllocSummaryInfoData)); + if (AllocSummaryInfoData == NULL) { + return NULL; + } + + AllocSummaryInfoData->Signature = MEMORY_PROFILE_ALLOC_SUMMARY_INFO_SIGNATURE; + AllocSummaryInfo = &AllocSummaryInfoData->AllocSummaryInfo; + AllocSummaryInfo->Header.Signature = MEMORY_PROFILE_ALLOC_SUMMARY_INFO_SIGNATURE; + AllocSummaryInfo->Header.Length = sizeof (*AllocSummaryInfo); + AllocSummaryInfo->Header.Revision = MEMORY_PROFILE_ALLOC_SUMMARY_INFO_REVISION; + AllocSummaryInfo->CallerAddress = AllocInfo->CallerAddress; + AllocSummaryInfo->Action = AllocInfo->Action; + if (AllocInfo->ActionStringOffset != 0) { + AllocSummaryInfo->ActionString = (CHAR8 *) ((UINTN) AllocInfo + AllocInfo->ActionStringOffset); + } else { + AllocSummaryInfo->ActionString = NULL; + } + AllocSummaryInfo->AllocateCount = 0; + AllocSummaryInfo->TotalSize = 0; + InsertTailList (DriverSummaryInfoData->AllocSummaryInfoList, &AllocSummaryInfoData->Link); + } + AllocSummaryInfo = &AllocSummaryInfoData->AllocSummaryInfo; + AllocSummaryInfo->AllocateCount ++; + AllocSummaryInfo->TotalSize += AllocInfo->Size; + + return (MEMORY_PROFILE_ALLOC_INFO *) ((UINTN) AllocInfo + AllocInfo->Header.Length); +} + +/** + Create Driver summary information structure and + link to Context summary information data structure. + + @param[in, out] ContextSummaryData Context summary information data structure. + @param[in] DriverInfo Pointer to memory profile driver info. + + @return Pointer to next memory profile driver info. + +**/ +MEMORY_PROFILE_DRIVER_INFO * +CreateDriverSummaryInfo ( + IN OUT MEMORY_PROFILE_CONTEXT_SUMMARY_DATA *ContextSummaryData, + IN MEMORY_PROFILE_DRIVER_INFO *DriverInfo + ) +{ + MEMORY_PROFILE_DRIVER_SUMMARY_INFO_DATA *DriverSummaryInfoData; + MEMORY_PROFILE_ALLOC_INFO *AllocInfo; + UINTN AllocIndex; + + if (DriverInfo->Header.Signature != MEMORY_PROFILE_DRIVER_INFO_SIGNATURE) { + return NULL; + } + + DriverSummaryInfoData = AllocatePool (sizeof (*DriverSummaryInfoData) + sizeof (LIST_ENTRY)); + if (DriverSummaryInfoData == NULL) { + return NULL; + } + DriverSummaryInfoData->Signature = MEMORY_PROFILE_DRIVER_INFO_SIGNATURE; + DriverSummaryInfoData->DriverInfo = DriverInfo; + DriverSummaryInfoData->AllocSummaryInfoList = (LIST_ENTRY *) (DriverSummaryInfoData + 1); + InitializeListHead (DriverSummaryInfoData->AllocSummaryInfoList); + InsertTailList (ContextSummaryData->DriverSummaryInfoList, &DriverSummaryInfoData->Link); + + AllocInfo = (MEMORY_PROFILE_ALLOC_INFO *) ((UINTN) DriverInfo + DriverInfo->Header.Length); + for (AllocIndex = 0; AllocIndex < DriverInfo->AllocRecordCount; AllocIndex++) { + AllocInfo = CreateAllocSummaryInfo (DriverSummaryInfoData, AllocInfo); + if (AllocInfo == NULL) { + return NULL; + } + } + return (MEMORY_PROFILE_DRIVER_INFO *) AllocInfo; +} + +/** + Create Context summary information structure. + + @param[in] ProfileBuffer Memory profile base address. + @param[in] ProfileSize Memory profile size. + + @return Context summary information structure. + +**/ +MEMORY_PROFILE_CONTEXT_SUMMARY_DATA * +CreateContextSummaryData ( + IN PHYSICAL_ADDRESS ProfileBuffer, + IN UINT64 ProfileSize + ) +{ + MEMORY_PROFILE_CONTEXT *Context; + MEMORY_PROFILE_DRIVER_INFO *DriverInfo; + UINTN DriverIndex; + + Context = (MEMORY_PROFILE_CONTEXT *) ScanMemoryProfileBySignature (ProfileBuffer, ProfileSize, MEMORY_PROFILE_CONTEXT_SIGNATURE); + if (Context == NULL) { + return NULL; + } + + mMemoryProfileContextSummary.Signature = MEMORY_PROFILE_CONTEXT_SIGNATURE; + mMemoryProfileContextSummary.Context = Context; + mMemoryProfileContextSummary.DriverSummaryInfoList = &mImageSummaryQueue; + + DriverInfo = (MEMORY_PROFILE_DRIVER_INFO *) ((UINTN) Context + Context->Header.Length); + for (DriverIndex = 0; DriverIndex < Context->ImageCount; DriverIndex++) { + DriverInfo = CreateDriverSummaryInfo (&mMemoryProfileContextSummary, DriverInfo); + if (DriverInfo == NULL) { + return NULL; + } + } + + return &mMemoryProfileContextSummary; +} + +/** + Dump Context summary information. + + @param[in] ContextSummaryData Context summary information data. + @param[in] IsForSmm TRUE - SMRAM profile. + FALSE - UEFI memory profile. + +**/ +VOID +DumpContextSummaryData ( + IN MEMORY_PROFILE_CONTEXT_SUMMARY_DATA *ContextSummaryData, + IN BOOLEAN IsForSmm + ) +{ + MEMORY_PROFILE_DRIVER_SUMMARY_INFO_DATA *DriverSummaryInfoData; + MEMORY_PROFILE_ALLOC_SUMMARY_INFO_DATA *AllocSummaryInfoData; + LIST_ENTRY *DriverSummaryInfoList; + LIST_ENTRY *DriverSummaryLink; + LIST_ENTRY *AllocSummaryInfoList; + LIST_ENTRY *AllocSummaryLink; + MEMORY_PROFILE_DRIVER_INFO *DriverInfo; + MEMORY_PROFILE_ALLOC_SUMMARY_INFO *AllocSummaryInfo; + CHAR8 *NameString; + + if (ContextSummaryData == NULL) { + return ; + } + + Print (L"\nSummary Data:\n"); + + DriverSummaryInfoList = ContextSummaryData->DriverSummaryInfoList; + for (DriverSummaryLink = DriverSummaryInfoList->ForwardLink; + DriverSummaryLink != DriverSummaryInfoList; + DriverSummaryLink = DriverSummaryLink->ForwardLink) { + DriverSummaryInfoData = CR ( + DriverSummaryLink, + MEMORY_PROFILE_DRIVER_SUMMARY_INFO_DATA, + Link, + MEMORY_PROFILE_DRIVER_INFO_SIGNATURE + ); + DriverInfo = DriverSummaryInfoData->DriverInfo; + + NameString = GetDriverNameString (DriverInfo); + Print (L"\nDriver - %a (Usage - 0x%08x)", NameString, DriverInfo->CurrentUsage); + if (DriverInfo->CurrentUsage == 0) { + Print (L"\n"); + continue; + } + + if (DriverInfo->PdbStringOffset != 0) { + Print (L" (Pdb - %a)\n", (CHAR8 *) ((UINTN) DriverInfo + DriverInfo->PdbStringOffset)); + } else { + Print (L"\n"); + } + Print (L"Caller List:\n"); + Print(L" Count Size RVA Action\n"); + Print(L"========== ================== ================== (================================)\n"); + AllocSummaryInfoList = DriverSummaryInfoData->AllocSummaryInfoList; + for (AllocSummaryLink = AllocSummaryInfoList->ForwardLink; + AllocSummaryLink != AllocSummaryInfoList; + AllocSummaryLink = AllocSummaryLink->ForwardLink) { + AllocSummaryInfoData = CR ( + AllocSummaryLink, + MEMORY_PROFILE_ALLOC_SUMMARY_INFO_DATA, + Link, + MEMORY_PROFILE_ALLOC_SUMMARY_INFO_SIGNATURE + ); + AllocSummaryInfo = &AllocSummaryInfoData->AllocSummaryInfo; + + Print(L"0x%08x 0x%016lx <== 0x%016lx", + AllocSummaryInfo->AllocateCount, + AllocSummaryInfo->TotalSize, + AllocSummaryInfo->CallerAddress - DriverInfo->ImageBase + ); + Print (L" (%a)\n", ProfileActionToStr (AllocSummaryInfo->Action, AllocSummaryInfo->ActionString, IsForSmm)); + } + } + return ; +} + +/** + Destroy Context summary information. + + @param[in, out] ContextSummaryData Context summary information data. + +**/ +VOID +DestroyContextSummaryData ( + IN OUT MEMORY_PROFILE_CONTEXT_SUMMARY_DATA *ContextSummaryData + ) +{ + MEMORY_PROFILE_DRIVER_SUMMARY_INFO_DATA *DriverSummaryInfoData; + MEMORY_PROFILE_ALLOC_SUMMARY_INFO_DATA *AllocSummaryInfoData; + LIST_ENTRY *DriverSummaryInfoList; + LIST_ENTRY *DriverSummaryLink; + LIST_ENTRY *AllocSummaryInfoList; + LIST_ENTRY *AllocSummaryLink; + + if (ContextSummaryData == NULL) { + return ; + } + + DriverSummaryInfoList = ContextSummaryData->DriverSummaryInfoList; + for (DriverSummaryLink = DriverSummaryInfoList->ForwardLink; + DriverSummaryLink != DriverSummaryInfoList; + ) { + DriverSummaryInfoData = CR ( + DriverSummaryLink, + MEMORY_PROFILE_DRIVER_SUMMARY_INFO_DATA, + Link, + MEMORY_PROFILE_DRIVER_INFO_SIGNATURE + ); + DriverSummaryLink = DriverSummaryLink->ForwardLink; + + AllocSummaryInfoList = DriverSummaryInfoData->AllocSummaryInfoList; + for (AllocSummaryLink = AllocSummaryInfoList->ForwardLink; + AllocSummaryLink != AllocSummaryInfoList; + ) { + AllocSummaryInfoData = CR ( + AllocSummaryLink, + MEMORY_PROFILE_ALLOC_SUMMARY_INFO_DATA, + Link, + MEMORY_PROFILE_ALLOC_SUMMARY_INFO_SIGNATURE + ); + AllocSummaryLink = AllocSummaryLink->ForwardLink; + + RemoveEntryList (&AllocSummaryInfoData->Link); + FreePool (AllocSummaryInfoData); + } + + RemoveEntryList (&DriverSummaryInfoData->Link); + FreePool (DriverSummaryInfoData); + } + return ; +} + /** Get and dump UEFI memory profile data. @@ -564,10 +1025,12 @@ GetUefiMemoryProfileData ( VOID ) { - EFI_STATUS Status; - EDKII_MEMORY_PROFILE_PROTOCOL *ProfileProtocol; - VOID *Data; - UINT64 Size; + EFI_STATUS Status; + EDKII_MEMORY_PROFILE_PROTOCOL *ProfileProtocol; + VOID *Data; + UINT64 Size; + MEMORY_PROFILE_CONTEXT_SUMMARY_DATA *MemoryProfileContextSummaryData; + BOOLEAN RecordingState; Status = gBS->LocateProtocol (&gEdkiiMemoryProfileGuid, NULL, (VOID **) &ProfileProtocol); if (EFI_ERROR (Status)) { @@ -575,6 +1038,15 @@ GetUefiMemoryProfileData ( return Status; } + // + // Set recording state if needed. + // + RecordingState = MEMORY_PROFILE_RECORDING_DISABLE; + Status = ProfileProtocol->GetRecordingState (ProfileProtocol, &RecordingState); + if (RecordingState == MEMORY_PROFILE_RECORDING_ENABLE) { + ProfileProtocol->SetRecordingState (ProfileProtocol, MEMORY_PROFILE_RECORDING_DISABLE); + } + Size = 0; Data = NULL; Status = ProfileProtocol->GetData ( @@ -584,13 +1056,9 @@ GetUefiMemoryProfileData ( ); if (Status != EFI_BUFFER_TOO_SMALL) { Print (L"UefiMemoryProfile: GetData - %r\n", Status); - return Status; + goto Done; } - // - // 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) { Status = EFI_OUT_OF_RESOURCES; @@ -604,20 +1072,39 @@ GetUefiMemoryProfileData ( Data ); if (EFI_ERROR (Status)) { - FreePool (Data); Print (L"UefiMemoryProfile: GetData - %r\n", Status); - return Status; + goto Done; } Print (L"UefiMemoryProfileSize - 0x%x\n", Size); Print (L"======= UefiMemoryProfile begin =======\n"); - DumpMemoryProfile ((PHYSICAL_ADDRESS) (UINTN) Data, Size); + DumpMemoryProfile ((PHYSICAL_ADDRESS) (UINTN) Data, Size, FALSE); + + // + // Dump summary information + // + MemoryProfileContextSummaryData = CreateContextSummaryData ((PHYSICAL_ADDRESS) (UINTN) Data, Size); + if (MemoryProfileContextSummaryData != NULL) { + DumpContextSummaryData (MemoryProfileContextSummaryData, FALSE); + DestroyContextSummaryData (MemoryProfileContextSummaryData); + } + Print (L"======= UefiMemoryProfile end =======\n\n\n"); - FreePool (Data); +Done: + if (Data != NULL) { + FreePool (Data); + } - return EFI_SUCCESS; + // + // Restore recording state if needed. + // + if (RecordingState == MEMORY_PROFILE_RECORDING_ENABLE) { + ProfileProtocol->SetRecordingState (ProfileProtocol, MEMORY_PROFILE_RECORDING_ENABLE); + } + + return Status; } /** @@ -638,6 +1125,7 @@ GetSmramProfileData ( EFI_SMM_COMMUNICATE_HEADER *CommHeader; SMRAM_PROFILE_PARAMETER_GET_PROFILE_INFO *CommGetProfileInfo; SMRAM_PROFILE_PARAMETER_GET_PROFILE_DATA_BY_OFFSET *CommGetProfileData; + SMRAM_PROFILE_PARAMETER_RECORDING_STATE *CommRecordingState; UINTN ProfileSize; VOID *ProfileBuffer; EFI_SMM_COMMUNICATION_PROTOCOL *SmmCommunication; @@ -648,6 +1136,10 @@ GetSmramProfileData ( VOID *Buffer; UINTN Size; UINTN Offset; + MEMORY_PROFILE_CONTEXT_SUMMARY_DATA *MemoryProfileContextSummaryData; + BOOLEAN RecordingState; + + ProfileBuffer = NULL; Status = gBS->LocateProtocol (&gEfiSmmCommunicationProtocolGuid, NULL, (VOID **) &SmmCommunication); if (EFI_ERROR (Status)) { @@ -658,7 +1150,8 @@ GetSmramProfileData ( MinimalSizeNeeded = sizeof (EFI_GUID) + sizeof (UINTN) + MAX (sizeof (SMRAM_PROFILE_PARAMETER_GET_PROFILE_INFO), - sizeof (SMRAM_PROFILE_PARAMETER_GET_PROFILE_DATA_BY_OFFSET)); + MAX (sizeof (SMRAM_PROFILE_PARAMETER_GET_PROFILE_DATA_BY_OFFSET), + sizeof (SMRAM_PROFILE_PARAMETER_RECORDING_STATE))); MinimalSizeNeeded += MAX (sizeof (MEMORY_PROFILE_CONTEXT), MAX (sizeof (MEMORY_PROFILE_DRIVER_INFO), MAX (sizeof (MEMORY_PROFILE_ALLOC_INFO), @@ -689,6 +1182,48 @@ GetSmramProfileData ( ASSERT (Index < PiSmmCommunicationRegionTable->NumberOfEntries); CommBuffer = (UINT8 *) (UINTN) Entry->PhysicalStart; + // + // Set recording state if needed. + // + RecordingState = MEMORY_PROFILE_RECORDING_DISABLE; + + CommHeader = (EFI_SMM_COMMUNICATE_HEADER *) &CommBuffer[0]; + CopyMem (&CommHeader->HeaderGuid, &gEdkiiMemoryProfileGuid, sizeof (gEdkiiMemoryProfileGuid)); + CommHeader->MessageLength = sizeof (SMRAM_PROFILE_PARAMETER_RECORDING_STATE); + + CommRecordingState = (SMRAM_PROFILE_PARAMETER_RECORDING_STATE *) &CommBuffer[OFFSET_OF (EFI_SMM_COMMUNICATE_HEADER, Data)]; + CommRecordingState->Header.Command = SMRAM_PROFILE_COMMAND_GET_RECORDING_STATE; + CommRecordingState->Header.DataLength = sizeof (*CommRecordingState); + CommRecordingState->Header.ReturnStatus = (UINT64)-1; + CommRecordingState->RecordingState = MEMORY_PROFILE_RECORDING_DISABLE; + + 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 (CommRecordingState->Header.ReturnStatus != 0) { + Print (L"SmramProfile: GetRecordingState - 0x%0x\n", CommRecordingState->Header.ReturnStatus); + return EFI_SUCCESS; + } + RecordingState = CommRecordingState->RecordingState; + if (RecordingState == MEMORY_PROFILE_RECORDING_ENABLE) { + CommHeader = (EFI_SMM_COMMUNICATE_HEADER *) &CommBuffer[0]; + CopyMem (&CommHeader->HeaderGuid, &gEdkiiMemoryProfileGuid, sizeof (gEdkiiMemoryProfileGuid)); + CommHeader->MessageLength = sizeof (SMRAM_PROFILE_PARAMETER_RECORDING_STATE); + + CommRecordingState = (SMRAM_PROFILE_PARAMETER_RECORDING_STATE *) &CommBuffer[OFFSET_OF (EFI_SMM_COMMUNICATE_HEADER, Data)]; + CommRecordingState->Header.Command = SMRAM_PROFILE_COMMAND_SET_RECORDING_STATE; + CommRecordingState->Header.DataLength = sizeof (*CommRecordingState); + CommRecordingState->Header.ReturnStatus = (UINT64)-1; + CommRecordingState->RecordingState = MEMORY_PROFILE_RECORDING_DISABLE; + + CommSize = sizeof (EFI_GUID) + sizeof (UINTN) + CommHeader->MessageLength; + SmmCommunication->Communicate (SmmCommunication, CommBuffer, &CommSize); + } + // // Get Size // @@ -704,14 +1239,12 @@ GetSmramProfileData ( 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; - } + ASSERT_EFI_ERROR (Status); if (CommGetProfileInfo->Header.ReturnStatus != 0) { + Status = EFI_SUCCESS; Print (L"SmramProfile: GetProfileInfo - 0x%0x\n", CommGetProfileInfo->Header.ReturnStatus); - return EFI_SUCCESS; + goto Done; } ProfileSize = (UINTN) CommGetProfileInfo->ProfileSize; @@ -720,10 +1253,10 @@ GetSmramProfileData ( // Get Data // ProfileBuffer = AllocateZeroPool (ProfileSize); - if (ProfileBuffer == 0) { + if (ProfileBuffer == NULL) { Status = EFI_OUT_OF_RESOURCES; Print (L"SmramProfile: AllocateZeroPool (0x%x) for profile buffer - %r\n", ProfileSize, Status); - return Status; + goto Done; } CommHeader = (EFI_SMM_COMMUNICATE_HEADER *) &CommBuffer[0]; @@ -752,9 +1285,9 @@ GetSmramProfileData ( ASSERT_EFI_ERROR (Status); if (CommGetProfileData->Header.ReturnStatus != 0) { - FreePool (ProfileBuffer); + Status = EFI_SUCCESS; Print (L"GetProfileData - 0x%x\n", CommGetProfileData->Header.ReturnStatus); - return EFI_SUCCESS; + goto Done; } CopyMem ((UINT8 *) ProfileBuffer + Offset, (VOID *) (UINTN) CommGetProfileData->ProfileBuffer, (UINTN) CommGetProfileData->ProfileSize); } @@ -762,21 +1295,52 @@ GetSmramProfileData ( Print (L"SmramProfileSize - 0x%x\n", ProfileSize); Print (L"======= SmramProfile begin =======\n"); - DumpMemoryProfile ((PHYSICAL_ADDRESS) (UINTN) ProfileBuffer, ProfileSize); + DumpMemoryProfile ((PHYSICAL_ADDRESS) (UINTN) ProfileBuffer, ProfileSize, TRUE); + + // + // Dump summary information + // + MemoryProfileContextSummaryData = CreateContextSummaryData ((PHYSICAL_ADDRESS) (UINTN) ProfileBuffer, ProfileSize); + if (MemoryProfileContextSummaryData != NULL) { + DumpContextSummaryData (MemoryProfileContextSummaryData, TRUE); + DestroyContextSummaryData (MemoryProfileContextSummaryData); + } + Print (L"======= SmramProfile end =======\n\n\n"); - FreePool (ProfileBuffer); +Done: + if (ProfileBuffer != NULL) { + FreePool (ProfileBuffer); + } - return EFI_SUCCESS; + // + // Restore recording state if needed. + // + if (RecordingState == MEMORY_PROFILE_RECORDING_ENABLE) { + CommHeader = (EFI_SMM_COMMUNICATE_HEADER *) &CommBuffer[0]; + CopyMem (&CommHeader->HeaderGuid, &gEdkiiMemoryProfileGuid, sizeof (gEdkiiMemoryProfileGuid)); + CommHeader->MessageLength = sizeof (SMRAM_PROFILE_PARAMETER_RECORDING_STATE); + + CommRecordingState = (SMRAM_PROFILE_PARAMETER_RECORDING_STATE *) &CommBuffer[OFFSET_OF (EFI_SMM_COMMUNICATE_HEADER, Data)]; + CommRecordingState->Header.Command = SMRAM_PROFILE_COMMAND_SET_RECORDING_STATE; + CommRecordingState->Header.DataLength = sizeof (*CommRecordingState); + CommRecordingState->Header.ReturnStatus = (UINT64)-1; + CommRecordingState->RecordingState = MEMORY_PROFILE_RECORDING_ENABLE; + + CommSize = sizeof (EFI_GUID) + sizeof (UINTN) + CommHeader->MessageLength; + SmmCommunication->Communicate (SmmCommunication, CommBuffer, &CommSize); + } + + return Status; } /** 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] 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. @@ -788,7 +1352,7 @@ UefiMain ( IN EFI_SYSTEM_TABLE *SystemTable ) { - EFI_STATUS Status; + EFI_STATUS Status; Status = GetUefiMemoryProfileData (); if (EFI_ERROR (Status)) { diff --git a/MdeModulePkg/Application/MemoryProfileInfo/MemoryProfileInfo.inf b/MdeModulePkg/Application/MemoryProfileInfo/MemoryProfileInfo.inf index a1bc6752f0..c512a3f651 100644 --- a/MdeModulePkg/Application/MemoryProfileInfo/MemoryProfileInfo.inf +++ b/MdeModulePkg/Application/MemoryProfileInfo/MemoryProfileInfo.inf @@ -46,9 +46,8 @@ UefiLib MemoryAllocationLib DxeServicesLib - PeCoffGetEntryPointLib PrintLib - + [Guids] ## SOMETIMES_CONSUMES ## GUID # Locate protocol ## SOMETIMES_CONSUMES ## GUID # SmiHandlerRegister diff --git a/MdeModulePkg/Application/VariableInfo/VariableInfo.c b/MdeModulePkg/Application/VariableInfo/VariableInfo.c index df91c1451c..a88b7f1ec4 100644 --- a/MdeModulePkg/Application/VariableInfo/VariableInfo.c +++ b/MdeModulePkg/Application/VariableInfo/VariableInfo.c @@ -104,6 +104,7 @@ PrintInfoFromSmm ( } CommBuffer = NULL; + RealCommSize = 0; Status = EfiGetSystemConfigurationTable ( &gEdkiiPiSmmCommunicationRegionTableGuid, (VOID **) &PiSmmCommunicationRegionTable diff --git a/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHcDxe.c b/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHcDxe.c index ed6b557347..0be081dad0 100644 --- a/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHcDxe.c +++ b/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHcDxe.c @@ -238,6 +238,7 @@ SdMmcPciHcEnumerateDevice ( LIST_ENTRY *Link; LIST_ENTRY *NextLink; SD_MMC_HC_TRB *Trb; + EFI_TPL OldTpl; Private = (SD_MMC_HC_PRIVATE_DATA*)Context; @@ -251,6 +252,7 @@ SdMmcPciHcEnumerateDevice ( // // Signal all async task events at the slot with EFI_NO_MEDIA status. // + OldTpl = gBS->RaiseTPL (TPL_NOTIFY); for (Link = GetFirstNode (&Private->Queue); !IsNull (&Private->Queue, Link); Link = NextLink) { @@ -263,6 +265,7 @@ SdMmcPciHcEnumerateDevice ( SdMmcFreeTrb (Trb); } } + gBS->RestoreTPL (OldTpl); // // Notify the upper layer the connect state change through ReinstallProtocolInterface. // @@ -665,7 +668,7 @@ SdMmcPciHcDriverBindingStart ( // Status = gBS->CreateEvent ( EVT_TIMER | EVT_NOTIFY_SIGNAL, - TPL_CALLBACK, + TPL_NOTIFY, ProcessAsyncTaskList, Private, &Private->TimerEvent @@ -961,7 +964,7 @@ SdMmcPassThruPassThru ( // Wait async I/O list is empty before execute sync I/O operation. // while (TRUE) { - OldTpl = gBS->RaiseTPL (TPL_CALLBACK); + OldTpl = gBS->RaiseTPL (TPL_NOTIFY); if (IsListEmpty (&Private->Queue)) { gBS->RestoreTPL (OldTpl); break; @@ -1273,7 +1276,7 @@ SdMmcPassThruResetDevice ( // // Free all async I/O requests in the queue // - OldTpl = gBS->RaiseTPL (TPL_CALLBACK); + OldTpl = gBS->RaiseTPL (TPL_NOTIFY); for (Link = GetFirstNode (&Private->Queue); !IsNull (&Private->Queue, Link); diff --git a/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHci.c b/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHci.c index 8978182f9e..b4ff2af019 100644 --- a/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHci.c +++ b/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHci.c @@ -1315,7 +1315,7 @@ SdMmcCreateTrb ( } if (Event != NULL) { - OldTpl = gBS->RaiseTPL (TPL_CALLBACK); + OldTpl = gBS->RaiseTPL (TPL_NOTIFY); InsertTailList (&Private->Queue, &Trb->TrbList); gBS->RestoreTPL (OldTpl); } diff --git a/MdeModulePkg/Bus/Sd/EmmcDxe/EmmcBlockIo.c b/MdeModulePkg/Bus/Sd/EmmcDxe/EmmcBlockIo.c index 5fe710dbb5..fc705e17d5 100644 --- a/MdeModulePkg/Bus/Sd/EmmcDxe/EmmcBlockIo.c +++ b/MdeModulePkg/Bus/Sd/EmmcDxe/EmmcBlockIo.c @@ -339,7 +339,7 @@ EmmcSetExtCsd ( } SetExtCsdReq->Signature = EMMC_REQUEST_SIGNATURE; - OldTpl = gBS->RaiseTPL (TPL_CALLBACK); + OldTpl = gBS->RaiseTPL (TPL_NOTIFY); InsertTailList (&Partition->Queue, &SetExtCsdReq->Link); gBS->RestoreTPL (OldTpl); SetExtCsdReq->Packet.SdMmcCmdBlk = &SetExtCsdReq->SdMmcCmdBlk; @@ -361,7 +361,7 @@ EmmcSetExtCsd ( if ((Token != NULL) && (Token->Event != NULL)) { Status = gBS->CreateEvent ( EVT_NOTIFY_SIGNAL, - TPL_CALLBACK, + TPL_NOTIFY, AsyncIoCallback, SetExtCsdReq, &SetExtCsdReq->Event @@ -382,7 +382,7 @@ Error: // The request and event will be freed in asynchronous callback for success case. // if (EFI_ERROR (Status) && (SetExtCsdReq != NULL)) { - OldTpl = gBS->RaiseTPL (TPL_CALLBACK); + OldTpl = gBS->RaiseTPL (TPL_NOTIFY); RemoveEntryList (&SetExtCsdReq->Link); gBS->RestoreTPL (OldTpl); if (SetExtCsdReq->Event != NULL) { @@ -395,7 +395,7 @@ Error: // For synchronous operation, free request whatever the execution result is. // if (SetExtCsdReq != NULL) { - OldTpl = gBS->RaiseTPL (TPL_CALLBACK); + OldTpl = gBS->RaiseTPL (TPL_NOTIFY); RemoveEntryList (&SetExtCsdReq->Link); gBS->RestoreTPL (OldTpl); FreePool (SetExtCsdReq); @@ -445,7 +445,7 @@ EmmcSetBlkCount ( } SetBlkCntReq->Signature = EMMC_REQUEST_SIGNATURE; - OldTpl = gBS->RaiseTPL (TPL_CALLBACK); + OldTpl = gBS->RaiseTPL (TPL_NOTIFY); InsertTailList (&Partition->Queue, &SetBlkCntReq->Link); gBS->RestoreTPL (OldTpl); SetBlkCntReq->Packet.SdMmcCmdBlk = &SetBlkCntReq->SdMmcCmdBlk; @@ -463,7 +463,7 @@ EmmcSetBlkCount ( if ((Token != NULL) && (Token->Event != NULL)) { Status = gBS->CreateEvent ( EVT_NOTIFY_SIGNAL, - TPL_CALLBACK, + TPL_NOTIFY, AsyncIoCallback, SetBlkCntReq, &SetBlkCntReq->Event @@ -484,7 +484,7 @@ Error: // The request and event will be freed in asynchronous callback for success case. // if (EFI_ERROR (Status) && (SetBlkCntReq != NULL)) { - OldTpl = gBS->RaiseTPL (TPL_CALLBACK); + OldTpl = gBS->RaiseTPL (TPL_NOTIFY); RemoveEntryList (&SetBlkCntReq->Link); gBS->RestoreTPL (OldTpl); if (SetBlkCntReq->Event != NULL) { @@ -497,7 +497,7 @@ Error: // For synchronous operation, free request whatever the execution result is. // if (SetBlkCntReq != NULL) { - OldTpl = gBS->RaiseTPL (TPL_CALLBACK); + OldTpl = gBS->RaiseTPL (TPL_NOTIFY); RemoveEntryList (&SetBlkCntReq->Link); gBS->RestoreTPL (OldTpl); FreePool (SetBlkCntReq); @@ -562,7 +562,7 @@ EmmcProtocolInOut ( } ProtocolReq->Signature = EMMC_REQUEST_SIGNATURE; - OldTpl = gBS->RaiseTPL (TPL_CALLBACK); + OldTpl = gBS->RaiseTPL (TPL_NOTIFY); InsertTailList (&Partition->Queue, &ProtocolReq->Link); gBS->RestoreTPL (OldTpl); ProtocolReq->Packet.SdMmcCmdBlk = &ProtocolReq->SdMmcCmdBlk; @@ -596,7 +596,7 @@ EmmcProtocolInOut ( if ((Token != NULL) && (Token->Event != NULL)) { Status = gBS->CreateEvent ( EVT_NOTIFY_SIGNAL, - TPL_CALLBACK, + TPL_NOTIFY, AsyncIoCallback, ProtocolReq, &ProtocolReq->Event @@ -617,7 +617,7 @@ Error: // The request and event will be freed in asynchronous callback for success case. // if (EFI_ERROR (Status) && (ProtocolReq != NULL)) { - OldTpl = gBS->RaiseTPL (TPL_CALLBACK); + OldTpl = gBS->RaiseTPL (TPL_NOTIFY); RemoveEntryList (&ProtocolReq->Link); gBS->RestoreTPL (OldTpl); if (ProtocolReq->Event != NULL) { @@ -630,7 +630,7 @@ Error: // For synchronous operation, free request whatever the execution result is. // if (ProtocolReq != NULL) { - OldTpl = gBS->RaiseTPL (TPL_CALLBACK); + OldTpl = gBS->RaiseTPL (TPL_NOTIFY); RemoveEntryList (&ProtocolReq->Link); gBS->RestoreTPL (OldTpl); FreePool (ProtocolReq); @@ -688,7 +688,7 @@ EmmcRwMultiBlocks ( } RwMultiBlkReq->Signature = EMMC_REQUEST_SIGNATURE; - OldTpl = gBS->RaiseTPL (TPL_CALLBACK); + OldTpl = gBS->RaiseTPL (TPL_NOTIFY); InsertTailList (&Partition->Queue, &RwMultiBlkReq->Link); gBS->RestoreTPL (OldTpl); RwMultiBlkReq->Packet.SdMmcCmdBlk = &RwMultiBlkReq->SdMmcCmdBlk; @@ -730,7 +730,7 @@ EmmcRwMultiBlocks ( if ((Token != NULL) && (Token->Event != NULL)) { Status = gBS->CreateEvent ( EVT_NOTIFY_SIGNAL, - TPL_CALLBACK, + TPL_NOTIFY, AsyncIoCallback, RwMultiBlkReq, &RwMultiBlkReq->Event @@ -751,7 +751,7 @@ Error: // The request and event will be freed in asynchronous callback for success case. // if (EFI_ERROR (Status) && (RwMultiBlkReq != NULL)) { - OldTpl = gBS->RaiseTPL (TPL_CALLBACK); + OldTpl = gBS->RaiseTPL (TPL_NOTIFY); RemoveEntryList (&RwMultiBlkReq->Link); gBS->RestoreTPL (OldTpl); if (RwMultiBlkReq->Event != NULL) { @@ -764,7 +764,7 @@ Error: // For synchronous operation, free request whatever the execution result is. // if (RwMultiBlkReq != NULL) { - OldTpl = gBS->RaiseTPL (TPL_CALLBACK); + OldTpl = gBS->RaiseTPL (TPL_NOTIFY); RemoveEntryList (&RwMultiBlkReq->Link); gBS->RestoreTPL (OldTpl); FreePool (RwMultiBlkReq); @@ -901,7 +901,7 @@ EmmcReadWrite ( if (EFI_ERROR (Status)) { return Status; } - DEBUG ((EFI_D_INFO, "Emmc%a(): Lba 0x%x BlkNo 0x%x Event %p with %r\n", IsRead ? "Read" : "Write", Lba, BlockNum, Token->Event, Status)); + DEBUG ((EFI_D_INFO, "Emmc%a(): Part %d Lba 0x%x BlkNo 0x%x Event %p with %r\n", IsRead ? "Read " : "Write", Partition->PartitionType, Lba, BlockNum, Token ? Token->Event : NULL, Status)); Lba += BlockNum; Buffer = (UINT8*)Buffer + BufferSize; @@ -1069,7 +1069,7 @@ EmmcResetEx ( Partition = EMMC_PARTITION_DATA_FROM_BLKIO2 (This); - OldTpl = gBS->RaiseTPL (TPL_CALLBACK); + OldTpl = gBS->RaiseTPL (TPL_NOTIFY); for (Link = GetFirstNode (&Partition->Queue); !IsNull (&Partition->Queue, Link); Link = NextLink) { @@ -1629,7 +1629,7 @@ EmmcEraseBlockStart ( } EraseBlockStart->Signature = EMMC_REQUEST_SIGNATURE; - OldTpl = gBS->RaiseTPL (TPL_CALLBACK); + OldTpl = gBS->RaiseTPL (TPL_NOTIFY); InsertTailList (&Partition->Queue, &EraseBlockStart->Link); gBS->RestoreTPL (OldTpl); EraseBlockStart->Packet.SdMmcCmdBlk = &EraseBlockStart->SdMmcCmdBlk; @@ -1652,7 +1652,7 @@ EmmcEraseBlockStart ( if ((Token != NULL) && (Token->Event != NULL)) { Status = gBS->CreateEvent ( EVT_NOTIFY_SIGNAL, - TPL_CALLBACK, + TPL_NOTIFY, AsyncIoCallback, EraseBlockStart, &EraseBlockStart->Event @@ -1673,7 +1673,9 @@ Error: // The request and event will be freed in asynchronous callback for success case. // if (EFI_ERROR (Status) && (EraseBlockStart != NULL)) { + OldTpl = gBS->RaiseTPL (TPL_NOTIFY); RemoveEntryList (&EraseBlockStart->Link); + gBS->RestoreTPL (OldTpl); if (EraseBlockStart->Event != NULL) { gBS->CloseEvent (EraseBlockStart->Event); } @@ -1684,7 +1686,9 @@ Error: // For synchronous operation, free request whatever the execution result is. // if (EraseBlockStart != NULL) { + OldTpl = gBS->RaiseTPL (TPL_NOTIFY); RemoveEntryList (&EraseBlockStart->Link); + gBS->RestoreTPL (OldTpl); FreePool (EraseBlockStart); } } @@ -1732,7 +1736,7 @@ EmmcEraseBlockEnd ( } EraseBlockEnd->Signature = EMMC_REQUEST_SIGNATURE; - OldTpl = gBS->RaiseTPL (TPL_CALLBACK); + OldTpl = gBS->RaiseTPL (TPL_NOTIFY); InsertTailList (&Partition->Queue, &EraseBlockEnd->Link); gBS->RestoreTPL (OldTpl); EraseBlockEnd->Packet.SdMmcCmdBlk = &EraseBlockEnd->SdMmcCmdBlk; @@ -1755,7 +1759,7 @@ EmmcEraseBlockEnd ( if ((Token != NULL) && (Token->Event != NULL)) { Status = gBS->CreateEvent ( EVT_NOTIFY_SIGNAL, - TPL_CALLBACK, + TPL_NOTIFY, AsyncIoCallback, EraseBlockEnd, &EraseBlockEnd->Event @@ -1776,7 +1780,9 @@ Error: // The request and event will be freed in asynchronous callback for success case. // if (EFI_ERROR (Status) && (EraseBlockEnd != NULL)) { + OldTpl = gBS->RaiseTPL (TPL_NOTIFY); RemoveEntryList (&EraseBlockEnd->Link); + gBS->RestoreTPL (OldTpl); if (EraseBlockEnd->Event != NULL) { gBS->CloseEvent (EraseBlockEnd->Event); } @@ -1787,7 +1793,9 @@ Error: // For synchronous operation, free request whatever the execution result is. // if (EraseBlockEnd != NULL) { + OldTpl = gBS->RaiseTPL (TPL_NOTIFY); RemoveEntryList (&EraseBlockEnd->Link); + gBS->RestoreTPL (OldTpl); FreePool (EraseBlockEnd); } } @@ -1833,7 +1841,7 @@ EmmcEraseBlock ( } EraseBlock->Signature = EMMC_REQUEST_SIGNATURE; - OldTpl = gBS->RaiseTPL (TPL_CALLBACK); + OldTpl = gBS->RaiseTPL (TPL_NOTIFY); InsertTailList (&Partition->Queue, &EraseBlock->Link); gBS->RestoreTPL (OldTpl); EraseBlock->Packet.SdMmcCmdBlk = &EraseBlock->SdMmcCmdBlk; @@ -1850,7 +1858,7 @@ EmmcEraseBlock ( if ((Token != NULL) && (Token->Event != NULL)) { Status = gBS->CreateEvent ( EVT_NOTIFY_SIGNAL, - TPL_CALLBACK, + TPL_NOTIFY, AsyncIoCallback, EraseBlock, &EraseBlock->Event @@ -1871,7 +1879,9 @@ Error: // The request and event will be freed in asynchronous callback for success case. // if (EFI_ERROR (Status) && (EraseBlock != NULL)) { + OldTpl = gBS->RaiseTPL (TPL_NOTIFY); RemoveEntryList (&EraseBlock->Link); + gBS->RestoreTPL (OldTpl); if (EraseBlock->Event != NULL) { gBS->CloseEvent (EraseBlock->Event); } @@ -1882,7 +1892,9 @@ Error: // For synchronous operation, free request whatever the execution result is. // if (EraseBlock != NULL) { + OldTpl = gBS->RaiseTPL (TPL_NOTIFY); RemoveEntryList (&EraseBlock->Link); + gBS->RestoreTPL (OldTpl); FreePool (EraseBlock); } } diff --git a/MdeModulePkg/Bus/Sd/EmmcDxe/EmmcDxe.c b/MdeModulePkg/Bus/Sd/EmmcDxe/EmmcDxe.c index d3602a5000..5040882d62 100644 --- a/MdeModulePkg/Bus/Sd/EmmcDxe/EmmcDxe.c +++ b/MdeModulePkg/Bus/Sd/EmmcDxe/EmmcDxe.c @@ -443,77 +443,60 @@ InstallProtocolOnPartition ( // // Install BlkIo/BlkIo2/Ssp for the specified partition // - Status = gBS->InstallMultipleProtocolInterfaces ( - &Partition->Handle, - &gEfiDevicePathProtocolGuid, - Partition->DevicePath, - &gEfiBlockIoProtocolGuid, - &Partition->BlockIo, - &gEfiBlockIo2ProtocolGuid, - &Partition->BlockIo2, - NULL - ); - if (EFI_ERROR (Status)) { - goto Error; - } - if (Partition->PartitionType != EmmcPartitionRPMB) { - Status = gBS->InstallProtocolInterface ( + Status = gBS->InstallMultipleProtocolInterfaces ( &Partition->Handle, + &gEfiDevicePathProtocolGuid, + Partition->DevicePath, + &gEfiBlockIoProtocolGuid, + &Partition->BlockIo, + &gEfiBlockIo2ProtocolGuid, + &Partition->BlockIo2, &gEfiEraseBlockProtocolGuid, - EFI_NATIVE_INTERFACE, - &Partition->EraseBlock + &Partition->EraseBlock, + NULL ); if (EFI_ERROR (Status)) { - gBS->UninstallMultipleProtocolInterfaces ( - &Partition->Handle, - &gEfiDevicePathProtocolGuid, - Partition->DevicePath, - &gEfiBlockIoProtocolGuid, - &Partition->BlockIo, - &gEfiBlockIo2ProtocolGuid, - &Partition->BlockIo2, - NULL - ); goto Error; } - } - if (((Partition->PartitionType == EmmcPartitionUserData) || - (Partition->PartitionType == EmmcPartitionBoot1) || - (Partition->PartitionType == EmmcPartitionBoot2)) && - ((Device->Csd.Ccc & BIT10) != 0)) { - Status = gBS->InstallProtocolInterface ( - &Partition->Handle, - &gEfiStorageSecurityCommandProtocolGuid, - EFI_NATIVE_INTERFACE, - &Partition->StorageSecurity - ); - if (EFI_ERROR (Status)) { - gBS->UninstallMultipleProtocolInterfaces ( - &Partition->Handle, - &gEfiDevicePathProtocolGuid, - Partition->DevicePath, - &gEfiBlockIoProtocolGuid, - &Partition->BlockIo, - &gEfiBlockIo2ProtocolGuid, - &Partition->BlockIo2, - &gEfiEraseBlockProtocolGuid, - &Partition->EraseBlock, - NULL - ); - goto Error; + if (((Partition->PartitionType == EmmcPartitionUserData) || + (Partition->PartitionType == EmmcPartitionBoot1) || + (Partition->PartitionType == EmmcPartitionBoot2)) && + ((Device->Csd.Ccc & BIT10) != 0)) { + Status = gBS->InstallProtocolInterface ( + &Partition->Handle, + &gEfiStorageSecurityCommandProtocolGuid, + EFI_NATIVE_INTERFACE, + &Partition->StorageSecurity + ); + if (EFI_ERROR (Status)) { + gBS->UninstallMultipleProtocolInterfaces ( + &Partition->Handle, + &gEfiDevicePathProtocolGuid, + Partition->DevicePath, + &gEfiBlockIoProtocolGuid, + &Partition->BlockIo, + &gEfiBlockIo2ProtocolGuid, + &Partition->BlockIo2, + &gEfiEraseBlockProtocolGuid, + &Partition->EraseBlock, + NULL + ); + goto Error; + } } + + gBS->OpenProtocol ( + Device->Private->Controller, + &gEfiSdMmcPassThruProtocolGuid, + (VOID **) &(Device->Private->PassThru), + Device->Private->DriverBindingHandle, + Partition->Handle, + EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER + ); } - gBS->OpenProtocol ( - Device->Private->Controller, - &gEfiSdMmcPassThruProtocolGuid, - (VOID **) &(Device->Private->PassThru), - Device->Private->DriverBindingHandle, - Partition->Handle, - EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER - ); } else { Status = EFI_INVALID_PARAMETER; } @@ -993,7 +976,6 @@ EmmcDxeDriverBindingStop ( EFI_BLOCK_IO_PROTOCOL *BlockIo; EFI_BLOCK_IO2_PROTOCOL *BlockIo2; EFI_STORAGE_SECURITY_COMMAND_PROTOCOL *StorageSecurity; - EFI_ERASE_BLOCK_PROTOCOL *EraseBlock; LIST_ENTRY *Link; LIST_ENTRY *NextLink; EMMC_REQUEST *Request; @@ -1120,6 +1102,8 @@ EmmcDxeDriverBindingStop ( &Partition->BlockIo, &gEfiBlockIo2ProtocolGuid, &Partition->BlockIo2, + &gEfiEraseBlockProtocolGuid, + &Partition->EraseBlock, NULL ); if (EFI_ERROR (Status)) { @@ -1135,38 +1119,6 @@ EmmcDxeDriverBindingStop ( continue; } - // - // If Erase Block Protocol is installed, then uninstall this protocol. - // - Status = gBS->OpenProtocol ( - ChildHandleBuffer[Index], - &gEfiEraseBlockProtocolGuid, - (VOID **) &EraseBlock, - This->DriverBindingHandle, - Controller, - EFI_OPEN_PROTOCOL_GET_PROTOCOL - ); - - if (!EFI_ERROR (Status)) { - Status = gBS->UninstallProtocolInterface ( - ChildHandleBuffer[Index], - &gEfiEraseBlockProtocolGuid, - &Partition->EraseBlock - ); - if (EFI_ERROR (Status)) { - gBS->OpenProtocol ( - Controller, - &gEfiSdMmcPassThruProtocolGuid, - (VOID **) &Partition->Device->Private->PassThru, - This->DriverBindingHandle, - ChildHandleBuffer[Index], - EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER - ); - AllChildrenStopped = FALSE; - continue; - } - } - // // If Storage Security Command Protocol is installed, then uninstall this protocol. // diff --git a/MdeModulePkg/Bus/Sd/SdDxe/SdBlockIo.c b/MdeModulePkg/Bus/Sd/SdDxe/SdBlockIo.c index d8b9459c63..516c3e7042 100644 --- a/MdeModulePkg/Bus/Sd/SdDxe/SdBlockIo.c +++ b/MdeModulePkg/Bus/Sd/SdDxe/SdBlockIo.c @@ -340,7 +340,7 @@ SdRwSingleBlock ( } RwSingleBlkReq->Signature = SD_REQUEST_SIGNATURE; - OldTpl = gBS->RaiseTPL (TPL_CALLBACK); + OldTpl = gBS->RaiseTPL (TPL_NOTIFY); InsertTailList (&Device->Queue, &RwSingleBlkReq->Link); gBS->RestoreTPL (OldTpl); RwSingleBlkReq->Packet.SdMmcCmdBlk = &RwSingleBlkReq->SdMmcCmdBlk; @@ -382,7 +382,7 @@ SdRwSingleBlock ( if ((Token != NULL) && (Token->Event != NULL)) { Status = gBS->CreateEvent ( EVT_NOTIFY_SIGNAL, - TPL_CALLBACK, + TPL_NOTIFY, AsyncIoCallback, RwSingleBlkReq, &RwSingleBlkReq->Event @@ -403,7 +403,9 @@ Error: // The request and event will be freed in asynchronous callback for success case. // if (EFI_ERROR (Status) && (RwSingleBlkReq != NULL)) { + OldTpl = gBS->RaiseTPL (TPL_NOTIFY); RemoveEntryList (&RwSingleBlkReq->Link); + gBS->RestoreTPL (OldTpl); if (RwSingleBlkReq->Event != NULL) { gBS->CloseEvent (RwSingleBlkReq->Event); } @@ -414,7 +416,9 @@ Error: // For synchronous operation, free request whatever the execution result is. // if (RwSingleBlkReq != NULL) { + OldTpl = gBS->RaiseTPL (TPL_NOTIFY); RemoveEntryList (&RwSingleBlkReq->Link); + gBS->RestoreTPL (OldTpl); FreePool (RwSingleBlkReq); } } @@ -468,7 +472,7 @@ SdRwMultiBlocks ( } RwMultiBlkReq->Signature = SD_REQUEST_SIGNATURE; - OldTpl = gBS->RaiseTPL (TPL_CALLBACK); + OldTpl = gBS->RaiseTPL (TPL_NOTIFY); InsertTailList (&Device->Queue, &RwMultiBlkReq->Link); gBS->RestoreTPL (OldTpl); RwMultiBlkReq->Packet.SdMmcCmdBlk = &RwMultiBlkReq->SdMmcCmdBlk; @@ -510,7 +514,7 @@ SdRwMultiBlocks ( if ((Token != NULL) && (Token->Event != NULL)) { Status = gBS->CreateEvent ( EVT_NOTIFY_SIGNAL, - TPL_CALLBACK, + TPL_NOTIFY, AsyncIoCallback, RwMultiBlkReq, &RwMultiBlkReq->Event @@ -531,7 +535,9 @@ Error: // The request and event will be freed in asynchronous callback for success case. // if (EFI_ERROR (Status) && (RwMultiBlkReq != NULL)) { + OldTpl = gBS->RaiseTPL (TPL_NOTIFY); RemoveEntryList (&RwMultiBlkReq->Link); + gBS->RestoreTPL (OldTpl); if (RwMultiBlkReq->Event != NULL) { gBS->CloseEvent (RwMultiBlkReq->Event); } @@ -542,7 +548,9 @@ Error: // For synchronous operation, free request whatever the execution result is. // if (RwMultiBlkReq != NULL) { + OldTpl = gBS->RaiseTPL (TPL_NOTIFY); RemoveEntryList (&RwMultiBlkReq->Link); + gBS->RestoreTPL (OldTpl); FreePool (RwMultiBlkReq); } } @@ -830,7 +838,7 @@ SdResetEx ( Device = SD_DEVICE_DATA_FROM_BLKIO2 (This); - OldTpl = gBS->RaiseTPL (TPL_CALLBACK); + OldTpl = gBS->RaiseTPL (TPL_NOTIFY); for (Link = GetFirstNode (&Device->Queue); !IsNull (&Device->Queue, Link); Link = NextLink) { @@ -1007,7 +1015,7 @@ SdEraseBlockStart ( } EraseBlockStart->Signature = SD_REQUEST_SIGNATURE; - OldTpl = gBS->RaiseTPL (TPL_CALLBACK); + OldTpl = gBS->RaiseTPL (TPL_NOTIFY); InsertTailList (&Device->Queue, &EraseBlockStart->Link); gBS->RestoreTPL (OldTpl); EraseBlockStart->Packet.SdMmcCmdBlk = &EraseBlockStart->SdMmcCmdBlk; @@ -1030,7 +1038,7 @@ SdEraseBlockStart ( if ((Token != NULL) && (Token->Event != NULL)) { Status = gBS->CreateEvent ( EVT_NOTIFY_SIGNAL, - TPL_CALLBACK, + TPL_NOTIFY, AsyncIoCallback, EraseBlockStart, &EraseBlockStart->Event @@ -1051,7 +1059,9 @@ Error: // The request and event will be freed in asynchronous callback for success case. // if (EFI_ERROR (Status) && (EraseBlockStart != NULL)) { + OldTpl = gBS->RaiseTPL (TPL_NOTIFY); RemoveEntryList (&EraseBlockStart->Link); + gBS->RestoreTPL (OldTpl); if (EraseBlockStart->Event != NULL) { gBS->CloseEvent (EraseBlockStart->Event); } @@ -1062,7 +1072,9 @@ Error: // For synchronous operation, free request whatever the execution result is. // if (EraseBlockStart != NULL) { + OldTpl = gBS->RaiseTPL (TPL_NOTIFY); RemoveEntryList (&EraseBlockStart->Link); + gBS->RestoreTPL (OldTpl); FreePool (EraseBlockStart); } } @@ -1107,7 +1119,7 @@ SdEraseBlockEnd ( } EraseBlockEnd->Signature = SD_REQUEST_SIGNATURE; - OldTpl = gBS->RaiseTPL (TPL_CALLBACK); + OldTpl = gBS->RaiseTPL (TPL_NOTIFY); InsertTailList (&Device->Queue, &EraseBlockEnd->Link); gBS->RestoreTPL (OldTpl); EraseBlockEnd->Packet.SdMmcCmdBlk = &EraseBlockEnd->SdMmcCmdBlk; @@ -1130,7 +1142,7 @@ SdEraseBlockEnd ( if ((Token != NULL) && (Token->Event != NULL)) { Status = gBS->CreateEvent ( EVT_NOTIFY_SIGNAL, - TPL_CALLBACK, + TPL_NOTIFY, AsyncIoCallback, EraseBlockEnd, &EraseBlockEnd->Event @@ -1151,7 +1163,9 @@ Error: // The request and event will be freed in asynchronous callback for success case. // if (EFI_ERROR (Status) && (EraseBlockEnd != NULL)) { + OldTpl = gBS->RaiseTPL (TPL_NOTIFY); RemoveEntryList (&EraseBlockEnd->Link); + gBS->RestoreTPL (OldTpl); if (EraseBlockEnd->Event != NULL) { gBS->CloseEvent (EraseBlockEnd->Event); } @@ -1162,7 +1176,9 @@ Error: // For synchronous operation, free request whatever the execution result is. // if (EraseBlockEnd != NULL) { + OldTpl = gBS->RaiseTPL (TPL_NOTIFY); RemoveEntryList (&EraseBlockEnd->Link); + gBS->RestoreTPL (OldTpl); FreePool (EraseBlockEnd); } } @@ -1205,7 +1221,7 @@ SdEraseBlock ( } EraseBlock->Signature = SD_REQUEST_SIGNATURE; - OldTpl = gBS->RaiseTPL (TPL_CALLBACK); + OldTpl = gBS->RaiseTPL (TPL_NOTIFY); InsertTailList (&Device->Queue, &EraseBlock->Link); gBS->RestoreTPL (OldTpl); EraseBlock->Packet.SdMmcCmdBlk = &EraseBlock->SdMmcCmdBlk; @@ -1222,7 +1238,7 @@ SdEraseBlock ( if ((Token != NULL) && (Token->Event != NULL)) { Status = gBS->CreateEvent ( EVT_NOTIFY_SIGNAL, - TPL_CALLBACK, + TPL_NOTIFY, AsyncIoCallback, EraseBlock, &EraseBlock->Event @@ -1243,7 +1259,9 @@ Error: // The request and event will be freed in asynchronous callback for success case. // if (EFI_ERROR (Status) && (EraseBlock != NULL)) { + OldTpl = gBS->RaiseTPL (TPL_NOTIFY); RemoveEntryList (&EraseBlock->Link); + gBS->RestoreTPL (OldTpl); if (EraseBlock->Event != NULL) { gBS->CloseEvent (EraseBlock->Event); } @@ -1254,7 +1272,9 @@ Error: // For synchronous operation, free request whatever the execution result is. // if (EraseBlock != NULL) { + OldTpl = gBS->RaiseTPL (TPL_NOTIFY); RemoveEntryList (&EraseBlock->Link); + gBS->RestoreTPL (OldTpl); FreePool (EraseBlock); } } diff --git a/MdeModulePkg/Bus/Sd/SdDxe/SdDxe.c b/MdeModulePkg/Bus/Sd/SdDxe/SdDxe.c index 7c70c60a50..0cf9067701 100644 --- a/MdeModulePkg/Bus/Sd/SdDxe/SdDxe.c +++ b/MdeModulePkg/Bus/Sd/SdDxe/SdDxe.c @@ -800,7 +800,7 @@ SdDxeDriverBindingStop ( // // Free all on-going async tasks. // - OldTpl = gBS->RaiseTPL (TPL_CALLBACK); + OldTpl = gBS->RaiseTPL (TPL_NOTIFY); for (Link = GetFirstNode (&Device->Queue); !IsNull (&Device->Queue, Link); Link = NextLink) { diff --git a/MdeModulePkg/Core/Dxe/DxeMain.h b/MdeModulePkg/Core/Dxe/DxeMain.h index e6b9114d2e..743221f675 100644 --- a/MdeModulePkg/Core/Dxe/DxeMain.h +++ b/MdeModulePkg/Core/Dxe/DxeMain.h @@ -2780,11 +2780,13 @@ MemoryProfileInstallProtocol ( @param DriverEntry Image info. @param FileType Image file type. - @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 RegisterMemoryProfileImage ( IN LOADED_IMAGE_PRIVATE_DATA *DriverEntry, IN EFI_FV_FILETYPE FileType @@ -2795,11 +2797,13 @@ RegisterMemoryProfileImage ( @param DriverEntry Image info. - @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 UnregisterMemoryProfileImage ( IN LOADED_IMAGE_PRIVATE_DATA *DriverEntry ); @@ -2810,20 +2814,31 @@ UnregisterMemoryProfileImage ( @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 CoreUpdateProfile ( IN EFI_PHYSICAL_ADDRESS CallerAddress, IN MEMORY_PROFILE_ACTION Action, IN EFI_MEMORY_TYPE MemoryType, IN UINTN Size, // Valid for AllocatePages/FreePages/AllocatePool - IN VOID *Buffer + IN VOID *Buffer, + IN CHAR8 *ActionString OPTIONAL ); /** diff --git a/MdeModulePkg/Core/Dxe/DxeMain.inf b/MdeModulePkg/Core/Dxe/DxeMain.inf index e3e4d036db..450da579e0 100644 --- a/MdeModulePkg/Core/Dxe/DxeMain.inf +++ b/MdeModulePkg/Core/Dxe/DxeMain.inf @@ -187,6 +187,7 @@ gEfiMdeModulePkgTokenSpaceGuid.PcdMaxEfiSystemTablePointerAddress ## CONSUMES gEfiMdeModulePkgTokenSpaceGuid.PcdMemoryProfileMemoryType ## CONSUMES gEfiMdeModulePkgTokenSpaceGuid.PcdMemoryProfilePropertyMask ## CONSUMES + gEfiMdeModulePkgTokenSpaceGuid.PcdMemoryProfileDriverPath ## CONSUMES gEfiMdeModulePkgTokenSpaceGuid.PcdPropertiesTableEnable ## CONSUMES # [Hob] diff --git a/MdeModulePkg/Core/Dxe/Mem/MemoryProfileRecord.c b/MdeModulePkg/Core/Dxe/Mem/MemoryProfileRecord.c index 6626e10159..14c4959f9f 100644 --- a/MdeModulePkg/Core/Dxe/Mem/MemoryProfileRecord.c +++ b/MdeModulePkg/Core/Dxe/Mem/MemoryProfileRecord.c @@ -17,6 +17,9 @@ #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; MEMORY_PROFILE_CONTEXT Context; @@ -27,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; @@ -58,7 +63,11 @@ GLOBAL_REMOVE_IF_UNREFERENCED MEMORY_PROFILE_CONTEXT_DATA mMemoryProfileContext }; GLOBAL_REMOVE_IF_UNREFERENCED MEMORY_PROFILE_CONTEXT_DATA *mMemoryProfileContextPtr = NULL; -BOOLEAN mMemoryProfileRecordingStatus = FALSE; +EFI_LOCK mMemoryProfileLock = EFI_INITIALIZE_LOCK_VARIABLE (TPL_NOTIFY); +BOOLEAN mMemoryProfileGettingStatus = FALSE; +BOOLEAN mMemoryProfileRecordingEnable = MEMORY_PROFILE_RECORDING_DISABLE; +EFI_DEVICE_PATH_PROTOCOL *mMemoryProfileDriverPath; +UINTN mMemoryProfileDriverPathSize; /** Get memory profile data. @@ -69,6 +78,7 @@ BOOLEAN mMemoryProfileRecordingStatus = FALSE; @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. @@ -90,7 +100,9 @@ ProfileProtocolGetData ( @param[in] ImageSize Image size. @param[in] FileType File type of the image. - @return EFI_SUCCESS Register success. + @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. **/ @@ -112,7 +124,9 @@ ProfileProtocolRegisterImage ( @param[in] ImageBase Image base address. @param[in] ImageSize Image size. - @return EFI_SUCCESS Unregister success. + @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. **/ @@ -125,12 +139,107 @@ ProfileProtocolUnregisterImage ( IN UINT64 ImageSize ); +/** + Get memory profile recording state. + + @param[in] This The EDKII_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 +ProfileProtocolGetRecordingState ( + IN EDKII_MEMORY_PROFILE_PROTOCOL *This, + OUT BOOLEAN *RecordingState + ); + +/** + Set memory profile recording state. + + @param[in] This The EDKII_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 +ProfileProtocolSetRecordingState ( + IN EDKII_MEMORY_PROFILE_PROTOCOL *This, + IN BOOLEAN RecordingState + ); + +/** + Record memory profile of multilevel caller. + + @param[in] This The EDKII_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 +ProfileProtocolRecord ( + IN EDKII_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_MEMORY_PROFILE_PROTOCOL mProfileProtocol = { ProfileProtocolGetData, ProfileProtocolRegisterImage, - ProfileProtocolUnregisterImage + ProfileProtocolUnregisterImage, + ProfileProtocolGetRecordingState, + ProfileProtocolSetRecordingState, + ProfileProtocolRecord, }; +/** + Acquire lock on mMemoryProfileLock. +**/ +VOID +CoreAcquireMemoryProfileLock ( + VOID + ) +{ + CoreAcquireLock (&mMemoryProfileLock); +} + +/** + Release lock on mMemoryProfileLock. +**/ +VOID +CoreReleaseMemoryProfileLock ( + VOID + ) +{ + CoreReleaseLock (&mMemoryProfileLock); +} + /** Return memory profile context. @@ -307,13 +416,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 CoreInternalAllocatePool() that will not update profile for this AllocatePool action. // Status = CoreInternalAllocatePool ( EfiBootServicesData, - sizeof (*DriverInfoData) + sizeof (LIST_ENTRY), + sizeof (*DriverInfoData) + sizeof (LIST_ENTRY) + PdbSize, (VOID **) &DriverInfoData ); if (EFI_ERROR (Status)) { @@ -325,7 +448,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)); @@ -349,6 +472,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 ++; @@ -357,6 +488,65 @@ BuildDriverInfo ( return DriverInfoData; } +/** + 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 (mMemoryProfileDriverPath, mMemoryProfileDriverPathSize)) { + // + // Invalid Device Path means record all. + // + return TRUE; + } + + // + // Record FilePath without END node. + // + FilePathSize = GetDevicePathSize (DriverFilePath) - sizeof(EFI_DEVICE_PATH_PROTOCOL); + + DevicePathInstance = mMemoryProfileDriverPath; + 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 DXE Core to memory profile. @@ -376,6 +566,8 @@ RegisterDxeCore ( EFI_PEI_HOB_POINTERS DxeCoreHob; 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); @@ -394,6 +586,14 @@ RegisterDxeCore ( } ASSERT (DxeCoreHob.Raw != NULL); + FilePath = (MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *) TempBuffer; + EfiInitializeFwVolDevicepathNode (FilePath, &DxeCoreHob.MemoryAllocationModule->ModuleName); + SetDevicePathEndNode (FilePath + 1); + + if (!NeedRecordThisDriver ((EFI_DEVICE_PATH_PROTOCOL *) FilePath)) { + return FALSE; + } + ImageBase = DxeCoreHob.MemoryAllocationModule->MemoryAllocationHeader.MemoryBaseAddress; DriverInfoData = BuildDriverInfo ( ContextData, @@ -433,7 +633,14 @@ MemoryProfileInit ( return; } - mMemoryProfileRecordingStatus = TRUE; + mMemoryProfileGettingStatus = FALSE; + if ((PcdGet8 (PcdMemoryProfilePropertyMask) & BIT7) != 0) { + mMemoryProfileRecordingEnable = MEMORY_PROFILE_RECORDING_DISABLE; + } else { + mMemoryProfileRecordingEnable = MEMORY_PROFILE_RECORDING_ENABLE; + } + mMemoryProfileDriverPathSize = PcdGetSize (PcdMemoryProfileDriverPath); + mMemoryProfileDriverPath = AllocateCopyPool (mMemoryProfileDriverPathSize, PcdGetPtr (PcdMemoryProfileDriverPath)); mMemoryProfileContextPtr = &mMemoryProfileContext; RegisterDxeCore (HobStart, &mMemoryProfileContext); @@ -504,11 +711,13 @@ GetFileNameFromFilePath ( @param DriverEntry Image info. @param FileType Image file type. - @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 RegisterMemoryProfileImage ( IN LOADED_IMAGE_PRIVATE_DATA *DriverEntry, IN EFI_FV_FILETYPE FileType @@ -518,12 +727,16 @@ RegisterMemoryProfileImage ( MEMORY_PROFILE_DRIVER_INFO_DATA *DriverInfoData; if (!IS_UEFI_MEMORY_PROFILE_ENABLED) { - return FALSE; + return EFI_UNSUPPORTED; + } + + if (!NeedRecordThisDriver (DriverEntry->Info.FilePath)) { + return EFI_UNSUPPORTED; } ContextData = GetMemoryProfileContext (); if (ContextData == NULL) { - return FALSE; + return EFI_UNSUPPORTED; } DriverInfoData = BuildDriverInfo ( @@ -536,10 +749,10 @@ RegisterMemoryProfileImage ( FileType ); if (DriverInfoData == NULL) { - return FALSE; + return EFI_OUT_OF_RESOURCES; } - return TRUE; + return EFI_SUCCESS; } /** @@ -586,45 +799,9 @@ GetMemoryProfileDriverInfoByFileNameAndAddress ( return NULL; } -/** - Search dummy image from memory 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) + It will return image, if (Address >= ImageBuffer) AND (Address < ImageBuffer + ImageSize). @param ContextData Memory profile context. @param Address Image or Function address. @@ -661,10 +838,7 @@ GetMemoryProfileDriverInfoFromAddress ( } } - // - // Should never come here. - // - return FindDummyImage (ContextData); + return NULL; } /** @@ -672,11 +846,13 @@ GetMemoryProfileDriverInfoFromAddress ( @param DriverEntry Image info. - @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 UnregisterMemoryProfileImage ( IN LOADED_IMAGE_PRIVATE_DATA *DriverEntry ) @@ -689,12 +865,16 @@ UnregisterMemoryProfileImage ( VOID *EntryPointInImage; if (!IS_UEFI_MEMORY_PROFILE_ENABLED) { - return FALSE; + return EFI_UNSUPPORTED; + } + + if (!NeedRecordThisDriver (DriverEntry->Info.FilePath)) { + return EFI_UNSUPPORTED; } ContextData = GetMemoryProfileContext (); if (ContextData == NULL) { - return FALSE; + return EFI_UNSUPPORTED; } DriverInfoData = NULL; @@ -716,12 +896,13 @@ UnregisterMemoryProfileImage ( 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) { @@ -733,7 +914,7 @@ UnregisterMemoryProfileImage ( CoreInternalFreePool (DriverInfoData, NULL); } - return TRUE; + return EFI_SUCCESS; } /** @@ -803,55 +984,80 @@ GetProfileMemoryIndex ( @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 CoreUpdateProfileAllocate ( 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; UINTN ProfileMemoryIndex; + MEMORY_PROFILE_ACTION BasicAction; + UINTN ActionStringSize; + UINTN ActionStringOccupiedSize; - AllocInfoData = NULL; + BasicAction = Action & MEMORY_PROFILE_ACTION_BASIC_MASK; ContextData = GetMemoryProfileContext (); 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 CoreInternalAllocatePool() that will not update profile for this AllocatePool action. // + AllocInfoData = NULL; Status = CoreInternalAllocatePool ( EfiBootServicesData, - 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; @@ -859,50 +1065,64 @@ CoreUpdateProfileAllocate ( 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]; + // + // Update summary if and only if it is basic action. + // + if (Action == BasicAction) { + ProfileMemoryIndex = GetProfileMemoryIndex (MemoryType); + + 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]; + } } - Context->SequenceCount ++; - return TRUE; + return EFI_SUCCESS; } /** - Get memory profile alloc info from memory profile + Get memory profile alloc info from memory profile. - @param DriverInfoData Driver info - @param Action This Free action - @param Size Buffer size - @param Buffer Buffer address + @param DriverInfoData Driver info. + @param BasicAction This Free basic action. + @param Size Buffer size. + @param Buffer Buffer address. @return Pointer to memory profile alloc info. + **/ 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 ) @@ -924,10 +1144,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))) { @@ -956,11 +1176,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 CoreUpdateProfileFree ( IN PHYSICAL_ADDRESS CallerAddress, IN MEMORY_PROFILE_ACTION Action, @@ -978,114 +1199,140 @@ CoreUpdateProfileFree ( MEMORY_PROFILE_DRIVER_INFO_DATA *ThisDriverInfoData; MEMORY_PROFILE_ALLOC_INFO_DATA *AllocInfoData; UINTN ProfileMemoryIndex; + MEMORY_PROFILE_ACTION BasicAction; + BOOLEAN Found; + + BasicAction = Action & MEMORY_PROFILE_ACTION_BASIC_MASK; ContextData = GetMemoryProfileContext (); 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; - - 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) { + // + // Do not return if DriverInfoData == NULL here, + // because driver A might free memory allocated by driver B. + // + + // + // Need use do-while loop to find all possible records, + // 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) { // - // 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. + // Legal case, because driver A might free memory allocated by driver B, by some protocol. // - return FALSE; - } - } + 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; + } + } - Context = &ContextData->Context; - DriverInfo = &DriverInfoData->DriverInfo; - AllocInfo = &AllocInfoData->AllocInfo; + 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 may 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); + } + } - ProfileMemoryIndex = GetProfileMemoryIndex (AllocInfo->MemoryType); + Found = TRUE; - Context->CurrentTotalUsage -= AllocInfo->Size; - Context->CurrentTotalUsageByType[ProfileMemoryIndex] -= AllocInfo->Size; + Context = &ContextData->Context; + DriverInfo = &DriverInfoData->DriverInfo; + AllocInfo = &AllocInfoData->AllocInfo; - DriverInfo->CurrentUsage -= AllocInfo->Size; - DriverInfo->CurrentUsageByType[ProfileMemoryIndex] -= AllocInfo->Size; - DriverInfo->AllocRecordCount --; + 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); - RemoveEntryList (&AllocInfoData->Link); + Context->CurrentTotalUsage -= AllocInfo->Size; + Context->CurrentTotalUsageByType[ProfileMemoryIndex] -= AllocInfo->Size; - if (Action == MemoryProfileActionFreePages) { - if (AllocInfo->Buffer != (PHYSICAL_ADDRESS) (UINTN) Buffer) { - CoreUpdateProfileAllocate ( - AllocInfo->CallerAddress, - MemoryProfileActionAllocatePages, - AllocInfo->MemoryType, - (UINTN) ((PHYSICAL_ADDRESS) (UINTN) Buffer - AllocInfo->Buffer), - (VOID *) (UINTN) AllocInfo->Buffer - ); - } - if (AllocInfo->Buffer + AllocInfo->Size != ((PHYSICAL_ADDRESS) (UINTN) Buffer + Size)) { - CoreUpdateProfileAllocate ( - AllocInfo->CallerAddress, - MemoryProfileActionAllocatePages, - AllocInfo->MemoryType, - (UINTN) ((AllocInfo->Buffer + AllocInfo->Size) - ((PHYSICAL_ADDRESS) (UINTN) Buffer + Size)), - (VOID *) ((UINTN) Buffer + Size) - ); + DriverInfo->CurrentUsage -= AllocInfo->Size; + DriverInfo->CurrentUsageByType[ProfileMemoryIndex] -= AllocInfo->Size; } - } - // - // Use CoreInternalFreePool() that will not update profile for this FreePool action. - // - CoreInternalFreePool (AllocInfoData, NULL); + RemoveEntryList (&AllocInfoData->Link); + + if (BasicAction == MemoryProfileActionFreePages) { + if (AllocInfo->Buffer != (PHYSICAL_ADDRESS) (UINTN) Buffer) { + CoreUpdateProfileAllocate ( + 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)) { + CoreUpdateProfileAllocate ( + AllocInfo->CallerAddress, + AllocInfo->Action, + AllocInfo->MemoryType, + (UINTN) ((AllocInfo->Buffer + AllocInfo->Size) - ((PHYSICAL_ADDRESS) (UINTN) Buffer + Size)), + (VOID *) ((UINTN) Buffer + Size), + AllocInfoData->ActionString + ); + } + } - return TRUE; + // + // Use CoreInternalFreePool() that will not update profile for this FreePool action. + // + CoreInternalFreePool (AllocInfoData, NULL); + } while (TRUE); } /** @@ -1094,62 +1341,93 @@ CoreUpdateProfileFree ( @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. - - @retval TRUE Profile udpate success. - @retval FALSE Profile update fail. + @param 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. **/ -BOOLEAN +EFI_STATUS +EFIAPI CoreUpdateProfile ( IN PHYSICAL_ADDRESS CallerAddress, IN MEMORY_PROFILE_ACTION Action, IN EFI_MEMORY_TYPE MemoryType, 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_UEFI_MEMORY_PROFILE_ENABLED) { - return FALSE; + return EFI_UNSUPPORTED; } - if (!mMemoryProfileRecordingStatus) { - return FALSE; + if (mMemoryProfileGettingStatus) { + return EFI_ACCESS_DENIED; + } + + if (!mMemoryProfileRecordingEnable) { + return EFI_ABORTED; } // - // Only record limited MemoryType. + // Get the basic action to know how to process the record // - if (!CoreNeedRecordProfile (MemoryType)) { - return FALSE; + BasicAction = Action & MEMORY_PROFILE_ACTION_BASIC_MASK; + + // + // EfiMaxMemoryType means the MemoryType is unknown. + // + if (MemoryType != EfiMaxMemoryType) { + // + // Only record limited MemoryType. + // + if (!CoreNeedRecordProfile (MemoryType)) { + return EFI_UNSUPPORTED; + } } ContextData = GetMemoryProfileContext (); if (ContextData == NULL) { - return FALSE; + return EFI_UNSUPPORTED; } - switch (Action) { + CoreAcquireMemoryProfileLock (); + switch (BasicAction) { case MemoryProfileActionAllocatePages: - CoreUpdateProfileAllocate (CallerAddress, Action, MemoryType, Size, Buffer); + Status = CoreUpdateProfileAllocate (CallerAddress, Action, MemoryType, Size, Buffer, ActionString); break; case MemoryProfileActionFreePages: - CoreUpdateProfileFree (CallerAddress, Action, Size, Buffer); + Status = CoreUpdateProfileFree (CallerAddress, Action, Size, Buffer); break; case MemoryProfileActionAllocatePool: - CoreUpdateProfileAllocate (CallerAddress, Action, MemoryType, Size, Buffer); + Status = CoreUpdateProfileAllocate (CallerAddress, Action, MemoryType, Size, Buffer, ActionString); break; case MemoryProfileActionFreePool: - CoreUpdateProfileFree (CallerAddress, Action, 0, Buffer); + Status = CoreUpdateProfileFree (CallerAddress, Action, 0, Buffer); break; default: ASSERT (FALSE); + Status = EFI_UNSUPPORTED; break; } - return TRUE; + CoreReleaseMemoryProfileLock (); + + return Status; } //////////////////// @@ -1167,8 +1445,11 @@ MemoryProfileGetDataSize ( { 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; @@ -1178,7 +1459,6 @@ MemoryProfileGetDataSize ( } TotalSize = sizeof (MEMORY_PROFILE_CONTEXT); - TotalSize += sizeof (MEMORY_PROFILE_DRIVER_INFO) * (UINTN) ContextData->Context.ImageCount; DriverInfoList = ContextData->DriverInfoList; for (DriverLink = DriverInfoList->ForwardLink; @@ -1190,7 +1470,20 @@ MemoryProfileGetDataSize ( 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; + } } return TotalSize; @@ -1217,6 +1510,8 @@ MemoryProfileCopyData ( LIST_ENTRY *DriverLink; LIST_ENTRY *AllocInfoList; LIST_ENTRY *AllocLink; + UINTN PdbSize; + UINTN ActionStringSize; ContextData = GetMemoryProfileContext (); if (ContextData == NULL) { @@ -1238,7 +1533,11 @@ MemoryProfileCopyData ( MEMORY_PROFILE_DRIVER_INFO_SIGNATURE ); CopyMem (DriverInfo, &DriverInfoData->DriverInfo, sizeof (MEMORY_PROFILE_DRIVER_INFO)); - AllocInfo = (MEMORY_PROFILE_ALLOC_INFO *) (DriverInfo + 1); + if (DriverInfo->PdbStringOffset != 0) { + PdbSize = AsciiStrSize (DriverInfoData->PdbString); + CopyMem ((VOID *) ((UINTN) DriverInfo + DriverInfo->PdbStringOffset), DriverInfoData->PdbString, PdbSize); + } + AllocInfo = (MEMORY_PROFILE_ALLOC_INFO *) ((UINTN) DriverInfo + DriverInfo->Header.Length); AllocInfoList = DriverInfoData->AllocInfoList; for (AllocLink = AllocInfoList->ForwardLink; @@ -1251,10 +1550,14 @@ MemoryProfileCopyData ( MEMORY_PROFILE_ALLOC_INFO_SIGNATURE ); CopyMem (AllocInfo, &AllocInfoData->AllocInfo, sizeof (MEMORY_PROFILE_ALLOC_INFO)); - AllocInfo += 1; + if (AllocInfo->ActionStringOffset != 0) { + ActionStringSize = AsciiStrSize (AllocInfoData->ActionString); + CopyMem ((VOID *) ((UINTN) AllocInfo + AllocInfo->ActionStringOffset), AllocInfoData->ActionString, ActionStringSize); + } + AllocInfo = (MEMORY_PROFILE_ALLOC_INFO *) ((UINTN) AllocInfo + AllocInfo->Header.Length); } - DriverInfo = (MEMORY_PROFILE_DRIVER_INFO *) ((UINTN) (DriverInfo + 1) + sizeof (MEMORY_PROFILE_ALLOC_INFO) * (UINTN) DriverInfo->AllocRecordCount); + DriverInfo = (MEMORY_PROFILE_DRIVER_INFO *) AllocInfo; } } @@ -1267,6 +1570,7 @@ MemoryProfileCopyData ( @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. @@ -1281,28 +1585,28 @@ ProfileProtocolGetData ( { UINTN Size; MEMORY_PROFILE_CONTEXT_DATA *ContextData; - BOOLEAN MemoryProfileRecordingStatus; + BOOLEAN MemoryProfileGettingStatus; ContextData = GetMemoryProfileContext (); if (ContextData == NULL) { return EFI_UNSUPPORTED; } - MemoryProfileRecordingStatus = mMemoryProfileRecordingStatus; - mMemoryProfileRecordingStatus = FALSE; + MemoryProfileGettingStatus = mMemoryProfileGettingStatus; + mMemoryProfileGettingStatus = TRUE; Size = MemoryProfileGetDataSize (); if (*ProfileSize < Size) { *ProfileSize = Size; - mMemoryProfileRecordingStatus = MemoryProfileRecordingStatus; + mMemoryProfileGettingStatus = MemoryProfileGettingStatus; return EFI_BUFFER_TOO_SMALL; } *ProfileSize = Size; MemoryProfileCopyData (ProfileBuffer); - mMemoryProfileRecordingStatus = MemoryProfileRecordingStatus; + mMemoryProfileGettingStatus = MemoryProfileGettingStatus; return EFI_SUCCESS; } @@ -1315,8 +1619,10 @@ ProfileProtocolGetData ( @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. + @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 @@ -1342,7 +1648,7 @@ ProfileProtocolRegisterImage ( DriverEntry.ImageContext.EntryPoint = (PHYSICAL_ADDRESS) (UINTN) EntryPointInImage; DriverEntry.ImageContext.ImageType = InternalPeCoffGetSubsystem ((VOID *) (UINTN) ImageBase); - return RegisterMemoryProfileImage (&DriverEntry, FileType) ? EFI_SUCCESS: EFI_OUT_OF_RESOURCES; + return RegisterMemoryProfileImage (&DriverEntry, FileType); } /** @@ -1353,7 +1659,9 @@ ProfileProtocolRegisterImage ( @param[in] ImageBase Image base address. @param[in] ImageSize Image size. - @return EFI_SUCCESS Unregister success. + @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. **/ @@ -1378,7 +1686,105 @@ ProfileProtocolUnregisterImage ( ASSERT_EFI_ERROR (Status); DriverEntry.ImageContext.EntryPoint = (PHYSICAL_ADDRESS) (UINTN) EntryPointInImage; - return UnregisterMemoryProfileImage (&DriverEntry) ? EFI_SUCCESS: EFI_NOT_FOUND; + return UnregisterMemoryProfileImage (&DriverEntry); +} + +/** + Get memory profile recording state. + + @param[in] This The EDKII_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 +ProfileProtocolGetRecordingState ( + IN EDKII_MEMORY_PROFILE_PROTOCOL *This, + OUT BOOLEAN *RecordingState + ) +{ + MEMORY_PROFILE_CONTEXT_DATA *ContextData; + + ContextData = GetMemoryProfileContext (); + if (ContextData == NULL) { + return EFI_UNSUPPORTED; + } + + if (RecordingState == NULL) { + return EFI_INVALID_PARAMETER; + } + *RecordingState = mMemoryProfileRecordingEnable; + return EFI_SUCCESS; +} + +/** + Set memory profile recording state. + + @param[in] This The EDKII_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 +ProfileProtocolSetRecordingState ( + IN EDKII_MEMORY_PROFILE_PROTOCOL *This, + IN BOOLEAN RecordingState + ) +{ + MEMORY_PROFILE_CONTEXT_DATA *ContextData; + + ContextData = GetMemoryProfileContext (); + if (ContextData == NULL) { + return EFI_UNSUPPORTED; + } + + mMemoryProfileRecordingEnable = RecordingState; + return EFI_SUCCESS; +} + +/** + Record memory profile of multilevel caller. + + @param[in] This The EDKII_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 +ProfileProtocolRecord ( + IN EDKII_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 CoreUpdateProfile (CallerAddress, Action, MemoryType, Size, Buffer, ActionString); } //////////////////// diff --git a/MdeModulePkg/Core/Dxe/Mem/Page.c b/MdeModulePkg/Core/Dxe/Mem/Page.c index 898b722a43..b02bafb4be 100644 --- a/MdeModulePkg/Core/Dxe/Mem/Page.c +++ b/MdeModulePkg/Core/Dxe/Mem/Page.c @@ -1335,7 +1335,14 @@ CoreAllocatePages ( 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); + CoreUpdateProfile ( + (EFI_PHYSICAL_ADDRESS) (UINTN) RETURN_ADDRESS (0), + MemoryProfileActionAllocatePages, + MemoryType, + EFI_PAGES_TO_SIZE (NumberOfPages), + (VOID *) (UINTN) *Memory, + NULL + ); InstallMemoryAttributesTableOnMemoryAllocation (MemoryType); } return Status; @@ -1444,7 +1451,14 @@ CoreFreePages ( Status = CoreInternalFreePages (Memory, NumberOfPages, &MemoryType); if (!EFI_ERROR (Status)) { - CoreUpdateProfile ((EFI_PHYSICAL_ADDRESS) (UINTN) RETURN_ADDRESS (0), MemoryProfileActionFreePages, MemoryType, EFI_PAGES_TO_SIZE (NumberOfPages), (VOID *) (UINTN) Memory); + CoreUpdateProfile ( + (EFI_PHYSICAL_ADDRESS) (UINTN) RETURN_ADDRESS (0), + MemoryProfileActionFreePages, + MemoryType, + EFI_PAGES_TO_SIZE (NumberOfPages), + (VOID *) (UINTN) Memory, + NULL + ); InstallMemoryAttributesTableOnMemoryAllocation (MemoryType); } return Status; diff --git a/MdeModulePkg/Core/Dxe/Mem/Pool.c b/MdeModulePkg/Core/Dxe/Mem/Pool.c index 2980e2293e..6ef5fba395 100644 --- a/MdeModulePkg/Core/Dxe/Mem/Pool.c +++ b/MdeModulePkg/Core/Dxe/Mem/Pool.c @@ -276,7 +276,14 @@ CoreAllocatePool ( Status = CoreInternalAllocatePool (PoolType, Size, Buffer); if (!EFI_ERROR (Status)) { - CoreUpdateProfile ((EFI_PHYSICAL_ADDRESS) (UINTN) RETURN_ADDRESS (0), MemoryProfileActionAllocatePool, PoolType, Size, *Buffer); + CoreUpdateProfile ( + (EFI_PHYSICAL_ADDRESS) (UINTN) RETURN_ADDRESS (0), + MemoryProfileActionAllocatePool, + PoolType, + Size, + *Buffer, + NULL + ); InstallMemoryAttributesTableOnMemoryAllocation (PoolType); } return Status; @@ -505,7 +512,14 @@ CoreFreePool ( Status = CoreInternalFreePool (Buffer, &PoolType); if (!EFI_ERROR (Status)) { - CoreUpdateProfile ((EFI_PHYSICAL_ADDRESS) (UINTN) RETURN_ADDRESS (0), MemoryProfileActionFreePool, PoolType, 0, Buffer); + CoreUpdateProfile ( + (EFI_PHYSICAL_ADDRESS) (UINTN) RETURN_ADDRESS (0), + MemoryProfileActionFreePool, + PoolType, + 0, + Buffer, + NULL + ); InstallMemoryAttributesTableOnMemoryAllocation (PoolType); } return Status; 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. - - @retval TRUE Profile udpate success. - @retval FALSE Profile update fail. + @param 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. **/ -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/PiSmmIpl.c b/MdeModulePkg/Core/PiSmmCore/PiSmmIpl.c index acfcc83e4f..acb852b8dd 100644 --- a/MdeModulePkg/Core/PiSmmCore/PiSmmIpl.c +++ b/MdeModulePkg/Core/PiSmmCore/PiSmmIpl.c @@ -1556,7 +1556,7 @@ SmmIplEntry ( } if (gSmmCorePrivate->SmramRanges[Index].CpuStart >= BASE_1MB) { - if ((gSmmCorePrivate->SmramRanges[Index].CpuStart + gSmmCorePrivate->SmramRanges[Index].PhysicalSize) <= BASE_4GB) { + if ((gSmmCorePrivate->SmramRanges[Index].CpuStart + gSmmCorePrivate->SmramRanges[Index].PhysicalSize - 1) <= MAX_ADDRESS) { if (gSmmCorePrivate->SmramRanges[Index].PhysicalSize >= MaxSize) { MaxSize = gSmmCorePrivate->SmramRanges[Index].PhysicalSize; mCurrentSmramRange = &gSmmCorePrivate->SmramRanges[Index]; diff --git a/MdeModulePkg/Core/PiSmmCore/Pool.c b/MdeModulePkg/Core/PiSmmCore/Pool.c index 761988e416..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 @@ -67,7 +67,7 @@ SmmInitializeMemoryServices ( } if (SmramRanges[Index].CpuStart >= BASE_1MB) { - if ((SmramRanges[Index].CpuStart + SmramRanges[Index].PhysicalSize) <= BASE_4GB) { + if ((SmramRanges[Index].CpuStart + SmramRanges[Index].PhysicalSize - 1) <= MAX_ADDRESS) { if (SmramRanges[Index].PhysicalSize >= MaxSize) { MaxSize = SmramRanges[Index].PhysicalSize; CurrentSmramRangesIndex = Index; @@ -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]; + // + // Update summary if and only if it is basic action. + // + if (Action == BasicAction) { + ProfileMemoryIndex = GetProfileMemoryIndex (MemoryType); + + 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); } - Context->SequenceCount ++; - SmramProfileUpdateFreePages (ContextData); - return TRUE; + 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; - - 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) { + // + // Do not return if DriverInfoData == NULL here, + // because driver A might free memory allocated by driver B. + // + + // + // 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) { // - // 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. + // Legal case, because driver A might free memory allocated by driver B, by some protocol. // - return FALSE; - } - } + 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; + } + } - Context = &ContextData->Context; - DriverInfo = &DriverInfoData->DriverInfo; - AllocInfo = &AllocInfoData->AllocInfo; + 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); + } + } - ProfileMemoryIndex = GetProfileMemoryIndex (AllocInfo->MemoryType); + Found = TRUE; - Context->CurrentTotalUsage -= AllocInfo->Size; - Context->CurrentTotalUsageByType[ProfileMemoryIndex] -= AllocInfo->Size; + Context = &ContextData->Context; + DriverInfo = &DriverInfoData->DriverInfo; + AllocInfo = &AllocInfoData->AllocInfo; - DriverInfo->CurrentUsage -= AllocInfo->Size; - DriverInfo->CurrentUsageByType[ProfileMemoryIndex] -= AllocInfo->Size; - DriverInfo->AllocRecordCount --; + 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); - RemoveEntryList (&AllocInfoData->Link); + Context->CurrentTotalUsage -= AllocInfo->Size; + Context->CurrentTotalUsageByType[ProfileMemoryIndex] -= AllocInfo->Size; - 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 (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) - ); + DriverInfo->CurrentUsage -= AllocInfo->Size; + DriverInfo->CurrentUsageByType[ProfileMemoryIndex] -= AllocInfo->Size; } - } - // - // Use SmmInternalFreePool() that will not update profile for this FreePool action. - // - SmmInternalFreePool (AllocInfoData); + RemoveEntryList (&AllocInfoData->Link); + + 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 + ); + } + } - 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. - - @retval TRUE Profile udpate success. - @retval FALSE Profile update fail. + @param 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. **/ -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; } /** diff --git a/MdeModulePkg/Include/Guid/MemoryProfile.h b/MdeModulePkg/Include/Guid/MemoryProfile.h index 9c70b9df39..38a64945e3 100644 --- a/MdeModulePkg/Include/Guid/MemoryProfile.h +++ b/MdeModulePkg/Include/Guid/MemoryProfile.h @@ -15,6 +15,8 @@ #ifndef _MEMORY_PROFILE_H_ #define _MEMORY_PROFILE_H_ +#include + // // For BIOS MemoryType (0 ~ EfiMaxMemoryType - 1), 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) @@ -42,7 +44,7 @@ typedef struct { } MEMORY_PROFILE_CONTEXT; #define MEMORY_PROFILE_DRIVER_INFO_SIGNATURE SIGNATURE_32 ('M','P','D','I') -#define MEMORY_PROFILE_DRIVER_INFO_REVISION 0x0002 +#define MEMORY_PROFILE_DRIVER_INFO_REVISION 0x0003 typedef struct { MEMORY_PROFILE_COMMON_HEADER Header; @@ -58,6 +60,9 @@ typedef struct { UINT64 PeakUsage; UINT64 CurrentUsageByType[EfiMaxMemoryType + 2]; UINT64 PeakUsageByType[EfiMaxMemoryType + 2]; + UINT16 PdbStringOffset; + UINT8 Reserved2[6]; +//CHAR8 PdbString[]; } MEMORY_PROFILE_DRIVER_INFO; typedef enum { @@ -67,8 +72,75 @@ typedef enum { MemoryProfileActionFreePool = 4, } MEMORY_PROFILE_ACTION; +// +// Below is the detailed MEMORY_PROFILE_ACTION definition. +// +// 31 15 9 8 8 7 7 6 6 5-4 3 - 0 +// +----------------------------------------------+ +// |User | |Lib| |Re|Copy|Zero|Align|Type|Basic| +// +----------------------------------------------+ +// + +// +// Basic Action +// 1 : AllocatePages +// 2 : FreePages +// 3 : AllocatePool +// 4 : FreePool +// +#define MEMORY_PROFILE_ACTION_BASIC_MASK 0xF + +// +// Extension +// +#define MEMORY_PROFILE_ACTION_EXTENSION_MASK 0xFFF0 +#define MEMORY_PROFILE_ACTION_EXTENSION_LIB_MASK 0x8000 +#define MEMORY_PROFILE_ACTION_EXTENSION_REALLOC_MASK 0x0200 +#define MEMORY_PROFILE_ACTION_EXTENSION_COPY_MASK 0x0100 +#define MEMORY_PROFILE_ACTION_EXTENSION_ZERO_MASK 0x0080 +#define MEMORY_PROFILE_ACTION_EXTENSION_ALIGN_MASK 0x0040 +#define MEMORY_PROFILE_ACTION_EXTENSION_MEM_TYPE_MASK 0x0030 +#define MEMORY_PROFILE_ACTION_EXTENSION_MEM_TYPE_BASIC 0x0000 +#define MEMORY_PROFILE_ACTION_EXTENSION_MEM_TYPE_RUNTIME 0x0010 +#define MEMORY_PROFILE_ACTION_EXTENSION_MEM_TYPE_RESERVED 0x0020 + +// +// Extension (used by memory allocation lib) +// +#define MEMORY_PROFILE_ACTION_LIB_ALLOCATE_PAGES 0x8001 +#define MEMORY_PROFILE_ACTION_LIB_ALLOCATE_RUNTIME_PAGES 0x8011 +#define MEMORY_PROFILE_ACTION_LIB_ALLOCATE_RESERVED_PAGES 0x8021 +#define MEMORY_PROFILE_ACTION_LIB_FREE_PAGES 0x8002 +#define MEMORY_PROFILE_ACTION_LIB_ALLOCATE_ALIGNED_PAGES 0x8041 +#define MEMORY_PROFILE_ACTION_LIB_ALLOCATE_ALIGNED_RUNTIME_PAGES 0x8051 +#define MEMORY_PROFILE_ACTION_LIB_ALLOCATE_ALIGNED_RESERVED_PAGES 0x8061 +#define MEMORY_PROFILE_ACTION_LIB_FREE_ALIGNED_PAGES 0x8042 +#define MEMORY_PROFILE_ACTION_LIB_ALLOCATE_POOL 0x8003 +#define MEMORY_PROFILE_ACTION_LIB_ALLOCATE_RUNTIME_POOL 0x8013 +#define MEMORY_PROFILE_ACTION_LIB_ALLOCATE_RESERVED_POOL 0x8023 +#define MEMORY_PROFILE_ACTION_LIB_FREE_POOL 0x8004 +#define MEMORY_PROFILE_ACTION_LIB_ALLOCATE_ZERO_POOL 0x8083 +#define MEMORY_PROFILE_ACTION_LIB_ALLOCATE_RUNTIME_ZERO_POOL 0x8093 +#define MEMORY_PROFILE_ACTION_LIB_ALLOCATE_RESERVED_ZERO_POOL 0x80a3 +#define MEMORY_PROFILE_ACTION_LIB_ALLOCATE_COPY_POOL 0x8103 +#define MEMORY_PROFILE_ACTION_LIB_ALLOCATE_RUNTIME_COPY_POOL 0x8113 +#define MEMORY_PROFILE_ACTION_LIB_ALLOCATE_RESERVED_COPY_POOL 0x8123 +#define MEMORY_PROFILE_ACTION_LIB_REALLOCATE_POOL 0x8203 +#define MEMORY_PROFILE_ACTION_LIB_REALLOCATE_RUNTIME_POOL 0x8213 +#define MEMORY_PROFILE_ACTION_LIB_REALLOCATE_RESERVED_POOL 0x8223 + +// +// User defined: 0x80000000~0xFFFFFFFF +// +// NOTE: User defined action MUST OR the basic action, +// so that core can know the action is allocate or free, +// and the type is pages (can be freed partially) +// or pool (cannot be freed partially). +// +#define MEMORY_PROFILE_ACTION_USER_DEFINED_MASK 0x80000000 + #define MEMORY_PROFILE_ALLOC_INFO_SIGNATURE SIGNATURE_32 ('M','P','A','I') -#define MEMORY_PROFILE_ALLOC_INFO_REVISION 0x0001 +#define MEMORY_PROFILE_ALLOC_INFO_REVISION 0x0002 typedef struct { MEMORY_PROFILE_COMMON_HEADER Header; @@ -79,6 +151,9 @@ typedef struct { EFI_MEMORY_TYPE MemoryType; PHYSICAL_ADDRESS Buffer; UINT64 Size; + UINT16 ActionStringOffset; + UINT8 Reserved2[6]; +//CHAR8 ActionString[]; } MEMORY_PROFILE_ALLOC_INFO; #define MEMORY_PROFILE_DESCRIPTOR_SIGNATURE SIGNATURE_32 ('M','P','D','R') @@ -141,6 +216,7 @@ typedef struct _EDKII_MEMORY_PROFILE_PROTOCOL EDKII_MEMORY_PROFILE_PROTOCOL; @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. @@ -162,8 +238,10 @@ EFI_STATUS @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. + @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. **/ typedef @@ -184,7 +262,9 @@ EFI_STATUS @param[in] ImageBase Image base address. @param[in] ImageSize Image size. - @return EFI_SUCCESS Unregister success. + @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. **/ @@ -197,10 +277,86 @@ EFI_STATUS IN UINT64 ImageSize ); +#define MEMORY_PROFILE_RECORDING_ENABLE TRUE +#define MEMORY_PROFILE_RECORDING_DISABLE FALSE + +/** + Get memory profile recording state. + + @param[in] This The EDKII_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. + +**/ +typedef +EFI_STATUS +(EFIAPI *EDKII_MEMORY_PROFILE_GET_RECORDING_STATE) ( + IN EDKII_MEMORY_PROFILE_PROTOCOL *This, + OUT BOOLEAN *RecordingState + ); + +/** + Set memory profile recording state. + + @param[in] This The EDKII_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. + +**/ +typedef +EFI_STATUS +(EFIAPI *EDKII_MEMORY_PROFILE_SET_RECORDING_STATE) ( + IN EDKII_MEMORY_PROFILE_PROTOCOL *This, + IN BOOLEAN RecordingState + ); + +/** + Record memory profile of multilevel caller. + + @param[in] This The EDKII_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. + +**/ +typedef +EFI_STATUS +(EFIAPI *EDKII_MEMORY_PROFILE_RECORD) ( + IN EDKII_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 + ); + struct _EDKII_MEMORY_PROFILE_PROTOCOL { - EDKII_MEMORY_PROFILE_GET_DATA GetData; - EDKII_MEMORY_PROFILE_REGISTER_IMAGE RegisterImage; - EDKII_MEMORY_PROFILE_UNREGISTER_IMAGE UnregisterImage; + EDKII_MEMORY_PROFILE_GET_DATA GetData; + EDKII_MEMORY_PROFILE_REGISTER_IMAGE RegisterImage; + EDKII_MEMORY_PROFILE_UNREGISTER_IMAGE UnregisterImage; + EDKII_MEMORY_PROFILE_GET_RECORDING_STATE GetRecordingState; + EDKII_MEMORY_PROFILE_SET_RECORDING_STATE SetRecordingState; + EDKII_MEMORY_PROFILE_RECORD Record; }; // @@ -246,6 +402,8 @@ struct _EDKII_MEMORY_PROFILE_PROTOCOL { #define SMRAM_PROFILE_COMMAND_UNREGISTER_IMAGE 0x4 #define SMRAM_PROFILE_COMMAND_GET_PROFILE_DATA_BY_OFFSET 0x5 +#define SMRAM_PROFILE_COMMAND_GET_RECORDING_STATE 0x6 +#define SMRAM_PROFILE_COMMAND_SET_RECORDING_STATE 0x7 typedef struct { UINT32 Command; @@ -279,6 +437,11 @@ typedef struct { UINT64 ProfileOffset; } SMRAM_PROFILE_PARAMETER_GET_PROFILE_DATA_BY_OFFSET; +typedef struct { + SMRAM_PROFILE_PARAMETER_HEADER Header; + BOOLEAN RecordingState; +} SMRAM_PROFILE_PARAMETER_RECORDING_STATE; + typedef struct { SMRAM_PROFILE_PARAMETER_HEADER Header; EFI_GUID FileName; @@ -295,10 +458,18 @@ typedef struct { #define EDKII_MEMORY_PROFILE_GUID { \ - 0x821c9a09, 0x541a, 0x40f6, 0x9f, 0x43, 0xa, 0xd1, 0x93, 0xa1, 0x2c, 0xfe \ + 0x821c9a09, 0x541a, 0x40f6, { 0x9f, 0x43, 0xa, 0xd1, 0x93, 0xa1, 0x2c, 0xfe } \ } extern EFI_GUID gEdkiiMemoryProfileGuid; +typedef EDKII_MEMORY_PROFILE_PROTOCOL EDKII_SMM_MEMORY_PROFILE_PROTOCOL; + +#define EDKII_SMM_MEMORY_PROFILE_GUID { \ + 0xe22bbcca, 0x516a, 0x46a8, { 0x80, 0xe2, 0x67, 0x45, 0xe8, 0x36, 0x93, 0xbd } \ +} + +extern EFI_GUID gEdkiiSmmMemoryProfileGuid; + #endif diff --git a/MdeModulePkg/Include/Library/MemoryProfileLib.h b/MdeModulePkg/Include/Library/MemoryProfileLib.h new file mode 100644 index 0000000000..8543801391 --- /dev/null +++ b/MdeModulePkg/Include/Library/MemoryProfileLib.h @@ -0,0 +1,53 @@ +/** @file + Provides services to record memory profile of multilevel caller. + + Copyright (c) 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 + 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_LIB_H_ +#define _MEMORY_PROFILE_LIB_H_ + +#include + +/** + Record memory profile of multilevel caller. + + @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 +MemoryProfileLibRecord ( + IN PHYSICAL_ADDRESS CallerAddress, + IN MEMORY_PROFILE_ACTION Action, + IN EFI_MEMORY_TYPE MemoryType, + IN VOID *Buffer, + IN UINTN Size, + IN CHAR8 *ActionString OPTIONAL + ); + +#endif diff --git a/MdeModulePkg/Library/DxeCoreMemoryAllocationLib/DxeCoreMemoryAllocationLib.inf b/MdeModulePkg/Library/DxeCoreMemoryAllocationLib/DxeCoreMemoryAllocationLib.inf index 0747f6e697..caba8cd4a4 100644 --- a/MdeModulePkg/Library/DxeCoreMemoryAllocationLib/DxeCoreMemoryAllocationLib.inf +++ b/MdeModulePkg/Library/DxeCoreMemoryAllocationLib/DxeCoreMemoryAllocationLib.inf @@ -1,10 +1,10 @@ ## @file # Memory Allocation Library instance dedicated to DXE Core. # The implementation borrows the DxeCore Memory Allocation services as the primitive -# for memory allocation instead of using UEFI boot servces in an indirect way. -# It is assumed that this library instance must be linked with DxeCore in this package. +# for memory allocation instead of using UEFI boot services in an indirect way. +# It is assumed that this library instance must be linked with DxeCore in this package. # -# Copyright (c) 2008 - 2014, Intel Corporation. All rights reserved.
+# Copyright (c) 2008 - 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 @@ -24,7 +24,7 @@ MODULE_TYPE = DXE_CORE VERSION_STRING = 1.0 LIBRARY_CLASS = MemoryAllocationLib|DXE_CORE - + # # The following information is for reference only and not required by the build tools. # @@ -34,13 +34,12 @@ [Sources] MemoryAllocationLib.c DxeCoreMemoryAllocationServices.h + DxeCoreMemoryProfileLibNull.c [Packages] MdePkg/MdePkg.dec - + MdeModulePkg/MdeModulePkg.dec [LibraryClasses] DebugLib BaseMemoryLib - - diff --git a/MdeModulePkg/Library/DxeCoreMemoryAllocationLib/DxeCoreMemoryAllocationLib.uni b/MdeModulePkg/Library/DxeCoreMemoryAllocationLib/DxeCoreMemoryAllocationLib.uni index 85f8c7ec27..aa67c8baf1 100644 --- a/MdeModulePkg/Library/DxeCoreMemoryAllocationLib/DxeCoreMemoryAllocationLib.uni +++ b/MdeModulePkg/Library/DxeCoreMemoryAllocationLib/DxeCoreMemoryAllocationLib.uni @@ -2,10 +2,10 @@ // Memory Allocation Library instance dedicated to DXE Core. // // The implementation borrows the DxeCore Memory Allocation services as the primitive -// for memory allocation instead of using UEFI boot servces in an indirect way. +// for memory allocation instead of using UEFI boot services in an indirect way. // It is assumed that this library instance must be linked with DxeCore in this package. // -// Copyright (c) 2008 - 2014, Intel Corporation. All rights reserved.
+// Copyright (c) 2008 - 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 diff --git a/MdeModulePkg/Library/DxeCoreMemoryAllocationLib/DxeCoreMemoryAllocationProfileLib.inf b/MdeModulePkg/Library/DxeCoreMemoryAllocationLib/DxeCoreMemoryAllocationProfileLib.inf new file mode 100644 index 0000000000..a2b5f8c102 --- /dev/null +++ b/MdeModulePkg/Library/DxeCoreMemoryAllocationLib/DxeCoreMemoryAllocationProfileLib.inf @@ -0,0 +1,48 @@ +## @file +# Memory Allocation/Profile Library instance dedicated to DXE Core. +# The implementation borrows the DxeCore Memory Allocation/profile services as the primitive +# for memory allocation/profile instead of using UEFI boot services or memory profile protocol in an indirect way. +# It is assumed that this library instance must be linked with DxeCore in this package. +# +# Copyright (c) 2008 - 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 +# 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 = DxeCoreMemoryAllocationProfileLib + MODULE_UNI_FILE = DxeCoreMemoryAllocationProfileLib.uni + FILE_GUID = 7ADD7147-74E8-4583-BE34-B6BC45353BB5 + MODULE_TYPE = DXE_CORE + VERSION_STRING = 1.0 + LIBRARY_CLASS = MemoryAllocationLib|DXE_CORE + LIBRARY_CLASS = MemoryProfileLib|DXE_CORE + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 IPF EBC +# + +[Sources] + MemoryAllocationLib.c + DxeCoreMemoryAllocationServices.h + DxeCoreMemoryProfileLib.c + DxeCoreMemoryProfileServices.h + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + +[LibraryClasses] + DebugLib + BaseMemoryLib + diff --git a/MdeModulePkg/Library/DxeCoreMemoryAllocationLib/DxeCoreMemoryAllocationProfileLib.uni b/MdeModulePkg/Library/DxeCoreMemoryAllocationLib/DxeCoreMemoryAllocationProfileLib.uni new file mode 100644 index 0000000000..82cdca62aa --- /dev/null +++ b/MdeModulePkg/Library/DxeCoreMemoryAllocationLib/DxeCoreMemoryAllocationProfileLib.uni @@ -0,0 +1,23 @@ +// /** @file +// Memory Allocation/Profile Library instance dedicated to DXE Core. +// +// The implementation borrows the DxeCore Memory Allocation/Profile services as the primitive +// for memory allocation/profile instead of using UEFI boot services or memory profile protocol in an indirect way. +// It is assumed that this library instance must be linked with DxeCore in this package. +// +// Copyright (c) 2008 - 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 +// 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. +// +// **/ + + +#string STR_MODULE_ABSTRACT #language en-US "Memory Allocation/Profile Library instance dedicated to DXE Core" + +#string STR_MODULE_DESCRIPTION #language en-US "The implementation borrows the DxeCore Memory Allocation/Profile services as the primitive for memory allocation/profile instead of using UEFI boot services or memory profile protocol in an indirect way. It is assumed that this library instance must be linked with DxeCore in this package." + diff --git a/MdeModulePkg/Library/DxeCoreMemoryAllocationLib/DxeCoreMemoryProfileLib.c b/MdeModulePkg/Library/DxeCoreMemoryAllocationLib/DxeCoreMemoryProfileLib.c new file mode 100644 index 0000000000..8f28b988f5 --- /dev/null +++ b/MdeModulePkg/Library/DxeCoreMemoryAllocationLib/DxeCoreMemoryProfileLib.c @@ -0,0 +1,57 @@ +/** @file + Support routines for memory profile for DxeCore. + + Copyright (c) 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 + 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 + +#include + +#include "DxeCoreMemoryProfileServices.h" + +/** + Record memory profile of multilevel caller. + + @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 +MemoryProfileLibRecord ( + 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 CoreUpdateProfile (CallerAddress, Action, MemoryType, Size, Buffer, ActionString); +} + diff --git a/MdeModulePkg/Library/DxeCoreMemoryAllocationLib/DxeCoreMemoryProfileLibNull.c b/MdeModulePkg/Library/DxeCoreMemoryAllocationLib/DxeCoreMemoryProfileLibNull.c new file mode 100644 index 0000000000..9ae0db8273 --- /dev/null +++ b/MdeModulePkg/Library/DxeCoreMemoryAllocationLib/DxeCoreMemoryProfileLibNull.c @@ -0,0 +1,55 @@ +/** @file + Null routines for memory profile for DxeCore. + + Copyright (c) 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 + 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 + +#include + +/** + Record memory profile of multilevel caller. + + @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 +MemoryProfileLibRecord ( + 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 EFI_UNSUPPORTED; +} + diff --git a/MdeModulePkg/Library/DxeCoreMemoryAllocationLib/DxeCoreMemoryProfileServices.h b/MdeModulePkg/Library/DxeCoreMemoryAllocationLib/DxeCoreMemoryProfileServices.h new file mode 100644 index 0000000000..619d7add9a --- /dev/null +++ b/MdeModulePkg/Library/DxeCoreMemoryAllocationLib/DxeCoreMemoryProfileServices.h @@ -0,0 +1,54 @@ +/** @file + Contains function prototypes for Memory Profile Services in DxeCore. + + This header file borrows the DxeCore Memory Profile services as the primitive + for memory profile. + + Copyright (c) 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 + 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 _DXE_CORE_MEMORY_PROFILE_SERVICES_H_ +#define _DXE_CORE_MEMORY_PROFILE_SERVICES_H_ + +/** + 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. + 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. + + @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 +CoreUpdateProfile ( + IN PHYSICAL_ADDRESS CallerAddress, + IN MEMORY_PROFILE_ACTION Action, + IN EFI_MEMORY_TYPE MemoryType, + IN UINTN Size, // Valid for AllocatePages/FreePages/AllocatePool + IN VOID *Buffer, + IN CHAR8 *ActionString OPTIONAL + ); + +#endif diff --git a/MdeModulePkg/Library/DxeCoreMemoryAllocationLib/MemoryAllocationLib.c b/MdeModulePkg/Library/DxeCoreMemoryAllocationLib/MemoryAllocationLib.c index d7d9ff311e..89c19e7c83 100644 --- a/MdeModulePkg/Library/DxeCoreMemoryAllocationLib/MemoryAllocationLib.c +++ b/MdeModulePkg/Library/DxeCoreMemoryAllocationLib/MemoryAllocationLib.c @@ -1,8 +1,9 @@ /** @file Support routines for memory allocation routines based - on boot services for Dxe phase drivers. + on DxeCore Memory Allocation services for DxeCore, + with memory profile support. - Copyright (c) 2006 - 2015, Intel Corporation. All rights reserved.
+ Copyright (c) 2006 - 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 @@ -22,6 +23,8 @@ #include #include "DxeCoreMemoryAllocationServices.h" +#include + /** Allocates one or more 4KB pages of a certain memory type. @@ -74,7 +77,20 @@ AllocatePages ( IN UINTN Pages ) { - return InternalAllocatePages (EfiBootServicesData, Pages); + VOID *Buffer; + + Buffer = InternalAllocatePages (EfiBootServicesData, Pages); + if (Buffer != NULL) { + MemoryProfileLibRecord ( + (PHYSICAL_ADDRESS) (UINTN) RETURN_ADDRESS(0), + MEMORY_PROFILE_ACTION_LIB_ALLOCATE_PAGES, + EfiBootServicesData, + Buffer, + EFI_PAGES_TO_SIZE (Pages), + NULL + ); + } + return Buffer; } /** @@ -96,7 +112,20 @@ AllocateRuntimePages ( IN UINTN Pages ) { - return InternalAllocatePages (EfiRuntimeServicesData, Pages); + VOID *Buffer; + + Buffer = InternalAllocatePages (EfiRuntimeServicesData, Pages); + if (Buffer != NULL) { + MemoryProfileLibRecord ( + (PHYSICAL_ADDRESS) (UINTN) RETURN_ADDRESS(0), + MEMORY_PROFILE_ACTION_LIB_ALLOCATE_RUNTIME_PAGES, + EfiRuntimeServicesData, + Buffer, + EFI_PAGES_TO_SIZE (Pages), + NULL + ); + } + return Buffer; } /** @@ -118,7 +147,20 @@ AllocateReservedPages ( IN UINTN Pages ) { - return InternalAllocatePages (EfiReservedMemoryType, Pages); + VOID *Buffer; + + Buffer = InternalAllocatePages (EfiReservedMemoryType, Pages); + if (Buffer != NULL) { + MemoryProfileLibRecord ( + (PHYSICAL_ADDRESS) (UINTN) RETURN_ADDRESS(0), + MEMORY_PROFILE_ACTION_LIB_ALLOCATE_RESERVED_PAGES, + EfiReservedMemoryType, + Buffer, + EFI_PAGES_TO_SIZE (Pages), + NULL + ); + } + return Buffer; } /** @@ -263,7 +305,20 @@ AllocateAlignedPages ( IN UINTN Alignment ) { - return InternalAllocateAlignedPages (EfiBootServicesData, Pages, Alignment); + VOID *Buffer; + + Buffer = InternalAllocateAlignedPages (EfiBootServicesData, Pages, Alignment); + if (Buffer != NULL) { + MemoryProfileLibRecord ( + (PHYSICAL_ADDRESS) (UINTN) RETURN_ADDRESS(0), + MEMORY_PROFILE_ACTION_LIB_ALLOCATE_ALIGNED_PAGES, + EfiBootServicesData, + Buffer, + EFI_PAGES_TO_SIZE (Pages), + NULL + ); + } + return Buffer; } /** @@ -291,7 +346,20 @@ AllocateAlignedRuntimePages ( IN UINTN Alignment ) { - return InternalAllocateAlignedPages (EfiRuntimeServicesData, Pages, Alignment); + VOID *Buffer; + + Buffer = InternalAllocateAlignedPages (EfiRuntimeServicesData, Pages, Alignment); + if (Buffer != NULL) { + MemoryProfileLibRecord ( + (PHYSICAL_ADDRESS) (UINTN) RETURN_ADDRESS(0), + MEMORY_PROFILE_ACTION_LIB_ALLOCATE_ALIGNED_RUNTIME_PAGES, + EfiRuntimeServicesData, + Buffer, + EFI_PAGES_TO_SIZE (Pages), + NULL + ); + } + return Buffer; } /** @@ -319,7 +387,20 @@ AllocateAlignedReservedPages ( IN UINTN Alignment ) { - return InternalAllocateAlignedPages (EfiReservedMemoryType, Pages, Alignment); + VOID *Buffer; + + Buffer = InternalAllocateAlignedPages (EfiReservedMemoryType, Pages, Alignment); + if (Buffer != NULL) { + MemoryProfileLibRecord ( + (PHYSICAL_ADDRESS) (UINTN) RETURN_ADDRESS(0), + MEMORY_PROFILE_ACTION_LIB_ALLOCATE_ALIGNED_RESERVED_PAGES, + EfiReservedMemoryType, + Buffer, + EFI_PAGES_TO_SIZE (Pages), + NULL + ); + } + return Buffer; } /** @@ -402,7 +483,20 @@ AllocatePool ( IN UINTN AllocationSize ) { - return InternalAllocatePool (EfiBootServicesData, AllocationSize); + VOID *Buffer; + + Buffer = InternalAllocatePool (EfiBootServicesData, AllocationSize); + if (Buffer != NULL) { + MemoryProfileLibRecord ( + (PHYSICAL_ADDRESS) (UINTN) RETURN_ADDRESS(0), + MEMORY_PROFILE_ACTION_LIB_ALLOCATE_POOL, + EfiBootServicesData, + Buffer, + AllocationSize, + NULL + ); + } + return Buffer; } /** @@ -423,7 +517,20 @@ AllocateRuntimePool ( IN UINTN AllocationSize ) { - return InternalAllocatePool (EfiRuntimeServicesData, AllocationSize); + VOID *Buffer; + + Buffer = InternalAllocatePool (EfiRuntimeServicesData, AllocationSize); + if (Buffer != NULL) { + MemoryProfileLibRecord ( + (PHYSICAL_ADDRESS) (UINTN) RETURN_ADDRESS(0), + MEMORY_PROFILE_ACTION_LIB_ALLOCATE_RUNTIME_POOL, + EfiRuntimeServicesData, + Buffer, + AllocationSize, + NULL + ); + } + return Buffer; } /** @@ -444,7 +551,20 @@ AllocateReservedPool ( IN UINTN AllocationSize ) { - return InternalAllocatePool (EfiReservedMemoryType, AllocationSize); + VOID *Buffer; + + Buffer = InternalAllocatePool (EfiReservedMemoryType, AllocationSize); + if (Buffer != NULL) { + MemoryProfileLibRecord ( + (PHYSICAL_ADDRESS) (UINTN) RETURN_ADDRESS(0), + MEMORY_PROFILE_ACTION_LIB_ALLOCATE_RESERVED_POOL, + EfiReservedMemoryType, + Buffer, + AllocationSize, + NULL + ); + } + return Buffer; } /** @@ -495,7 +615,20 @@ AllocateZeroPool ( IN UINTN AllocationSize ) { - return InternalAllocateZeroPool (EfiBootServicesData, AllocationSize); + VOID *Buffer; + + Buffer = InternalAllocateZeroPool (EfiBootServicesData, AllocationSize); + if (Buffer != NULL) { + MemoryProfileLibRecord ( + (PHYSICAL_ADDRESS) (UINTN) RETURN_ADDRESS(0), + MEMORY_PROFILE_ACTION_LIB_ALLOCATE_ZERO_POOL, + EfiBootServicesData, + Buffer, + AllocationSize, + NULL + ); + } + return Buffer; } /** @@ -517,7 +650,20 @@ AllocateRuntimeZeroPool ( IN UINTN AllocationSize ) { - return InternalAllocateZeroPool (EfiRuntimeServicesData, AllocationSize); + VOID *Buffer; + + Buffer = InternalAllocateZeroPool (EfiRuntimeServicesData, AllocationSize); + if (Buffer != NULL) { + MemoryProfileLibRecord ( + (PHYSICAL_ADDRESS) (UINTN) RETURN_ADDRESS(0), + MEMORY_PROFILE_ACTION_LIB_ALLOCATE_RUNTIME_ZERO_POOL, + EfiRuntimeServicesData, + Buffer, + AllocationSize, + NULL + ); + } + return Buffer; } /** @@ -539,7 +685,20 @@ AllocateReservedZeroPool ( IN UINTN AllocationSize ) { - return InternalAllocateZeroPool (EfiReservedMemoryType, AllocationSize); + VOID *Buffer; + + Buffer = InternalAllocateZeroPool (EfiReservedMemoryType, AllocationSize); + if (Buffer != NULL) { + MemoryProfileLibRecord ( + (PHYSICAL_ADDRESS) (UINTN) RETURN_ADDRESS(0), + MEMORY_PROFILE_ACTION_LIB_ALLOCATE_RESERVED_ZERO_POOL, + EfiReservedMemoryType, + Buffer, + AllocationSize, + NULL + ); + } + return Buffer; } /** @@ -602,7 +761,20 @@ AllocateCopyPool ( IN CONST VOID *Buffer ) { - return InternalAllocateCopyPool (EfiBootServicesData, AllocationSize, Buffer); + VOID *NewBuffer; + + NewBuffer = InternalAllocateCopyPool (EfiBootServicesData, AllocationSize, Buffer); + if (NewBuffer != NULL) { + MemoryProfileLibRecord ( + (PHYSICAL_ADDRESS) (UINTN) RETURN_ADDRESS(0), + MEMORY_PROFILE_ACTION_LIB_ALLOCATE_COPY_POOL, + EfiBootServicesData, + NewBuffer, + AllocationSize, + NULL + ); + } + return NewBuffer; } /** @@ -629,7 +801,20 @@ AllocateRuntimeCopyPool ( IN CONST VOID *Buffer ) { - return InternalAllocateCopyPool (EfiRuntimeServicesData, AllocationSize, Buffer); + VOID *NewBuffer; + + NewBuffer = InternalAllocateCopyPool (EfiRuntimeServicesData, AllocationSize, Buffer); + if (NewBuffer != NULL) { + MemoryProfileLibRecord ( + (PHYSICAL_ADDRESS) (UINTN) RETURN_ADDRESS(0), + MEMORY_PROFILE_ACTION_LIB_ALLOCATE_RUNTIME_COPY_POOL, + EfiRuntimeServicesData, + NewBuffer, + AllocationSize, + NULL + ); + } + return NewBuffer; } /** @@ -656,7 +841,20 @@ AllocateReservedCopyPool ( IN CONST VOID *Buffer ) { - return InternalAllocateCopyPool (EfiReservedMemoryType, AllocationSize, Buffer); + VOID *NewBuffer; + + NewBuffer = InternalAllocateCopyPool (EfiReservedMemoryType, AllocationSize, Buffer); + if (NewBuffer != NULL) { + MemoryProfileLibRecord ( + (PHYSICAL_ADDRESS) (UINTN) RETURN_ADDRESS(0), + MEMORY_PROFILE_ACTION_LIB_ALLOCATE_RESERVED_COPY_POOL, + EfiRuntimeServicesData, + NewBuffer, + AllocationSize, + NULL + ); + } + return NewBuffer; } /** @@ -728,7 +926,20 @@ ReallocatePool ( IN VOID *OldBuffer OPTIONAL ) { - return InternalReallocatePool (EfiBootServicesData, OldSize, NewSize, OldBuffer); + VOID *Buffer; + + Buffer = InternalReallocatePool (EfiBootServicesData, OldSize, NewSize, OldBuffer); + if (Buffer != NULL) { + MemoryProfileLibRecord ( + (PHYSICAL_ADDRESS) (UINTN) RETURN_ADDRESS(0), + MEMORY_PROFILE_ACTION_LIB_REALLOCATE_POOL, + EfiBootServicesData, + Buffer, + NewSize, + NULL + ); + } + return Buffer; } /** @@ -760,7 +971,20 @@ ReallocateRuntimePool ( IN VOID *OldBuffer OPTIONAL ) { - return InternalReallocatePool (EfiRuntimeServicesData, OldSize, NewSize, OldBuffer); + VOID *Buffer; + + Buffer = InternalReallocatePool (EfiRuntimeServicesData, OldSize, NewSize, OldBuffer); + if (Buffer != NULL) { + MemoryProfileLibRecord ( + (PHYSICAL_ADDRESS) (UINTN) RETURN_ADDRESS(0), + MEMORY_PROFILE_ACTION_LIB_REALLOCATE_RUNTIME_POOL, + EfiRuntimeServicesData, + Buffer, + NewSize, + NULL + ); + } + return Buffer; } /** @@ -792,7 +1016,20 @@ ReallocateReservedPool ( IN VOID *OldBuffer OPTIONAL ) { - return InternalReallocatePool (EfiReservedMemoryType, OldSize, NewSize, OldBuffer); + VOID *Buffer; + + Buffer = InternalReallocatePool (EfiReservedMemoryType, OldSize, NewSize, OldBuffer); + if (Buffer != NULL) { + MemoryProfileLibRecord ( + (PHYSICAL_ADDRESS) (UINTN) RETURN_ADDRESS(0), + MEMORY_PROFILE_ACTION_LIB_REALLOCATE_RESERVED_POOL, + EfiReservedMemoryType, + Buffer, + NewSize, + NULL + ); + } + return Buffer; } /** diff --git a/MdeModulePkg/Library/PiSmmCoreMemoryAllocationLib/MemoryAllocationLib.c b/MdeModulePkg/Library/PiSmmCoreMemoryAllocationLib/MemoryAllocationLib.c index 5e13a3eda2..08dd17ba69 100644 --- a/MdeModulePkg/Library/PiSmmCoreMemoryAllocationLib/MemoryAllocationLib.c +++ b/MdeModulePkg/Library/PiSmmCoreMemoryAllocationLib/MemoryAllocationLib.c @@ -1,5 +1,6 @@ /** @file - Support routines for memory allocation routines based on SMM Core internal functions. + Support routines for memory allocation routines based on SMM Core internal functions, + with memory profile support. The PI System Management Mode Core Interface Specification only allows the use of EfiRuntimeServicesCode and EfiRuntimeServicesData memory types for memory @@ -10,7 +11,7 @@ In addition, allocation for the Reserved memory types are not supported and will always return NULL. - Copyright (c) 2006 - 2015, Intel Corporation. All rights reserved.
+ Copyright (c) 2006 - 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 @@ -23,13 +24,14 @@ #include -#include #include #include #include #include #include "PiSmmCoreMemoryAllocationServices.h" +#include + EFI_SMRAM_DESCRIPTOR *mSmmCoreMemoryAllocLibSmramRanges = NULL; UINTN mSmmCoreMemoryAllocLibSmramRangeCount = 0; @@ -111,7 +113,20 @@ AllocatePages ( IN UINTN Pages ) { - return InternalAllocatePages (EfiRuntimeServicesData, Pages); + VOID *Buffer; + + Buffer = InternalAllocatePages (EfiRuntimeServicesData, Pages); + if (Buffer != NULL) { + MemoryProfileLibRecord ( + (PHYSICAL_ADDRESS) (UINTN) RETURN_ADDRESS(0), + MEMORY_PROFILE_ACTION_LIB_ALLOCATE_PAGES, + EfiRuntimeServicesData, + Buffer, + EFI_PAGES_TO_SIZE(Pages), + NULL + ); + } + return Buffer; } /** @@ -133,7 +148,20 @@ AllocateRuntimePages ( IN UINTN Pages ) { - return InternalAllocatePages (EfiRuntimeServicesData, Pages); + VOID *Buffer; + + Buffer = InternalAllocatePages (EfiRuntimeServicesData, Pages); + if (Buffer != NULL) { + MemoryProfileLibRecord ( + (PHYSICAL_ADDRESS) (UINTN) RETURN_ADDRESS(0), + MEMORY_PROFILE_ACTION_LIB_ALLOCATE_RUNTIME_PAGES, + EfiRuntimeServicesData, + Buffer, + EFI_PAGES_TO_SIZE(Pages), + NULL + ); + } + return Buffer; } /** @@ -312,7 +340,20 @@ AllocateAlignedPages ( IN UINTN Alignment ) { - return InternalAllocateAlignedPages (EfiRuntimeServicesData, Pages, Alignment); + VOID *Buffer; + + Buffer = InternalAllocateAlignedPages (EfiRuntimeServicesData, Pages, Alignment); + if (Buffer != NULL) { + MemoryProfileLibRecord ( + (PHYSICAL_ADDRESS) (UINTN) RETURN_ADDRESS(0), + MEMORY_PROFILE_ACTION_LIB_ALLOCATE_ALIGNED_PAGES, + EfiRuntimeServicesData, + Buffer, + EFI_PAGES_TO_SIZE(Pages), + NULL + ); + } + return Buffer; } /** @@ -340,7 +381,20 @@ AllocateAlignedRuntimePages ( IN UINTN Alignment ) { - return InternalAllocateAlignedPages (EfiRuntimeServicesData, Pages, Alignment); + VOID *Buffer; + + Buffer = InternalAllocateAlignedPages (EfiRuntimeServicesData, Pages, Alignment); + if (Buffer != NULL) { + MemoryProfileLibRecord ( + (PHYSICAL_ADDRESS) (UINTN) RETURN_ADDRESS(0), + MEMORY_PROFILE_ACTION_LIB_ALLOCATE_ALIGNED_RUNTIME_PAGES, + EfiRuntimeServicesData, + Buffer, + EFI_PAGES_TO_SIZE(Pages), + NULL + ); + } + return Buffer; } /** @@ -463,7 +517,20 @@ AllocatePool ( IN UINTN AllocationSize ) { - return InternalAllocatePool (EfiRuntimeServicesData, AllocationSize); + VOID *Buffer; + + Buffer = InternalAllocatePool (EfiRuntimeServicesData, AllocationSize); + if (Buffer != NULL) { + MemoryProfileLibRecord ( + (PHYSICAL_ADDRESS) (UINTN) RETURN_ADDRESS(0), + MEMORY_PROFILE_ACTION_LIB_ALLOCATE_POOL, + EfiRuntimeServicesData, + Buffer, + AllocationSize, + NULL + ); + } + return Buffer; } /** @@ -484,7 +551,20 @@ AllocateRuntimePool ( IN UINTN AllocationSize ) { - return InternalAllocatePool (EfiRuntimeServicesData, AllocationSize); + VOID *Buffer; + + Buffer = InternalAllocatePool (EfiRuntimeServicesData, AllocationSize); + if (Buffer != NULL) { + MemoryProfileLibRecord ( + (PHYSICAL_ADDRESS) (UINTN) RETURN_ADDRESS(0), + MEMORY_PROFILE_ACTION_LIB_ALLOCATE_RUNTIME_POOL, + EfiRuntimeServicesData, + Buffer, + AllocationSize, + NULL + ); + } + return Buffer; } /** @@ -556,7 +636,20 @@ AllocateZeroPool ( IN UINTN AllocationSize ) { - return InternalAllocateZeroPool (EfiRuntimeServicesData, AllocationSize); + VOID *Buffer; + + Buffer = InternalAllocateZeroPool (EfiRuntimeServicesData, AllocationSize); + if (Buffer != NULL) { + MemoryProfileLibRecord ( + (PHYSICAL_ADDRESS) (UINTN) RETURN_ADDRESS(0), + MEMORY_PROFILE_ACTION_LIB_ALLOCATE_ZERO_POOL, + EfiRuntimeServicesData, + Buffer, + AllocationSize, + NULL + ); + } + return Buffer; } /** @@ -578,7 +671,20 @@ AllocateRuntimeZeroPool ( IN UINTN AllocationSize ) { - return InternalAllocateZeroPool (EfiRuntimeServicesData, AllocationSize); + VOID *Buffer; + + Buffer = InternalAllocateZeroPool (EfiRuntimeServicesData, AllocationSize); + if (Buffer != NULL) { + MemoryProfileLibRecord ( + (PHYSICAL_ADDRESS) (UINTN) RETURN_ADDRESS(0), + MEMORY_PROFILE_ACTION_LIB_ALLOCATE_RUNTIME_ZERO_POOL, + EfiRuntimeServicesData, + Buffer, + AllocationSize, + NULL + ); + } + return Buffer; } /** @@ -663,7 +769,20 @@ AllocateCopyPool ( IN CONST VOID *Buffer ) { - return InternalAllocateCopyPool (EfiRuntimeServicesData, AllocationSize, Buffer); + VOID *NewBuffer; + + NewBuffer = InternalAllocateCopyPool (EfiRuntimeServicesData, AllocationSize, Buffer); + if (NewBuffer != NULL) { + MemoryProfileLibRecord ( + (PHYSICAL_ADDRESS) (UINTN) RETURN_ADDRESS(0), + MEMORY_PROFILE_ACTION_LIB_ALLOCATE_COPY_POOL, + EfiRuntimeServicesData, + NewBuffer, + AllocationSize, + NULL + ); + } + return NewBuffer; } /** @@ -690,7 +809,20 @@ AllocateRuntimeCopyPool ( IN CONST VOID *Buffer ) { - return InternalAllocateCopyPool (EfiRuntimeServicesData, AllocationSize, Buffer); + VOID *NewBuffer; + + NewBuffer = InternalAllocateCopyPool (EfiRuntimeServicesData, AllocationSize, Buffer); + if (NewBuffer != NULL) { + MemoryProfileLibRecord ( + (PHYSICAL_ADDRESS) (UINTN) RETURN_ADDRESS(0), + MEMORY_PROFILE_ACTION_LIB_ALLOCATE_RUNTIME_COPY_POOL, + EfiRuntimeServicesData, + NewBuffer, + AllocationSize, + NULL + ); + } + return NewBuffer; } /** @@ -789,7 +921,20 @@ ReallocatePool ( IN VOID *OldBuffer OPTIONAL ) { - return InternalReallocatePool (EfiRuntimeServicesData, OldSize, NewSize, OldBuffer); + VOID *Buffer; + + Buffer = InternalReallocatePool (EfiRuntimeServicesData, OldSize, NewSize, OldBuffer); + if (Buffer != NULL) { + MemoryProfileLibRecord ( + (PHYSICAL_ADDRESS) (UINTN) RETURN_ADDRESS(0), + MEMORY_PROFILE_ACTION_LIB_REALLOCATE_POOL, + EfiRuntimeServicesData, + Buffer, + NewSize, + NULL + ); + } + return Buffer; } /** @@ -821,7 +966,20 @@ ReallocateRuntimePool ( IN VOID *OldBuffer OPTIONAL ) { - return InternalReallocatePool (EfiRuntimeServicesData, OldSize, NewSize, OldBuffer); + VOID *Buffer; + + Buffer = InternalReallocatePool (EfiRuntimeServicesData, OldSize, NewSize, OldBuffer); + if (Buffer != NULL) { + MemoryProfileLibRecord ( + (PHYSICAL_ADDRESS) (UINTN) RETURN_ADDRESS(0), + MEMORY_PROFILE_ACTION_LIB_REALLOCATE_RUNTIME_POOL, + EfiRuntimeServicesData, + Buffer, + NewSize, + NULL + ); + } + return Buffer; } /** diff --git a/MdeModulePkg/Library/PiSmmCoreMemoryAllocationLib/PiSmmCoreMemoryAllocationLib.inf b/MdeModulePkg/Library/PiSmmCoreMemoryAllocationLib/PiSmmCoreMemoryAllocationLib.inf index e8f7081149..f2a0bf8853 100644 --- a/MdeModulePkg/Library/PiSmmCoreMemoryAllocationLib/PiSmmCoreMemoryAllocationLib.inf +++ b/MdeModulePkg/Library/PiSmmCoreMemoryAllocationLib/PiSmmCoreMemoryAllocationLib.inf @@ -1,10 +1,10 @@ ## @file # Memory Allocation Library instance dedicated to SMM Core. # The implementation borrows the SMM Core Memory Allocation services as the primitive -# for memory allocation instead of using SMM System Table servces in an indirect way. -# It is assumed that this library instance must be linked with SMM Cre in this package. +# for memory allocation instead of using SMM System Table services in an indirect way. +# It is assumed that this library instance must be linked with SMM Cre in this package. # -# Copyright (c) 2010 - 2015, Intel Corporation. All rights reserved.
+# Copyright (c) 2010 - 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 @@ -35,14 +35,13 @@ [Sources] MemoryAllocationLib.c PiSmmCoreMemoryAllocationServices.h + PiSmmCoreMemoryProfileLibNull.c [Packages] MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec [LibraryClasses] DebugLib BaseMemoryLib UefiBootServicesTableLib - -[Protocols] - gEfiSmmAccess2ProtocolGuid ## CONSUMES diff --git a/MdeModulePkg/Library/PiSmmCoreMemoryAllocationLib/PiSmmCoreMemoryAllocationLib.uni b/MdeModulePkg/Library/PiSmmCoreMemoryAllocationLib/PiSmmCoreMemoryAllocationLib.uni index 56bd6ee315..28e812b4df 100644 --- a/MdeModulePkg/Library/PiSmmCoreMemoryAllocationLib/PiSmmCoreMemoryAllocationLib.uni +++ b/MdeModulePkg/Library/PiSmmCoreMemoryAllocationLib/PiSmmCoreMemoryAllocationLib.uni @@ -2,10 +2,10 @@ // Memory Allocation Library instance dedicated to SMM Core. // // The implementation borrows the SMM Core Memory Allocation services as the primitive -// for memory allocation instead of using SMM System Table servces in an indirect way. +// for memory allocation instead of using SMM System Table services in an indirect way. // It is assumed that this library instance must be linked with SMM Cre in this package. // -// Copyright (c) 2010 - 2014, Intel Corporation. All rights reserved.
+// Copyright (c) 2010 - 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 diff --git a/MdeModulePkg/Library/PiSmmCoreMemoryAllocationLib/PiSmmCoreMemoryAllocationProfileLib.inf b/MdeModulePkg/Library/PiSmmCoreMemoryAllocationLib/PiSmmCoreMemoryAllocationProfileLib.inf new file mode 100644 index 0000000000..f9800b395f --- /dev/null +++ b/MdeModulePkg/Library/PiSmmCoreMemoryAllocationLib/PiSmmCoreMemoryAllocationProfileLib.inf @@ -0,0 +1,54 @@ +## @file +# Memory Allocation/Profile Library instance dedicated to SMM Core. +# The implementation borrows the SMM Core Memory Allocation/Profile services as the primitive +# for memory allocation/profile instead of using SMM System Table servces or SMM memory profile protocol in an indirect way. +# It is assumed that this library instance must be linked with SMM Cre in this package. +# +# Copyright (c) 2010 - 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 +# 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 = PiSmmCoreMemoryAllocationProfileLib + MODULE_UNI_FILE = PiSmmCoreMemoryAllocationProfileLib.uni + FILE_GUID = D55E42AD-3E63-4536-8281-82C0F1098C5E + MODULE_TYPE = SMM_CORE + VERSION_STRING = 1.0 + PI_SPECIFICATION_VERSION = 0x0001000A + LIBRARY_CLASS = MemoryAllocationLib|SMM_CORE + CONSTRUCTOR = PiSmmCoreMemoryAllocationLibConstructor + LIBRARY_CLASS = MemoryProfileLib|SMM_CORE + CONSTRUCTOR = PiSmmCoreMemoryProfileLibConstructor + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 +# + +[Sources] + MemoryAllocationLib.c + PiSmmCoreMemoryAllocationServices.h + PiSmmCoreMemoryProfileLib.c + PiSmmCoreMemoryProfileServices.h + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + +[LibraryClasses] + DebugLib + BaseMemoryLib + UefiBootServicesTableLib + +[Guids] + gEdkiiMemoryProfileGuid ## SOMETIMES_CONSUMES ## GUID # Locate protocol + diff --git a/MdeModulePkg/Library/PiSmmCoreMemoryAllocationLib/PiSmmCoreMemoryAllocationProfileLib.uni b/MdeModulePkg/Library/PiSmmCoreMemoryAllocationLib/PiSmmCoreMemoryAllocationProfileLib.uni new file mode 100644 index 0000000000..a56b117061 --- /dev/null +++ b/MdeModulePkg/Library/PiSmmCoreMemoryAllocationLib/PiSmmCoreMemoryAllocationProfileLib.uni @@ -0,0 +1,23 @@ +// /** @file +// Memory Allocation/Profile Library instance dedicated to SMM Core. +// +// The implementation borrows the SMM Core Memory Allocation/Profile services as the primitive +// for memory allocation/profile instead of using SMM System Table servces or SMM memory profile protocol in an indirect way. +// It is assumed that this library instance must be linked with SMM Cre in this package. +// +// Copyright (c) 2010 - 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 +// 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. +// +// **/ + + +#string STR_MODULE_ABSTRACT #language en-US "Memory Allocation/Profile Library instance dedicated to SMM Core" + +#string STR_MODULE_DESCRIPTION #language en-US "The implementation borrows the SMM Core Memory Allocation/Profile services as the primitive for memory allocation/profile instead of using SMM System Table services or SMM memory profile protocol in an indirect way. This library is only intended to be linked with the SMM Core that resides in this same package." + diff --git a/MdeModulePkg/Library/PiSmmCoreMemoryAllocationLib/PiSmmCoreMemoryProfileLib.c b/MdeModulePkg/Library/PiSmmCoreMemoryAllocationLib/PiSmmCoreMemoryProfileLib.c new file mode 100644 index 0000000000..f6a064aa82 --- /dev/null +++ b/MdeModulePkg/Library/PiSmmCoreMemoryAllocationLib/PiSmmCoreMemoryProfileLib.c @@ -0,0 +1,123 @@ +/** @file + Support routines for memory profile for PiSmmCore. + + Copyright (c) 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 + 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 + +#include +#include + +#include + +#include "PiSmmCoreMemoryProfileServices.h" + +EDKII_MEMORY_PROFILE_PROTOCOL *mLibProfileProtocol; + +/** + Check whether the start address of buffer is within any of the SMRAM ranges. + + @param[in] Buffer The pointer to the buffer to be checked. + + @retval TURE The buffer is in SMRAM ranges. + @retval FALSE The buffer is out of SMRAM ranges. +**/ +BOOLEAN +EFIAPI +BufferInSmram ( + IN VOID *Buffer + ); + +/** + The constructor function initializes memory profile for SMM phase. + + @param ImageHandle The firmware allocated handle for the EFI image. + @param SystemTable A pointer to the EFI System Table. + + @retval EFI_SUCCESS The constructor always returns EFI_SUCCESS. + +**/ +EFI_STATUS +EFIAPI +PiSmmCoreMemoryProfileLibConstructor ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + + // + // Locate Profile Protocol + // + Status = gBS->LocateProtocol ( + &gEdkiiMemoryProfileGuid, + NULL, + (VOID **)&mLibProfileProtocol + ); + if (EFI_ERROR (Status)) { + mLibProfileProtocol = NULL; + } + + return EFI_SUCCESS; +} + +/** + Record memory profile of multilevel caller. + + @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 +MemoryProfileLibRecord ( + IN PHYSICAL_ADDRESS CallerAddress, + IN MEMORY_PROFILE_ACTION Action, + IN EFI_MEMORY_TYPE MemoryType, + IN VOID *Buffer, + IN UINTN Size, + IN CHAR8 *ActionString OPTIONAL + ) +{ + if (BufferInSmram (Buffer)) { + return SmmCoreUpdateProfile (CallerAddress, Action, MemoryType, Size, Buffer, ActionString); + } else { + if (mLibProfileProtocol == NULL) { + return EFI_UNSUPPORTED; + } + return mLibProfileProtocol->Record ( + mLibProfileProtocol, + CallerAddress, + Action, + MemoryType, + Buffer, + Size, + ActionString + ); + } +} + diff --git a/MdeModulePkg/Library/PiSmmCoreMemoryAllocationLib/PiSmmCoreMemoryProfileLibNull.c b/MdeModulePkg/Library/PiSmmCoreMemoryAllocationLib/PiSmmCoreMemoryProfileLibNull.c new file mode 100644 index 0000000000..6f6c2ebc91 --- /dev/null +++ b/MdeModulePkg/Library/PiSmmCoreMemoryAllocationLib/PiSmmCoreMemoryProfileLibNull.c @@ -0,0 +1,54 @@ +/** @file + Null routines for memory profile for PiSmmCore. + + Copyright (c) 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 + 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 + +#include + +/** + Record memory profile of multilevel caller. + + @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 +MemoryProfileLibRecord ( + 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 EFI_UNSUPPORTED; +} + diff --git a/MdeModulePkg/Library/PiSmmCoreMemoryAllocationLib/PiSmmCoreMemoryProfileServices.h b/MdeModulePkg/Library/PiSmmCoreMemoryAllocationLib/PiSmmCoreMemoryProfileServices.h new file mode 100644 index 0000000000..29923ea0a2 --- /dev/null +++ b/MdeModulePkg/Library/PiSmmCoreMemoryAllocationLib/PiSmmCoreMemoryProfileServices.h @@ -0,0 +1,54 @@ +/** @file + Contains function prototypes for Memory Profile Services in the SMM Core. + + This header file borrows the PiSmmCore Memory Profile services as the primitive + for memory profile. + + Copyright (c) 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 + 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 _PI_SMM_CORE_MEMORY_PROFILE_SERVICES_H_ +#define _PI_SMM_CORE_MEMORY_PROFILE_SERVICES_H_ + +/** + 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. + 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. + + @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 +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 CHAR8 *ActionString OPTIONAL + ); + +#endif diff --git a/MdeModulePkg/Library/SmmMemoryAllocationProfileLib/MemoryAllocationLib.c b/MdeModulePkg/Library/SmmMemoryAllocationProfileLib/MemoryAllocationLib.c new file mode 100644 index 0000000000..34ff120f41 --- /dev/null +++ b/MdeModulePkg/Library/SmmMemoryAllocationProfileLib/MemoryAllocationLib.c @@ -0,0 +1,1140 @@ +/** @file + Support routines for memory allocation routines based + on SMM Services Table services for SMM phase drivers, with memory profile support. + + The PI System Management Mode Core Interface Specification only allows the use + of EfiRuntimeServicesCode and EfiRuntimeServicesData memory types for memory + allocations through the SMM Services Table as the SMRAM space should be + reserved after BDS phase. The functions in the Memory Allocation Library use + EfiBootServicesData as the default memory allocation type. For this SMM + specific instance of the Memory Allocation Library, EfiRuntimeServicesData + is used as the default memory type for all allocations. In addition, + allocation for the Reserved memory types are not supported and will always + return NULL. + + Copyright (c) 2006 - 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 + 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 + +#include +#include +#include +#include +#include +#include + +#include + +EFI_SMRAM_DESCRIPTOR *mSmramRanges; +UINTN mSmramRangeCount; + +/** + The constructor function caches SMRAM ranges that are present in the system. + + It will ASSERT() if SMM Access2 Protocol doesn't exist. + It will ASSERT() if SMRAM ranges can't be got. + It will ASSERT() if Resource can't be allocated for cache SMRAM range. + It will always return EFI_SUCCESS. + + @param ImageHandle The firmware allocated handle for the EFI image. + @param SystemTable A pointer to the EFI System Table. + + @retval EFI_SUCCESS The constructor always returns EFI_SUCCESS. + +**/ +EFI_STATUS +EFIAPI +SmmMemoryAllocationLibConstructor ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + EFI_SMM_ACCESS2_PROTOCOL *SmmAccess; + UINTN Size; + + // + // Locate SMM Access2 Protocol + // + Status = gBS->LocateProtocol ( + &gEfiSmmAccess2ProtocolGuid, + NULL, + (VOID **)&SmmAccess + ); + ASSERT_EFI_ERROR (Status); + + // + // Get SMRAM range information + // + Size = 0; + Status = SmmAccess->GetCapabilities (SmmAccess, &Size, NULL); + ASSERT (Status == EFI_BUFFER_TOO_SMALL); + + mSmramRanges = (EFI_SMRAM_DESCRIPTOR *) AllocatePool (Size); + ASSERT (mSmramRanges != NULL); + + Status = SmmAccess->GetCapabilities (SmmAccess, &Size, mSmramRanges); + ASSERT_EFI_ERROR (Status); + + mSmramRangeCount = Size / sizeof (EFI_SMRAM_DESCRIPTOR); + + return EFI_SUCCESS; +} + +/** + If SMM driver exits with an error, it must call this routine + to free the allocated resource before the exiting. + + @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 deconstructor always returns EFI_SUCCESS. +**/ +EFI_STATUS +EFIAPI +SmmMemoryAllocationLibDestructor ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + FreePool (mSmramRanges); + + return EFI_SUCCESS; +} + +/** + Check whether the start address of buffer is within any of the SMRAM ranges. + + @param[in] Buffer The pointer to the buffer to be checked. + + @retval TURE The buffer is in SMRAM ranges. + @retval FALSE The buffer is out of SMRAM ranges. +**/ +BOOLEAN +EFIAPI +BufferInSmram ( + IN VOID *Buffer + ) +{ + UINTN Index; + + for (Index = 0; Index < mSmramRangeCount; Index ++) { + if (((EFI_PHYSICAL_ADDRESS) (UINTN) Buffer >= mSmramRanges[Index].CpuStart) && + ((EFI_PHYSICAL_ADDRESS) (UINTN) Buffer < (mSmramRanges[Index].CpuStart + mSmramRanges[Index].PhysicalSize))) { + return TRUE; + } + } + + return FALSE; +} + +/** + Allocates one or more 4KB pages of a certain memory type. + + Allocates the number of 4KB pages of a certain memory type and returns a pointer + to the allocated buffer. The buffer returned is aligned on a 4KB boundary. If + Pages is 0, then NULL is returned. If there is not enough memory remaining to + satisfy the request, then NULL is returned. + + @param MemoryType The type of memory to allocate. + @param Pages The number of 4 KB pages to allocate. + + @return A pointer to the allocated buffer or NULL if allocation fails. + +**/ +VOID * +InternalAllocatePages ( + IN EFI_MEMORY_TYPE MemoryType, + IN UINTN Pages + ) +{ + EFI_STATUS Status; + EFI_PHYSICAL_ADDRESS Memory; + + if (Pages == 0) { + return NULL; + } + + Status = gSmst->SmmAllocatePages (AllocateAnyPages, MemoryType, Pages, &Memory); + if (EFI_ERROR (Status)) { + return NULL; + } + return (VOID *) (UINTN) Memory; +} + +/** + Allocates one or more 4KB pages of type EfiRuntimeServicesData. + + Allocates the number of 4KB pages of type EfiRuntimeServicesData and returns a pointer + to the allocated buffer. The buffer returned is aligned on a 4KB boundary. If + Pages is 0, then NULL is returned. If there is not enough memory remaining to + satisfy the request, then NULL is returned. + + @param Pages The number of 4 KB pages to allocate. + + @return A pointer to the allocated buffer or NULL if allocation fails. + +**/ +VOID * +EFIAPI +AllocatePages ( + IN UINTN Pages + ) +{ + VOID *Buffer; + + Buffer = InternalAllocatePages (EfiRuntimeServicesData, Pages); + if (Buffer != NULL) { + MemoryProfileLibRecord ( + (PHYSICAL_ADDRESS) (UINTN) RETURN_ADDRESS(0), + MEMORY_PROFILE_ACTION_LIB_ALLOCATE_PAGES, + EfiRuntimeServicesData, + Buffer, + EFI_PAGES_TO_SIZE(Pages), + NULL + ); + } + return Buffer; +} + +/** + Allocates one or more 4KB pages of type EfiRuntimeServicesData. + + Allocates the number of 4KB pages of type EfiRuntimeServicesData and returns a + pointer to the allocated buffer. The buffer returned is aligned on a 4KB boundary. + If Pages is 0, then NULL is returned. If there is not enough memory remaining + to satisfy the request, then NULL is returned. + + @param Pages The number of 4 KB pages to allocate. + + @return A pointer to the allocated buffer or NULL if allocation fails. + +**/ +VOID * +EFIAPI +AllocateRuntimePages ( + IN UINTN Pages + ) +{ + VOID *Buffer; + + Buffer = InternalAllocatePages (EfiRuntimeServicesData, Pages); + if (Buffer != NULL) { + MemoryProfileLibRecord ( + (PHYSICAL_ADDRESS) (UINTN) RETURN_ADDRESS(0), + MEMORY_PROFILE_ACTION_LIB_ALLOCATE_RUNTIME_PAGES, + EfiRuntimeServicesData, + Buffer, + EFI_PAGES_TO_SIZE(Pages), + NULL + ); + } + return Buffer; +} + +/** + Allocates one or more 4KB pages of type EfiReservedMemoryType. + + Allocates the number of 4KB pages of type EfiReservedMemoryType and returns a + pointer to the allocated buffer. The buffer returned is aligned on a 4KB boundary. + If Pages is 0, then NULL is returned. If there is not enough memory remaining + to satisfy the request, then NULL is returned. + + @param Pages The number of 4 KB pages to allocate. + + @return A pointer to the allocated buffer or NULL if allocation fails. + +**/ +VOID * +EFIAPI +AllocateReservedPages ( + IN UINTN Pages + ) +{ + return NULL; +} + +/** + Frees one or more 4KB pages that were previously allocated with one of the page allocation + functions in the Memory Allocation Library. + + Frees the number of 4KB pages specified by Pages from the buffer specified by Buffer. + Buffer must have been allocated on a previous call to the page allocation services + of the Memory Allocation Library. If it is not possible to free allocated pages, + then this function will perform no actions. + + If Buffer was not allocated with a page allocation function in the Memory Allocation + Library, then ASSERT(). + If Pages is zero, then ASSERT(). + + @param Buffer The pointer to the buffer of pages to free. + @param Pages The number of 4 KB pages to free. + +**/ +VOID +EFIAPI +FreePages ( + IN VOID *Buffer, + IN UINTN Pages + ) +{ + EFI_STATUS Status; + + ASSERT (Pages != 0); + if (BufferInSmram (Buffer)) { + // + // When Buffer is in SMRAM range, it should be allocated by gSmst->SmmAllocatePages() service. + // So, gSmst->SmmFreePages() service is used to free it. + // + Status = gSmst->SmmFreePages ((EFI_PHYSICAL_ADDRESS) (UINTN) Buffer, Pages); + } else { + // + // When Buffer is out of SMRAM range, it should be allocated by gBS->AllocatePages() service. + // So, gBS->FreePages() service is used to free it. + // + Status = gBS->FreePages ((EFI_PHYSICAL_ADDRESS) (UINTN) Buffer, Pages); + } + ASSERT_EFI_ERROR (Status); +} + +/** + Allocates one or more 4KB pages of a certain memory type at a specified alignment. + + Allocates the number of 4KB pages specified by Pages of a certain memory type + with an alignment specified by Alignment. The allocated buffer is returned. + If Pages is 0, then NULL is returned. If there is not enough memory at the + specified alignment remaining to satisfy the request, then NULL is returned. + If Alignment is not a power of two and Alignment is not zero, then ASSERT(). + If Pages plus EFI_SIZE_TO_PAGES (Alignment) overflows, then ASSERT(). + + @param MemoryType The type of memory to allocate. + @param Pages The number of 4 KB pages to allocate. + @param Alignment The requested alignment of the allocation. + Must be a power of two. + If Alignment is zero, then byte alignment is used. + + @return A pointer to the allocated buffer or NULL if allocation fails. + +**/ +VOID * +InternalAllocateAlignedPages ( + IN EFI_MEMORY_TYPE MemoryType, + IN UINTN Pages, + IN UINTN Alignment + ) +{ + EFI_STATUS Status; + EFI_PHYSICAL_ADDRESS Memory; + UINTN AlignedMemory; + UINTN AlignmentMask; + UINTN UnalignedPages; + UINTN RealPages; + + // + // Alignment must be a power of two or zero. + // + ASSERT ((Alignment & (Alignment - 1)) == 0); + + if (Pages == 0) { + return NULL; + } + if (Alignment > EFI_PAGE_SIZE) { + // + // Calculate the total number of pages since alignment is larger than page size. + // + AlignmentMask = Alignment - 1; + RealPages = Pages + EFI_SIZE_TO_PAGES (Alignment); + // + // Make sure that Pages plus EFI_SIZE_TO_PAGES (Alignment) does not overflow. + // + ASSERT (RealPages > Pages); + + Status = gSmst->SmmAllocatePages (AllocateAnyPages, MemoryType, RealPages, &Memory); + if (EFI_ERROR (Status)) { + return NULL; + } + AlignedMemory = ((UINTN) Memory + AlignmentMask) & ~AlignmentMask; + UnalignedPages = EFI_SIZE_TO_PAGES (AlignedMemory - (UINTN) Memory); + if (UnalignedPages > 0) { + // + // Free first unaligned page(s). + // + Status = gSmst->SmmFreePages (Memory, UnalignedPages); + ASSERT_EFI_ERROR (Status); + } + Memory = (EFI_PHYSICAL_ADDRESS) (AlignedMemory + EFI_PAGES_TO_SIZE (Pages)); + UnalignedPages = RealPages - Pages - UnalignedPages; + if (UnalignedPages > 0) { + // + // Free last unaligned page(s). + // + Status = gSmst->SmmFreePages (Memory, UnalignedPages); + ASSERT_EFI_ERROR (Status); + } + } else { + // + // Do not over-allocate pages in this case. + // + Status = gSmst->SmmAllocatePages (AllocateAnyPages, MemoryType, Pages, &Memory); + if (EFI_ERROR (Status)) { + return NULL; + } + AlignedMemory = (UINTN) Memory; + } + return (VOID *) AlignedMemory; +} + +/** + Allocates one or more 4KB pages of type EfiRuntimeServicesData at a specified alignment. + + Allocates the number of 4KB pages specified by Pages of type EfiRuntimeServicesData + with an alignment specified by Alignment. The allocated buffer is returned. + If Pages is 0, then NULL is returned. If there is not enough memory at the + specified alignment remaining to satisfy the request, then NULL is returned. + + If Alignment is not a power of two and Alignment is not zero, then ASSERT(). + If Pages plus EFI_SIZE_TO_PAGES (Alignment) overflows, then ASSERT(). + + @param Pages The number of 4 KB pages to allocate. + @param Alignment The requested alignment of the allocation. + Must be a power of two. + If Alignment is zero, then byte alignment is used. + + @return A pointer to the allocated buffer or NULL if allocation fails. + +**/ +VOID * +EFIAPI +AllocateAlignedPages ( + IN UINTN Pages, + IN UINTN Alignment + ) +{ + VOID *Buffer; + + Buffer = InternalAllocateAlignedPages (EfiRuntimeServicesData, Pages, Alignment); + if (Buffer != NULL) { + MemoryProfileLibRecord ( + (PHYSICAL_ADDRESS) (UINTN) RETURN_ADDRESS(0), + MEMORY_PROFILE_ACTION_LIB_ALLOCATE_ALIGNED_PAGES, + EfiRuntimeServicesData, + Buffer, + EFI_PAGES_TO_SIZE(Pages), + NULL + ); + } + return Buffer; +} + +/** + Allocates one or more 4KB pages of type EfiRuntimeServicesData at a specified alignment. + + Allocates the number of 4KB pages specified by Pages of type EfiRuntimeServicesData + with an alignment specified by Alignment. The allocated buffer is returned. + If Pages is 0, then NULL is returned. If there is not enough memory at the + specified alignment remaining to satisfy the request, then NULL is returned. + + If Alignment is not a power of two and Alignment is not zero, then ASSERT(). + If Pages plus EFI_SIZE_TO_PAGES (Alignment) overflows, then ASSERT(). + + @param Pages The number of 4 KB pages to allocate. + @param Alignment The requested alignment of the allocation. + Must be a power of two. + If Alignment is zero, then byte alignment is used. + + @return A pointer to the allocated buffer or NULL if allocation fails. + +**/ +VOID * +EFIAPI +AllocateAlignedRuntimePages ( + IN UINTN Pages, + IN UINTN Alignment + ) +{ + VOID *Buffer; + + Buffer = InternalAllocateAlignedPages (EfiRuntimeServicesData, Pages, Alignment); + if (Buffer != NULL) { + MemoryProfileLibRecord ( + (PHYSICAL_ADDRESS) (UINTN) RETURN_ADDRESS(0), + MEMORY_PROFILE_ACTION_LIB_ALLOCATE_ALIGNED_RUNTIME_PAGES, + EfiRuntimeServicesData, + Buffer, + EFI_PAGES_TO_SIZE(Pages), + NULL + ); + } + return Buffer; +} + +/** + Allocates one or more 4KB pages of type EfiReservedMemoryType at a specified alignment. + + Allocates the number of 4KB pages specified by Pages of type EfiReservedMemoryType + with an alignment specified by Alignment. The allocated buffer is returned. + If Pages is 0, then NULL is returned. If there is not enough memory at the + specified alignment remaining to satisfy the request, then NULL is returned. + + If Alignment is not a power of two and Alignment is not zero, then ASSERT(). + If Pages plus EFI_SIZE_TO_PAGES (Alignment) overflows, then ASSERT(). + + @param Pages The number of 4 KB pages to allocate. + @param Alignment The requested alignment of the allocation. + Must be a power of two. + If Alignment is zero, then byte alignment is used. + + @return A pointer to the allocated buffer or NULL if allocation fails. + +**/ +VOID * +EFIAPI +AllocateAlignedReservedPages ( + IN UINTN Pages, + IN UINTN Alignment + ) +{ + return NULL; +} + +/** + Frees one or more 4KB pages that were previously allocated with one of the aligned page + allocation functions in the Memory Allocation Library. + + Frees the number of 4KB pages specified by Pages from the buffer specified by + Buffer. Buffer must have been allocated on a previous call to the aligned page + allocation services of the Memory Allocation Library. If it is not possible to + free allocated pages, then this function will perform no actions. + + If Buffer was not allocated with an aligned page allocation function in the + Memory Allocation Library, then ASSERT(). + If Pages is zero, then ASSERT(). + + @param Buffer The pointer to the buffer of pages to free. + @param Pages The number of 4 KB pages to free. + +**/ +VOID +EFIAPI +FreeAlignedPages ( + IN VOID *Buffer, + IN UINTN Pages + ) +{ + EFI_STATUS Status; + + ASSERT (Pages != 0); + if (BufferInSmram (Buffer)) { + // + // When Buffer is in SMRAM range, it should be allocated by gSmst->SmmAllocatePages() service. + // So, gSmst->SmmFreePages() service is used to free it. + // + Status = gSmst->SmmFreePages ((EFI_PHYSICAL_ADDRESS) (UINTN) Buffer, Pages); + } else { + // + // When Buffer is out of SMRAM range, it should be allocated by gBS->AllocatePages() service. + // So, gBS->FreePages() service is used to free it. + // + Status = gBS->FreePages ((EFI_PHYSICAL_ADDRESS) (UINTN) Buffer, Pages); + } + ASSERT_EFI_ERROR (Status); +} + +/** + Allocates a buffer of a certain pool type. + + Allocates the number bytes specified by AllocationSize of a certain pool type + and returns a pointer to the allocated buffer. If AllocationSize is 0, then a + valid buffer of 0 size is returned. If there is not enough memory remaining to + satisfy the request, then NULL is returned. + + @param MemoryType The type of memory to allocate. + @param AllocationSize The number of bytes to allocate. + + @return A pointer to the allocated buffer or NULL if allocation fails. + +**/ +VOID * +InternalAllocatePool ( + IN EFI_MEMORY_TYPE MemoryType, + IN UINTN AllocationSize + ) +{ + EFI_STATUS Status; + VOID *Memory; + + Status = gSmst->SmmAllocatePool (MemoryType, AllocationSize, &Memory); + if (EFI_ERROR (Status)) { + Memory = NULL; + } + return Memory; +} + +/** + Allocates a buffer of type EfiRuntimeServicesData. + + Allocates the number bytes specified by AllocationSize of type EfiRuntimeServicesData + and returns a pointer to the allocated buffer. If AllocationSize is 0, then a + valid buffer of 0 size is returned. If there is not enough memory remaining to + satisfy the request, then NULL is returned. + + @param AllocationSize The number of bytes to allocate. + + @return A pointer to the allocated buffer or NULL if allocation fails. + +**/ +VOID * +EFIAPI +AllocatePool ( + IN UINTN AllocationSize + ) +{ + VOID *Buffer; + + Buffer = InternalAllocatePool (EfiRuntimeServicesData, AllocationSize); + if (Buffer != NULL) { + MemoryProfileLibRecord ( + (PHYSICAL_ADDRESS) (UINTN) RETURN_ADDRESS(0), + MEMORY_PROFILE_ACTION_LIB_ALLOCATE_POOL, + EfiRuntimeServicesData, + Buffer, + AllocationSize, + NULL + ); + } + return Buffer; +} + +/** + Allocates a buffer of type EfiRuntimeServicesData. + + Allocates the number bytes specified by AllocationSize of type EfiRuntimeServicesData + and returns a pointer to the allocated buffer. If AllocationSize is 0, then a + valid buffer of 0 size is returned. If there is not enough memory remaining to + satisfy the request, then NULL is returned. + + @param AllocationSize The number of bytes to allocate. + + @return A pointer to the allocated buffer or NULL if allocation fails. + +**/ +VOID * +EFIAPI +AllocateRuntimePool ( + IN UINTN AllocationSize + ) +{ + VOID *Buffer; + + Buffer = InternalAllocatePool (EfiRuntimeServicesData, AllocationSize); + if (Buffer != NULL) { + MemoryProfileLibRecord ( + (PHYSICAL_ADDRESS) (UINTN) RETURN_ADDRESS(0), + MEMORY_PROFILE_ACTION_LIB_ALLOCATE_RUNTIME_POOL, + EfiRuntimeServicesData, + Buffer, + AllocationSize, + NULL + ); + } + return Buffer; +} + +/** + Allocates a buffer of type EfiReservedMemoryType. + + Allocates the number bytes specified by AllocationSize of type EfiReservedMemoryType + and returns a pointer to the allocated buffer. If AllocationSize is 0, then a + valid buffer of 0 size is returned. If there is not enough memory remaining to + satisfy the request, then NULL is returned. + + @param AllocationSize The number of bytes to allocate. + + @return A pointer to the allocated buffer or NULL if allocation fails. + +**/ +VOID * +EFIAPI +AllocateReservedPool ( + IN UINTN AllocationSize + ) +{ + return NULL; +} + +/** + Allocates and zeros a buffer of a certain pool type. + + Allocates the number bytes specified by AllocationSize of a certain pool type, + clears the buffer with zeros, and returns a pointer to the allocated buffer. + If AllocationSize is 0, then a valid buffer of 0 size is returned. If there is + not enough memory remaining to satisfy the request, then NULL is returned. + + @param PoolType The type of memory to allocate. + @param AllocationSize The number of bytes to allocate and zero. + + @return A pointer to the allocated buffer or NULL if allocation fails. + +**/ +VOID * +InternalAllocateZeroPool ( + IN EFI_MEMORY_TYPE PoolType, + IN UINTN AllocationSize + ) +{ + VOID *Memory; + + Memory = InternalAllocatePool (PoolType, AllocationSize); + if (Memory != NULL) { + Memory = ZeroMem (Memory, AllocationSize); + } + return Memory; +} + +/** + Allocates and zeros a buffer of type EfiRuntimeServicesData. + + Allocates the number bytes specified by AllocationSize of type EfiRuntimeServicesData, + clears the buffer with zeros, and returns a pointer to the allocated buffer. + If AllocationSize is 0, then a valid buffer of 0 size is returned. If there is + not enough memory remaining to satisfy the request, then NULL is returned. + + @param AllocationSize The number of bytes to allocate and zero. + + @return A pointer to the allocated buffer or NULL if allocation fails. + +**/ +VOID * +EFIAPI +AllocateZeroPool ( + IN UINTN AllocationSize + ) +{ + VOID *Buffer; + + Buffer = InternalAllocateZeroPool (EfiRuntimeServicesData, AllocationSize); + if (Buffer != NULL) { + MemoryProfileLibRecord ( + (PHYSICAL_ADDRESS) (UINTN) RETURN_ADDRESS(0), + MEMORY_PROFILE_ACTION_LIB_ALLOCATE_ZERO_POOL, + EfiRuntimeServicesData, + Buffer, + AllocationSize, + NULL + ); + } + return Buffer; +} + +/** + Allocates and zeros a buffer of type EfiRuntimeServicesData. + + Allocates the number bytes specified by AllocationSize of type EfiRuntimeServicesData, + clears the buffer with zeros, and returns a pointer to the allocated buffer. + If AllocationSize is 0, then a valid buffer of 0 size is returned. If there is + not enough memory remaining to satisfy the request, then NULL is returned. + + @param AllocationSize The number of bytes to allocate and zero. + + @return A pointer to the allocated buffer or NULL if allocation fails. + +**/ +VOID * +EFIAPI +AllocateRuntimeZeroPool ( + IN UINTN AllocationSize + ) +{ + VOID *Buffer; + + Buffer = InternalAllocateZeroPool (EfiRuntimeServicesData, AllocationSize); + if (Buffer != NULL) { + MemoryProfileLibRecord ( + (PHYSICAL_ADDRESS) (UINTN) RETURN_ADDRESS(0), + MEMORY_PROFILE_ACTION_LIB_ALLOCATE_RUNTIME_ZERO_POOL, + EfiRuntimeServicesData, + Buffer, + AllocationSize, + NULL + ); + } + return Buffer; +} + +/** + Allocates and zeros a buffer of type EfiReservedMemoryType. + + Allocates the number bytes specified by AllocationSize of type EfiReservedMemoryType, + clears the buffer with zeros, and returns a pointer to the allocated buffer. + If AllocationSize is 0, then a valid buffer of 0 size is returned. If there is + not enough memory remaining to satisfy the request, then NULL is returned. + + @param AllocationSize The number of bytes to allocate and zero. + + @return A pointer to the allocated buffer or NULL if allocation fails. + +**/ +VOID * +EFIAPI +AllocateReservedZeroPool ( + IN UINTN AllocationSize + ) +{ + return NULL; +} + +/** + Copies a buffer to an allocated buffer of a certain pool type. + + Allocates the number bytes specified by AllocationSize of a certain pool type, + copies AllocationSize bytes from Buffer to the newly allocated buffer, and returns + a pointer to the allocated buffer. If AllocationSize is 0, then a valid buffer + of 0 size is returned. If there is not enough memory remaining to satisfy the + request, then NULL is returned. If Buffer is NULL, then ASSERT(). + If AllocationSize is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). + + @param PoolType The type of pool to allocate. + @param AllocationSize The number of bytes to allocate and zero. + @param Buffer The buffer to copy to the allocated buffer. + + @return A pointer to the allocated buffer or NULL if allocation fails. + +**/ +VOID * +InternalAllocateCopyPool ( + IN EFI_MEMORY_TYPE PoolType, + IN UINTN AllocationSize, + IN CONST VOID *Buffer + ) +{ + VOID *Memory; + + ASSERT (Buffer != NULL); + ASSERT (AllocationSize <= (MAX_ADDRESS - (UINTN) Buffer + 1)); + + Memory = InternalAllocatePool (PoolType, AllocationSize); + if (Memory != NULL) { + Memory = CopyMem (Memory, Buffer, AllocationSize); + } + return Memory; +} + +/** + Copies a buffer to an allocated buffer of type EfiRuntimeServicesData. + + Allocates the number bytes specified by AllocationSize of type EfiRuntimeServicesData, + copies AllocationSize bytes from Buffer to the newly allocated buffer, and returns + a pointer to the allocated buffer. If AllocationSize is 0, then a valid buffer + of 0 size is returned. If there is not enough memory remaining to satisfy the + request, then NULL is returned. + + If Buffer is NULL, then ASSERT(). + If AllocationSize is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). + + @param AllocationSize The number of bytes to allocate and zero. + @param Buffer The buffer to copy to the allocated buffer. + + @return A pointer to the allocated buffer or NULL if allocation fails. + +**/ +VOID * +EFIAPI +AllocateCopyPool ( + IN UINTN AllocationSize, + IN CONST VOID *Buffer + ) +{ + VOID *NewBuffer; + + NewBuffer = InternalAllocateCopyPool (EfiRuntimeServicesData, AllocationSize, Buffer); + if (NewBuffer != NULL) { + MemoryProfileLibRecord ( + (PHYSICAL_ADDRESS) (UINTN) RETURN_ADDRESS(0), + MEMORY_PROFILE_ACTION_LIB_ALLOCATE_COPY_POOL, + EfiRuntimeServicesData, + NewBuffer, + AllocationSize, + NULL + ); + } + return NewBuffer; +} + +/** + Copies a buffer to an allocated buffer of type EfiRuntimeServicesData. + + Allocates the number bytes specified by AllocationSize of type EfiRuntimeServicesData, + copies AllocationSize bytes from Buffer to the newly allocated buffer, and returns + a pointer to the allocated buffer. If AllocationSize is 0, then a valid buffer + of 0 size is returned. If there is not enough memory remaining to satisfy the + request, then NULL is returned. + + If Buffer is NULL, then ASSERT(). + If AllocationSize is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). + + @param AllocationSize The number of bytes to allocate and zero. + @param Buffer The buffer to copy to the allocated buffer. + + @return A pointer to the allocated buffer or NULL if allocation fails. + +**/ +VOID * +EFIAPI +AllocateRuntimeCopyPool ( + IN UINTN AllocationSize, + IN CONST VOID *Buffer + ) +{ + VOID *NewBuffer; + + NewBuffer = InternalAllocateCopyPool (EfiRuntimeServicesData, AllocationSize, Buffer); + if (NewBuffer != NULL) { + MemoryProfileLibRecord ( + (PHYSICAL_ADDRESS) (UINTN) RETURN_ADDRESS(0), + MEMORY_PROFILE_ACTION_LIB_ALLOCATE_RUNTIME_COPY_POOL, + EfiRuntimeServicesData, + NewBuffer, + AllocationSize, + NULL + ); + } + return NewBuffer; +} + +/** + Copies a buffer to an allocated buffer of type EfiReservedMemoryType. + + Allocates the number bytes specified by AllocationSize of type EfiReservedMemoryType, + copies AllocationSize bytes from Buffer to the newly allocated buffer, and returns + a pointer to the allocated buffer. If AllocationSize is 0, then a valid buffer + of 0 size is returned. If there is not enough memory remaining to satisfy the + request, then NULL is returned. + + If Buffer is NULL, then ASSERT(). + If AllocationSize is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). + + @param AllocationSize The number of bytes to allocate and zero. + @param Buffer The buffer to copy to the allocated buffer. + + @return A pointer to the allocated buffer or NULL if allocation fails. + +**/ +VOID * +EFIAPI +AllocateReservedCopyPool ( + IN UINTN AllocationSize, + IN CONST VOID *Buffer + ) +{ + return NULL; +} + +/** + Reallocates a buffer of a specified memory type. + + Allocates and zeros the number bytes specified by NewSize from memory of the type + specified by PoolType. If OldBuffer is not NULL, then the smaller of OldSize and + NewSize bytes are copied from OldBuffer to the newly allocated buffer, and + OldBuffer is freed. A pointer to the newly allocated buffer is returned. + If NewSize is 0, then a valid buffer of 0 size is returned. If there is not + enough memory remaining to satisfy the request, then NULL is returned. + + If the allocation of the new buffer is successful and the smaller of NewSize + and OldSize is greater than (MAX_ADDRESS - OldBuffer + 1), then ASSERT(). + + @param PoolType The type of pool to allocate. + @param OldSize The size, in bytes, of OldBuffer. + @param NewSize The size, in bytes, of the buffer to reallocate. + @param OldBuffer The buffer to copy to the allocated buffer. This is an + optional parameter that may be NULL. + + @return A pointer to the allocated buffer or NULL if allocation fails. + +**/ +VOID * +InternalReallocatePool ( + IN EFI_MEMORY_TYPE PoolType, + IN UINTN OldSize, + IN UINTN NewSize, + IN VOID *OldBuffer OPTIONAL + ) +{ + VOID *NewBuffer; + + NewBuffer = InternalAllocateZeroPool (PoolType, NewSize); + if (NewBuffer != NULL && OldBuffer != NULL) { + CopyMem (NewBuffer, OldBuffer, MIN (OldSize, NewSize)); + FreePool (OldBuffer); + } + return NewBuffer; +} + +/** + Reallocates a buffer of type EfiRuntimeServicesData. + + Allocates and zeros the number bytes specified by NewSize from memory of type + EfiRuntimeServicesData. If OldBuffer is not NULL, then the smaller of OldSize and + NewSize bytes are copied from OldBuffer to the newly allocated buffer, and + OldBuffer is freed. A pointer to the newly allocated buffer is returned. + If NewSize is 0, then a valid buffer of 0 size is returned. If there is not + enough memory remaining to satisfy the request, then NULL is returned. + + If the allocation of the new buffer is successful and the smaller of NewSize + and OldSize is greater than (MAX_ADDRESS - OldBuffer + 1), then ASSERT(). + + @param OldSize The size, in bytes, of OldBuffer. + @param NewSize The size, in bytes, of the buffer to reallocate. + @param OldBuffer The buffer to copy to the allocated buffer. This is an + optional parameter that may be NULL. + + @return A pointer to the allocated buffer or NULL if allocation fails. + +**/ +VOID * +EFIAPI +ReallocatePool ( + IN UINTN OldSize, + IN UINTN NewSize, + IN VOID *OldBuffer OPTIONAL + ) +{ + VOID *Buffer; + + Buffer = InternalReallocatePool (EfiRuntimeServicesData, OldSize, NewSize, OldBuffer); + if (Buffer != NULL) { + MemoryProfileLibRecord ( + (PHYSICAL_ADDRESS) (UINTN) RETURN_ADDRESS(0), + MEMORY_PROFILE_ACTION_LIB_REALLOCATE_POOL, + EfiRuntimeServicesData, + Buffer, + NewSize, + NULL + ); + } + return Buffer; +} + +/** + Reallocates a buffer of type EfiRuntimeServicesData. + + Allocates and zeros the number bytes specified by NewSize from memory of type + EfiRuntimeServicesData. If OldBuffer is not NULL, then the smaller of OldSize + and NewSize bytes are copied from OldBuffer to the newly allocated buffer, and + OldBuffer is freed. A pointer to the newly allocated buffer is returned. + If NewSize is 0, then a valid buffer of 0 size is returned. If there is not + enough memory remaining to satisfy the request, then NULL is returned. + + If the allocation of the new buffer is successful and the smaller of NewSize + and OldSize is greater than (MAX_ADDRESS - OldBuffer + 1), then ASSERT(). + + @param OldSize The size, in bytes, of OldBuffer. + @param NewSize The size, in bytes, of the buffer to reallocate. + @param OldBuffer The buffer to copy to the allocated buffer. This is an + optional parameter that may be NULL. + + @return A pointer to the allocated buffer or NULL if allocation fails. + +**/ +VOID * +EFIAPI +ReallocateRuntimePool ( + IN UINTN OldSize, + IN UINTN NewSize, + IN VOID *OldBuffer OPTIONAL + ) +{ + VOID *Buffer; + + Buffer = InternalReallocatePool (EfiRuntimeServicesData, OldSize, NewSize, OldBuffer); + if (Buffer != NULL) { + MemoryProfileLibRecord ( + (PHYSICAL_ADDRESS) (UINTN) RETURN_ADDRESS(0), + MEMORY_PROFILE_ACTION_LIB_REALLOCATE_RUNTIME_POOL, + EfiRuntimeServicesData, + Buffer, + NewSize, + NULL + ); + } + return Buffer; +} + +/** + Reallocates a buffer of type EfiReservedMemoryType. + + Allocates and zeros the number bytes specified by NewSize from memory of type + EfiReservedMemoryType. If OldBuffer is not NULL, then the smaller of OldSize + and NewSize bytes are copied from OldBuffer to the newly allocated buffer, and + OldBuffer is freed. A pointer to the newly allocated buffer is returned. + If NewSize is 0, then a valid buffer of 0 size is returned. If there is not + enough memory remaining to satisfy the request, then NULL is returned. + + If the allocation of the new buffer is successful and the smaller of NewSize + and OldSize is greater than (MAX_ADDRESS - OldBuffer + 1), then ASSERT(). + + @param OldSize The size, in bytes, of OldBuffer. + @param NewSize The size, in bytes, of the buffer to reallocate. + @param OldBuffer The buffer to copy to the allocated buffer. This is an + optional parameter that may be NULL. + + @return A pointer to the allocated buffer or NULL if allocation fails. + +**/ +VOID * +EFIAPI +ReallocateReservedPool ( + IN UINTN OldSize, + IN UINTN NewSize, + IN VOID *OldBuffer OPTIONAL + ) +{ + return NULL; +} + +/** + Frees a buffer that was previously allocated with one of the pool allocation + functions in the Memory Allocation Library. + + Frees the buffer specified by Buffer. Buffer must have been allocated on a + previous call to the pool allocation services of the Memory Allocation Library. + If it is not possible to free pool resources, then this function will perform + no actions. + + If Buffer was not allocated with a pool allocation function in the Memory + Allocation Library, then ASSERT(). + + @param Buffer The pointer to the buffer to free. + +**/ +VOID +EFIAPI +FreePool ( + IN VOID *Buffer + ) +{ + EFI_STATUS Status; + + if (BufferInSmram (Buffer)) { + // + // When Buffer is in SMRAM range, it should be allocated by gSmst->SmmAllocatePool() service. + // So, gSmst->SmmFreePool() service is used to free it. + // + Status = gSmst->SmmFreePool (Buffer); + } else { + // + // When Buffer is out of SMRAM range, it should be allocated by gBS->AllocatePool() service. + // So, gBS->FreePool() service is used to free it. + // + Status = gBS->FreePool (Buffer); + } + ASSERT_EFI_ERROR (Status); +} diff --git a/MdeModulePkg/Library/SmmMemoryAllocationProfileLib/SmmMemoryAllocationProfileLib.inf b/MdeModulePkg/Library/SmmMemoryAllocationProfileLib/SmmMemoryAllocationProfileLib.inf new file mode 100644 index 0000000000..60ec75c30e --- /dev/null +++ b/MdeModulePkg/Library/SmmMemoryAllocationProfileLib/SmmMemoryAllocationProfileLib.inf @@ -0,0 +1,62 @@ +## @file +# Instance of Memory Allocation Library using SMM Services Table, +# with memory profile support. +# +# Memory Allocation Library that uses services from the SMM Services Table to +# allocate and free memory, with memory profile support. +# +# The implementation of this instance is copied from UefiMemoryAllocationLib +# in MdePkg and updated to support both MemoryAllocationLib and MemoryProfileLib. +# +# Copyright (c) 2010 - 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 +# 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 = SmmMemoryAllocationProfileLib + MODULE_UNI_FILE = SmmMemoryAllocationProfileLib.uni + FILE_GUID = DC50729F-8633-47ab-8FD3-6939688CEE4C + MODULE_TYPE = DXE_SMM_DRIVER + VERSION_STRING = 1.0 + PI_SPECIFICATION_VERSION = 0x0001000A + LIBRARY_CLASS = MemoryAllocationLib|DXE_SMM_DRIVER + CONSTRUCTOR = SmmMemoryAllocationLibConstructor + DESTRUCTOR = SmmMemoryAllocationLibDestructor + LIBRARY_CLASS = MemoryProfileLib|DXE_SMM_DRIVER + CONSTRUCTOR = SmmMemoryProfileLibConstructor + +# +# VALID_ARCHITECTURES = IA32 X64 +# + +[Sources] + MemoryAllocationLib.c + SmmMemoryProfileLib.c + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + +[LibraryClasses] + DebugLib + BaseMemoryLib + SmmServicesTableLib + UefiBootServicesTableLib + +[Protocols] + gEfiSmmAccess2ProtocolGuid ## CONSUMES + +[Guids] + gEdkiiMemoryProfileGuid ## SOMETIMES_CONSUMES ## GUID # Locate protocol + gEdkiiSmmMemoryProfileGuid ## SOMETIMES_CONSUMES ## GUID # Locate protocol + +[Depex] + gEfiSmmAccess2ProtocolGuid + diff --git a/MdeModulePkg/Library/SmmMemoryAllocationProfileLib/SmmMemoryAllocationProfileLib.uni b/MdeModulePkg/Library/SmmMemoryAllocationProfileLib/SmmMemoryAllocationProfileLib.uni new file mode 100644 index 0000000000..a0774f0204 --- /dev/null +++ b/MdeModulePkg/Library/SmmMemoryAllocationProfileLib/SmmMemoryAllocationProfileLib.uni @@ -0,0 +1,23 @@ +// /** @file +// Instance of Memory Allocation Library using SMM Services Table, +// with memory profile support. +// +// Memory Allocation Library that uses services from the SMM Services Table to +// allocate and free memory, with memory profile support. +// +// Copyright (c) 2010 - 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 +// 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. +// +// **/ + + +#string STR_MODULE_ABSTRACT #language en-US "Instance of Memory Allocation Library using SMM Services Table, with memory profile support" + +#string STR_MODULE_DESCRIPTION #language en-US "This Memory Allocation Library uses services from the SMM Services Table to allocate and free memory, with memory profile support." + diff --git a/MdeModulePkg/Library/SmmMemoryAllocationProfileLib/SmmMemoryProfileLib.c b/MdeModulePkg/Library/SmmMemoryAllocationProfileLib/SmmMemoryProfileLib.c new file mode 100644 index 0000000000..dcf08689b6 --- /dev/null +++ b/MdeModulePkg/Library/SmmMemoryAllocationProfileLib/SmmMemoryProfileLib.c @@ -0,0 +1,143 @@ +/** @file + Support routines for memory profile for Smm phase drivers. + + Copyright (c) 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 + 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 + +#include +#include +#include + +#include + +EDKII_MEMORY_PROFILE_PROTOCOL *mLibProfileProtocol; +EDKII_SMM_MEMORY_PROFILE_PROTOCOL *mLibSmmProfileProtocol; + +/** + Check whether the start address of buffer is within any of the SMRAM ranges. + + @param[in] Buffer The pointer to the buffer to be checked. + + @retval TURE The buffer is in SMRAM ranges. + @retval FALSE The buffer is out of SMRAM ranges. +**/ +BOOLEAN +EFIAPI +BufferInSmram ( + IN VOID *Buffer + ); + +/** + The constructor function initializes memory profile for SMM phase. + + @param ImageHandle The firmware allocated handle for the EFI image. + @param SystemTable A pointer to the EFI System Table. + + @retval EFI_SUCCESS The constructor always returns EFI_SUCCESS. + +**/ +EFI_STATUS +EFIAPI +SmmMemoryProfileLibConstructor ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + + // + // Locate Profile Protocol + // + Status = gBS->LocateProtocol ( + &gEdkiiMemoryProfileGuid, + NULL, + (VOID **)&mLibProfileProtocol + ); + if (EFI_ERROR (Status)) { + mLibProfileProtocol = NULL; + } + + Status = gSmst->SmmLocateProtocol ( + &gEdkiiSmmMemoryProfileGuid, + NULL, + (VOID **)&mLibSmmProfileProtocol + ); + if (EFI_ERROR (Status)) { + mLibSmmProfileProtocol = NULL; + } + + return EFI_SUCCESS; +} + +/** + Record memory profile of multilevel caller. + + @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 +MemoryProfileLibRecord ( + IN PHYSICAL_ADDRESS CallerAddress, + IN MEMORY_PROFILE_ACTION Action, + IN EFI_MEMORY_TYPE MemoryType, + IN VOID *Buffer, + IN UINTN Size, + IN CHAR8 *ActionString OPTIONAL + ) +{ + if (BufferInSmram (Buffer)) { + if (mLibSmmProfileProtocol == NULL) { + return EFI_UNSUPPORTED; + } + return mLibSmmProfileProtocol->Record ( + mLibSmmProfileProtocol, + CallerAddress, + Action, + MemoryType, + Buffer, + Size, + ActionString + ); + } else { + if (mLibProfileProtocol == NULL) { + return EFI_UNSUPPORTED; + } + return mLibProfileProtocol->Record ( + mLibProfileProtocol, + CallerAddress, + Action, + MemoryType, + Buffer, + Size, + ActionString + ); + } +} + diff --git a/MdeModulePkg/Library/UefiMemoryAllocationProfileLib/DxeMemoryProfileLib.c b/MdeModulePkg/Library/UefiMemoryAllocationProfileLib/DxeMemoryProfileLib.c new file mode 100644 index 0000000000..78c75fbc73 --- /dev/null +++ b/MdeModulePkg/Library/UefiMemoryAllocationProfileLib/DxeMemoryProfileLib.c @@ -0,0 +1,102 @@ +/** @file + Support routines for memory profile for Dxe phase drivers. + + Copyright (c) 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 + 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 + + +#include +#include + +#include + +EDKII_MEMORY_PROFILE_PROTOCOL *mLibProfileProtocol; + +/** + The constructor function initializes memory profile for DXE phase. + + @param ImageHandle The firmware allocated handle for the EFI image. + @param SystemTable A pointer to the EFI System Table. + + @retval EFI_SUCCESS The constructor always returns EFI_SUCCESS. + +**/ +EFI_STATUS +EFIAPI +MemoryProfileLibConstructor ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + + Status = gBS->LocateProtocol ( + &gEdkiiMemoryProfileGuid, + NULL, + (VOID **) &mLibProfileProtocol + ); + if (EFI_ERROR (Status)) { + mLibProfileProtocol = NULL; + } + + return EFI_SUCCESS; +} + +/** + Record memory profile of multilevel caller. + + @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 +MemoryProfileLibRecord ( + IN PHYSICAL_ADDRESS CallerAddress, + IN MEMORY_PROFILE_ACTION Action, + IN EFI_MEMORY_TYPE MemoryType, + IN VOID *Buffer, + IN UINTN Size, + IN CHAR8 *ActionString OPTIONAL + ) +{ + if (mLibProfileProtocol == NULL) { + return EFI_UNSUPPORTED; + } + return mLibProfileProtocol->Record ( + mLibProfileProtocol, + CallerAddress, + Action, + MemoryType, + Buffer, + Size, + ActionString + ); +} + diff --git a/MdeModulePkg/Library/UefiMemoryAllocationProfileLib/MemoryAllocationLib.c b/MdeModulePkg/Library/UefiMemoryAllocationProfileLib/MemoryAllocationLib.c new file mode 100644 index 0000000000..370827ddde --- /dev/null +++ b/MdeModulePkg/Library/UefiMemoryAllocationProfileLib/MemoryAllocationLib.c @@ -0,0 +1,1057 @@ +/** @file + Support routines for memory allocation routines based + on boot services for Dxe phase drivers, with memory profile support. + + Copyright (c) 2006 - 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 + 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 + + +#include +#include +#include +#include + +#include + +/** + Allocates one or more 4KB pages of a certain memory type. + + Allocates the number of 4KB pages of a certain memory type and returns a pointer to the allocated + buffer. The buffer returned is aligned on a 4KB boundary. If Pages is 0, then NULL is returned. + If there is not enough memory remaining to satisfy the request, then NULL is returned. + + @param MemoryType The type of memory to allocate. + @param Pages The number of 4 KB pages to allocate. + + @return A pointer to the allocated buffer or NULL if allocation fails. + +**/ +VOID * +InternalAllocatePages ( + IN EFI_MEMORY_TYPE MemoryType, + IN UINTN Pages + ) +{ + EFI_STATUS Status; + EFI_PHYSICAL_ADDRESS Memory; + + if (Pages == 0) { + return NULL; + } + + Status = gBS->AllocatePages (AllocateAnyPages, MemoryType, Pages, &Memory); + if (EFI_ERROR (Status)) { + return NULL; + } + return (VOID *) (UINTN) Memory; +} + +/** + Allocates one or more 4KB pages of type EfiBootServicesData. + + Allocates the number of 4KB pages of type EfiBootServicesData and returns a pointer to the + allocated buffer. The buffer returned is aligned on a 4KB boundary. If Pages is 0, then NULL + is returned. If there is not enough memory remaining to satisfy the request, then NULL is + returned. + + @param Pages The number of 4 KB pages to allocate. + + @return A pointer to the allocated buffer or NULL if allocation fails. + +**/ +VOID * +EFIAPI +AllocatePages ( + IN UINTN Pages + ) +{ + VOID *Buffer; + + Buffer = InternalAllocatePages (EfiBootServicesData, Pages); + if (Buffer != NULL) { + MemoryProfileLibRecord ( + (PHYSICAL_ADDRESS) (UINTN) RETURN_ADDRESS(0), + MEMORY_PROFILE_ACTION_LIB_ALLOCATE_PAGES, + EfiBootServicesData, + Buffer, + EFI_PAGES_TO_SIZE (Pages), + NULL + ); + } + return Buffer; +} + +/** + Allocates one or more 4KB pages of type EfiRuntimeServicesData. + + Allocates the number of 4KB pages of type EfiRuntimeServicesData and returns a pointer to the + allocated buffer. The buffer returned is aligned on a 4KB boundary. If Pages is 0, then NULL + is returned. If there is not enough memory remaining to satisfy the request, then NULL is + returned. + + @param Pages The number of 4 KB pages to allocate. + + @return A pointer to the allocated buffer or NULL if allocation fails. + +**/ +VOID * +EFIAPI +AllocateRuntimePages ( + IN UINTN Pages + ) +{ + VOID *Buffer; + + Buffer = InternalAllocatePages (EfiRuntimeServicesData, Pages); + if (Buffer != NULL) { + MemoryProfileLibRecord ( + (PHYSICAL_ADDRESS) (UINTN) RETURN_ADDRESS(0), + MEMORY_PROFILE_ACTION_LIB_ALLOCATE_RUNTIME_PAGES, + EfiRuntimeServicesData, + Buffer, + EFI_PAGES_TO_SIZE (Pages), + NULL + ); + } + return Buffer; +} + +/** + Allocates one or more 4KB pages of type EfiReservedMemoryType. + + Allocates the number of 4KB pages of type EfiReservedMemoryType and returns a pointer to the + allocated buffer. The buffer returned is aligned on a 4KB boundary. If Pages is 0, then NULL + is returned. If there is not enough memory remaining to satisfy the request, then NULL is + returned. + + @param Pages The number of 4 KB pages to allocate. + + @return A pointer to the allocated buffer or NULL if allocation fails. + +**/ +VOID * +EFIAPI +AllocateReservedPages ( + IN UINTN Pages + ) +{ + VOID *Buffer; + + Buffer = InternalAllocatePages (EfiReservedMemoryType, Pages); + if (Buffer != NULL) { + MemoryProfileLibRecord ( + (PHYSICAL_ADDRESS) (UINTN) RETURN_ADDRESS(0), + MEMORY_PROFILE_ACTION_LIB_ALLOCATE_RESERVED_PAGES, + EfiReservedMemoryType, + Buffer, + EFI_PAGES_TO_SIZE (Pages), + NULL + ); + } + return Buffer; +} + +/** + Frees one or more 4KB pages that were previously allocated with one of the page allocation + functions in the Memory Allocation Library. + + Frees the number of 4KB pages specified by Pages from the buffer specified by Buffer. Buffer + must have been allocated on a previous call to the page allocation services of the Memory + Allocation Library. If it is not possible to free allocated pages, then this function will + perform no actions. + + If Buffer was not allocated with a page allocation function in the Memory Allocation Library, + then ASSERT(). + If Pages is zero, then ASSERT(). + + @param Buffer The pointer to the buffer of pages to free. + @param Pages The number of 4 KB pages to free. + +**/ +VOID +EFIAPI +FreePages ( + IN VOID *Buffer, + IN UINTN Pages + ) +{ + EFI_STATUS Status; + + ASSERT (Pages != 0); + Status = gBS->FreePages ((EFI_PHYSICAL_ADDRESS) (UINTN) Buffer, Pages); + ASSERT_EFI_ERROR (Status); +} + +/** + Allocates one or more 4KB pages of a certain memory type at a specified alignment. + + Allocates the number of 4KB pages specified by Pages of a certain memory type with an alignment + specified by Alignment. The allocated buffer is returned. If Pages is 0, then NULL is returned. + If there is not enough memory at the specified alignment remaining to satisfy the request, then + NULL is returned. + If Alignment is not a power of two and Alignment is not zero, then ASSERT(). + If Pages plus EFI_SIZE_TO_PAGES (Alignment) overflows, then ASSERT(). + + @param MemoryType The type of memory to allocate. + @param Pages The number of 4 KB pages to allocate. + @param Alignment The requested alignment of the allocation. Must be a power of two. + If Alignment is zero, then byte alignment is used. + + @return A pointer to the allocated buffer or NULL if allocation fails. + +**/ +VOID * +InternalAllocateAlignedPages ( + IN EFI_MEMORY_TYPE MemoryType, + IN UINTN Pages, + IN UINTN Alignment + ) +{ + EFI_STATUS Status; + EFI_PHYSICAL_ADDRESS Memory; + UINTN AlignedMemory; + UINTN AlignmentMask; + UINTN UnalignedPages; + UINTN RealPages; + + // + // Alignment must be a power of two or zero. + // + ASSERT ((Alignment & (Alignment - 1)) == 0); + + if (Pages == 0) { + return NULL; + } + if (Alignment > EFI_PAGE_SIZE) { + // + // Calculate the total number of pages since alignment is larger than page size. + // + AlignmentMask = Alignment - 1; + RealPages = Pages + EFI_SIZE_TO_PAGES (Alignment); + // + // Make sure that Pages plus EFI_SIZE_TO_PAGES (Alignment) does not overflow. + // + ASSERT (RealPages > Pages); + + Status = gBS->AllocatePages (AllocateAnyPages, MemoryType, RealPages, &Memory); + if (EFI_ERROR (Status)) { + return NULL; + } + AlignedMemory = ((UINTN) Memory + AlignmentMask) & ~AlignmentMask; + UnalignedPages = EFI_SIZE_TO_PAGES (AlignedMemory - (UINTN) Memory); + if (UnalignedPages > 0) { + // + // Free first unaligned page(s). + // + Status = gBS->FreePages (Memory, UnalignedPages); + ASSERT_EFI_ERROR (Status); + } + Memory = (EFI_PHYSICAL_ADDRESS) (AlignedMemory + EFI_PAGES_TO_SIZE (Pages)); + UnalignedPages = RealPages - Pages - UnalignedPages; + if (UnalignedPages > 0) { + // + // Free last unaligned page(s). + // + Status = gBS->FreePages (Memory, UnalignedPages); + ASSERT_EFI_ERROR (Status); + } + } else { + // + // Do not over-allocate pages in this case. + // + Status = gBS->AllocatePages (AllocateAnyPages, MemoryType, Pages, &Memory); + if (EFI_ERROR (Status)) { + return NULL; + } + AlignedMemory = (UINTN) Memory; + } + return (VOID *) AlignedMemory; +} + +/** + Allocates one or more 4KB pages of type EfiBootServicesData at a specified alignment. + + Allocates the number of 4KB pages specified by Pages of type EfiBootServicesData with an + alignment specified by Alignment. The allocated buffer is returned. If Pages is 0, then NULL is + returned. If there is not enough memory at the specified alignment remaining to satisfy the + request, then NULL is returned. + + If Alignment is not a power of two and Alignment is not zero, then ASSERT(). + If Pages plus EFI_SIZE_TO_PAGES (Alignment) overflows, then ASSERT(). + + @param Pages The number of 4 KB pages to allocate. + @param Alignment The requested alignment of the allocation. Must be a power of two. + If Alignment is zero, then byte alignment is used. + + @return A pointer to the allocated buffer or NULL if allocation fails. + +**/ +VOID * +EFIAPI +AllocateAlignedPages ( + IN UINTN Pages, + IN UINTN Alignment + ) +{ + VOID *Buffer; + + Buffer = InternalAllocateAlignedPages (EfiBootServicesData, Pages, Alignment); + if (Buffer != NULL) { + MemoryProfileLibRecord ( + (PHYSICAL_ADDRESS) (UINTN) RETURN_ADDRESS(0), + MEMORY_PROFILE_ACTION_LIB_ALLOCATE_ALIGNED_PAGES, + EfiBootServicesData, + Buffer, + EFI_PAGES_TO_SIZE (Pages), + NULL + ); + } + return Buffer; +} + +/** + Allocates one or more 4KB pages of type EfiRuntimeServicesData at a specified alignment. + + Allocates the number of 4KB pages specified by Pages of type EfiRuntimeServicesData with an + alignment specified by Alignment. The allocated buffer is returned. If Pages is 0, then NULL is + returned. If there is not enough memory at the specified alignment remaining to satisfy the + request, then NULL is returned. + + If Alignment is not a power of two and Alignment is not zero, then ASSERT(). + If Pages plus EFI_SIZE_TO_PAGES (Alignment) overflows, then ASSERT(). + + @param Pages The number of 4 KB pages to allocate. + @param Alignment The requested alignment of the allocation. Must be a power of two. + If Alignment is zero, then byte alignment is used. + + @return A pointer to the allocated buffer or NULL if allocation fails. + +**/ +VOID * +EFIAPI +AllocateAlignedRuntimePages ( + IN UINTN Pages, + IN UINTN Alignment + ) +{ + VOID *Buffer; + + Buffer = InternalAllocateAlignedPages (EfiRuntimeServicesData, Pages, Alignment); + if (Buffer != NULL) { + MemoryProfileLibRecord ( + (PHYSICAL_ADDRESS) (UINTN) RETURN_ADDRESS(0), + MEMORY_PROFILE_ACTION_LIB_ALLOCATE_ALIGNED_RUNTIME_PAGES, + EfiRuntimeServicesData, + Buffer, + EFI_PAGES_TO_SIZE (Pages), + NULL + ); + } + return Buffer; +} + +/** + Allocates one or more 4KB pages of type EfiReservedMemoryType at a specified alignment. + + Allocates the number of 4KB pages specified by Pages of type EfiReservedMemoryType with an + alignment specified by Alignment. The allocated buffer is returned. If Pages is 0, then NULL is + returned. If there is not enough memory at the specified alignment remaining to satisfy the + request, then NULL is returned. + + If Alignment is not a power of two and Alignment is not zero, then ASSERT(). + If Pages plus EFI_SIZE_TO_PAGES (Alignment) overflows, then ASSERT(). + + @param Pages The number of 4 KB pages to allocate. + @param Alignment The requested alignment of the allocation. Must be a power of two. + If Alignment is zero, then byte alignment is used. + + @return A pointer to the allocated buffer or NULL if allocation fails. + +**/ +VOID * +EFIAPI +AllocateAlignedReservedPages ( + IN UINTN Pages, + IN UINTN Alignment + ) +{ + VOID *Buffer; + + Buffer = InternalAllocateAlignedPages (EfiReservedMemoryType, Pages, Alignment); + if (Buffer != NULL) { + MemoryProfileLibRecord ( + (PHYSICAL_ADDRESS) (UINTN) RETURN_ADDRESS(0), + MEMORY_PROFILE_ACTION_LIB_ALLOCATE_ALIGNED_RESERVED_PAGES, + EfiReservedMemoryType, + Buffer, + EFI_PAGES_TO_SIZE (Pages), + NULL + ); + } + return Buffer; +} + +/** + Frees one or more 4KB pages that were previously allocated with one of the aligned page + allocation functions in the Memory Allocation Library. + + Frees the number of 4KB pages specified by Pages from the buffer specified by Buffer. Buffer + must have been allocated on a previous call to the aligned page allocation services of the Memory + Allocation Library. If it is not possible to free allocated pages, then this function will + perform no actions. + + If Buffer was not allocated with an aligned page allocation function in the Memory Allocation + Library, then ASSERT(). + If Pages is zero, then ASSERT(). + + @param Buffer The pointer to the buffer of pages to free. + @param Pages The number of 4 KB pages to free. + +**/ +VOID +EFIAPI +FreeAlignedPages ( + IN VOID *Buffer, + IN UINTN Pages + ) +{ + EFI_STATUS Status; + + ASSERT (Pages != 0); + Status = gBS->FreePages ((EFI_PHYSICAL_ADDRESS) (UINTN) Buffer, Pages); + ASSERT_EFI_ERROR (Status); +} + +/** + Allocates a buffer of a certain pool type. + + Allocates the number bytes specified by AllocationSize of a certain pool type and returns a + pointer to the allocated buffer. If AllocationSize is 0, then a valid buffer of 0 size is + returned. If there is not enough memory remaining to satisfy the request, then NULL is returned. + + @param MemoryType The type of memory to allocate. + @param AllocationSize The number of bytes to allocate. + + @return A pointer to the allocated buffer or NULL if allocation fails. + +**/ +VOID * +InternalAllocatePool ( + IN EFI_MEMORY_TYPE MemoryType, + IN UINTN AllocationSize + ) +{ + EFI_STATUS Status; + VOID *Memory; + + Status = gBS->AllocatePool (MemoryType, AllocationSize, &Memory); + if (EFI_ERROR (Status)) { + Memory = NULL; + } + return Memory; +} + +/** + Allocates a buffer of type EfiBootServicesData. + + Allocates the number bytes specified by AllocationSize of type EfiBootServicesData and returns a + pointer to the allocated buffer. If AllocationSize is 0, then a valid buffer of 0 size is + returned. If there is not enough memory remaining to satisfy the request, then NULL is returned. + + @param AllocationSize The number of bytes to allocate. + + @return A pointer to the allocated buffer or NULL if allocation fails. + +**/ +VOID * +EFIAPI +AllocatePool ( + IN UINTN AllocationSize + ) +{ + VOID *Buffer; + + Buffer = InternalAllocatePool (EfiBootServicesData, AllocationSize); + if (Buffer != NULL) { + MemoryProfileLibRecord ( + (PHYSICAL_ADDRESS) (UINTN) RETURN_ADDRESS(0), + MEMORY_PROFILE_ACTION_LIB_ALLOCATE_POOL, + EfiBootServicesData, + Buffer, + AllocationSize, + NULL + ); + } + return Buffer; +} + +/** + Allocates a buffer of type EfiRuntimeServicesData. + + Allocates the number bytes specified by AllocationSize of type EfiRuntimeServicesData and returns + a pointer to the allocated buffer. If AllocationSize is 0, then a valid buffer of 0 size is + returned. If there is not enough memory remaining to satisfy the request, then NULL is returned. + + @param AllocationSize The number of bytes to allocate. + + @return A pointer to the allocated buffer or NULL if allocation fails. + +**/ +VOID * +EFIAPI +AllocateRuntimePool ( + IN UINTN AllocationSize + ) +{ + VOID *Buffer; + + Buffer = InternalAllocatePool (EfiRuntimeServicesData, AllocationSize); + if (Buffer != NULL) { + MemoryProfileLibRecord ( + (PHYSICAL_ADDRESS) (UINTN) RETURN_ADDRESS(0), + MEMORY_PROFILE_ACTION_LIB_ALLOCATE_RUNTIME_POOL, + EfiRuntimeServicesData, + Buffer, + AllocationSize, + NULL + ); + } + return Buffer; +} + +/** + Allocates a buffer of type EfiReservedMemoryType. + + Allocates the number bytes specified by AllocationSize of type EfiReservedMemoryType and returns + a pointer to the allocated buffer. If AllocationSize is 0, then a valid buffer of 0 size is + returned. If there is not enough memory remaining to satisfy the request, then NULL is returned. + + @param AllocationSize The number of bytes to allocate. + + @return A pointer to the allocated buffer or NULL if allocation fails. + +**/ +VOID * +EFIAPI +AllocateReservedPool ( + IN UINTN AllocationSize + ) +{ + VOID *Buffer; + + Buffer = InternalAllocatePool (EfiReservedMemoryType, AllocationSize); + if (Buffer != NULL) { + MemoryProfileLibRecord ( + (PHYSICAL_ADDRESS) (UINTN) RETURN_ADDRESS(0), + MEMORY_PROFILE_ACTION_LIB_ALLOCATE_RESERVED_POOL, + EfiReservedMemoryType, + Buffer, + AllocationSize, + NULL + ); + } + return Buffer; +} + +/** + Allocates and zeros a buffer of a certain pool type. + + Allocates the number bytes specified by AllocationSize of a certain pool type, clears the buffer + with zeros, and returns a pointer to the allocated buffer. If AllocationSize is 0, then a valid + buffer of 0 size is returned. If there is not enough memory remaining to satisfy the request, + then NULL is returned. + + @param PoolType The type of memory to allocate. + @param AllocationSize The number of bytes to allocate and zero. + + @return A pointer to the allocated buffer or NULL if allocation fails. + +**/ +VOID * +InternalAllocateZeroPool ( + IN EFI_MEMORY_TYPE PoolType, + IN UINTN AllocationSize + ) +{ + VOID *Memory; + + Memory = InternalAllocatePool (PoolType, AllocationSize); + if (Memory != NULL) { + Memory = ZeroMem (Memory, AllocationSize); + } + return Memory; +} + +/** + Allocates and zeros a buffer of type EfiBootServicesData. + + Allocates the number bytes specified by AllocationSize of type EfiBootServicesData, clears the + buffer with zeros, and returns a pointer to the allocated buffer. If AllocationSize is 0, then a + valid buffer of 0 size is returned. If there is not enough memory remaining to satisfy the + request, then NULL is returned. + + @param AllocationSize The number of bytes to allocate and zero. + + @return A pointer to the allocated buffer or NULL if allocation fails. + +**/ +VOID * +EFIAPI +AllocateZeroPool ( + IN UINTN AllocationSize + ) +{ + VOID *Buffer; + + Buffer = InternalAllocateZeroPool (EfiBootServicesData, AllocationSize); + if (Buffer != NULL) { + MemoryProfileLibRecord ( + (PHYSICAL_ADDRESS) (UINTN) RETURN_ADDRESS(0), + MEMORY_PROFILE_ACTION_LIB_ALLOCATE_ZERO_POOL, + EfiBootServicesData, + Buffer, + AllocationSize, + NULL + ); + } + return Buffer; +} + +/** + Allocates and zeros a buffer of type EfiRuntimeServicesData. + + Allocates the number bytes specified by AllocationSize of type EfiRuntimeServicesData, clears the + buffer with zeros, and returns a pointer to the allocated buffer. If AllocationSize is 0, then a + valid buffer of 0 size is returned. If there is not enough memory remaining to satisfy the + request, then NULL is returned. + + @param AllocationSize The number of bytes to allocate and zero. + + @return A pointer to the allocated buffer or NULL if allocation fails. + +**/ +VOID * +EFIAPI +AllocateRuntimeZeroPool ( + IN UINTN AllocationSize + ) +{ + VOID *Buffer; + + Buffer = InternalAllocateZeroPool (EfiRuntimeServicesData, AllocationSize); + if (Buffer != NULL) { + MemoryProfileLibRecord ( + (PHYSICAL_ADDRESS) (UINTN) RETURN_ADDRESS(0), + MEMORY_PROFILE_ACTION_LIB_ALLOCATE_RUNTIME_ZERO_POOL, + EfiRuntimeServicesData, + Buffer, + AllocationSize, + NULL + ); + } + return Buffer; +} + +/** + Allocates and zeros a buffer of type EfiReservedMemoryType. + + Allocates the number bytes specified by AllocationSize of type EfiReservedMemoryType, clears the + buffer with zeros, and returns a pointer to the allocated buffer. If AllocationSize is 0, then a + valid buffer of 0 size is returned. If there is not enough memory remaining to satisfy the + request, then NULL is returned. + + @param AllocationSize The number of bytes to allocate and zero. + + @return A pointer to the allocated buffer or NULL if allocation fails. + +**/ +VOID * +EFIAPI +AllocateReservedZeroPool ( + IN UINTN AllocationSize + ) +{ + VOID *Buffer; + + Buffer = InternalAllocateZeroPool (EfiReservedMemoryType, AllocationSize); + if (Buffer != NULL) { + MemoryProfileLibRecord ( + (PHYSICAL_ADDRESS) (UINTN) RETURN_ADDRESS(0), + MEMORY_PROFILE_ACTION_LIB_ALLOCATE_RESERVED_ZERO_POOL, + EfiReservedMemoryType, + Buffer, + AllocationSize, + NULL + ); + } + return Buffer; +} + +/** + Copies a buffer to an allocated buffer of a certain pool type. + + Allocates the number bytes specified by AllocationSize of a certain pool type, copies + AllocationSize bytes from Buffer to the newly allocated buffer, and returns a pointer to the + allocated buffer. If AllocationSize is 0, then a valid buffer of 0 size is returned. If there + is not enough memory remaining to satisfy the request, then NULL is returned. + If Buffer is NULL, then ASSERT(). + If AllocationSize is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). + + @param PoolType The type of pool to allocate. + @param AllocationSize The number of bytes to allocate and zero. + @param Buffer The buffer to copy to the allocated buffer. + + @return A pointer to the allocated buffer or NULL if allocation fails. + +**/ +VOID * +InternalAllocateCopyPool ( + IN EFI_MEMORY_TYPE PoolType, + IN UINTN AllocationSize, + IN CONST VOID *Buffer + ) +{ + VOID *Memory; + + ASSERT (Buffer != NULL); + ASSERT (AllocationSize <= (MAX_ADDRESS - (UINTN) Buffer + 1)); + + Memory = InternalAllocatePool (PoolType, AllocationSize); + if (Memory != NULL) { + Memory = CopyMem (Memory, Buffer, AllocationSize); + } + return Memory; +} + +/** + Copies a buffer to an allocated buffer of type EfiBootServicesData. + + Allocates the number bytes specified by AllocationSize of type EfiBootServicesData, copies + AllocationSize bytes from Buffer to the newly allocated buffer, and returns a pointer to the + allocated buffer. If AllocationSize is 0, then a valid buffer of 0 size is returned. If there + is not enough memory remaining to satisfy the request, then NULL is returned. + + If Buffer is NULL, then ASSERT(). + If AllocationSize is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). + + @param AllocationSize The number of bytes to allocate and zero. + @param Buffer The buffer to copy to the allocated buffer. + + @return A pointer to the allocated buffer or NULL if allocation fails. + +**/ +VOID * +EFIAPI +AllocateCopyPool ( + IN UINTN AllocationSize, + IN CONST VOID *Buffer + ) +{ + VOID *NewBuffer; + + NewBuffer = InternalAllocateCopyPool (EfiBootServicesData, AllocationSize, Buffer); + if (NewBuffer != NULL) { + MemoryProfileLibRecord ( + (PHYSICAL_ADDRESS) (UINTN) RETURN_ADDRESS(0), + MEMORY_PROFILE_ACTION_LIB_ALLOCATE_COPY_POOL, + EfiBootServicesData, + NewBuffer, + AllocationSize, + NULL + ); + } + return NewBuffer; +} + +/** + Copies a buffer to an allocated buffer of type EfiRuntimeServicesData. + + Allocates the number bytes specified by AllocationSize of type EfiRuntimeServicesData, copies + AllocationSize bytes from Buffer to the newly allocated buffer, and returns a pointer to the + allocated buffer. If AllocationSize is 0, then a valid buffer of 0 size is returned. If there + is not enough memory remaining to satisfy the request, then NULL is returned. + + If Buffer is NULL, then ASSERT(). + If AllocationSize is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). + + @param AllocationSize The number of bytes to allocate and zero. + @param Buffer The buffer to copy to the allocated buffer. + + @return A pointer to the allocated buffer or NULL if allocation fails. + +**/ +VOID * +EFIAPI +AllocateRuntimeCopyPool ( + IN UINTN AllocationSize, + IN CONST VOID *Buffer + ) +{ + VOID *NewBuffer; + + NewBuffer = InternalAllocateCopyPool (EfiRuntimeServicesData, AllocationSize, Buffer); + if (NewBuffer != NULL) { + MemoryProfileLibRecord ( + (PHYSICAL_ADDRESS) (UINTN) RETURN_ADDRESS(0), + MEMORY_PROFILE_ACTION_LIB_ALLOCATE_RUNTIME_COPY_POOL, + EfiRuntimeServicesData, + NewBuffer, + AllocationSize, + NULL + ); + } + return NewBuffer; +} + +/** + Copies a buffer to an allocated buffer of type EfiReservedMemoryType. + + Allocates the number bytes specified by AllocationSize of type EfiReservedMemoryType, copies + AllocationSize bytes from Buffer to the newly allocated buffer, and returns a pointer to the + allocated buffer. If AllocationSize is 0, then a valid buffer of 0 size is returned. If there + is not enough memory remaining to satisfy the request, then NULL is returned. + + If Buffer is NULL, then ASSERT(). + If AllocationSize is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). + + @param AllocationSize The number of bytes to allocate and zero. + @param Buffer The buffer to copy to the allocated buffer. + + @return A pointer to the allocated buffer or NULL if allocation fails. + +**/ +VOID * +EFIAPI +AllocateReservedCopyPool ( + IN UINTN AllocationSize, + IN CONST VOID *Buffer + ) +{ + VOID *NewBuffer; + + NewBuffer = InternalAllocateCopyPool (EfiReservedMemoryType, AllocationSize, Buffer); + if (NewBuffer != NULL) { + MemoryProfileLibRecord ( + (PHYSICAL_ADDRESS) (UINTN) RETURN_ADDRESS(0), + MEMORY_PROFILE_ACTION_LIB_ALLOCATE_RESERVED_COPY_POOL, + EfiRuntimeServicesData, + NewBuffer, + AllocationSize, + NULL + ); + } + return NewBuffer; +} + +/** + Reallocates a buffer of a specified memory type. + + Allocates and zeros the number bytes specified by NewSize from memory of the type + specified by PoolType. If OldBuffer is not NULL, then the smaller of OldSize and + NewSize bytes are copied from OldBuffer to the newly allocated buffer, and + OldBuffer is freed. A pointer to the newly allocated buffer is returned. + If NewSize is 0, then a valid buffer of 0 size is returned. If there is not + enough memory remaining to satisfy the request, then NULL is returned. + + If the allocation of the new buffer is successful and the smaller of NewSize and OldSize + is greater than (MAX_ADDRESS - OldBuffer + 1), then ASSERT(). + + @param PoolType The type of pool to allocate. + @param OldSize The size, in bytes, of OldBuffer. + @param NewSize The size, in bytes, of the buffer to reallocate. + @param OldBuffer The buffer to copy to the allocated buffer. This is an optional + parameter that may be NULL. + + @return A pointer to the allocated buffer or NULL if allocation fails. + +**/ +VOID * +InternalReallocatePool ( + IN EFI_MEMORY_TYPE PoolType, + IN UINTN OldSize, + IN UINTN NewSize, + IN VOID *OldBuffer OPTIONAL + ) +{ + VOID *NewBuffer; + + NewBuffer = InternalAllocateZeroPool (PoolType, NewSize); + if (NewBuffer != NULL && OldBuffer != NULL) { + CopyMem (NewBuffer, OldBuffer, MIN (OldSize, NewSize)); + FreePool (OldBuffer); + } + return NewBuffer; +} + +/** + Reallocates a buffer of type EfiBootServicesData. + + Allocates and zeros the number bytes specified by NewSize from memory of type + EfiBootServicesData. If OldBuffer is not NULL, then the smaller of OldSize and + NewSize bytes are copied from OldBuffer to the newly allocated buffer, and + OldBuffer is freed. A pointer to the newly allocated buffer is returned. + If NewSize is 0, then a valid buffer of 0 size is returned. If there is not + enough memory remaining to satisfy the request, then NULL is returned. + + If the allocation of the new buffer is successful and the smaller of NewSize and OldSize + is greater than (MAX_ADDRESS - OldBuffer + 1), then ASSERT(). + + @param OldSize The size, in bytes, of OldBuffer. + @param NewSize The size, in bytes, of the buffer to reallocate. + @param OldBuffer The buffer to copy to the allocated buffer. This is an optional + parameter that may be NULL. + + @return A pointer to the allocated buffer or NULL if allocation fails. + +**/ +VOID * +EFIAPI +ReallocatePool ( + IN UINTN OldSize, + IN UINTN NewSize, + IN VOID *OldBuffer OPTIONAL + ) +{ + VOID *Buffer; + + Buffer = InternalReallocatePool (EfiBootServicesData, OldSize, NewSize, OldBuffer); + if (Buffer != NULL) { + MemoryProfileLibRecord ( + (PHYSICAL_ADDRESS) (UINTN) RETURN_ADDRESS(0), + MEMORY_PROFILE_ACTION_LIB_REALLOCATE_POOL, + EfiBootServicesData, + Buffer, + NewSize, + NULL + ); + } + return Buffer; +} + +/** + Reallocates a buffer of type EfiRuntimeServicesData. + + Allocates and zeros the number bytes specified by NewSize from memory of type + EfiRuntimeServicesData. If OldBuffer is not NULL, then the smaller of OldSize and + NewSize bytes are copied from OldBuffer to the newly allocated buffer, and + OldBuffer is freed. A pointer to the newly allocated buffer is returned. + If NewSize is 0, then a valid buffer of 0 size is returned. If there is not + enough memory remaining to satisfy the request, then NULL is returned. + + If the allocation of the new buffer is successful and the smaller of NewSize and OldSize + is greater than (MAX_ADDRESS - OldBuffer + 1), then ASSERT(). + + @param OldSize The size, in bytes, of OldBuffer. + @param NewSize The size, in bytes, of the buffer to reallocate. + @param OldBuffer The buffer to copy to the allocated buffer. This is an optional + parameter that may be NULL. + + @return A pointer to the allocated buffer or NULL if allocation fails. + +**/ +VOID * +EFIAPI +ReallocateRuntimePool ( + IN UINTN OldSize, + IN UINTN NewSize, + IN VOID *OldBuffer OPTIONAL + ) +{ + VOID *Buffer; + + Buffer = InternalReallocatePool (EfiRuntimeServicesData, OldSize, NewSize, OldBuffer); + if (Buffer != NULL) { + MemoryProfileLibRecord ( + (PHYSICAL_ADDRESS) (UINTN) RETURN_ADDRESS(0), + MEMORY_PROFILE_ACTION_LIB_REALLOCATE_RUNTIME_POOL, + EfiRuntimeServicesData, + Buffer, + NewSize, + NULL + ); + } + return Buffer; +} + +/** + Reallocates a buffer of type EfiReservedMemoryType. + + Allocates and zeros the number bytes specified by NewSize from memory of type + EfiReservedMemoryType. If OldBuffer is not NULL, then the smaller of OldSize and + NewSize bytes are copied from OldBuffer to the newly allocated buffer, and + OldBuffer is freed. A pointer to the newly allocated buffer is returned. + If NewSize is 0, then a valid buffer of 0 size is returned. If there is not + enough memory remaining to satisfy the request, then NULL is returned. + + If the allocation of the new buffer is successful and the smaller of NewSize and OldSize + is greater than (MAX_ADDRESS - OldBuffer + 1), then ASSERT(). + + @param OldSize The size, in bytes, of OldBuffer. + @param NewSize The size, in bytes, of the buffer to reallocate. + @param OldBuffer The buffer to copy to the allocated buffer. This is an optional + parameter that may be NULL. + + @return A pointer to the allocated buffer or NULL if allocation fails. + +**/ +VOID * +EFIAPI +ReallocateReservedPool ( + IN UINTN OldSize, + IN UINTN NewSize, + IN VOID *OldBuffer OPTIONAL + ) +{ + VOID *Buffer; + + Buffer = InternalReallocatePool (EfiReservedMemoryType, OldSize, NewSize, OldBuffer); + if (Buffer != NULL) { + MemoryProfileLibRecord ( + (PHYSICAL_ADDRESS) (UINTN) RETURN_ADDRESS(0), + MEMORY_PROFILE_ACTION_LIB_REALLOCATE_RESERVED_POOL, + EfiReservedMemoryType, + Buffer, + NewSize, + NULL + ); + } + return Buffer; +} + +/** + Frees a buffer that was previously allocated with one of the pool allocation functions in the + Memory Allocation Library. + + Frees the buffer specified by Buffer. Buffer must have been allocated on a previous call to the + pool allocation services of the Memory Allocation Library. If it is not possible to free pool + resources, then this function will perform no actions. + + If Buffer was not allocated with a pool allocation function in the Memory Allocation Library, + then ASSERT(). + + @param Buffer The pointer to the buffer to free. + +**/ +VOID +EFIAPI +FreePool ( + IN VOID *Buffer + ) +{ + EFI_STATUS Status; + + Status = gBS->FreePool (Buffer); + ASSERT_EFI_ERROR (Status); +} + diff --git a/MdeModulePkg/Library/UefiMemoryAllocationProfileLib/UefiMemoryAllocationProfileLib.inf b/MdeModulePkg/Library/UefiMemoryAllocationProfileLib/UefiMemoryAllocationProfileLib.inf new file mode 100644 index 0000000000..21b544cc10 --- /dev/null +++ b/MdeModulePkg/Library/UefiMemoryAllocationProfileLib/UefiMemoryAllocationProfileLib.inf @@ -0,0 +1,53 @@ +## @file +# Instance of Memory Allocation Library using EFI Boot Services, +# with memory profile support. +# +# Memory Allocation Library that uses EFI Boot Services to allocate +# and free memory, with memory profile support. +# +# The implementation of this instance is copied from UefiMemoryAllocationLib +# in MdePkg and updated to support both MemoryAllocationLib and MemoryProfileLib. +# +# Copyright (c) 2007 - 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 +# 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 = UefiMemoryAllocationProfileLib + MODULE_UNI_FILE = UefiMemoryAllocationProfileLib.uni + FILE_GUID = 9E8A380A-231E-41E4-AD40-5E706196B853 + MODULE_TYPE = UEFI_DRIVER + VERSION_STRING = 1.0 + LIBRARY_CLASS = MemoryAllocationLib|DXE_DRIVER DXE_RUNTIME_DRIVER DXE_SAL_DRIVER DXE_SMM_DRIVER UEFI_APPLICATION UEFI_DRIVER + LIBRARY_CLASS = MemoryProfileLib|DXE_DRIVER DXE_RUNTIME_DRIVER DXE_SAL_DRIVER DXE_SMM_DRIVER UEFI_APPLICATION UEFI_DRIVER + CONSTRUCTOR = MemoryProfileLibConstructor + +# +# VALID_ARCHITECTURES = IA32 X64 IPF EBC +# + +[Sources] + MemoryAllocationLib.c + DxeMemoryProfileLib.c + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + +[LibraryClasses] + DebugLib + BaseMemoryLib + UefiBootServicesTableLib + +[Guids] + gEdkiiMemoryProfileGuid ## SOMETIMES_CONSUMES ## GUID # Locate protocol + diff --git a/MdeModulePkg/Library/UefiMemoryAllocationProfileLib/UefiMemoryAllocationProfileLib.uni b/MdeModulePkg/Library/UefiMemoryAllocationProfileLib/UefiMemoryAllocationProfileLib.uni new file mode 100644 index 0000000000..7da7d783e3 --- /dev/null +++ b/MdeModulePkg/Library/UefiMemoryAllocationProfileLib/UefiMemoryAllocationProfileLib.uni @@ -0,0 +1,23 @@ +// /** @file +// Instance of Memory Allocation Library using EFI Boot Services, +// with memory profile support. +// +// Memory Allocation Library that uses EFI Boot Services to allocate +// and free memory, with memory profile support. +// +// Copyright (c) 2007 - 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 +// 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. +// +// **/ + + +#string STR_MODULE_ABSTRACT #language en-US "Instance of Memory Allocation Library using EFI Boot Services, with memory profile support" + +#string STR_MODULE_DESCRIPTION #language en-US "This Memory Allocation Library uses EFI Boot Services to allocate and free memory, with memory profile support." + diff --git a/MdeModulePkg/MdeModulePkg.dec b/MdeModulePkg/MdeModulePkg.dec index 27efb378bd..8d90f169b2 100644 --- a/MdeModulePkg/MdeModulePkg.dec +++ b/MdeModulePkg/MdeModulePkg.dec @@ -153,6 +153,10 @@ # PciHostBridgeLib|Include/Library/PciHostBridgeLib.h + ## @libraryclass Provides services to record memory profile of multilevel caller. + # + MemoryProfileLib|Include/Library/MemoryProfileLib.h + [Guids] ## MdeModule package token space guid # Include/Guid/MdeModulePkgTokenSpace.h @@ -327,6 +331,7 @@ ## Include/Guid/MemoryProfile.h gEdkiiMemoryProfileGuid = { 0x821c9a09, 0x541a, 0x40f6, { 0x9f, 0x43, 0xa, 0xd1, 0x93, 0xa1, 0x2c, 0xfe }} + gEdkiiSmmMemoryProfileGuid = { 0xe22bbcca, 0x516a, 0x46a8, { 0x80, 0xe2, 0x67, 0x45, 0xe8, 0x36, 0x93, 0xbd }} ## Include/Protocol/VarErrorFlag.h gEdkiiVarErrorFlagGuid = { 0x4b37fe8, 0xf6ae, 0x480b, { 0xbd, 0xd5, 0x37, 0xd9, 0x8c, 0x5e, 0x89, 0xaa } } @@ -995,8 +1000,9 @@ ## The mask is used to control memory profile behavior.

# BIT0 - Enable UEFI memory profile.
# BIT1 - Enable SMRAM profile.
+ # BIT7 - Disable recording at the start.
# @Prompt Memory Profile Property. - # @Expression 0x80000002 | (gEfiMdeModulePkgTokenSpaceGuid.PcdMemoryProfilePropertyMask & 0xFC) == 0 + # @Expression 0x80000002 | (gEfiMdeModulePkgTokenSpaceGuid.PcdMemoryProfilePropertyMask & 0x7C) == 0 gEfiMdeModulePkgTokenSpaceGuid.PcdMemoryProfilePropertyMask|0x0|UINT8|0x30001041 ## This flag is to control which memory types of alloc info will be recorded by DxeCore & SmmCore.

@@ -1026,6 +1032,20 @@ # @Prompt Memory profile memory type. gEfiMdeModulePkgTokenSpaceGuid.PcdMemoryProfileMemoryType|0x0|UINT64|0x30001042 + ## This PCD is to control which drivers need memory profile data.

+ # For example:
+ # One image only (Shell):
+ # Header GUID
+ # {0x04, 0x06, 0x14, 0x00, 0x83, 0xA5, 0x04, 0x7C, 0x3E, 0x9E, 0x1C, 0x4F, 0xAD, 0x65, 0xE0, 0x52, 0x68, 0xD0, 0xB4, 0xD1,
+ # 0x7F, 0xFF, 0x04, 0x00}
+ # Two or more images (Shell + WinNtSimpleFileSystem):
+ # {0x04, 0x06, 0x14, 0x00, 0x83, 0xA5, 0x04, 0x7C, 0x3E, 0x9E, 0x1C, 0x4F, 0xAD, 0x65, 0xE0, 0x52, 0x68, 0xD0, 0xB4, 0xD1,
+ # 0x7F, 0x01, 0x04, 0x00,
+ # 0x04, 0x06, 0x14, 0x00, 0x8B, 0xE1, 0x25, 0x9C, 0xBA, 0x76, 0xDA, 0x43, 0xA1, 0x32, 0xDB, 0xB0, 0x99, 0x7C, 0xEF, 0xEF,
+ # 0x7F, 0xFF, 0x04, 0x00}
+ # @Prompt Memory profile driver path. + gEfiMdeModulePkgTokenSpaceGuid.PcdMemoryProfileDriverPath|{0x0}|VOID*|0x00001043 + ## PCI Serial Device Info. It is an array of Device, Function, and Power Management # information that describes the path that contains zero or more PCI to PCI briges # followed by a PCI serial device. Each array entry is 4-bytes in length. The diff --git a/MdeModulePkg/MdeModulePkg.dsc b/MdeModulePkg/MdeModulePkg.dsc index abce62d93c..1e57389e6e 100644 --- a/MdeModulePkg/MdeModulePkg.dsc +++ b/MdeModulePkg/MdeModulePkg.dsc @@ -259,7 +259,9 @@ MdeModulePkg/Core/RuntimeDxe/RuntimeDxe.inf MdeModulePkg/Library/DxeCapsuleLibNull/DxeCapsuleLibNull.inf + MdeModulePkg/Library/UefiMemoryAllocationProfileLib/UefiMemoryAllocationProfileLib.inf MdeModulePkg/Library/DxeCoreMemoryAllocationLib/DxeCoreMemoryAllocationLib.inf + MdeModulePkg/Library/DxeCoreMemoryAllocationLib/DxeCoreMemoryAllocationProfileLib.inf MdeModulePkg/Library/DxeCorePerformanceLib/DxeCorePerformanceLib.inf MdeModulePkg/Library/DxeCrc32GuidedSectionExtractLib/DxeCrc32GuidedSectionExtractLib.inf MdeModulePkg/Library/DxeDpcLib/DxeDpcLib.inf @@ -432,6 +434,9 @@ MdeModulePkg/Universal/StatusCodeHandler/Smm/StatusCodeHandlerSmm.inf MdeModulePkg/Universal/ReportStatusCodeRouter/Smm/ReportStatusCodeRouterSmm.inf MdeModulePkg/Universal/LockBox/SmmLockBox/SmmLockBox.inf + MdeModulePkg/Library/SmmMemoryAllocationProfileLib/SmmMemoryAllocationProfileLib.inf + MdeModulePkg/Library/PiSmmCoreMemoryAllocationLib/PiSmmCoreMemoryAllocationProfileLib.inf + MdeModulePkg/Library/PiSmmCoreMemoryAllocationLib/PiSmmCoreMemoryAllocationLib.inf MdeModulePkg/Library/SmmCorePerformanceLib/SmmCorePerformanceLib.inf MdeModulePkg/Library/SmmPerformanceLib/SmmPerformanceLib.inf MdeModulePkg/Library/DxeSmmPerformanceLib/DxeSmmPerformanceLib.inf diff --git a/MdeModulePkg/MdeModulePkg.uni b/MdeModulePkg/MdeModulePkg.uni index f529dced6f..1a5f24efbf 100644 --- a/MdeModulePkg/MdeModulePkg.uni +++ b/MdeModulePkg/MdeModulePkg.uni @@ -266,7 +266,8 @@ #string STR_gEfiMdeModulePkgTokenSpaceGuid_PcdMemoryProfilePropertyMask_HELP #language en-US "The mask is used to control memory profile behavior.

\n" "BIT0 - Enable UEFI memory profile.
\n" - "BIT1 - Enable SMRAM profile.
" + "BIT1 - Enable SMRAM profile.
\n" + "BIT7 - Disable recording at the start.
" #string STR_gEfiMdeModulePkgTokenSpaceGuid_PcdMemoryProfileMemoryType_PROMPT #language en-US "Memory profile memory type" @@ -292,6 +293,20 @@ " OS Reserved 0x80000000
\n" "e.g. Reserved+ACPINvs+ACPIReclaim+RuntimeCode+RuntimeData are needed, 0x661 should be used.
\n" +#string STR_gEfiMdeModulePkgTokenSpaceGuid_PcdMemoryProfileDriverPath_PROMPT #language en-US "Memory profile driver path" + +#string STR_gEfiMdeModulePkgTokenSpaceGuid_PcdMemoryProfileDriverPath_HELP #language en-US "This PCD is to control which drivers need memory profile data.

\n" + "For example:
\n" + "One image only (Shell):
\n" + " Header GUID
\n" + " {0x04, 0x06, 0x14, 0x00, 0x83, 0xA5, 0x04, 0x7C, 0x3E, 0x9E, 0x1C, 0x4F, 0xAD, 0x65, 0xE0, 0x52, 0x68, 0xD0, 0xB4, 0xD1,
\n" + " 0x7F, 0xFF, 0x04, 0x00}
\n" + "Two or more images (Shell + WinNtSimpleFileSystem):
\n" + " {0x04, 0x06, 0x14, 0x00, 0x83, 0xA5, 0x04, 0x7C, 0x3E, 0x9E, 0x1C, 0x4F, 0xAD, 0x65, 0xE0, 0x52, 0x68, 0xD0, 0xB4, 0xD1,
\n" + " 0x7F, 0x01, 0x04, 0x00,
\n" + " 0x04, 0x06, 0x14, 0x00, 0x8B, 0xE1, 0x25, 0x9C, 0xBA, 0x76, 0xDA, 0x43, 0xA1, 0x32, 0xDB, 0xB0, 0x99, 0x7C, 0xEF, 0xEF,
\n" + " 0x7F, 0xFF, 0x04, 0x00}
\n" + #string STR_gEfiMdeModulePkgTokenSpaceGuid_PcdSerialClockRate_PROMPT #language en-US "Serial Port Clock Rate" #string STR_gEfiMdeModulePkgTokenSpaceGuid_PcdSerialClockRate_HELP #language en-US "UART clock frequency is for the baud rate configuration." diff --git a/NetworkPkg/IpSecDxe/Ikev2/Sa.c b/NetworkPkg/IpSecDxe/Ikev2/Sa.c index 74ef79c237..4cbfac33b1 100644 --- a/NetworkPkg/IpSecDxe/Ikev2/Sa.c +++ b/NetworkPkg/IpSecDxe/Ikev2/Sa.c @@ -384,7 +384,7 @@ Ikev2InitPskParser ( // 5. Generate Nr_b // IkeSaSession->NrBlock = IkeGenerateNonce (IKE_NONCE_SIZE); - ASSERT_EFI_ERROR (IkeSaSession->NrBlock != NULL); + ASSERT (IkeSaSession->NrBlock != NULL); IkeSaSession->NrBlkSize = IKE_NONCE_SIZE; // diff --git a/QuarkPlatformPkg/Acpi/Dxe/AcpiPlatform/AcpiPlatform.c b/QuarkPlatformPkg/Acpi/Dxe/AcpiPlatform/AcpiPlatform.c index 309eb041ee..36300efd31 100644 --- a/QuarkPlatformPkg/Acpi/Dxe/AcpiPlatform/AcpiPlatform.c +++ b/QuarkPlatformPkg/Acpi/Dxe/AcpiPlatform/AcpiPlatform.c @@ -680,7 +680,7 @@ AcpiPlatformEntryPoint ( // Init Pci Device PRT PRW information structure from PCD // mConfigData = (PCI_DEVICE_SETTING *)AllocateZeroPool (sizeof (PCI_DEVICE_SETTING)); - ASSERT_EFI_ERROR (mConfigData); + ASSERT (mConfigData != NULL); InitPciDeviceInfoStructure (mConfigData); // // Get the Acpi SDT protocol for manipulation on acpi table diff --git a/QuarkPlatformPkg/Acpi/Dxe/AcpiPlatform/MadtPlatform.c b/QuarkPlatformPkg/Acpi/Dxe/AcpiPlatform/MadtPlatform.c index 11781e03f4..98035bedd5 100644 --- a/QuarkPlatformPkg/Acpi/Dxe/AcpiPlatform/MadtPlatform.c +++ b/QuarkPlatformPkg/Acpi/Dxe/AcpiPlatform/MadtPlatform.c @@ -218,7 +218,7 @@ MadtTableInitialize ( //ASSERT (NumberOfCPUs <= 2 && NumberOfCPUs > 0); MadtSize = GetAcutalMadtTableSize (&MadtConfigData, NumberOfCPUs); Madt = (EFI_ACPI_2_0_MULTIPLE_APIC_DESCRIPTION_TABLE_HEADER *)AllocateZeroPool (MadtSize); - ASSERT_EFI_ERROR (Madt); + ASSERT (Madt != NULL); // // Initialize MADT Header information // diff --git a/QuarkPlatformPkg/Library/PlatformHelperLib/PlatformHelperDxe.c b/QuarkPlatformPkg/Library/PlatformHelperLib/PlatformHelperDxe.c index 441f7609a5..39185bc0d5 100644 --- a/QuarkPlatformPkg/Library/PlatformHelperLib/PlatformHelperDxe.c +++ b/QuarkPlatformPkg/Library/PlatformHelperLib/PlatformHelperDxe.c @@ -174,7 +174,7 @@ PlatformFlashLockConfig ( // SpiProtocol = LocateSpiProtocol (NULL); // This routine will not be called in SMM. - ASSERT_EFI_ERROR (SpiProtocol != NULL); + ASSERT (SpiProtocol != NULL); if (SpiProtocol != NULL) { Status = SpiProtocol->Lock (SpiProtocol); diff --git a/QuarkPlatformPkg/Platform/Pei/PlatformInit/MrcWrapper.c b/QuarkPlatformPkg/Platform/Pei/PlatformInit/MrcWrapper.c index df6c1cc232..6b07d78293 100644 --- a/QuarkPlatformPkg/Platform/Pei/PlatformInit/MrcWrapper.c +++ b/QuarkPlatformPkg/Platform/Pei/PlatformInit/MrcWrapper.c @@ -1034,7 +1034,7 @@ InstallS3Memory ( // memory above 1MB. So Memory Callback can set cache for the system memory // correctly on S3 boot path, just like it does on Normal boot path. // - ASSERT_EFI_ERROR ((S3MemoryRangeData->SystemMemoryLength - 0x100000) > 0); + ASSERT ((S3MemoryRangeData->SystemMemoryLength - 0x100000) > 0); BuildResourceDescriptorHob ( EFI_RESOURCE_SYSTEM_MEMORY, ( diff --git a/SecurityPkg/Tcg/Tcg2Dxe/Tcg2Dxe.c b/SecurityPkg/Tcg/Tcg2Dxe/Tcg2Dxe.c index bdff5bd598..7720c2708d 100644 --- a/SecurityPkg/Tcg/Tcg2Dxe/Tcg2Dxe.c +++ b/SecurityPkg/Tcg/Tcg2Dxe/Tcg2Dxe.c @@ -1330,10 +1330,10 @@ Tcg2SubmitCommand ( return EFI_DEVICE_ERROR; } - if (InputParameterBlockSize >= mTcgDxeData.BsCap.MaxCommandSize) { + if (InputParameterBlockSize > mTcgDxeData.BsCap.MaxCommandSize) { return EFI_INVALID_PARAMETER; } - if (OutputParameterBlockSize >= mTcgDxeData.BsCap.MaxResponseSize) { + if (OutputParameterBlockSize > mTcgDxeData.BsCap.MaxResponseSize) { return EFI_INVALID_PARAMETER; } diff --git a/SecurityPkg/Tcg/TrEEDxe/TrEEDxe.c b/SecurityPkg/Tcg/TrEEDxe/TrEEDxe.c index dfdee04688..a30cd5161d 100644 --- a/SecurityPkg/Tcg/TrEEDxe/TrEEDxe.c +++ b/SecurityPkg/Tcg/TrEEDxe/TrEEDxe.c @@ -893,10 +893,10 @@ TreeSubmitCommand ( return EFI_UNSUPPORTED; } - if (InputParameterBlockSize >= mTcgDxeData.BsCap.MaxCommandSize) { + if (InputParameterBlockSize > mTcgDxeData.BsCap.MaxCommandSize) { return EFI_INVALID_PARAMETER; } - if (OutputParameterBlockSize >= mTcgDxeData.BsCap.MaxResponseSize) { + if (OutputParameterBlockSize > mTcgDxeData.BsCap.MaxResponseSize) { return EFI_INVALID_PARAMETER; } diff --git a/ShellPkg/Library/UefiHandleParsingLib/UefiHandleParsingLib.c b/ShellPkg/Library/UefiHandleParsingLib/UefiHandleParsingLib.c index b82f925c92..6371086525 100644 --- a/ShellPkg/Library/UefiHandleParsingLib/UefiHandleParsingLib.c +++ b/ShellPkg/Library/UefiHandleParsingLib/UefiHandleParsingLib.c @@ -2460,10 +2460,6 @@ ParseHandleDatabaseByRelationshipWithType ( (*HandleType)[HandleIndex] |= (UINTN)HR_COMPONENT_NAME_HANDLE; } else if (CompareGuid (ProtocolGuidArray[ProtocolIndex], &gEfiDevicePathProtocolGuid) ) { (*HandleType)[HandleIndex] |= (UINTN)HR_DEVICE_HANDLE; - } else { - DEBUG_CODE_BEGIN(); - ASSERT((*HandleType)[HandleIndex] == (*HandleType)[HandleIndex]); - DEBUG_CODE_END(); } // // Retrieve the list of agents that have opened each protocol diff --git a/ShellPkg/Library/UefiShellLevel1CommandsLib/If.c b/ShellPkg/Library/UefiShellLevel1CommandsLib/If.c index 7abfd8944b..dc96bffde7 100644 --- a/ShellPkg/Library/UefiShellLevel1CommandsLib/If.c +++ b/ShellPkg/Library/UefiShellLevel1CommandsLib/If.c @@ -991,8 +991,11 @@ ShellCommandRunElse ( IN EFI_SYSTEM_TABLE *SystemTable ) { + EFI_STATUS Status; SCRIPT_FILE *CurrentScriptFile; - ASSERT_EFI_ERROR(CommandInit()); + + Status = CommandInit (); + ASSERT_EFI_ERROR (Status); if (gEfiShellParametersProtocol->Argc > 1) { ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellLevel1HiiHandle, L"if"); @@ -1066,8 +1069,11 @@ ShellCommandRunEndIf ( IN EFI_SYSTEM_TABLE *SystemTable ) { + EFI_STATUS Status; SCRIPT_FILE *CurrentScriptFile; - ASSERT_EFI_ERROR(CommandInit()); + + Status = CommandInit (); + ASSERT_EFI_ERROR (Status); if (gEfiShellParametersProtocol->Argc > 1) { ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellLevel1HiiHandle, L"if"); diff --git a/ShellPkg/Library/UefiShellLib/UefiShellLib.c b/ShellPkg/Library/UefiShellLib/UefiShellLib.c index cf89a4ac87..35a1a7169c 100644 --- a/ShellPkg/Library/UefiShellLib/UefiShellLib.c +++ b/ShellPkg/Library/UefiShellLib/UefiShellLib.c @@ -373,6 +373,8 @@ EFIAPI ShellInitialize ( ) { + EFI_STATUS Status; + // // if auto initialize is not false then skip // @@ -383,7 +385,8 @@ ShellInitialize ( // // deinit the current stuff // - ASSERT_EFI_ERROR(ShellLibDestructor(gImageHandle, gST)); + Status = ShellLibDestructor (gImageHandle, gST); + ASSERT_EFI_ERROR (Status); // // init the new stuff diff --git a/UefiCpuPkg/PiSmmCpuDxeSmm/X64/SmmProfileArch.c b/UefiCpuPkg/PiSmmCpuDxeSmm/X64/SmmProfileArch.c index 79e23ef647..065fb2c24c 100644 --- a/UefiCpuPkg/PiSmmCpuDxeSmm/X64/SmmProfileArch.c +++ b/UefiCpuPkg/PiSmmCpuDxeSmm/X64/SmmProfileArch.c @@ -78,7 +78,7 @@ InitPagesForPFHandler ( // Address = NULL; Address = AllocatePages (MAX_PF_PAGE_COUNT); - ASSERT_EFI_ERROR (Address != NULL); + ASSERT (Address != NULL); mPFPageBuffer = (UINT64)(UINTN) Address; mPFPageIndex = 0;