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