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