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