1 /** @file
2 
3   Copyright (c) 2014 - 2015, 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/PeCoffGetEntryPointLib.h>
26 #include <Library/PrintLib.h>
27 
28 #include <Protocol/SmmCommunication.h>
29 #include <Protocol/SmmAccess2.h>
30 
31 #include <Guid/ZeroGuid.h>
32 #include <Guid/MemoryProfile.h>
33 
34 CHAR16 *mActionString[] = {
35   L"Unknown",
36   L"AllocatePages",
37   L"FreePages",
38   L"AllocatePool",
39   L"FreePool",
40 };
41 
42 CHAR16 *mMemoryTypeString[] = {
43   L"EfiReservedMemoryType",
44   L"EfiLoaderCode",
45   L"EfiLoaderData",
46   L"EfiBootServicesCode",
47   L"EfiBootServicesData",
48   L"EfiRuntimeServicesCode",
49   L"EfiRuntimeServicesData",
50   L"EfiConventionalMemory",
51   L"EfiUnusableMemory",
52   L"EfiACPIReclaimMemory",
53   L"EfiACPIMemoryNVS",
54   L"EfiMemoryMappedIO",
55   L"EfiMemoryMappedIOPortSpace",
56   L"EfiPalCode",
57   L"EfiPersistentMemory",
58   L"EfiOSReserved",
59 };
60 
61 CHAR16 *mSubsystemString[] = {
62   L"Unknown",
63   L"NATIVE",
64   L"WINDOWS_GUI",
65   L"WINDOWS_CUI",
66   L"Unknown",
67   L"Unknown",
68   L"Unknown",
69   L"POSIX_CUI",
70   L"Unknown",
71   L"WINDOWS_CE_GUI",
72   L"EFI_APPLICATION",
73   L"EFI_BOOT_SERVICE_DRIVER",
74   L"EFI_RUNTIME_DRIVER",
75   L"EFI_ROM",
76   L"XBOX",
77   L"Unknown",
78 };
79 
80 CHAR16 *mFileTypeString[] = {
81   L"Unknown",
82   L"RAW",
83   L"FREEFORM",
84   L"SECURITY_CORE",
85   L"PEI_CORE",
86   L"DXE_CORE",
87   L"PEIM",
88   L"DRIVER",
89   L"COMBINED_PEIM_DRIVER",
90   L"APPLICATION",
91   L"SMM",
92   L"FIRMWARE_VOLUME_IMAGE",
93   L"COMBINED_SMM_DXE",
94   L"SMM_CORE",
95 };
96 
97 #define PROFILE_NAME_STRING_LENGTH  36
98 CHAR16 mNameString[PROFILE_NAME_STRING_LENGTH + 1];
99 
100 /**
101   Get the file name portion of the Pdb File Name.
102 
103   The portion of the Pdb File Name between the last backslash and
104   either a following period or the end of the string is converted
105   to Unicode and copied into UnicodeBuffer.  The name is truncated,
106   if necessary, to ensure that UnicodeBuffer is not overrun.
107 
108   @param[in]  PdbFileName     Pdb file name.
109   @param[out] UnicodeBuffer   The resultant Unicode File Name.
110 
111 **/
112 VOID
GetShortPdbFileName(IN CHAR8 * PdbFileName,OUT CHAR16 * UnicodeBuffer)113 GetShortPdbFileName (
114   IN  CHAR8     *PdbFileName,
115   OUT CHAR16    *UnicodeBuffer
116   )
117 {
118   UINTN IndexA;     // Current work location within an ASCII string.
119   UINTN IndexU;     // Current work location within a Unicode string.
120   UINTN StartIndex;
121   UINTN EndIndex;
122 
123   ZeroMem (UnicodeBuffer, PROFILE_NAME_STRING_LENGTH * sizeof (CHAR16));
124 
125   if (PdbFileName == NULL) {
126     StrnCpy (UnicodeBuffer, L" ", 1);
127   } else {
128     StartIndex = 0;
129     for (EndIndex = 0; PdbFileName[EndIndex] != 0; EndIndex++);
130     for (IndexA = 0; PdbFileName[IndexA] != 0; IndexA++) {
131       if (PdbFileName[IndexA] == '\\') {
132         StartIndex = IndexA + 1;
133       }
134 
135       if (PdbFileName[IndexA] == '.') {
136         EndIndex = IndexA;
137       }
138     }
139 
140     IndexU = 0;
141     for (IndexA = StartIndex; IndexA < EndIndex; IndexA++) {
142       UnicodeBuffer[IndexU] = (CHAR16) PdbFileName[IndexA];
143       IndexU++;
144       if (IndexU >= PROFILE_NAME_STRING_LENGTH) {
145         UnicodeBuffer[PROFILE_NAME_STRING_LENGTH] = 0;
146         break;
147       }
148     }
149   }
150 }
151 
152 /**
153   Get a human readable name for an image.
154   The following methods will be tried orderly:
155     1. Image PDB
156     2. FFS UI section
157     3. Image GUID
158 
159   @param[in] DriverInfo Pointer to memory profile driver info.
160 
161   @post The resulting Unicode name string is stored in the mNameString global array.
162 
163 **/
164 VOID
GetDriverNameString(IN MEMORY_PROFILE_DRIVER_INFO * DriverInfo)165 GetDriverNameString (
166  IN MEMORY_PROFILE_DRIVER_INFO  *DriverInfo
167  )
168 {
169   EFI_STATUS                  Status;
170   CHAR8                       *PdbFileName;
171   CHAR16                      *NameString;
172   UINTN                       StringSize;
173 
174   //
175   // Method 1: Get the name string from image PDB
176   //
177   if ((DriverInfo->ImageBase != 0) && (DriverInfo->FileType != EFI_FV_FILETYPE_SMM) && (DriverInfo->FileType != EFI_FV_FILETYPE_SMM_CORE)) {
178     PdbFileName = PeCoffLoaderGetPdbPointer ((VOID *) (UINTN) DriverInfo->ImageBase);
179 
180     if (PdbFileName != NULL) {
181       GetShortPdbFileName (PdbFileName, mNameString);
182       return;
183     }
184   }
185 
186   if (!CompareGuid (&DriverInfo->FileName, &gZeroGuid)) {
187     //
188     // Try to get the image's FFS UI section by image GUID
189     //
190     NameString = NULL;
191     StringSize = 0;
192     Status = GetSectionFromAnyFv (
193               &DriverInfo->FileName,
194               EFI_SECTION_USER_INTERFACE,
195               0,
196               (VOID **) &NameString,
197               &StringSize
198               );
199     if (!EFI_ERROR (Status)) {
200       //
201       // Method 2: Get the name string from FFS UI section
202       //
203       StrnCpy (mNameString, NameString, PROFILE_NAME_STRING_LENGTH);
204       mNameString[PROFILE_NAME_STRING_LENGTH] = 0;
205       FreePool (NameString);
206       return;
207     }
208   }
209 
210   //
211   // Method 3: Get the name string from image GUID
212   //
213   UnicodeSPrint (mNameString, sizeof (mNameString), L"%g", &DriverInfo->FileName);
214 }
215 
216 /**
217   Dump memory profile allocate information.
218 
219   @param[in] DriverInfo         Pointer to memory profile driver info.
220   @param[in] AllocIndex         Memory profile alloc info index.
221   @param[in] AllocInfo          Pointer to memory profile alloc info.
222 
223   @return Pointer to next memory profile alloc info.
224 
225 **/
226 MEMORY_PROFILE_ALLOC_INFO *
DumpMemoryProfileAllocInfo(IN MEMORY_PROFILE_DRIVER_INFO * DriverInfo,IN UINTN AllocIndex,IN MEMORY_PROFILE_ALLOC_INFO * AllocInfo)227 DumpMemoryProfileAllocInfo (
228   IN MEMORY_PROFILE_DRIVER_INFO *DriverInfo,
229   IN UINTN                      AllocIndex,
230   IN MEMORY_PROFILE_ALLOC_INFO  *AllocInfo
231   )
232 {
233   if (AllocInfo->Header.Signature != MEMORY_PROFILE_ALLOC_INFO_SIGNATURE) {
234     return NULL;
235   }
236   Print (L"    MEMORY_PROFILE_ALLOC_INFO (0x%x)\n", AllocIndex);
237   Print (L"      Signature     - 0x%08x\n", AllocInfo->Header.Signature);
238   Print (L"      Length        - 0x%04x\n", AllocInfo->Header.Length);
239   Print (L"      Revision      - 0x%04x\n", AllocInfo->Header.Revision);
240   Print (L"      CallerAddress - 0x%016lx (Offset: 0x%08x)\n", AllocInfo->CallerAddress, (UINTN) (AllocInfo->CallerAddress - DriverInfo->ImageBase));
241   Print (L"      SequenceId    - 0x%08x\n", AllocInfo->SequenceId);
242   Print (L"      Action        - 0x%08x (%s)\n", AllocInfo->Action, mActionString[(AllocInfo->Action < sizeof(mActionString)/sizeof(mActionString[0])) ? AllocInfo->Action : 0]);
243   Print (L"      MemoryType    - 0x%08x (%s)\n", AllocInfo->MemoryType, mMemoryTypeString[(AllocInfo->MemoryType < sizeof(mMemoryTypeString)/sizeof(mMemoryTypeString[0])) ? AllocInfo->MemoryType : (sizeof(mMemoryTypeString)/sizeof(mMemoryTypeString[0]) - 1)]);
244   Print (L"      Buffer        - 0x%016lx\n", AllocInfo->Buffer);
245   Print (L"      Size          - 0x%016lx\n", AllocInfo->Size);
246 
247   return (MEMORY_PROFILE_ALLOC_INFO *) ((UINTN) AllocInfo + AllocInfo->Header.Length);
248 }
249 
250 /**
251   Dump memory profile driver information.
252 
253   @param[in] DriverIndex        Memory profile driver info index.
254   @param[in] DriverInfo         Pointer to memory profile driver info.
255 
256   @return Pointer to next memory profile driver info.
257 
258 **/
259 MEMORY_PROFILE_DRIVER_INFO *
DumpMemoryProfileDriverInfo(IN UINTN DriverIndex,IN MEMORY_PROFILE_DRIVER_INFO * DriverInfo)260 DumpMemoryProfileDriverInfo (
261   IN UINTN                      DriverIndex,
262   IN MEMORY_PROFILE_DRIVER_INFO *DriverInfo
263   )
264 {
265   UINTN                         TypeIndex;
266   MEMORY_PROFILE_ALLOC_INFO     *AllocInfo;
267   UINTN                         AllocIndex;
268 
269   if (DriverInfo->Header.Signature != MEMORY_PROFILE_DRIVER_INFO_SIGNATURE) {
270     return NULL;
271   }
272   Print (L"  MEMORY_PROFILE_DRIVER_INFO (0x%x)\n", DriverIndex);
273   Print (L"    Signature               - 0x%08x\n", DriverInfo->Header.Signature);
274   Print (L"    Length                  - 0x%04x\n", DriverInfo->Header.Length);
275   Print (L"    Revision                - 0x%04x\n", DriverInfo->Header.Revision);
276   GetDriverNameString (DriverInfo);
277   Print (L"    FileName                - %s\n", &mNameString);
278   Print (L"    ImageBase               - 0x%016lx\n", DriverInfo->ImageBase);
279   Print (L"    ImageSize               - 0x%016lx\n", DriverInfo->ImageSize);
280   Print (L"    EntryPoint              - 0x%016lx\n", DriverInfo->EntryPoint);
281   Print (L"    ImageSubsystem          - 0x%04x (%s)\n", DriverInfo->ImageSubsystem, mSubsystemString[(DriverInfo->ImageSubsystem < sizeof(mSubsystemString)/sizeof(mSubsystemString[0])) ? DriverInfo->ImageSubsystem : 0]);
282   Print (L"    FileType                - 0x%02x (%s)\n", DriverInfo->FileType, mFileTypeString[(DriverInfo->FileType < sizeof(mFileTypeString)/sizeof(mFileTypeString[0])) ? DriverInfo->FileType : 0]);
283   Print (L"    CurrentUsage            - 0x%016lx\n", DriverInfo->CurrentUsage);
284   Print (L"    PeakUsage               - 0x%016lx\n", DriverInfo->PeakUsage);
285   for (TypeIndex = 0; TypeIndex <= EfiMaxMemoryType; TypeIndex++) {
286     if ((DriverInfo->CurrentUsageByType[TypeIndex] != 0) ||
287         (DriverInfo->PeakUsageByType[TypeIndex] != 0)) {
288       Print (L"    CurrentUsage[0x%02x]      - 0x%016lx (%s)\n", TypeIndex, DriverInfo->CurrentUsageByType[TypeIndex], mMemoryTypeString[TypeIndex]);
289       Print (L"    PeakUsage[0x%02x]         - 0x%016lx (%s)\n", TypeIndex, DriverInfo->PeakUsageByType[TypeIndex], mMemoryTypeString[TypeIndex]);
290     }
291   }
292   Print (L"    AllocRecordCount        - 0x%08x\n", DriverInfo->AllocRecordCount);
293 
294   AllocInfo = (MEMORY_PROFILE_ALLOC_INFO *) ((UINTN) DriverInfo + DriverInfo->Header.Length);
295   for (AllocIndex = 0; AllocIndex < DriverInfo->AllocRecordCount; AllocIndex++) {
296     AllocInfo = DumpMemoryProfileAllocInfo (DriverInfo, AllocIndex, AllocInfo);
297     if (AllocInfo == NULL) {
298       return NULL;
299     }
300   }
301   return (MEMORY_PROFILE_DRIVER_INFO *) AllocInfo;
302 }
303 
304 /**
305   Dump memory profile context information.
306 
307   @param[in] Context            Pointer to memory profile context.
308 
309   @return Pointer to the end of memory profile context buffer.
310 
311 **/
312 VOID *
DumpMemoryProfileContext(IN MEMORY_PROFILE_CONTEXT * Context)313 DumpMemoryProfileContext (
314   IN MEMORY_PROFILE_CONTEXT     *Context
315   )
316 {
317   UINTN                         TypeIndex;
318   MEMORY_PROFILE_DRIVER_INFO    *DriverInfo;
319   UINTN                         DriverIndex;
320 
321   if (Context->Header.Signature != MEMORY_PROFILE_CONTEXT_SIGNATURE) {
322     return NULL;
323   }
324   Print (L"MEMORY_PROFILE_CONTEXT\n");
325   Print (L"  Signature                     - 0x%08x\n", Context->Header.Signature);
326   Print (L"  Length                        - 0x%04x\n", Context->Header.Length);
327   Print (L"  Revision                      - 0x%04x\n", Context->Header.Revision);
328   Print (L"  CurrentTotalUsage             - 0x%016lx\n", Context->CurrentTotalUsage);
329   Print (L"  PeakTotalUsage                - 0x%016lx\n", Context->PeakTotalUsage);
330   for (TypeIndex = 0; TypeIndex <= EfiMaxMemoryType; TypeIndex++) {
331     if ((Context->CurrentTotalUsageByType[TypeIndex] != 0) ||
332         (Context->PeakTotalUsageByType[TypeIndex] != 0)) {
333       Print (L"  CurrentTotalUsage[0x%02x]       - 0x%016lx (%s)\n", TypeIndex, Context->CurrentTotalUsageByType[TypeIndex], mMemoryTypeString[TypeIndex]);
334       Print (L"  PeakTotalUsage[0x%02x]          - 0x%016lx (%s)\n", TypeIndex, Context->PeakTotalUsageByType[TypeIndex], mMemoryTypeString[TypeIndex]);
335     }
336   }
337   Print (L"  TotalImageSize                - 0x%016lx\n", Context->TotalImageSize);
338   Print (L"  ImageCount                    - 0x%08x\n", Context->ImageCount);
339   Print (L"  SequenceCount                 - 0x%08x\n", Context->SequenceCount);
340 
341   DriverInfo = (MEMORY_PROFILE_DRIVER_INFO *) ((UINTN) Context + Context->Header.Length);
342   for (DriverIndex = 0; DriverIndex < Context->ImageCount; DriverIndex++) {
343     DriverInfo = DumpMemoryProfileDriverInfo (DriverIndex, DriverInfo);
344     if (DriverInfo == NULL) {
345       return NULL;
346     }
347   }
348   return (VOID *) DriverInfo;
349 }
350 
351 /**
352   Dump memory profile descriptor information.
353 
354   @param[in] DescriptorIndex    Memory profile descriptor index.
355   @param[in] Descriptor         Pointer to memory profile descriptor.
356 
357   @return Pointer to next memory profile descriptor.
358 
359 **/
360 MEMORY_PROFILE_DESCRIPTOR *
DumpMemoryProfileDescriptor(IN UINTN DescriptorIndex,IN MEMORY_PROFILE_DESCRIPTOR * Descriptor)361 DumpMemoryProfileDescriptor (
362   IN UINTN                      DescriptorIndex,
363   IN MEMORY_PROFILE_DESCRIPTOR  *Descriptor
364   )
365 {
366   if (Descriptor->Header.Signature != MEMORY_PROFILE_DESCRIPTOR_SIGNATURE) {
367     return NULL;
368   }
369   Print (L"  MEMORY_PROFILE_DESCRIPTOR (0x%x)\n", DescriptorIndex);
370   Print (L"    Signature               - 0x%08x\n", Descriptor->Header.Signature);
371   Print (L"    Length                  - 0x%04x\n", Descriptor->Header.Length);
372   Print (L"    Revision                - 0x%04x\n", Descriptor->Header.Revision);
373   Print (L"    Address                 - 0x%016lx\n", Descriptor->Address);
374   Print (L"    Size                    - 0x%016lx\n", Descriptor->Size);
375 
376   return (MEMORY_PROFILE_DESCRIPTOR *) ((UINTN) Descriptor + Descriptor->Header.Length);
377 }
378 
379 /**
380   Dump memory profile free memory information.
381 
382   @param[in] FreeMemory         Pointer to memory profile free memory.
383 
384   @return Pointer to the end of memory profile free memory buffer.
385 
386 **/
387 VOID *
DumpMemoryProfileFreeMemory(IN MEMORY_PROFILE_FREE_MEMORY * FreeMemory)388 DumpMemoryProfileFreeMemory (
389   IN MEMORY_PROFILE_FREE_MEMORY *FreeMemory
390   )
391 {
392   MEMORY_PROFILE_DESCRIPTOR     *Descriptor;
393   UINTN                         DescriptorIndex;
394 
395   if (FreeMemory->Header.Signature != MEMORY_PROFILE_FREE_MEMORY_SIGNATURE) {
396     return NULL;
397   }
398   Print (L"MEMORY_PROFILE_FREE_MEMORY\n");
399   Print (L"  Signature                     - 0x%08x\n", FreeMemory->Header.Signature);
400   Print (L"  Length                        - 0x%04x\n", FreeMemory->Header.Length);
401   Print (L"  Revision                      - 0x%04x\n", FreeMemory->Header.Revision);
402   Print (L"  TotalFreeMemoryPages          - 0x%016lx\n", FreeMemory->TotalFreeMemoryPages);
403   Print (L"  FreeMemoryEntryCount          - 0x%08x\n", FreeMemory->FreeMemoryEntryCount);
404 
405   Descriptor = (MEMORY_PROFILE_DESCRIPTOR *) ((UINTN) FreeMemory + FreeMemory->Header.Length);
406   for (DescriptorIndex = 0; DescriptorIndex < FreeMemory->FreeMemoryEntryCount; DescriptorIndex++) {
407     Descriptor = DumpMemoryProfileDescriptor (DescriptorIndex, Descriptor);
408     if (Descriptor == NULL) {
409       return NULL;
410     }
411   }
412 
413   return (VOID *) Descriptor;
414 }
415 
416 /**
417   Dump memory profile memory range information.
418 
419   @param[in] MemoryRange        Pointer to memory profile memory range.
420 
421   @return Pointer to the end of memory profile memory range buffer.
422 
423 **/
424 VOID *
DumpMemoryProfileMemoryRange(IN MEMORY_PROFILE_MEMORY_RANGE * MemoryRange)425 DumpMemoryProfileMemoryRange (
426   IN MEMORY_PROFILE_MEMORY_RANGE    *MemoryRange
427   )
428 {
429   MEMORY_PROFILE_DESCRIPTOR     *Descriptor;
430   UINTN                         DescriptorIndex;
431 
432   if (MemoryRange->Header.Signature != MEMORY_PROFILE_MEMORY_RANGE_SIGNATURE) {
433     return NULL;
434   }
435   Print (L"MEMORY_PROFILE_MEMORY_RANGE\n");
436   Print (L"  Signature                     - 0x%08x\n", MemoryRange->Header.Signature);
437   Print (L"  Length                        - 0x%04x\n", MemoryRange->Header.Length);
438   Print (L"  Revision                      - 0x%04x\n", MemoryRange->Header.Revision);
439   Print (L"  MemoryRangeCount              - 0x%08x\n", MemoryRange->MemoryRangeCount);
440 
441   Descriptor = (MEMORY_PROFILE_DESCRIPTOR *) ((UINTN) MemoryRange + MemoryRange->Header.Length);
442   for (DescriptorIndex = 0; DescriptorIndex < MemoryRange->MemoryRangeCount; DescriptorIndex++) {
443     Descriptor = DumpMemoryProfileDescriptor (DescriptorIndex, Descriptor);
444     if (Descriptor == NULL) {
445       return NULL;
446     }
447   }
448 
449   return (VOID *) Descriptor;
450 }
451 
452 /**
453   Scan memory profile by Signature.
454 
455   @param[in] ProfileBuffer      Memory profile base address.
456   @param[in] ProfileSize        Memory profile size.
457   @param[in] Signature          Signature.
458 
459   @return Pointer to the stucture with the signature.
460 
461 **/
462 VOID *
ScanMemoryProfileBySignature(IN PHYSICAL_ADDRESS ProfileBuffer,IN UINT64 ProfileSize,IN UINT32 Signature)463 ScanMemoryProfileBySignature (
464   IN PHYSICAL_ADDRESS           ProfileBuffer,
465   IN UINT64                     ProfileSize,
466   IN UINT32                     Signature
467   )
468 {
469   MEMORY_PROFILE_COMMON_HEADER  *CommonHeader;
470   UINTN                          ProfileEnd;
471 
472   ProfileEnd = (UINTN) (ProfileBuffer + ProfileSize);
473   CommonHeader = (MEMORY_PROFILE_COMMON_HEADER *) (UINTN) ProfileBuffer;
474   while ((UINTN) CommonHeader < ProfileEnd) {
475     if (CommonHeader->Signature == Signature) {
476       //
477       // Found it.
478       //
479       return (VOID *) CommonHeader;
480     }
481     CommonHeader = (MEMORY_PROFILE_COMMON_HEADER *) ((UINTN) CommonHeader + CommonHeader->Length);
482   }
483 
484   return NULL;
485 }
486 
487 /**
488   Dump memory profile information.
489 
490   @param[in] ProfileBuffer      Memory profile base address.
491   @param[in] ProfileSize        Memory profile size.
492 
493 **/
494 VOID
DumpMemoryProfile(IN PHYSICAL_ADDRESS ProfileBuffer,IN UINT64 ProfileSize)495 DumpMemoryProfile (
496   IN PHYSICAL_ADDRESS           ProfileBuffer,
497   IN UINT64                     ProfileSize
498   )
499 {
500   MEMORY_PROFILE_CONTEXT        *Context;
501   MEMORY_PROFILE_FREE_MEMORY    *FreeMemory;
502   MEMORY_PROFILE_MEMORY_RANGE   *MemoryRange;
503 
504   Context = (MEMORY_PROFILE_CONTEXT *) ScanMemoryProfileBySignature (ProfileBuffer, ProfileSize, MEMORY_PROFILE_CONTEXT_SIGNATURE);
505   if (Context != NULL) {
506     DumpMemoryProfileContext (Context);
507   }
508 
509   FreeMemory = (MEMORY_PROFILE_FREE_MEMORY *) ScanMemoryProfileBySignature (ProfileBuffer, ProfileSize, MEMORY_PROFILE_FREE_MEMORY_SIGNATURE);
510   if (FreeMemory != NULL) {
511     DumpMemoryProfileFreeMemory (FreeMemory);
512   }
513 
514   MemoryRange = (MEMORY_PROFILE_MEMORY_RANGE *) ScanMemoryProfileBySignature (ProfileBuffer, ProfileSize, MEMORY_PROFILE_MEMORY_RANGE_SIGNATURE);
515   if (MemoryRange != NULL) {
516     DumpMemoryProfileMemoryRange (MemoryRange);
517   }
518 }
519 
520 /**
521   Get and dump UEFI memory profile data.
522 
523   @return EFI_SUCCESS   Get the memory profile data successfully.
524   @return other         Fail to get the memory profile data.
525 
526 **/
527 EFI_STATUS
GetUefiMemoryProfileData(VOID)528 GetUefiMemoryProfileData (
529   VOID
530   )
531 {
532   EFI_STATUS                    Status;
533   EDKII_MEMORY_PROFILE_PROTOCOL *ProfileProtocol;
534   VOID                          *Data;
535   UINT64                        Size;
536 
537   Status = gBS->LocateProtocol (&gEdkiiMemoryProfileGuid, NULL, (VOID **) &ProfileProtocol);
538   if (EFI_ERROR (Status)) {
539     DEBUG ((EFI_D_ERROR, "UefiMemoryProfile: Locate MemoryProfile protocol - %r\n", Status));
540     return Status;
541   }
542 
543   Size = 0;
544   Data = NULL;
545   Status = ProfileProtocol->GetData (
546                               ProfileProtocol,
547                               &Size,
548                               Data
549                               );
550   if (Status != EFI_BUFFER_TOO_SMALL) {
551     Print (L"UefiMemoryProfile: GetData - %r\n", Status);
552     return Status;
553   }
554 
555   //
556   // Add one sizeof (MEMORY_PROFILE_ALLOC_INFO) to Size for this AllocatePool action.
557   //
558   Size = Size + sizeof (MEMORY_PROFILE_ALLOC_INFO);
559   Data = AllocateZeroPool ((UINTN) Size);
560   if (Data == NULL) {
561     Status = EFI_OUT_OF_RESOURCES;
562     Print (L"UefiMemoryProfile: AllocateZeroPool (0x%x) - %r\n", Size, Status);
563     return Status;
564   }
565 
566   Status = ProfileProtocol->GetData (
567                               ProfileProtocol,
568                               &Size,
569                               Data
570                               );
571   if (EFI_ERROR (Status)) {
572     FreePool (Data);
573     Print (L"UefiMemoryProfile: GetData - %r\n", Status);
574     return Status;
575   }
576 
577 
578   Print (L"UefiMemoryProfileSize - 0x%x\n", Size);
579   Print (L"======= UefiMemoryProfile begin =======\n");
580   DumpMemoryProfile ((PHYSICAL_ADDRESS) (UINTN) Data, Size);
581   Print (L"======= UefiMemoryProfile end =======\n\n\n");
582 
583   FreePool (Data);
584 
585   return EFI_SUCCESS;
586 }
587 
588 /**
589   Get and dump SMRAM profile data.
590 
591   @return EFI_SUCCESS   Get the SMRAM profile data successfully.
592   @return other         Fail to get the SMRAM profile data.
593 
594 **/
595 EFI_STATUS
GetSmramProfileData(VOID)596 GetSmramProfileData (
597   VOID
598   )
599 {
600   EFI_STATUS                                    Status;
601   UINTN                                         CommSize;
602   UINT8                                         *CommBuffer;
603   EFI_SMM_COMMUNICATE_HEADER                    *CommHeader;
604   SMRAM_PROFILE_PARAMETER_GET_PROFILE_INFO      *CommGetProfileInfo;
605   SMRAM_PROFILE_PARAMETER_GET_PROFILE_DATA      *CommGetProfileData;
606   UINT64                                        ProfileSize;
607   PHYSICAL_ADDRESS                              ProfileBuffer;
608   EFI_SMM_COMMUNICATION_PROTOCOL                *SmmCommunication;
609 
610   Status = gBS->LocateProtocol (&gEfiSmmCommunicationProtocolGuid, NULL, (VOID **) &SmmCommunication);
611   if (EFI_ERROR (Status)) {
612     DEBUG ((EFI_D_ERROR, "SmramProfile: Locate SmmCommunication protocol - %r\n", Status));
613     return Status;
614   }
615 
616   CommSize = sizeof (EFI_GUID) + sizeof (UINTN) + sizeof (SMRAM_PROFILE_PARAMETER_GET_PROFILE_DATA);
617   CommBuffer = AllocateZeroPool (CommSize);
618   if (CommBuffer == NULL) {
619     Status = EFI_OUT_OF_RESOURCES;
620     Print (L"SmramProfile: AllocateZeroPool (0x%x) for comm buffer - %r\n", CommSize, Status);
621     return Status;
622   }
623 
624   //
625   // Get Size
626   //
627   CommHeader = (EFI_SMM_COMMUNICATE_HEADER *) &CommBuffer[0];
628   CopyMem (&CommHeader->HeaderGuid, &gEdkiiMemoryProfileGuid, sizeof (gEdkiiMemoryProfileGuid));
629   CommHeader->MessageLength = sizeof (SMRAM_PROFILE_PARAMETER_GET_PROFILE_INFO);
630 
631   CommGetProfileInfo = (SMRAM_PROFILE_PARAMETER_GET_PROFILE_INFO *) &CommBuffer[OFFSET_OF (EFI_SMM_COMMUNICATE_HEADER, Data)];
632   CommGetProfileInfo->Header.Command      = SMRAM_PROFILE_COMMAND_GET_PROFILE_INFO;
633   CommGetProfileInfo->Header.DataLength   = sizeof (*CommGetProfileInfo);
634   CommGetProfileInfo->Header.ReturnStatus = (UINT64)-1;
635   CommGetProfileInfo->ProfileSize         = 0;
636 
637   CommSize = sizeof (EFI_GUID) + sizeof (UINTN) + CommHeader->MessageLength;
638   Status = SmmCommunication->Communicate (SmmCommunication, CommBuffer, &CommSize);
639   if (EFI_ERROR (Status)) {
640     FreePool (CommBuffer);
641     DEBUG ((EFI_D_ERROR, "SmramProfile: SmmCommunication - %r\n", Status));
642     return Status;
643   }
644 
645   if (CommGetProfileInfo->Header.ReturnStatus != 0) {
646     Print (L"SmramProfile: GetProfileInfo - 0x%0x\n", CommGetProfileInfo->Header.ReturnStatus);
647     return EFI_SUCCESS;
648   }
649 
650   ProfileSize = CommGetProfileInfo->ProfileSize;
651 
652   //
653   // Get Data
654   //
655   ProfileBuffer = (PHYSICAL_ADDRESS) (UINTN) AllocateZeroPool ((UINTN) ProfileSize);
656   if (ProfileBuffer == 0) {
657     FreePool (CommBuffer);
658     Status = EFI_OUT_OF_RESOURCES;
659     Print (L"SmramProfile: AllocateZeroPool (0x%x) for profile buffer - %r\n", (UINTN) ProfileSize, Status);
660     return Status;
661   }
662 
663   CommHeader = (EFI_SMM_COMMUNICATE_HEADER *) &CommBuffer[0];
664   CopyMem (&CommHeader->HeaderGuid, &gEdkiiMemoryProfileGuid, sizeof(gEdkiiMemoryProfileGuid));
665   CommHeader->MessageLength = sizeof (SMRAM_PROFILE_PARAMETER_GET_PROFILE_DATA);
666 
667   CommGetProfileData = (SMRAM_PROFILE_PARAMETER_GET_PROFILE_DATA *) &CommBuffer[OFFSET_OF (EFI_SMM_COMMUNICATE_HEADER, Data)];
668   CommGetProfileData->Header.Command      = SMRAM_PROFILE_COMMAND_GET_PROFILE_DATA;
669   CommGetProfileData->Header.DataLength   = sizeof (*CommGetProfileData);
670   CommGetProfileData->Header.ReturnStatus = (UINT64)-1;
671   CommGetProfileData->ProfileSize         = ProfileSize;
672   CommGetProfileData->ProfileBuffer       = ProfileBuffer;
673 
674   CommSize = sizeof (EFI_GUID) + sizeof (UINTN) + CommHeader->MessageLength;
675   Status = SmmCommunication->Communicate (SmmCommunication, CommBuffer, &CommSize);
676   ASSERT_EFI_ERROR (Status);
677 
678   if (CommGetProfileData->Header.ReturnStatus != 0) {
679     FreePool ((VOID *) (UINTN) CommGetProfileData->ProfileBuffer);
680     FreePool (CommBuffer);
681     Print (L"GetProfileData - 0x%x\n", CommGetProfileData->Header.ReturnStatus);
682     return EFI_SUCCESS;
683   }
684 
685 
686   Print (L"SmramProfileSize - 0x%x\n", CommGetProfileData->ProfileSize);
687   Print (L"======= SmramProfile begin =======\n");
688   DumpMemoryProfile (CommGetProfileData->ProfileBuffer, CommGetProfileData->ProfileSize);
689   Print (L"======= SmramProfile end =======\n\n\n");
690 
691   FreePool ((VOID *) (UINTN) CommGetProfileData->ProfileBuffer);
692   FreePool (CommBuffer);
693 
694   return EFI_SUCCESS;
695 }
696 
697 /**
698   The user Entry Point for Application. The user code starts with this function
699   as the real entry point for the image goes into a library that calls this function.
700 
701   @param[in] ImageHandle    The firmware allocated handle for the EFI image.
702   @param[in] SystemTable    A pointer to the EFI System Table.
703 
704   @retval EFI_SUCCESS       The entry point is executed successfully.
705   @retval other             Some error occurs when executing this entry point.
706 
707 **/
708 EFI_STATUS
709 EFIAPI
UefiMain(IN EFI_HANDLE ImageHandle,IN EFI_SYSTEM_TABLE * SystemTable)710 UefiMain (
711   IN EFI_HANDLE         ImageHandle,
712   IN EFI_SYSTEM_TABLE   *SystemTable
713   )
714 {
715   EFI_STATUS                    Status;
716 
717   Status = GetUefiMemoryProfileData ();
718   if (EFI_ERROR (Status)) {
719     DEBUG ((EFI_D_ERROR, "GetUefiMemoryProfileData - %r\n", Status));
720   }
721 
722   Status = GetSmramProfileData ();
723   if (EFI_ERROR (Status)) {
724     DEBUG ((EFI_D_ERROR, "GetSmramProfileData - %r\n", Status));
725   }
726 
727   return EFI_SUCCESS;
728 }
729