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