1 /** @file 2 Support routines for SMRAM 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 "PiSmmCore.h" 16 17 #define IS_SMRAM_PROFILE_ENABLED ((PcdGet8 (PcdMemoryProfilePropertyMask) & BIT1) != 0) 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 // When free memory less than 4 pages, dump it. 46 // 47 #define SMRAM_INFO_DUMP_PAGE_THRESHOLD 4 48 49 GLOBAL_REMOVE_IF_UNREFERENCED MEMORY_PROFILE_FREE_MEMORY mSmramFreeMemory = { 50 { 51 MEMORY_PROFILE_FREE_MEMORY_SIGNATURE, 52 sizeof (MEMORY_PROFILE_FREE_MEMORY), 53 MEMORY_PROFILE_FREE_MEMORY_REVISION 54 }, 55 0, 56 0 57 }; 58 59 GLOBAL_REMOVE_IF_UNREFERENCED LIST_ENTRY mImageQueue = INITIALIZE_LIST_HEAD_VARIABLE (mImageQueue); 60 GLOBAL_REMOVE_IF_UNREFERENCED MEMORY_PROFILE_CONTEXT_DATA mSmramProfileContext = { 61 MEMORY_PROFILE_CONTEXT_SIGNATURE, 62 { 63 { 64 MEMORY_PROFILE_CONTEXT_SIGNATURE, 65 sizeof (MEMORY_PROFILE_CONTEXT), 66 MEMORY_PROFILE_CONTEXT_REVISION 67 }, 68 0, 69 0, 70 {0}, 71 {0}, 72 0, 73 0, 74 0 75 }, 76 &mImageQueue, 77 }; 78 GLOBAL_REMOVE_IF_UNREFERENCED MEMORY_PROFILE_CONTEXT_DATA *mSmramProfileContextPtr = NULL; 79 80 BOOLEAN mSmramReadyToLock; 81 BOOLEAN mSmramProfileGettingStatus = FALSE; 82 BOOLEAN mSmramProfileRecordingEnable = MEMORY_PROFILE_RECORDING_DISABLE; 83 EFI_DEVICE_PATH_PROTOCOL *mSmramProfileDriverPath; 84 UINTN mSmramProfileDriverPathSize; 85 86 /** 87 Dump SMRAM infromation. 88 89 **/ 90 VOID 91 DumpSmramInfo ( 92 VOID 93 ); 94 95 /** 96 Get memory profile data. 97 98 @param[in] This The EDKII_SMM_MEMORY_PROFILE_PROTOCOL instance. 99 @param[in, out] ProfileSize On entry, points to the size in bytes of the ProfileBuffer. 100 On return, points to the size of the data returned in ProfileBuffer. 101 @param[out] ProfileBuffer Profile buffer. 102 103 @return EFI_SUCCESS Get the memory profile data successfully. 104 @return EFI_UNSUPPORTED Memory profile is unsupported. 105 @return EFI_BUFFER_TO_SMALL The ProfileSize is too small for the resulting data. 106 ProfileSize is updated with the size required. 107 108 **/ 109 EFI_STATUS 110 EFIAPI 111 SmramProfileProtocolGetData ( 112 IN EDKII_SMM_MEMORY_PROFILE_PROTOCOL *This, 113 IN OUT UINT64 *ProfileSize, 114 OUT VOID *ProfileBuffer 115 ); 116 117 /** 118 Register image to memory profile. 119 120 @param[in] This The EDKII_SMM_MEMORY_PROFILE_PROTOCOL instance. 121 @param[in] FilePath File path of the image. 122 @param[in] ImageBase Image base address. 123 @param[in] ImageSize Image size. 124 @param[in] FileType File type of the image. 125 126 @return EFI_SUCCESS Register successfully. 127 @return EFI_UNSUPPORTED Memory profile is unsupported, 128 or memory profile for the image is not required. 129 @return EFI_OUT_OF_RESOURCE No enough resource for this register. 130 131 **/ 132 EFI_STATUS 133 EFIAPI 134 SmramProfileProtocolRegisterImage ( 135 IN EDKII_SMM_MEMORY_PROFILE_PROTOCOL *This, 136 IN EFI_DEVICE_PATH_PROTOCOL *FilePath, 137 IN PHYSICAL_ADDRESS ImageBase, 138 IN UINT64 ImageSize, 139 IN EFI_FV_FILETYPE FileType 140 ); 141 142 /** 143 Unregister image from memory profile. 144 145 @param[in] This The EDKII_SMM_MEMORY_PROFILE_PROTOCOL instance. 146 @param[in] FilePath File path of the image. 147 @param[in] ImageBase Image base address. 148 @param[in] ImageSize Image size. 149 150 @return EFI_SUCCESS Unregister successfully. 151 @return EFI_UNSUPPORTED Memory profile is unsupported, 152 or memory profile for the image is not required. 153 @return EFI_NOT_FOUND The image is not found. 154 155 **/ 156 EFI_STATUS 157 EFIAPI 158 SmramProfileProtocolUnregisterImage ( 159 IN EDKII_SMM_MEMORY_PROFILE_PROTOCOL *This, 160 IN EFI_DEVICE_PATH_PROTOCOL *FilePath, 161 IN PHYSICAL_ADDRESS ImageBase, 162 IN UINT64 ImageSize 163 ); 164 165 /** 166 Get memory profile recording state. 167 168 @param[in] This The EDKII_SMM_MEMORY_PROFILE_PROTOCOL instance. 169 @param[out] RecordingState Recording state. 170 171 @return EFI_SUCCESS Memory profile recording state is returned. 172 @return EFI_UNSUPPORTED Memory profile is unsupported. 173 @return EFI_INVALID_PARAMETER RecordingState is NULL. 174 175 **/ 176 EFI_STATUS 177 EFIAPI 178 SmramProfileProtocolGetRecordingState ( 179 IN EDKII_SMM_MEMORY_PROFILE_PROTOCOL *This, 180 OUT BOOLEAN *RecordingState 181 ); 182 183 /** 184 Set memory profile recording state. 185 186 @param[in] This The EDKII_SMM_MEMORY_PROFILE_PROTOCOL instance. 187 @param[in] RecordingState Recording state. 188 189 @return EFI_SUCCESS Set memory profile recording state successfully. 190 @return EFI_UNSUPPORTED Memory profile is unsupported. 191 192 **/ 193 EFI_STATUS 194 EFIAPI 195 SmramProfileProtocolSetRecordingState ( 196 IN EDKII_SMM_MEMORY_PROFILE_PROTOCOL *This, 197 IN BOOLEAN RecordingState 198 ); 199 200 /** 201 Record memory profile of multilevel caller. 202 203 @param[in] This The EDKII_SMM_MEMORY_PROFILE_PROTOCOL instance. 204 @param[in] CallerAddress Address of caller. 205 @param[in] Action Memory profile action. 206 @param[in] MemoryType Memory type. 207 EfiMaxMemoryType means the MemoryType is unknown. 208 @param[in] Buffer Buffer address. 209 @param[in] Size Buffer size. 210 @param[in] ActionString String for memory profile action. 211 Only needed for user defined allocate action. 212 213 @return EFI_SUCCESS Memory profile is updated. 214 @return EFI_UNSUPPORTED Memory profile is unsupported, 215 or memory profile for the image is not required, 216 or memory profile for the memory type is not required. 217 @return EFI_ACCESS_DENIED It is during memory profile data getting. 218 @return EFI_ABORTED Memory profile recording is not enabled. 219 @return EFI_OUT_OF_RESOURCES No enough resource to update memory profile for allocate action. 220 @return EFI_NOT_FOUND No matched allocate info found for free action. 221 222 **/ 223 EFI_STATUS 224 EFIAPI 225 SmramProfileProtocolRecord ( 226 IN EDKII_SMM_MEMORY_PROFILE_PROTOCOL *This, 227 IN PHYSICAL_ADDRESS CallerAddress, 228 IN MEMORY_PROFILE_ACTION Action, 229 IN EFI_MEMORY_TYPE MemoryType, 230 IN VOID *Buffer, 231 IN UINTN Size, 232 IN CHAR8 *ActionString OPTIONAL 233 ); 234 235 EDKII_SMM_MEMORY_PROFILE_PROTOCOL mSmmProfileProtocol = { 236 SmramProfileProtocolGetData, 237 SmramProfileProtocolRegisterImage, 238 SmramProfileProtocolUnregisterImage, 239 SmramProfileProtocolGetRecordingState, 240 SmramProfileProtocolSetRecordingState, 241 SmramProfileProtocolRecord, 242 }; 243 244 /** 245 Return SMRAM profile context. 246 247 @return SMRAM profile context. 248 249 **/ 250 MEMORY_PROFILE_CONTEXT_DATA * 251 GetSmramProfileContext ( 252 VOID 253 ) 254 { 255 return mSmramProfileContextPtr; 256 } 257 258 /** 259 Retrieves the magic value from the PE/COFF header. 260 261 @param Hdr The buffer in which to return the PE32, PE32+, or TE header. 262 263 @return EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC - Image is PE32 264 @return EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC - Image is PE32+ 265 266 **/ 267 UINT16 268 InternalPeCoffGetPeHeaderMagicValue ( 269 IN EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION Hdr 270 ) 271 { 272 // 273 // NOTE: Some versions of Linux ELILO for Itanium have an incorrect magic value 274 // in the PE/COFF Header. If the MachineType is Itanium(IA64) and the 275 // Magic value in the OptionalHeader is EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC 276 // then override the returned value to EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC 277 // 278 if (Hdr.Pe32->FileHeader.Machine == IMAGE_FILE_MACHINE_IA64 && Hdr.Pe32->OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) { 279 return EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC; 280 } 281 // 282 // Return the magic value from the PC/COFF Optional Header 283 // 284 return Hdr.Pe32->OptionalHeader.Magic; 285 } 286 287 /** 288 Retrieves and returns the Subsystem of a PE/COFF image that has been loaded into system memory. 289 If Pe32Data is NULL, then ASSERT(). 290 291 @param Pe32Data The pointer to the PE/COFF image that is loaded in system memory. 292 293 @return The Subsystem of the PE/COFF image. 294 295 **/ 296 UINT16 297 InternalPeCoffGetSubsystem ( 298 IN VOID *Pe32Data 299 ) 300 { 301 EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION Hdr; 302 EFI_IMAGE_DOS_HEADER *DosHdr; 303 UINT16 Magic; 304 305 ASSERT (Pe32Data != NULL); 306 307 DosHdr = (EFI_IMAGE_DOS_HEADER *) Pe32Data; 308 if (DosHdr->e_magic == EFI_IMAGE_DOS_SIGNATURE) { 309 // 310 // DOS image header is present, so read the PE header after the DOS image header. 311 // 312 Hdr.Pe32 = (EFI_IMAGE_NT_HEADERS32 *) ((UINTN) Pe32Data + (UINTN) ((DosHdr->e_lfanew) & 0x0ffff)); 313 } else { 314 // 315 // DOS image header is not present, so PE header is at the image base. 316 // 317 Hdr.Pe32 = (EFI_IMAGE_NT_HEADERS32 *) Pe32Data; 318 } 319 320 if (Hdr.Te->Signature == EFI_TE_IMAGE_HEADER_SIGNATURE) { 321 return Hdr.Te->Subsystem; 322 } else if (Hdr.Pe32->Signature == EFI_IMAGE_NT_SIGNATURE) { 323 Magic = InternalPeCoffGetPeHeaderMagicValue (Hdr); 324 if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) { 325 return Hdr.Pe32->OptionalHeader.Subsystem; 326 } else if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC) { 327 return Hdr.Pe32Plus->OptionalHeader.Subsystem; 328 } 329 } 330 331 return 0x0000; 332 } 333 334 /** 335 Retrieves and returns a pointer to the entry point to a PE/COFF image that has been loaded 336 into system memory with the PE/COFF Loader Library functions. 337 338 Retrieves the entry point to the PE/COFF image specified by Pe32Data and returns this entry 339 point in EntryPoint. If the entry point could not be retrieved from the PE/COFF image, then 340 return RETURN_INVALID_PARAMETER. Otherwise return RETURN_SUCCESS. 341 If Pe32Data is NULL, then ASSERT(). 342 If EntryPoint is NULL, then ASSERT(). 343 344 @param Pe32Data The pointer to the PE/COFF image that is loaded in system memory. 345 @param EntryPoint The pointer to entry point to the PE/COFF image to return. 346 347 @retval RETURN_SUCCESS EntryPoint was returned. 348 @retval RETURN_INVALID_PARAMETER The entry point could not be found in the PE/COFF image. 349 350 **/ 351 RETURN_STATUS 352 InternalPeCoffGetEntryPoint ( 353 IN VOID *Pe32Data, 354 OUT VOID **EntryPoint 355 ) 356 { 357 EFI_IMAGE_DOS_HEADER *DosHdr; 358 EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION Hdr; 359 360 ASSERT (Pe32Data != NULL); 361 ASSERT (EntryPoint != NULL); 362 363 DosHdr = (EFI_IMAGE_DOS_HEADER *) Pe32Data; 364 if (DosHdr->e_magic == EFI_IMAGE_DOS_SIGNATURE) { 365 // 366 // DOS image header is present, so read the PE header after the DOS image header. 367 // 368 Hdr.Pe32 = (EFI_IMAGE_NT_HEADERS32 *) ((UINTN) Pe32Data + (UINTN) ((DosHdr->e_lfanew) & 0x0ffff)); 369 } else { 370 // 371 // DOS image header is not present, so PE header is at the image base. 372 // 373 Hdr.Pe32 = (EFI_IMAGE_NT_HEADERS32 *) Pe32Data; 374 } 375 376 // 377 // Calculate the entry point relative to the start of the image. 378 // AddressOfEntryPoint is common for PE32 & PE32+ 379 // 380 if (Hdr.Te->Signature == EFI_TE_IMAGE_HEADER_SIGNATURE) { 381 *EntryPoint = (VOID *) ((UINTN) Pe32Data + (UINTN) (Hdr.Te->AddressOfEntryPoint & 0x0ffffffff) + sizeof (EFI_TE_IMAGE_HEADER) - Hdr.Te->StrippedSize); 382 return RETURN_SUCCESS; 383 } else if (Hdr.Pe32->Signature == EFI_IMAGE_NT_SIGNATURE) { 384 *EntryPoint = (VOID *) ((UINTN) Pe32Data + (UINTN) (Hdr.Pe32->OptionalHeader.AddressOfEntryPoint & 0x0ffffffff)); 385 return RETURN_SUCCESS; 386 } 387 388 return RETURN_UNSUPPORTED; 389 } 390 391 /** 392 Build driver info. 393 394 @param ContextData Memory profile context. 395 @param FileName File name of the image. 396 @param ImageBase Image base address. 397 @param ImageSize Image size. 398 @param EntryPoint Entry point of the image. 399 @param ImageSubsystem Image subsystem of the image. 400 @param FileType File type of the image. 401 402 @return Pointer to memory profile driver info. 403 404 **/ 405 MEMORY_PROFILE_DRIVER_INFO_DATA * 406 BuildDriverInfo ( 407 IN MEMORY_PROFILE_CONTEXT_DATA *ContextData, 408 IN EFI_GUID *FileName, 409 IN PHYSICAL_ADDRESS ImageBase, 410 IN UINT64 ImageSize, 411 IN PHYSICAL_ADDRESS EntryPoint, 412 IN UINT16 ImageSubsystem, 413 IN EFI_FV_FILETYPE FileType 414 ) 415 { 416 EFI_STATUS Status; 417 MEMORY_PROFILE_DRIVER_INFO *DriverInfo; 418 MEMORY_PROFILE_DRIVER_INFO_DATA *DriverInfoData; 419 VOID *EntryPointInImage; 420 CHAR8 *PdbString; 421 UINTN PdbSize; 422 UINTN PdbOccupiedSize; 423 424 PdbSize = 0; 425 PdbOccupiedSize = 0; 426 PdbString = NULL; 427 if (ImageBase != 0) { 428 PdbString = PeCoffLoaderGetPdbPointer ((VOID*) (UINTN) ImageBase); 429 if (PdbString != NULL) { 430 PdbSize = AsciiStrSize (PdbString); 431 PdbOccupiedSize = GET_OCCUPIED_SIZE (PdbSize, sizeof (UINT64)); 432 } 433 } 434 435 // 436 // Use SmmInternalAllocatePool() that will not update profile for this AllocatePool action. 437 // 438 Status = SmmInternalAllocatePool ( 439 EfiRuntimeServicesData, 440 sizeof (*DriverInfoData) + sizeof (LIST_ENTRY) + PdbSize, 441 (VOID **) &DriverInfoData 442 ); 443 if (EFI_ERROR (Status)) { 444 return NULL; 445 } 446 ASSERT (DriverInfoData != NULL); 447 448 ZeroMem (DriverInfoData, sizeof (*DriverInfoData)); 449 450 DriverInfo = &DriverInfoData->DriverInfo; 451 DriverInfoData->Signature = MEMORY_PROFILE_DRIVER_INFO_SIGNATURE; 452 DriverInfo->Header.Signature = MEMORY_PROFILE_DRIVER_INFO_SIGNATURE; 453 DriverInfo->Header.Length = (UINT16) (sizeof (MEMORY_PROFILE_DRIVER_INFO) + PdbOccupiedSize); 454 DriverInfo->Header.Revision = MEMORY_PROFILE_DRIVER_INFO_REVISION; 455 if (FileName != NULL) { 456 CopyMem (&DriverInfo->FileName, FileName, sizeof (EFI_GUID)); 457 } 458 DriverInfo->ImageBase = ImageBase; 459 DriverInfo->ImageSize = ImageSize; 460 DriverInfo->EntryPoint = EntryPoint; 461 DriverInfo->ImageSubsystem = ImageSubsystem; 462 if ((EntryPoint != 0) && ((EntryPoint < ImageBase) || (EntryPoint >= (ImageBase + ImageSize)))) { 463 // 464 // If the EntryPoint is not in the range of image buffer, it should come from emulation environment. 465 // So patch ImageBuffer here to align the EntryPoint. 466 // 467 Status = InternalPeCoffGetEntryPoint ((VOID *) (UINTN) ImageBase, &EntryPointInImage); 468 ASSERT_EFI_ERROR (Status); 469 DriverInfo->ImageBase = ImageBase + EntryPoint - (PHYSICAL_ADDRESS) (UINTN) EntryPointInImage; 470 } 471 DriverInfo->FileType = FileType; 472 DriverInfoData->AllocInfoList = (LIST_ENTRY *) (DriverInfoData + 1); 473 InitializeListHead (DriverInfoData->AllocInfoList); 474 DriverInfo->CurrentUsage = 0; 475 DriverInfo->PeakUsage = 0; 476 DriverInfo->AllocRecordCount = 0; 477 if (PdbSize != 0) { 478 DriverInfo->PdbStringOffset = (UINT16) sizeof (MEMORY_PROFILE_DRIVER_INFO); 479 DriverInfoData->PdbString = (CHAR8 *) (DriverInfoData->AllocInfoList + 1); 480 CopyMem (DriverInfoData->PdbString, PdbString, PdbSize); 481 } else { 482 DriverInfo->PdbStringOffset = 0; 483 DriverInfoData->PdbString = NULL; 484 } 485 486 InsertTailList (ContextData->DriverInfoList, &DriverInfoData->Link); 487 ContextData->Context.ImageCount ++; 488 ContextData->Context.TotalImageSize += DriverInfo->ImageSize; 489 490 return DriverInfoData; 491 } 492 493 /** 494 Register image to DXE. 495 496 @param FileName File name of the image. 497 @param ImageBase Image base address. 498 @param ImageSize Image size. 499 @param FileType File type of the image. 500 501 **/ 502 VOID 503 RegisterImageToDxe ( 504 IN EFI_GUID *FileName, 505 IN PHYSICAL_ADDRESS ImageBase, 506 IN UINT64 ImageSize, 507 IN EFI_FV_FILETYPE FileType 508 ) 509 { 510 EFI_STATUS Status; 511 EDKII_MEMORY_PROFILE_PROTOCOL *ProfileProtocol; 512 MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *FilePath; 513 UINT8 TempBuffer[sizeof (MEDIA_FW_VOL_FILEPATH_DEVICE_PATH) + sizeof (EFI_DEVICE_PATH_PROTOCOL)]; 514 515 if (IS_UEFI_MEMORY_PROFILE_ENABLED) { 516 517 FilePath = (MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *)TempBuffer; 518 Status = gBS->LocateProtocol (&gEdkiiMemoryProfileGuid, NULL, (VOID **) &ProfileProtocol); 519 if (!EFI_ERROR (Status)) { 520 EfiInitializeFwVolDevicepathNode (FilePath, FileName); 521 SetDevicePathEndNode (FilePath + 1); 522 523 Status = ProfileProtocol->RegisterImage ( 524 ProfileProtocol, 525 (EFI_DEVICE_PATH_PROTOCOL *) FilePath, 526 ImageBase, 527 ImageSize, 528 FileType 529 ); 530 } 531 } 532 } 533 534 /** 535 Unregister image from DXE. 536 537 @param FileName File name of the image. 538 @param ImageBase Image base address. 539 @param ImageSize Image size. 540 541 **/ 542 VOID 543 UnregisterImageFromDxe ( 544 IN EFI_GUID *FileName, 545 IN PHYSICAL_ADDRESS ImageBase, 546 IN UINT64 ImageSize 547 ) 548 { 549 EFI_STATUS Status; 550 EDKII_MEMORY_PROFILE_PROTOCOL *ProfileProtocol; 551 MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *FilePath; 552 UINT8 TempBuffer[sizeof (MEDIA_FW_VOL_FILEPATH_DEVICE_PATH) + sizeof (EFI_DEVICE_PATH_PROTOCOL)]; 553 554 if (IS_UEFI_MEMORY_PROFILE_ENABLED) { 555 556 FilePath = (MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *)TempBuffer; 557 Status = gBS->LocateProtocol (&gEdkiiMemoryProfileGuid, NULL, (VOID *) &ProfileProtocol); 558 if (!EFI_ERROR (Status)) { 559 EfiInitializeFwVolDevicepathNode (FilePath, FileName); 560 SetDevicePathEndNode (FilePath + 1); 561 562 Status = ProfileProtocol->UnregisterImage ( 563 ProfileProtocol, 564 (EFI_DEVICE_PATH_PROTOCOL *) FilePath, 565 ImageBase, 566 ImageSize 567 ); 568 } 569 } 570 } 571 572 /** 573 Return if record for this driver is needed.. 574 575 @param DriverFilePath Driver file path. 576 577 @retval TRUE Record for this driver is needed. 578 @retval FALSE Record for this driver is not needed. 579 580 **/ 581 BOOLEAN 582 NeedRecordThisDriver ( 583 IN EFI_DEVICE_PATH_PROTOCOL *DriverFilePath 584 ) 585 { 586 EFI_DEVICE_PATH_PROTOCOL *TmpDevicePath; 587 EFI_DEVICE_PATH_PROTOCOL *DevicePathInstance; 588 UINTN DevicePathSize; 589 UINTN FilePathSize; 590 591 if (!IsDevicePathValid (mSmramProfileDriverPath, mSmramProfileDriverPathSize)) { 592 // 593 // Invalid Device Path means record all. 594 // 595 return TRUE; 596 } 597 598 // 599 // Record FilePath without end node. 600 // 601 FilePathSize = GetDevicePathSize (DriverFilePath) - sizeof(EFI_DEVICE_PATH_PROTOCOL); 602 603 DevicePathInstance = mSmramProfileDriverPath; 604 do { 605 // 606 // Find End node (it might be END_ENTIRE or END_INSTANCE) 607 // 608 TmpDevicePath = DevicePathInstance; 609 while (!IsDevicePathEndType (TmpDevicePath)) { 610 TmpDevicePath = NextDevicePathNode (TmpDevicePath); 611 } 612 613 // 614 // Do not compare END node 615 // 616 DevicePathSize = (UINTN)TmpDevicePath - (UINTN)DevicePathInstance; 617 if ((FilePathSize == DevicePathSize) && 618 (CompareMem (DriverFilePath, DevicePathInstance, DevicePathSize) == 0)) { 619 return TRUE; 620 } 621 622 // 623 // Get next instance 624 // 625 DevicePathInstance = (EFI_DEVICE_PATH_PROTOCOL *)((UINTN)DevicePathInstance + DevicePathSize + DevicePathNodeLength(TmpDevicePath)); 626 } while (DevicePathSubType (TmpDevicePath) != END_ENTIRE_DEVICE_PATH_SUBTYPE); 627 628 return FALSE; 629 } 630 631 /** 632 Register SMM Core to SMRAM profile. 633 634 @param ContextData SMRAM profile context. 635 636 @retval TRUE Register success. 637 @retval FALSE Register fail. 638 639 **/ 640 BOOLEAN 641 RegisterSmmCore ( 642 IN MEMORY_PROFILE_CONTEXT_DATA *ContextData 643 ) 644 { 645 MEMORY_PROFILE_DRIVER_INFO_DATA *DriverInfoData; 646 PHYSICAL_ADDRESS ImageBase; 647 UINT8 TempBuffer[sizeof(MEDIA_FW_VOL_FILEPATH_DEVICE_PATH) + sizeof(EFI_DEVICE_PATH_PROTOCOL)]; 648 MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *FilePath; 649 650 FilePath = (MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *) TempBuffer; 651 EfiInitializeFwVolDevicepathNode (FilePath, &gEfiCallerIdGuid); 652 SetDevicePathEndNode (FilePath + 1); 653 654 if (!NeedRecordThisDriver ((EFI_DEVICE_PATH_PROTOCOL *) FilePath)) { 655 return FALSE; 656 } 657 658 ImageBase = gSmmCorePrivate->PiSmmCoreImageBase; 659 DriverInfoData = BuildDriverInfo ( 660 ContextData, 661 &gEfiCallerIdGuid, 662 ImageBase, 663 gSmmCorePrivate->PiSmmCoreImageSize, 664 gSmmCorePrivate->PiSmmCoreEntryPoint, 665 InternalPeCoffGetSubsystem ((VOID *) (UINTN) ImageBase), 666 EFI_FV_FILETYPE_SMM_CORE 667 ); 668 if (DriverInfoData == NULL) { 669 return FALSE; 670 } 671 672 return TRUE; 673 } 674 675 /** 676 Initialize SMRAM profile. 677 678 **/ 679 VOID 680 SmramProfileInit ( 681 VOID 682 ) 683 { 684 MEMORY_PROFILE_CONTEXT_DATA *SmramProfileContext; 685 686 RegisterImageToDxe ( 687 &gEfiCallerIdGuid, 688 gSmmCorePrivate->PiSmmCoreImageBase, 689 gSmmCorePrivate->PiSmmCoreImageSize, 690 EFI_FV_FILETYPE_SMM_CORE 691 ); 692 693 if (!IS_SMRAM_PROFILE_ENABLED) { 694 return; 695 } 696 697 SmramProfileContext = GetSmramProfileContext (); 698 if (SmramProfileContext != NULL) { 699 return; 700 } 701 702 mSmramProfileGettingStatus = FALSE; 703 if ((PcdGet8 (PcdMemoryProfilePropertyMask) & BIT7) != 0) { 704 mSmramProfileRecordingEnable = MEMORY_PROFILE_RECORDING_DISABLE; 705 } else { 706 mSmramProfileRecordingEnable = MEMORY_PROFILE_RECORDING_ENABLE; 707 } 708 mSmramProfileDriverPathSize = PcdGetSize (PcdMemoryProfileDriverPath); 709 mSmramProfileDriverPath = AllocateCopyPool (mSmramProfileDriverPathSize, PcdGetPtr (PcdMemoryProfileDriverPath)); 710 mSmramProfileContextPtr = &mSmramProfileContext; 711 712 RegisterSmmCore (&mSmramProfileContext); 713 714 DEBUG ((EFI_D_INFO, "SmramProfileInit SmramProfileContext - 0x%x\n", &mSmramProfileContext)); 715 } 716 717 /** 718 Install SMRAM profile protocol. 719 720 **/ 721 VOID 722 SmramProfileInstallProtocol ( 723 VOID 724 ) 725 { 726 EFI_HANDLE Handle; 727 EFI_STATUS Status; 728 729 if (!IS_SMRAM_PROFILE_ENABLED) { 730 return; 731 } 732 733 Handle = NULL; 734 Status = SmmInstallProtocolInterface ( 735 &Handle, 736 &gEdkiiSmmMemoryProfileGuid, 737 EFI_NATIVE_INTERFACE, 738 &mSmmProfileProtocol 739 ); 740 ASSERT_EFI_ERROR (Status); 741 } 742 743 /** 744 Get the GUID file name from the file path. 745 746 @param FilePath File path. 747 748 @return The GUID file name from the file path. 749 750 **/ 751 EFI_GUID * 752 GetFileNameFromFilePath ( 753 IN EFI_DEVICE_PATH_PROTOCOL *FilePath 754 ) 755 { 756 MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *ThisFilePath; 757 EFI_GUID *FileName; 758 759 FileName = NULL; 760 if (FilePath != NULL) { 761 ThisFilePath = (MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *) FilePath; 762 while (!IsDevicePathEnd (ThisFilePath)) { 763 FileName = EfiGetNameGuidFromFwVolDevicePathNode (ThisFilePath); 764 if (FileName != NULL) { 765 break; 766 } 767 ThisFilePath = (MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *) NextDevicePathNode (ThisFilePath); 768 } 769 } 770 771 return FileName; 772 } 773 774 /** 775 Register SMM image to SMRAM profile. 776 777 @param DriverEntry SMM image info. 778 @param RegisterToDxe Register image to DXE. 779 780 @return EFI_SUCCESS Register successfully. 781 @return EFI_UNSUPPORTED Memory profile is unsupported, 782 or memory profile for the image is not required. 783 @return EFI_OUT_OF_RESOURCES No enough resource for this register. 784 785 **/ 786 EFI_STATUS 787 RegisterSmramProfileImage ( 788 IN EFI_SMM_DRIVER_ENTRY *DriverEntry, 789 IN BOOLEAN RegisterToDxe 790 ) 791 { 792 MEMORY_PROFILE_CONTEXT_DATA *ContextData; 793 MEMORY_PROFILE_DRIVER_INFO_DATA *DriverInfoData; 794 UINT8 TempBuffer[sizeof(MEDIA_FW_VOL_FILEPATH_DEVICE_PATH) + sizeof(EFI_DEVICE_PATH_PROTOCOL)]; 795 MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *FilePath; 796 797 if (RegisterToDxe) { 798 RegisterImageToDxe ( 799 &DriverEntry->FileName, 800 DriverEntry->ImageBuffer, 801 EFI_PAGES_TO_SIZE (DriverEntry->NumberOfPage), 802 EFI_FV_FILETYPE_SMM 803 ); 804 } 805 806 if (!IS_SMRAM_PROFILE_ENABLED) { 807 return EFI_UNSUPPORTED; 808 } 809 810 FilePath = (MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *) TempBuffer; 811 EfiInitializeFwVolDevicepathNode (FilePath, &DriverEntry->FileName); 812 SetDevicePathEndNode (FilePath + 1); 813 814 if (!NeedRecordThisDriver ((EFI_DEVICE_PATH_PROTOCOL *) FilePath)) { 815 return EFI_UNSUPPORTED; 816 } 817 818 ContextData = GetSmramProfileContext (); 819 if (ContextData == NULL) { 820 return EFI_UNSUPPORTED; 821 } 822 823 DriverInfoData = BuildDriverInfo ( 824 ContextData, 825 &DriverEntry->FileName, 826 DriverEntry->ImageBuffer, 827 EFI_PAGES_TO_SIZE (DriverEntry->NumberOfPage), 828 DriverEntry->ImageEntryPoint, 829 InternalPeCoffGetSubsystem ((VOID *) (UINTN) DriverEntry->ImageBuffer), 830 EFI_FV_FILETYPE_SMM 831 ); 832 if (DriverInfoData == NULL) { 833 return EFI_OUT_OF_RESOURCES; 834 } 835 836 return EFI_SUCCESS; 837 } 838 839 /** 840 Search image from memory profile. 841 842 @param ContextData Memory profile context. 843 @param FileName Image file name. 844 @param Address Image Address. 845 846 @return Pointer to memory profile driver info. 847 848 **/ 849 MEMORY_PROFILE_DRIVER_INFO_DATA * 850 GetMemoryProfileDriverInfoByFileNameAndAddress ( 851 IN MEMORY_PROFILE_CONTEXT_DATA *ContextData, 852 IN EFI_GUID *FileName, 853 IN PHYSICAL_ADDRESS Address 854 ) 855 { 856 MEMORY_PROFILE_DRIVER_INFO *DriverInfo; 857 MEMORY_PROFILE_DRIVER_INFO_DATA *DriverInfoData; 858 LIST_ENTRY *DriverLink; 859 LIST_ENTRY *DriverInfoList; 860 861 DriverInfoList = ContextData->DriverInfoList; 862 863 for (DriverLink = DriverInfoList->ForwardLink; 864 DriverLink != DriverInfoList; 865 DriverLink = DriverLink->ForwardLink) { 866 DriverInfoData = CR ( 867 DriverLink, 868 MEMORY_PROFILE_DRIVER_INFO_DATA, 869 Link, 870 MEMORY_PROFILE_DRIVER_INFO_SIGNATURE 871 ); 872 DriverInfo = &DriverInfoData->DriverInfo; 873 if ((CompareGuid (&DriverInfo->FileName, FileName)) && 874 (Address >= DriverInfo->ImageBase) && 875 (Address < (DriverInfo->ImageBase + DriverInfo->ImageSize))) { 876 return DriverInfoData; 877 } 878 } 879 880 return NULL; 881 } 882 883 /** 884 Search image from memory profile. 885 It will return image, if (Address >= ImageBuffer) AND (Address < ImageBuffer + ImageSize) 886 887 @param ContextData Memory profile context. 888 @param Address Image or Function address. 889 890 @return Pointer to memory profile driver info. 891 892 **/ 893 MEMORY_PROFILE_DRIVER_INFO_DATA * 894 GetMemoryProfileDriverInfoFromAddress ( 895 IN MEMORY_PROFILE_CONTEXT_DATA *ContextData, 896 IN PHYSICAL_ADDRESS Address 897 ) 898 { 899 MEMORY_PROFILE_DRIVER_INFO *DriverInfo; 900 MEMORY_PROFILE_DRIVER_INFO_DATA *DriverInfoData; 901 LIST_ENTRY *DriverLink; 902 LIST_ENTRY *DriverInfoList; 903 904 DriverInfoList = ContextData->DriverInfoList; 905 906 for (DriverLink = DriverInfoList->ForwardLink; 907 DriverLink != DriverInfoList; 908 DriverLink = DriverLink->ForwardLink) { 909 DriverInfoData = CR ( 910 DriverLink, 911 MEMORY_PROFILE_DRIVER_INFO_DATA, 912 Link, 913 MEMORY_PROFILE_DRIVER_INFO_SIGNATURE 914 ); 915 DriverInfo = &DriverInfoData->DriverInfo; 916 if ((Address >= DriverInfo->ImageBase) && 917 (Address < (DriverInfo->ImageBase + DriverInfo->ImageSize))) { 918 return DriverInfoData; 919 } 920 } 921 922 return NULL; 923 } 924 925 /** 926 Unregister image from SMRAM profile. 927 928 @param DriverEntry SMM image info. 929 @param UnregisterFromDxe Unregister image from DXE. 930 931 @return EFI_SUCCESS Unregister successfully. 932 @return EFI_UNSUPPORTED Memory profile is unsupported, 933 or memory profile for the image is not required. 934 @return EFI_NOT_FOUND The image is not found. 935 936 **/ 937 EFI_STATUS 938 UnregisterSmramProfileImage ( 939 IN EFI_SMM_DRIVER_ENTRY *DriverEntry, 940 IN BOOLEAN UnregisterFromDxe 941 ) 942 { 943 EFI_STATUS Status; 944 MEMORY_PROFILE_CONTEXT_DATA *ContextData; 945 MEMORY_PROFILE_DRIVER_INFO_DATA *DriverInfoData; 946 EFI_GUID *FileName; 947 PHYSICAL_ADDRESS ImageAddress; 948 VOID *EntryPointInImage; 949 UINT8 TempBuffer[sizeof(MEDIA_FW_VOL_FILEPATH_DEVICE_PATH) + sizeof(EFI_DEVICE_PATH_PROTOCOL)]; 950 MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *FilePath; 951 952 if (UnregisterFromDxe) { 953 UnregisterImageFromDxe ( 954 &DriverEntry->FileName, 955 DriverEntry->ImageBuffer, 956 EFI_PAGES_TO_SIZE (DriverEntry->NumberOfPage) 957 ); 958 } 959 960 if (!IS_SMRAM_PROFILE_ENABLED) { 961 return EFI_UNSUPPORTED; 962 } 963 964 FilePath = (MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *) TempBuffer; 965 EfiInitializeFwVolDevicepathNode (FilePath, &DriverEntry->FileName); 966 SetDevicePathEndNode (FilePath + 1); 967 968 if (!NeedRecordThisDriver ((EFI_DEVICE_PATH_PROTOCOL *) FilePath)) { 969 return EFI_UNSUPPORTED; 970 } 971 972 ContextData = GetSmramProfileContext (); 973 if (ContextData == NULL) { 974 return EFI_UNSUPPORTED; 975 } 976 977 DriverInfoData = NULL; 978 FileName = &DriverEntry->FileName; 979 ImageAddress = DriverEntry->ImageBuffer; 980 if ((DriverEntry->ImageEntryPoint < ImageAddress) || (DriverEntry->ImageEntryPoint >= (ImageAddress + EFI_PAGES_TO_SIZE (DriverEntry->NumberOfPage)))) { 981 // 982 // If the EntryPoint is not in the range of image buffer, it should come from emulation environment. 983 // So patch ImageAddress here to align the EntryPoint. 984 // 985 Status = InternalPeCoffGetEntryPoint ((VOID *) (UINTN) ImageAddress, &EntryPointInImage); 986 ASSERT_EFI_ERROR (Status); 987 ImageAddress = ImageAddress + (UINTN) DriverEntry->ImageEntryPoint - (UINTN) EntryPointInImage; 988 } 989 if (FileName != NULL) { 990 DriverInfoData = GetMemoryProfileDriverInfoByFileNameAndAddress (ContextData, FileName, ImageAddress); 991 } 992 if (DriverInfoData == NULL) { 993 DriverInfoData = GetMemoryProfileDriverInfoFromAddress (ContextData, ImageAddress); 994 } 995 if (DriverInfoData == NULL) { 996 return EFI_NOT_FOUND; 997 } 998 999 ContextData->Context.TotalImageSize -= DriverInfoData->DriverInfo.ImageSize; 1000 1001 // Keep the ImageBase for RVA calculation in Application. 1002 //DriverInfoData->DriverInfo.ImageBase = 0; 1003 DriverInfoData->DriverInfo.ImageSize = 0; 1004 1005 if (DriverInfoData->DriverInfo.PeakUsage == 0) { 1006 ContextData->Context.ImageCount --; 1007 RemoveEntryList (&DriverInfoData->Link); 1008 // 1009 // Use SmmInternalFreePool() that will not update profile for this FreePool action. 1010 // 1011 SmmInternalFreePool (DriverInfoData); 1012 } 1013 1014 return EFI_SUCCESS; 1015 } 1016 1017 /** 1018 Return if this memory type needs to be recorded into memory profile. 1019 Only need to record EfiRuntimeServicesCode and EfiRuntimeServicesData for SMRAM profile. 1020 1021 @param MemoryType Memory type. 1022 1023 @retval TRUE This memory type need to be recorded. 1024 @retval FALSE This memory type need not to be recorded. 1025 1026 **/ 1027 BOOLEAN 1028 SmmCoreNeedRecordProfile ( 1029 IN EFI_MEMORY_TYPE MemoryType 1030 ) 1031 { 1032 UINT64 TestBit; 1033 1034 if (MemoryType != EfiRuntimeServicesCode && 1035 MemoryType != EfiRuntimeServicesData) { 1036 return FALSE; 1037 } 1038 1039 TestBit = LShiftU64 (1, MemoryType); 1040 1041 if ((PcdGet64 (PcdMemoryProfileMemoryType) & TestBit) != 0) { 1042 return TRUE; 1043 } else { 1044 return FALSE; 1045 } 1046 } 1047 1048 /** 1049 Convert EFI memory type to profile memory index. The rule is: 1050 If BIOS memory type (0 ~ EfiMaxMemoryType - 1), ProfileMemoryIndex = MemoryType. 1051 As SMRAM profile is only to record EfiRuntimeServicesCode and EfiRuntimeServicesData, 1052 so return input memory type directly. 1053 1054 @param MemoryType Memory type. 1055 1056 @return EFI memory type as profile memory index. 1057 1058 **/ 1059 EFI_MEMORY_TYPE 1060 GetProfileMemoryIndex ( 1061 IN EFI_MEMORY_TYPE MemoryType 1062 ) 1063 { 1064 return MemoryType; 1065 } 1066 1067 /** 1068 Update SMRAM profile FreeMemoryPages information 1069 1070 @param ContextData Memory profile context. 1071 1072 **/ 1073 VOID 1074 SmramProfileUpdateFreePages ( 1075 IN MEMORY_PROFILE_CONTEXT_DATA *ContextData 1076 ) 1077 { 1078 LIST_ENTRY *Node; 1079 FREE_PAGE_LIST *Pages; 1080 LIST_ENTRY *FreePageList; 1081 UINTN NumberOfPages; 1082 1083 NumberOfPages = 0; 1084 FreePageList = &mSmmMemoryMap; 1085 for (Node = FreePageList->BackLink; 1086 Node != FreePageList; 1087 Node = Node->BackLink) { 1088 Pages = BASE_CR (Node, FREE_PAGE_LIST, Link); 1089 NumberOfPages += Pages->NumberOfPages; 1090 } 1091 1092 mSmramFreeMemory.TotalFreeMemoryPages = NumberOfPages; 1093 1094 if (NumberOfPages <= SMRAM_INFO_DUMP_PAGE_THRESHOLD) { 1095 DumpSmramInfo (); 1096 } 1097 } 1098 1099 /** 1100 Update SMRAM profile Allocate information. 1101 1102 @param CallerAddress Address of caller who call Allocate. 1103 @param Action This Allocate action. 1104 @param MemoryType Memory type. 1105 @param Size Buffer size. 1106 @param Buffer Buffer address. 1107 @param ActionString String for memory profile action. 1108 1109 @return EFI_SUCCESS Memory profile is updated. 1110 @return EFI_UNSUPPORTED Memory profile is unsupported, 1111 or memory profile for the image is not required. 1112 @return EFI_OUT_OF_RESOURCES No enough resource to update memory profile for allocate action. 1113 1114 **/ 1115 EFI_STATUS 1116 SmmCoreUpdateProfileAllocate ( 1117 IN PHYSICAL_ADDRESS CallerAddress, 1118 IN MEMORY_PROFILE_ACTION Action, 1119 IN EFI_MEMORY_TYPE MemoryType, 1120 IN UINTN Size, 1121 IN VOID *Buffer, 1122 IN CHAR8 *ActionString OPTIONAL 1123 ) 1124 { 1125 EFI_STATUS Status; 1126 MEMORY_PROFILE_CONTEXT *Context; 1127 MEMORY_PROFILE_DRIVER_INFO *DriverInfo; 1128 MEMORY_PROFILE_ALLOC_INFO *AllocInfo; 1129 MEMORY_PROFILE_CONTEXT_DATA *ContextData; 1130 MEMORY_PROFILE_DRIVER_INFO_DATA *DriverInfoData; 1131 MEMORY_PROFILE_ALLOC_INFO_DATA *AllocInfoData; 1132 EFI_MEMORY_TYPE ProfileMemoryIndex; 1133 MEMORY_PROFILE_ACTION BasicAction; 1134 UINTN ActionStringSize; 1135 UINTN ActionStringOccupiedSize; 1136 1137 BasicAction = Action & MEMORY_PROFILE_ACTION_BASIC_MASK; 1138 1139 ContextData = GetSmramProfileContext (); 1140 if (ContextData == NULL) { 1141 return EFI_UNSUPPORTED; 1142 } 1143 1144 DriverInfoData = GetMemoryProfileDriverInfoFromAddress (ContextData, CallerAddress); 1145 if (DriverInfoData == NULL) { 1146 return EFI_UNSUPPORTED; 1147 } 1148 1149 ActionStringSize = 0; 1150 ActionStringOccupiedSize = 0; 1151 if (ActionString != NULL) { 1152 ActionStringSize = AsciiStrSize (ActionString); 1153 ActionStringOccupiedSize = GET_OCCUPIED_SIZE (ActionStringSize, sizeof (UINT64)); 1154 } 1155 1156 // 1157 // Use SmmInternalAllocatePool() that will not update profile for this AllocatePool action. 1158 // 1159 AllocInfoData = NULL; 1160 Status = SmmInternalAllocatePool ( 1161 EfiRuntimeServicesData, 1162 sizeof (*AllocInfoData) + ActionStringSize, 1163 (VOID **) &AllocInfoData 1164 ); 1165 if (EFI_ERROR (Status)) { 1166 return EFI_OUT_OF_RESOURCES; 1167 } 1168 ASSERT (AllocInfoData != NULL); 1169 1170 // 1171 // Only update SequenceCount if and only if it is basic action. 1172 // 1173 if (Action == BasicAction) { 1174 ContextData->Context.SequenceCount ++; 1175 } 1176 1177 AllocInfo = &AllocInfoData->AllocInfo; 1178 AllocInfoData->Signature = MEMORY_PROFILE_ALLOC_INFO_SIGNATURE; 1179 AllocInfo->Header.Signature = MEMORY_PROFILE_ALLOC_INFO_SIGNATURE; 1180 AllocInfo->Header.Length = (UINT16) (sizeof (MEMORY_PROFILE_ALLOC_INFO) + ActionStringOccupiedSize); 1181 AllocInfo->Header.Revision = MEMORY_PROFILE_ALLOC_INFO_REVISION; 1182 AllocInfo->CallerAddress = CallerAddress; 1183 AllocInfo->SequenceId = ContextData->Context.SequenceCount; 1184 AllocInfo->Action = Action; 1185 AllocInfo->MemoryType = MemoryType; 1186 AllocInfo->Buffer = (PHYSICAL_ADDRESS) (UINTN) Buffer; 1187 AllocInfo->Size = Size; 1188 if (ActionString != NULL) { 1189 AllocInfo->ActionStringOffset = (UINT16) sizeof (MEMORY_PROFILE_ALLOC_INFO); 1190 AllocInfoData->ActionString = (CHAR8 *) (AllocInfoData + 1); 1191 CopyMem (AllocInfoData->ActionString, ActionString, ActionStringSize); 1192 } else { 1193 AllocInfo->ActionStringOffset = 0; 1194 AllocInfoData->ActionString = NULL; 1195 } 1196 1197 InsertTailList (DriverInfoData->AllocInfoList, &AllocInfoData->Link); 1198 1199 Context = &ContextData->Context; 1200 DriverInfo = &DriverInfoData->DriverInfo; 1201 DriverInfo->AllocRecordCount ++; 1202 1203 // 1204 // Update summary if and only if it is basic action. 1205 // 1206 if (Action == BasicAction) { 1207 ProfileMemoryIndex = GetProfileMemoryIndex (MemoryType); 1208 1209 DriverInfo->CurrentUsage += Size; 1210 if (DriverInfo->PeakUsage < DriverInfo->CurrentUsage) { 1211 DriverInfo->PeakUsage = DriverInfo->CurrentUsage; 1212 } 1213 DriverInfo->CurrentUsageByType[ProfileMemoryIndex] += Size; 1214 if (DriverInfo->PeakUsageByType[ProfileMemoryIndex] < DriverInfo->CurrentUsageByType[ProfileMemoryIndex]) { 1215 DriverInfo->PeakUsageByType[ProfileMemoryIndex] = DriverInfo->CurrentUsageByType[ProfileMemoryIndex]; 1216 } 1217 1218 Context->CurrentTotalUsage += Size; 1219 if (Context->PeakTotalUsage < Context->CurrentTotalUsage) { 1220 Context->PeakTotalUsage = Context->CurrentTotalUsage; 1221 } 1222 Context->CurrentTotalUsageByType[ProfileMemoryIndex] += Size; 1223 if (Context->PeakTotalUsageByType[ProfileMemoryIndex] < Context->CurrentTotalUsageByType[ProfileMemoryIndex]) { 1224 Context->PeakTotalUsageByType[ProfileMemoryIndex] = Context->CurrentTotalUsageByType[ProfileMemoryIndex]; 1225 } 1226 1227 SmramProfileUpdateFreePages (ContextData); 1228 } 1229 1230 return EFI_SUCCESS; 1231 } 1232 1233 /** 1234 Get memory profile alloc info from memory profile 1235 1236 @param DriverInfoData Driver info 1237 @param BasicAction This Free basic action 1238 @param Size Buffer size 1239 @param Buffer Buffer address 1240 1241 @return Pointer to memory profile alloc info. 1242 **/ 1243 MEMORY_PROFILE_ALLOC_INFO_DATA * 1244 GetMemoryProfileAllocInfoFromAddress ( 1245 IN MEMORY_PROFILE_DRIVER_INFO_DATA *DriverInfoData, 1246 IN MEMORY_PROFILE_ACTION BasicAction, 1247 IN UINTN Size, 1248 IN VOID *Buffer 1249 ) 1250 { 1251 LIST_ENTRY *AllocInfoList; 1252 LIST_ENTRY *AllocLink; 1253 MEMORY_PROFILE_ALLOC_INFO *AllocInfo; 1254 MEMORY_PROFILE_ALLOC_INFO_DATA *AllocInfoData; 1255 1256 AllocInfoList = DriverInfoData->AllocInfoList; 1257 1258 for (AllocLink = AllocInfoList->ForwardLink; 1259 AllocLink != AllocInfoList; 1260 AllocLink = AllocLink->ForwardLink) { 1261 AllocInfoData = CR ( 1262 AllocLink, 1263 MEMORY_PROFILE_ALLOC_INFO_DATA, 1264 Link, 1265 MEMORY_PROFILE_ALLOC_INFO_SIGNATURE 1266 ); 1267 AllocInfo = &AllocInfoData->AllocInfo; 1268 if ((AllocInfo->Action & MEMORY_PROFILE_ACTION_BASIC_MASK) != BasicAction) { 1269 continue; 1270 } 1271 switch (BasicAction) { 1272 case MemoryProfileActionAllocatePages: 1273 if ((AllocInfo->Buffer <= (PHYSICAL_ADDRESS) (UINTN) Buffer) && 1274 ((AllocInfo->Buffer + AllocInfo->Size) >= ((PHYSICAL_ADDRESS) (UINTN) Buffer + Size))) { 1275 return AllocInfoData; 1276 } 1277 break; 1278 case MemoryProfileActionAllocatePool: 1279 if (AllocInfo->Buffer == (PHYSICAL_ADDRESS) (UINTN) Buffer) { 1280 return AllocInfoData; 1281 } 1282 break; 1283 default: 1284 ASSERT (FALSE); 1285 break; 1286 } 1287 } 1288 1289 return NULL; 1290 } 1291 1292 /** 1293 Update SMRAM profile Free information. 1294 1295 @param CallerAddress Address of caller who call Free. 1296 @param Action This Free action. 1297 @param Size Buffer size. 1298 @param Buffer Buffer address. 1299 1300 @return EFI_SUCCESS Memory profile is updated. 1301 @return EFI_UNSUPPORTED Memory profile is unsupported. 1302 @return EFI_NOT_FOUND No matched allocate info found for free action. 1303 1304 **/ 1305 EFI_STATUS 1306 SmmCoreUpdateProfileFree ( 1307 IN PHYSICAL_ADDRESS CallerAddress, 1308 IN MEMORY_PROFILE_ACTION Action, 1309 IN UINTN Size, 1310 IN VOID *Buffer 1311 ) 1312 { 1313 MEMORY_PROFILE_CONTEXT *Context; 1314 MEMORY_PROFILE_DRIVER_INFO *DriverInfo; 1315 MEMORY_PROFILE_ALLOC_INFO *AllocInfo; 1316 MEMORY_PROFILE_CONTEXT_DATA *ContextData; 1317 MEMORY_PROFILE_DRIVER_INFO_DATA *DriverInfoData; 1318 LIST_ENTRY *DriverLink; 1319 LIST_ENTRY *DriverInfoList; 1320 MEMORY_PROFILE_DRIVER_INFO_DATA *ThisDriverInfoData; 1321 MEMORY_PROFILE_ALLOC_INFO_DATA *AllocInfoData; 1322 EFI_MEMORY_TYPE ProfileMemoryIndex; 1323 MEMORY_PROFILE_ACTION BasicAction; 1324 BOOLEAN Found; 1325 1326 BasicAction = Action & MEMORY_PROFILE_ACTION_BASIC_MASK; 1327 1328 ContextData = GetSmramProfileContext (); 1329 if (ContextData == NULL) { 1330 return EFI_UNSUPPORTED; 1331 } 1332 1333 DriverInfoData = GetMemoryProfileDriverInfoFromAddress (ContextData, CallerAddress); 1334 1335 // 1336 // Do not return if DriverInfoData == NULL here, 1337 // because driver A might free memory allocated by driver B. 1338 // 1339 1340 // 1341 // Need use do-while loop to find all possible record, 1342 // because one address might be recorded multiple times. 1343 // 1344 Found = FALSE; 1345 AllocInfoData = NULL; 1346 do { 1347 if (DriverInfoData != NULL) { 1348 switch (BasicAction) { 1349 case MemoryProfileActionFreePages: 1350 AllocInfoData = GetMemoryProfileAllocInfoFromAddress (DriverInfoData, MemoryProfileActionAllocatePages, Size, Buffer); 1351 break; 1352 case MemoryProfileActionFreePool: 1353 AllocInfoData = GetMemoryProfileAllocInfoFromAddress (DriverInfoData, MemoryProfileActionAllocatePool, 0, Buffer); 1354 break; 1355 default: 1356 ASSERT (FALSE); 1357 AllocInfoData = NULL; 1358 break; 1359 } 1360 } 1361 if (AllocInfoData == NULL) { 1362 // 1363 // Legal case, because driver A might free memory allocated by driver B, by some protocol. 1364 // 1365 DriverInfoList = ContextData->DriverInfoList; 1366 1367 for (DriverLink = DriverInfoList->ForwardLink; 1368 DriverLink != DriverInfoList; 1369 DriverLink = DriverLink->ForwardLink) { 1370 ThisDriverInfoData = CR ( 1371 DriverLink, 1372 MEMORY_PROFILE_DRIVER_INFO_DATA, 1373 Link, 1374 MEMORY_PROFILE_DRIVER_INFO_SIGNATURE 1375 ); 1376 switch (BasicAction) { 1377 case MemoryProfileActionFreePages: 1378 AllocInfoData = GetMemoryProfileAllocInfoFromAddress (ThisDriverInfoData, MemoryProfileActionAllocatePages, Size, Buffer); 1379 break; 1380 case MemoryProfileActionFreePool: 1381 AllocInfoData = GetMemoryProfileAllocInfoFromAddress (ThisDriverInfoData, MemoryProfileActionAllocatePool, 0, Buffer); 1382 break; 1383 default: 1384 ASSERT (FALSE); 1385 AllocInfoData = NULL; 1386 break; 1387 } 1388 if (AllocInfoData != NULL) { 1389 DriverInfoData = ThisDriverInfoData; 1390 break; 1391 } 1392 } 1393 1394 if (AllocInfoData == NULL) { 1395 // 1396 // If (!Found), no matched allocate info is found for this free action. 1397 // It is because the specified memory type allocate actions have been filtered by 1398 // CoreNeedRecordProfile(), but free actions have no memory type information, 1399 // they can not be filtered by CoreNeedRecordProfile(). Then, they will be 1400 // filtered here. 1401 // 1402 // If (Found), it is normal exit path. 1403 return (Found ? EFI_SUCCESS : EFI_NOT_FOUND); 1404 } 1405 } 1406 1407 ASSERT (DriverInfoData != NULL); 1408 ASSERT (AllocInfoData != NULL); 1409 1410 Found = TRUE; 1411 1412 Context = &ContextData->Context; 1413 DriverInfo = &DriverInfoData->DriverInfo; 1414 AllocInfo = &AllocInfoData->AllocInfo; 1415 1416 DriverInfo->AllocRecordCount --; 1417 // 1418 // Update summary if and only if it is basic action. 1419 // 1420 if (AllocInfo->Action == (AllocInfo->Action & MEMORY_PROFILE_ACTION_BASIC_MASK)) { 1421 ProfileMemoryIndex = GetProfileMemoryIndex (AllocInfo->MemoryType); 1422 1423 Context->CurrentTotalUsage -= AllocInfo->Size; 1424 Context->CurrentTotalUsageByType[ProfileMemoryIndex] -= AllocInfo->Size; 1425 1426 DriverInfo->CurrentUsage -= AllocInfo->Size; 1427 DriverInfo->CurrentUsageByType[ProfileMemoryIndex] -= AllocInfo->Size; 1428 } 1429 1430 RemoveEntryList (&AllocInfoData->Link); 1431 1432 if (BasicAction == MemoryProfileActionFreePages) { 1433 if (AllocInfo->Buffer != (PHYSICAL_ADDRESS) (UINTN) Buffer) { 1434 SmmCoreUpdateProfileAllocate ( 1435 AllocInfo->CallerAddress, 1436 AllocInfo->Action, 1437 AllocInfo->MemoryType, 1438 (UINTN) ((PHYSICAL_ADDRESS) (UINTN) Buffer - AllocInfo->Buffer), 1439 (VOID *) (UINTN) AllocInfo->Buffer, 1440 AllocInfoData->ActionString 1441 ); 1442 } 1443 if (AllocInfo->Buffer + AllocInfo->Size != ((PHYSICAL_ADDRESS) (UINTN) Buffer + Size)) { 1444 SmmCoreUpdateProfileAllocate ( 1445 AllocInfo->CallerAddress, 1446 AllocInfo->Action, 1447 AllocInfo->MemoryType, 1448 (UINTN) ((AllocInfo->Buffer + AllocInfo->Size) - ((PHYSICAL_ADDRESS) (UINTN) Buffer + Size)), 1449 (VOID *) ((UINTN) Buffer + Size), 1450 AllocInfoData->ActionString 1451 ); 1452 } 1453 } 1454 1455 // 1456 // Use SmmInternalFreePool() that will not update profile for this FreePool action. 1457 // 1458 SmmInternalFreePool (AllocInfoData); 1459 } while (TRUE); 1460 } 1461 1462 /** 1463 Update SMRAM profile information. 1464 1465 @param CallerAddress Address of caller who call Allocate or Free. 1466 @param Action This Allocate or Free action. 1467 @param MemoryType Memory type. 1468 EfiMaxMemoryType means the MemoryType is unknown. 1469 @param Size Buffer size. 1470 @param Buffer Buffer address. 1471 @param ActionString String for memory profile action. 1472 Only needed for user defined allocate action. 1473 1474 @return EFI_SUCCESS Memory profile is updated. 1475 @return EFI_UNSUPPORTED Memory profile is unsupported, 1476 or memory profile for the image is not required, 1477 or memory profile for the memory type is not required. 1478 @return EFI_ACCESS_DENIED It is during memory profile data getting. 1479 @return EFI_ABORTED Memory profile recording is not enabled. 1480 @return EFI_OUT_OF_RESOURCES No enough resource to update memory profile for allocate action. 1481 @return EFI_NOT_FOUND No matched allocate info found for free action. 1482 1483 **/ 1484 EFI_STATUS 1485 EFIAPI 1486 SmmCoreUpdateProfile ( 1487 IN PHYSICAL_ADDRESS CallerAddress, 1488 IN MEMORY_PROFILE_ACTION Action, 1489 IN EFI_MEMORY_TYPE MemoryType, // Valid for AllocatePages/AllocatePool 1490 IN UINTN Size, // Valid for AllocatePages/FreePages/AllocatePool 1491 IN VOID *Buffer, 1492 IN CHAR8 *ActionString OPTIONAL 1493 ) 1494 { 1495 EFI_STATUS Status; 1496 MEMORY_PROFILE_CONTEXT_DATA *ContextData; 1497 MEMORY_PROFILE_ACTION BasicAction; 1498 1499 if (!IS_SMRAM_PROFILE_ENABLED) { 1500 return EFI_UNSUPPORTED; 1501 } 1502 1503 if (mSmramProfileGettingStatus) { 1504 return EFI_ACCESS_DENIED; 1505 } 1506 1507 if (!mSmramProfileRecordingEnable) { 1508 return EFI_ABORTED; 1509 } 1510 1511 // 1512 // Get the basic action to know how to process the record 1513 // 1514 BasicAction = Action & MEMORY_PROFILE_ACTION_BASIC_MASK; 1515 1516 // 1517 // Free operations have no memory type information, so skip the check. 1518 // 1519 if ((BasicAction == MemoryProfileActionAllocatePages) || (BasicAction == MemoryProfileActionAllocatePool)) { 1520 // 1521 // Only record limited MemoryType. 1522 // 1523 if (!SmmCoreNeedRecordProfile (MemoryType)) { 1524 return EFI_UNSUPPORTED; 1525 } 1526 } 1527 1528 ContextData = GetSmramProfileContext (); 1529 if (ContextData == NULL) { 1530 return EFI_UNSUPPORTED; 1531 } 1532 1533 switch (BasicAction) { 1534 case MemoryProfileActionAllocatePages: 1535 Status = SmmCoreUpdateProfileAllocate (CallerAddress, Action, MemoryType, Size, Buffer, ActionString); 1536 break; 1537 case MemoryProfileActionFreePages: 1538 Status = SmmCoreUpdateProfileFree (CallerAddress, Action, Size, Buffer); 1539 break; 1540 case MemoryProfileActionAllocatePool: 1541 Status = SmmCoreUpdateProfileAllocate (CallerAddress, Action, MemoryType, Size, Buffer, ActionString); 1542 break; 1543 case MemoryProfileActionFreePool: 1544 Status = SmmCoreUpdateProfileFree (CallerAddress, Action, 0, Buffer); 1545 break; 1546 default: 1547 ASSERT (FALSE); 1548 Status = EFI_UNSUPPORTED; 1549 break; 1550 } 1551 1552 return Status; 1553 } 1554 1555 /** 1556 SMRAM profile ready to lock callback function. 1557 1558 **/ 1559 VOID 1560 SmramProfileReadyToLock ( 1561 VOID 1562 ) 1563 { 1564 if (!IS_SMRAM_PROFILE_ENABLED) { 1565 return; 1566 } 1567 1568 DEBUG ((EFI_D_INFO, "SmramProfileReadyToLock\n")); 1569 mSmramReadyToLock = TRUE; 1570 } 1571 1572 //////////////////// 1573 1574 /** 1575 Get SMRAM profile data size. 1576 1577 @return SMRAM profile data size. 1578 1579 **/ 1580 UINTN 1581 SmramProfileGetDataSize ( 1582 VOID 1583 ) 1584 { 1585 MEMORY_PROFILE_CONTEXT_DATA *ContextData; 1586 MEMORY_PROFILE_DRIVER_INFO_DATA *DriverInfoData; 1587 MEMORY_PROFILE_ALLOC_INFO_DATA *AllocInfoData; 1588 LIST_ENTRY *DriverInfoList; 1589 LIST_ENTRY *DriverLink; 1590 LIST_ENTRY *AllocInfoList; 1591 LIST_ENTRY *AllocLink; 1592 UINTN TotalSize; 1593 LIST_ENTRY *Node; 1594 LIST_ENTRY *FreePageList; 1595 LIST_ENTRY *FreePoolList; 1596 FREE_POOL_HEADER *Pool; 1597 UINTN PoolListIndex; 1598 UINTN Index; 1599 UINTN SmmPoolTypeIndex; 1600 1601 ContextData = GetSmramProfileContext (); 1602 if (ContextData == NULL) { 1603 return 0; 1604 } 1605 1606 TotalSize = sizeof (MEMORY_PROFILE_CONTEXT); 1607 1608 DriverInfoList = ContextData->DriverInfoList; 1609 for (DriverLink = DriverInfoList->ForwardLink; 1610 DriverLink != DriverInfoList; 1611 DriverLink = DriverLink->ForwardLink) { 1612 DriverInfoData = CR ( 1613 DriverLink, 1614 MEMORY_PROFILE_DRIVER_INFO_DATA, 1615 Link, 1616 MEMORY_PROFILE_DRIVER_INFO_SIGNATURE 1617 ); 1618 TotalSize += DriverInfoData->DriverInfo.Header.Length; 1619 1620 AllocInfoList = DriverInfoData->AllocInfoList; 1621 for (AllocLink = AllocInfoList->ForwardLink; 1622 AllocLink != AllocInfoList; 1623 AllocLink = AllocLink->ForwardLink) { 1624 AllocInfoData = CR ( 1625 AllocLink, 1626 MEMORY_PROFILE_ALLOC_INFO_DATA, 1627 Link, 1628 MEMORY_PROFILE_ALLOC_INFO_SIGNATURE 1629 ); 1630 TotalSize += AllocInfoData->AllocInfo.Header.Length; 1631 } 1632 } 1633 1634 1635 Index = 0; 1636 FreePageList = &mSmmMemoryMap; 1637 for (Node = FreePageList->BackLink; 1638 Node != FreePageList; 1639 Node = Node->BackLink) { 1640 Index++; 1641 } 1642 for (SmmPoolTypeIndex = 0; SmmPoolTypeIndex < SmmPoolTypeMax; SmmPoolTypeIndex++) { 1643 for (PoolListIndex = 0; PoolListIndex < MAX_POOL_INDEX; PoolListIndex++) { 1644 FreePoolList = &mSmmPoolLists[SmmPoolTypeIndex][PoolListIndex]; 1645 for (Node = FreePoolList->BackLink; 1646 Node != FreePoolList; 1647 Node = Node->BackLink) { 1648 Pool = BASE_CR (Node, FREE_POOL_HEADER, Link); 1649 if (Pool->Header.Available) { 1650 Index++; 1651 } 1652 } 1653 } 1654 } 1655 1656 TotalSize += (sizeof (MEMORY_PROFILE_FREE_MEMORY) + Index * sizeof (MEMORY_PROFILE_DESCRIPTOR)); 1657 TotalSize += (sizeof (MEMORY_PROFILE_MEMORY_RANGE) + mFullSmramRangeCount * sizeof (MEMORY_PROFILE_DESCRIPTOR)); 1658 1659 return TotalSize; 1660 } 1661 1662 /** 1663 Copy SMRAM profile data. 1664 1665 @param ProfileBuffer The buffer to hold SMRAM profile data. 1666 @param ProfileSize On input, profile buffer size. 1667 On output, actual profile data size copied. 1668 @param ProfileOffset On input, profile buffer offset to copy. 1669 On output, next time profile buffer offset to copy. 1670 1671 **/ 1672 VOID 1673 SmramProfileCopyData ( 1674 OUT VOID *ProfileBuffer, 1675 IN OUT UINT64 *ProfileSize, 1676 IN OUT UINT64 *ProfileOffset 1677 ) 1678 { 1679 MEMORY_PROFILE_CONTEXT *Context; 1680 MEMORY_PROFILE_DRIVER_INFO *DriverInfo; 1681 MEMORY_PROFILE_ALLOC_INFO *AllocInfo; 1682 MEMORY_PROFILE_CONTEXT_DATA *ContextData; 1683 MEMORY_PROFILE_DRIVER_INFO_DATA *DriverInfoData; 1684 MEMORY_PROFILE_ALLOC_INFO_DATA *AllocInfoData; 1685 LIST_ENTRY *DriverInfoList; 1686 LIST_ENTRY *DriverLink; 1687 LIST_ENTRY *AllocInfoList; 1688 LIST_ENTRY *AllocLink; 1689 LIST_ENTRY *Node; 1690 FREE_PAGE_LIST *Pages; 1691 LIST_ENTRY *FreePageList; 1692 LIST_ENTRY *FreePoolList; 1693 FREE_POOL_HEADER *Pool; 1694 UINTN PoolListIndex; 1695 UINT32 Index; 1696 MEMORY_PROFILE_FREE_MEMORY *FreeMemory; 1697 MEMORY_PROFILE_MEMORY_RANGE *MemoryRange; 1698 MEMORY_PROFILE_DESCRIPTOR *MemoryProfileDescriptor; 1699 UINT64 Offset; 1700 UINT64 RemainingSize; 1701 UINTN PdbSize; 1702 UINTN ActionStringSize; 1703 UINTN SmmPoolTypeIndex; 1704 1705 ContextData = GetSmramProfileContext (); 1706 if (ContextData == NULL) { 1707 return ; 1708 } 1709 1710 RemainingSize = *ProfileSize; 1711 Offset = 0; 1712 1713 if (*ProfileOffset < sizeof (MEMORY_PROFILE_CONTEXT)) { 1714 if (RemainingSize >= sizeof (MEMORY_PROFILE_CONTEXT)) { 1715 Context = ProfileBuffer; 1716 CopyMem (Context, &ContextData->Context, sizeof (MEMORY_PROFILE_CONTEXT)); 1717 RemainingSize -= sizeof (MEMORY_PROFILE_CONTEXT); 1718 ProfileBuffer = (UINT8 *) ProfileBuffer + sizeof (MEMORY_PROFILE_CONTEXT); 1719 } else { 1720 goto Done; 1721 } 1722 } 1723 Offset += sizeof (MEMORY_PROFILE_CONTEXT); 1724 1725 DriverInfoList = ContextData->DriverInfoList; 1726 for (DriverLink = DriverInfoList->ForwardLink; 1727 DriverLink != DriverInfoList; 1728 DriverLink = DriverLink->ForwardLink) { 1729 DriverInfoData = CR ( 1730 DriverLink, 1731 MEMORY_PROFILE_DRIVER_INFO_DATA, 1732 Link, 1733 MEMORY_PROFILE_DRIVER_INFO_SIGNATURE 1734 ); 1735 if (*ProfileOffset < (Offset + DriverInfoData->DriverInfo.Header.Length)) { 1736 if (RemainingSize >= DriverInfoData->DriverInfo.Header.Length) { 1737 DriverInfo = ProfileBuffer; 1738 CopyMem (DriverInfo, &DriverInfoData->DriverInfo, sizeof (MEMORY_PROFILE_DRIVER_INFO)); 1739 if (DriverInfo->PdbStringOffset != 0) { 1740 PdbSize = AsciiStrSize (DriverInfoData->PdbString); 1741 CopyMem ((VOID *) ((UINTN) DriverInfo + DriverInfo->PdbStringOffset), DriverInfoData->PdbString, PdbSize); 1742 } 1743 RemainingSize -= DriverInfo->Header.Length; 1744 ProfileBuffer = (UINT8 *) ProfileBuffer + DriverInfo->Header.Length; 1745 } else { 1746 goto Done; 1747 } 1748 } 1749 Offset += DriverInfoData->DriverInfo.Header.Length; 1750 1751 AllocInfoList = DriverInfoData->AllocInfoList; 1752 for (AllocLink = AllocInfoList->ForwardLink; 1753 AllocLink != AllocInfoList; 1754 AllocLink = AllocLink->ForwardLink) { 1755 AllocInfoData = CR ( 1756 AllocLink, 1757 MEMORY_PROFILE_ALLOC_INFO_DATA, 1758 Link, 1759 MEMORY_PROFILE_ALLOC_INFO_SIGNATURE 1760 ); 1761 if (*ProfileOffset < (Offset + AllocInfoData->AllocInfo.Header.Length)) { 1762 if (RemainingSize >= AllocInfoData->AllocInfo.Header.Length) { 1763 AllocInfo = ProfileBuffer; 1764 CopyMem (AllocInfo, &AllocInfoData->AllocInfo, sizeof (MEMORY_PROFILE_ALLOC_INFO)); 1765 if (AllocInfo->ActionStringOffset) { 1766 ActionStringSize = AsciiStrSize (AllocInfoData->ActionString); 1767 CopyMem ((VOID *) ((UINTN) AllocInfo + AllocInfo->ActionStringOffset), AllocInfoData->ActionString, ActionStringSize); 1768 } 1769 RemainingSize -= AllocInfo->Header.Length; 1770 ProfileBuffer = (UINT8 *) ProfileBuffer + AllocInfo->Header.Length; 1771 } else { 1772 goto Done; 1773 } 1774 } 1775 Offset += AllocInfoData->AllocInfo.Header.Length; 1776 } 1777 } 1778 1779 1780 if (*ProfileOffset < (Offset + sizeof (MEMORY_PROFILE_FREE_MEMORY))) { 1781 if (RemainingSize >= sizeof (MEMORY_PROFILE_FREE_MEMORY)) { 1782 FreeMemory = ProfileBuffer; 1783 CopyMem (FreeMemory, &mSmramFreeMemory, sizeof (MEMORY_PROFILE_FREE_MEMORY)); 1784 Index = 0; 1785 FreePageList = &mSmmMemoryMap; 1786 for (Node = FreePageList->BackLink; 1787 Node != FreePageList; 1788 Node = Node->BackLink) { 1789 Index++; 1790 } 1791 for (SmmPoolTypeIndex = 0; SmmPoolTypeIndex < SmmPoolTypeMax; SmmPoolTypeIndex++) { 1792 for (PoolListIndex = 0; PoolListIndex < MAX_POOL_INDEX; PoolListIndex++) { 1793 FreePoolList = &mSmmPoolLists[SmmPoolTypeIndex][MAX_POOL_INDEX - PoolListIndex - 1]; 1794 for (Node = FreePoolList->BackLink; 1795 Node != FreePoolList; 1796 Node = Node->BackLink) { 1797 Pool = BASE_CR (Node, FREE_POOL_HEADER, Link); 1798 if (Pool->Header.Available) { 1799 Index++; 1800 } 1801 } 1802 } 1803 } 1804 FreeMemory->FreeMemoryEntryCount = Index; 1805 1806 RemainingSize -= sizeof (MEMORY_PROFILE_FREE_MEMORY); 1807 ProfileBuffer = (UINT8 *) ProfileBuffer + sizeof (MEMORY_PROFILE_FREE_MEMORY); 1808 } else { 1809 goto Done; 1810 } 1811 } 1812 Offset += sizeof (MEMORY_PROFILE_FREE_MEMORY); 1813 FreePageList = &mSmmMemoryMap; 1814 for (Node = FreePageList->BackLink; 1815 Node != FreePageList; 1816 Node = Node->BackLink) { 1817 if (*ProfileOffset < (Offset + sizeof (MEMORY_PROFILE_DESCRIPTOR))) { 1818 if (RemainingSize >= sizeof (MEMORY_PROFILE_DESCRIPTOR)) { 1819 Pages = BASE_CR (Node, FREE_PAGE_LIST, Link); 1820 MemoryProfileDescriptor = ProfileBuffer; 1821 MemoryProfileDescriptor->Header.Signature = MEMORY_PROFILE_DESCRIPTOR_SIGNATURE; 1822 MemoryProfileDescriptor->Header.Length = sizeof (MEMORY_PROFILE_DESCRIPTOR); 1823 MemoryProfileDescriptor->Header.Revision = MEMORY_PROFILE_DESCRIPTOR_REVISION; 1824 MemoryProfileDescriptor->Address = (PHYSICAL_ADDRESS) (UINTN) Pages; 1825 MemoryProfileDescriptor->Size = EFI_PAGES_TO_SIZE (Pages->NumberOfPages); 1826 1827 RemainingSize -= sizeof (MEMORY_PROFILE_DESCRIPTOR); 1828 ProfileBuffer = (UINT8 *) ProfileBuffer + sizeof (MEMORY_PROFILE_DESCRIPTOR); 1829 } else { 1830 goto Done; 1831 } 1832 } 1833 Offset += sizeof (MEMORY_PROFILE_DESCRIPTOR); 1834 } 1835 for (SmmPoolTypeIndex = 0; SmmPoolTypeIndex < SmmPoolTypeMax; SmmPoolTypeIndex++) { 1836 for (PoolListIndex = 0; PoolListIndex < MAX_POOL_INDEX; PoolListIndex++) { 1837 FreePoolList = &mSmmPoolLists[SmmPoolTypeIndex][MAX_POOL_INDEX - PoolListIndex - 1]; 1838 for (Node = FreePoolList->BackLink; 1839 Node != FreePoolList; 1840 Node = Node->BackLink) { 1841 Pool = BASE_CR (Node, FREE_POOL_HEADER, Link); 1842 if (Pool->Header.Available) { 1843 if (*ProfileOffset < (Offset + sizeof (MEMORY_PROFILE_DESCRIPTOR))) { 1844 if (RemainingSize >= sizeof (MEMORY_PROFILE_DESCRIPTOR)) { 1845 MemoryProfileDescriptor = ProfileBuffer; 1846 MemoryProfileDescriptor->Header.Signature = MEMORY_PROFILE_DESCRIPTOR_SIGNATURE; 1847 MemoryProfileDescriptor->Header.Length = sizeof (MEMORY_PROFILE_DESCRIPTOR); 1848 MemoryProfileDescriptor->Header.Revision = MEMORY_PROFILE_DESCRIPTOR_REVISION; 1849 MemoryProfileDescriptor->Address = (PHYSICAL_ADDRESS) (UINTN) Pool; 1850 MemoryProfileDescriptor->Size = Pool->Header.Size; 1851 1852 RemainingSize -= sizeof (MEMORY_PROFILE_DESCRIPTOR); 1853 ProfileBuffer = (UINT8 *) ProfileBuffer + sizeof (MEMORY_PROFILE_DESCRIPTOR); 1854 } else { 1855 goto Done; 1856 } 1857 } 1858 Offset += sizeof (MEMORY_PROFILE_DESCRIPTOR); 1859 } 1860 } 1861 } 1862 } 1863 1864 if (*ProfileOffset < (Offset + sizeof (MEMORY_PROFILE_MEMORY_RANGE))) { 1865 if (RemainingSize >= sizeof (MEMORY_PROFILE_MEMORY_RANGE)) { 1866 MemoryRange = ProfileBuffer; 1867 MemoryRange->Header.Signature = MEMORY_PROFILE_MEMORY_RANGE_SIGNATURE; 1868 MemoryRange->Header.Length = sizeof (MEMORY_PROFILE_MEMORY_RANGE); 1869 MemoryRange->Header.Revision = MEMORY_PROFILE_MEMORY_RANGE_REVISION; 1870 MemoryRange->MemoryRangeCount = (UINT32) mFullSmramRangeCount; 1871 1872 RemainingSize -= sizeof (MEMORY_PROFILE_MEMORY_RANGE); 1873 ProfileBuffer = (UINT8 *) ProfileBuffer + sizeof (MEMORY_PROFILE_MEMORY_RANGE); 1874 } else { 1875 goto Done; 1876 } 1877 } 1878 Offset += sizeof (MEMORY_PROFILE_MEMORY_RANGE); 1879 for (Index = 0; Index < mFullSmramRangeCount; Index++) { 1880 if (*ProfileOffset < (Offset + sizeof (MEMORY_PROFILE_DESCRIPTOR))) { 1881 if (RemainingSize >= sizeof (MEMORY_PROFILE_DESCRIPTOR)) { 1882 MemoryProfileDescriptor = ProfileBuffer; 1883 MemoryProfileDescriptor->Header.Signature = MEMORY_PROFILE_DESCRIPTOR_SIGNATURE; 1884 MemoryProfileDescriptor->Header.Length = sizeof (MEMORY_PROFILE_DESCRIPTOR); 1885 MemoryProfileDescriptor->Header.Revision = MEMORY_PROFILE_DESCRIPTOR_REVISION; 1886 MemoryProfileDescriptor->Address = mFullSmramRanges[Index].PhysicalStart; 1887 MemoryProfileDescriptor->Size = mFullSmramRanges[Index].PhysicalSize; 1888 1889 RemainingSize -= sizeof (MEMORY_PROFILE_DESCRIPTOR); 1890 ProfileBuffer = (UINT8 *) ProfileBuffer + sizeof (MEMORY_PROFILE_DESCRIPTOR); 1891 } else { 1892 goto Done; 1893 } 1894 } 1895 Offset += sizeof (MEMORY_PROFILE_DESCRIPTOR); 1896 } 1897 1898 Done: 1899 // 1900 // On output, actual profile data size copied. 1901 // 1902 *ProfileSize -= RemainingSize; 1903 // 1904 // On output, next time profile buffer offset to copy. 1905 // 1906 *ProfileOffset = Offset; 1907 } 1908 1909 /** 1910 Get memory profile data. 1911 1912 @param[in] This The EDKII_SMM_MEMORY_PROFILE_PROTOCOL instance. 1913 @param[in, out] ProfileSize On entry, points to the size in bytes of the ProfileBuffer. 1914 On return, points to the size of the data returned in ProfileBuffer. 1915 @param[out] ProfileBuffer Profile buffer. 1916 1917 @return EFI_SUCCESS Get the memory profile data successfully. 1918 @return EFI_UNSUPPORTED Memory profile is unsupported. 1919 @return EFI_BUFFER_TO_SMALL The ProfileSize is too small for the resulting data. 1920 ProfileSize is updated with the size required. 1921 1922 **/ 1923 EFI_STATUS 1924 EFIAPI 1925 SmramProfileProtocolGetData ( 1926 IN EDKII_SMM_MEMORY_PROFILE_PROTOCOL *This, 1927 IN OUT UINT64 *ProfileSize, 1928 OUT VOID *ProfileBuffer 1929 ) 1930 { 1931 UINT64 Size; 1932 UINT64 Offset; 1933 MEMORY_PROFILE_CONTEXT_DATA *ContextData; 1934 BOOLEAN SmramProfileGettingStatus; 1935 1936 ContextData = GetSmramProfileContext (); 1937 if (ContextData == NULL) { 1938 return EFI_UNSUPPORTED; 1939 } 1940 1941 SmramProfileGettingStatus = mSmramProfileGettingStatus; 1942 mSmramProfileGettingStatus = TRUE; 1943 1944 Size = SmramProfileGetDataSize (); 1945 1946 if (*ProfileSize < Size) { 1947 *ProfileSize = Size; 1948 mSmramProfileGettingStatus = SmramProfileGettingStatus; 1949 return EFI_BUFFER_TOO_SMALL; 1950 } 1951 1952 Offset = 0; 1953 SmramProfileCopyData (ProfileBuffer, &Size, &Offset); 1954 *ProfileSize = Size; 1955 1956 mSmramProfileGettingStatus = SmramProfileGettingStatus; 1957 return EFI_SUCCESS; 1958 } 1959 1960 /** 1961 Register image to memory profile. 1962 1963 @param[in] This The EDKII_SMM_MEMORY_PROFILE_PROTOCOL instance. 1964 @param[in] FilePath File path of the image. 1965 @param[in] ImageBase Image base address. 1966 @param[in] ImageSize Image size. 1967 @param[in] FileType File type of the image. 1968 1969 @return EFI_SUCCESS Register successfully. 1970 @return EFI_UNSUPPORTED Memory profile is unsupported, 1971 or memory profile for the image is not required. 1972 @return EFI_OUT_OF_RESOURCES No enough resource for this register. 1973 1974 **/ 1975 EFI_STATUS 1976 EFIAPI 1977 SmramProfileProtocolRegisterImage ( 1978 IN EDKII_SMM_MEMORY_PROFILE_PROTOCOL *This, 1979 IN EFI_DEVICE_PATH_PROTOCOL *FilePath, 1980 IN PHYSICAL_ADDRESS ImageBase, 1981 IN UINT64 ImageSize, 1982 IN EFI_FV_FILETYPE FileType 1983 ) 1984 { 1985 EFI_STATUS Status; 1986 EFI_SMM_DRIVER_ENTRY DriverEntry; 1987 VOID *EntryPointInImage; 1988 EFI_GUID *Name; 1989 1990 ZeroMem (&DriverEntry, sizeof (DriverEntry)); 1991 Name = GetFileNameFromFilePath (FilePath); 1992 if (Name != NULL) { 1993 CopyMem (&DriverEntry.FileName, Name, sizeof (EFI_GUID)); 1994 } 1995 DriverEntry.ImageBuffer = ImageBase; 1996 DriverEntry.NumberOfPage = EFI_SIZE_TO_PAGES ((UINTN) ImageSize); 1997 Status = InternalPeCoffGetEntryPoint ((VOID *) (UINTN) DriverEntry.ImageBuffer, &EntryPointInImage); 1998 ASSERT_EFI_ERROR (Status); 1999 DriverEntry.ImageEntryPoint = (PHYSICAL_ADDRESS) (UINTN) EntryPointInImage; 2000 2001 return RegisterSmramProfileImage (&DriverEntry, FALSE); 2002 } 2003 2004 /** 2005 Unregister image from memory profile. 2006 2007 @param[in] This The EDKII_SMM_MEMORY_PROFILE_PROTOCOL instance. 2008 @param[in] FilePath File path of the image. 2009 @param[in] ImageBase Image base address. 2010 @param[in] ImageSize Image size. 2011 2012 @return EFI_SUCCESS Unregister successfully. 2013 @return EFI_UNSUPPORTED Memory profile is unsupported, 2014 or memory profile for the image is not required. 2015 @return EFI_NOT_FOUND The image is not found. 2016 2017 **/ 2018 EFI_STATUS 2019 EFIAPI 2020 SmramProfileProtocolUnregisterImage ( 2021 IN EDKII_SMM_MEMORY_PROFILE_PROTOCOL *This, 2022 IN EFI_DEVICE_PATH_PROTOCOL *FilePath, 2023 IN PHYSICAL_ADDRESS ImageBase, 2024 IN UINT64 ImageSize 2025 ) 2026 { 2027 EFI_STATUS Status; 2028 EFI_SMM_DRIVER_ENTRY DriverEntry; 2029 VOID *EntryPointInImage; 2030 EFI_GUID *Name; 2031 2032 ZeroMem (&DriverEntry, sizeof (DriverEntry)); 2033 Name = GetFileNameFromFilePath (FilePath); 2034 if (Name != NULL) { 2035 CopyMem (&DriverEntry.FileName, Name, sizeof (EFI_GUID)); 2036 } 2037 DriverEntry.ImageBuffer = ImageBase; 2038 DriverEntry.NumberOfPage = EFI_SIZE_TO_PAGES ((UINTN) ImageSize); 2039 Status = InternalPeCoffGetEntryPoint ((VOID *) (UINTN) DriverEntry.ImageBuffer, &EntryPointInImage); 2040 ASSERT_EFI_ERROR (Status); 2041 DriverEntry.ImageEntryPoint = (PHYSICAL_ADDRESS) (UINTN) EntryPointInImage; 2042 2043 return UnregisterSmramProfileImage (&DriverEntry, FALSE); 2044 } 2045 2046 /** 2047 Get memory profile recording state. 2048 2049 @param[in] This The EDKII_SMM_MEMORY_PROFILE_PROTOCOL instance. 2050 @param[out] RecordingState Recording state. 2051 2052 @return EFI_SUCCESS Memory profile recording state is returned. 2053 @return EFI_UNSUPPORTED Memory profile is unsupported. 2054 @return EFI_INVALID_PARAMETER RecordingState is NULL. 2055 2056 **/ 2057 EFI_STATUS 2058 EFIAPI 2059 SmramProfileProtocolGetRecordingState ( 2060 IN EDKII_SMM_MEMORY_PROFILE_PROTOCOL *This, 2061 OUT BOOLEAN *RecordingState 2062 ) 2063 { 2064 MEMORY_PROFILE_CONTEXT_DATA *ContextData; 2065 2066 ContextData = GetSmramProfileContext (); 2067 if (ContextData == NULL) { 2068 return EFI_UNSUPPORTED; 2069 } 2070 2071 if (RecordingState == NULL) { 2072 return EFI_INVALID_PARAMETER; 2073 } 2074 *RecordingState = mSmramProfileRecordingEnable; 2075 return EFI_SUCCESS; 2076 } 2077 2078 /** 2079 Set memory profile recording state. 2080 2081 @param[in] This The EDKII_SMM_MEMORY_PROFILE_PROTOCOL instance. 2082 @param[in] RecordingState Recording state. 2083 2084 @return EFI_SUCCESS Set memory profile recording state successfully. 2085 @return EFI_UNSUPPORTED Memory profile is unsupported. 2086 2087 **/ 2088 EFI_STATUS 2089 EFIAPI 2090 SmramProfileProtocolSetRecordingState ( 2091 IN EDKII_SMM_MEMORY_PROFILE_PROTOCOL *This, 2092 IN BOOLEAN RecordingState 2093 ) 2094 { 2095 MEMORY_PROFILE_CONTEXT_DATA *ContextData; 2096 2097 ContextData = GetSmramProfileContext (); 2098 if (ContextData == NULL) { 2099 return EFI_UNSUPPORTED; 2100 } 2101 2102 mSmramProfileRecordingEnable = RecordingState; 2103 return EFI_SUCCESS; 2104 } 2105 2106 /** 2107 Record memory profile of multilevel caller. 2108 2109 @param[in] This The EDKII_SMM_MEMORY_PROFILE_PROTOCOL instance. 2110 @param[in] CallerAddress Address of caller. 2111 @param[in] Action Memory profile action. 2112 @param[in] MemoryType Memory type. 2113 EfiMaxMemoryType means the MemoryType is unknown. 2114 @param[in] Buffer Buffer address. 2115 @param[in] Size Buffer size. 2116 @param[in] ActionString String for memory profile action. 2117 Only needed for user defined allocate action. 2118 2119 @return EFI_SUCCESS Memory profile is updated. 2120 @return EFI_UNSUPPORTED Memory profile is unsupported, 2121 or memory profile for the image is not required, 2122 or memory profile for the memory type is not required. 2123 @return EFI_ACCESS_DENIED It is during memory profile data getting. 2124 @return EFI_ABORTED Memory profile recording is not enabled. 2125 @return EFI_OUT_OF_RESOURCES No enough resource to update memory profile for allocate action. 2126 @return EFI_NOT_FOUND No matched allocate info found for free action. 2127 2128 **/ 2129 EFI_STATUS 2130 EFIAPI 2131 SmramProfileProtocolRecord ( 2132 IN EDKII_SMM_MEMORY_PROFILE_PROTOCOL *This, 2133 IN PHYSICAL_ADDRESS CallerAddress, 2134 IN MEMORY_PROFILE_ACTION Action, 2135 IN EFI_MEMORY_TYPE MemoryType, 2136 IN VOID *Buffer, 2137 IN UINTN Size, 2138 IN CHAR8 *ActionString OPTIONAL 2139 ) 2140 { 2141 return SmmCoreUpdateProfile (CallerAddress, Action, MemoryType, Size, Buffer, ActionString); 2142 } 2143 2144 /** 2145 SMRAM profile handler to get profile info. 2146 2147 @param SmramProfileParameterGetInfo The parameter of SMM profile get size. 2148 2149 **/ 2150 VOID 2151 SmramProfileHandlerGetInfo ( 2152 IN SMRAM_PROFILE_PARAMETER_GET_PROFILE_INFO *SmramProfileParameterGetInfo 2153 ) 2154 { 2155 MEMORY_PROFILE_CONTEXT_DATA *ContextData; 2156 BOOLEAN SmramProfileGettingStatus; 2157 2158 ContextData = GetSmramProfileContext (); 2159 if (ContextData == NULL) { 2160 return ; 2161 } 2162 2163 SmramProfileGettingStatus = mSmramProfileGettingStatus; 2164 mSmramProfileGettingStatus = TRUE; 2165 2166 SmramProfileParameterGetInfo->ProfileSize = SmramProfileGetDataSize(); 2167 SmramProfileParameterGetInfo->Header.ReturnStatus = 0; 2168 2169 mSmramProfileGettingStatus = SmramProfileGettingStatus; 2170 } 2171 2172 /** 2173 SMRAM profile handler to get profile data. 2174 2175 @param SmramProfileParameterGetData The parameter of SMM profile get data. 2176 2177 **/ 2178 VOID 2179 SmramProfileHandlerGetData ( 2180 IN SMRAM_PROFILE_PARAMETER_GET_PROFILE_DATA *SmramProfileParameterGetData 2181 ) 2182 { 2183 UINT64 ProfileSize; 2184 UINT64 ProfileOffset; 2185 SMRAM_PROFILE_PARAMETER_GET_PROFILE_DATA SmramProfileGetData; 2186 MEMORY_PROFILE_CONTEXT_DATA *ContextData; 2187 BOOLEAN SmramProfileGettingStatus; 2188 2189 ContextData = GetSmramProfileContext (); 2190 if (ContextData == NULL) { 2191 return ; 2192 } 2193 2194 SmramProfileGettingStatus = mSmramProfileGettingStatus; 2195 mSmramProfileGettingStatus = TRUE; 2196 2197 2198 CopyMem (&SmramProfileGetData, SmramProfileParameterGetData, sizeof (SmramProfileGetData)); 2199 2200 ProfileSize = SmramProfileGetDataSize(); 2201 2202 // 2203 // Sanity check 2204 // 2205 if (!SmmIsBufferOutsideSmmValid ((UINTN) SmramProfileGetData.ProfileBuffer, (UINTN) ProfileSize)) { 2206 DEBUG ((EFI_D_ERROR, "SmramProfileHandlerGetData: SMM ProfileBuffer in SMRAM or overflow!\n")); 2207 SmramProfileParameterGetData->ProfileSize = ProfileSize; 2208 SmramProfileParameterGetData->Header.ReturnStatus = (UINT64) (INT64) (INTN) EFI_ACCESS_DENIED; 2209 goto Done; 2210 } 2211 2212 if (SmramProfileGetData.ProfileSize < ProfileSize) { 2213 SmramProfileParameterGetData->ProfileSize = ProfileSize; 2214 SmramProfileParameterGetData->Header.ReturnStatus = (UINT64) (INT64) (INTN) EFI_BUFFER_TOO_SMALL; 2215 goto Done; 2216 } 2217 2218 ProfileOffset = 0; 2219 SmramProfileCopyData ((VOID *) (UINTN) SmramProfileGetData.ProfileBuffer, &ProfileSize, &ProfileOffset); 2220 SmramProfileParameterGetData->ProfileSize = ProfileSize; 2221 SmramProfileParameterGetData->Header.ReturnStatus = 0; 2222 2223 Done: 2224 mSmramProfileGettingStatus = SmramProfileGettingStatus; 2225 } 2226 2227 /** 2228 SMRAM profile handler to get profile data by offset. 2229 2230 @param SmramProfileParameterGetDataByOffset The parameter of SMM profile get data by offset. 2231 2232 **/ 2233 VOID 2234 SmramProfileHandlerGetDataByOffset ( 2235 IN SMRAM_PROFILE_PARAMETER_GET_PROFILE_DATA_BY_OFFSET *SmramProfileParameterGetDataByOffset 2236 ) 2237 { 2238 SMRAM_PROFILE_PARAMETER_GET_PROFILE_DATA_BY_OFFSET SmramProfileGetDataByOffset; 2239 MEMORY_PROFILE_CONTEXT_DATA *ContextData; 2240 BOOLEAN SmramProfileGettingStatus; 2241 2242 ContextData = GetSmramProfileContext (); 2243 if (ContextData == NULL) { 2244 return ; 2245 } 2246 2247 SmramProfileGettingStatus = mSmramProfileGettingStatus; 2248 mSmramProfileGettingStatus = TRUE; 2249 2250 2251 CopyMem (&SmramProfileGetDataByOffset, SmramProfileParameterGetDataByOffset, sizeof (SmramProfileGetDataByOffset)); 2252 2253 // 2254 // Sanity check 2255 // 2256 if (!SmmIsBufferOutsideSmmValid ((UINTN) SmramProfileGetDataByOffset.ProfileBuffer, (UINTN) SmramProfileGetDataByOffset.ProfileSize)) { 2257 DEBUG ((EFI_D_ERROR, "SmramProfileHandlerGetDataByOffset: SMM ProfileBuffer in SMRAM or overflow!\n")); 2258 SmramProfileParameterGetDataByOffset->Header.ReturnStatus = (UINT64) (INT64) (INTN) EFI_ACCESS_DENIED; 2259 goto Done; 2260 } 2261 2262 SmramProfileCopyData ((VOID *) (UINTN) SmramProfileGetDataByOffset.ProfileBuffer, &SmramProfileGetDataByOffset.ProfileSize, &SmramProfileGetDataByOffset.ProfileOffset); 2263 CopyMem (SmramProfileParameterGetDataByOffset, &SmramProfileGetDataByOffset, sizeof (SmramProfileGetDataByOffset)); 2264 SmramProfileParameterGetDataByOffset->Header.ReturnStatus = 0; 2265 2266 Done: 2267 mSmramProfileGettingStatus = SmramProfileGettingStatus; 2268 } 2269 2270 /** 2271 SMRAM profile handler to register SMM image. 2272 2273 @param SmramProfileParameterRegisterImage The parameter of SMM profile register image. 2274 2275 **/ 2276 VOID 2277 SmramProfileHandlerRegisterImage ( 2278 IN SMRAM_PROFILE_PARAMETER_REGISTER_IMAGE *SmramProfileParameterRegisterImage 2279 ) 2280 { 2281 EFI_STATUS Status; 2282 EFI_SMM_DRIVER_ENTRY DriverEntry; 2283 VOID *EntryPointInImage; 2284 2285 ZeroMem (&DriverEntry, sizeof (DriverEntry)); 2286 CopyMem (&DriverEntry.FileName, &SmramProfileParameterRegisterImage->FileName, sizeof(EFI_GUID)); 2287 DriverEntry.ImageBuffer = SmramProfileParameterRegisterImage->ImageBuffer; 2288 DriverEntry.NumberOfPage = (UINTN) SmramProfileParameterRegisterImage->NumberOfPage; 2289 Status = InternalPeCoffGetEntryPoint ((VOID *) (UINTN) DriverEntry.ImageBuffer, &EntryPointInImage); 2290 ASSERT_EFI_ERROR (Status); 2291 DriverEntry.ImageEntryPoint = (PHYSICAL_ADDRESS) (UINTN) EntryPointInImage; 2292 2293 Status = RegisterSmramProfileImage (&DriverEntry, FALSE); 2294 if (!EFI_ERROR (Status)) { 2295 SmramProfileParameterRegisterImage->Header.ReturnStatus = 0; 2296 } 2297 } 2298 2299 /** 2300 SMRAM profile handler to unregister SMM image. 2301 2302 @param SmramProfileParameterUnregisterImage The parameter of SMM profile unregister image. 2303 2304 **/ 2305 VOID 2306 SmramProfileHandlerUnregisterImage ( 2307 IN SMRAM_PROFILE_PARAMETER_UNREGISTER_IMAGE *SmramProfileParameterUnregisterImage 2308 ) 2309 { 2310 EFI_STATUS Status; 2311 EFI_SMM_DRIVER_ENTRY DriverEntry; 2312 VOID *EntryPointInImage; 2313 2314 ZeroMem (&DriverEntry, sizeof (DriverEntry)); 2315 CopyMem (&DriverEntry.FileName, &SmramProfileParameterUnregisterImage->FileName, sizeof (EFI_GUID)); 2316 DriverEntry.ImageBuffer = SmramProfileParameterUnregisterImage->ImageBuffer; 2317 DriverEntry.NumberOfPage = (UINTN) SmramProfileParameterUnregisterImage->NumberOfPage; 2318 Status = InternalPeCoffGetEntryPoint ((VOID *) (UINTN) DriverEntry.ImageBuffer, &EntryPointInImage); 2319 ASSERT_EFI_ERROR (Status); 2320 DriverEntry.ImageEntryPoint = (PHYSICAL_ADDRESS) (UINTN) EntryPointInImage; 2321 2322 Status = UnregisterSmramProfileImage (&DriverEntry, FALSE); 2323 if (!EFI_ERROR (Status)) { 2324 SmramProfileParameterUnregisterImage->Header.ReturnStatus = 0; 2325 } 2326 } 2327 2328 /** 2329 Dispatch function for a Software SMI handler. 2330 2331 Caution: This function may receive untrusted input. 2332 Communicate buffer and buffer size are external input, so this function will do basic validation. 2333 2334 @param DispatchHandle The unique handle assigned to this handler by SmiHandlerRegister(). 2335 @param Context Points to an optional handler context which was specified when the 2336 handler was registered. 2337 @param CommBuffer A pointer to a collection of data in memory that will 2338 be conveyed from a non-SMM environment into an SMM environment. 2339 @param CommBufferSize The size of the CommBuffer. 2340 2341 @retval EFI_SUCCESS Command is handled successfully. 2342 2343 **/ 2344 EFI_STATUS 2345 EFIAPI 2346 SmramProfileHandler ( 2347 IN EFI_HANDLE DispatchHandle, 2348 IN CONST VOID *Context OPTIONAL, 2349 IN OUT VOID *CommBuffer OPTIONAL, 2350 IN OUT UINTN *CommBufferSize OPTIONAL 2351 ) 2352 { 2353 SMRAM_PROFILE_PARAMETER_HEADER *SmramProfileParameterHeader; 2354 UINTN TempCommBufferSize; 2355 SMRAM_PROFILE_PARAMETER_RECORDING_STATE *ParameterRecordingState; 2356 2357 DEBUG ((EFI_D_ERROR, "SmramProfileHandler Enter\n")); 2358 2359 // 2360 // If input is invalid, stop processing this SMI 2361 // 2362 if (CommBuffer == NULL || CommBufferSize == NULL) { 2363 return EFI_SUCCESS; 2364 } 2365 2366 TempCommBufferSize = *CommBufferSize; 2367 2368 if (TempCommBufferSize < sizeof (SMRAM_PROFILE_PARAMETER_HEADER)) { 2369 DEBUG ((EFI_D_ERROR, "SmramProfileHandler: SMM communication buffer size invalid!\n")); 2370 return EFI_SUCCESS; 2371 } 2372 2373 if (mSmramReadyToLock && !SmmIsBufferOutsideSmmValid ((UINTN)CommBuffer, TempCommBufferSize)) { 2374 DEBUG ((EFI_D_ERROR, "SmramProfileHandler: SMM communication buffer in SMRAM or overflow!\n")); 2375 return EFI_SUCCESS; 2376 } 2377 2378 SmramProfileParameterHeader = (SMRAM_PROFILE_PARAMETER_HEADER *) ((UINTN) CommBuffer); 2379 2380 SmramProfileParameterHeader->ReturnStatus = (UINT64)-1; 2381 2382 if (GetSmramProfileContext () == NULL) { 2383 SmramProfileParameterHeader->ReturnStatus = (UINT64) (INT64) (INTN) EFI_UNSUPPORTED; 2384 return EFI_SUCCESS; 2385 } 2386 2387 switch (SmramProfileParameterHeader->Command) { 2388 case SMRAM_PROFILE_COMMAND_GET_PROFILE_INFO: 2389 DEBUG ((EFI_D_ERROR, "SmramProfileHandlerGetInfo\n")); 2390 if (TempCommBufferSize != sizeof (SMRAM_PROFILE_PARAMETER_GET_PROFILE_INFO)) { 2391 DEBUG ((EFI_D_ERROR, "SmramProfileHandler: SMM communication buffer size invalid!\n")); 2392 return EFI_SUCCESS; 2393 } 2394 SmramProfileHandlerGetInfo ((SMRAM_PROFILE_PARAMETER_GET_PROFILE_INFO *) (UINTN) CommBuffer); 2395 break; 2396 case SMRAM_PROFILE_COMMAND_GET_PROFILE_DATA: 2397 DEBUG ((EFI_D_ERROR, "SmramProfileHandlerGetData\n")); 2398 if (TempCommBufferSize != sizeof (SMRAM_PROFILE_PARAMETER_GET_PROFILE_DATA)) { 2399 DEBUG ((EFI_D_ERROR, "SmramProfileHandler: SMM communication buffer size invalid!\n")); 2400 return EFI_SUCCESS; 2401 } 2402 SmramProfileHandlerGetData ((SMRAM_PROFILE_PARAMETER_GET_PROFILE_DATA *) (UINTN) CommBuffer); 2403 break; 2404 case SMRAM_PROFILE_COMMAND_GET_PROFILE_DATA_BY_OFFSET: 2405 DEBUG ((EFI_D_ERROR, "SmramProfileHandlerGetDataByOffset\n")); 2406 if (TempCommBufferSize != sizeof (SMRAM_PROFILE_PARAMETER_GET_PROFILE_DATA_BY_OFFSET)) { 2407 DEBUG ((EFI_D_ERROR, "SmramProfileHandler: SMM communication buffer size invalid!\n")); 2408 return EFI_SUCCESS; 2409 } 2410 SmramProfileHandlerGetDataByOffset ((SMRAM_PROFILE_PARAMETER_GET_PROFILE_DATA_BY_OFFSET *) (UINTN) CommBuffer); 2411 break; 2412 case SMRAM_PROFILE_COMMAND_REGISTER_IMAGE: 2413 DEBUG ((EFI_D_ERROR, "SmramProfileHandlerRegisterImage\n")); 2414 if (TempCommBufferSize != sizeof (SMRAM_PROFILE_PARAMETER_REGISTER_IMAGE)) { 2415 DEBUG ((EFI_D_ERROR, "SmramProfileHandler: SMM communication buffer size invalid!\n")); 2416 return EFI_SUCCESS; 2417 } 2418 if (mSmramReadyToLock) { 2419 return EFI_SUCCESS; 2420 } 2421 SmramProfileHandlerRegisterImage ((SMRAM_PROFILE_PARAMETER_REGISTER_IMAGE *) (UINTN) CommBuffer); 2422 break; 2423 case SMRAM_PROFILE_COMMAND_UNREGISTER_IMAGE: 2424 DEBUG ((EFI_D_ERROR, "SmramProfileHandlerUnregisterImage\n")); 2425 if (TempCommBufferSize != sizeof (SMRAM_PROFILE_PARAMETER_UNREGISTER_IMAGE)) { 2426 DEBUG ((EFI_D_ERROR, "SmramProfileHandler: SMM communication buffer size invalid!\n")); 2427 return EFI_SUCCESS; 2428 } 2429 if (mSmramReadyToLock) { 2430 return EFI_SUCCESS; 2431 } 2432 SmramProfileHandlerUnregisterImage ((SMRAM_PROFILE_PARAMETER_UNREGISTER_IMAGE *) (UINTN) CommBuffer); 2433 break; 2434 case SMRAM_PROFILE_COMMAND_GET_RECORDING_STATE: 2435 DEBUG ((EFI_D_ERROR, "SmramProfileHandlerGetRecordingState\n")); 2436 if (TempCommBufferSize != sizeof (SMRAM_PROFILE_PARAMETER_RECORDING_STATE)) { 2437 DEBUG ((EFI_D_ERROR, "SmramProfileHandler: SMM communication buffer size invalid!\n")); 2438 return EFI_SUCCESS; 2439 } 2440 ParameterRecordingState = (SMRAM_PROFILE_PARAMETER_RECORDING_STATE *) (UINTN) CommBuffer; 2441 ParameterRecordingState->RecordingState = mSmramProfileRecordingEnable; 2442 ParameterRecordingState->Header.ReturnStatus = 0; 2443 break; 2444 case SMRAM_PROFILE_COMMAND_SET_RECORDING_STATE: 2445 DEBUG ((EFI_D_ERROR, "SmramProfileHandlerSetRecordingState\n")); 2446 if (TempCommBufferSize != sizeof (SMRAM_PROFILE_PARAMETER_RECORDING_STATE)) { 2447 DEBUG ((EFI_D_ERROR, "SmramProfileHandler: SMM communication buffer size invalid!\n")); 2448 return EFI_SUCCESS; 2449 } 2450 ParameterRecordingState = (SMRAM_PROFILE_PARAMETER_RECORDING_STATE *) (UINTN) CommBuffer; 2451 mSmramProfileRecordingEnable = ParameterRecordingState->RecordingState; 2452 ParameterRecordingState->Header.ReturnStatus = 0; 2453 break; 2454 2455 default: 2456 break; 2457 } 2458 2459 DEBUG ((EFI_D_ERROR, "SmramProfileHandler Exit\n")); 2460 2461 return EFI_SUCCESS; 2462 } 2463 2464 /** 2465 Register SMRAM profile handler. 2466 2467 **/ 2468 VOID 2469 RegisterSmramProfileHandler ( 2470 VOID 2471 ) 2472 { 2473 EFI_STATUS Status; 2474 EFI_HANDLE DispatchHandle; 2475 2476 if (!IS_SMRAM_PROFILE_ENABLED) { 2477 return; 2478 } 2479 2480 Status = SmiHandlerRegister ( 2481 SmramProfileHandler, 2482 &gEdkiiMemoryProfileGuid, 2483 &DispatchHandle 2484 ); 2485 ASSERT_EFI_ERROR (Status); 2486 } 2487 2488 //////////////////// 2489 2490 /** 2491 Dump SMRAM range. 2492 2493 **/ 2494 VOID 2495 DumpSmramRange ( 2496 VOID 2497 ) 2498 { 2499 UINTN Index; 2500 MEMORY_PROFILE_CONTEXT_DATA *ContextData; 2501 BOOLEAN SmramProfileGettingStatus; 2502 2503 ContextData = GetSmramProfileContext (); 2504 if (ContextData == NULL) { 2505 return ; 2506 } 2507 2508 SmramProfileGettingStatus = mSmramProfileGettingStatus; 2509 mSmramProfileGettingStatus = TRUE; 2510 2511 DEBUG ((EFI_D_INFO, "FullSmramRange address - 0x%08x\n", mFullSmramRanges)); 2512 2513 DEBUG ((EFI_D_INFO, "======= SmramProfile begin =======\n")); 2514 2515 DEBUG ((EFI_D_INFO, "FullSmramRange:\n")); 2516 for (Index = 0; Index < mFullSmramRangeCount; Index++) { 2517 DEBUG ((EFI_D_INFO, " FullSmramRange (0x%x)\n", Index)); 2518 DEBUG ((EFI_D_INFO, " PhysicalStart - 0x%016lx\n", mFullSmramRanges[Index].PhysicalStart)); 2519 DEBUG ((EFI_D_INFO, " CpuStart - 0x%016lx\n", mFullSmramRanges[Index].CpuStart)); 2520 DEBUG ((EFI_D_INFO, " PhysicalSize - 0x%016lx\n", mFullSmramRanges[Index].PhysicalSize)); 2521 DEBUG ((EFI_D_INFO, " RegionState - 0x%016lx\n", mFullSmramRanges[Index].RegionState)); 2522 } 2523 2524 DEBUG ((EFI_D_INFO, "======= SmramProfile end =======\n")); 2525 2526 mSmramProfileGettingStatus = SmramProfileGettingStatus; 2527 } 2528 2529 /** 2530 Dump SMRAM free page list. 2531 2532 **/ 2533 VOID 2534 DumpFreePagesList ( 2535 VOID 2536 ) 2537 { 2538 LIST_ENTRY *FreePageList; 2539 LIST_ENTRY *Node; 2540 FREE_PAGE_LIST *Pages; 2541 UINTN Index; 2542 MEMORY_PROFILE_CONTEXT_DATA *ContextData; 2543 BOOLEAN SmramProfileGettingStatus; 2544 2545 ContextData = GetSmramProfileContext (); 2546 if (ContextData == NULL) { 2547 return ; 2548 } 2549 2550 SmramProfileGettingStatus = mSmramProfileGettingStatus; 2551 mSmramProfileGettingStatus = TRUE; 2552 2553 DEBUG ((EFI_D_INFO, "======= SmramProfile begin =======\n")); 2554 2555 DEBUG ((EFI_D_INFO, "FreePagesList:\n")); 2556 FreePageList = &mSmmMemoryMap; 2557 for (Node = FreePageList->BackLink, Index = 0; 2558 Node != FreePageList; 2559 Node = Node->BackLink, Index++) { 2560 Pages = BASE_CR (Node, FREE_PAGE_LIST, Link); 2561 DEBUG ((EFI_D_INFO, " Index - 0x%x\n", Index)); 2562 DEBUG ((EFI_D_INFO, " PhysicalStart - 0x%016lx\n", (PHYSICAL_ADDRESS) (UINTN) Pages)); 2563 DEBUG ((EFI_D_INFO, " NumberOfPages - 0x%08x\n", Pages->NumberOfPages)); 2564 } 2565 2566 DEBUG ((EFI_D_INFO, "======= SmramProfile end =======\n")); 2567 2568 mSmramProfileGettingStatus = SmramProfileGettingStatus; 2569 } 2570 2571 /** 2572 Dump SMRAM free pool list. 2573 2574 **/ 2575 VOID 2576 DumpFreePoolList ( 2577 VOID 2578 ) 2579 { 2580 LIST_ENTRY *FreePoolList; 2581 LIST_ENTRY *Node; 2582 FREE_POOL_HEADER *Pool; 2583 UINTN Index; 2584 UINTN PoolListIndex; 2585 MEMORY_PROFILE_CONTEXT_DATA *ContextData; 2586 BOOLEAN SmramProfileGettingStatus; 2587 UINTN SmmPoolTypeIndex; 2588 2589 ContextData = GetSmramProfileContext (); 2590 if (ContextData == NULL) { 2591 return ; 2592 } 2593 2594 SmramProfileGettingStatus = mSmramProfileGettingStatus; 2595 mSmramProfileGettingStatus = TRUE; 2596 2597 DEBUG ((DEBUG_INFO, "======= SmramProfile begin =======\n")); 2598 2599 for (SmmPoolTypeIndex = 0; SmmPoolTypeIndex < SmmPoolTypeMax; SmmPoolTypeIndex++) { 2600 for (PoolListIndex = 0; PoolListIndex < MAX_POOL_INDEX; PoolListIndex++) { 2601 DEBUG ((DEBUG_INFO, "FreePoolList(%d)(%d):\n", SmmPoolTypeIndex, PoolListIndex)); 2602 FreePoolList = &mSmmPoolLists[SmmPoolTypeIndex][PoolListIndex]; 2603 for (Node = FreePoolList->BackLink, Index = 0; 2604 Node != FreePoolList; 2605 Node = Node->BackLink, Index++) { 2606 Pool = BASE_CR (Node, FREE_POOL_HEADER, Link); 2607 DEBUG ((DEBUG_INFO, " Index - 0x%x\n", Index)); 2608 DEBUG ((DEBUG_INFO, " PhysicalStart - 0x%016lx\n", (PHYSICAL_ADDRESS) (UINTN) Pool)); 2609 DEBUG ((DEBUG_INFO, " Size - 0x%08x\n", Pool->Header.Size)); 2610 DEBUG ((DEBUG_INFO, " Available - 0x%02x\n", Pool->Header.Available)); 2611 } 2612 } 2613 } 2614 2615 DEBUG ((DEBUG_INFO, "======= SmramProfile end =======\n")); 2616 2617 mSmramProfileGettingStatus = SmramProfileGettingStatus; 2618 } 2619 2620 GLOBAL_REMOVE_IF_UNREFERENCED CHAR8 *mSmmActionString[] = { 2621 "SmmUnknown", 2622 "gSmst->SmmAllocatePages", 2623 "gSmst->SmmFreePages", 2624 "gSmst->SmmAllocatePool", 2625 "gSmst->SmmFreePool", 2626 }; 2627 2628 typedef struct { 2629 MEMORY_PROFILE_ACTION Action; 2630 CHAR8 *String; 2631 } ACTION_STRING; 2632 2633 ACTION_STRING mExtActionString[] = { 2634 {MEMORY_PROFILE_ACTION_LIB_ALLOCATE_PAGES, "Lib:AllocatePages"}, 2635 {MEMORY_PROFILE_ACTION_LIB_ALLOCATE_RUNTIME_PAGES, "Lib:AllocateRuntimePages"}, 2636 {MEMORY_PROFILE_ACTION_LIB_ALLOCATE_RESERVED_PAGES, "Lib:AllocateReservedPages"}, 2637 {MEMORY_PROFILE_ACTION_LIB_FREE_PAGES, "Lib:FreePages"}, 2638 {MEMORY_PROFILE_ACTION_LIB_ALLOCATE_ALIGNED_PAGES, "Lib:AllocateAlignedPages"}, 2639 {MEMORY_PROFILE_ACTION_LIB_ALLOCATE_ALIGNED_RUNTIME_PAGES, "Lib:AllocateAlignedRuntimePages"}, 2640 {MEMORY_PROFILE_ACTION_LIB_ALLOCATE_ALIGNED_RESERVED_PAGES, "Lib:AllocateAlignedReservedPages"}, 2641 {MEMORY_PROFILE_ACTION_LIB_FREE_ALIGNED_PAGES, "Lib:FreeAlignedPages"}, 2642 {MEMORY_PROFILE_ACTION_LIB_ALLOCATE_POOL, "Lib:AllocatePool"}, 2643 {MEMORY_PROFILE_ACTION_LIB_ALLOCATE_RUNTIME_POOL, "Lib:AllocateRuntimePool"}, 2644 {MEMORY_PROFILE_ACTION_LIB_ALLOCATE_RESERVED_POOL, "Lib:AllocateReservedPool"}, 2645 {MEMORY_PROFILE_ACTION_LIB_FREE_POOL, "Lib:FreePool"}, 2646 {MEMORY_PROFILE_ACTION_LIB_ALLOCATE_ZERO_POOL, "Lib:AllocateZeroPool"}, 2647 {MEMORY_PROFILE_ACTION_LIB_ALLOCATE_RUNTIME_ZERO_POOL, "Lib:AllocateRuntimeZeroPool"}, 2648 {MEMORY_PROFILE_ACTION_LIB_ALLOCATE_RESERVED_ZERO_POOL, "Lib:AllocateReservedZeroPool"}, 2649 {MEMORY_PROFILE_ACTION_LIB_ALLOCATE_COPY_POOL, "Lib:AllocateCopyPool"}, 2650 {MEMORY_PROFILE_ACTION_LIB_ALLOCATE_RUNTIME_COPY_POOL, "Lib:AllocateRuntimeCopyPool"}, 2651 {MEMORY_PROFILE_ACTION_LIB_ALLOCATE_RESERVED_COPY_POOL, "Lib:AllocateReservedCopyPool"}, 2652 {MEMORY_PROFILE_ACTION_LIB_REALLOCATE_POOL, "Lib:ReallocatePool"}, 2653 {MEMORY_PROFILE_ACTION_LIB_REALLOCATE_RUNTIME_POOL, "Lib:ReallocateRuntimePool"}, 2654 {MEMORY_PROFILE_ACTION_LIB_REALLOCATE_RESERVED_POOL, "Lib:ReallocateReservedPool"}, 2655 }; 2656 2657 GLOBAL_REMOVE_IF_UNREFERENCED CHAR8 mUserDefinedActionString[] = {"UserDefined-0x80000000"}; 2658 2659 typedef struct { 2660 EFI_MEMORY_TYPE MemoryType; 2661 CHAR8 *MemoryTypeStr; 2662 } PROFILE_MEMORY_TYPE_STRING; 2663 2664 GLOBAL_REMOVE_IF_UNREFERENCED PROFILE_MEMORY_TYPE_STRING mMemoryTypeString[] = { 2665 {EfiRuntimeServicesCode, "EfiRuntimeServicesCode"}, 2666 {EfiRuntimeServicesData, "EfiRuntimeServicesData"} 2667 }; 2668 2669 /** 2670 Memory type to string. 2671 2672 @param[in] MemoryType Memory type. 2673 2674 @return Pointer to string. 2675 2676 **/ 2677 CHAR8 * 2678 ProfileMemoryTypeToStr ( 2679 IN EFI_MEMORY_TYPE MemoryType 2680 ) 2681 { 2682 UINTN Index; 2683 for (Index = 0; Index < ARRAY_SIZE (mMemoryTypeString); Index++) { 2684 if (mMemoryTypeString[Index].MemoryType == MemoryType) { 2685 return mMemoryTypeString[Index].MemoryTypeStr; 2686 } 2687 } 2688 2689 return "UnexpectedMemoryType"; 2690 } 2691 2692 /** 2693 Action to string. 2694 2695 @param[in] Action Profile action. 2696 2697 @return Pointer to string. 2698 2699 **/ 2700 CHAR8 * 2701 ProfileActionToStr ( 2702 IN MEMORY_PROFILE_ACTION Action 2703 ) 2704 { 2705 UINTN Index; 2706 UINTN ActionStringCount; 2707 CHAR8 **ActionString; 2708 2709 ActionString = mSmmActionString; 2710 ActionStringCount = ARRAY_SIZE (mSmmActionString); 2711 2712 if ((UINTN) (UINT32) Action < ActionStringCount) { 2713 return ActionString[Action]; 2714 } 2715 for (Index = 0; Index < ARRAY_SIZE (mExtActionString); Index++) { 2716 if (mExtActionString[Index].Action == Action) { 2717 return mExtActionString[Index].String; 2718 } 2719 } 2720 2721 return ActionString[0]; 2722 } 2723 2724 /** 2725 Dump SMRAM profile. 2726 2727 **/ 2728 VOID 2729 DumpSmramProfile ( 2730 VOID 2731 ) 2732 { 2733 MEMORY_PROFILE_CONTEXT *Context; 2734 MEMORY_PROFILE_DRIVER_INFO *DriverInfo; 2735 MEMORY_PROFILE_ALLOC_INFO *AllocInfo; 2736 MEMORY_PROFILE_CONTEXT_DATA *ContextData; 2737 MEMORY_PROFILE_DRIVER_INFO_DATA *DriverInfoData; 2738 MEMORY_PROFILE_ALLOC_INFO_DATA *AllocInfoData; 2739 LIST_ENTRY *SmramDriverInfoList; 2740 UINTN DriverIndex; 2741 LIST_ENTRY *DriverLink; 2742 LIST_ENTRY *AllocInfoList; 2743 UINTN AllocIndex; 2744 LIST_ENTRY *AllocLink; 2745 BOOLEAN SmramProfileGettingStatus; 2746 UINTN TypeIndex; 2747 2748 ContextData = GetSmramProfileContext (); 2749 if (ContextData == NULL) { 2750 return ; 2751 } 2752 2753 SmramProfileGettingStatus = mSmramProfileGettingStatus; 2754 mSmramProfileGettingStatus = TRUE; 2755 2756 Context = &ContextData->Context; 2757 DEBUG ((EFI_D_INFO, "======= SmramProfile begin =======\n")); 2758 DEBUG ((EFI_D_INFO, "MEMORY_PROFILE_CONTEXT\n")); 2759 2760 DEBUG ((EFI_D_INFO, " CurrentTotalUsage - 0x%016lx\n", Context->CurrentTotalUsage)); 2761 DEBUG ((EFI_D_INFO, " PeakTotalUsage - 0x%016lx\n", Context->PeakTotalUsage)); 2762 for (TypeIndex = 0; TypeIndex < sizeof (Context->CurrentTotalUsageByType) / sizeof (Context->CurrentTotalUsageByType[0]); TypeIndex++) { 2763 if ((Context->CurrentTotalUsageByType[TypeIndex] != 0) || 2764 (Context->PeakTotalUsageByType[TypeIndex] != 0)) { 2765 DEBUG ((EFI_D_INFO, " CurrentTotalUsage[0x%02x] - 0x%016lx (%a)\n", TypeIndex, Context->CurrentTotalUsageByType[TypeIndex], ProfileMemoryTypeToStr (TypeIndex))); 2766 DEBUG ((EFI_D_INFO, " PeakTotalUsage[0x%02x] - 0x%016lx (%a)\n", TypeIndex, Context->PeakTotalUsageByType[TypeIndex], ProfileMemoryTypeToStr (TypeIndex))); 2767 } 2768 } 2769 DEBUG ((EFI_D_INFO, " TotalImageSize - 0x%016lx\n", Context->TotalImageSize)); 2770 DEBUG ((EFI_D_INFO, " ImageCount - 0x%08x\n", Context->ImageCount)); 2771 DEBUG ((EFI_D_INFO, " SequenceCount - 0x%08x\n", Context->SequenceCount)); 2772 2773 SmramDriverInfoList = ContextData->DriverInfoList; 2774 for (DriverLink = SmramDriverInfoList->ForwardLink, DriverIndex = 0; 2775 DriverLink != SmramDriverInfoList; 2776 DriverLink = DriverLink->ForwardLink, DriverIndex++) { 2777 DriverInfoData = CR ( 2778 DriverLink, 2779 MEMORY_PROFILE_DRIVER_INFO_DATA, 2780 Link, 2781 MEMORY_PROFILE_DRIVER_INFO_SIGNATURE 2782 ); 2783 DriverInfo = &DriverInfoData->DriverInfo; 2784 DEBUG ((EFI_D_INFO, " MEMORY_PROFILE_DRIVER_INFO (0x%x)\n", DriverIndex)); 2785 DEBUG ((EFI_D_INFO, " FileName - %g\n", &DriverInfo->FileName)); 2786 DEBUG ((EFI_D_INFO, " ImageBase - 0x%016lx\n", DriverInfo->ImageBase)); 2787 DEBUG ((EFI_D_INFO, " ImageSize - 0x%016lx\n", DriverInfo->ImageSize)); 2788 DEBUG ((EFI_D_INFO, " EntryPoint - 0x%016lx\n", DriverInfo->EntryPoint)); 2789 DEBUG ((EFI_D_INFO, " ImageSubsystem - 0x%04x\n", DriverInfo->ImageSubsystem)); 2790 DEBUG ((EFI_D_INFO, " FileType - 0x%02x\n", DriverInfo->FileType)); 2791 DEBUG ((EFI_D_INFO, " CurrentUsage - 0x%016lx\n", DriverInfo->CurrentUsage)); 2792 DEBUG ((EFI_D_INFO, " PeakUsage - 0x%016lx\n", DriverInfo->PeakUsage)); 2793 for (TypeIndex = 0; TypeIndex < sizeof (DriverInfo->CurrentUsageByType) / sizeof (DriverInfo->CurrentUsageByType[0]); TypeIndex++) { 2794 if ((DriverInfo->CurrentUsageByType[TypeIndex] != 0) || 2795 (DriverInfo->PeakUsageByType[TypeIndex] != 0)) { 2796 DEBUG ((EFI_D_INFO, " CurrentUsage[0x%02x] - 0x%016lx (%a)\n", TypeIndex, DriverInfo->CurrentUsageByType[TypeIndex], ProfileMemoryTypeToStr (TypeIndex))); 2797 DEBUG ((EFI_D_INFO, " PeakUsage[0x%02x] - 0x%016lx (%a)\n", TypeIndex, DriverInfo->PeakUsageByType[TypeIndex], ProfileMemoryTypeToStr (TypeIndex))); 2798 } 2799 } 2800 DEBUG ((EFI_D_INFO, " AllocRecordCount - 0x%08x\n", DriverInfo->AllocRecordCount)); 2801 2802 AllocInfoList = DriverInfoData->AllocInfoList; 2803 for (AllocLink = AllocInfoList->ForwardLink, AllocIndex = 0; 2804 AllocLink != AllocInfoList; 2805 AllocLink = AllocLink->ForwardLink, AllocIndex++) { 2806 AllocInfoData = CR ( 2807 AllocLink, 2808 MEMORY_PROFILE_ALLOC_INFO_DATA, 2809 Link, 2810 MEMORY_PROFILE_ALLOC_INFO_SIGNATURE 2811 ); 2812 AllocInfo = &AllocInfoData->AllocInfo; 2813 DEBUG ((EFI_D_INFO, " MEMORY_PROFILE_ALLOC_INFO (0x%x)\n", AllocIndex)); 2814 DEBUG ((EFI_D_INFO, " CallerAddress - 0x%016lx (Offset: 0x%08x)\n", AllocInfo->CallerAddress, AllocInfo->CallerAddress - DriverInfo->ImageBase)); 2815 DEBUG ((EFI_D_INFO, " SequenceId - 0x%08x\n", AllocInfo->SequenceId)); 2816 if ((AllocInfo->Action & MEMORY_PROFILE_ACTION_USER_DEFINED_MASK) != 0) { 2817 if (AllocInfoData->ActionString != NULL) { 2818 DEBUG ((EFI_D_INFO, " Action - 0x%08x (%a)\n", AllocInfo->Action, AllocInfoData->ActionString)); 2819 } else { 2820 DEBUG ((EFI_D_INFO, " Action - 0x%08x (UserDefined-0x%08x)\n", AllocInfo->Action, AllocInfo->Action)); 2821 } 2822 } else { 2823 DEBUG ((EFI_D_INFO, " Action - 0x%08x (%a)\n", AllocInfo->Action, ProfileActionToStr (AllocInfo->Action))); 2824 } 2825 DEBUG ((EFI_D_INFO, " MemoryType - 0x%08x (%a)\n", AllocInfo->MemoryType, ProfileMemoryTypeToStr (AllocInfo->MemoryType))); 2826 DEBUG ((EFI_D_INFO, " Buffer - 0x%016lx\n", AllocInfo->Buffer)); 2827 DEBUG ((EFI_D_INFO, " Size - 0x%016lx\n", AllocInfo->Size)); 2828 } 2829 } 2830 2831 DEBUG ((EFI_D_INFO, "======= SmramProfile end =======\n")); 2832 2833 mSmramProfileGettingStatus = SmramProfileGettingStatus; 2834 } 2835 2836 /** 2837 Dump SMRAM infromation. 2838 2839 **/ 2840 VOID 2841 DumpSmramInfo ( 2842 VOID 2843 ) 2844 { 2845 DEBUG_CODE ( 2846 if (IS_SMRAM_PROFILE_ENABLED) { 2847 DumpSmramProfile (); 2848 DumpFreePagesList (); 2849 DumpFreePoolList (); 2850 DumpSmramRange (); 2851 } 2852 ); 2853 } 2854 2855