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 + 1) * sizeof (CHAR16)); 125 126 if (PdbFileName == NULL) { 127 StrnCpyS (UnicodeBuffer, PROFILE_NAME_STRING_LENGTH + 1, 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 StrnCpyS (mNameString, PROFILE_NAME_STRING_LENGTH + 1, 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 } 762