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