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