1 /** @file 2 Support routines for UEFI memory profile. 3 4 Copyright (c) 2014 - 2016, Intel Corporation. All rights reserved.<BR> 5 This program and the accompanying materials 6 are licensed and made available under the terms and conditions of the BSD License 7 which accompanies this distribution. The full text of the license may be found at 8 http://opensource.org/licenses/bsd-license.php. 9 10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, 11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. 12 13 **/ 14 15 #include "DxeMain.h" 16 #include "Imem.h" 17 18 #define IS_UEFI_MEMORY_PROFILE_ENABLED ((PcdGet8 (PcdMemoryProfilePropertyMask) & BIT0) != 0) 19 20 #define GET_OCCUPIED_SIZE(ActualSize, Alignment) \ 21 ((ActualSize) + (((Alignment) - ((ActualSize) & ((Alignment) - 1))) & ((Alignment) - 1))) 22 23 typedef struct { 24 UINT32 Signature; 25 MEMORY_PROFILE_CONTEXT Context; 26 LIST_ENTRY *DriverInfoList; 27 } MEMORY_PROFILE_CONTEXT_DATA; 28 29 typedef struct { 30 UINT32 Signature; 31 MEMORY_PROFILE_DRIVER_INFO DriverInfo; 32 LIST_ENTRY *AllocInfoList; 33 CHAR8 *PdbString; 34 LIST_ENTRY Link; 35 } MEMORY_PROFILE_DRIVER_INFO_DATA; 36 37 typedef struct { 38 UINT32 Signature; 39 MEMORY_PROFILE_ALLOC_INFO AllocInfo; 40 CHAR8 *ActionString; 41 LIST_ENTRY Link; 42 } MEMORY_PROFILE_ALLOC_INFO_DATA; 43 44 45 GLOBAL_REMOVE_IF_UNREFERENCED LIST_ENTRY mImageQueue = INITIALIZE_LIST_HEAD_VARIABLE (mImageQueue); 46 GLOBAL_REMOVE_IF_UNREFERENCED MEMORY_PROFILE_CONTEXT_DATA mMemoryProfileContext = { 47 MEMORY_PROFILE_CONTEXT_SIGNATURE, 48 { 49 { 50 MEMORY_PROFILE_CONTEXT_SIGNATURE, 51 sizeof (MEMORY_PROFILE_CONTEXT), 52 MEMORY_PROFILE_CONTEXT_REVISION 53 }, 54 0, 55 0, 56 {0}, 57 {0}, 58 0, 59 0, 60 0 61 }, 62 &mImageQueue, 63 }; 64 GLOBAL_REMOVE_IF_UNREFERENCED MEMORY_PROFILE_CONTEXT_DATA *mMemoryProfileContextPtr = NULL; 65 66 EFI_LOCK mMemoryProfileLock = EFI_INITIALIZE_LOCK_VARIABLE (TPL_NOTIFY); 67 BOOLEAN mMemoryProfileGettingStatus = FALSE; 68 BOOLEAN mMemoryProfileRecordingEnable = MEMORY_PROFILE_RECORDING_DISABLE; 69 EFI_DEVICE_PATH_PROTOCOL *mMemoryProfileDriverPath; 70 UINTN mMemoryProfileDriverPathSize; 71 72 /** 73 Get memory profile data. 74 75 @param[in] This The EDKII_MEMORY_PROFILE_PROTOCOL instance. 76 @param[in, out] ProfileSize On entry, points to the size in bytes of the ProfileBuffer. 77 On return, points to the size of the data returned in ProfileBuffer. 78 @param[out] ProfileBuffer Profile buffer. 79 80 @return EFI_SUCCESS Get the memory profile data successfully. 81 @return EFI_UNSUPPORTED Memory profile is unsupported. 82 @return EFI_BUFFER_TO_SMALL The ProfileSize is too small for the resulting data. 83 ProfileSize is updated with the size required. 84 85 **/ 86 EFI_STATUS 87 EFIAPI 88 ProfileProtocolGetData ( 89 IN EDKII_MEMORY_PROFILE_PROTOCOL *This, 90 IN OUT UINT64 *ProfileSize, 91 OUT VOID *ProfileBuffer 92 ); 93 94 /** 95 Register image to memory profile. 96 97 @param[in] This The EDKII_MEMORY_PROFILE_PROTOCOL instance. 98 @param[in] FilePath File path of the image. 99 @param[in] ImageBase Image base address. 100 @param[in] ImageSize Image size. 101 @param[in] FileType File type of the image. 102 103 @return EFI_SUCCESS Register successfully. 104 @return EFI_UNSUPPORTED Memory profile is unsupported, 105 or memory profile for the image is not required. 106 @return EFI_OUT_OF_RESOURCE No enough resource for this register. 107 108 **/ 109 EFI_STATUS 110 EFIAPI 111 ProfileProtocolRegisterImage ( 112 IN EDKII_MEMORY_PROFILE_PROTOCOL *This, 113 IN EFI_DEVICE_PATH_PROTOCOL *FilePath, 114 IN PHYSICAL_ADDRESS ImageBase, 115 IN UINT64 ImageSize, 116 IN EFI_FV_FILETYPE FileType 117 ); 118 119 /** 120 Unregister image from memory profile. 121 122 @param[in] This The EDKII_MEMORY_PROFILE_PROTOCOL instance. 123 @param[in] FilePath File path of the image. 124 @param[in] ImageBase Image base address. 125 @param[in] ImageSize Image size. 126 127 @return EFI_SUCCESS Unregister successfully. 128 @return EFI_UNSUPPORTED Memory profile is unsupported, 129 or memory profile for the image is not required. 130 @return EFI_NOT_FOUND The image is not found. 131 132 **/ 133 EFI_STATUS 134 EFIAPI 135 ProfileProtocolUnregisterImage ( 136 IN EDKII_MEMORY_PROFILE_PROTOCOL *This, 137 IN EFI_DEVICE_PATH_PROTOCOL *FilePath, 138 IN PHYSICAL_ADDRESS ImageBase, 139 IN UINT64 ImageSize 140 ); 141 142 /** 143 Get memory profile recording state. 144 145 @param[in] This The EDKII_MEMORY_PROFILE_PROTOCOL instance. 146 @param[out] RecordingState Recording state. 147 148 @return EFI_SUCCESS Memory profile recording state is returned. 149 @return EFI_UNSUPPORTED Memory profile is unsupported. 150 @return EFI_INVALID_PARAMETER RecordingState is NULL. 151 152 **/ 153 EFI_STATUS 154 EFIAPI 155 ProfileProtocolGetRecordingState ( 156 IN EDKII_MEMORY_PROFILE_PROTOCOL *This, 157 OUT BOOLEAN *RecordingState 158 ); 159 160 /** 161 Set memory profile recording state. 162 163 @param[in] This The EDKII_MEMORY_PROFILE_PROTOCOL instance. 164 @param[in] RecordingState Recording state. 165 166 @return EFI_SUCCESS Set memory profile recording state successfully. 167 @return EFI_UNSUPPORTED Memory profile is unsupported. 168 169 **/ 170 EFI_STATUS 171 EFIAPI 172 ProfileProtocolSetRecordingState ( 173 IN EDKII_MEMORY_PROFILE_PROTOCOL *This, 174 IN BOOLEAN RecordingState 175 ); 176 177 /** 178 Record memory profile of multilevel caller. 179 180 @param[in] This The EDKII_MEMORY_PROFILE_PROTOCOL instance. 181 @param[in] CallerAddress Address of caller. 182 @param[in] Action Memory profile action. 183 @param[in] MemoryType Memory type. 184 EfiMaxMemoryType means the MemoryType is unknown. 185 @param[in] Buffer Buffer address. 186 @param[in] Size Buffer size. 187 @param[in] ActionString String for memory profile action. 188 Only needed for user defined allocate action. 189 190 @return EFI_SUCCESS Memory profile is updated. 191 @return EFI_UNSUPPORTED Memory profile is unsupported, 192 or memory profile for the image is not required, 193 or memory profile for the memory type is not required. 194 @return EFI_ACCESS_DENIED It is during memory profile data getting. 195 @return EFI_ABORTED Memory profile recording is not enabled. 196 @return EFI_OUT_OF_RESOURCES No enough resource to update memory profile for allocate action. 197 @return EFI_NOT_FOUND No matched allocate info found for free action. 198 199 **/ 200 EFI_STATUS 201 EFIAPI 202 ProfileProtocolRecord ( 203 IN EDKII_MEMORY_PROFILE_PROTOCOL *This, 204 IN PHYSICAL_ADDRESS CallerAddress, 205 IN MEMORY_PROFILE_ACTION Action, 206 IN EFI_MEMORY_TYPE MemoryType, 207 IN VOID *Buffer, 208 IN UINTN Size, 209 IN CHAR8 *ActionString OPTIONAL 210 ); 211 212 EDKII_MEMORY_PROFILE_PROTOCOL mProfileProtocol = { 213 ProfileProtocolGetData, 214 ProfileProtocolRegisterImage, 215 ProfileProtocolUnregisterImage, 216 ProfileProtocolGetRecordingState, 217 ProfileProtocolSetRecordingState, 218 ProfileProtocolRecord, 219 }; 220 221 /** 222 Acquire lock on mMemoryProfileLock. 223 **/ 224 VOID 225 CoreAcquireMemoryProfileLock ( 226 VOID 227 ) 228 { 229 CoreAcquireLock (&mMemoryProfileLock); 230 } 231 232 /** 233 Release lock on mMemoryProfileLock. 234 **/ 235 VOID 236 CoreReleaseMemoryProfileLock ( 237 VOID 238 ) 239 { 240 CoreReleaseLock (&mMemoryProfileLock); 241 } 242 243 /** 244 Return memory profile context. 245 246 @return Memory profile context. 247 248 **/ 249 MEMORY_PROFILE_CONTEXT_DATA * 250 GetMemoryProfileContext ( 251 VOID 252 ) 253 { 254 return mMemoryProfileContextPtr; 255 } 256 257 /** 258 Retrieves the magic value from the PE/COFF header. 259 260 @param Hdr The buffer in which to return the PE32, PE32+, or TE header. 261 262 @return EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC - Image is PE32 263 @return EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC - Image is PE32+ 264 265 **/ 266 UINT16 267 InternalPeCoffGetPeHeaderMagicValue ( 268 IN EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION Hdr 269 ) 270 { 271 // 272 // NOTE: Some versions of Linux ELILO for Itanium have an incorrect magic value 273 // in the PE/COFF Header. If the MachineType is Itanium(IA64) and the 274 // Magic value in the OptionalHeader is EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC 275 // then override the returned value to EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC 276 // 277 if (Hdr.Pe32->FileHeader.Machine == IMAGE_FILE_MACHINE_IA64 && Hdr.Pe32->OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) { 278 return EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC; 279 } 280 // 281 // Return the magic value from the PC/COFF Optional Header 282 // 283 return Hdr.Pe32->OptionalHeader.Magic; 284 } 285 286 /** 287 Retrieves and returns the Subsystem of a PE/COFF image that has been loaded into system memory. 288 If Pe32Data is NULL, then ASSERT(). 289 290 @param Pe32Data The pointer to the PE/COFF image that is loaded in system memory. 291 292 @return The Subsystem of the PE/COFF image. 293 294 **/ 295 UINT16 296 InternalPeCoffGetSubsystem ( 297 IN VOID *Pe32Data 298 ) 299 { 300 EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION Hdr; 301 EFI_IMAGE_DOS_HEADER *DosHdr; 302 UINT16 Magic; 303 304 ASSERT (Pe32Data != NULL); 305 306 DosHdr = (EFI_IMAGE_DOS_HEADER *) Pe32Data; 307 if (DosHdr->e_magic == EFI_IMAGE_DOS_SIGNATURE) { 308 // 309 // DOS image header is present, so read the PE header after the DOS image header. 310 // 311 Hdr.Pe32 = (EFI_IMAGE_NT_HEADERS32 *) ((UINTN) Pe32Data + (UINTN) ((DosHdr->e_lfanew) & 0x0ffff)); 312 } else { 313 // 314 // DOS image header is not present, so PE header is at the image base. 315 // 316 Hdr.Pe32 = (EFI_IMAGE_NT_HEADERS32 *) Pe32Data; 317 } 318 319 if (Hdr.Te->Signature == EFI_TE_IMAGE_HEADER_SIGNATURE) { 320 return Hdr.Te->Subsystem; 321 } else if (Hdr.Pe32->Signature == EFI_IMAGE_NT_SIGNATURE) { 322 Magic = InternalPeCoffGetPeHeaderMagicValue (Hdr); 323 if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) { 324 return Hdr.Pe32->OptionalHeader.Subsystem; 325 } else if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC) { 326 return Hdr.Pe32Plus->OptionalHeader.Subsystem; 327 } 328 } 329 330 return 0x0000; 331 } 332 333 /** 334 Retrieves and returns a pointer to the entry point to a PE/COFF image that has been loaded 335 into system memory with the PE/COFF Loader Library functions. 336 337 Retrieves the entry point to the PE/COFF image specified by Pe32Data and returns this entry 338 point in EntryPoint. If the entry point could not be retrieved from the PE/COFF image, then 339 return RETURN_INVALID_PARAMETER. Otherwise return RETURN_SUCCESS. 340 If Pe32Data is NULL, then ASSERT(). 341 If EntryPoint is NULL, then ASSERT(). 342 343 @param Pe32Data The pointer to the PE/COFF image that is loaded in system memory. 344 @param EntryPoint The pointer to entry point to the PE/COFF image to return. 345 346 @retval RETURN_SUCCESS EntryPoint was returned. 347 @retval RETURN_INVALID_PARAMETER The entry point could not be found in the PE/COFF image. 348 349 **/ 350 RETURN_STATUS 351 InternalPeCoffGetEntryPoint ( 352 IN VOID *Pe32Data, 353 OUT VOID **EntryPoint 354 ) 355 { 356 EFI_IMAGE_DOS_HEADER *DosHdr; 357 EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION Hdr; 358 359 ASSERT (Pe32Data != NULL); 360 ASSERT (EntryPoint != NULL); 361 362 DosHdr = (EFI_IMAGE_DOS_HEADER *) Pe32Data; 363 if (DosHdr->e_magic == EFI_IMAGE_DOS_SIGNATURE) { 364 // 365 // DOS image header is present, so read the PE header after the DOS image header. 366 // 367 Hdr.Pe32 = (EFI_IMAGE_NT_HEADERS32 *) ((UINTN) Pe32Data + (UINTN) ((DosHdr->e_lfanew) & 0x0ffff)); 368 } else { 369 // 370 // DOS image header is not present, so PE header is at the image base. 371 // 372 Hdr.Pe32 = (EFI_IMAGE_NT_HEADERS32 *) Pe32Data; 373 } 374 375 // 376 // Calculate the entry point relative to the start of the image. 377 // AddressOfEntryPoint is common for PE32 & PE32+ 378 // 379 if (Hdr.Te->Signature == EFI_TE_IMAGE_HEADER_SIGNATURE) { 380 *EntryPoint = (VOID *) ((UINTN) Pe32Data + (UINTN) (Hdr.Te->AddressOfEntryPoint & 0x0ffffffff) + sizeof (EFI_TE_IMAGE_HEADER) - Hdr.Te->StrippedSize); 381 return RETURN_SUCCESS; 382 } else if (Hdr.Pe32->Signature == EFI_IMAGE_NT_SIGNATURE) { 383 *EntryPoint = (VOID *) ((UINTN) Pe32Data + (UINTN) (Hdr.Pe32->OptionalHeader.AddressOfEntryPoint & 0x0ffffffff)); 384 return RETURN_SUCCESS; 385 } 386 387 return RETURN_UNSUPPORTED; 388 } 389 390 /** 391 Build driver info. 392 393 @param ContextData Memory profile context. 394 @param FileName File name of the image. 395 @param ImageBase Image base address. 396 @param ImageSize Image size. 397 @param EntryPoint Entry point of the image. 398 @param ImageSubsystem Image subsystem of the image. 399 @param FileType File type of the image. 400 401 @return Pointer to memory profile driver info. 402 403 **/ 404 MEMORY_PROFILE_DRIVER_INFO_DATA * 405 BuildDriverInfo ( 406 IN MEMORY_PROFILE_CONTEXT_DATA *ContextData, 407 IN EFI_GUID *FileName, 408 IN PHYSICAL_ADDRESS ImageBase, 409 IN UINT64 ImageSize, 410 IN PHYSICAL_ADDRESS EntryPoint, 411 IN UINT16 ImageSubsystem, 412 IN EFI_FV_FILETYPE FileType 413 ) 414 { 415 EFI_STATUS Status; 416 MEMORY_PROFILE_DRIVER_INFO *DriverInfo; 417 MEMORY_PROFILE_DRIVER_INFO_DATA *DriverInfoData; 418 VOID *EntryPointInImage; 419 CHAR8 *PdbString; 420 UINTN PdbSize; 421 UINTN PdbOccupiedSize; 422 423 PdbSize = 0; 424 PdbOccupiedSize = 0; 425 PdbString = NULL; 426 if (ImageBase != 0) { 427 PdbString = PeCoffLoaderGetPdbPointer ((VOID*) (UINTN) ImageBase); 428 if (PdbString != NULL) { 429 PdbSize = AsciiStrSize (PdbString); 430 PdbOccupiedSize = GET_OCCUPIED_SIZE (PdbSize, sizeof (UINT64)); 431 } 432 } 433 434 // 435 // Use CoreInternalAllocatePool() that will not update profile for this AllocatePool action. 436 // 437 Status = CoreInternalAllocatePool ( 438 EfiBootServicesData, 439 sizeof (*DriverInfoData) + sizeof (LIST_ENTRY) + PdbSize, 440 (VOID **) &DriverInfoData 441 ); 442 if (EFI_ERROR (Status)) { 443 return NULL; 444 } 445 ASSERT (DriverInfoData != NULL); 446 447 ZeroMem (DriverInfoData, sizeof (*DriverInfoData)); 448 449 DriverInfo = &DriverInfoData->DriverInfo; 450 DriverInfoData->Signature = MEMORY_PROFILE_DRIVER_INFO_SIGNATURE; 451 DriverInfo->Header.Signature = MEMORY_PROFILE_DRIVER_INFO_SIGNATURE; 452 DriverInfo->Header.Length = (UINT16) (sizeof (MEMORY_PROFILE_DRIVER_INFO) + PdbOccupiedSize); 453 DriverInfo->Header.Revision = MEMORY_PROFILE_DRIVER_INFO_REVISION; 454 if (FileName != NULL) { 455 CopyMem (&DriverInfo->FileName, FileName, sizeof (EFI_GUID)); 456 } 457 DriverInfo->ImageBase = ImageBase; 458 DriverInfo->ImageSize = ImageSize; 459 DriverInfo->EntryPoint = EntryPoint; 460 DriverInfo->ImageSubsystem = ImageSubsystem; 461 if ((EntryPoint != 0) && ((EntryPoint < ImageBase) || (EntryPoint >= (ImageBase + ImageSize)))) { 462 // 463 // If the EntryPoint is not in the range of image buffer, it should come from emulation environment. 464 // So patch ImageBuffer here to align the EntryPoint. 465 // 466 Status = InternalPeCoffGetEntryPoint ((VOID *) (UINTN) ImageBase, &EntryPointInImage); 467 ASSERT_EFI_ERROR (Status); 468 DriverInfo->ImageBase = ImageBase + EntryPoint - (PHYSICAL_ADDRESS) (UINTN) EntryPointInImage; 469 } 470 DriverInfo->FileType = FileType; 471 DriverInfoData->AllocInfoList = (LIST_ENTRY *) (DriverInfoData + 1); 472 InitializeListHead (DriverInfoData->AllocInfoList); 473 DriverInfo->CurrentUsage = 0; 474 DriverInfo->PeakUsage = 0; 475 DriverInfo->AllocRecordCount = 0; 476 if (PdbSize != 0) { 477 DriverInfo->PdbStringOffset = (UINT16) sizeof (MEMORY_PROFILE_DRIVER_INFO); 478 DriverInfoData->PdbString = (CHAR8 *) (DriverInfoData->AllocInfoList + 1); 479 CopyMem (DriverInfoData->PdbString, PdbString, PdbSize); 480 } else { 481 DriverInfo->PdbStringOffset = 0; 482 DriverInfoData->PdbString = NULL; 483 } 484 485 InsertTailList (ContextData->DriverInfoList, &DriverInfoData->Link); 486 ContextData->Context.ImageCount ++; 487 ContextData->Context.TotalImageSize += DriverInfo->ImageSize; 488 489 return DriverInfoData; 490 } 491 492 /** 493 Return if record for this driver is needed.. 494 495 @param DriverFilePath Driver file path. 496 497 @retval TRUE Record for this driver is needed. 498 @retval FALSE Record for this driver is not needed. 499 500 **/ 501 BOOLEAN 502 NeedRecordThisDriver ( 503 IN EFI_DEVICE_PATH_PROTOCOL *DriverFilePath 504 ) 505 { 506 EFI_DEVICE_PATH_PROTOCOL *TmpDevicePath; 507 EFI_DEVICE_PATH_PROTOCOL *DevicePathInstance; 508 UINTN DevicePathSize; 509 UINTN FilePathSize; 510 511 if (!IsDevicePathValid (mMemoryProfileDriverPath, mMemoryProfileDriverPathSize)) { 512 // 513 // Invalid Device Path means record all. 514 // 515 return TRUE; 516 } 517 518 // 519 // Record FilePath without END node. 520 // 521 FilePathSize = GetDevicePathSize (DriverFilePath) - sizeof(EFI_DEVICE_PATH_PROTOCOL); 522 523 DevicePathInstance = mMemoryProfileDriverPath; 524 do { 525 // 526 // Find END node (it might be END_ENTIRE or END_INSTANCE). 527 // 528 TmpDevicePath = DevicePathInstance; 529 while (!IsDevicePathEndType (TmpDevicePath)) { 530 TmpDevicePath = NextDevicePathNode (TmpDevicePath); 531 } 532 533 // 534 // Do not compare END node. 535 // 536 DevicePathSize = (UINTN)TmpDevicePath - (UINTN)DevicePathInstance; 537 if ((FilePathSize == DevicePathSize) && 538 (CompareMem (DriverFilePath, DevicePathInstance, DevicePathSize) == 0)) { 539 return TRUE; 540 } 541 542 // 543 // Get next instance. 544 // 545 DevicePathInstance = (EFI_DEVICE_PATH_PROTOCOL *)((UINTN)DevicePathInstance + DevicePathSize + DevicePathNodeLength(TmpDevicePath)); 546 } while (DevicePathSubType (TmpDevicePath) != END_ENTIRE_DEVICE_PATH_SUBTYPE); 547 548 return FALSE; 549 } 550 551 /** 552 Register DXE Core to memory profile. 553 554 @param HobStart The start address of the HOB. 555 @param ContextData Memory profile context. 556 557 @retval TRUE Register success. 558 @retval FALSE Register fail. 559 560 **/ 561 BOOLEAN 562 RegisterDxeCore ( 563 IN VOID *HobStart, 564 IN MEMORY_PROFILE_CONTEXT_DATA *ContextData 565 ) 566 { 567 EFI_PEI_HOB_POINTERS DxeCoreHob; 568 MEMORY_PROFILE_DRIVER_INFO_DATA *DriverInfoData; 569 PHYSICAL_ADDRESS ImageBase; 570 UINT8 TempBuffer[sizeof(MEDIA_FW_VOL_FILEPATH_DEVICE_PATH) + sizeof(EFI_DEVICE_PATH_PROTOCOL)]; 571 MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *FilePath; 572 573 ASSERT (ContextData != NULL); 574 575 // 576 // Searching for image hob 577 // 578 DxeCoreHob.Raw = HobStart; 579 while ((DxeCoreHob.Raw = GetNextHob (EFI_HOB_TYPE_MEMORY_ALLOCATION, DxeCoreHob.Raw)) != NULL) { 580 if (CompareGuid (&DxeCoreHob.MemoryAllocationModule->MemoryAllocationHeader.Name, &gEfiHobMemoryAllocModuleGuid)) { 581 // 582 // Find Dxe Core HOB 583 // 584 break; 585 } 586 DxeCoreHob.Raw = GET_NEXT_HOB (DxeCoreHob); 587 } 588 ASSERT (DxeCoreHob.Raw != NULL); 589 590 FilePath = (MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *) TempBuffer; 591 EfiInitializeFwVolDevicepathNode (FilePath, &DxeCoreHob.MemoryAllocationModule->ModuleName); 592 SetDevicePathEndNode (FilePath + 1); 593 594 if (!NeedRecordThisDriver ((EFI_DEVICE_PATH_PROTOCOL *) FilePath)) { 595 return FALSE; 596 } 597 598 ImageBase = DxeCoreHob.MemoryAllocationModule->MemoryAllocationHeader.MemoryBaseAddress; 599 DriverInfoData = BuildDriverInfo ( 600 ContextData, 601 &DxeCoreHob.MemoryAllocationModule->ModuleName, 602 ImageBase, 603 DxeCoreHob.MemoryAllocationModule->MemoryAllocationHeader.MemoryLength, 604 DxeCoreHob.MemoryAllocationModule->EntryPoint, 605 InternalPeCoffGetSubsystem ((VOID *) (UINTN) ImageBase), 606 EFI_FV_FILETYPE_DXE_CORE 607 ); 608 if (DriverInfoData == NULL) { 609 return FALSE; 610 } 611 612 return TRUE; 613 } 614 615 /** 616 Initialize memory profile. 617 618 @param HobStart The start address of the HOB. 619 620 **/ 621 VOID 622 MemoryProfileInit ( 623 IN VOID *HobStart 624 ) 625 { 626 MEMORY_PROFILE_CONTEXT_DATA *ContextData; 627 628 if (!IS_UEFI_MEMORY_PROFILE_ENABLED) { 629 return; 630 } 631 632 ContextData = GetMemoryProfileContext (); 633 if (ContextData != NULL) { 634 return; 635 } 636 637 mMemoryProfileGettingStatus = FALSE; 638 if ((PcdGet8 (PcdMemoryProfilePropertyMask) & BIT7) != 0) { 639 mMemoryProfileRecordingEnable = MEMORY_PROFILE_RECORDING_DISABLE; 640 } else { 641 mMemoryProfileRecordingEnable = MEMORY_PROFILE_RECORDING_ENABLE; 642 } 643 mMemoryProfileDriverPathSize = PcdGetSize (PcdMemoryProfileDriverPath); 644 mMemoryProfileDriverPath = AllocateCopyPool (mMemoryProfileDriverPathSize, PcdGetPtr (PcdMemoryProfileDriverPath)); 645 mMemoryProfileContextPtr = &mMemoryProfileContext; 646 647 RegisterDxeCore (HobStart, &mMemoryProfileContext); 648 649 DEBUG ((EFI_D_INFO, "MemoryProfileInit MemoryProfileContext - 0x%x\n", &mMemoryProfileContext)); 650 } 651 652 /** 653 Install memory profile protocol. 654 655 **/ 656 VOID 657 MemoryProfileInstallProtocol ( 658 VOID 659 ) 660 { 661 EFI_HANDLE Handle; 662 EFI_STATUS Status; 663 664 if (!IS_UEFI_MEMORY_PROFILE_ENABLED) { 665 return; 666 } 667 668 Handle = NULL; 669 Status = CoreInstallMultipleProtocolInterfaces ( 670 &Handle, 671 &gEdkiiMemoryProfileGuid, 672 &mProfileProtocol, 673 NULL 674 ); 675 ASSERT_EFI_ERROR (Status); 676 } 677 678 /** 679 Get the GUID file name from the file path. 680 681 @param FilePath File path. 682 683 @return The GUID file name from the file path. 684 685 **/ 686 EFI_GUID * 687 GetFileNameFromFilePath ( 688 IN EFI_DEVICE_PATH_PROTOCOL *FilePath 689 ) 690 { 691 MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *ThisFilePath; 692 EFI_GUID *FileName; 693 694 FileName = NULL; 695 if (FilePath != NULL) { 696 ThisFilePath = (MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *) FilePath; 697 while (!IsDevicePathEnd (ThisFilePath)) { 698 FileName = EfiGetNameGuidFromFwVolDevicePathNode (ThisFilePath); 699 if (FileName != NULL) { 700 break; 701 } 702 ThisFilePath = (MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *) NextDevicePathNode (ThisFilePath); 703 } 704 } 705 706 return FileName; 707 } 708 709 /** 710 Register image to memory profile. 711 712 @param DriverEntry Image info. 713 @param FileType Image file type. 714 715 @return EFI_SUCCESS Register successfully. 716 @return EFI_UNSUPPORTED Memory profile is unsupported, 717 or memory profile for the image is not required. 718 @return EFI_OUT_OF_RESOURCES No enough resource for this register. 719 720 **/ 721 EFI_STATUS 722 RegisterMemoryProfileImage ( 723 IN LOADED_IMAGE_PRIVATE_DATA *DriverEntry, 724 IN EFI_FV_FILETYPE FileType 725 ) 726 { 727 MEMORY_PROFILE_CONTEXT_DATA *ContextData; 728 MEMORY_PROFILE_DRIVER_INFO_DATA *DriverInfoData; 729 730 if (!IS_UEFI_MEMORY_PROFILE_ENABLED) { 731 return EFI_UNSUPPORTED; 732 } 733 734 if (!NeedRecordThisDriver (DriverEntry->Info.FilePath)) { 735 return EFI_UNSUPPORTED; 736 } 737 738 ContextData = GetMemoryProfileContext (); 739 if (ContextData == NULL) { 740 return EFI_UNSUPPORTED; 741 } 742 743 DriverInfoData = BuildDriverInfo ( 744 ContextData, 745 GetFileNameFromFilePath (DriverEntry->Info.FilePath), 746 DriverEntry->ImageContext.ImageAddress, 747 DriverEntry->ImageContext.ImageSize, 748 DriverEntry->ImageContext.EntryPoint, 749 DriverEntry->ImageContext.ImageType, 750 FileType 751 ); 752 if (DriverInfoData == NULL) { 753 return EFI_OUT_OF_RESOURCES; 754 } 755 756 return EFI_SUCCESS; 757 } 758 759 /** 760 Search image from memory profile. 761 762 @param ContextData Memory profile context. 763 @param FileName Image file name. 764 @param Address Image Address. 765 766 @return Pointer to memory profile driver info. 767 768 **/ 769 MEMORY_PROFILE_DRIVER_INFO_DATA * 770 GetMemoryProfileDriverInfoByFileNameAndAddress ( 771 IN MEMORY_PROFILE_CONTEXT_DATA *ContextData, 772 IN EFI_GUID *FileName, 773 IN PHYSICAL_ADDRESS Address 774 ) 775 { 776 MEMORY_PROFILE_DRIVER_INFO *DriverInfo; 777 MEMORY_PROFILE_DRIVER_INFO_DATA *DriverInfoData; 778 LIST_ENTRY *DriverLink; 779 LIST_ENTRY *DriverInfoList; 780 781 DriverInfoList = ContextData->DriverInfoList; 782 783 for (DriverLink = DriverInfoList->ForwardLink; 784 DriverLink != DriverInfoList; 785 DriverLink = DriverLink->ForwardLink) { 786 DriverInfoData = CR ( 787 DriverLink, 788 MEMORY_PROFILE_DRIVER_INFO_DATA, 789 Link, 790 MEMORY_PROFILE_DRIVER_INFO_SIGNATURE 791 ); 792 DriverInfo = &DriverInfoData->DriverInfo; 793 if ((CompareGuid (&DriverInfo->FileName, FileName)) && 794 (Address >= DriverInfo->ImageBase) && 795 (Address < (DriverInfo->ImageBase + DriverInfo->ImageSize))) { 796 return DriverInfoData; 797 } 798 } 799 800 return NULL; 801 } 802 803 /** 804 Search image from memory profile. 805 It will return image, if (Address >= ImageBuffer) AND (Address < ImageBuffer + ImageSize). 806 807 @param ContextData Memory profile context. 808 @param Address Image or Function address. 809 810 @return Pointer to memory profile driver info. 811 812 **/ 813 MEMORY_PROFILE_DRIVER_INFO_DATA * 814 GetMemoryProfileDriverInfoFromAddress ( 815 IN MEMORY_PROFILE_CONTEXT_DATA *ContextData, 816 IN PHYSICAL_ADDRESS Address 817 ) 818 { 819 MEMORY_PROFILE_DRIVER_INFO *DriverInfo; 820 MEMORY_PROFILE_DRIVER_INFO_DATA *DriverInfoData; 821 LIST_ENTRY *DriverLink; 822 LIST_ENTRY *DriverInfoList; 823 824 DriverInfoList = ContextData->DriverInfoList; 825 826 for (DriverLink = DriverInfoList->ForwardLink; 827 DriverLink != DriverInfoList; 828 DriverLink = DriverLink->ForwardLink) { 829 DriverInfoData = CR ( 830 DriverLink, 831 MEMORY_PROFILE_DRIVER_INFO_DATA, 832 Link, 833 MEMORY_PROFILE_DRIVER_INFO_SIGNATURE 834 ); 835 DriverInfo = &DriverInfoData->DriverInfo; 836 if ((Address >= DriverInfo->ImageBase) && 837 (Address < (DriverInfo->ImageBase + DriverInfo->ImageSize))) { 838 return DriverInfoData; 839 } 840 } 841 842 return NULL; 843 } 844 845 /** 846 Unregister image from memory profile. 847 848 @param DriverEntry Image info. 849 850 @return EFI_SUCCESS Unregister successfully. 851 @return EFI_UNSUPPORTED Memory profile is unsupported, 852 or memory profile for the image is not required. 853 @return EFI_NOT_FOUND The image is not found. 854 855 **/ 856 EFI_STATUS 857 UnregisterMemoryProfileImage ( 858 IN LOADED_IMAGE_PRIVATE_DATA *DriverEntry 859 ) 860 { 861 EFI_STATUS Status; 862 MEMORY_PROFILE_CONTEXT_DATA *ContextData; 863 MEMORY_PROFILE_DRIVER_INFO_DATA *DriverInfoData; 864 EFI_GUID *FileName; 865 PHYSICAL_ADDRESS ImageAddress; 866 VOID *EntryPointInImage; 867 868 if (!IS_UEFI_MEMORY_PROFILE_ENABLED) { 869 return EFI_UNSUPPORTED; 870 } 871 872 if (!NeedRecordThisDriver (DriverEntry->Info.FilePath)) { 873 return EFI_UNSUPPORTED; 874 } 875 876 ContextData = GetMemoryProfileContext (); 877 if (ContextData == NULL) { 878 return EFI_UNSUPPORTED; 879 } 880 881 DriverInfoData = NULL; 882 FileName = GetFileNameFromFilePath (DriverEntry->Info.FilePath); 883 ImageAddress = DriverEntry->ImageContext.ImageAddress; 884 if ((DriverEntry->ImageContext.EntryPoint < ImageAddress) || (DriverEntry->ImageContext.EntryPoint >= (ImageAddress + DriverEntry->ImageContext.ImageSize))) { 885 // 886 // If the EntryPoint is not in the range of image buffer, it should come from emulation environment. 887 // So patch ImageAddress here to align the EntryPoint. 888 // 889 Status = InternalPeCoffGetEntryPoint ((VOID *) (UINTN) ImageAddress, &EntryPointInImage); 890 ASSERT_EFI_ERROR (Status); 891 ImageAddress = ImageAddress + (UINTN) DriverEntry->ImageContext.EntryPoint - (UINTN) EntryPointInImage; 892 } 893 if (FileName != NULL) { 894 DriverInfoData = GetMemoryProfileDriverInfoByFileNameAndAddress (ContextData, FileName, ImageAddress); 895 } 896 if (DriverInfoData == NULL) { 897 DriverInfoData = GetMemoryProfileDriverInfoFromAddress (ContextData, ImageAddress); 898 } 899 if (DriverInfoData == NULL) { 900 return EFI_NOT_FOUND; 901 } 902 903 ContextData->Context.TotalImageSize -= DriverInfoData->DriverInfo.ImageSize; 904 905 // Keep the ImageBase for RVA calculation in Application. 906 //DriverInfoData->DriverInfo.ImageBase = 0; 907 DriverInfoData->DriverInfo.ImageSize = 0; 908 909 if (DriverInfoData->DriverInfo.PeakUsage == 0) { 910 ContextData->Context.ImageCount --; 911 RemoveEntryList (&DriverInfoData->Link); 912 // 913 // Use CoreInternalFreePool() that will not update profile for this FreePool action. 914 // 915 CoreInternalFreePool (DriverInfoData, NULL); 916 } 917 918 return EFI_SUCCESS; 919 } 920 921 /** 922 Return if this memory type needs to be recorded into memory profile. 923 If BIOS memory type (0 ~ EfiMaxMemoryType - 1), it checks bit (1 << MemoryType). 924 If OS memory type (0x80000000 ~ 0xFFFFFFFF), it checks bit63 - 0x8000000000000000. 925 If OEM memory type (0x70000000 ~ 0x7FFFFFFF), it checks bit62 - 0x4000000000000000. 926 927 @param MemoryType Memory type. 928 929 @retval TRUE This memory type need to be recorded. 930 @retval FALSE This memory type need not to be recorded. 931 932 **/ 933 BOOLEAN 934 CoreNeedRecordProfile ( 935 IN EFI_MEMORY_TYPE MemoryType 936 ) 937 { 938 UINT64 TestBit; 939 940 if ((UINT32) MemoryType >= MEMORY_TYPE_OS_RESERVED_MIN) { 941 TestBit = BIT63; 942 } else if ((UINT32) MemoryType >= MEMORY_TYPE_OEM_RESERVED_MIN) { 943 TestBit = BIT62; 944 } else { 945 TestBit = LShiftU64 (1, MemoryType); 946 } 947 948 if ((PcdGet64 (PcdMemoryProfileMemoryType) & TestBit) != 0) { 949 return TRUE; 950 } else { 951 return FALSE; 952 } 953 } 954 955 /** 956 Convert EFI memory type to profile memory index. The rule is: 957 If BIOS memory type (0 ~ EfiMaxMemoryType - 1), ProfileMemoryIndex = MemoryType. 958 If OS memory type (0x80000000 ~ 0xFFFFFFFF), ProfileMemoryIndex = EfiMaxMemoryType. 959 If OEM memory type (0x70000000 ~ 0x7FFFFFFF), ProfileMemoryIndex = EfiMaxMemoryType + 1. 960 961 @param MemoryType Memory type. 962 963 @return Profile memory index. 964 965 **/ 966 UINTN 967 GetProfileMemoryIndex ( 968 IN EFI_MEMORY_TYPE MemoryType 969 ) 970 { 971 if ((UINT32) MemoryType >= MEMORY_TYPE_OS_RESERVED_MIN) { 972 return EfiMaxMemoryType; 973 } else if ((UINT32) MemoryType >= MEMORY_TYPE_OEM_RESERVED_MIN) { 974 return EfiMaxMemoryType + 1; 975 } else { 976 return MemoryType; 977 } 978 } 979 980 /** 981 Update memory profile Allocate information. 982 983 @param CallerAddress Address of caller who call Allocate. 984 @param Action This Allocate action. 985 @param MemoryType Memory type. 986 @param Size Buffer size. 987 @param Buffer Buffer address. 988 @param ActionString String for memory profile action. 989 990 @return EFI_SUCCESS Memory profile is updated. 991 @return EFI_UNSUPPORTED Memory profile is unsupported, 992 or memory profile for the image is not required. 993 @return EFI_OUT_OF_RESOURCES No enough resource to update memory profile for allocate action. 994 995 **/ 996 EFI_STATUS 997 CoreUpdateProfileAllocate ( 998 IN PHYSICAL_ADDRESS CallerAddress, 999 IN MEMORY_PROFILE_ACTION Action, 1000 IN EFI_MEMORY_TYPE MemoryType, 1001 IN UINTN Size, 1002 IN VOID *Buffer, 1003 IN CHAR8 *ActionString OPTIONAL 1004 ) 1005 { 1006 EFI_STATUS Status; 1007 MEMORY_PROFILE_CONTEXT *Context; 1008 MEMORY_PROFILE_DRIVER_INFO *DriverInfo; 1009 MEMORY_PROFILE_ALLOC_INFO *AllocInfo; 1010 MEMORY_PROFILE_CONTEXT_DATA *ContextData; 1011 MEMORY_PROFILE_DRIVER_INFO_DATA *DriverInfoData; 1012 MEMORY_PROFILE_ALLOC_INFO_DATA *AllocInfoData; 1013 UINTN ProfileMemoryIndex; 1014 MEMORY_PROFILE_ACTION BasicAction; 1015 UINTN ActionStringSize; 1016 UINTN ActionStringOccupiedSize; 1017 1018 BasicAction = Action & MEMORY_PROFILE_ACTION_BASIC_MASK; 1019 1020 ContextData = GetMemoryProfileContext (); 1021 if (ContextData == NULL) { 1022 return EFI_UNSUPPORTED; 1023 } 1024 1025 DriverInfoData = GetMemoryProfileDriverInfoFromAddress (ContextData, CallerAddress); 1026 if (DriverInfoData == NULL) { 1027 return EFI_UNSUPPORTED; 1028 } 1029 1030 ActionStringSize = 0; 1031 ActionStringOccupiedSize = 0; 1032 if (ActionString != NULL) { 1033 ActionStringSize = AsciiStrSize (ActionString); 1034 ActionStringOccupiedSize = GET_OCCUPIED_SIZE (ActionStringSize, sizeof (UINT64)); 1035 } 1036 1037 // 1038 // Use CoreInternalAllocatePool() that will not update profile for this AllocatePool action. 1039 // 1040 AllocInfoData = NULL; 1041 Status = CoreInternalAllocatePool ( 1042 EfiBootServicesData, 1043 sizeof (*AllocInfoData) + ActionStringSize, 1044 (VOID **) &AllocInfoData 1045 ); 1046 if (EFI_ERROR (Status)) { 1047 return EFI_OUT_OF_RESOURCES; 1048 } 1049 ASSERT (AllocInfoData != NULL); 1050 1051 // 1052 // Only update SequenceCount if and only if it is basic action. 1053 // 1054 if (Action == BasicAction) { 1055 ContextData->Context.SequenceCount ++; 1056 } 1057 1058 AllocInfo = &AllocInfoData->AllocInfo; 1059 AllocInfoData->Signature = MEMORY_PROFILE_ALLOC_INFO_SIGNATURE; 1060 AllocInfo->Header.Signature = MEMORY_PROFILE_ALLOC_INFO_SIGNATURE; 1061 AllocInfo->Header.Length = (UINT16) (sizeof (MEMORY_PROFILE_ALLOC_INFO) + ActionStringOccupiedSize); 1062 AllocInfo->Header.Revision = MEMORY_PROFILE_ALLOC_INFO_REVISION; 1063 AllocInfo->CallerAddress = CallerAddress; 1064 AllocInfo->SequenceId = ContextData->Context.SequenceCount; 1065 AllocInfo->Action = Action; 1066 AllocInfo->MemoryType = MemoryType; 1067 AllocInfo->Buffer = (PHYSICAL_ADDRESS) (UINTN) Buffer; 1068 AllocInfo->Size = Size; 1069 if (ActionString != NULL) { 1070 AllocInfo->ActionStringOffset = (UINT16) sizeof (MEMORY_PROFILE_ALLOC_INFO); 1071 AllocInfoData->ActionString = (CHAR8 *) (AllocInfoData + 1); 1072 CopyMem (AllocInfoData->ActionString, ActionString, ActionStringSize); 1073 } else { 1074 AllocInfo->ActionStringOffset = 0; 1075 AllocInfoData->ActionString = NULL; 1076 } 1077 1078 InsertTailList (DriverInfoData->AllocInfoList, &AllocInfoData->Link); 1079 1080 Context = &ContextData->Context; 1081 DriverInfo = &DriverInfoData->DriverInfo; 1082 DriverInfo->AllocRecordCount ++; 1083 1084 // 1085 // Update summary if and only if it is basic action. 1086 // 1087 if (Action == BasicAction) { 1088 ProfileMemoryIndex = GetProfileMemoryIndex (MemoryType); 1089 1090 DriverInfo->CurrentUsage += Size; 1091 if (DriverInfo->PeakUsage < DriverInfo->CurrentUsage) { 1092 DriverInfo->PeakUsage = DriverInfo->CurrentUsage; 1093 } 1094 DriverInfo->CurrentUsageByType[ProfileMemoryIndex] += Size; 1095 if (DriverInfo->PeakUsageByType[ProfileMemoryIndex] < DriverInfo->CurrentUsageByType[ProfileMemoryIndex]) { 1096 DriverInfo->PeakUsageByType[ProfileMemoryIndex] = DriverInfo->CurrentUsageByType[ProfileMemoryIndex]; 1097 } 1098 1099 Context->CurrentTotalUsage += Size; 1100 if (Context->PeakTotalUsage < Context->CurrentTotalUsage) { 1101 Context->PeakTotalUsage = Context->CurrentTotalUsage; 1102 } 1103 Context->CurrentTotalUsageByType[ProfileMemoryIndex] += Size; 1104 if (Context->PeakTotalUsageByType[ProfileMemoryIndex] < Context->CurrentTotalUsageByType[ProfileMemoryIndex]) { 1105 Context->PeakTotalUsageByType[ProfileMemoryIndex] = Context->CurrentTotalUsageByType[ProfileMemoryIndex]; 1106 } 1107 } 1108 1109 return EFI_SUCCESS; 1110 } 1111 1112 /** 1113 Get memory profile alloc info from memory profile. 1114 1115 @param DriverInfoData Driver info. 1116 @param BasicAction This Free basic action. 1117 @param Size Buffer size. 1118 @param Buffer Buffer address. 1119 1120 @return Pointer to memory profile alloc info. 1121 1122 **/ 1123 MEMORY_PROFILE_ALLOC_INFO_DATA * 1124 GetMemoryProfileAllocInfoFromAddress ( 1125 IN MEMORY_PROFILE_DRIVER_INFO_DATA *DriverInfoData, 1126 IN MEMORY_PROFILE_ACTION BasicAction, 1127 IN UINTN Size, 1128 IN VOID *Buffer 1129 ) 1130 { 1131 LIST_ENTRY *AllocInfoList; 1132 LIST_ENTRY *AllocLink; 1133 MEMORY_PROFILE_ALLOC_INFO *AllocInfo; 1134 MEMORY_PROFILE_ALLOC_INFO_DATA *AllocInfoData; 1135 1136 AllocInfoList = DriverInfoData->AllocInfoList; 1137 1138 for (AllocLink = AllocInfoList->ForwardLink; 1139 AllocLink != AllocInfoList; 1140 AllocLink = AllocLink->ForwardLink) { 1141 AllocInfoData = CR ( 1142 AllocLink, 1143 MEMORY_PROFILE_ALLOC_INFO_DATA, 1144 Link, 1145 MEMORY_PROFILE_ALLOC_INFO_SIGNATURE 1146 ); 1147 AllocInfo = &AllocInfoData->AllocInfo; 1148 if ((AllocInfo->Action & MEMORY_PROFILE_ACTION_BASIC_MASK) != BasicAction) { 1149 continue; 1150 } 1151 switch (BasicAction) { 1152 case MemoryProfileActionAllocatePages: 1153 if ((AllocInfo->Buffer <= (PHYSICAL_ADDRESS) (UINTN) Buffer) && 1154 ((AllocInfo->Buffer + AllocInfo->Size) >= ((PHYSICAL_ADDRESS) (UINTN) Buffer + Size))) { 1155 return AllocInfoData; 1156 } 1157 break; 1158 case MemoryProfileActionAllocatePool: 1159 if (AllocInfo->Buffer == (PHYSICAL_ADDRESS) (UINTN) Buffer) { 1160 return AllocInfoData; 1161 } 1162 break; 1163 default: 1164 ASSERT (FALSE); 1165 break; 1166 } 1167 } 1168 1169 return NULL; 1170 } 1171 1172 /** 1173 Update memory profile Free information. 1174 1175 @param CallerAddress Address of caller who call Free. 1176 @param Action This Free action. 1177 @param Size Buffer size. 1178 @param Buffer Buffer address. 1179 1180 @return EFI_SUCCESS Memory profile is updated. 1181 @return EFI_UNSUPPORTED Memory profile is unsupported. 1182 @return EFI_NOT_FOUND No matched allocate info found for free action. 1183 1184 **/ 1185 EFI_STATUS 1186 CoreUpdateProfileFree ( 1187 IN PHYSICAL_ADDRESS CallerAddress, 1188 IN MEMORY_PROFILE_ACTION Action, 1189 IN UINTN Size, 1190 IN VOID *Buffer 1191 ) 1192 { 1193 MEMORY_PROFILE_CONTEXT *Context; 1194 MEMORY_PROFILE_DRIVER_INFO *DriverInfo; 1195 MEMORY_PROFILE_ALLOC_INFO *AllocInfo; 1196 MEMORY_PROFILE_CONTEXT_DATA *ContextData; 1197 MEMORY_PROFILE_DRIVER_INFO_DATA *DriverInfoData; 1198 LIST_ENTRY *DriverLink; 1199 LIST_ENTRY *DriverInfoList; 1200 MEMORY_PROFILE_DRIVER_INFO_DATA *ThisDriverInfoData; 1201 MEMORY_PROFILE_ALLOC_INFO_DATA *AllocInfoData; 1202 UINTN ProfileMemoryIndex; 1203 MEMORY_PROFILE_ACTION BasicAction; 1204 BOOLEAN Found; 1205 1206 BasicAction = Action & MEMORY_PROFILE_ACTION_BASIC_MASK; 1207 1208 ContextData = GetMemoryProfileContext (); 1209 if (ContextData == NULL) { 1210 return EFI_UNSUPPORTED; 1211 } 1212 1213 DriverInfoData = GetMemoryProfileDriverInfoFromAddress (ContextData, CallerAddress); 1214 1215 // 1216 // Do not return if DriverInfoData == NULL here, 1217 // because driver A might free memory allocated by driver B. 1218 // 1219 1220 // 1221 // Need use do-while loop to find all possible records, 1222 // because one address might be recorded multiple times. 1223 // 1224 Found = FALSE; 1225 AllocInfoData = NULL; 1226 do { 1227 if (DriverInfoData != NULL) { 1228 switch (BasicAction) { 1229 case MemoryProfileActionFreePages: 1230 AllocInfoData = GetMemoryProfileAllocInfoFromAddress (DriverInfoData, MemoryProfileActionAllocatePages, Size, Buffer); 1231 break; 1232 case MemoryProfileActionFreePool: 1233 AllocInfoData = GetMemoryProfileAllocInfoFromAddress (DriverInfoData, MemoryProfileActionAllocatePool, 0, Buffer); 1234 break; 1235 default: 1236 ASSERT (FALSE); 1237 AllocInfoData = NULL; 1238 break; 1239 } 1240 } 1241 if (AllocInfoData == NULL) { 1242 // 1243 // Legal case, because driver A might free memory allocated by driver B, by some protocol. 1244 // 1245 DriverInfoList = ContextData->DriverInfoList; 1246 1247 for (DriverLink = DriverInfoList->ForwardLink; 1248 DriverLink != DriverInfoList; 1249 DriverLink = DriverLink->ForwardLink) { 1250 ThisDriverInfoData = CR ( 1251 DriverLink, 1252 MEMORY_PROFILE_DRIVER_INFO_DATA, 1253 Link, 1254 MEMORY_PROFILE_DRIVER_INFO_SIGNATURE 1255 ); 1256 switch (BasicAction) { 1257 case MemoryProfileActionFreePages: 1258 AllocInfoData = GetMemoryProfileAllocInfoFromAddress (ThisDriverInfoData, MemoryProfileActionAllocatePages, Size, Buffer); 1259 break; 1260 case MemoryProfileActionFreePool: 1261 AllocInfoData = GetMemoryProfileAllocInfoFromAddress (ThisDriverInfoData, MemoryProfileActionAllocatePool, 0, Buffer); 1262 break; 1263 default: 1264 ASSERT (FALSE); 1265 AllocInfoData = NULL; 1266 break; 1267 } 1268 if (AllocInfoData != NULL) { 1269 DriverInfoData = ThisDriverInfoData; 1270 break; 1271 } 1272 } 1273 1274 if (AllocInfoData == NULL) { 1275 // 1276 // If (!Found), no matched allocate info is found for this free action. 1277 // It is because the specified memory type allocate actions have been filtered by 1278 // CoreNeedRecordProfile(), but free actions may have no memory type information, 1279 // they can not be filtered by CoreNeedRecordProfile(). Then, they will be 1280 // filtered here. 1281 // 1282 // If (Found), it is normal exit path. 1283 return (Found ? EFI_SUCCESS : EFI_NOT_FOUND); 1284 } 1285 } 1286 1287 ASSERT (DriverInfoData != NULL); 1288 ASSERT (AllocInfoData != NULL); 1289 1290 Found = TRUE; 1291 1292 Context = &ContextData->Context; 1293 DriverInfo = &DriverInfoData->DriverInfo; 1294 AllocInfo = &AllocInfoData->AllocInfo; 1295 1296 DriverInfo->AllocRecordCount --; 1297 // 1298 // Update summary if and only if it is basic action. 1299 // 1300 if (AllocInfo->Action == (AllocInfo->Action & MEMORY_PROFILE_ACTION_BASIC_MASK)) { 1301 ProfileMemoryIndex = GetProfileMemoryIndex (AllocInfo->MemoryType); 1302 1303 Context->CurrentTotalUsage -= AllocInfo->Size; 1304 Context->CurrentTotalUsageByType[ProfileMemoryIndex] -= AllocInfo->Size; 1305 1306 DriverInfo->CurrentUsage -= AllocInfo->Size; 1307 DriverInfo->CurrentUsageByType[ProfileMemoryIndex] -= AllocInfo->Size; 1308 } 1309 1310 RemoveEntryList (&AllocInfoData->Link); 1311 1312 if (BasicAction == MemoryProfileActionFreePages) { 1313 if (AllocInfo->Buffer != (PHYSICAL_ADDRESS) (UINTN) Buffer) { 1314 CoreUpdateProfileAllocate ( 1315 AllocInfo->CallerAddress, 1316 AllocInfo->Action, 1317 AllocInfo->MemoryType, 1318 (UINTN) ((PHYSICAL_ADDRESS) (UINTN) Buffer - AllocInfo->Buffer), 1319 (VOID *) (UINTN) AllocInfo->Buffer, 1320 AllocInfoData->ActionString 1321 ); 1322 } 1323 if (AllocInfo->Buffer + AllocInfo->Size != ((PHYSICAL_ADDRESS) (UINTN) Buffer + Size)) { 1324 CoreUpdateProfileAllocate ( 1325 AllocInfo->CallerAddress, 1326 AllocInfo->Action, 1327 AllocInfo->MemoryType, 1328 (UINTN) ((AllocInfo->Buffer + AllocInfo->Size) - ((PHYSICAL_ADDRESS) (UINTN) Buffer + Size)), 1329 (VOID *) ((UINTN) Buffer + Size), 1330 AllocInfoData->ActionString 1331 ); 1332 } 1333 } 1334 1335 // 1336 // Use CoreInternalFreePool() that will not update profile for this FreePool action. 1337 // 1338 CoreInternalFreePool (AllocInfoData, NULL); 1339 } while (TRUE); 1340 } 1341 1342 /** 1343 Update memory profile information. 1344 1345 @param CallerAddress Address of caller who call Allocate or Free. 1346 @param Action This Allocate or Free action. 1347 @param MemoryType Memory type. 1348 EfiMaxMemoryType means the MemoryType is unknown. 1349 @param Size Buffer size. 1350 @param Buffer Buffer address. 1351 @param ActionString String for memory profile action. 1352 Only needed for user defined allocate action. 1353 1354 @return EFI_SUCCESS Memory profile is updated. 1355 @return EFI_UNSUPPORTED Memory profile is unsupported, 1356 or memory profile for the image is not required, 1357 or memory profile for the memory type is not required. 1358 @return EFI_ACCESS_DENIED It is during memory profile data getting. 1359 @return EFI_ABORTED Memory profile recording is not enabled. 1360 @return EFI_OUT_OF_RESOURCES No enough resource to update memory profile for allocate action. 1361 @return EFI_NOT_FOUND No matched allocate info found for free action. 1362 1363 **/ 1364 EFI_STATUS 1365 EFIAPI 1366 CoreUpdateProfile ( 1367 IN PHYSICAL_ADDRESS CallerAddress, 1368 IN MEMORY_PROFILE_ACTION Action, 1369 IN EFI_MEMORY_TYPE MemoryType, 1370 IN UINTN Size, // Valid for AllocatePages/FreePages/AllocatePool 1371 IN VOID *Buffer, 1372 IN CHAR8 *ActionString OPTIONAL 1373 ) 1374 { 1375 EFI_STATUS Status; 1376 MEMORY_PROFILE_CONTEXT_DATA *ContextData; 1377 MEMORY_PROFILE_ACTION BasicAction; 1378 1379 if (!IS_UEFI_MEMORY_PROFILE_ENABLED) { 1380 return EFI_UNSUPPORTED; 1381 } 1382 1383 if (mMemoryProfileGettingStatus) { 1384 return EFI_ACCESS_DENIED; 1385 } 1386 1387 if (!mMemoryProfileRecordingEnable) { 1388 return EFI_ABORTED; 1389 } 1390 1391 // 1392 // Get the basic action to know how to process the record 1393 // 1394 BasicAction = Action & MEMORY_PROFILE_ACTION_BASIC_MASK; 1395 1396 // 1397 // EfiMaxMemoryType means the MemoryType is unknown. 1398 // 1399 if (MemoryType != EfiMaxMemoryType) { 1400 // 1401 // Only record limited MemoryType. 1402 // 1403 if (!CoreNeedRecordProfile (MemoryType)) { 1404 return EFI_UNSUPPORTED; 1405 } 1406 } 1407 1408 ContextData = GetMemoryProfileContext (); 1409 if (ContextData == NULL) { 1410 return EFI_UNSUPPORTED; 1411 } 1412 1413 CoreAcquireMemoryProfileLock (); 1414 switch (BasicAction) { 1415 case MemoryProfileActionAllocatePages: 1416 Status = CoreUpdateProfileAllocate (CallerAddress, Action, MemoryType, Size, Buffer, ActionString); 1417 break; 1418 case MemoryProfileActionFreePages: 1419 Status = CoreUpdateProfileFree (CallerAddress, Action, Size, Buffer); 1420 break; 1421 case MemoryProfileActionAllocatePool: 1422 Status = CoreUpdateProfileAllocate (CallerAddress, Action, MemoryType, Size, Buffer, ActionString); 1423 break; 1424 case MemoryProfileActionFreePool: 1425 Status = CoreUpdateProfileFree (CallerAddress, Action, 0, Buffer); 1426 break; 1427 default: 1428 ASSERT (FALSE); 1429 Status = EFI_UNSUPPORTED; 1430 break; 1431 } 1432 CoreReleaseMemoryProfileLock (); 1433 1434 return Status; 1435 } 1436 1437 //////////////////// 1438 1439 /** 1440 Get memory profile data size. 1441 1442 @return Memory profile data size. 1443 1444 **/ 1445 UINTN 1446 MemoryProfileGetDataSize ( 1447 VOID 1448 ) 1449 { 1450 MEMORY_PROFILE_CONTEXT_DATA *ContextData; 1451 MEMORY_PROFILE_DRIVER_INFO_DATA *DriverInfoData; 1452 MEMORY_PROFILE_ALLOC_INFO_DATA *AllocInfoData; 1453 LIST_ENTRY *DriverInfoList; 1454 LIST_ENTRY *DriverLink; 1455 LIST_ENTRY *AllocInfoList; 1456 LIST_ENTRY *AllocLink; 1457 UINTN TotalSize; 1458 1459 1460 ContextData = GetMemoryProfileContext (); 1461 if (ContextData == NULL) { 1462 return 0; 1463 } 1464 1465 TotalSize = sizeof (MEMORY_PROFILE_CONTEXT); 1466 1467 DriverInfoList = ContextData->DriverInfoList; 1468 for (DriverLink = DriverInfoList->ForwardLink; 1469 DriverLink != DriverInfoList; 1470 DriverLink = DriverLink->ForwardLink) { 1471 DriverInfoData = CR ( 1472 DriverLink, 1473 MEMORY_PROFILE_DRIVER_INFO_DATA, 1474 Link, 1475 MEMORY_PROFILE_DRIVER_INFO_SIGNATURE 1476 ); 1477 TotalSize += DriverInfoData->DriverInfo.Header.Length; 1478 1479 AllocInfoList = DriverInfoData->AllocInfoList; 1480 for (AllocLink = AllocInfoList->ForwardLink; 1481 AllocLink != AllocInfoList; 1482 AllocLink = AllocLink->ForwardLink) { 1483 AllocInfoData = CR ( 1484 AllocLink, 1485 MEMORY_PROFILE_ALLOC_INFO_DATA, 1486 Link, 1487 MEMORY_PROFILE_ALLOC_INFO_SIGNATURE 1488 ); 1489 TotalSize += AllocInfoData->AllocInfo.Header.Length; 1490 } 1491 } 1492 1493 return TotalSize; 1494 } 1495 1496 /** 1497 Copy memory profile data. 1498 1499 @param ProfileBuffer The buffer to hold memory profile data. 1500 1501 **/ 1502 VOID 1503 MemoryProfileCopyData ( 1504 IN VOID *ProfileBuffer 1505 ) 1506 { 1507 MEMORY_PROFILE_CONTEXT *Context; 1508 MEMORY_PROFILE_DRIVER_INFO *DriverInfo; 1509 MEMORY_PROFILE_ALLOC_INFO *AllocInfo; 1510 MEMORY_PROFILE_CONTEXT_DATA *ContextData; 1511 MEMORY_PROFILE_DRIVER_INFO_DATA *DriverInfoData; 1512 MEMORY_PROFILE_ALLOC_INFO_DATA *AllocInfoData; 1513 LIST_ENTRY *DriverInfoList; 1514 LIST_ENTRY *DriverLink; 1515 LIST_ENTRY *AllocInfoList; 1516 LIST_ENTRY *AllocLink; 1517 UINTN PdbSize; 1518 UINTN ActionStringSize; 1519 1520 ContextData = GetMemoryProfileContext (); 1521 if (ContextData == NULL) { 1522 return ; 1523 } 1524 1525 Context = ProfileBuffer; 1526 CopyMem (Context, &ContextData->Context, sizeof (MEMORY_PROFILE_CONTEXT)); 1527 DriverInfo = (MEMORY_PROFILE_DRIVER_INFO *) (Context + 1); 1528 1529 DriverInfoList = ContextData->DriverInfoList; 1530 for (DriverLink = DriverInfoList->ForwardLink; 1531 DriverLink != DriverInfoList; 1532 DriverLink = DriverLink->ForwardLink) { 1533 DriverInfoData = CR ( 1534 DriverLink, 1535 MEMORY_PROFILE_DRIVER_INFO_DATA, 1536 Link, 1537 MEMORY_PROFILE_DRIVER_INFO_SIGNATURE 1538 ); 1539 CopyMem (DriverInfo, &DriverInfoData->DriverInfo, sizeof (MEMORY_PROFILE_DRIVER_INFO)); 1540 if (DriverInfo->PdbStringOffset != 0) { 1541 PdbSize = AsciiStrSize (DriverInfoData->PdbString); 1542 CopyMem ((VOID *) ((UINTN) DriverInfo + DriverInfo->PdbStringOffset), DriverInfoData->PdbString, PdbSize); 1543 } 1544 AllocInfo = (MEMORY_PROFILE_ALLOC_INFO *) ((UINTN) DriverInfo + DriverInfo->Header.Length); 1545 1546 AllocInfoList = DriverInfoData->AllocInfoList; 1547 for (AllocLink = AllocInfoList->ForwardLink; 1548 AllocLink != AllocInfoList; 1549 AllocLink = AllocLink->ForwardLink) { 1550 AllocInfoData = CR ( 1551 AllocLink, 1552 MEMORY_PROFILE_ALLOC_INFO_DATA, 1553 Link, 1554 MEMORY_PROFILE_ALLOC_INFO_SIGNATURE 1555 ); 1556 CopyMem (AllocInfo, &AllocInfoData->AllocInfo, sizeof (MEMORY_PROFILE_ALLOC_INFO)); 1557 if (AllocInfo->ActionStringOffset != 0) { 1558 ActionStringSize = AsciiStrSize (AllocInfoData->ActionString); 1559 CopyMem ((VOID *) ((UINTN) AllocInfo + AllocInfo->ActionStringOffset), AllocInfoData->ActionString, ActionStringSize); 1560 } 1561 AllocInfo = (MEMORY_PROFILE_ALLOC_INFO *) ((UINTN) AllocInfo + AllocInfo->Header.Length); 1562 } 1563 1564 DriverInfo = (MEMORY_PROFILE_DRIVER_INFO *) AllocInfo; 1565 } 1566 } 1567 1568 /** 1569 Get memory profile data. 1570 1571 @param[in] This The EDKII_MEMORY_PROFILE_PROTOCOL instance. 1572 @param[in, out] ProfileSize On entry, points to the size in bytes of the ProfileBuffer. 1573 On return, points to the size of the data returned in ProfileBuffer. 1574 @param[out] ProfileBuffer Profile buffer. 1575 1576 @return EFI_SUCCESS Get the memory profile data successfully. 1577 @return EFI_UNSUPPORTED Memory profile is unsupported. 1578 @return EFI_BUFFER_TO_SMALL The ProfileSize is too small for the resulting data. 1579 ProfileSize is updated with the size required. 1580 1581 **/ 1582 EFI_STATUS 1583 EFIAPI 1584 ProfileProtocolGetData ( 1585 IN EDKII_MEMORY_PROFILE_PROTOCOL *This, 1586 IN OUT UINT64 *ProfileSize, 1587 OUT VOID *ProfileBuffer 1588 ) 1589 { 1590 UINTN Size; 1591 MEMORY_PROFILE_CONTEXT_DATA *ContextData; 1592 BOOLEAN MemoryProfileGettingStatus; 1593 1594 ContextData = GetMemoryProfileContext (); 1595 if (ContextData == NULL) { 1596 return EFI_UNSUPPORTED; 1597 } 1598 1599 MemoryProfileGettingStatus = mMemoryProfileGettingStatus; 1600 mMemoryProfileGettingStatus = TRUE; 1601 1602 Size = MemoryProfileGetDataSize (); 1603 1604 if (*ProfileSize < Size) { 1605 *ProfileSize = Size; 1606 mMemoryProfileGettingStatus = MemoryProfileGettingStatus; 1607 return EFI_BUFFER_TOO_SMALL; 1608 } 1609 1610 *ProfileSize = Size; 1611 MemoryProfileCopyData (ProfileBuffer); 1612 1613 mMemoryProfileGettingStatus = MemoryProfileGettingStatus; 1614 return EFI_SUCCESS; 1615 } 1616 1617 /** 1618 Register image to memory profile. 1619 1620 @param[in] This The EDKII_MEMORY_PROFILE_PROTOCOL instance. 1621 @param[in] FilePath File path of the image. 1622 @param[in] ImageBase Image base address. 1623 @param[in] ImageSize Image size. 1624 @param[in] FileType File type of the image. 1625 1626 @return EFI_SUCCESS Register successfully. 1627 @return EFI_UNSUPPORTED Memory profile is unsupported, 1628 or memory profile for the image is not required. 1629 @return EFI_OUT_OF_RESOURCES No enough resource for this register. 1630 1631 **/ 1632 EFI_STATUS 1633 EFIAPI 1634 ProfileProtocolRegisterImage ( 1635 IN EDKII_MEMORY_PROFILE_PROTOCOL *This, 1636 IN EFI_DEVICE_PATH_PROTOCOL *FilePath, 1637 IN PHYSICAL_ADDRESS ImageBase, 1638 IN UINT64 ImageSize, 1639 IN EFI_FV_FILETYPE FileType 1640 ) 1641 { 1642 EFI_STATUS Status; 1643 LOADED_IMAGE_PRIVATE_DATA DriverEntry; 1644 VOID *EntryPointInImage; 1645 1646 ZeroMem (&DriverEntry, sizeof (DriverEntry)); 1647 DriverEntry.Info.FilePath = FilePath; 1648 DriverEntry.ImageContext.ImageAddress = ImageBase; 1649 DriverEntry.ImageContext.ImageSize = ImageSize; 1650 Status = InternalPeCoffGetEntryPoint ((VOID *) (UINTN) ImageBase, &EntryPointInImage); 1651 ASSERT_EFI_ERROR (Status); 1652 DriverEntry.ImageContext.EntryPoint = (PHYSICAL_ADDRESS) (UINTN) EntryPointInImage; 1653 DriverEntry.ImageContext.ImageType = InternalPeCoffGetSubsystem ((VOID *) (UINTN) ImageBase); 1654 1655 return RegisterMemoryProfileImage (&DriverEntry, FileType); 1656 } 1657 1658 /** 1659 Unregister image from memory profile. 1660 1661 @param[in] This The EDKII_MEMORY_PROFILE_PROTOCOL instance. 1662 @param[in] FilePath File path of the image. 1663 @param[in] ImageBase Image base address. 1664 @param[in] ImageSize Image size. 1665 1666 @return EFI_SUCCESS Unregister successfully. 1667 @return EFI_UNSUPPORTED Memory profile is unsupported, 1668 or memory profile for the image is not required. 1669 @return EFI_NOT_FOUND The image is not found. 1670 1671 **/ 1672 EFI_STATUS 1673 EFIAPI 1674 ProfileProtocolUnregisterImage ( 1675 IN EDKII_MEMORY_PROFILE_PROTOCOL *This, 1676 IN EFI_DEVICE_PATH_PROTOCOL *FilePath, 1677 IN PHYSICAL_ADDRESS ImageBase, 1678 IN UINT64 ImageSize 1679 ) 1680 { 1681 EFI_STATUS Status; 1682 LOADED_IMAGE_PRIVATE_DATA DriverEntry; 1683 VOID *EntryPointInImage; 1684 1685 ZeroMem (&DriverEntry, sizeof (DriverEntry)); 1686 DriverEntry.Info.FilePath = FilePath; 1687 DriverEntry.ImageContext.ImageAddress = ImageBase; 1688 DriverEntry.ImageContext.ImageSize = ImageSize; 1689 Status = InternalPeCoffGetEntryPoint ((VOID *) (UINTN) ImageBase, &EntryPointInImage); 1690 ASSERT_EFI_ERROR (Status); 1691 DriverEntry.ImageContext.EntryPoint = (PHYSICAL_ADDRESS) (UINTN) EntryPointInImage; 1692 1693 return UnregisterMemoryProfileImage (&DriverEntry); 1694 } 1695 1696 /** 1697 Get memory profile recording state. 1698 1699 @param[in] This The EDKII_MEMORY_PROFILE_PROTOCOL instance. 1700 @param[out] RecordingState Recording state. 1701 1702 @return EFI_SUCCESS Memory profile recording state is returned. 1703 @return EFI_UNSUPPORTED Memory profile is unsupported. 1704 @return EFI_INVALID_PARAMETER RecordingState is NULL. 1705 1706 **/ 1707 EFI_STATUS 1708 EFIAPI 1709 ProfileProtocolGetRecordingState ( 1710 IN EDKII_MEMORY_PROFILE_PROTOCOL *This, 1711 OUT BOOLEAN *RecordingState 1712 ) 1713 { 1714 MEMORY_PROFILE_CONTEXT_DATA *ContextData; 1715 1716 ContextData = GetMemoryProfileContext (); 1717 if (ContextData == NULL) { 1718 return EFI_UNSUPPORTED; 1719 } 1720 1721 if (RecordingState == NULL) { 1722 return EFI_INVALID_PARAMETER; 1723 } 1724 *RecordingState = mMemoryProfileRecordingEnable; 1725 return EFI_SUCCESS; 1726 } 1727 1728 /** 1729 Set memory profile recording state. 1730 1731 @param[in] This The EDKII_MEMORY_PROFILE_PROTOCOL instance. 1732 @param[in] RecordingState Recording state. 1733 1734 @return EFI_SUCCESS Set memory profile recording state successfully. 1735 @return EFI_UNSUPPORTED Memory profile is unsupported. 1736 1737 **/ 1738 EFI_STATUS 1739 EFIAPI 1740 ProfileProtocolSetRecordingState ( 1741 IN EDKII_MEMORY_PROFILE_PROTOCOL *This, 1742 IN BOOLEAN RecordingState 1743 ) 1744 { 1745 MEMORY_PROFILE_CONTEXT_DATA *ContextData; 1746 1747 ContextData = GetMemoryProfileContext (); 1748 if (ContextData == NULL) { 1749 return EFI_UNSUPPORTED; 1750 } 1751 1752 mMemoryProfileRecordingEnable = RecordingState; 1753 return EFI_SUCCESS; 1754 } 1755 1756 /** 1757 Record memory profile of multilevel caller. 1758 1759 @param[in] This The EDKII_MEMORY_PROFILE_PROTOCOL instance. 1760 @param[in] CallerAddress Address of caller. 1761 @param[in] Action Memory profile action. 1762 @param[in] MemoryType Memory type. 1763 EfiMaxMemoryType means the MemoryType is unknown. 1764 @param[in] Buffer Buffer address. 1765 @param[in] Size Buffer size. 1766 @param[in] ActionString String for memory profile action. 1767 Only needed for user defined allocate action. 1768 1769 @return EFI_SUCCESS Memory profile is updated. 1770 @return EFI_UNSUPPORTED Memory profile is unsupported, 1771 or memory profile for the image is not required, 1772 or memory profile for the memory type is not required. 1773 @return EFI_ACCESS_DENIED It is during memory profile data getting. 1774 @return EFI_ABORTED Memory profile recording is not enabled. 1775 @return EFI_OUT_OF_RESOURCES No enough resource to update memory profile for allocate action. 1776 @return EFI_NOT_FOUND No matched allocate info found for free action. 1777 1778 **/ 1779 EFI_STATUS 1780 EFIAPI 1781 ProfileProtocolRecord ( 1782 IN EDKII_MEMORY_PROFILE_PROTOCOL *This, 1783 IN PHYSICAL_ADDRESS CallerAddress, 1784 IN MEMORY_PROFILE_ACTION Action, 1785 IN EFI_MEMORY_TYPE MemoryType, 1786 IN VOID *Buffer, 1787 IN UINTN Size, 1788 IN CHAR8 *ActionString OPTIONAL 1789 ) 1790 { 1791 return CoreUpdateProfile (CallerAddress, Action, MemoryType, Size, Buffer, ActionString); 1792 } 1793 1794 //////////////////// 1795