]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Application/MemoryProfileInfo/MemoryProfileInfo.c
UefiCpuPkg: Move AsmRelocateApLoopStart from Mpfuncs.nasm to AmdSev.nasm
[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 }
201
202 for (IndexPdb = 0; PdbFileName[IndexPdb] != 0; IndexPdb++) {
203 if ((PdbFileName[IndexPdb] == '\\') || (PdbFileName[IndexPdb] == '/')) {
204 StartIndex = IndexPdb + 1;
205 }
206
207 if (PdbFileName[IndexPdb] == '.') {
208 EndIndex = IndexPdb;
209 }
210 }
211
212 IndexBuffer = 0;
213 for (IndexPdb = StartIndex; IndexPdb < EndIndex; IndexPdb++) {
214 AsciiBuffer[IndexBuffer] = PdbFileName[IndexPdb];
215 IndexBuffer++;
216 if (IndexBuffer >= PROFILE_NAME_STRING_LENGTH) {
217 AsciiBuffer[PROFILE_NAME_STRING_LENGTH] = 0;
218 break;
219 }
220 }
221 }
222 }
223
224 /**
225 Get a human readable name for an image.
226 The following methods will be tried orderly:
227 1. Image PDB
228 2. FFS UI section
229 3. Image GUID
230
231 @param[in] DriverInfo Pointer to memory profile driver info.
232
233 @return The resulting Ascii name string is stored in the mNameString global array.
234
235 **/
236 CHAR8 *
237 GetDriverNameString (
238 IN MEMORY_PROFILE_DRIVER_INFO *DriverInfo
239 )
240 {
241 EFI_STATUS Status;
242 CHAR16 *NameString;
243 UINTN StringSize;
244
245 //
246 // Method 1: Get the name string from image PDB
247 //
248 if (DriverInfo->PdbStringOffset != 0) {
249 GetShortPdbFileName ((CHAR8 *)((UINTN)DriverInfo + DriverInfo->PdbStringOffset), mNameString);
250 return mNameString;
251 }
252
253 if (!IsZeroGuid (&DriverInfo->FileName)) {
254 //
255 // Try to get the image's FFS UI section by image GUID
256 //
257 NameString = NULL;
258 StringSize = 0;
259 Status = GetSectionFromAnyFv (
260 &DriverInfo->FileName,
261 EFI_SECTION_USER_INTERFACE,
262 0,
263 (VOID **)&NameString,
264 &StringSize
265 );
266 if (!EFI_ERROR (Status)) {
267 //
268 // Method 2: Get the name string from FFS UI section
269 //
270 if (StrLen (NameString) > PROFILE_NAME_STRING_LENGTH) {
271 NameString[PROFILE_NAME_STRING_LENGTH] = 0;
272 }
273
274 UnicodeStrToAsciiStrS (NameString, mNameString, sizeof (mNameString));
275 FreePool (NameString);
276 return mNameString;
277 }
278 }
279
280 //
281 // Method 3: Get the name string from image GUID
282 //
283 AsciiSPrint (mNameString, sizeof (mNameString), "%g", &DriverInfo->FileName);
284 return mNameString;
285 }
286
287 /**
288 Memory type to string.
289
290 @param[in] MemoryType Memory type.
291
292 @return Pointer to string.
293
294 **/
295 CHAR8 *
296 ProfileMemoryTypeToStr (
297 IN EFI_MEMORY_TYPE MemoryType
298 )
299 {
300 UINTN Index;
301
302 if ((UINT32)MemoryType >= 0x80000000) {
303 //
304 // OS reserved memory type.
305 //
306 Index = EfiMaxMemoryType;
307 } else if ((UINT32)MemoryType >= 0x70000000) {
308 //
309 // OEM reserved memory type.
310 //
311 Index = EfiMaxMemoryType + 1;
312 } else {
313 Index = MemoryType;
314 }
315
316 return mMemoryTypeString[Index];
317 }
318
319 /**
320 Action to string.
321
322 @param[in] Action Profile action.
323 @param[in] UserDefinedActionString Pointer to user defined action string.
324 @param[in] IsForSmm TRUE - SMRAM profile.
325 FALSE - UEFI memory profile.
326
327 @return Pointer to string.
328
329 **/
330 CHAR8 *
331 ProfileActionToStr (
332 IN MEMORY_PROFILE_ACTION Action,
333 IN CHAR8 *UserDefinedActionString,
334 IN BOOLEAN IsForSmm
335 )
336 {
337 UINTN Index;
338 UINTN ActionStringCount;
339 CHAR8 **ActionString;
340
341 if (IsForSmm) {
342 ActionString = mSmmActionString;
343 ActionStringCount = ARRAY_SIZE (mSmmActionString);
344 } else {
345 ActionString = mActionString;
346 ActionStringCount = ARRAY_SIZE (mActionString);
347 }
348
349 if ((UINTN)(UINT32)Action < ActionStringCount) {
350 return ActionString[Action];
351 }
352
353 for (Index = 0; Index < ARRAY_SIZE (mExtActionString); Index++) {
354 if (mExtActionString[Index].Action == Action) {
355 return mExtActionString[Index].String;
356 }
357 }
358
359 if ((Action & MEMORY_PROFILE_ACTION_USER_DEFINED_MASK) != 0) {
360 if (UserDefinedActionString != NULL) {
361 return UserDefinedActionString;
362 }
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
444 Print (L" MEMORY_PROFILE_DRIVER_INFO (0x%x)\n", DriverIndex);
445 Print (L" Signature - 0x%08x\n", DriverInfo->Header.Signature);
446 Print (L" Length - 0x%04x\n", DriverInfo->Header.Length);
447 Print (L" Revision - 0x%04x\n", DriverInfo->Header.Revision);
448 NameString = GetDriverNameString (DriverInfo);
449 Print (L" FileName - %a\n", NameString);
450 if (DriverInfo->PdbStringOffset != 0) {
451 Print (L" Pdb - %a\n", (CHAR8 *)((UINTN)DriverInfo + DriverInfo->PdbStringOffset));
452 }
453
454 Print (L" ImageBase - 0x%016lx\n", DriverInfo->ImageBase);
455 Print (L" ImageSize - 0x%016lx\n", DriverInfo->ImageSize);
456 Print (L" EntryPoint - 0x%016lx\n", DriverInfo->EntryPoint);
457 Print (L" ImageSubsystem - 0x%04x (%a)\n", DriverInfo->ImageSubsystem, mSubsystemString[(DriverInfo->ImageSubsystem < sizeof (mSubsystemString)/sizeof (mSubsystemString[0])) ? DriverInfo->ImageSubsystem : 0]);
458 Print (L" FileType - 0x%02x (%a)\n", DriverInfo->FileType, mFileTypeString[(DriverInfo->FileType < sizeof (mFileTypeString)/sizeof (mFileTypeString[0])) ? DriverInfo->FileType : 0]);
459 Print (L" CurrentUsage - 0x%016lx\n", DriverInfo->CurrentUsage);
460 Print (L" PeakUsage - 0x%016lx\n", DriverInfo->PeakUsage);
461 for (TypeIndex = 0; TypeIndex < sizeof (DriverInfo->CurrentUsageByType) / sizeof (DriverInfo->CurrentUsageByType[0]); TypeIndex++) {
462 if ((DriverInfo->CurrentUsageByType[TypeIndex] != 0) ||
463 (DriverInfo->PeakUsageByType[TypeIndex] != 0))
464 {
465 Print (L" CurrentUsage[0x%02x] - 0x%016lx (%a)\n", TypeIndex, DriverInfo->CurrentUsageByType[TypeIndex], mMemoryTypeString[TypeIndex]);
466 Print (L" PeakUsage[0x%02x] - 0x%016lx (%a)\n", TypeIndex, DriverInfo->PeakUsageByType[TypeIndex], mMemoryTypeString[TypeIndex]);
467 }
468 }
469
470 Print (L" AllocRecordCount - 0x%08x\n", DriverInfo->AllocRecordCount);
471
472 AllocInfo = (MEMORY_PROFILE_ALLOC_INFO *)((UINTN)DriverInfo + DriverInfo->Header.Length);
473 for (AllocIndex = 0; AllocIndex < DriverInfo->AllocRecordCount; AllocIndex++) {
474 AllocInfo = DumpMemoryProfileAllocInfo (DriverInfo, AllocIndex, AllocInfo, IsForSmm);
475 if (AllocInfo == NULL) {
476 return NULL;
477 }
478 }
479
480 return (MEMORY_PROFILE_DRIVER_INFO *)AllocInfo;
481 }
482
483 /**
484 Dump memory profile context information.
485
486 @param[in] Context Pointer to memory profile context.
487 @param[in] IsForSmm TRUE - SMRAM profile.
488 FALSE - UEFI memory profile.
489
490 @return Pointer to the end of memory profile context buffer.
491
492 **/
493 VOID *
494 DumpMemoryProfileContext (
495 IN MEMORY_PROFILE_CONTEXT *Context,
496 IN BOOLEAN IsForSmm
497 )
498 {
499 UINTN TypeIndex;
500 MEMORY_PROFILE_DRIVER_INFO *DriverInfo;
501 UINTN DriverIndex;
502
503 if (Context->Header.Signature != MEMORY_PROFILE_CONTEXT_SIGNATURE) {
504 return NULL;
505 }
506
507 Print (L"MEMORY_PROFILE_CONTEXT\n");
508 Print (L" Signature - 0x%08x\n", Context->Header.Signature);
509 Print (L" Length - 0x%04x\n", Context->Header.Length);
510 Print (L" Revision - 0x%04x\n", Context->Header.Revision);
511 Print (L" CurrentTotalUsage - 0x%016lx\n", Context->CurrentTotalUsage);
512 Print (L" PeakTotalUsage - 0x%016lx\n", Context->PeakTotalUsage);
513 for (TypeIndex = 0; TypeIndex < sizeof (Context->CurrentTotalUsageByType) / sizeof (Context->CurrentTotalUsageByType[0]); TypeIndex++) {
514 if ((Context->CurrentTotalUsageByType[TypeIndex] != 0) ||
515 (Context->PeakTotalUsageByType[TypeIndex] != 0))
516 {
517 Print (L" CurrentTotalUsage[0x%02x] - 0x%016lx (%a)\n", TypeIndex, Context->CurrentTotalUsageByType[TypeIndex], mMemoryTypeString[TypeIndex]);
518 Print (L" PeakTotalUsage[0x%02x] - 0x%016lx (%a)\n", TypeIndex, Context->PeakTotalUsageByType[TypeIndex], mMemoryTypeString[TypeIndex]);
519 }
520 }
521
522 Print (L" TotalImageSize - 0x%016lx\n", Context->TotalImageSize);
523 Print (L" ImageCount - 0x%08x\n", Context->ImageCount);
524 Print (L" SequenceCount - 0x%08x\n", Context->SequenceCount);
525
526 DriverInfo = (MEMORY_PROFILE_DRIVER_INFO *)((UINTN)Context + Context->Header.Length);
527 for (DriverIndex = 0; DriverIndex < Context->ImageCount; DriverIndex++) {
528 DriverInfo = DumpMemoryProfileDriverInfo (DriverIndex, DriverInfo, IsForSmm);
529 if (DriverInfo == NULL) {
530 return NULL;
531 }
532 }
533
534 return (VOID *)DriverInfo;
535 }
536
537 /**
538 Dump memory profile descriptor information.
539
540 @param[in] DescriptorIndex Memory profile descriptor index.
541 @param[in] Descriptor Pointer to memory profile descriptor.
542
543 @return Pointer to next memory profile descriptor.
544
545 **/
546 MEMORY_PROFILE_DESCRIPTOR *
547 DumpMemoryProfileDescriptor (
548 IN UINTN DescriptorIndex,
549 IN MEMORY_PROFILE_DESCRIPTOR *Descriptor
550 )
551 {
552 if (Descriptor->Header.Signature != MEMORY_PROFILE_DESCRIPTOR_SIGNATURE) {
553 return NULL;
554 }
555
556 Print (L" MEMORY_PROFILE_DESCRIPTOR (0x%x)\n", DescriptorIndex);
557 Print (L" Signature - 0x%08x\n", Descriptor->Header.Signature);
558 Print (L" Length - 0x%04x\n", Descriptor->Header.Length);
559 Print (L" Revision - 0x%04x\n", Descriptor->Header.Revision);
560 Print (L" Address - 0x%016lx\n", Descriptor->Address);
561 Print (L" Size - 0x%016lx\n", Descriptor->Size);
562
563 return (MEMORY_PROFILE_DESCRIPTOR *)((UINTN)Descriptor + Descriptor->Header.Length);
564 }
565
566 /**
567 Dump memory profile free memory information.
568
569 @param[in] FreeMemory Pointer to memory profile free memory.
570
571 @return Pointer to the end of memory profile free memory buffer.
572
573 **/
574 VOID *
575 DumpMemoryProfileFreeMemory (
576 IN MEMORY_PROFILE_FREE_MEMORY *FreeMemory
577 )
578 {
579 MEMORY_PROFILE_DESCRIPTOR *Descriptor;
580 UINTN DescriptorIndex;
581
582 if (FreeMemory->Header.Signature != MEMORY_PROFILE_FREE_MEMORY_SIGNATURE) {
583 return NULL;
584 }
585
586 Print (L"MEMORY_PROFILE_FREE_MEMORY\n");
587 Print (L" Signature - 0x%08x\n", FreeMemory->Header.Signature);
588 Print (L" Length - 0x%04x\n", FreeMemory->Header.Length);
589 Print (L" Revision - 0x%04x\n", FreeMemory->Header.Revision);
590 Print (L" TotalFreeMemoryPages - 0x%016lx\n", FreeMemory->TotalFreeMemoryPages);
591 Print (L" FreeMemoryEntryCount - 0x%08x\n", FreeMemory->FreeMemoryEntryCount);
592
593 Descriptor = (MEMORY_PROFILE_DESCRIPTOR *)((UINTN)FreeMemory + FreeMemory->Header.Length);
594 for (DescriptorIndex = 0; DescriptorIndex < FreeMemory->FreeMemoryEntryCount; DescriptorIndex++) {
595 Descriptor = DumpMemoryProfileDescriptor (DescriptorIndex, Descriptor);
596 if (Descriptor == NULL) {
597 return NULL;
598 }
599 }
600
601 return (VOID *)Descriptor;
602 }
603
604 /**
605 Dump memory profile memory range information.
606
607 @param[in] MemoryRange Pointer to memory profile memory range.
608
609 @return Pointer to the end of memory profile memory range buffer.
610
611 **/
612 VOID *
613 DumpMemoryProfileMemoryRange (
614 IN MEMORY_PROFILE_MEMORY_RANGE *MemoryRange
615 )
616 {
617 MEMORY_PROFILE_DESCRIPTOR *Descriptor;
618 UINTN DescriptorIndex;
619
620 if (MemoryRange->Header.Signature != MEMORY_PROFILE_MEMORY_RANGE_SIGNATURE) {
621 return NULL;
622 }
623
624 Print (L"MEMORY_PROFILE_MEMORY_RANGE\n");
625 Print (L" Signature - 0x%08x\n", MemoryRange->Header.Signature);
626 Print (L" Length - 0x%04x\n", MemoryRange->Header.Length);
627 Print (L" Revision - 0x%04x\n", MemoryRange->Header.Revision);
628 Print (L" MemoryRangeCount - 0x%08x\n", MemoryRange->MemoryRangeCount);
629
630 Descriptor = (MEMORY_PROFILE_DESCRIPTOR *)((UINTN)MemoryRange + MemoryRange->Header.Length);
631 for (DescriptorIndex = 0; DescriptorIndex < MemoryRange->MemoryRangeCount; DescriptorIndex++) {
632 Descriptor = DumpMemoryProfileDescriptor (DescriptorIndex, Descriptor);
633 if (Descriptor == NULL) {
634 return NULL;
635 }
636 }
637
638 return (VOID *)Descriptor;
639 }
640
641 /**
642 Scan memory profile by Signature.
643
644 @param[in] ProfileBuffer Memory profile base address.
645 @param[in] ProfileSize Memory profile size.
646 @param[in] Signature Signature.
647
648 @return Pointer to the structure with the signature.
649
650 **/
651 VOID *
652 ScanMemoryProfileBySignature (
653 IN PHYSICAL_ADDRESS ProfileBuffer,
654 IN UINT64 ProfileSize,
655 IN UINT32 Signature
656 )
657 {
658 MEMORY_PROFILE_COMMON_HEADER *CommonHeader;
659 UINTN ProfileEnd;
660
661 ProfileEnd = (UINTN)(ProfileBuffer + ProfileSize);
662 CommonHeader = (MEMORY_PROFILE_COMMON_HEADER *)(UINTN)ProfileBuffer;
663 while ((UINTN)CommonHeader < ProfileEnd) {
664 if (CommonHeader->Signature == Signature) {
665 //
666 // Found it.
667 //
668 return (VOID *)CommonHeader;
669 }
670
671 if (CommonHeader->Length == 0) {
672 ASSERT (FALSE);
673 return NULL;
674 }
675
676 CommonHeader = (MEMORY_PROFILE_COMMON_HEADER *)((UINTN)CommonHeader + CommonHeader->Length);
677 }
678
679 return NULL;
680 }
681
682 /**
683 Dump memory profile information.
684
685 @param[in] ProfileBuffer Memory profile base address.
686 @param[in] ProfileSize Memory profile size.
687 @param[in] IsForSmm TRUE - SMRAM profile.
688 FALSE - UEFI memory profile.
689
690 **/
691 VOID
692 DumpMemoryProfile (
693 IN PHYSICAL_ADDRESS ProfileBuffer,
694 IN UINT64 ProfileSize,
695 IN BOOLEAN IsForSmm
696 )
697 {
698 MEMORY_PROFILE_CONTEXT *Context;
699 MEMORY_PROFILE_FREE_MEMORY *FreeMemory;
700 MEMORY_PROFILE_MEMORY_RANGE *MemoryRange;
701
702 Context = (MEMORY_PROFILE_CONTEXT *)ScanMemoryProfileBySignature (ProfileBuffer, ProfileSize, MEMORY_PROFILE_CONTEXT_SIGNATURE);
703 if (Context != NULL) {
704 DumpMemoryProfileContext (Context, IsForSmm);
705 }
706
707 FreeMemory = (MEMORY_PROFILE_FREE_MEMORY *)ScanMemoryProfileBySignature (ProfileBuffer, ProfileSize, MEMORY_PROFILE_FREE_MEMORY_SIGNATURE);
708 if (FreeMemory != NULL) {
709 DumpMemoryProfileFreeMemory (FreeMemory);
710 }
711
712 MemoryRange = (MEMORY_PROFILE_MEMORY_RANGE *)ScanMemoryProfileBySignature (ProfileBuffer, ProfileSize, MEMORY_PROFILE_MEMORY_RANGE_SIGNATURE);
713 if (MemoryRange != NULL) {
714 DumpMemoryProfileMemoryRange (MemoryRange);
715 }
716 }
717
718 /**
719 Get Allocate summary information structure by caller address.
720
721 @param[in] CallerAddress Caller address.
722 @param[in] DriverSummaryInfoData Driver summary information data structure.
723
724 @return Allocate summary information structure by caller address.
725
726 **/
727 MEMORY_PROFILE_ALLOC_SUMMARY_INFO_DATA *
728 GetAllocSummaryInfoByCallerAddress (
729 IN PHYSICAL_ADDRESS CallerAddress,
730 IN MEMORY_PROFILE_DRIVER_SUMMARY_INFO_DATA *DriverSummaryInfoData
731 )
732 {
733 LIST_ENTRY *AllocSummaryInfoList;
734 LIST_ENTRY *AllocSummaryLink;
735 MEMORY_PROFILE_ALLOC_SUMMARY_INFO *AllocSummaryInfo;
736 MEMORY_PROFILE_ALLOC_SUMMARY_INFO_DATA *AllocSummaryInfoData;
737
738 AllocSummaryInfoList = DriverSummaryInfoData->AllocSummaryInfoList;
739
740 for (AllocSummaryLink = AllocSummaryInfoList->ForwardLink;
741 AllocSummaryLink != AllocSummaryInfoList;
742 AllocSummaryLink = AllocSummaryLink->ForwardLink)
743 {
744 AllocSummaryInfoData = CR (
745 AllocSummaryLink,
746 MEMORY_PROFILE_ALLOC_SUMMARY_INFO_DATA,
747 Link,
748 MEMORY_PROFILE_ALLOC_SUMMARY_INFO_SIGNATURE
749 );
750 AllocSummaryInfo = &AllocSummaryInfoData->AllocSummaryInfo;
751 if (AllocSummaryInfo->CallerAddress == CallerAddress) {
752 return AllocSummaryInfoData;
753 }
754 }
755
756 return NULL;
757 }
758
759 /**
760 Create Allocate summary information structure and
761 link to Driver summary information data structure.
762
763 @param[in, out] DriverSummaryInfoData Driver summary information data structure.
764 @param[in] AllocInfo Pointer to memory profile alloc info.
765
766 @return Pointer to next memory profile alloc info.
767
768 **/
769 MEMORY_PROFILE_ALLOC_INFO *
770 CreateAllocSummaryInfo (
771 IN OUT MEMORY_PROFILE_DRIVER_SUMMARY_INFO_DATA *DriverSummaryInfoData,
772 IN MEMORY_PROFILE_ALLOC_INFO *AllocInfo
773 )
774 {
775 MEMORY_PROFILE_ALLOC_SUMMARY_INFO_DATA *AllocSummaryInfoData;
776 MEMORY_PROFILE_ALLOC_SUMMARY_INFO *AllocSummaryInfo;
777
778 if (AllocInfo->Header.Signature != MEMORY_PROFILE_ALLOC_INFO_SIGNATURE) {
779 return NULL;
780 }
781
782 AllocSummaryInfoData = GetAllocSummaryInfoByCallerAddress (AllocInfo->CallerAddress, DriverSummaryInfoData);
783 if (AllocSummaryInfoData == NULL) {
784 AllocSummaryInfoData = AllocatePool (sizeof (*AllocSummaryInfoData));
785 if (AllocSummaryInfoData == NULL) {
786 return NULL;
787 }
788
789 AllocSummaryInfoData->Signature = MEMORY_PROFILE_ALLOC_SUMMARY_INFO_SIGNATURE;
790 AllocSummaryInfo = &AllocSummaryInfoData->AllocSummaryInfo;
791 AllocSummaryInfo->Header.Signature = MEMORY_PROFILE_ALLOC_SUMMARY_INFO_SIGNATURE;
792 AllocSummaryInfo->Header.Length = sizeof (*AllocSummaryInfo);
793 AllocSummaryInfo->Header.Revision = MEMORY_PROFILE_ALLOC_SUMMARY_INFO_REVISION;
794 AllocSummaryInfo->CallerAddress = AllocInfo->CallerAddress;
795 AllocSummaryInfo->Action = AllocInfo->Action;
796 if (AllocInfo->ActionStringOffset != 0) {
797 AllocSummaryInfo->ActionString = (CHAR8 *)((UINTN)AllocInfo + AllocInfo->ActionStringOffset);
798 } else {
799 AllocSummaryInfo->ActionString = NULL;
800 }
801
802 AllocSummaryInfo->AllocateCount = 0;
803 AllocSummaryInfo->TotalSize = 0;
804 InsertTailList (DriverSummaryInfoData->AllocSummaryInfoList, &AllocSummaryInfoData->Link);
805 }
806
807 AllocSummaryInfo = &AllocSummaryInfoData->AllocSummaryInfo;
808 AllocSummaryInfo->AllocateCount++;
809 AllocSummaryInfo->TotalSize += AllocInfo->Size;
810
811 return (MEMORY_PROFILE_ALLOC_INFO *)((UINTN)AllocInfo + AllocInfo->Header.Length);
812 }
813
814 /**
815 Create Driver summary information structure and
816 link to Context summary information data structure.
817
818 @param[in, out] ContextSummaryData Context summary information data structure.
819 @param[in] DriverInfo Pointer to memory profile driver info.
820
821 @return Pointer to next memory profile driver info.
822
823 **/
824 MEMORY_PROFILE_DRIVER_INFO *
825 CreateDriverSummaryInfo (
826 IN OUT MEMORY_PROFILE_CONTEXT_SUMMARY_DATA *ContextSummaryData,
827 IN MEMORY_PROFILE_DRIVER_INFO *DriverInfo
828 )
829 {
830 MEMORY_PROFILE_DRIVER_SUMMARY_INFO_DATA *DriverSummaryInfoData;
831 MEMORY_PROFILE_ALLOC_INFO *AllocInfo;
832 UINTN AllocIndex;
833
834 if (DriverInfo->Header.Signature != MEMORY_PROFILE_DRIVER_INFO_SIGNATURE) {
835 return NULL;
836 }
837
838 DriverSummaryInfoData = AllocatePool (sizeof (*DriverSummaryInfoData) + sizeof (LIST_ENTRY));
839 if (DriverSummaryInfoData == NULL) {
840 return NULL;
841 }
842
843 DriverSummaryInfoData->Signature = MEMORY_PROFILE_DRIVER_INFO_SIGNATURE;
844 DriverSummaryInfoData->DriverInfo = DriverInfo;
845 DriverSummaryInfoData->AllocSummaryInfoList = (LIST_ENTRY *)(DriverSummaryInfoData + 1);
846 InitializeListHead (DriverSummaryInfoData->AllocSummaryInfoList);
847 InsertTailList (ContextSummaryData->DriverSummaryInfoList, &DriverSummaryInfoData->Link);
848
849 AllocInfo = (MEMORY_PROFILE_ALLOC_INFO *)((UINTN)DriverInfo + DriverInfo->Header.Length);
850 for (AllocIndex = 0; AllocIndex < DriverInfo->AllocRecordCount; AllocIndex++) {
851 AllocInfo = CreateAllocSummaryInfo (DriverSummaryInfoData, AllocInfo);
852 if (AllocInfo == NULL) {
853 return NULL;
854 }
855 }
856
857 return (MEMORY_PROFILE_DRIVER_INFO *)AllocInfo;
858 }
859
860 /**
861 Create Context summary information structure.
862
863 @param[in] ProfileBuffer Memory profile base address.
864 @param[in] ProfileSize Memory profile size.
865
866 @return Context summary information structure.
867
868 **/
869 MEMORY_PROFILE_CONTEXT_SUMMARY_DATA *
870 CreateContextSummaryData (
871 IN PHYSICAL_ADDRESS ProfileBuffer,
872 IN UINT64 ProfileSize
873 )
874 {
875 MEMORY_PROFILE_CONTEXT *Context;
876 MEMORY_PROFILE_DRIVER_INFO *DriverInfo;
877 UINTN DriverIndex;
878
879 Context = (MEMORY_PROFILE_CONTEXT *)ScanMemoryProfileBySignature (ProfileBuffer, ProfileSize, MEMORY_PROFILE_CONTEXT_SIGNATURE);
880 if (Context == NULL) {
881 return NULL;
882 }
883
884 mMemoryProfileContextSummary.Signature = MEMORY_PROFILE_CONTEXT_SIGNATURE;
885 mMemoryProfileContextSummary.Context = Context;
886 mMemoryProfileContextSummary.DriverSummaryInfoList = &mImageSummaryQueue;
887
888 DriverInfo = (MEMORY_PROFILE_DRIVER_INFO *)((UINTN)Context + Context->Header.Length);
889 for (DriverIndex = 0; DriverIndex < Context->ImageCount; DriverIndex++) {
890 DriverInfo = CreateDriverSummaryInfo (&mMemoryProfileContextSummary, DriverInfo);
891 if (DriverInfo == NULL) {
892 return NULL;
893 }
894 }
895
896 return &mMemoryProfileContextSummary;
897 }
898
899 /**
900 Dump Context summary information.
901
902 @param[in] ContextSummaryData Context summary information data.
903 @param[in] IsForSmm TRUE - SMRAM profile.
904 FALSE - UEFI memory profile.
905
906 **/
907 VOID
908 DumpContextSummaryData (
909 IN MEMORY_PROFILE_CONTEXT_SUMMARY_DATA *ContextSummaryData,
910 IN BOOLEAN IsForSmm
911 )
912 {
913 MEMORY_PROFILE_DRIVER_SUMMARY_INFO_DATA *DriverSummaryInfoData;
914 MEMORY_PROFILE_ALLOC_SUMMARY_INFO_DATA *AllocSummaryInfoData;
915 LIST_ENTRY *DriverSummaryInfoList;
916 LIST_ENTRY *DriverSummaryLink;
917 LIST_ENTRY *AllocSummaryInfoList;
918 LIST_ENTRY *AllocSummaryLink;
919 MEMORY_PROFILE_DRIVER_INFO *DriverInfo;
920 MEMORY_PROFILE_ALLOC_SUMMARY_INFO *AllocSummaryInfo;
921 CHAR8 *NameString;
922
923 if (ContextSummaryData == NULL) {
924 return;
925 }
926
927 Print (L"\nSummary Data:\n");
928
929 DriverSummaryInfoList = ContextSummaryData->DriverSummaryInfoList;
930 for (DriverSummaryLink = DriverSummaryInfoList->ForwardLink;
931 DriverSummaryLink != DriverSummaryInfoList;
932 DriverSummaryLink = DriverSummaryLink->ForwardLink)
933 {
934 DriverSummaryInfoData = CR (
935 DriverSummaryLink,
936 MEMORY_PROFILE_DRIVER_SUMMARY_INFO_DATA,
937 Link,
938 MEMORY_PROFILE_DRIVER_INFO_SIGNATURE
939 );
940 DriverInfo = DriverSummaryInfoData->DriverInfo;
941
942 NameString = GetDriverNameString (DriverInfo);
943 Print (L"\nDriver - %a (Usage - 0x%08x)", NameString, DriverInfo->CurrentUsage);
944 if (DriverInfo->CurrentUsage == 0) {
945 Print (L"\n");
946 continue;
947 }
948
949 if (DriverInfo->PdbStringOffset != 0) {
950 Print (L" (Pdb - %a)\n", (CHAR8 *)((UINTN)DriverInfo + DriverInfo->PdbStringOffset));
951 } else {
952 Print (L"\n");
953 }
954
955 Print (L"Caller List:\n");
956 Print (L" Count Size RVA Action\n");
957 Print (L"========== ================== ================== (================================)\n");
958 AllocSummaryInfoList = DriverSummaryInfoData->AllocSummaryInfoList;
959 for (AllocSummaryLink = AllocSummaryInfoList->ForwardLink;
960 AllocSummaryLink != AllocSummaryInfoList;
961 AllocSummaryLink = AllocSummaryLink->ForwardLink)
962 {
963 AllocSummaryInfoData = CR (
964 AllocSummaryLink,
965 MEMORY_PROFILE_ALLOC_SUMMARY_INFO_DATA,
966 Link,
967 MEMORY_PROFILE_ALLOC_SUMMARY_INFO_SIGNATURE
968 );
969 AllocSummaryInfo = &AllocSummaryInfoData->AllocSummaryInfo;
970
971 Print (
972 L"0x%08x 0x%016lx <== 0x%016lx",
973 AllocSummaryInfo->AllocateCount,
974 AllocSummaryInfo->TotalSize,
975 AllocSummaryInfo->CallerAddress - DriverInfo->ImageBase
976 );
977 Print (L" (%a)\n", ProfileActionToStr (AllocSummaryInfo->Action, AllocSummaryInfo->ActionString, IsForSmm));
978 }
979 }
980
981 return;
982 }
983
984 /**
985 Destroy Context summary information.
986
987 @param[in, out] ContextSummaryData Context summary information data.
988
989 **/
990 VOID
991 DestroyContextSummaryData (
992 IN OUT MEMORY_PROFILE_CONTEXT_SUMMARY_DATA *ContextSummaryData
993 )
994 {
995 MEMORY_PROFILE_DRIVER_SUMMARY_INFO_DATA *DriverSummaryInfoData;
996 MEMORY_PROFILE_ALLOC_SUMMARY_INFO_DATA *AllocSummaryInfoData;
997 LIST_ENTRY *DriverSummaryInfoList;
998 LIST_ENTRY *DriverSummaryLink;
999 LIST_ENTRY *AllocSummaryInfoList;
1000 LIST_ENTRY *AllocSummaryLink;
1001
1002 if (ContextSummaryData == NULL) {
1003 return;
1004 }
1005
1006 DriverSummaryInfoList = ContextSummaryData->DriverSummaryInfoList;
1007 for (DriverSummaryLink = DriverSummaryInfoList->ForwardLink;
1008 DriverSummaryLink != DriverSummaryInfoList;
1009 )
1010 {
1011 DriverSummaryInfoData = CR (
1012 DriverSummaryLink,
1013 MEMORY_PROFILE_DRIVER_SUMMARY_INFO_DATA,
1014 Link,
1015 MEMORY_PROFILE_DRIVER_INFO_SIGNATURE
1016 );
1017 DriverSummaryLink = DriverSummaryLink->ForwardLink;
1018
1019 AllocSummaryInfoList = DriverSummaryInfoData->AllocSummaryInfoList;
1020 for (AllocSummaryLink = AllocSummaryInfoList->ForwardLink;
1021 AllocSummaryLink != AllocSummaryInfoList;
1022 )
1023 {
1024 AllocSummaryInfoData = CR (
1025 AllocSummaryLink,
1026 MEMORY_PROFILE_ALLOC_SUMMARY_INFO_DATA,
1027 Link,
1028 MEMORY_PROFILE_ALLOC_SUMMARY_INFO_SIGNATURE
1029 );
1030 AllocSummaryLink = AllocSummaryLink->ForwardLink;
1031
1032 RemoveEntryList (&AllocSummaryInfoData->Link);
1033 FreePool (AllocSummaryInfoData);
1034 }
1035
1036 RemoveEntryList (&DriverSummaryInfoData->Link);
1037 FreePool (DriverSummaryInfoData);
1038 }
1039
1040 return;
1041 }
1042
1043 /**
1044 Get and dump UEFI memory profile data.
1045
1046 @return EFI_SUCCESS Get the memory profile data successfully.
1047 @return other Fail to get the memory profile data.
1048
1049 **/
1050 EFI_STATUS
1051 GetUefiMemoryProfileData (
1052 VOID
1053 )
1054 {
1055 EFI_STATUS Status;
1056 EDKII_MEMORY_PROFILE_PROTOCOL *ProfileProtocol;
1057 VOID *Data;
1058 UINT64 Size;
1059 MEMORY_PROFILE_CONTEXT_SUMMARY_DATA *MemoryProfileContextSummaryData;
1060 BOOLEAN RecordingState;
1061
1062 Status = gBS->LocateProtocol (&gEdkiiMemoryProfileGuid, NULL, (VOID **)&ProfileProtocol);
1063 if (EFI_ERROR (Status)) {
1064 DEBUG ((DEBUG_ERROR, "UefiMemoryProfile: Locate MemoryProfile protocol - %r\n", Status));
1065 return Status;
1066 }
1067
1068 //
1069 // Set recording state if needed.
1070 //
1071 RecordingState = MEMORY_PROFILE_RECORDING_DISABLE;
1072 Status = ProfileProtocol->GetRecordingState (ProfileProtocol, &RecordingState);
1073 if (RecordingState == MEMORY_PROFILE_RECORDING_ENABLE) {
1074 ProfileProtocol->SetRecordingState (ProfileProtocol, MEMORY_PROFILE_RECORDING_DISABLE);
1075 }
1076
1077 Size = 0;
1078 Data = NULL;
1079 Status = ProfileProtocol->GetData (
1080 ProfileProtocol,
1081 &Size,
1082 Data
1083 );
1084 if (Status != EFI_BUFFER_TOO_SMALL) {
1085 Print (L"UefiMemoryProfile: GetData - %r\n", Status);
1086 goto Done;
1087 }
1088
1089 Data = AllocateZeroPool ((UINTN)Size);
1090 if (Data == NULL) {
1091 Status = EFI_OUT_OF_RESOURCES;
1092 Print (L"UefiMemoryProfile: AllocateZeroPool (0x%x) - %r\n", Size, Status);
1093 return Status;
1094 }
1095
1096 Status = ProfileProtocol->GetData (
1097 ProfileProtocol,
1098 &Size,
1099 Data
1100 );
1101 if (EFI_ERROR (Status)) {
1102 Print (L"UefiMemoryProfile: GetData - %r\n", Status);
1103 goto Done;
1104 }
1105
1106 Print (L"UefiMemoryProfileSize - 0x%x\n", Size);
1107 Print (L"======= UefiMemoryProfile begin =======\n");
1108 DumpMemoryProfile ((PHYSICAL_ADDRESS)(UINTN)Data, Size, FALSE);
1109
1110 //
1111 // Dump summary information
1112 //
1113 MemoryProfileContextSummaryData = CreateContextSummaryData ((PHYSICAL_ADDRESS)(UINTN)Data, Size);
1114 if (MemoryProfileContextSummaryData != NULL) {
1115 DumpContextSummaryData (MemoryProfileContextSummaryData, FALSE);
1116 DestroyContextSummaryData (MemoryProfileContextSummaryData);
1117 }
1118
1119 Print (L"======= UefiMemoryProfile end =======\n\n\n");
1120
1121 Done:
1122 if (Data != NULL) {
1123 FreePool (Data);
1124 }
1125
1126 //
1127 // Restore recording state if needed.
1128 //
1129 if (RecordingState == MEMORY_PROFILE_RECORDING_ENABLE) {
1130 ProfileProtocol->SetRecordingState (ProfileProtocol, MEMORY_PROFILE_RECORDING_ENABLE);
1131 }
1132
1133 return Status;
1134 }
1135
1136 /**
1137 Get and dump SMRAM profile data.
1138
1139 @return EFI_SUCCESS Get the SMRAM profile data successfully.
1140 @return other Fail to get the SMRAM profile data.
1141
1142 **/
1143 EFI_STATUS
1144 GetSmramProfileData (
1145 VOID
1146 )
1147 {
1148 EFI_STATUS Status;
1149 UINTN CommSize;
1150 UINT8 *CommBuffer;
1151 EFI_SMM_COMMUNICATE_HEADER *CommHeader;
1152 SMRAM_PROFILE_PARAMETER_GET_PROFILE_INFO *CommGetProfileInfo;
1153 SMRAM_PROFILE_PARAMETER_GET_PROFILE_DATA_BY_OFFSET *CommGetProfileData;
1154 SMRAM_PROFILE_PARAMETER_RECORDING_STATE *CommRecordingState;
1155 UINTN ProfileSize;
1156 VOID *ProfileBuffer;
1157 EFI_SMM_COMMUNICATION_PROTOCOL *SmmCommunication;
1158 UINTN MinimalSizeNeeded;
1159 EDKII_PI_SMM_COMMUNICATION_REGION_TABLE *PiSmmCommunicationRegionTable;
1160 UINT32 Index;
1161 EFI_MEMORY_DESCRIPTOR *Entry;
1162 VOID *Buffer;
1163 UINTN Size;
1164 UINTN Offset;
1165 MEMORY_PROFILE_CONTEXT_SUMMARY_DATA *MemoryProfileContextSummaryData;
1166 BOOLEAN RecordingState;
1167
1168 ProfileBuffer = NULL;
1169
1170 Status = gBS->LocateProtocol (&gEfiSmmCommunicationProtocolGuid, NULL, (VOID **)&SmmCommunication);
1171 if (EFI_ERROR (Status)) {
1172 DEBUG ((DEBUG_ERROR, "SmramProfile: Locate SmmCommunication protocol - %r\n", Status));
1173 return Status;
1174 }
1175
1176 MinimalSizeNeeded = sizeof (EFI_GUID) +
1177 sizeof (UINTN) +
1178 MAX (
1179 sizeof (SMRAM_PROFILE_PARAMETER_GET_PROFILE_INFO),
1180 MAX (
1181 sizeof (SMRAM_PROFILE_PARAMETER_GET_PROFILE_DATA_BY_OFFSET),
1182 sizeof (SMRAM_PROFILE_PARAMETER_RECORDING_STATE)
1183 )
1184 );
1185 MinimalSizeNeeded += MAX (
1186 sizeof (MEMORY_PROFILE_CONTEXT),
1187 MAX (
1188 sizeof (MEMORY_PROFILE_DRIVER_INFO),
1189 MAX (
1190 sizeof (MEMORY_PROFILE_ALLOC_INFO),
1191 MAX (
1192 sizeof (MEMORY_PROFILE_DESCRIPTOR),
1193 MAX (
1194 sizeof (MEMORY_PROFILE_FREE_MEMORY),
1195 sizeof (MEMORY_PROFILE_MEMORY_RANGE)
1196 )
1197 )
1198 )
1199 )
1200 );
1201
1202 Status = EfiGetSystemConfigurationTable (
1203 &gEdkiiPiSmmCommunicationRegionTableGuid,
1204 (VOID **)&PiSmmCommunicationRegionTable
1205 );
1206 if (EFI_ERROR (Status)) {
1207 DEBUG ((DEBUG_ERROR, "SmramProfile: Get PiSmmCommunicationRegionTable - %r\n", Status));
1208 return Status;
1209 }
1210
1211 ASSERT (PiSmmCommunicationRegionTable != NULL);
1212 Entry = (EFI_MEMORY_DESCRIPTOR *)(PiSmmCommunicationRegionTable + 1);
1213 Size = 0;
1214 for (Index = 0; Index < PiSmmCommunicationRegionTable->NumberOfEntries; Index++) {
1215 if (Entry->Type == EfiConventionalMemory) {
1216 Size = EFI_PAGES_TO_SIZE ((UINTN)Entry->NumberOfPages);
1217 if (Size >= MinimalSizeNeeded) {
1218 break;
1219 }
1220 }
1221
1222 Entry = (EFI_MEMORY_DESCRIPTOR *)((UINT8 *)Entry + PiSmmCommunicationRegionTable->DescriptorSize);
1223 }
1224
1225 ASSERT (Index < PiSmmCommunicationRegionTable->NumberOfEntries);
1226 CommBuffer = (UINT8 *)(UINTN)Entry->PhysicalStart;
1227
1228 //
1229 // Set recording state if needed.
1230 //
1231 RecordingState = MEMORY_PROFILE_RECORDING_DISABLE;
1232
1233 CommHeader = (EFI_SMM_COMMUNICATE_HEADER *)&CommBuffer[0];
1234 CopyMem (&CommHeader->HeaderGuid, &gEdkiiMemoryProfileGuid, sizeof (gEdkiiMemoryProfileGuid));
1235 CommHeader->MessageLength = sizeof (SMRAM_PROFILE_PARAMETER_RECORDING_STATE);
1236
1237 CommRecordingState = (SMRAM_PROFILE_PARAMETER_RECORDING_STATE *)&CommBuffer[OFFSET_OF (EFI_SMM_COMMUNICATE_HEADER, Data)];
1238 CommRecordingState->Header.Command = SMRAM_PROFILE_COMMAND_GET_RECORDING_STATE;
1239 CommRecordingState->Header.DataLength = sizeof (*CommRecordingState);
1240 CommRecordingState->Header.ReturnStatus = (UINT64)-1;
1241 CommRecordingState->RecordingState = MEMORY_PROFILE_RECORDING_DISABLE;
1242
1243 CommSize = sizeof (EFI_GUID) + sizeof (UINTN) + CommHeader->MessageLength;
1244 Status = SmmCommunication->Communicate (SmmCommunication, CommBuffer, &CommSize);
1245 if (EFI_ERROR (Status)) {
1246 DEBUG ((DEBUG_ERROR, "SmramProfile: SmmCommunication - %r\n", Status));
1247 return Status;
1248 }
1249
1250 if (CommRecordingState->Header.ReturnStatus != 0) {
1251 Print (L"SmramProfile: GetRecordingState - 0x%0x\n", CommRecordingState->Header.ReturnStatus);
1252 return EFI_SUCCESS;
1253 }
1254
1255 RecordingState = CommRecordingState->RecordingState;
1256 if (RecordingState == MEMORY_PROFILE_RECORDING_ENABLE) {
1257 CommHeader = (EFI_SMM_COMMUNICATE_HEADER *)&CommBuffer[0];
1258 CopyMem (&CommHeader->HeaderGuid, &gEdkiiMemoryProfileGuid, sizeof (gEdkiiMemoryProfileGuid));
1259 CommHeader->MessageLength = sizeof (SMRAM_PROFILE_PARAMETER_RECORDING_STATE);
1260
1261 CommRecordingState = (SMRAM_PROFILE_PARAMETER_RECORDING_STATE *)&CommBuffer[OFFSET_OF (EFI_SMM_COMMUNICATE_HEADER, Data)];
1262 CommRecordingState->Header.Command = SMRAM_PROFILE_COMMAND_SET_RECORDING_STATE;
1263 CommRecordingState->Header.DataLength = sizeof (*CommRecordingState);
1264 CommRecordingState->Header.ReturnStatus = (UINT64)-1;
1265 CommRecordingState->RecordingState = MEMORY_PROFILE_RECORDING_DISABLE;
1266
1267 CommSize = sizeof (EFI_GUID) + sizeof (UINTN) + CommHeader->MessageLength;
1268 SmmCommunication->Communicate (SmmCommunication, CommBuffer, &CommSize);
1269 }
1270
1271 //
1272 // Get Size
1273 //
1274 CommHeader = (EFI_SMM_COMMUNICATE_HEADER *)&CommBuffer[0];
1275 CopyMem (&CommHeader->HeaderGuid, &gEdkiiMemoryProfileGuid, sizeof (gEdkiiMemoryProfileGuid));
1276 CommHeader->MessageLength = sizeof (SMRAM_PROFILE_PARAMETER_GET_PROFILE_INFO);
1277
1278 CommGetProfileInfo = (SMRAM_PROFILE_PARAMETER_GET_PROFILE_INFO *)&CommBuffer[OFFSET_OF (EFI_SMM_COMMUNICATE_HEADER, Data)];
1279 CommGetProfileInfo->Header.Command = SMRAM_PROFILE_COMMAND_GET_PROFILE_INFO;
1280 CommGetProfileInfo->Header.DataLength = sizeof (*CommGetProfileInfo);
1281 CommGetProfileInfo->Header.ReturnStatus = (UINT64)-1;
1282 CommGetProfileInfo->ProfileSize = 0;
1283
1284 CommSize = sizeof (EFI_GUID) + sizeof (UINTN) + CommHeader->MessageLength;
1285 Status = SmmCommunication->Communicate (SmmCommunication, CommBuffer, &CommSize);
1286 ASSERT_EFI_ERROR (Status);
1287
1288 if (CommGetProfileInfo->Header.ReturnStatus != 0) {
1289 Status = EFI_SUCCESS;
1290 Print (L"SmramProfile: GetProfileInfo - 0x%0x\n", CommGetProfileInfo->Header.ReturnStatus);
1291 goto Done;
1292 }
1293
1294 ProfileSize = (UINTN)CommGetProfileInfo->ProfileSize;
1295
1296 //
1297 // Get Data
1298 //
1299 ProfileBuffer = AllocateZeroPool (ProfileSize);
1300 if (ProfileBuffer == NULL) {
1301 Status = EFI_OUT_OF_RESOURCES;
1302 Print (L"SmramProfile: AllocateZeroPool (0x%x) for profile buffer - %r\n", ProfileSize, Status);
1303 goto Done;
1304 }
1305
1306 CommHeader = (EFI_SMM_COMMUNICATE_HEADER *)&CommBuffer[0];
1307 CopyMem (&CommHeader->HeaderGuid, &gEdkiiMemoryProfileGuid, sizeof (gEdkiiMemoryProfileGuid));
1308 CommHeader->MessageLength = sizeof (SMRAM_PROFILE_PARAMETER_GET_PROFILE_DATA_BY_OFFSET);
1309
1310 CommGetProfileData = (SMRAM_PROFILE_PARAMETER_GET_PROFILE_DATA_BY_OFFSET *)&CommBuffer[OFFSET_OF (EFI_SMM_COMMUNICATE_HEADER, Data)];
1311 CommGetProfileData->Header.Command = SMRAM_PROFILE_COMMAND_GET_PROFILE_DATA_BY_OFFSET;
1312 CommGetProfileData->Header.DataLength = sizeof (*CommGetProfileData);
1313 CommGetProfileData->Header.ReturnStatus = (UINT64)-1;
1314
1315 CommSize = sizeof (EFI_GUID) + sizeof (UINTN) + CommHeader->MessageLength;
1316 Buffer = (UINT8 *)CommHeader + CommSize;
1317 Size -= CommSize;
1318
1319 CommGetProfileData->ProfileBuffer = (PHYSICAL_ADDRESS)(UINTN)Buffer;
1320 CommGetProfileData->ProfileOffset = 0;
1321 while (CommGetProfileData->ProfileOffset < ProfileSize) {
1322 Offset = (UINTN)CommGetProfileData->ProfileOffset;
1323 if (Size <= (ProfileSize - CommGetProfileData->ProfileOffset)) {
1324 CommGetProfileData->ProfileSize = (UINT64)Size;
1325 } else {
1326 CommGetProfileData->ProfileSize = (UINT64)(ProfileSize - CommGetProfileData->ProfileOffset);
1327 }
1328
1329 Status = SmmCommunication->Communicate (SmmCommunication, CommBuffer, &CommSize);
1330 ASSERT_EFI_ERROR (Status);
1331
1332 if (CommGetProfileData->Header.ReturnStatus != 0) {
1333 Status = EFI_SUCCESS;
1334 Print (L"GetProfileData - 0x%x\n", CommGetProfileData->Header.ReturnStatus);
1335 goto Done;
1336 }
1337
1338 CopyMem ((UINT8 *)ProfileBuffer + Offset, (VOID *)(UINTN)CommGetProfileData->ProfileBuffer, (UINTN)CommGetProfileData->ProfileSize);
1339 }
1340
1341 Print (L"SmramProfileSize - 0x%x\n", ProfileSize);
1342 Print (L"======= SmramProfile begin =======\n");
1343 DumpMemoryProfile ((PHYSICAL_ADDRESS)(UINTN)ProfileBuffer, ProfileSize, TRUE);
1344
1345 //
1346 // Dump summary information
1347 //
1348 MemoryProfileContextSummaryData = CreateContextSummaryData ((PHYSICAL_ADDRESS)(UINTN)ProfileBuffer, ProfileSize);
1349 if (MemoryProfileContextSummaryData != NULL) {
1350 DumpContextSummaryData (MemoryProfileContextSummaryData, TRUE);
1351 DestroyContextSummaryData (MemoryProfileContextSummaryData);
1352 }
1353
1354 Print (L"======= SmramProfile end =======\n\n\n");
1355
1356 Done:
1357 if (ProfileBuffer != NULL) {
1358 FreePool (ProfileBuffer);
1359 }
1360
1361 //
1362 // Restore recording state if needed.
1363 //
1364 if (RecordingState == MEMORY_PROFILE_RECORDING_ENABLE) {
1365 CommHeader = (EFI_SMM_COMMUNICATE_HEADER *)&CommBuffer[0];
1366 CopyMem (&CommHeader->HeaderGuid, &gEdkiiMemoryProfileGuid, sizeof (gEdkiiMemoryProfileGuid));
1367 CommHeader->MessageLength = sizeof (SMRAM_PROFILE_PARAMETER_RECORDING_STATE);
1368
1369 CommRecordingState = (SMRAM_PROFILE_PARAMETER_RECORDING_STATE *)&CommBuffer[OFFSET_OF (EFI_SMM_COMMUNICATE_HEADER, Data)];
1370 CommRecordingState->Header.Command = SMRAM_PROFILE_COMMAND_SET_RECORDING_STATE;
1371 CommRecordingState->Header.DataLength = sizeof (*CommRecordingState);
1372 CommRecordingState->Header.ReturnStatus = (UINT64)-1;
1373 CommRecordingState->RecordingState = MEMORY_PROFILE_RECORDING_ENABLE;
1374
1375 CommSize = sizeof (EFI_GUID) + sizeof (UINTN) + CommHeader->MessageLength;
1376 SmmCommunication->Communicate (SmmCommunication, CommBuffer, &CommSize);
1377 }
1378
1379 return Status;
1380 }
1381
1382 /**
1383 The user Entry Point for Application. The user code starts with this function
1384 as the real entry point for the image goes into a library that calls this function.
1385
1386 @param[in] ImageHandle The firmware allocated handle for the EFI image.
1387 @param[in] SystemTable A pointer to the EFI System Table.
1388
1389 @retval EFI_SUCCESS The entry point is executed successfully.
1390 @retval other Some error occurs when executing this entry point.
1391
1392 **/
1393 EFI_STATUS
1394 EFIAPI
1395 UefiMain (
1396 IN EFI_HANDLE ImageHandle,
1397 IN EFI_SYSTEM_TABLE *SystemTable
1398 )
1399 {
1400 EFI_STATUS Status;
1401
1402 Status = GetUefiMemoryProfileData ();
1403 if (EFI_ERROR (Status)) {
1404 DEBUG ((DEBUG_ERROR, "GetUefiMemoryProfileData - %r\n", Status));
1405 }
1406
1407 Status = GetSmramProfileData ();
1408 if (EFI_ERROR (Status)) {
1409 DEBUG ((DEBUG_ERROR, "GetSmramProfileData - %r\n", Status));
1410 }
1411
1412 return EFI_SUCCESS;
1413 }