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