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 <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/PrintLib.h> 26 27 #include <Protocol/SmmCommunication.h> 28 #include <Protocol/SmmAccess2.h> 29 30 #include <Guid/MemoryProfile.h> 31 #include <Guid/PiSmmCommunicationRegionTable.h> 32 33 CHAR8 *mActionString[] = { 34 "Unknown", 35 "gBS->AllocatePages", 36 "gBS->FreePages", 37 "gBS->AllocatePool", 38 "gBS->FreePool", 39 }; 40 41 CHAR8 *mSmmActionString[] = { 42 "SmmUnknown", 43 "gSmst->SmmAllocatePages", 44 "gSmst->SmmFreePages", 45 "gSmst->SmmAllocatePool", 46 "gSmst->SmmFreePool", 47 }; 48 49 typedef struct { 50 MEMORY_PROFILE_ACTION Action; 51 CHAR8 *String; 52 } ACTION_STRING; 53 54 ACTION_STRING mExtActionString[] = { 55 {MEMORY_PROFILE_ACTION_LIB_ALLOCATE_PAGES, "Lib:AllocatePages"}, 56 {MEMORY_PROFILE_ACTION_LIB_ALLOCATE_RUNTIME_PAGES, "Lib:AllocateRuntimePages"}, 57 {MEMORY_PROFILE_ACTION_LIB_ALLOCATE_RESERVED_PAGES, "Lib:AllocateReservedPages"}, 58 {MEMORY_PROFILE_ACTION_LIB_FREE_PAGES, "Lib:FreePages"}, 59 {MEMORY_PROFILE_ACTION_LIB_ALLOCATE_ALIGNED_PAGES, "Lib:AllocateAlignedPages"}, 60 {MEMORY_PROFILE_ACTION_LIB_ALLOCATE_ALIGNED_RUNTIME_PAGES, "Lib:AllocateAlignedRuntimePages"}, 61 {MEMORY_PROFILE_ACTION_LIB_ALLOCATE_ALIGNED_RESERVED_PAGES, "Lib:AllocateAlignedReservedPages"}, 62 {MEMORY_PROFILE_ACTION_LIB_FREE_ALIGNED_PAGES, "Lib:FreeAlignedPages"}, 63 {MEMORY_PROFILE_ACTION_LIB_ALLOCATE_POOL, "Lib:AllocatePool"}, 64 {MEMORY_PROFILE_ACTION_LIB_ALLOCATE_RUNTIME_POOL, "Lib:AllocateRuntimePool"}, 65 {MEMORY_PROFILE_ACTION_LIB_ALLOCATE_RESERVED_POOL, "Lib:AllocateReservedPool"}, 66 {MEMORY_PROFILE_ACTION_LIB_FREE_POOL, "Lib:FreePool"}, 67 {MEMORY_PROFILE_ACTION_LIB_ALLOCATE_ZERO_POOL, "Lib:AllocateZeroPool"}, 68 {MEMORY_PROFILE_ACTION_LIB_ALLOCATE_RUNTIME_ZERO_POOL, "Lib:AllocateRuntimeZeroPool"}, 69 {MEMORY_PROFILE_ACTION_LIB_ALLOCATE_RESERVED_ZERO_POOL, "Lib:AllocateReservedZeroPool"}, 70 {MEMORY_PROFILE_ACTION_LIB_ALLOCATE_COPY_POOL, "Lib:AllocateCopyPool"}, 71 {MEMORY_PROFILE_ACTION_LIB_ALLOCATE_RUNTIME_COPY_POOL, "Lib:AllocateRuntimeCopyPool"}, 72 {MEMORY_PROFILE_ACTION_LIB_ALLOCATE_RESERVED_COPY_POOL, "Lib:AllocateReservedCopyPool"}, 73 {MEMORY_PROFILE_ACTION_LIB_REALLOCATE_POOL, "Lib:ReallocatePool"}, 74 {MEMORY_PROFILE_ACTION_LIB_REALLOCATE_RUNTIME_POOL, "Lib:ReallocateRuntimePool"}, 75 {MEMORY_PROFILE_ACTION_LIB_REALLOCATE_RESERVED_POOL, "Lib:ReallocateReservedPool"}, 76 }; 77 78 CHAR8 mUserDefinedActionString[] = {"UserDefined-0x80000000"}; 79 80 CHAR8 *mMemoryTypeString[] = { 81 "EfiReservedMemoryType", 82 "EfiLoaderCode", 83 "EfiLoaderData", 84 "EfiBootServicesCode", 85 "EfiBootServicesData", 86 "EfiRuntimeServicesCode", 87 "EfiRuntimeServicesData", 88 "EfiConventionalMemory", 89 "EfiUnusableMemory", 90 "EfiACPIReclaimMemory", 91 "EfiACPIMemoryNVS", 92 "EfiMemoryMappedIO", 93 "EfiMemoryMappedIOPortSpace", 94 "EfiPalCode", 95 "EfiPersistentMemory", 96 "EfiOSReserved", 97 "EfiOemReserved", 98 }; 99 100 CHAR8 *mSubsystemString[] = { 101 "Unknown", 102 "NATIVE", 103 "WINDOWS_GUI", 104 "WINDOWS_CUI", 105 "Unknown", 106 "Unknown", 107 "Unknown", 108 "POSIX_CUI", 109 "Unknown", 110 "WINDOWS_CE_GUI", 111 "EFI_APPLICATION", 112 "EFI_BOOT_SERVICE_DRIVER", 113 "EFI_RUNTIME_DRIVER", 114 "EFI_ROM", 115 "XBOX", 116 "Unknown", 117 }; 118 119 CHAR8 *mFileTypeString[] = { 120 "Unknown", 121 "RAW", 122 "FREEFORM", 123 "SECURITY_CORE", 124 "PEI_CORE", 125 "DXE_CORE", 126 "PEIM", 127 "DRIVER", 128 "COMBINED_PEIM_DRIVER", 129 "APPLICATION", 130 "SMM", 131 "FIRMWARE_VOLUME_IMAGE", 132 "COMBINED_SMM_DXE", 133 "SMM_CORE", 134 }; 135 136 #define PROFILE_NAME_STRING_LENGTH 64 137 CHAR8 mNameString[PROFILE_NAME_STRING_LENGTH + 1]; 138 139 // 140 // Profile summary information 141 // 142 #define MEMORY_PROFILE_ALLOC_SUMMARY_INFO_SIGNATURE SIGNATURE_32 ('M','P','A','S') 143 #define MEMORY_PROFILE_ALLOC_SUMMARY_INFO_REVISION 0x0001 144 145 typedef struct { 146 MEMORY_PROFILE_COMMON_HEADER Header; 147 PHYSICAL_ADDRESS CallerAddress; 148 MEMORY_PROFILE_ACTION Action; 149 CHAR8 *ActionString; 150 UINT32 AllocateCount; 151 UINT64 TotalSize; 152 } MEMORY_PROFILE_ALLOC_SUMMARY_INFO; 153 154 typedef struct { 155 UINT32 Signature; 156 MEMORY_PROFILE_ALLOC_SUMMARY_INFO AllocSummaryInfo; 157 LIST_ENTRY Link; 158 } MEMORY_PROFILE_ALLOC_SUMMARY_INFO_DATA; 159 160 typedef struct { 161 UINT32 Signature; 162 MEMORY_PROFILE_DRIVER_INFO *DriverInfo; 163 LIST_ENTRY *AllocSummaryInfoList; 164 LIST_ENTRY Link; 165 } MEMORY_PROFILE_DRIVER_SUMMARY_INFO_DATA; 166 167 typedef struct { 168 UINT32 Signature; 169 MEMORY_PROFILE_CONTEXT *Context; 170 LIST_ENTRY *DriverSummaryInfoList; 171 } MEMORY_PROFILE_CONTEXT_SUMMARY_DATA; 172 173 LIST_ENTRY mImageSummaryQueue = INITIALIZE_LIST_HEAD_VARIABLE (mImageSummaryQueue); 174 MEMORY_PROFILE_CONTEXT_SUMMARY_DATA mMemoryProfileContextSummary; 175 176 /** 177 Get the file name portion of the Pdb File Name. 178 179 The portion of the Pdb File Name between the last backslash and 180 either a following period or the end of the string is copied into 181 AsciiBuffer. The name is truncated, if necessary, to ensure that 182 AsciiBuffer is not overrun. 183 184 @param[in] PdbFileName Pdb file name. 185 @param[out] AsciiBuffer The resultant Ascii File Name. 186 187 **/ 188 VOID 189 GetShortPdbFileName ( 190 IN CHAR8 *PdbFileName, 191 OUT CHAR8 *AsciiBuffer 192 ) 193 { 194 UINTN IndexPdb; // Current work location within a Pdb string. 195 UINTN IndexBuffer; // Current work location within a Buffer string. 196 UINTN StartIndex; 197 UINTN EndIndex; 198 199 ZeroMem (AsciiBuffer, PROFILE_NAME_STRING_LENGTH + 1); 200 201 if (PdbFileName == NULL) { 202 AsciiStrnCpyS (AsciiBuffer, PROFILE_NAME_STRING_LENGTH + 1, " ", 1); 203 } else { 204 StartIndex = 0; 205 for (EndIndex = 0; PdbFileName[EndIndex] != 0; EndIndex++); 206 for (IndexPdb = 0; PdbFileName[IndexPdb] != 0; IndexPdb++) { 207 if ((PdbFileName[IndexPdb] == '\\') || (PdbFileName[IndexPdb] == '/')) { 208 StartIndex = IndexPdb + 1; 209 } 210 211 if (PdbFileName[IndexPdb] == '.') { 212 EndIndex = IndexPdb; 213 } 214 } 215 216 IndexBuffer = 0; 217 for (IndexPdb = StartIndex; IndexPdb < EndIndex; IndexPdb++) { 218 AsciiBuffer[IndexBuffer] = PdbFileName[IndexPdb]; 219 IndexBuffer++; 220 if (IndexBuffer >= PROFILE_NAME_STRING_LENGTH) { 221 AsciiBuffer[PROFILE_NAME_STRING_LENGTH] = 0; 222 break; 223 } 224 } 225 } 226 } 227 228 /** 229 Get a human readable name for an image. 230 The following methods will be tried orderly: 231 1. Image PDB 232 2. FFS UI section 233 3. Image GUID 234 235 @param[in] DriverInfo Pointer to memory profile driver info. 236 237 @return The resulting Ascii name string is stored in the mNameString global array. 238 239 **/ 240 CHAR8 * 241 GetDriverNameString ( 242 IN MEMORY_PROFILE_DRIVER_INFO *DriverInfo 243 ) 244 { 245 EFI_STATUS Status; 246 CHAR16 *NameString; 247 UINTN StringSize; 248 249 // 250 // Method 1: Get the name string from image PDB 251 // 252 if (DriverInfo->Header.Length > sizeof (MEMORY_PROFILE_DRIVER_INFO)) { 253 GetShortPdbFileName ((CHAR8 *) (DriverInfo + 1), mNameString); 254 return mNameString; 255 } 256 257 if (!IsZeroGuid (&DriverInfo->FileName)) { 258 // 259 // Try to get the image's FFS UI section by image GUID 260 // 261 NameString = NULL; 262 StringSize = 0; 263 Status = GetSectionFromAnyFv ( 264 &DriverInfo->FileName, 265 EFI_SECTION_USER_INTERFACE, 266 0, 267 (VOID **) &NameString, 268 &StringSize 269 ); 270 if (!EFI_ERROR (Status)) { 271 // 272 // Method 2: Get the name string from FFS UI section 273 // 274 if (StrLen (NameString) > PROFILE_NAME_STRING_LENGTH) { 275 NameString[PROFILE_NAME_STRING_LENGTH] = 0; 276 } 277 UnicodeStrToAsciiStrS (NameString, mNameString, sizeof (mNameString)); 278 FreePool (NameString); 279 return mNameString; 280 } 281 } 282 283 // 284 // Method 3: Get the name string from image GUID 285 // 286 AsciiSPrint (mNameString, sizeof (mNameString), "%g", &DriverInfo->FileName); 287 return mNameString; 288 } 289 290 /** 291 Memory type to string. 292 293 @param[in] MemoryType Memory type. 294 295 @return Pointer to string. 296 297 **/ 298 CHAR8 * 299 ProfileMemoryTypeToStr ( 300 IN EFI_MEMORY_TYPE MemoryType 301 ) 302 { 303 UINTN Index; 304 305 if ((UINT32) MemoryType >= 0x80000000) { 306 // 307 // OS reserved memory type. 308 // 309 Index = EfiMaxMemoryType; 310 } else if ((UINT32) MemoryType >= 0x70000000) { 311 // 312 // OEM reserved memory type. 313 // 314 Index = EfiMaxMemoryType + 1; 315 } else { 316 Index = MemoryType; 317 } 318 319 return mMemoryTypeString[Index]; 320 } 321 322 /** 323 Action to string. 324 325 @param[in] Action Profile action. 326 @param[in] UserDefinedActionString Pointer to user defined action string. 327 @param[in] IsForSmm TRUE - SMRAM profile. 328 FALSE - UEFI memory profile. 329 330 @return Pointer to string. 331 332 **/ 333 CHAR8 * 334 ProfileActionToStr ( 335 IN MEMORY_PROFILE_ACTION Action, 336 IN CHAR8 *UserDefinedActionString, 337 IN BOOLEAN IsForSmm 338 ) 339 { 340 UINTN Index; 341 UINTN ActionStringCount; 342 CHAR8 **ActionString; 343 344 if (IsForSmm) { 345 ActionString = mSmmActionString; 346 ActionStringCount = ARRAY_SIZE (mSmmActionString); 347 } else { 348 ActionString = mActionString; 349 ActionStringCount = ARRAY_SIZE (mActionString); 350 } 351 352 if ((UINTN) (UINT32) Action < ActionStringCount) { 353 return ActionString[Action]; 354 } 355 for (Index = 0; Index < ARRAY_SIZE (mExtActionString); Index++) { 356 if (mExtActionString[Index].Action == Action) { 357 return mExtActionString[Index].String; 358 } 359 } 360 if ((Action & MEMORY_PROFILE_ACTION_USER_DEFINED_MASK) != 0) { 361 if (UserDefinedActionString != NULL) { 362 return UserDefinedActionString; 363 } 364 AsciiSPrint (mUserDefinedActionString, sizeof (mUserDefinedActionString), "UserDefined-0x%08x", Action); 365 return mUserDefinedActionString; 366 } 367 368 return ActionString[0]; 369 } 370 371 /** 372 Dump memory profile allocate information. 373 374 @param[in] DriverInfo Pointer to memory profile driver info. 375 @param[in] AllocIndex Memory profile alloc info index. 376 @param[in] AllocInfo Pointer to memory profile alloc info. 377 @param[in] IsForSmm TRUE - SMRAM profile. 378 FALSE - UEFI memory profile. 379 380 @return Pointer to next memory profile alloc info. 381 382 **/ 383 MEMORY_PROFILE_ALLOC_INFO * 384 DumpMemoryProfileAllocInfo ( 385 IN MEMORY_PROFILE_DRIVER_INFO *DriverInfo, 386 IN UINTN AllocIndex, 387 IN MEMORY_PROFILE_ALLOC_INFO *AllocInfo, 388 IN BOOLEAN IsForSmm 389 ) 390 { 391 CHAR8 *ActionString; 392 393 if (AllocInfo->Header.Signature != MEMORY_PROFILE_ALLOC_INFO_SIGNATURE) { 394 return NULL; 395 } 396 397 if (AllocInfo->ActionStringOffset != 0) { 398 ActionString = (CHAR8 *) ((UINTN) AllocInfo + AllocInfo->ActionStringOffset); 399 } else { 400 ActionString = NULL; 401 } 402 403 Print (L" MEMORY_PROFILE_ALLOC_INFO (0x%x)\n", AllocIndex); 404 Print (L" Signature - 0x%08x\n", AllocInfo->Header.Signature); 405 Print (L" Length - 0x%04x\n", AllocInfo->Header.Length); 406 Print (L" Revision - 0x%04x\n", AllocInfo->Header.Revision); 407 Print (L" CallerAddress - 0x%016lx (Offset: 0x%08x)\n", AllocInfo->CallerAddress, (UINTN) (AllocInfo->CallerAddress - DriverInfo->ImageBase)); 408 Print (L" SequenceId - 0x%08x\n", AllocInfo->SequenceId); 409 Print (L" Action - 0x%08x (%a)\n", AllocInfo->Action, ProfileActionToStr (AllocInfo->Action, ActionString, IsForSmm)); 410 Print (L" MemoryType - 0x%08x (%a)\n", AllocInfo->MemoryType, ProfileMemoryTypeToStr (AllocInfo->MemoryType)); 411 Print (L" Buffer - 0x%016lx\n", AllocInfo->Buffer); 412 Print (L" Size - 0x%016lx\n", AllocInfo->Size); 413 414 return (MEMORY_PROFILE_ALLOC_INFO *) ((UINTN) AllocInfo + AllocInfo->Header.Length); 415 } 416 417 /** 418 Dump memory profile driver information. 419 420 @param[in] DriverIndex Memory profile driver info index. 421 @param[in] DriverInfo Pointer to memory profile driver info. 422 @param[in] IsForSmm TRUE - SMRAM profile. 423 FALSE - UEFI memory profile. 424 425 @return Pointer to next memory profile driver info. 426 427 **/ 428 MEMORY_PROFILE_DRIVER_INFO * 429 DumpMemoryProfileDriverInfo ( 430 IN UINTN DriverIndex, 431 IN MEMORY_PROFILE_DRIVER_INFO *DriverInfo, 432 IN BOOLEAN IsForSmm 433 ) 434 { 435 UINTN TypeIndex; 436 MEMORY_PROFILE_ALLOC_INFO *AllocInfo; 437 UINTN AllocIndex; 438 CHAR8 *NameString; 439 440 if (DriverInfo->Header.Signature != MEMORY_PROFILE_DRIVER_INFO_SIGNATURE) { 441 return NULL; 442 } 443 Print (L" MEMORY_PROFILE_DRIVER_INFO (0x%x)\n", DriverIndex); 444 Print (L" Signature - 0x%08x\n", DriverInfo->Header.Signature); 445 Print (L" Length - 0x%04x\n", DriverInfo->Header.Length); 446 Print (L" Revision - 0x%04x\n", DriverInfo->Header.Revision); 447 NameString = GetDriverNameString (DriverInfo); 448 Print (L" FileName - %a\n", NameString); 449 if (DriverInfo->PdbStringOffset != 0) { 450 Print (L" Pdb - %a\n", (CHAR8 *) ((UINTN) DriverInfo + DriverInfo->PdbStringOffset)); 451 } 452 Print (L" ImageBase - 0x%016lx\n", DriverInfo->ImageBase); 453 Print (L" ImageSize - 0x%016lx\n", DriverInfo->ImageSize); 454 Print (L" EntryPoint - 0x%016lx\n", DriverInfo->EntryPoint); 455 Print (L" ImageSubsystem - 0x%04x (%a)\n", DriverInfo->ImageSubsystem, mSubsystemString[(DriverInfo->ImageSubsystem < sizeof(mSubsystemString)/sizeof(mSubsystemString[0])) ? DriverInfo->ImageSubsystem : 0]); 456 Print (L" FileType - 0x%02x (%a)\n", DriverInfo->FileType, mFileTypeString[(DriverInfo->FileType < sizeof(mFileTypeString)/sizeof(mFileTypeString[0])) ? DriverInfo->FileType : 0]); 457 Print (L" CurrentUsage - 0x%016lx\n", DriverInfo->CurrentUsage); 458 Print (L" PeakUsage - 0x%016lx\n", DriverInfo->PeakUsage); 459 for (TypeIndex = 0; TypeIndex < sizeof (DriverInfo->CurrentUsageByType) / sizeof (DriverInfo->CurrentUsageByType[0]); TypeIndex++) { 460 if ((DriverInfo->CurrentUsageByType[TypeIndex] != 0) || 461 (DriverInfo->PeakUsageByType[TypeIndex] != 0)) { 462 Print (L" CurrentUsage[0x%02x] - 0x%016lx (%a)\n", TypeIndex, DriverInfo->CurrentUsageByType[TypeIndex], mMemoryTypeString[TypeIndex]); 463 Print (L" PeakUsage[0x%02x] - 0x%016lx (%a)\n", TypeIndex, DriverInfo->PeakUsageByType[TypeIndex], mMemoryTypeString[TypeIndex]); 464 } 465 } 466 Print (L" AllocRecordCount - 0x%08x\n", DriverInfo->AllocRecordCount); 467 468 AllocInfo = (MEMORY_PROFILE_ALLOC_INFO *) ((UINTN) DriverInfo + DriverInfo->Header.Length); 469 for (AllocIndex = 0; AllocIndex < DriverInfo->AllocRecordCount; AllocIndex++) { 470 AllocInfo = DumpMemoryProfileAllocInfo (DriverInfo, AllocIndex, AllocInfo, IsForSmm); 471 if (AllocInfo == NULL) { 472 return NULL; 473 } 474 } 475 return (MEMORY_PROFILE_DRIVER_INFO *) AllocInfo; 476 } 477 478 /** 479 Dump memory profile context information. 480 481 @param[in] Context Pointer to memory profile context. 482 @param[in] IsForSmm TRUE - SMRAM profile. 483 FALSE - UEFI memory profile. 484 485 @return Pointer to the end of memory profile context buffer. 486 487 **/ 488 VOID * 489 DumpMemoryProfileContext ( 490 IN MEMORY_PROFILE_CONTEXT *Context, 491 IN BOOLEAN IsForSmm 492 ) 493 { 494 UINTN TypeIndex; 495 MEMORY_PROFILE_DRIVER_INFO *DriverInfo; 496 UINTN DriverIndex; 497 498 if (Context->Header.Signature != MEMORY_PROFILE_CONTEXT_SIGNATURE) { 499 return NULL; 500 } 501 Print (L"MEMORY_PROFILE_CONTEXT\n"); 502 Print (L" Signature - 0x%08x\n", Context->Header.Signature); 503 Print (L" Length - 0x%04x\n", Context->Header.Length); 504 Print (L" Revision - 0x%04x\n", Context->Header.Revision); 505 Print (L" CurrentTotalUsage - 0x%016lx\n", Context->CurrentTotalUsage); 506 Print (L" PeakTotalUsage - 0x%016lx\n", Context->PeakTotalUsage); 507 for (TypeIndex = 0; TypeIndex < sizeof (Context->CurrentTotalUsageByType) / sizeof (Context->CurrentTotalUsageByType[0]); TypeIndex++) { 508 if ((Context->CurrentTotalUsageByType[TypeIndex] != 0) || 509 (Context->PeakTotalUsageByType[TypeIndex] != 0)) { 510 Print (L" CurrentTotalUsage[0x%02x] - 0x%016lx (%a)\n", TypeIndex, Context->CurrentTotalUsageByType[TypeIndex], mMemoryTypeString[TypeIndex]); 511 Print (L" PeakTotalUsage[0x%02x] - 0x%016lx (%a)\n", TypeIndex, Context->PeakTotalUsageByType[TypeIndex], mMemoryTypeString[TypeIndex]); 512 } 513 } 514 Print (L" TotalImageSize - 0x%016lx\n", Context->TotalImageSize); 515 Print (L" ImageCount - 0x%08x\n", Context->ImageCount); 516 Print (L" SequenceCount - 0x%08x\n", Context->SequenceCount); 517 518 DriverInfo = (MEMORY_PROFILE_DRIVER_INFO *) ((UINTN) Context + Context->Header.Length); 519 for (DriverIndex = 0; DriverIndex < Context->ImageCount; DriverIndex++) { 520 DriverInfo = DumpMemoryProfileDriverInfo (DriverIndex, DriverInfo, IsForSmm); 521 if (DriverInfo == NULL) { 522 return NULL; 523 } 524 } 525 return (VOID *) DriverInfo; 526 } 527 528 /** 529 Dump memory profile descriptor information. 530 531 @param[in] DescriptorIndex Memory profile descriptor index. 532 @param[in] Descriptor Pointer to memory profile descriptor. 533 534 @return Pointer to next memory profile descriptor. 535 536 **/ 537 MEMORY_PROFILE_DESCRIPTOR * 538 DumpMemoryProfileDescriptor ( 539 IN UINTN DescriptorIndex, 540 IN MEMORY_PROFILE_DESCRIPTOR *Descriptor 541 ) 542 { 543 if (Descriptor->Header.Signature != MEMORY_PROFILE_DESCRIPTOR_SIGNATURE) { 544 return NULL; 545 } 546 Print (L" MEMORY_PROFILE_DESCRIPTOR (0x%x)\n", DescriptorIndex); 547 Print (L" Signature - 0x%08x\n", Descriptor->Header.Signature); 548 Print (L" Length - 0x%04x\n", Descriptor->Header.Length); 549 Print (L" Revision - 0x%04x\n", Descriptor->Header.Revision); 550 Print (L" Address - 0x%016lx\n", Descriptor->Address); 551 Print (L" Size - 0x%016lx\n", Descriptor->Size); 552 553 return (MEMORY_PROFILE_DESCRIPTOR *) ((UINTN) Descriptor + Descriptor->Header.Length); 554 } 555 556 /** 557 Dump memory profile free memory information. 558 559 @param[in] FreeMemory Pointer to memory profile free memory. 560 561 @return Pointer to the end of memory profile free memory buffer. 562 563 **/ 564 VOID * 565 DumpMemoryProfileFreeMemory ( 566 IN MEMORY_PROFILE_FREE_MEMORY *FreeMemory 567 ) 568 { 569 MEMORY_PROFILE_DESCRIPTOR *Descriptor; 570 UINTN DescriptorIndex; 571 572 if (FreeMemory->Header.Signature != MEMORY_PROFILE_FREE_MEMORY_SIGNATURE) { 573 return NULL; 574 } 575 Print (L"MEMORY_PROFILE_FREE_MEMORY\n"); 576 Print (L" Signature - 0x%08x\n", FreeMemory->Header.Signature); 577 Print (L" Length - 0x%04x\n", FreeMemory->Header.Length); 578 Print (L" Revision - 0x%04x\n", FreeMemory->Header.Revision); 579 Print (L" TotalFreeMemoryPages - 0x%016lx\n", FreeMemory->TotalFreeMemoryPages); 580 Print (L" FreeMemoryEntryCount - 0x%08x\n", FreeMemory->FreeMemoryEntryCount); 581 582 Descriptor = (MEMORY_PROFILE_DESCRIPTOR *) ((UINTN) FreeMemory + FreeMemory->Header.Length); 583 for (DescriptorIndex = 0; DescriptorIndex < FreeMemory->FreeMemoryEntryCount; DescriptorIndex++) { 584 Descriptor = DumpMemoryProfileDescriptor (DescriptorIndex, Descriptor); 585 if (Descriptor == NULL) { 586 return NULL; 587 } 588 } 589 590 return (VOID *) Descriptor; 591 } 592 593 /** 594 Dump memory profile memory range information. 595 596 @param[in] MemoryRange Pointer to memory profile memory range. 597 598 @return Pointer to the end of memory profile memory range buffer. 599 600 **/ 601 VOID * 602 DumpMemoryProfileMemoryRange ( 603 IN MEMORY_PROFILE_MEMORY_RANGE *MemoryRange 604 ) 605 { 606 MEMORY_PROFILE_DESCRIPTOR *Descriptor; 607 UINTN DescriptorIndex; 608 609 if (MemoryRange->Header.Signature != MEMORY_PROFILE_MEMORY_RANGE_SIGNATURE) { 610 return NULL; 611 } 612 Print (L"MEMORY_PROFILE_MEMORY_RANGE\n"); 613 Print (L" Signature - 0x%08x\n", MemoryRange->Header.Signature); 614 Print (L" Length - 0x%04x\n", MemoryRange->Header.Length); 615 Print (L" Revision - 0x%04x\n", MemoryRange->Header.Revision); 616 Print (L" MemoryRangeCount - 0x%08x\n", MemoryRange->MemoryRangeCount); 617 618 Descriptor = (MEMORY_PROFILE_DESCRIPTOR *) ((UINTN) MemoryRange + MemoryRange->Header.Length); 619 for (DescriptorIndex = 0; DescriptorIndex < MemoryRange->MemoryRangeCount; DescriptorIndex++) { 620 Descriptor = DumpMemoryProfileDescriptor (DescriptorIndex, Descriptor); 621 if (Descriptor == NULL) { 622 return NULL; 623 } 624 } 625 626 return (VOID *) Descriptor; 627 } 628 629 /** 630 Scan memory profile by Signature. 631 632 @param[in] ProfileBuffer Memory profile base address. 633 @param[in] ProfileSize Memory profile size. 634 @param[in] Signature Signature. 635 636 @return Pointer to the stucture with the signature. 637 638 **/ 639 VOID * 640 ScanMemoryProfileBySignature ( 641 IN PHYSICAL_ADDRESS ProfileBuffer, 642 IN UINT64 ProfileSize, 643 IN UINT32 Signature 644 ) 645 { 646 MEMORY_PROFILE_COMMON_HEADER *CommonHeader; 647 UINTN ProfileEnd; 648 649 ProfileEnd = (UINTN) (ProfileBuffer + ProfileSize); 650 CommonHeader = (MEMORY_PROFILE_COMMON_HEADER *) (UINTN) ProfileBuffer; 651 while ((UINTN) CommonHeader < ProfileEnd) { 652 if (CommonHeader->Signature == Signature) { 653 // 654 // Found it. 655 // 656 return (VOID *) CommonHeader; 657 } 658 if (CommonHeader->Length == 0) { 659 ASSERT (FALSE); 660 return NULL; 661 } 662 CommonHeader = (MEMORY_PROFILE_COMMON_HEADER *) ((UINTN) CommonHeader + CommonHeader->Length); 663 } 664 665 return NULL; 666 } 667 668 /** 669 Dump memory profile information. 670 671 @param[in] ProfileBuffer Memory profile base address. 672 @param[in] ProfileSize Memory profile size. 673 @param[in] IsForSmm TRUE - SMRAM profile. 674 FALSE - UEFI memory profile. 675 676 **/ 677 VOID 678 DumpMemoryProfile ( 679 IN PHYSICAL_ADDRESS ProfileBuffer, 680 IN UINT64 ProfileSize, 681 IN BOOLEAN IsForSmm 682 ) 683 { 684 MEMORY_PROFILE_CONTEXT *Context; 685 MEMORY_PROFILE_FREE_MEMORY *FreeMemory; 686 MEMORY_PROFILE_MEMORY_RANGE *MemoryRange; 687 688 Context = (MEMORY_PROFILE_CONTEXT *) ScanMemoryProfileBySignature (ProfileBuffer, ProfileSize, MEMORY_PROFILE_CONTEXT_SIGNATURE); 689 if (Context != NULL) { 690 DumpMemoryProfileContext (Context, IsForSmm); 691 } 692 693 FreeMemory = (MEMORY_PROFILE_FREE_MEMORY *) ScanMemoryProfileBySignature (ProfileBuffer, ProfileSize, MEMORY_PROFILE_FREE_MEMORY_SIGNATURE); 694 if (FreeMemory != NULL) { 695 DumpMemoryProfileFreeMemory (FreeMemory); 696 } 697 698 MemoryRange = (MEMORY_PROFILE_MEMORY_RANGE *) ScanMemoryProfileBySignature (ProfileBuffer, ProfileSize, MEMORY_PROFILE_MEMORY_RANGE_SIGNATURE); 699 if (MemoryRange != NULL) { 700 DumpMemoryProfileMemoryRange (MemoryRange); 701 } 702 } 703 704 /** 705 Get Allocate summary information structure by caller address. 706 707 @param[in] CallerAddress Caller address. 708 @param[in] DriverSummaryInfoData Driver summary information data structure. 709 710 @return Allocate summary information structure by caller address. 711 712 **/ 713 MEMORY_PROFILE_ALLOC_SUMMARY_INFO_DATA * 714 GetAllocSummaryInfoByCallerAddress ( 715 IN PHYSICAL_ADDRESS CallerAddress, 716 IN MEMORY_PROFILE_DRIVER_SUMMARY_INFO_DATA *DriverSummaryInfoData 717 ) 718 { 719 LIST_ENTRY *AllocSummaryInfoList; 720 LIST_ENTRY *AllocSummaryLink; 721 MEMORY_PROFILE_ALLOC_SUMMARY_INFO *AllocSummaryInfo; 722 MEMORY_PROFILE_ALLOC_SUMMARY_INFO_DATA *AllocSummaryInfoData; 723 724 AllocSummaryInfoList = DriverSummaryInfoData->AllocSummaryInfoList; 725 726 for (AllocSummaryLink = AllocSummaryInfoList->ForwardLink; 727 AllocSummaryLink != AllocSummaryInfoList; 728 AllocSummaryLink = AllocSummaryLink->ForwardLink) { 729 AllocSummaryInfoData = CR ( 730 AllocSummaryLink, 731 MEMORY_PROFILE_ALLOC_SUMMARY_INFO_DATA, 732 Link, 733 MEMORY_PROFILE_ALLOC_SUMMARY_INFO_SIGNATURE 734 ); 735 AllocSummaryInfo = &AllocSummaryInfoData->AllocSummaryInfo; 736 if (AllocSummaryInfo->CallerAddress == CallerAddress) { 737 return AllocSummaryInfoData; 738 } 739 } 740 return NULL; 741 } 742 743 /** 744 Create Allocate summary information structure and 745 link to Driver summary information data structure. 746 747 @param[in, out] DriverSummaryInfoData Driver summary information data structure. 748 @param[in] AllocInfo Pointer to memory profile alloc info. 749 750 @return Pointer to next memory profile alloc info. 751 752 **/ 753 MEMORY_PROFILE_ALLOC_INFO * 754 CreateAllocSummaryInfo ( 755 IN OUT MEMORY_PROFILE_DRIVER_SUMMARY_INFO_DATA *DriverSummaryInfoData, 756 IN MEMORY_PROFILE_ALLOC_INFO *AllocInfo 757 ) 758 { 759 MEMORY_PROFILE_ALLOC_SUMMARY_INFO_DATA *AllocSummaryInfoData; 760 MEMORY_PROFILE_ALLOC_SUMMARY_INFO *AllocSummaryInfo; 761 762 if (AllocInfo->Header.Signature != MEMORY_PROFILE_ALLOC_INFO_SIGNATURE) { 763 return NULL; 764 } 765 766 AllocSummaryInfoData = GetAllocSummaryInfoByCallerAddress (AllocInfo->CallerAddress, DriverSummaryInfoData); 767 if (AllocSummaryInfoData == NULL) { 768 AllocSummaryInfoData = AllocatePool (sizeof (*AllocSummaryInfoData)); 769 if (AllocSummaryInfoData == NULL) { 770 return NULL; 771 } 772 773 AllocSummaryInfoData->Signature = MEMORY_PROFILE_ALLOC_SUMMARY_INFO_SIGNATURE; 774 AllocSummaryInfo = &AllocSummaryInfoData->AllocSummaryInfo; 775 AllocSummaryInfo->Header.Signature = MEMORY_PROFILE_ALLOC_SUMMARY_INFO_SIGNATURE; 776 AllocSummaryInfo->Header.Length = sizeof (*AllocSummaryInfo); 777 AllocSummaryInfo->Header.Revision = MEMORY_PROFILE_ALLOC_SUMMARY_INFO_REVISION; 778 AllocSummaryInfo->CallerAddress = AllocInfo->CallerAddress; 779 AllocSummaryInfo->Action = AllocInfo->Action; 780 if (AllocInfo->ActionStringOffset != 0) { 781 AllocSummaryInfo->ActionString = (CHAR8 *) ((UINTN) AllocInfo + AllocInfo->ActionStringOffset); 782 } else { 783 AllocSummaryInfo->ActionString = NULL; 784 } 785 AllocSummaryInfo->AllocateCount = 0; 786 AllocSummaryInfo->TotalSize = 0; 787 InsertTailList (DriverSummaryInfoData->AllocSummaryInfoList, &AllocSummaryInfoData->Link); 788 } 789 AllocSummaryInfo = &AllocSummaryInfoData->AllocSummaryInfo; 790 AllocSummaryInfo->AllocateCount ++; 791 AllocSummaryInfo->TotalSize += AllocInfo->Size; 792 793 return (MEMORY_PROFILE_ALLOC_INFO *) ((UINTN) AllocInfo + AllocInfo->Header.Length); 794 } 795 796 /** 797 Create Driver summary information structure and 798 link to Context summary information data structure. 799 800 @param[in, out] ContextSummaryData Context summary information data structure. 801 @param[in] DriverInfo Pointer to memory profile driver info. 802 803 @return Pointer to next memory profile driver info. 804 805 **/ 806 MEMORY_PROFILE_DRIVER_INFO * 807 CreateDriverSummaryInfo ( 808 IN OUT MEMORY_PROFILE_CONTEXT_SUMMARY_DATA *ContextSummaryData, 809 IN MEMORY_PROFILE_DRIVER_INFO *DriverInfo 810 ) 811 { 812 MEMORY_PROFILE_DRIVER_SUMMARY_INFO_DATA *DriverSummaryInfoData; 813 MEMORY_PROFILE_ALLOC_INFO *AllocInfo; 814 UINTN AllocIndex; 815 816 if (DriverInfo->Header.Signature != MEMORY_PROFILE_DRIVER_INFO_SIGNATURE) { 817 return NULL; 818 } 819 820 DriverSummaryInfoData = AllocatePool (sizeof (*DriverSummaryInfoData) + sizeof (LIST_ENTRY)); 821 if (DriverSummaryInfoData == NULL) { 822 return NULL; 823 } 824 DriverSummaryInfoData->Signature = MEMORY_PROFILE_DRIVER_INFO_SIGNATURE; 825 DriverSummaryInfoData->DriverInfo = DriverInfo; 826 DriverSummaryInfoData->AllocSummaryInfoList = (LIST_ENTRY *) (DriverSummaryInfoData + 1); 827 InitializeListHead (DriverSummaryInfoData->AllocSummaryInfoList); 828 InsertTailList (ContextSummaryData->DriverSummaryInfoList, &DriverSummaryInfoData->Link); 829 830 AllocInfo = (MEMORY_PROFILE_ALLOC_INFO *) ((UINTN) DriverInfo + DriverInfo->Header.Length); 831 for (AllocIndex = 0; AllocIndex < DriverInfo->AllocRecordCount; AllocIndex++) { 832 AllocInfo = CreateAllocSummaryInfo (DriverSummaryInfoData, AllocInfo); 833 if (AllocInfo == NULL) { 834 return NULL; 835 } 836 } 837 return (MEMORY_PROFILE_DRIVER_INFO *) AllocInfo; 838 } 839 840 /** 841 Create Context summary information structure. 842 843 @param[in] ProfileBuffer Memory profile base address. 844 @param[in] ProfileSize Memory profile size. 845 846 @return Context summary information structure. 847 848 **/ 849 MEMORY_PROFILE_CONTEXT_SUMMARY_DATA * 850 CreateContextSummaryData ( 851 IN PHYSICAL_ADDRESS ProfileBuffer, 852 IN UINT64 ProfileSize 853 ) 854 { 855 MEMORY_PROFILE_CONTEXT *Context; 856 MEMORY_PROFILE_DRIVER_INFO *DriverInfo; 857 UINTN DriverIndex; 858 859 Context = (MEMORY_PROFILE_CONTEXT *) ScanMemoryProfileBySignature (ProfileBuffer, ProfileSize, MEMORY_PROFILE_CONTEXT_SIGNATURE); 860 if (Context == NULL) { 861 return NULL; 862 } 863 864 mMemoryProfileContextSummary.Signature = MEMORY_PROFILE_CONTEXT_SIGNATURE; 865 mMemoryProfileContextSummary.Context = Context; 866 mMemoryProfileContextSummary.DriverSummaryInfoList = &mImageSummaryQueue; 867 868 DriverInfo = (MEMORY_PROFILE_DRIVER_INFO *) ((UINTN) Context + Context->Header.Length); 869 for (DriverIndex = 0; DriverIndex < Context->ImageCount; DriverIndex++) { 870 DriverInfo = CreateDriverSummaryInfo (&mMemoryProfileContextSummary, DriverInfo); 871 if (DriverInfo == NULL) { 872 return NULL; 873 } 874 } 875 876 return &mMemoryProfileContextSummary; 877 } 878 879 /** 880 Dump Context summary information. 881 882 @param[in] ContextSummaryData Context summary information data. 883 @param[in] IsForSmm TRUE - SMRAM profile. 884 FALSE - UEFI memory profile. 885 886 **/ 887 VOID 888 DumpContextSummaryData ( 889 IN MEMORY_PROFILE_CONTEXT_SUMMARY_DATA *ContextSummaryData, 890 IN BOOLEAN IsForSmm 891 ) 892 { 893 MEMORY_PROFILE_DRIVER_SUMMARY_INFO_DATA *DriverSummaryInfoData; 894 MEMORY_PROFILE_ALLOC_SUMMARY_INFO_DATA *AllocSummaryInfoData; 895 LIST_ENTRY *DriverSummaryInfoList; 896 LIST_ENTRY *DriverSummaryLink; 897 LIST_ENTRY *AllocSummaryInfoList; 898 LIST_ENTRY *AllocSummaryLink; 899 MEMORY_PROFILE_DRIVER_INFO *DriverInfo; 900 MEMORY_PROFILE_ALLOC_SUMMARY_INFO *AllocSummaryInfo; 901 CHAR8 *NameString; 902 903 if (ContextSummaryData == NULL) { 904 return ; 905 } 906 907 Print (L"\nSummary Data:\n"); 908 909 DriverSummaryInfoList = ContextSummaryData->DriverSummaryInfoList; 910 for (DriverSummaryLink = DriverSummaryInfoList->ForwardLink; 911 DriverSummaryLink != DriverSummaryInfoList; 912 DriverSummaryLink = DriverSummaryLink->ForwardLink) { 913 DriverSummaryInfoData = CR ( 914 DriverSummaryLink, 915 MEMORY_PROFILE_DRIVER_SUMMARY_INFO_DATA, 916 Link, 917 MEMORY_PROFILE_DRIVER_INFO_SIGNATURE 918 ); 919 DriverInfo = DriverSummaryInfoData->DriverInfo; 920 921 NameString = GetDriverNameString (DriverInfo); 922 Print (L"\nDriver - %a (Usage - 0x%08x)", NameString, DriverInfo->CurrentUsage); 923 if (DriverInfo->CurrentUsage == 0) { 924 Print (L"\n"); 925 continue; 926 } 927 928 if (DriverInfo->PdbStringOffset != 0) { 929 Print (L" (Pdb - %a)\n", (CHAR8 *) ((UINTN) DriverInfo + DriverInfo->PdbStringOffset)); 930 } else { 931 Print (L"\n"); 932 } 933 Print (L"Caller List:\n"); 934 Print(L" Count Size RVA Action\n"); 935 Print(L"========== ================== ================== (================================)\n"); 936 AllocSummaryInfoList = DriverSummaryInfoData->AllocSummaryInfoList; 937 for (AllocSummaryLink = AllocSummaryInfoList->ForwardLink; 938 AllocSummaryLink != AllocSummaryInfoList; 939 AllocSummaryLink = AllocSummaryLink->ForwardLink) { 940 AllocSummaryInfoData = CR ( 941 AllocSummaryLink, 942 MEMORY_PROFILE_ALLOC_SUMMARY_INFO_DATA, 943 Link, 944 MEMORY_PROFILE_ALLOC_SUMMARY_INFO_SIGNATURE 945 ); 946 AllocSummaryInfo = &AllocSummaryInfoData->AllocSummaryInfo; 947 948 Print(L"0x%08x 0x%016lx <== 0x%016lx", 949 AllocSummaryInfo->AllocateCount, 950 AllocSummaryInfo->TotalSize, 951 AllocSummaryInfo->CallerAddress - DriverInfo->ImageBase 952 ); 953 Print (L" (%a)\n", ProfileActionToStr (AllocSummaryInfo->Action, AllocSummaryInfo->ActionString, IsForSmm)); 954 } 955 } 956 return ; 957 } 958 959 /** 960 Destroy Context summary information. 961 962 @param[in, out] ContextSummaryData Context summary information data. 963 964 **/ 965 VOID 966 DestroyContextSummaryData ( 967 IN OUT MEMORY_PROFILE_CONTEXT_SUMMARY_DATA *ContextSummaryData 968 ) 969 { 970 MEMORY_PROFILE_DRIVER_SUMMARY_INFO_DATA *DriverSummaryInfoData; 971 MEMORY_PROFILE_ALLOC_SUMMARY_INFO_DATA *AllocSummaryInfoData; 972 LIST_ENTRY *DriverSummaryInfoList; 973 LIST_ENTRY *DriverSummaryLink; 974 LIST_ENTRY *AllocSummaryInfoList; 975 LIST_ENTRY *AllocSummaryLink; 976 977 if (ContextSummaryData == NULL) { 978 return ; 979 } 980 981 DriverSummaryInfoList = ContextSummaryData->DriverSummaryInfoList; 982 for (DriverSummaryLink = DriverSummaryInfoList->ForwardLink; 983 DriverSummaryLink != DriverSummaryInfoList; 984 ) { 985 DriverSummaryInfoData = CR ( 986 DriverSummaryLink, 987 MEMORY_PROFILE_DRIVER_SUMMARY_INFO_DATA, 988 Link, 989 MEMORY_PROFILE_DRIVER_INFO_SIGNATURE 990 ); 991 DriverSummaryLink = DriverSummaryLink->ForwardLink; 992 993 AllocSummaryInfoList = DriverSummaryInfoData->AllocSummaryInfoList; 994 for (AllocSummaryLink = AllocSummaryInfoList->ForwardLink; 995 AllocSummaryLink != AllocSummaryInfoList; 996 ) { 997 AllocSummaryInfoData = CR ( 998 AllocSummaryLink, 999 MEMORY_PROFILE_ALLOC_SUMMARY_INFO_DATA, 1000 Link, 1001 MEMORY_PROFILE_ALLOC_SUMMARY_INFO_SIGNATURE 1002 ); 1003 AllocSummaryLink = AllocSummaryLink->ForwardLink; 1004 1005 RemoveEntryList (&AllocSummaryInfoData->Link); 1006 FreePool (AllocSummaryInfoData); 1007 } 1008 1009 RemoveEntryList (&DriverSummaryInfoData->Link); 1010 FreePool (DriverSummaryInfoData); 1011 } 1012 return ; 1013 } 1014 1015 /** 1016 Get and dump UEFI memory profile data. 1017 1018 @return EFI_SUCCESS Get the memory profile data successfully. 1019 @return other Fail to get the memory profile data. 1020 1021 **/ 1022 EFI_STATUS 1023 GetUefiMemoryProfileData ( 1024 VOID 1025 ) 1026 { 1027 EFI_STATUS Status; 1028 EDKII_MEMORY_PROFILE_PROTOCOL *ProfileProtocol; 1029 VOID *Data; 1030 UINT64 Size; 1031 MEMORY_PROFILE_CONTEXT_SUMMARY_DATA *MemoryProfileContextSummaryData; 1032 BOOLEAN RecordingState; 1033 1034 Status = gBS->LocateProtocol (&gEdkiiMemoryProfileGuid, NULL, (VOID **) &ProfileProtocol); 1035 if (EFI_ERROR (Status)) { 1036 DEBUG ((EFI_D_ERROR, "UefiMemoryProfile: Locate MemoryProfile protocol - %r\n", Status)); 1037 return Status; 1038 } 1039 1040 // 1041 // Set recording state if needed. 1042 // 1043 RecordingState = MEMORY_PROFILE_RECORDING_DISABLE; 1044 Status = ProfileProtocol->GetRecordingState (ProfileProtocol, &RecordingState); 1045 if (RecordingState == MEMORY_PROFILE_RECORDING_ENABLE) { 1046 ProfileProtocol->SetRecordingState (ProfileProtocol, MEMORY_PROFILE_RECORDING_DISABLE); 1047 } 1048 1049 Size = 0; 1050 Data = NULL; 1051 Status = ProfileProtocol->GetData ( 1052 ProfileProtocol, 1053 &Size, 1054 Data 1055 ); 1056 if (Status != EFI_BUFFER_TOO_SMALL) { 1057 Print (L"UefiMemoryProfile: GetData - %r\n", Status); 1058 goto Done; 1059 } 1060 1061 Data = AllocateZeroPool ((UINTN) Size); 1062 if (Data == NULL) { 1063 Status = EFI_OUT_OF_RESOURCES; 1064 Print (L"UefiMemoryProfile: AllocateZeroPool (0x%x) - %r\n", Size, Status); 1065 return Status; 1066 } 1067 1068 Status = ProfileProtocol->GetData ( 1069 ProfileProtocol, 1070 &Size, 1071 Data 1072 ); 1073 if (EFI_ERROR (Status)) { 1074 Print (L"UefiMemoryProfile: GetData - %r\n", Status); 1075 goto Done; 1076 } 1077 1078 1079 Print (L"UefiMemoryProfileSize - 0x%x\n", Size); 1080 Print (L"======= UefiMemoryProfile begin =======\n"); 1081 DumpMemoryProfile ((PHYSICAL_ADDRESS) (UINTN) Data, Size, FALSE); 1082 1083 // 1084 // Dump summary information 1085 // 1086 MemoryProfileContextSummaryData = CreateContextSummaryData ((PHYSICAL_ADDRESS) (UINTN) Data, Size); 1087 if (MemoryProfileContextSummaryData != NULL) { 1088 DumpContextSummaryData (MemoryProfileContextSummaryData, FALSE); 1089 DestroyContextSummaryData (MemoryProfileContextSummaryData); 1090 } 1091 1092 Print (L"======= UefiMemoryProfile end =======\n\n\n"); 1093 1094 Done: 1095 if (Data != NULL) { 1096 FreePool (Data); 1097 } 1098 1099 // 1100 // Restore recording state if needed. 1101 // 1102 if (RecordingState == MEMORY_PROFILE_RECORDING_ENABLE) { 1103 ProfileProtocol->SetRecordingState (ProfileProtocol, MEMORY_PROFILE_RECORDING_ENABLE); 1104 } 1105 1106 return Status; 1107 } 1108 1109 /** 1110 Get and dump SMRAM profile data. 1111 1112 @return EFI_SUCCESS Get the SMRAM profile data successfully. 1113 @return other Fail to get the SMRAM profile data. 1114 1115 **/ 1116 EFI_STATUS 1117 GetSmramProfileData ( 1118 VOID 1119 ) 1120 { 1121 EFI_STATUS Status; 1122 UINTN CommSize; 1123 UINT8 *CommBuffer; 1124 EFI_SMM_COMMUNICATE_HEADER *CommHeader; 1125 SMRAM_PROFILE_PARAMETER_GET_PROFILE_INFO *CommGetProfileInfo; 1126 SMRAM_PROFILE_PARAMETER_GET_PROFILE_DATA_BY_OFFSET *CommGetProfileData; 1127 SMRAM_PROFILE_PARAMETER_RECORDING_STATE *CommRecordingState; 1128 UINTN ProfileSize; 1129 VOID *ProfileBuffer; 1130 EFI_SMM_COMMUNICATION_PROTOCOL *SmmCommunication; 1131 UINTN MinimalSizeNeeded; 1132 EDKII_PI_SMM_COMMUNICATION_REGION_TABLE *PiSmmCommunicationRegionTable; 1133 UINT32 Index; 1134 EFI_MEMORY_DESCRIPTOR *Entry; 1135 VOID *Buffer; 1136 UINTN Size; 1137 UINTN Offset; 1138 MEMORY_PROFILE_CONTEXT_SUMMARY_DATA *MemoryProfileContextSummaryData; 1139 BOOLEAN RecordingState; 1140 1141 ProfileBuffer = NULL; 1142 1143 Status = gBS->LocateProtocol (&gEfiSmmCommunicationProtocolGuid, NULL, (VOID **) &SmmCommunication); 1144 if (EFI_ERROR (Status)) { 1145 DEBUG ((EFI_D_ERROR, "SmramProfile: Locate SmmCommunication protocol - %r\n", Status)); 1146 return Status; 1147 } 1148 1149 MinimalSizeNeeded = sizeof (EFI_GUID) + 1150 sizeof (UINTN) + 1151 MAX (sizeof (SMRAM_PROFILE_PARAMETER_GET_PROFILE_INFO), 1152 MAX (sizeof (SMRAM_PROFILE_PARAMETER_GET_PROFILE_DATA_BY_OFFSET), 1153 sizeof (SMRAM_PROFILE_PARAMETER_RECORDING_STATE))); 1154 MinimalSizeNeeded += MAX (sizeof (MEMORY_PROFILE_CONTEXT), 1155 MAX (sizeof (MEMORY_PROFILE_DRIVER_INFO), 1156 MAX (sizeof (MEMORY_PROFILE_ALLOC_INFO), 1157 MAX (sizeof (MEMORY_PROFILE_DESCRIPTOR), 1158 MAX (sizeof (MEMORY_PROFILE_FREE_MEMORY), 1159 sizeof (MEMORY_PROFILE_MEMORY_RANGE)))))); 1160 1161 Status = EfiGetSystemConfigurationTable ( 1162 &gEdkiiPiSmmCommunicationRegionTableGuid, 1163 (VOID **) &PiSmmCommunicationRegionTable 1164 ); 1165 if (EFI_ERROR (Status)) { 1166 DEBUG ((EFI_D_ERROR, "SmramProfile: Get PiSmmCommunicationRegionTable - %r\n", Status)); 1167 return Status; 1168 } 1169 ASSERT (PiSmmCommunicationRegionTable != NULL); 1170 Entry = (EFI_MEMORY_DESCRIPTOR *) (PiSmmCommunicationRegionTable + 1); 1171 Size = 0; 1172 for (Index = 0; Index < PiSmmCommunicationRegionTable->NumberOfEntries; Index++) { 1173 if (Entry->Type == EfiConventionalMemory) { 1174 Size = EFI_PAGES_TO_SIZE ((UINTN) Entry->NumberOfPages); 1175 if (Size >= MinimalSizeNeeded) { 1176 break; 1177 } 1178 } 1179 Entry = (EFI_MEMORY_DESCRIPTOR *) ((UINT8 *) Entry + PiSmmCommunicationRegionTable->DescriptorSize); 1180 } 1181 ASSERT (Index < PiSmmCommunicationRegionTable->NumberOfEntries); 1182 CommBuffer = (UINT8 *) (UINTN) Entry->PhysicalStart; 1183 1184 // 1185 // Set recording state if needed. 1186 // 1187 RecordingState = MEMORY_PROFILE_RECORDING_DISABLE; 1188 1189 CommHeader = (EFI_SMM_COMMUNICATE_HEADER *) &CommBuffer[0]; 1190 CopyMem (&CommHeader->HeaderGuid, &gEdkiiMemoryProfileGuid, sizeof (gEdkiiMemoryProfileGuid)); 1191 CommHeader->MessageLength = sizeof (SMRAM_PROFILE_PARAMETER_RECORDING_STATE); 1192 1193 CommRecordingState = (SMRAM_PROFILE_PARAMETER_RECORDING_STATE *) &CommBuffer[OFFSET_OF (EFI_SMM_COMMUNICATE_HEADER, Data)]; 1194 CommRecordingState->Header.Command = SMRAM_PROFILE_COMMAND_GET_RECORDING_STATE; 1195 CommRecordingState->Header.DataLength = sizeof (*CommRecordingState); 1196 CommRecordingState->Header.ReturnStatus = (UINT64)-1; 1197 CommRecordingState->RecordingState = MEMORY_PROFILE_RECORDING_DISABLE; 1198 1199 CommSize = sizeof (EFI_GUID) + sizeof (UINTN) + CommHeader->MessageLength; 1200 Status = SmmCommunication->Communicate (SmmCommunication, CommBuffer, &CommSize); 1201 if (EFI_ERROR (Status)) { 1202 DEBUG ((EFI_D_ERROR, "SmramProfile: SmmCommunication - %r\n", Status)); 1203 return Status; 1204 } 1205 1206 if (CommRecordingState->Header.ReturnStatus != 0) { 1207 Print (L"SmramProfile: GetRecordingState - 0x%0x\n", CommRecordingState->Header.ReturnStatus); 1208 return EFI_SUCCESS; 1209 } 1210 RecordingState = CommRecordingState->RecordingState; 1211 if (RecordingState == MEMORY_PROFILE_RECORDING_ENABLE) { 1212 CommHeader = (EFI_SMM_COMMUNICATE_HEADER *) &CommBuffer[0]; 1213 CopyMem (&CommHeader->HeaderGuid, &gEdkiiMemoryProfileGuid, sizeof (gEdkiiMemoryProfileGuid)); 1214 CommHeader->MessageLength = sizeof (SMRAM_PROFILE_PARAMETER_RECORDING_STATE); 1215 1216 CommRecordingState = (SMRAM_PROFILE_PARAMETER_RECORDING_STATE *) &CommBuffer[OFFSET_OF (EFI_SMM_COMMUNICATE_HEADER, Data)]; 1217 CommRecordingState->Header.Command = SMRAM_PROFILE_COMMAND_SET_RECORDING_STATE; 1218 CommRecordingState->Header.DataLength = sizeof (*CommRecordingState); 1219 CommRecordingState->Header.ReturnStatus = (UINT64)-1; 1220 CommRecordingState->RecordingState = MEMORY_PROFILE_RECORDING_DISABLE; 1221 1222 CommSize = sizeof (EFI_GUID) + sizeof (UINTN) + CommHeader->MessageLength; 1223 SmmCommunication->Communicate (SmmCommunication, CommBuffer, &CommSize); 1224 } 1225 1226 // 1227 // Get Size 1228 // 1229 CommHeader = (EFI_SMM_COMMUNICATE_HEADER *) &CommBuffer[0]; 1230 CopyMem (&CommHeader->HeaderGuid, &gEdkiiMemoryProfileGuid, sizeof (gEdkiiMemoryProfileGuid)); 1231 CommHeader->MessageLength = sizeof (SMRAM_PROFILE_PARAMETER_GET_PROFILE_INFO); 1232 1233 CommGetProfileInfo = (SMRAM_PROFILE_PARAMETER_GET_PROFILE_INFO *) &CommBuffer[OFFSET_OF (EFI_SMM_COMMUNICATE_HEADER, Data)]; 1234 CommGetProfileInfo->Header.Command = SMRAM_PROFILE_COMMAND_GET_PROFILE_INFO; 1235 CommGetProfileInfo->Header.DataLength = sizeof (*CommGetProfileInfo); 1236 CommGetProfileInfo->Header.ReturnStatus = (UINT64)-1; 1237 CommGetProfileInfo->ProfileSize = 0; 1238 1239 CommSize = sizeof (EFI_GUID) + sizeof (UINTN) + CommHeader->MessageLength; 1240 Status = SmmCommunication->Communicate (SmmCommunication, CommBuffer, &CommSize); 1241 ASSERT_EFI_ERROR (Status); 1242 1243 if (CommGetProfileInfo->Header.ReturnStatus != 0) { 1244 Status = EFI_SUCCESS; 1245 Print (L"SmramProfile: GetProfileInfo - 0x%0x\n", CommGetProfileInfo->Header.ReturnStatus); 1246 goto Done; 1247 } 1248 1249 ProfileSize = (UINTN) CommGetProfileInfo->ProfileSize; 1250 1251 // 1252 // Get Data 1253 // 1254 ProfileBuffer = AllocateZeroPool (ProfileSize); 1255 if (ProfileBuffer == NULL) { 1256 Status = EFI_OUT_OF_RESOURCES; 1257 Print (L"SmramProfile: AllocateZeroPool (0x%x) for profile buffer - %r\n", ProfileSize, Status); 1258 goto Done; 1259 } 1260 1261 CommHeader = (EFI_SMM_COMMUNICATE_HEADER *) &CommBuffer[0]; 1262 CopyMem (&CommHeader->HeaderGuid, &gEdkiiMemoryProfileGuid, sizeof(gEdkiiMemoryProfileGuid)); 1263 CommHeader->MessageLength = sizeof (SMRAM_PROFILE_PARAMETER_GET_PROFILE_DATA_BY_OFFSET); 1264 1265 CommGetProfileData = (SMRAM_PROFILE_PARAMETER_GET_PROFILE_DATA_BY_OFFSET *) &CommBuffer[OFFSET_OF (EFI_SMM_COMMUNICATE_HEADER, Data)]; 1266 CommGetProfileData->Header.Command = SMRAM_PROFILE_COMMAND_GET_PROFILE_DATA_BY_OFFSET; 1267 CommGetProfileData->Header.DataLength = sizeof (*CommGetProfileData); 1268 CommGetProfileData->Header.ReturnStatus = (UINT64)-1; 1269 1270 CommSize = sizeof (EFI_GUID) + sizeof (UINTN) + CommHeader->MessageLength; 1271 Buffer = (UINT8 *) CommHeader + CommSize; 1272 Size -= CommSize; 1273 1274 CommGetProfileData->ProfileBuffer = (PHYSICAL_ADDRESS) (UINTN) Buffer; 1275 CommGetProfileData->ProfileOffset = 0; 1276 while (CommGetProfileData->ProfileOffset < ProfileSize) { 1277 Offset = (UINTN) CommGetProfileData->ProfileOffset; 1278 if (Size <= (ProfileSize - CommGetProfileData->ProfileOffset)) { 1279 CommGetProfileData->ProfileSize = (UINT64) Size; 1280 } else { 1281 CommGetProfileData->ProfileSize = (UINT64) (ProfileSize - CommGetProfileData->ProfileOffset); 1282 } 1283 Status = SmmCommunication->Communicate (SmmCommunication, CommBuffer, &CommSize); 1284 ASSERT_EFI_ERROR (Status); 1285 1286 if (CommGetProfileData->Header.ReturnStatus != 0) { 1287 Status = EFI_SUCCESS; 1288 Print (L"GetProfileData - 0x%x\n", CommGetProfileData->Header.ReturnStatus); 1289 goto Done; 1290 } 1291 CopyMem ((UINT8 *) ProfileBuffer + Offset, (VOID *) (UINTN) CommGetProfileData->ProfileBuffer, (UINTN) CommGetProfileData->ProfileSize); 1292 } 1293 1294 1295 Print (L"SmramProfileSize - 0x%x\n", ProfileSize); 1296 Print (L"======= SmramProfile begin =======\n"); 1297 DumpMemoryProfile ((PHYSICAL_ADDRESS) (UINTN) ProfileBuffer, ProfileSize, TRUE); 1298 1299 // 1300 // Dump summary information 1301 // 1302 MemoryProfileContextSummaryData = CreateContextSummaryData ((PHYSICAL_ADDRESS) (UINTN) ProfileBuffer, ProfileSize); 1303 if (MemoryProfileContextSummaryData != NULL) { 1304 DumpContextSummaryData (MemoryProfileContextSummaryData, TRUE); 1305 DestroyContextSummaryData (MemoryProfileContextSummaryData); 1306 } 1307 1308 Print (L"======= SmramProfile end =======\n\n\n"); 1309 1310 Done: 1311 if (ProfileBuffer != NULL) { 1312 FreePool (ProfileBuffer); 1313 } 1314 1315 // 1316 // Restore recording state if needed. 1317 // 1318 if (RecordingState == MEMORY_PROFILE_RECORDING_ENABLE) { 1319 CommHeader = (EFI_SMM_COMMUNICATE_HEADER *) &CommBuffer[0]; 1320 CopyMem (&CommHeader->HeaderGuid, &gEdkiiMemoryProfileGuid, sizeof (gEdkiiMemoryProfileGuid)); 1321 CommHeader->MessageLength = sizeof (SMRAM_PROFILE_PARAMETER_RECORDING_STATE); 1322 1323 CommRecordingState = (SMRAM_PROFILE_PARAMETER_RECORDING_STATE *) &CommBuffer[OFFSET_OF (EFI_SMM_COMMUNICATE_HEADER, Data)]; 1324 CommRecordingState->Header.Command = SMRAM_PROFILE_COMMAND_SET_RECORDING_STATE; 1325 CommRecordingState->Header.DataLength = sizeof (*CommRecordingState); 1326 CommRecordingState->Header.ReturnStatus = (UINT64)-1; 1327 CommRecordingState->RecordingState = MEMORY_PROFILE_RECORDING_ENABLE; 1328 1329 CommSize = sizeof (EFI_GUID) + sizeof (UINTN) + CommHeader->MessageLength; 1330 SmmCommunication->Communicate (SmmCommunication, CommBuffer, &CommSize); 1331 } 1332 1333 return Status; 1334 } 1335 1336 /** 1337 The user Entry Point for Application. The user code starts with this function 1338 as the real entry point for the image goes into a library that calls this function. 1339 1340 @param[in] ImageHandle The firmware allocated handle for the EFI image. 1341 @param[in] SystemTable A pointer to the EFI System Table. 1342 1343 @retval EFI_SUCCESS The entry point is executed successfully. 1344 @retval other Some error occurs when executing this entry point. 1345 1346 **/ 1347 EFI_STATUS 1348 EFIAPI 1349 UefiMain ( 1350 IN EFI_HANDLE ImageHandle, 1351 IN EFI_SYSTEM_TABLE *SystemTable 1352 ) 1353 { 1354 EFI_STATUS Status; 1355 1356 Status = GetUefiMemoryProfileData (); 1357 if (EFI_ERROR (Status)) { 1358 DEBUG ((EFI_D_ERROR, "GetUefiMemoryProfileData - %r\n", Status)); 1359 } 1360 1361 Status = GetSmramProfileData (); 1362 if (EFI_ERROR (Status)) { 1363 DEBUG ((EFI_D_ERROR, "GetSmramProfileData - %r\n", Status)); 1364 } 1365 1366 return EFI_SUCCESS; 1367 } 1368