MemoryProfileInfo.c 50 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361
  1. /** @file
  2. Copyright (c) 2014 - 2017, Intel Corporation. All rights reserved.<BR>
  3. SPDX-License-Identifier: BSD-2-Clause-Patent
  4. **/
  5. #include <Uefi.h>
  6. #include <PiDxe.h>
  7. #include <Library/BaseLib.h>
  8. #include <Library/BaseMemoryLib.h>
  9. #include <Library/MemoryAllocationLib.h>
  10. #include <Library/UefiLib.h>
  11. #include <Library/UefiApplicationEntryPoint.h>
  12. #include <Library/UefiBootServicesTableLib.h>
  13. #include <Library/UefiRuntimeServicesTableLib.h>
  14. #include <Library/DebugLib.h>
  15. #include <Library/DxeServicesLib.h>
  16. #include <Library/PrintLib.h>
  17. #include <Protocol/SmmCommunication.h>
  18. #include <Protocol/SmmAccess2.h>
  19. #include <Guid/MemoryProfile.h>
  20. #include <Guid/PiSmmCommunicationRegionTable.h>
  21. CHAR8 *mActionString[] = {
  22. "Unknown",
  23. "gBS->AllocatePages",
  24. "gBS->FreePages",
  25. "gBS->AllocatePool",
  26. "gBS->FreePool",
  27. };
  28. CHAR8 *mSmmActionString[] = {
  29. "SmmUnknown",
  30. "gSmst->SmmAllocatePages",
  31. "gSmst->SmmFreePages",
  32. "gSmst->SmmAllocatePool",
  33. "gSmst->SmmFreePool",
  34. };
  35. typedef struct {
  36. MEMORY_PROFILE_ACTION Action;
  37. CHAR8 *String;
  38. } ACTION_STRING;
  39. ACTION_STRING mExtActionString[] = {
  40. {MEMORY_PROFILE_ACTION_LIB_ALLOCATE_PAGES, "Lib:AllocatePages"},
  41. {MEMORY_PROFILE_ACTION_LIB_ALLOCATE_RUNTIME_PAGES, "Lib:AllocateRuntimePages"},
  42. {MEMORY_PROFILE_ACTION_LIB_ALLOCATE_RESERVED_PAGES, "Lib:AllocateReservedPages"},
  43. {MEMORY_PROFILE_ACTION_LIB_FREE_PAGES, "Lib:FreePages"},
  44. {MEMORY_PROFILE_ACTION_LIB_ALLOCATE_ALIGNED_PAGES, "Lib:AllocateAlignedPages"},
  45. {MEMORY_PROFILE_ACTION_LIB_ALLOCATE_ALIGNED_RUNTIME_PAGES, "Lib:AllocateAlignedRuntimePages"},
  46. {MEMORY_PROFILE_ACTION_LIB_ALLOCATE_ALIGNED_RESERVED_PAGES, "Lib:AllocateAlignedReservedPages"},
  47. {MEMORY_PROFILE_ACTION_LIB_FREE_ALIGNED_PAGES, "Lib:FreeAlignedPages"},
  48. {MEMORY_PROFILE_ACTION_LIB_ALLOCATE_POOL, "Lib:AllocatePool"},
  49. {MEMORY_PROFILE_ACTION_LIB_ALLOCATE_RUNTIME_POOL, "Lib:AllocateRuntimePool"},
  50. {MEMORY_PROFILE_ACTION_LIB_ALLOCATE_RESERVED_POOL, "Lib:AllocateReservedPool"},
  51. {MEMORY_PROFILE_ACTION_LIB_FREE_POOL, "Lib:FreePool"},
  52. {MEMORY_PROFILE_ACTION_LIB_ALLOCATE_ZERO_POOL, "Lib:AllocateZeroPool"},
  53. {MEMORY_PROFILE_ACTION_LIB_ALLOCATE_RUNTIME_ZERO_POOL, "Lib:AllocateRuntimeZeroPool"},
  54. {MEMORY_PROFILE_ACTION_LIB_ALLOCATE_RESERVED_ZERO_POOL, "Lib:AllocateReservedZeroPool"},
  55. {MEMORY_PROFILE_ACTION_LIB_ALLOCATE_COPY_POOL, "Lib:AllocateCopyPool"},
  56. {MEMORY_PROFILE_ACTION_LIB_ALLOCATE_RUNTIME_COPY_POOL, "Lib:AllocateRuntimeCopyPool"},
  57. {MEMORY_PROFILE_ACTION_LIB_ALLOCATE_RESERVED_COPY_POOL, "Lib:AllocateReservedCopyPool"},
  58. {MEMORY_PROFILE_ACTION_LIB_REALLOCATE_POOL, "Lib:ReallocatePool"},
  59. {MEMORY_PROFILE_ACTION_LIB_REALLOCATE_RUNTIME_POOL, "Lib:ReallocateRuntimePool"},
  60. {MEMORY_PROFILE_ACTION_LIB_REALLOCATE_RESERVED_POOL, "Lib:ReallocateReservedPool"},
  61. };
  62. CHAR8 mUserDefinedActionString[] = {"UserDefined-0x80000000"};
  63. CHAR8 *mMemoryTypeString[] = {
  64. "EfiReservedMemoryType",
  65. "EfiLoaderCode",
  66. "EfiLoaderData",
  67. "EfiBootServicesCode",
  68. "EfiBootServicesData",
  69. "EfiRuntimeServicesCode",
  70. "EfiRuntimeServicesData",
  71. "EfiConventionalMemory",
  72. "EfiUnusableMemory",
  73. "EfiACPIReclaimMemory",
  74. "EfiACPIMemoryNVS",
  75. "EfiMemoryMappedIO",
  76. "EfiMemoryMappedIOPortSpace",
  77. "EfiPalCode",
  78. "EfiPersistentMemory",
  79. "EfiOSReserved",
  80. "EfiOemReserved",
  81. };
  82. CHAR8 *mSubsystemString[] = {
  83. "Unknown",
  84. "NATIVE",
  85. "WINDOWS_GUI",
  86. "WINDOWS_CUI",
  87. "Unknown",
  88. "Unknown",
  89. "Unknown",
  90. "POSIX_CUI",
  91. "Unknown",
  92. "WINDOWS_CE_GUI",
  93. "EFI_APPLICATION",
  94. "EFI_BOOT_SERVICE_DRIVER",
  95. "EFI_RUNTIME_DRIVER",
  96. "EFI_ROM",
  97. "XBOX",
  98. "Unknown",
  99. };
  100. CHAR8 *mFileTypeString[] = {
  101. "Unknown",
  102. "RAW",
  103. "FREEFORM",
  104. "SECURITY_CORE",
  105. "PEI_CORE",
  106. "DXE_CORE",
  107. "PEIM",
  108. "DRIVER",
  109. "COMBINED_PEIM_DRIVER",
  110. "APPLICATION",
  111. "SMM",
  112. "FIRMWARE_VOLUME_IMAGE",
  113. "COMBINED_SMM_DXE",
  114. "SMM_CORE",
  115. };
  116. #define PROFILE_NAME_STRING_LENGTH 64
  117. CHAR8 mNameString[PROFILE_NAME_STRING_LENGTH + 1];
  118. //
  119. // Profile summary information
  120. //
  121. #define MEMORY_PROFILE_ALLOC_SUMMARY_INFO_SIGNATURE SIGNATURE_32 ('M','P','A','S')
  122. #define MEMORY_PROFILE_ALLOC_SUMMARY_INFO_REVISION 0x0001
  123. typedef struct {
  124. MEMORY_PROFILE_COMMON_HEADER Header;
  125. PHYSICAL_ADDRESS CallerAddress;
  126. MEMORY_PROFILE_ACTION Action;
  127. CHAR8 *ActionString;
  128. UINT32 AllocateCount;
  129. UINT64 TotalSize;
  130. } MEMORY_PROFILE_ALLOC_SUMMARY_INFO;
  131. typedef struct {
  132. UINT32 Signature;
  133. MEMORY_PROFILE_ALLOC_SUMMARY_INFO AllocSummaryInfo;
  134. LIST_ENTRY Link;
  135. } MEMORY_PROFILE_ALLOC_SUMMARY_INFO_DATA;
  136. typedef struct {
  137. UINT32 Signature;
  138. MEMORY_PROFILE_DRIVER_INFO *DriverInfo;
  139. LIST_ENTRY *AllocSummaryInfoList;
  140. LIST_ENTRY Link;
  141. } MEMORY_PROFILE_DRIVER_SUMMARY_INFO_DATA;
  142. typedef struct {
  143. UINT32 Signature;
  144. MEMORY_PROFILE_CONTEXT *Context;
  145. LIST_ENTRY *DriverSummaryInfoList;
  146. } MEMORY_PROFILE_CONTEXT_SUMMARY_DATA;
  147. LIST_ENTRY mImageSummaryQueue = INITIALIZE_LIST_HEAD_VARIABLE (mImageSummaryQueue);
  148. MEMORY_PROFILE_CONTEXT_SUMMARY_DATA mMemoryProfileContextSummary;
  149. /**
  150. Get the file name portion of the Pdb File Name.
  151. The portion of the Pdb File Name between the last backslash and
  152. either a following period or the end of the string is copied into
  153. AsciiBuffer. The name is truncated, if necessary, to ensure that
  154. AsciiBuffer is not overrun.
  155. @param[in] PdbFileName Pdb file name.
  156. @param[out] AsciiBuffer The resultant Ascii File Name.
  157. **/
  158. VOID
  159. GetShortPdbFileName (
  160. IN CHAR8 *PdbFileName,
  161. OUT CHAR8 *AsciiBuffer
  162. )
  163. {
  164. UINTN IndexPdb; // Current work location within a Pdb string.
  165. UINTN IndexBuffer; // Current work location within a Buffer string.
  166. UINTN StartIndex;
  167. UINTN EndIndex;
  168. ZeroMem (AsciiBuffer, PROFILE_NAME_STRING_LENGTH + 1);
  169. if (PdbFileName == NULL) {
  170. AsciiStrnCpyS (AsciiBuffer, PROFILE_NAME_STRING_LENGTH + 1, " ", 1);
  171. } else {
  172. StartIndex = 0;
  173. for (EndIndex = 0; PdbFileName[EndIndex] != 0; EndIndex++);
  174. for (IndexPdb = 0; PdbFileName[IndexPdb] != 0; IndexPdb++) {
  175. if ((PdbFileName[IndexPdb] == '\\') || (PdbFileName[IndexPdb] == '/')) {
  176. StartIndex = IndexPdb + 1;
  177. }
  178. if (PdbFileName[IndexPdb] == '.') {
  179. EndIndex = IndexPdb;
  180. }
  181. }
  182. IndexBuffer = 0;
  183. for (IndexPdb = StartIndex; IndexPdb < EndIndex; IndexPdb++) {
  184. AsciiBuffer[IndexBuffer] = PdbFileName[IndexPdb];
  185. IndexBuffer++;
  186. if (IndexBuffer >= PROFILE_NAME_STRING_LENGTH) {
  187. AsciiBuffer[PROFILE_NAME_STRING_LENGTH] = 0;
  188. break;
  189. }
  190. }
  191. }
  192. }
  193. /**
  194. Get a human readable name for an image.
  195. The following methods will be tried orderly:
  196. 1. Image PDB
  197. 2. FFS UI section
  198. 3. Image GUID
  199. @param[in] DriverInfo Pointer to memory profile driver info.
  200. @return The resulting Ascii name string is stored in the mNameString global array.
  201. **/
  202. CHAR8 *
  203. GetDriverNameString (
  204. IN MEMORY_PROFILE_DRIVER_INFO *DriverInfo
  205. )
  206. {
  207. EFI_STATUS Status;
  208. CHAR16 *NameString;
  209. UINTN StringSize;
  210. //
  211. // Method 1: Get the name string from image PDB
  212. //
  213. if (DriverInfo->PdbStringOffset != 0) {
  214. GetShortPdbFileName ((CHAR8 *) ((UINTN) DriverInfo + DriverInfo->PdbStringOffset), mNameString);
  215. return mNameString;
  216. }
  217. if (!IsZeroGuid (&DriverInfo->FileName)) {
  218. //
  219. // Try to get the image's FFS UI section by image GUID
  220. //
  221. NameString = NULL;
  222. StringSize = 0;
  223. Status = GetSectionFromAnyFv (
  224. &DriverInfo->FileName,
  225. EFI_SECTION_USER_INTERFACE,
  226. 0,
  227. (VOID **) &NameString,
  228. &StringSize
  229. );
  230. if (!EFI_ERROR (Status)) {
  231. //
  232. // Method 2: Get the name string from FFS UI section
  233. //
  234. if (StrLen (NameString) > PROFILE_NAME_STRING_LENGTH) {
  235. NameString[PROFILE_NAME_STRING_LENGTH] = 0;
  236. }
  237. UnicodeStrToAsciiStrS (NameString, mNameString, sizeof (mNameString));
  238. FreePool (NameString);
  239. return mNameString;
  240. }
  241. }
  242. //
  243. // Method 3: Get the name string from image GUID
  244. //
  245. AsciiSPrint (mNameString, sizeof (mNameString), "%g", &DriverInfo->FileName);
  246. return mNameString;
  247. }
  248. /**
  249. Memory type to string.
  250. @param[in] MemoryType Memory type.
  251. @return Pointer to string.
  252. **/
  253. CHAR8 *
  254. ProfileMemoryTypeToStr (
  255. IN EFI_MEMORY_TYPE MemoryType
  256. )
  257. {
  258. UINTN Index;
  259. if ((UINT32) MemoryType >= 0x80000000) {
  260. //
  261. // OS reserved memory type.
  262. //
  263. Index = EfiMaxMemoryType;
  264. } else if ((UINT32) MemoryType >= 0x70000000) {
  265. //
  266. // OEM reserved memory type.
  267. //
  268. Index = EfiMaxMemoryType + 1;
  269. } else {
  270. Index = MemoryType;
  271. }
  272. return mMemoryTypeString[Index];
  273. }
  274. /**
  275. Action to string.
  276. @param[in] Action Profile action.
  277. @param[in] UserDefinedActionString Pointer to user defined action string.
  278. @param[in] IsForSmm TRUE - SMRAM profile.
  279. FALSE - UEFI memory profile.
  280. @return Pointer to string.
  281. **/
  282. CHAR8 *
  283. ProfileActionToStr (
  284. IN MEMORY_PROFILE_ACTION Action,
  285. IN CHAR8 *UserDefinedActionString,
  286. IN BOOLEAN IsForSmm
  287. )
  288. {
  289. UINTN Index;
  290. UINTN ActionStringCount;
  291. CHAR8 **ActionString;
  292. if (IsForSmm) {
  293. ActionString = mSmmActionString;
  294. ActionStringCount = ARRAY_SIZE (mSmmActionString);
  295. } else {
  296. ActionString = mActionString;
  297. ActionStringCount = ARRAY_SIZE (mActionString);
  298. }
  299. if ((UINTN) (UINT32) Action < ActionStringCount) {
  300. return ActionString[Action];
  301. }
  302. for (Index = 0; Index < ARRAY_SIZE (mExtActionString); Index++) {
  303. if (mExtActionString[Index].Action == Action) {
  304. return mExtActionString[Index].String;
  305. }
  306. }
  307. if ((Action & MEMORY_PROFILE_ACTION_USER_DEFINED_MASK) != 0) {
  308. if (UserDefinedActionString != NULL) {
  309. return UserDefinedActionString;
  310. }
  311. AsciiSPrint (mUserDefinedActionString, sizeof (mUserDefinedActionString), "UserDefined-0x%08x", Action);
  312. return mUserDefinedActionString;
  313. }
  314. return ActionString[0];
  315. }
  316. /**
  317. Dump memory profile allocate information.
  318. @param[in] DriverInfo Pointer to memory profile driver info.
  319. @param[in] AllocIndex Memory profile alloc info index.
  320. @param[in] AllocInfo Pointer to memory profile alloc info.
  321. @param[in] IsForSmm TRUE - SMRAM profile.
  322. FALSE - UEFI memory profile.
  323. @return Pointer to next memory profile alloc info.
  324. **/
  325. MEMORY_PROFILE_ALLOC_INFO *
  326. DumpMemoryProfileAllocInfo (
  327. IN MEMORY_PROFILE_DRIVER_INFO *DriverInfo,
  328. IN UINTN AllocIndex,
  329. IN MEMORY_PROFILE_ALLOC_INFO *AllocInfo,
  330. IN BOOLEAN IsForSmm
  331. )
  332. {
  333. CHAR8 *ActionString;
  334. if (AllocInfo->Header.Signature != MEMORY_PROFILE_ALLOC_INFO_SIGNATURE) {
  335. return NULL;
  336. }
  337. if (AllocInfo->ActionStringOffset != 0) {
  338. ActionString = (CHAR8 *) ((UINTN) AllocInfo + AllocInfo->ActionStringOffset);
  339. } else {
  340. ActionString = NULL;
  341. }
  342. Print (L" MEMORY_PROFILE_ALLOC_INFO (0x%x)\n", AllocIndex);
  343. Print (L" Signature - 0x%08x\n", AllocInfo->Header.Signature);
  344. Print (L" Length - 0x%04x\n", AllocInfo->Header.Length);
  345. Print (L" Revision - 0x%04x\n", AllocInfo->Header.Revision);
  346. Print (L" CallerAddress - 0x%016lx (Offset: 0x%08x)\n", AllocInfo->CallerAddress, (UINTN) (AllocInfo->CallerAddress - DriverInfo->ImageBase));
  347. Print (L" SequenceId - 0x%08x\n", AllocInfo->SequenceId);
  348. Print (L" Action - 0x%08x (%a)\n", AllocInfo->Action, ProfileActionToStr (AllocInfo->Action, ActionString, IsForSmm));
  349. Print (L" MemoryType - 0x%08x (%a)\n", AllocInfo->MemoryType, ProfileMemoryTypeToStr (AllocInfo->MemoryType));
  350. Print (L" Buffer - 0x%016lx\n", AllocInfo->Buffer);
  351. Print (L" Size - 0x%016lx\n", AllocInfo->Size);
  352. return (MEMORY_PROFILE_ALLOC_INFO *) ((UINTN) AllocInfo + AllocInfo->Header.Length);
  353. }
  354. /**
  355. Dump memory profile driver information.
  356. @param[in] DriverIndex Memory profile driver info index.
  357. @param[in] DriverInfo Pointer to memory profile driver info.
  358. @param[in] IsForSmm TRUE - SMRAM profile.
  359. FALSE - UEFI memory profile.
  360. @return Pointer to next memory profile driver info.
  361. **/
  362. MEMORY_PROFILE_DRIVER_INFO *
  363. DumpMemoryProfileDriverInfo (
  364. IN UINTN DriverIndex,
  365. IN MEMORY_PROFILE_DRIVER_INFO *DriverInfo,
  366. IN BOOLEAN IsForSmm
  367. )
  368. {
  369. UINTN TypeIndex;
  370. MEMORY_PROFILE_ALLOC_INFO *AllocInfo;
  371. UINTN AllocIndex;
  372. CHAR8 *NameString;
  373. if (DriverInfo->Header.Signature != MEMORY_PROFILE_DRIVER_INFO_SIGNATURE) {
  374. return NULL;
  375. }
  376. Print (L" MEMORY_PROFILE_DRIVER_INFO (0x%x)\n", DriverIndex);
  377. Print (L" Signature - 0x%08x\n", DriverInfo->Header.Signature);
  378. Print (L" Length - 0x%04x\n", DriverInfo->Header.Length);
  379. Print (L" Revision - 0x%04x\n", DriverInfo->Header.Revision);
  380. NameString = GetDriverNameString (DriverInfo);
  381. Print (L" FileName - %a\n", NameString);
  382. if (DriverInfo->PdbStringOffset != 0) {
  383. Print (L" Pdb - %a\n", (CHAR8 *) ((UINTN) DriverInfo + DriverInfo->PdbStringOffset));
  384. }
  385. Print (L" ImageBase - 0x%016lx\n", DriverInfo->ImageBase);
  386. Print (L" ImageSize - 0x%016lx\n", DriverInfo->ImageSize);
  387. Print (L" EntryPoint - 0x%016lx\n", DriverInfo->EntryPoint);
  388. Print (L" ImageSubsystem - 0x%04x (%a)\n", DriverInfo->ImageSubsystem, mSubsystemString[(DriverInfo->ImageSubsystem < sizeof(mSubsystemString)/sizeof(mSubsystemString[0])) ? DriverInfo->ImageSubsystem : 0]);
  389. Print (L" FileType - 0x%02x (%a)\n", DriverInfo->FileType, mFileTypeString[(DriverInfo->FileType < sizeof(mFileTypeString)/sizeof(mFileTypeString[0])) ? DriverInfo->FileType : 0]);
  390. Print (L" CurrentUsage - 0x%016lx\n", DriverInfo->CurrentUsage);
  391. Print (L" PeakUsage - 0x%016lx\n", DriverInfo->PeakUsage);
  392. for (TypeIndex = 0; TypeIndex < sizeof (DriverInfo->CurrentUsageByType) / sizeof (DriverInfo->CurrentUsageByType[0]); TypeIndex++) {
  393. if ((DriverInfo->CurrentUsageByType[TypeIndex] != 0) ||
  394. (DriverInfo->PeakUsageByType[TypeIndex] != 0)) {
  395. Print (L" CurrentUsage[0x%02x] - 0x%016lx (%a)\n", TypeIndex, DriverInfo->CurrentUsageByType[TypeIndex], mMemoryTypeString[TypeIndex]);
  396. Print (L" PeakUsage[0x%02x] - 0x%016lx (%a)\n", TypeIndex, DriverInfo->PeakUsageByType[TypeIndex], mMemoryTypeString[TypeIndex]);
  397. }
  398. }
  399. Print (L" AllocRecordCount - 0x%08x\n", DriverInfo->AllocRecordCount);
  400. AllocInfo = (MEMORY_PROFILE_ALLOC_INFO *) ((UINTN) DriverInfo + DriverInfo->Header.Length);
  401. for (AllocIndex = 0; AllocIndex < DriverInfo->AllocRecordCount; AllocIndex++) {
  402. AllocInfo = DumpMemoryProfileAllocInfo (DriverInfo, AllocIndex, AllocInfo, IsForSmm);
  403. if (AllocInfo == NULL) {
  404. return NULL;
  405. }
  406. }
  407. return (MEMORY_PROFILE_DRIVER_INFO *) AllocInfo;
  408. }
  409. /**
  410. Dump memory profile context information.
  411. @param[in] Context Pointer to memory profile context.
  412. @param[in] IsForSmm TRUE - SMRAM profile.
  413. FALSE - UEFI memory profile.
  414. @return Pointer to the end of memory profile context buffer.
  415. **/
  416. VOID *
  417. DumpMemoryProfileContext (
  418. IN MEMORY_PROFILE_CONTEXT *Context,
  419. IN BOOLEAN IsForSmm
  420. )
  421. {
  422. UINTN TypeIndex;
  423. MEMORY_PROFILE_DRIVER_INFO *DriverInfo;
  424. UINTN DriverIndex;
  425. if (Context->Header.Signature != MEMORY_PROFILE_CONTEXT_SIGNATURE) {
  426. return NULL;
  427. }
  428. Print (L"MEMORY_PROFILE_CONTEXT\n");
  429. Print (L" Signature - 0x%08x\n", Context->Header.Signature);
  430. Print (L" Length - 0x%04x\n", Context->Header.Length);
  431. Print (L" Revision - 0x%04x\n", Context->Header.Revision);
  432. Print (L" CurrentTotalUsage - 0x%016lx\n", Context->CurrentTotalUsage);
  433. Print (L" PeakTotalUsage - 0x%016lx\n", Context->PeakTotalUsage);
  434. for (TypeIndex = 0; TypeIndex < sizeof (Context->CurrentTotalUsageByType) / sizeof (Context->CurrentTotalUsageByType[0]); TypeIndex++) {
  435. if ((Context->CurrentTotalUsageByType[TypeIndex] != 0) ||
  436. (Context->PeakTotalUsageByType[TypeIndex] != 0)) {
  437. Print (L" CurrentTotalUsage[0x%02x] - 0x%016lx (%a)\n", TypeIndex, Context->CurrentTotalUsageByType[TypeIndex], mMemoryTypeString[TypeIndex]);
  438. Print (L" PeakTotalUsage[0x%02x] - 0x%016lx (%a)\n", TypeIndex, Context->PeakTotalUsageByType[TypeIndex], mMemoryTypeString[TypeIndex]);
  439. }
  440. }
  441. Print (L" TotalImageSize - 0x%016lx\n", Context->TotalImageSize);
  442. Print (L" ImageCount - 0x%08x\n", Context->ImageCount);
  443. Print (L" SequenceCount - 0x%08x\n", Context->SequenceCount);
  444. DriverInfo = (MEMORY_PROFILE_DRIVER_INFO *) ((UINTN) Context + Context->Header.Length);
  445. for (DriverIndex = 0; DriverIndex < Context->ImageCount; DriverIndex++) {
  446. DriverInfo = DumpMemoryProfileDriverInfo (DriverIndex, DriverInfo, IsForSmm);
  447. if (DriverInfo == NULL) {
  448. return NULL;
  449. }
  450. }
  451. return (VOID *) DriverInfo;
  452. }
  453. /**
  454. Dump memory profile descriptor information.
  455. @param[in] DescriptorIndex Memory profile descriptor index.
  456. @param[in] Descriptor Pointer to memory profile descriptor.
  457. @return Pointer to next memory profile descriptor.
  458. **/
  459. MEMORY_PROFILE_DESCRIPTOR *
  460. DumpMemoryProfileDescriptor (
  461. IN UINTN DescriptorIndex,
  462. IN MEMORY_PROFILE_DESCRIPTOR *Descriptor
  463. )
  464. {
  465. if (Descriptor->Header.Signature != MEMORY_PROFILE_DESCRIPTOR_SIGNATURE) {
  466. return NULL;
  467. }
  468. Print (L" MEMORY_PROFILE_DESCRIPTOR (0x%x)\n", DescriptorIndex);
  469. Print (L" Signature - 0x%08x\n", Descriptor->Header.Signature);
  470. Print (L" Length - 0x%04x\n", Descriptor->Header.Length);
  471. Print (L" Revision - 0x%04x\n", Descriptor->Header.Revision);
  472. Print (L" Address - 0x%016lx\n", Descriptor->Address);
  473. Print (L" Size - 0x%016lx\n", Descriptor->Size);
  474. return (MEMORY_PROFILE_DESCRIPTOR *) ((UINTN) Descriptor + Descriptor->Header.Length);
  475. }
  476. /**
  477. Dump memory profile free memory information.
  478. @param[in] FreeMemory Pointer to memory profile free memory.
  479. @return Pointer to the end of memory profile free memory buffer.
  480. **/
  481. VOID *
  482. DumpMemoryProfileFreeMemory (
  483. IN MEMORY_PROFILE_FREE_MEMORY *FreeMemory
  484. )
  485. {
  486. MEMORY_PROFILE_DESCRIPTOR *Descriptor;
  487. UINTN DescriptorIndex;
  488. if (FreeMemory->Header.Signature != MEMORY_PROFILE_FREE_MEMORY_SIGNATURE) {
  489. return NULL;
  490. }
  491. Print (L"MEMORY_PROFILE_FREE_MEMORY\n");
  492. Print (L" Signature - 0x%08x\n", FreeMemory->Header.Signature);
  493. Print (L" Length - 0x%04x\n", FreeMemory->Header.Length);
  494. Print (L" Revision - 0x%04x\n", FreeMemory->Header.Revision);
  495. Print (L" TotalFreeMemoryPages - 0x%016lx\n", FreeMemory->TotalFreeMemoryPages);
  496. Print (L" FreeMemoryEntryCount - 0x%08x\n", FreeMemory->FreeMemoryEntryCount);
  497. Descriptor = (MEMORY_PROFILE_DESCRIPTOR *) ((UINTN) FreeMemory + FreeMemory->Header.Length);
  498. for (DescriptorIndex = 0; DescriptorIndex < FreeMemory->FreeMemoryEntryCount; DescriptorIndex++) {
  499. Descriptor = DumpMemoryProfileDescriptor (DescriptorIndex, Descriptor);
  500. if (Descriptor == NULL) {
  501. return NULL;
  502. }
  503. }
  504. return (VOID *) Descriptor;
  505. }
  506. /**
  507. Dump memory profile memory range information.
  508. @param[in] MemoryRange Pointer to memory profile memory range.
  509. @return Pointer to the end of memory profile memory range buffer.
  510. **/
  511. VOID *
  512. DumpMemoryProfileMemoryRange (
  513. IN MEMORY_PROFILE_MEMORY_RANGE *MemoryRange
  514. )
  515. {
  516. MEMORY_PROFILE_DESCRIPTOR *Descriptor;
  517. UINTN DescriptorIndex;
  518. if (MemoryRange->Header.Signature != MEMORY_PROFILE_MEMORY_RANGE_SIGNATURE) {
  519. return NULL;
  520. }
  521. Print (L"MEMORY_PROFILE_MEMORY_RANGE\n");
  522. Print (L" Signature - 0x%08x\n", MemoryRange->Header.Signature);
  523. Print (L" Length - 0x%04x\n", MemoryRange->Header.Length);
  524. Print (L" Revision - 0x%04x\n", MemoryRange->Header.Revision);
  525. Print (L" MemoryRangeCount - 0x%08x\n", MemoryRange->MemoryRangeCount);
  526. Descriptor = (MEMORY_PROFILE_DESCRIPTOR *) ((UINTN) MemoryRange + MemoryRange->Header.Length);
  527. for (DescriptorIndex = 0; DescriptorIndex < MemoryRange->MemoryRangeCount; DescriptorIndex++) {
  528. Descriptor = DumpMemoryProfileDescriptor (DescriptorIndex, Descriptor);
  529. if (Descriptor == NULL) {
  530. return NULL;
  531. }
  532. }
  533. return (VOID *) Descriptor;
  534. }
  535. /**
  536. Scan memory profile by Signature.
  537. @param[in] ProfileBuffer Memory profile base address.
  538. @param[in] ProfileSize Memory profile size.
  539. @param[in] Signature Signature.
  540. @return Pointer to the stucture with the signature.
  541. **/
  542. VOID *
  543. ScanMemoryProfileBySignature (
  544. IN PHYSICAL_ADDRESS ProfileBuffer,
  545. IN UINT64 ProfileSize,
  546. IN UINT32 Signature
  547. )
  548. {
  549. MEMORY_PROFILE_COMMON_HEADER *CommonHeader;
  550. UINTN ProfileEnd;
  551. ProfileEnd = (UINTN) (ProfileBuffer + ProfileSize);
  552. CommonHeader = (MEMORY_PROFILE_COMMON_HEADER *) (UINTN) ProfileBuffer;
  553. while ((UINTN) CommonHeader < ProfileEnd) {
  554. if (CommonHeader->Signature == Signature) {
  555. //
  556. // Found it.
  557. //
  558. return (VOID *) CommonHeader;
  559. }
  560. if (CommonHeader->Length == 0) {
  561. ASSERT (FALSE);
  562. return NULL;
  563. }
  564. CommonHeader = (MEMORY_PROFILE_COMMON_HEADER *) ((UINTN) CommonHeader + CommonHeader->Length);
  565. }
  566. return NULL;
  567. }
  568. /**
  569. Dump memory profile information.
  570. @param[in] ProfileBuffer Memory profile base address.
  571. @param[in] ProfileSize Memory profile size.
  572. @param[in] IsForSmm TRUE - SMRAM profile.
  573. FALSE - UEFI memory profile.
  574. **/
  575. VOID
  576. DumpMemoryProfile (
  577. IN PHYSICAL_ADDRESS ProfileBuffer,
  578. IN UINT64 ProfileSize,
  579. IN BOOLEAN IsForSmm
  580. )
  581. {
  582. MEMORY_PROFILE_CONTEXT *Context;
  583. MEMORY_PROFILE_FREE_MEMORY *FreeMemory;
  584. MEMORY_PROFILE_MEMORY_RANGE *MemoryRange;
  585. Context = (MEMORY_PROFILE_CONTEXT *) ScanMemoryProfileBySignature (ProfileBuffer, ProfileSize, MEMORY_PROFILE_CONTEXT_SIGNATURE);
  586. if (Context != NULL) {
  587. DumpMemoryProfileContext (Context, IsForSmm);
  588. }
  589. FreeMemory = (MEMORY_PROFILE_FREE_MEMORY *) ScanMemoryProfileBySignature (ProfileBuffer, ProfileSize, MEMORY_PROFILE_FREE_MEMORY_SIGNATURE);
  590. if (FreeMemory != NULL) {
  591. DumpMemoryProfileFreeMemory (FreeMemory);
  592. }
  593. MemoryRange = (MEMORY_PROFILE_MEMORY_RANGE *) ScanMemoryProfileBySignature (ProfileBuffer, ProfileSize, MEMORY_PROFILE_MEMORY_RANGE_SIGNATURE);
  594. if (MemoryRange != NULL) {
  595. DumpMemoryProfileMemoryRange (MemoryRange);
  596. }
  597. }
  598. /**
  599. Get Allocate summary information structure by caller address.
  600. @param[in] CallerAddress Caller address.
  601. @param[in] DriverSummaryInfoData Driver summary information data structure.
  602. @return Allocate summary information structure by caller address.
  603. **/
  604. MEMORY_PROFILE_ALLOC_SUMMARY_INFO_DATA *
  605. GetAllocSummaryInfoByCallerAddress (
  606. IN PHYSICAL_ADDRESS CallerAddress,
  607. IN MEMORY_PROFILE_DRIVER_SUMMARY_INFO_DATA *DriverSummaryInfoData
  608. )
  609. {
  610. LIST_ENTRY *AllocSummaryInfoList;
  611. LIST_ENTRY *AllocSummaryLink;
  612. MEMORY_PROFILE_ALLOC_SUMMARY_INFO *AllocSummaryInfo;
  613. MEMORY_PROFILE_ALLOC_SUMMARY_INFO_DATA *AllocSummaryInfoData;
  614. AllocSummaryInfoList = DriverSummaryInfoData->AllocSummaryInfoList;
  615. for (AllocSummaryLink = AllocSummaryInfoList->ForwardLink;
  616. AllocSummaryLink != AllocSummaryInfoList;
  617. AllocSummaryLink = AllocSummaryLink->ForwardLink) {
  618. AllocSummaryInfoData = CR (
  619. AllocSummaryLink,
  620. MEMORY_PROFILE_ALLOC_SUMMARY_INFO_DATA,
  621. Link,
  622. MEMORY_PROFILE_ALLOC_SUMMARY_INFO_SIGNATURE
  623. );
  624. AllocSummaryInfo = &AllocSummaryInfoData->AllocSummaryInfo;
  625. if (AllocSummaryInfo->CallerAddress == CallerAddress) {
  626. return AllocSummaryInfoData;
  627. }
  628. }
  629. return NULL;
  630. }
  631. /**
  632. Create Allocate summary information structure and
  633. link to Driver summary information data structure.
  634. @param[in, out] DriverSummaryInfoData Driver summary information data structure.
  635. @param[in] AllocInfo Pointer to memory profile alloc info.
  636. @return Pointer to next memory profile alloc info.
  637. **/
  638. MEMORY_PROFILE_ALLOC_INFO *
  639. CreateAllocSummaryInfo (
  640. IN OUT MEMORY_PROFILE_DRIVER_SUMMARY_INFO_DATA *DriverSummaryInfoData,
  641. IN MEMORY_PROFILE_ALLOC_INFO *AllocInfo
  642. )
  643. {
  644. MEMORY_PROFILE_ALLOC_SUMMARY_INFO_DATA *AllocSummaryInfoData;
  645. MEMORY_PROFILE_ALLOC_SUMMARY_INFO *AllocSummaryInfo;
  646. if (AllocInfo->Header.Signature != MEMORY_PROFILE_ALLOC_INFO_SIGNATURE) {
  647. return NULL;
  648. }
  649. AllocSummaryInfoData = GetAllocSummaryInfoByCallerAddress (AllocInfo->CallerAddress, DriverSummaryInfoData);
  650. if (AllocSummaryInfoData == NULL) {
  651. AllocSummaryInfoData = AllocatePool (sizeof (*AllocSummaryInfoData));
  652. if (AllocSummaryInfoData == NULL) {
  653. return NULL;
  654. }
  655. AllocSummaryInfoData->Signature = MEMORY_PROFILE_ALLOC_SUMMARY_INFO_SIGNATURE;
  656. AllocSummaryInfo = &AllocSummaryInfoData->AllocSummaryInfo;
  657. AllocSummaryInfo->Header.Signature = MEMORY_PROFILE_ALLOC_SUMMARY_INFO_SIGNATURE;
  658. AllocSummaryInfo->Header.Length = sizeof (*AllocSummaryInfo);
  659. AllocSummaryInfo->Header.Revision = MEMORY_PROFILE_ALLOC_SUMMARY_INFO_REVISION;
  660. AllocSummaryInfo->CallerAddress = AllocInfo->CallerAddress;
  661. AllocSummaryInfo->Action = AllocInfo->Action;
  662. if (AllocInfo->ActionStringOffset != 0) {
  663. AllocSummaryInfo->ActionString = (CHAR8 *) ((UINTN) AllocInfo + AllocInfo->ActionStringOffset);
  664. } else {
  665. AllocSummaryInfo->ActionString = NULL;
  666. }
  667. AllocSummaryInfo->AllocateCount = 0;
  668. AllocSummaryInfo->TotalSize = 0;
  669. InsertTailList (DriverSummaryInfoData->AllocSummaryInfoList, &AllocSummaryInfoData->Link);
  670. }
  671. AllocSummaryInfo = &AllocSummaryInfoData->AllocSummaryInfo;
  672. AllocSummaryInfo->AllocateCount ++;
  673. AllocSummaryInfo->TotalSize += AllocInfo->Size;
  674. return (MEMORY_PROFILE_ALLOC_INFO *) ((UINTN) AllocInfo + AllocInfo->Header.Length);
  675. }
  676. /**
  677. Create Driver summary information structure and
  678. link to Context summary information data structure.
  679. @param[in, out] ContextSummaryData Context summary information data structure.
  680. @param[in] DriverInfo Pointer to memory profile driver info.
  681. @return Pointer to next memory profile driver info.
  682. **/
  683. MEMORY_PROFILE_DRIVER_INFO *
  684. CreateDriverSummaryInfo (
  685. IN OUT MEMORY_PROFILE_CONTEXT_SUMMARY_DATA *ContextSummaryData,
  686. IN MEMORY_PROFILE_DRIVER_INFO *DriverInfo
  687. )
  688. {
  689. MEMORY_PROFILE_DRIVER_SUMMARY_INFO_DATA *DriverSummaryInfoData;
  690. MEMORY_PROFILE_ALLOC_INFO *AllocInfo;
  691. UINTN AllocIndex;
  692. if (DriverInfo->Header.Signature != MEMORY_PROFILE_DRIVER_INFO_SIGNATURE) {
  693. return NULL;
  694. }
  695. DriverSummaryInfoData = AllocatePool (sizeof (*DriverSummaryInfoData) + sizeof (LIST_ENTRY));
  696. if (DriverSummaryInfoData == NULL) {
  697. return NULL;
  698. }
  699. DriverSummaryInfoData->Signature = MEMORY_PROFILE_DRIVER_INFO_SIGNATURE;
  700. DriverSummaryInfoData->DriverInfo = DriverInfo;
  701. DriverSummaryInfoData->AllocSummaryInfoList = (LIST_ENTRY *) (DriverSummaryInfoData + 1);
  702. InitializeListHead (DriverSummaryInfoData->AllocSummaryInfoList);
  703. InsertTailList (ContextSummaryData->DriverSummaryInfoList, &DriverSummaryInfoData->Link);
  704. AllocInfo = (MEMORY_PROFILE_ALLOC_INFO *) ((UINTN) DriverInfo + DriverInfo->Header.Length);
  705. for (AllocIndex = 0; AllocIndex < DriverInfo->AllocRecordCount; AllocIndex++) {
  706. AllocInfo = CreateAllocSummaryInfo (DriverSummaryInfoData, AllocInfo);
  707. if (AllocInfo == NULL) {
  708. return NULL;
  709. }
  710. }
  711. return (MEMORY_PROFILE_DRIVER_INFO *) AllocInfo;
  712. }
  713. /**
  714. Create Context summary information structure.
  715. @param[in] ProfileBuffer Memory profile base address.
  716. @param[in] ProfileSize Memory profile size.
  717. @return Context summary information structure.
  718. **/
  719. MEMORY_PROFILE_CONTEXT_SUMMARY_DATA *
  720. CreateContextSummaryData (
  721. IN PHYSICAL_ADDRESS ProfileBuffer,
  722. IN UINT64 ProfileSize
  723. )
  724. {
  725. MEMORY_PROFILE_CONTEXT *Context;
  726. MEMORY_PROFILE_DRIVER_INFO *DriverInfo;
  727. UINTN DriverIndex;
  728. Context = (MEMORY_PROFILE_CONTEXT *) ScanMemoryProfileBySignature (ProfileBuffer, ProfileSize, MEMORY_PROFILE_CONTEXT_SIGNATURE);
  729. if (Context == NULL) {
  730. return NULL;
  731. }
  732. mMemoryProfileContextSummary.Signature = MEMORY_PROFILE_CONTEXT_SIGNATURE;
  733. mMemoryProfileContextSummary.Context = Context;
  734. mMemoryProfileContextSummary.DriverSummaryInfoList = &mImageSummaryQueue;
  735. DriverInfo = (MEMORY_PROFILE_DRIVER_INFO *) ((UINTN) Context + Context->Header.Length);
  736. for (DriverIndex = 0; DriverIndex < Context->ImageCount; DriverIndex++) {
  737. DriverInfo = CreateDriverSummaryInfo (&mMemoryProfileContextSummary, DriverInfo);
  738. if (DriverInfo == NULL) {
  739. return NULL;
  740. }
  741. }
  742. return &mMemoryProfileContextSummary;
  743. }
  744. /**
  745. Dump Context summary information.
  746. @param[in] ContextSummaryData Context summary information data.
  747. @param[in] IsForSmm TRUE - SMRAM profile.
  748. FALSE - UEFI memory profile.
  749. **/
  750. VOID
  751. DumpContextSummaryData (
  752. IN MEMORY_PROFILE_CONTEXT_SUMMARY_DATA *ContextSummaryData,
  753. IN BOOLEAN IsForSmm
  754. )
  755. {
  756. MEMORY_PROFILE_DRIVER_SUMMARY_INFO_DATA *DriverSummaryInfoData;
  757. MEMORY_PROFILE_ALLOC_SUMMARY_INFO_DATA *AllocSummaryInfoData;
  758. LIST_ENTRY *DriverSummaryInfoList;
  759. LIST_ENTRY *DriverSummaryLink;
  760. LIST_ENTRY *AllocSummaryInfoList;
  761. LIST_ENTRY *AllocSummaryLink;
  762. MEMORY_PROFILE_DRIVER_INFO *DriverInfo;
  763. MEMORY_PROFILE_ALLOC_SUMMARY_INFO *AllocSummaryInfo;
  764. CHAR8 *NameString;
  765. if (ContextSummaryData == NULL) {
  766. return ;
  767. }
  768. Print (L"\nSummary Data:\n");
  769. DriverSummaryInfoList = ContextSummaryData->DriverSummaryInfoList;
  770. for (DriverSummaryLink = DriverSummaryInfoList->ForwardLink;
  771. DriverSummaryLink != DriverSummaryInfoList;
  772. DriverSummaryLink = DriverSummaryLink->ForwardLink) {
  773. DriverSummaryInfoData = CR (
  774. DriverSummaryLink,
  775. MEMORY_PROFILE_DRIVER_SUMMARY_INFO_DATA,
  776. Link,
  777. MEMORY_PROFILE_DRIVER_INFO_SIGNATURE
  778. );
  779. DriverInfo = DriverSummaryInfoData->DriverInfo;
  780. NameString = GetDriverNameString (DriverInfo);
  781. Print (L"\nDriver - %a (Usage - 0x%08x)", NameString, DriverInfo->CurrentUsage);
  782. if (DriverInfo->CurrentUsage == 0) {
  783. Print (L"\n");
  784. continue;
  785. }
  786. if (DriverInfo->PdbStringOffset != 0) {
  787. Print (L" (Pdb - %a)\n", (CHAR8 *) ((UINTN) DriverInfo + DriverInfo->PdbStringOffset));
  788. } else {
  789. Print (L"\n");
  790. }
  791. Print (L"Caller List:\n");
  792. Print(L" Count Size RVA Action\n");
  793. Print(L"========== ================== ================== (================================)\n");
  794. AllocSummaryInfoList = DriverSummaryInfoData->AllocSummaryInfoList;
  795. for (AllocSummaryLink = AllocSummaryInfoList->ForwardLink;
  796. AllocSummaryLink != AllocSummaryInfoList;
  797. AllocSummaryLink = AllocSummaryLink->ForwardLink) {
  798. AllocSummaryInfoData = CR (
  799. AllocSummaryLink,
  800. MEMORY_PROFILE_ALLOC_SUMMARY_INFO_DATA,
  801. Link,
  802. MEMORY_PROFILE_ALLOC_SUMMARY_INFO_SIGNATURE
  803. );
  804. AllocSummaryInfo = &AllocSummaryInfoData->AllocSummaryInfo;
  805. Print(L"0x%08x 0x%016lx <== 0x%016lx",
  806. AllocSummaryInfo->AllocateCount,
  807. AllocSummaryInfo->TotalSize,
  808. AllocSummaryInfo->CallerAddress - DriverInfo->ImageBase
  809. );
  810. Print (L" (%a)\n", ProfileActionToStr (AllocSummaryInfo->Action, AllocSummaryInfo->ActionString, IsForSmm));
  811. }
  812. }
  813. return ;
  814. }
  815. /**
  816. Destroy Context summary information.
  817. @param[in, out] ContextSummaryData Context summary information data.
  818. **/
  819. VOID
  820. DestroyContextSummaryData (
  821. IN OUT MEMORY_PROFILE_CONTEXT_SUMMARY_DATA *ContextSummaryData
  822. )
  823. {
  824. MEMORY_PROFILE_DRIVER_SUMMARY_INFO_DATA *DriverSummaryInfoData;
  825. MEMORY_PROFILE_ALLOC_SUMMARY_INFO_DATA *AllocSummaryInfoData;
  826. LIST_ENTRY *DriverSummaryInfoList;
  827. LIST_ENTRY *DriverSummaryLink;
  828. LIST_ENTRY *AllocSummaryInfoList;
  829. LIST_ENTRY *AllocSummaryLink;
  830. if (ContextSummaryData == NULL) {
  831. return ;
  832. }
  833. DriverSummaryInfoList = ContextSummaryData->DriverSummaryInfoList;
  834. for (DriverSummaryLink = DriverSummaryInfoList->ForwardLink;
  835. DriverSummaryLink != DriverSummaryInfoList;
  836. ) {
  837. DriverSummaryInfoData = CR (
  838. DriverSummaryLink,
  839. MEMORY_PROFILE_DRIVER_SUMMARY_INFO_DATA,
  840. Link,
  841. MEMORY_PROFILE_DRIVER_INFO_SIGNATURE
  842. );
  843. DriverSummaryLink = DriverSummaryLink->ForwardLink;
  844. AllocSummaryInfoList = DriverSummaryInfoData->AllocSummaryInfoList;
  845. for (AllocSummaryLink = AllocSummaryInfoList->ForwardLink;
  846. AllocSummaryLink != AllocSummaryInfoList;
  847. ) {
  848. AllocSummaryInfoData = CR (
  849. AllocSummaryLink,
  850. MEMORY_PROFILE_ALLOC_SUMMARY_INFO_DATA,
  851. Link,
  852. MEMORY_PROFILE_ALLOC_SUMMARY_INFO_SIGNATURE
  853. );
  854. AllocSummaryLink = AllocSummaryLink->ForwardLink;
  855. RemoveEntryList (&AllocSummaryInfoData->Link);
  856. FreePool (AllocSummaryInfoData);
  857. }
  858. RemoveEntryList (&DriverSummaryInfoData->Link);
  859. FreePool (DriverSummaryInfoData);
  860. }
  861. return ;
  862. }
  863. /**
  864. Get and dump UEFI memory profile data.
  865. @return EFI_SUCCESS Get the memory profile data successfully.
  866. @return other Fail to get the memory profile data.
  867. **/
  868. EFI_STATUS
  869. GetUefiMemoryProfileData (
  870. VOID
  871. )
  872. {
  873. EFI_STATUS Status;
  874. EDKII_MEMORY_PROFILE_PROTOCOL *ProfileProtocol;
  875. VOID *Data;
  876. UINT64 Size;
  877. MEMORY_PROFILE_CONTEXT_SUMMARY_DATA *MemoryProfileContextSummaryData;
  878. BOOLEAN RecordingState;
  879. Status = gBS->LocateProtocol (&gEdkiiMemoryProfileGuid, NULL, (VOID **) &ProfileProtocol);
  880. if (EFI_ERROR (Status)) {
  881. DEBUG ((EFI_D_ERROR, "UefiMemoryProfile: Locate MemoryProfile protocol - %r\n", Status));
  882. return Status;
  883. }
  884. //
  885. // Set recording state if needed.
  886. //
  887. RecordingState = MEMORY_PROFILE_RECORDING_DISABLE;
  888. Status = ProfileProtocol->GetRecordingState (ProfileProtocol, &RecordingState);
  889. if (RecordingState == MEMORY_PROFILE_RECORDING_ENABLE) {
  890. ProfileProtocol->SetRecordingState (ProfileProtocol, MEMORY_PROFILE_RECORDING_DISABLE);
  891. }
  892. Size = 0;
  893. Data = NULL;
  894. Status = ProfileProtocol->GetData (
  895. ProfileProtocol,
  896. &Size,
  897. Data
  898. );
  899. if (Status != EFI_BUFFER_TOO_SMALL) {
  900. Print (L"UefiMemoryProfile: GetData - %r\n", Status);
  901. goto Done;
  902. }
  903. Data = AllocateZeroPool ((UINTN) Size);
  904. if (Data == NULL) {
  905. Status = EFI_OUT_OF_RESOURCES;
  906. Print (L"UefiMemoryProfile: AllocateZeroPool (0x%x) - %r\n", Size, Status);
  907. return Status;
  908. }
  909. Status = ProfileProtocol->GetData (
  910. ProfileProtocol,
  911. &Size,
  912. Data
  913. );
  914. if (EFI_ERROR (Status)) {
  915. Print (L"UefiMemoryProfile: GetData - %r\n", Status);
  916. goto Done;
  917. }
  918. Print (L"UefiMemoryProfileSize - 0x%x\n", Size);
  919. Print (L"======= UefiMemoryProfile begin =======\n");
  920. DumpMemoryProfile ((PHYSICAL_ADDRESS) (UINTN) Data, Size, FALSE);
  921. //
  922. // Dump summary information
  923. //
  924. MemoryProfileContextSummaryData = CreateContextSummaryData ((PHYSICAL_ADDRESS) (UINTN) Data, Size);
  925. if (MemoryProfileContextSummaryData != NULL) {
  926. DumpContextSummaryData (MemoryProfileContextSummaryData, FALSE);
  927. DestroyContextSummaryData (MemoryProfileContextSummaryData);
  928. }
  929. Print (L"======= UefiMemoryProfile end =======\n\n\n");
  930. Done:
  931. if (Data != NULL) {
  932. FreePool (Data);
  933. }
  934. //
  935. // Restore recording state if needed.
  936. //
  937. if (RecordingState == MEMORY_PROFILE_RECORDING_ENABLE) {
  938. ProfileProtocol->SetRecordingState (ProfileProtocol, MEMORY_PROFILE_RECORDING_ENABLE);
  939. }
  940. return Status;
  941. }
  942. /**
  943. Get and dump SMRAM profile data.
  944. @return EFI_SUCCESS Get the SMRAM profile data successfully.
  945. @return other Fail to get the SMRAM profile data.
  946. **/
  947. EFI_STATUS
  948. GetSmramProfileData (
  949. VOID
  950. )
  951. {
  952. EFI_STATUS Status;
  953. UINTN CommSize;
  954. UINT8 *CommBuffer;
  955. EFI_SMM_COMMUNICATE_HEADER *CommHeader;
  956. SMRAM_PROFILE_PARAMETER_GET_PROFILE_INFO *CommGetProfileInfo;
  957. SMRAM_PROFILE_PARAMETER_GET_PROFILE_DATA_BY_OFFSET *CommGetProfileData;
  958. SMRAM_PROFILE_PARAMETER_RECORDING_STATE *CommRecordingState;
  959. UINTN ProfileSize;
  960. VOID *ProfileBuffer;
  961. EFI_SMM_COMMUNICATION_PROTOCOL *SmmCommunication;
  962. UINTN MinimalSizeNeeded;
  963. EDKII_PI_SMM_COMMUNICATION_REGION_TABLE *PiSmmCommunicationRegionTable;
  964. UINT32 Index;
  965. EFI_MEMORY_DESCRIPTOR *Entry;
  966. VOID *Buffer;
  967. UINTN Size;
  968. UINTN Offset;
  969. MEMORY_PROFILE_CONTEXT_SUMMARY_DATA *MemoryProfileContextSummaryData;
  970. BOOLEAN RecordingState;
  971. ProfileBuffer = NULL;
  972. Status = gBS->LocateProtocol (&gEfiSmmCommunicationProtocolGuid, NULL, (VOID **) &SmmCommunication);
  973. if (EFI_ERROR (Status)) {
  974. DEBUG ((EFI_D_ERROR, "SmramProfile: Locate SmmCommunication protocol - %r\n", Status));
  975. return Status;
  976. }
  977. MinimalSizeNeeded = sizeof (EFI_GUID) +
  978. sizeof (UINTN) +
  979. MAX (sizeof (SMRAM_PROFILE_PARAMETER_GET_PROFILE_INFO),
  980. MAX (sizeof (SMRAM_PROFILE_PARAMETER_GET_PROFILE_DATA_BY_OFFSET),
  981. sizeof (SMRAM_PROFILE_PARAMETER_RECORDING_STATE)));
  982. MinimalSizeNeeded += MAX (sizeof (MEMORY_PROFILE_CONTEXT),
  983. MAX (sizeof (MEMORY_PROFILE_DRIVER_INFO),
  984. MAX (sizeof (MEMORY_PROFILE_ALLOC_INFO),
  985. MAX (sizeof (MEMORY_PROFILE_DESCRIPTOR),
  986. MAX (sizeof (MEMORY_PROFILE_FREE_MEMORY),
  987. sizeof (MEMORY_PROFILE_MEMORY_RANGE))))));
  988. Status = EfiGetSystemConfigurationTable (
  989. &gEdkiiPiSmmCommunicationRegionTableGuid,
  990. (VOID **) &PiSmmCommunicationRegionTable
  991. );
  992. if (EFI_ERROR (Status)) {
  993. DEBUG ((EFI_D_ERROR, "SmramProfile: Get PiSmmCommunicationRegionTable - %r\n", Status));
  994. return Status;
  995. }
  996. ASSERT (PiSmmCommunicationRegionTable != NULL);
  997. Entry = (EFI_MEMORY_DESCRIPTOR *) (PiSmmCommunicationRegionTable + 1);
  998. Size = 0;
  999. for (Index = 0; Index < PiSmmCommunicationRegionTable->NumberOfEntries; Index++) {
  1000. if (Entry->Type == EfiConventionalMemory) {
  1001. Size = EFI_PAGES_TO_SIZE ((UINTN) Entry->NumberOfPages);
  1002. if (Size >= MinimalSizeNeeded) {
  1003. break;
  1004. }
  1005. }
  1006. Entry = (EFI_MEMORY_DESCRIPTOR *) ((UINT8 *) Entry + PiSmmCommunicationRegionTable->DescriptorSize);
  1007. }
  1008. ASSERT (Index < PiSmmCommunicationRegionTable->NumberOfEntries);
  1009. CommBuffer = (UINT8 *) (UINTN) Entry->PhysicalStart;
  1010. //
  1011. // Set recording state if needed.
  1012. //
  1013. RecordingState = MEMORY_PROFILE_RECORDING_DISABLE;
  1014. CommHeader = (EFI_SMM_COMMUNICATE_HEADER *) &CommBuffer[0];
  1015. CopyMem (&CommHeader->HeaderGuid, &gEdkiiMemoryProfileGuid, sizeof (gEdkiiMemoryProfileGuid));
  1016. CommHeader->MessageLength = sizeof (SMRAM_PROFILE_PARAMETER_RECORDING_STATE);
  1017. CommRecordingState = (SMRAM_PROFILE_PARAMETER_RECORDING_STATE *) &CommBuffer[OFFSET_OF (EFI_SMM_COMMUNICATE_HEADER, Data)];
  1018. CommRecordingState->Header.Command = SMRAM_PROFILE_COMMAND_GET_RECORDING_STATE;
  1019. CommRecordingState->Header.DataLength = sizeof (*CommRecordingState);
  1020. CommRecordingState->Header.ReturnStatus = (UINT64)-1;
  1021. CommRecordingState->RecordingState = MEMORY_PROFILE_RECORDING_DISABLE;
  1022. CommSize = sizeof (EFI_GUID) + sizeof (UINTN) + CommHeader->MessageLength;
  1023. Status = SmmCommunication->Communicate (SmmCommunication, CommBuffer, &CommSize);
  1024. if (EFI_ERROR (Status)) {
  1025. DEBUG ((EFI_D_ERROR, "SmramProfile: SmmCommunication - %r\n", Status));
  1026. return Status;
  1027. }
  1028. if (CommRecordingState->Header.ReturnStatus != 0) {
  1029. Print (L"SmramProfile: GetRecordingState - 0x%0x\n", CommRecordingState->Header.ReturnStatus);
  1030. return EFI_SUCCESS;
  1031. }
  1032. RecordingState = CommRecordingState->RecordingState;
  1033. if (RecordingState == MEMORY_PROFILE_RECORDING_ENABLE) {
  1034. CommHeader = (EFI_SMM_COMMUNICATE_HEADER *) &CommBuffer[0];
  1035. CopyMem (&CommHeader->HeaderGuid, &gEdkiiMemoryProfileGuid, sizeof (gEdkiiMemoryProfileGuid));
  1036. CommHeader->MessageLength = sizeof (SMRAM_PROFILE_PARAMETER_RECORDING_STATE);
  1037. CommRecordingState = (SMRAM_PROFILE_PARAMETER_RECORDING_STATE *) &CommBuffer[OFFSET_OF (EFI_SMM_COMMUNICATE_HEADER, Data)];
  1038. CommRecordingState->Header.Command = SMRAM_PROFILE_COMMAND_SET_RECORDING_STATE;
  1039. CommRecordingState->Header.DataLength = sizeof (*CommRecordingState);
  1040. CommRecordingState->Header.ReturnStatus = (UINT64)-1;
  1041. CommRecordingState->RecordingState = MEMORY_PROFILE_RECORDING_DISABLE;
  1042. CommSize = sizeof (EFI_GUID) + sizeof (UINTN) + CommHeader->MessageLength;
  1043. SmmCommunication->Communicate (SmmCommunication, CommBuffer, &CommSize);
  1044. }
  1045. //
  1046. // Get Size
  1047. //
  1048. CommHeader = (EFI_SMM_COMMUNICATE_HEADER *) &CommBuffer[0];
  1049. CopyMem (&CommHeader->HeaderGuid, &gEdkiiMemoryProfileGuid, sizeof (gEdkiiMemoryProfileGuid));
  1050. CommHeader->MessageLength = sizeof (SMRAM_PROFILE_PARAMETER_GET_PROFILE_INFO);
  1051. CommGetProfileInfo = (SMRAM_PROFILE_PARAMETER_GET_PROFILE_INFO *) &CommBuffer[OFFSET_OF (EFI_SMM_COMMUNICATE_HEADER, Data)];
  1052. CommGetProfileInfo->Header.Command = SMRAM_PROFILE_COMMAND_GET_PROFILE_INFO;
  1053. CommGetProfileInfo->Header.DataLength = sizeof (*CommGetProfileInfo);
  1054. CommGetProfileInfo->Header.ReturnStatus = (UINT64)-1;
  1055. CommGetProfileInfo->ProfileSize = 0;
  1056. CommSize = sizeof (EFI_GUID) + sizeof (UINTN) + CommHeader->MessageLength;
  1057. Status = SmmCommunication->Communicate (SmmCommunication, CommBuffer, &CommSize);
  1058. ASSERT_EFI_ERROR (Status);
  1059. if (CommGetProfileInfo->Header.ReturnStatus != 0) {
  1060. Status = EFI_SUCCESS;
  1061. Print (L"SmramProfile: GetProfileInfo - 0x%0x\n", CommGetProfileInfo->Header.ReturnStatus);
  1062. goto Done;
  1063. }
  1064. ProfileSize = (UINTN) CommGetProfileInfo->ProfileSize;
  1065. //
  1066. // Get Data
  1067. //
  1068. ProfileBuffer = AllocateZeroPool (ProfileSize);
  1069. if (ProfileBuffer == NULL) {
  1070. Status = EFI_OUT_OF_RESOURCES;
  1071. Print (L"SmramProfile: AllocateZeroPool (0x%x) for profile buffer - %r\n", ProfileSize, Status);
  1072. goto Done;
  1073. }
  1074. CommHeader = (EFI_SMM_COMMUNICATE_HEADER *) &CommBuffer[0];
  1075. CopyMem (&CommHeader->HeaderGuid, &gEdkiiMemoryProfileGuid, sizeof(gEdkiiMemoryProfileGuid));
  1076. CommHeader->MessageLength = sizeof (SMRAM_PROFILE_PARAMETER_GET_PROFILE_DATA_BY_OFFSET);
  1077. CommGetProfileData = (SMRAM_PROFILE_PARAMETER_GET_PROFILE_DATA_BY_OFFSET *) &CommBuffer[OFFSET_OF (EFI_SMM_COMMUNICATE_HEADER, Data)];
  1078. CommGetProfileData->Header.Command = SMRAM_PROFILE_COMMAND_GET_PROFILE_DATA_BY_OFFSET;
  1079. CommGetProfileData->Header.DataLength = sizeof (*CommGetProfileData);
  1080. CommGetProfileData->Header.ReturnStatus = (UINT64)-1;
  1081. CommSize = sizeof (EFI_GUID) + sizeof (UINTN) + CommHeader->MessageLength;
  1082. Buffer = (UINT8 *) CommHeader + CommSize;
  1083. Size -= CommSize;
  1084. CommGetProfileData->ProfileBuffer = (PHYSICAL_ADDRESS) (UINTN) Buffer;
  1085. CommGetProfileData->ProfileOffset = 0;
  1086. while (CommGetProfileData->ProfileOffset < ProfileSize) {
  1087. Offset = (UINTN) CommGetProfileData->ProfileOffset;
  1088. if (Size <= (ProfileSize - CommGetProfileData->ProfileOffset)) {
  1089. CommGetProfileData->ProfileSize = (UINT64) Size;
  1090. } else {
  1091. CommGetProfileData->ProfileSize = (UINT64) (ProfileSize - CommGetProfileData->ProfileOffset);
  1092. }
  1093. Status = SmmCommunication->Communicate (SmmCommunication, CommBuffer, &CommSize);
  1094. ASSERT_EFI_ERROR (Status);
  1095. if (CommGetProfileData->Header.ReturnStatus != 0) {
  1096. Status = EFI_SUCCESS;
  1097. Print (L"GetProfileData - 0x%x\n", CommGetProfileData->Header.ReturnStatus);
  1098. goto Done;
  1099. }
  1100. CopyMem ((UINT8 *) ProfileBuffer + Offset, (VOID *) (UINTN) CommGetProfileData->ProfileBuffer, (UINTN) CommGetProfileData->ProfileSize);
  1101. }
  1102. Print (L"SmramProfileSize - 0x%x\n", ProfileSize);
  1103. Print (L"======= SmramProfile begin =======\n");
  1104. DumpMemoryProfile ((PHYSICAL_ADDRESS) (UINTN) ProfileBuffer, ProfileSize, TRUE);
  1105. //
  1106. // Dump summary information
  1107. //
  1108. MemoryProfileContextSummaryData = CreateContextSummaryData ((PHYSICAL_ADDRESS) (UINTN) ProfileBuffer, ProfileSize);
  1109. if (MemoryProfileContextSummaryData != NULL) {
  1110. DumpContextSummaryData (MemoryProfileContextSummaryData, TRUE);
  1111. DestroyContextSummaryData (MemoryProfileContextSummaryData);
  1112. }
  1113. Print (L"======= SmramProfile end =======\n\n\n");
  1114. Done:
  1115. if (ProfileBuffer != NULL) {
  1116. FreePool (ProfileBuffer);
  1117. }
  1118. //
  1119. // Restore recording state if needed.
  1120. //
  1121. if (RecordingState == MEMORY_PROFILE_RECORDING_ENABLE) {
  1122. CommHeader = (EFI_SMM_COMMUNICATE_HEADER *) &CommBuffer[0];
  1123. CopyMem (&CommHeader->HeaderGuid, &gEdkiiMemoryProfileGuid, sizeof (gEdkiiMemoryProfileGuid));
  1124. CommHeader->MessageLength = sizeof (SMRAM_PROFILE_PARAMETER_RECORDING_STATE);
  1125. CommRecordingState = (SMRAM_PROFILE_PARAMETER_RECORDING_STATE *) &CommBuffer[OFFSET_OF (EFI_SMM_COMMUNICATE_HEADER, Data)];
  1126. CommRecordingState->Header.Command = SMRAM_PROFILE_COMMAND_SET_RECORDING_STATE;
  1127. CommRecordingState->Header.DataLength = sizeof (*CommRecordingState);
  1128. CommRecordingState->Header.ReturnStatus = (UINT64)-1;
  1129. CommRecordingState->RecordingState = MEMORY_PROFILE_RECORDING_ENABLE;
  1130. CommSize = sizeof (EFI_GUID) + sizeof (UINTN) + CommHeader->MessageLength;
  1131. SmmCommunication->Communicate (SmmCommunication, CommBuffer, &CommSize);
  1132. }
  1133. return Status;
  1134. }
  1135. /**
  1136. The user Entry Point for Application. The user code starts with this function
  1137. as the real entry point for the image goes into a library that calls this function.
  1138. @param[in] ImageHandle The firmware allocated handle for the EFI image.
  1139. @param[in] SystemTable A pointer to the EFI System Table.
  1140. @retval EFI_SUCCESS The entry point is executed successfully.
  1141. @retval other Some error occurs when executing this entry point.
  1142. **/
  1143. EFI_STATUS
  1144. EFIAPI
  1145. UefiMain (
  1146. IN EFI_HANDLE ImageHandle,
  1147. IN EFI_SYSTEM_TABLE *SystemTable
  1148. )
  1149. {
  1150. EFI_STATUS Status;
  1151. Status = GetUefiMemoryProfileData ();
  1152. if (EFI_ERROR (Status)) {
  1153. DEBUG ((EFI_D_ERROR, "GetUefiMemoryProfileData - %r\n", Status));
  1154. }
  1155. Status = GetSmramProfileData ();
  1156. if (EFI_ERROR (Status)) {
  1157. DEBUG ((EFI_D_ERROR, "GetSmramProfileData - %r\n", Status));
  1158. }
  1159. return EFI_SUCCESS;
  1160. }