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