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