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