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