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