IntelSiliconPkg: Replace BSD License with BSD+Patent License
[mirror_edk2.git] / MdeModulePkg / Application / MemoryProfileInfo / MemoryProfileInfo.c
1 /** @file
2
3 Copyright (c) 2014 - 2017, 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
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 *
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->PdbStringOffset != 0) {
253 GetShortPdbFileName ((CHAR8 *) ((UINTN) DriverInfo + DriverInfo->PdbStringOffset), 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 *
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 *
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 *
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 *
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 *
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 *
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 *
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 *
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 *
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
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 *
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 *
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 *
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 *
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
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
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
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
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
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 }