1/** @file 2 Support routines for memory allocation routines based 3 on SMM Services Table services for SMM phase drivers, with memory profile support. 4 5 The PI System Management Mode Core Interface Specification only allows the use 6 of EfiRuntimeServicesCode and EfiRuntimeServicesData memory types for memory 7 allocations through the SMM Services Table as the SMRAM space should be 8 reserved after BDS phase. The functions in the Memory Allocation Library use 9 EfiBootServicesData as the default memory allocation type. For this SMM 10 specific instance of the Memory Allocation Library, EfiRuntimeServicesData 11 is used as the default memory type for all allocations. In addition, 12 allocation for the Reserved memory types are not supported and will always 13 return NULL. 14 15 Copyright (c) 2006 - 2016, Intel Corporation. All rights reserved.<BR> 16 This program and the accompanying materials 17 are licensed and made available under the terms and conditions of the BSD License 18 which accompanies this distribution. The full text of the license may be found at 19 http://opensource.org/licenses/bsd-license.php. 20 21 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, 22 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. 23 24**/ 25 26#include <PiSmm.h> 27 28#include <Protocol/SmmAccess2.h> 29#include <Library/MemoryAllocationLib.h> 30#include <Library/UefiBootServicesTableLib.h> 31#include <Library/SmmServicesTableLib.h> 32#include <Library/BaseMemoryLib.h> 33#include <Library/DebugLib.h> 34 35#include <Library/MemoryProfileLib.h> 36 37EFI_SMRAM_DESCRIPTOR *mSmramRanges; 38UINTN mSmramRangeCount; 39 40/** 41 The constructor function caches SMRAM ranges that are present in the system. 42 43 It will ASSERT() if SMM Access2 Protocol doesn't exist. 44 It will ASSERT() if SMRAM ranges can't be got. 45 It will ASSERT() if Resource can't be allocated for cache SMRAM range. 46 It will always return EFI_SUCCESS. 47 48 @param ImageHandle The firmware allocated handle for the EFI image. 49 @param SystemTable A pointer to the EFI System Table. 50 51 @retval EFI_SUCCESS The constructor always returns EFI_SUCCESS. 52 53**/ 54EFI_STATUS 55EFIAPI 56SmmMemoryAllocationLibConstructor ( 57 IN EFI_HANDLE ImageHandle, 58 IN EFI_SYSTEM_TABLE *SystemTable 59 ) 60{ 61 EFI_STATUS Status; 62 EFI_SMM_ACCESS2_PROTOCOL *SmmAccess; 63 UINTN Size; 64 65 // 66 // Locate SMM Access2 Protocol 67 // 68 Status = gBS->LocateProtocol ( 69 &gEfiSmmAccess2ProtocolGuid, 70 NULL, 71 (VOID **)&SmmAccess 72 ); 73 ASSERT_EFI_ERROR (Status); 74 75 // 76 // Get SMRAM range information 77 // 78 Size = 0; 79 Status = SmmAccess->GetCapabilities (SmmAccess, &Size, NULL); 80 ASSERT (Status == EFI_BUFFER_TOO_SMALL); 81 82 mSmramRanges = (EFI_SMRAM_DESCRIPTOR *) AllocatePool (Size); 83 ASSERT (mSmramRanges != NULL); 84 85 Status = SmmAccess->GetCapabilities (SmmAccess, &Size, mSmramRanges); 86 ASSERT_EFI_ERROR (Status); 87 88 mSmramRangeCount = Size / sizeof (EFI_SMRAM_DESCRIPTOR); 89 90 return EFI_SUCCESS; 91} 92 93/** 94 If SMM driver exits with an error, it must call this routine 95 to free the allocated resource before the exiting. 96 97 @param[in] ImageHandle The firmware allocated handle for the EFI image. 98 @param[in] SystemTable A pointer to the EFI System Table. 99 100 @retval EFI_SUCCESS The deconstructor always returns EFI_SUCCESS. 101**/ 102EFI_STATUS 103EFIAPI 104SmmMemoryAllocationLibDestructor ( 105 IN EFI_HANDLE ImageHandle, 106 IN EFI_SYSTEM_TABLE *SystemTable 107 ) 108{ 109 FreePool (mSmramRanges); 110 111 return EFI_SUCCESS; 112} 113 114/** 115 Check whether the start address of buffer is within any of the SMRAM ranges. 116 117 @param[in] Buffer The pointer to the buffer to be checked. 118 119 @retval TRUE The buffer is in SMRAM ranges. 120 @retval FALSE The buffer is out of SMRAM ranges. 121**/ 122BOOLEAN 123EFIAPI 124BufferInSmram ( 125 IN VOID *Buffer 126 ) 127{ 128 UINTN Index; 129 130 for (Index = 0; Index < mSmramRangeCount; Index ++) { 131 if (((EFI_PHYSICAL_ADDRESS) (UINTN) Buffer >= mSmramRanges[Index].CpuStart) && 132 ((EFI_PHYSICAL_ADDRESS) (UINTN) Buffer < (mSmramRanges[Index].CpuStart + mSmramRanges[Index].PhysicalSize))) { 133 return TRUE; 134 } 135 } 136 137 return FALSE; 138} 139 140/** 141 Allocates one or more 4KB pages of a certain memory type. 142 143 Allocates the number of 4KB pages of a certain memory type and returns a pointer 144 to the allocated buffer. The buffer returned is aligned on a 4KB boundary. If 145 Pages is 0, then NULL is returned. If there is not enough memory remaining to 146 satisfy the request, then NULL is returned. 147 148 @param MemoryType The type of memory to allocate. 149 @param Pages The number of 4 KB pages to allocate. 150 151 @return A pointer to the allocated buffer or NULL if allocation fails. 152 153**/ 154VOID * 155InternalAllocatePages ( 156 IN EFI_MEMORY_TYPE MemoryType, 157 IN UINTN Pages 158 ) 159{ 160 EFI_STATUS Status; 161 EFI_PHYSICAL_ADDRESS Memory; 162 163 if (Pages == 0) { 164 return NULL; 165 } 166 167 Status = gSmst->SmmAllocatePages (AllocateAnyPages, MemoryType, Pages, &Memory); 168 if (EFI_ERROR (Status)) { 169 return NULL; 170 } 171 return (VOID *) (UINTN) Memory; 172} 173 174/** 175 Allocates one or more 4KB pages of type EfiRuntimeServicesData. 176 177 Allocates the number of 4KB pages of type EfiRuntimeServicesData and returns a pointer 178 to the allocated buffer. The buffer returned is aligned on a 4KB boundary. If 179 Pages is 0, then NULL is returned. If there is not enough memory remaining to 180 satisfy the request, then NULL is returned. 181 182 @param Pages The number of 4 KB pages to allocate. 183 184 @return A pointer to the allocated buffer or NULL if allocation fails. 185 186**/ 187VOID * 188EFIAPI 189AllocatePages ( 190 IN UINTN Pages 191 ) 192{ 193 VOID *Buffer; 194 195 Buffer = InternalAllocatePages (EfiRuntimeServicesData, Pages); 196 if (Buffer != NULL) { 197 MemoryProfileLibRecord ( 198 (PHYSICAL_ADDRESS) (UINTN) RETURN_ADDRESS(0), 199 MEMORY_PROFILE_ACTION_LIB_ALLOCATE_PAGES, 200 EfiRuntimeServicesData, 201 Buffer, 202 EFI_PAGES_TO_SIZE(Pages), 203 NULL 204 ); 205 } 206 return Buffer; 207} 208 209/** 210 Allocates one or more 4KB pages of type EfiRuntimeServicesData. 211 212 Allocates the number of 4KB pages of type EfiRuntimeServicesData and returns a 213 pointer to the allocated buffer. The buffer returned is aligned on a 4KB boundary. 214 If Pages is 0, then NULL is returned. If there is not enough memory remaining 215 to satisfy the request, then NULL is returned. 216 217 @param Pages The number of 4 KB pages to allocate. 218 219 @return A pointer to the allocated buffer or NULL if allocation fails. 220 221**/ 222VOID * 223EFIAPI 224AllocateRuntimePages ( 225 IN UINTN Pages 226 ) 227{ 228 VOID *Buffer; 229 230 Buffer = InternalAllocatePages (EfiRuntimeServicesData, Pages); 231 if (Buffer != NULL) { 232 MemoryProfileLibRecord ( 233 (PHYSICAL_ADDRESS) (UINTN) RETURN_ADDRESS(0), 234 MEMORY_PROFILE_ACTION_LIB_ALLOCATE_RUNTIME_PAGES, 235 EfiRuntimeServicesData, 236 Buffer, 237 EFI_PAGES_TO_SIZE(Pages), 238 NULL 239 ); 240 } 241 return Buffer; 242} 243 244/** 245 Allocates one or more 4KB pages of type EfiReservedMemoryType. 246 247 Allocates the number of 4KB pages of type EfiReservedMemoryType and returns a 248 pointer to the allocated buffer. The buffer returned is aligned on a 4KB boundary. 249 If Pages is 0, then NULL is returned. If there is not enough memory remaining 250 to satisfy the request, then NULL is returned. 251 252 @param Pages The number of 4 KB pages to allocate. 253 254 @return A pointer to the allocated buffer or NULL if allocation fails. 255 256**/ 257VOID * 258EFIAPI 259AllocateReservedPages ( 260 IN UINTN Pages 261 ) 262{ 263 return NULL; 264} 265 266/** 267 Frees one or more 4KB pages that were previously allocated with one of the page allocation 268 functions in the Memory Allocation Library. 269 270 Frees the number of 4KB pages specified by Pages from the buffer specified by Buffer. 271 Buffer must have been allocated on a previous call to the page allocation services 272 of the Memory Allocation Library. If it is not possible to free allocated pages, 273 then this function will perform no actions. 274 275 If Buffer was not allocated with a page allocation function in the Memory Allocation 276 Library, then ASSERT(). 277 If Pages is zero, then ASSERT(). 278 279 @param Buffer The pointer to the buffer of pages to free. 280 @param Pages The number of 4 KB pages to free. 281 282**/ 283VOID 284EFIAPI 285FreePages ( 286 IN VOID *Buffer, 287 IN UINTN Pages 288 ) 289{ 290 EFI_STATUS Status; 291 292 ASSERT (Pages != 0); 293 if (BufferInSmram (Buffer)) { 294 // 295 // When Buffer is in SMRAM range, it should be allocated by gSmst->SmmAllocatePages() service. 296 // So, gSmst->SmmFreePages() service is used to free it. 297 // 298 Status = gSmst->SmmFreePages ((EFI_PHYSICAL_ADDRESS) (UINTN) Buffer, Pages); 299 } else { 300 // 301 // When Buffer is out of SMRAM range, it should be allocated by gBS->AllocatePages() service. 302 // So, gBS->FreePages() service is used to free it. 303 // 304 Status = gBS->FreePages ((EFI_PHYSICAL_ADDRESS) (UINTN) Buffer, Pages); 305 } 306 ASSERT_EFI_ERROR (Status); 307} 308 309/** 310 Allocates one or more 4KB pages of a certain memory type at a specified alignment. 311 312 Allocates the number of 4KB pages specified by Pages of a certain memory type 313 with an alignment specified by Alignment. The allocated buffer is returned. 314 If Pages is 0, then NULL is returned. If there is not enough memory at the 315 specified alignment remaining to satisfy the request, then NULL is returned. 316 If Alignment is not a power of two and Alignment is not zero, then ASSERT(). 317 If Pages plus EFI_SIZE_TO_PAGES (Alignment) overflows, then ASSERT(). 318 319 @param MemoryType The type of memory to allocate. 320 @param Pages The number of 4 KB pages to allocate. 321 @param Alignment The requested alignment of the allocation. 322 Must be a power of two. 323 If Alignment is zero, then byte alignment is used. 324 325 @return A pointer to the allocated buffer or NULL if allocation fails. 326 327**/ 328VOID * 329InternalAllocateAlignedPages ( 330 IN EFI_MEMORY_TYPE MemoryType, 331 IN UINTN Pages, 332 IN UINTN Alignment 333 ) 334{ 335 EFI_STATUS Status; 336 EFI_PHYSICAL_ADDRESS Memory; 337 UINTN AlignedMemory; 338 UINTN AlignmentMask; 339 UINTN UnalignedPages; 340 UINTN RealPages; 341 342 // 343 // Alignment must be a power of two or zero. 344 // 345 ASSERT ((Alignment & (Alignment - 1)) == 0); 346 347 if (Pages == 0) { 348 return NULL; 349 } 350 if (Alignment > EFI_PAGE_SIZE) { 351 // 352 // Calculate the total number of pages since alignment is larger than page size. 353 // 354 AlignmentMask = Alignment - 1; 355 RealPages = Pages + EFI_SIZE_TO_PAGES (Alignment); 356 // 357 // Make sure that Pages plus EFI_SIZE_TO_PAGES (Alignment) does not overflow. 358 // 359 ASSERT (RealPages > Pages); 360 361 Status = gSmst->SmmAllocatePages (AllocateAnyPages, MemoryType, RealPages, &Memory); 362 if (EFI_ERROR (Status)) { 363 return NULL; 364 } 365 AlignedMemory = ((UINTN) Memory + AlignmentMask) & ~AlignmentMask; 366 UnalignedPages = EFI_SIZE_TO_PAGES (AlignedMemory - (UINTN) Memory); 367 if (UnalignedPages > 0) { 368 // 369 // Free first unaligned page(s). 370 // 371 Status = gSmst->SmmFreePages (Memory, UnalignedPages); 372 ASSERT_EFI_ERROR (Status); 373 } 374 Memory = (EFI_PHYSICAL_ADDRESS) (AlignedMemory + EFI_PAGES_TO_SIZE (Pages)); 375 UnalignedPages = RealPages - Pages - UnalignedPages; 376 if (UnalignedPages > 0) { 377 // 378 // Free last unaligned page(s). 379 // 380 Status = gSmst->SmmFreePages (Memory, UnalignedPages); 381 ASSERT_EFI_ERROR (Status); 382 } 383 } else { 384 // 385 // Do not over-allocate pages in this case. 386 // 387 Status = gSmst->SmmAllocatePages (AllocateAnyPages, MemoryType, Pages, &Memory); 388 if (EFI_ERROR (Status)) { 389 return NULL; 390 } 391 AlignedMemory = (UINTN) Memory; 392 } 393 return (VOID *) AlignedMemory; 394} 395 396/** 397 Allocates one or more 4KB pages of type EfiRuntimeServicesData at a specified alignment. 398 399 Allocates the number of 4KB pages specified by Pages of type EfiRuntimeServicesData 400 with an alignment specified by Alignment. The allocated buffer is returned. 401 If Pages is 0, then NULL is returned. If there is not enough memory at the 402 specified alignment remaining to satisfy the request, then NULL is returned. 403 404 If Alignment is not a power of two and Alignment is not zero, then ASSERT(). 405 If Pages plus EFI_SIZE_TO_PAGES (Alignment) overflows, then ASSERT(). 406 407 @param Pages The number of 4 KB pages to allocate. 408 @param Alignment The requested alignment of the allocation. 409 Must be a power of two. 410 If Alignment is zero, then byte alignment is used. 411 412 @return A pointer to the allocated buffer or NULL if allocation fails. 413 414**/ 415VOID * 416EFIAPI 417AllocateAlignedPages ( 418 IN UINTN Pages, 419 IN UINTN Alignment 420 ) 421{ 422 VOID *Buffer; 423 424 Buffer = InternalAllocateAlignedPages (EfiRuntimeServicesData, Pages, Alignment); 425 if (Buffer != NULL) { 426 MemoryProfileLibRecord ( 427 (PHYSICAL_ADDRESS) (UINTN) RETURN_ADDRESS(0), 428 MEMORY_PROFILE_ACTION_LIB_ALLOCATE_ALIGNED_PAGES, 429 EfiRuntimeServicesData, 430 Buffer, 431 EFI_PAGES_TO_SIZE(Pages), 432 NULL 433 ); 434 } 435 return Buffer; 436} 437 438/** 439 Allocates one or more 4KB pages of type EfiRuntimeServicesData at a specified alignment. 440 441 Allocates the number of 4KB pages specified by Pages of type EfiRuntimeServicesData 442 with an alignment specified by Alignment. The allocated buffer is returned. 443 If Pages is 0, then NULL is returned. If there is not enough memory at the 444 specified alignment remaining to satisfy the request, then NULL is returned. 445 446 If Alignment is not a power of two and Alignment is not zero, then ASSERT(). 447 If Pages plus EFI_SIZE_TO_PAGES (Alignment) overflows, then ASSERT(). 448 449 @param Pages The number of 4 KB pages to allocate. 450 @param Alignment The requested alignment of the allocation. 451 Must be a power of two. 452 If Alignment is zero, then byte alignment is used. 453 454 @return A pointer to the allocated buffer or NULL if allocation fails. 455 456**/ 457VOID * 458EFIAPI 459AllocateAlignedRuntimePages ( 460 IN UINTN Pages, 461 IN UINTN Alignment 462 ) 463{ 464 VOID *Buffer; 465 466 Buffer = InternalAllocateAlignedPages (EfiRuntimeServicesData, Pages, Alignment); 467 if (Buffer != NULL) { 468 MemoryProfileLibRecord ( 469 (PHYSICAL_ADDRESS) (UINTN) RETURN_ADDRESS(0), 470 MEMORY_PROFILE_ACTION_LIB_ALLOCATE_ALIGNED_RUNTIME_PAGES, 471 EfiRuntimeServicesData, 472 Buffer, 473 EFI_PAGES_TO_SIZE(Pages), 474 NULL 475 ); 476 } 477 return Buffer; 478} 479 480/** 481 Allocates one or more 4KB pages of type EfiReservedMemoryType at a specified alignment. 482 483 Allocates the number of 4KB pages specified by Pages of type EfiReservedMemoryType 484 with an alignment specified by Alignment. The allocated buffer is returned. 485 If Pages is 0, then NULL is returned. If there is not enough memory at the 486 specified alignment remaining to satisfy the request, then NULL is returned. 487 488 If Alignment is not a power of two and Alignment is not zero, then ASSERT(). 489 If Pages plus EFI_SIZE_TO_PAGES (Alignment) overflows, then ASSERT(). 490 491 @param Pages The number of 4 KB pages to allocate. 492 @param Alignment The requested alignment of the allocation. 493 Must be a power of two. 494 If Alignment is zero, then byte alignment is used. 495 496 @return A pointer to the allocated buffer or NULL if allocation fails. 497 498**/ 499VOID * 500EFIAPI 501AllocateAlignedReservedPages ( 502 IN UINTN Pages, 503 IN UINTN Alignment 504 ) 505{ 506 return NULL; 507} 508 509/** 510 Frees one or more 4KB pages that were previously allocated with one of the aligned page 511 allocation functions in the Memory Allocation Library. 512 513 Frees the number of 4KB pages specified by Pages from the buffer specified by 514 Buffer. Buffer must have been allocated on a previous call to the aligned page 515 allocation services of the Memory Allocation Library. If it is not possible to 516 free allocated pages, then this function will perform no actions. 517 518 If Buffer was not allocated with an aligned page allocation function in the 519 Memory Allocation Library, then ASSERT(). 520 If Pages is zero, then ASSERT(). 521 522 @param Buffer The pointer to the buffer of pages to free. 523 @param Pages The number of 4 KB pages to free. 524 525**/ 526VOID 527EFIAPI 528FreeAlignedPages ( 529 IN VOID *Buffer, 530 IN UINTN Pages 531 ) 532{ 533 EFI_STATUS Status; 534 535 ASSERT (Pages != 0); 536 if (BufferInSmram (Buffer)) { 537 // 538 // When Buffer is in SMRAM range, it should be allocated by gSmst->SmmAllocatePages() service. 539 // So, gSmst->SmmFreePages() service is used to free it. 540 // 541 Status = gSmst->SmmFreePages ((EFI_PHYSICAL_ADDRESS) (UINTN) Buffer, Pages); 542 } else { 543 // 544 // When Buffer is out of SMRAM range, it should be allocated by gBS->AllocatePages() service. 545 // So, gBS->FreePages() service is used to free it. 546 // 547 Status = gBS->FreePages ((EFI_PHYSICAL_ADDRESS) (UINTN) Buffer, Pages); 548 } 549 ASSERT_EFI_ERROR (Status); 550} 551 552/** 553 Allocates a buffer of a certain pool type. 554 555 Allocates the number bytes specified by AllocationSize of a certain pool type 556 and returns a pointer to the allocated buffer. If AllocationSize is 0, then a 557 valid buffer of 0 size is returned. If there is not enough memory remaining to 558 satisfy the request, then NULL is returned. 559 560 @param MemoryType The type of memory to allocate. 561 @param AllocationSize The number of bytes to allocate. 562 563 @return A pointer to the allocated buffer or NULL if allocation fails. 564 565**/ 566VOID * 567InternalAllocatePool ( 568 IN EFI_MEMORY_TYPE MemoryType, 569 IN UINTN AllocationSize 570 ) 571{ 572 EFI_STATUS Status; 573 VOID *Memory; 574 575 Status = gSmst->SmmAllocatePool (MemoryType, AllocationSize, &Memory); 576 if (EFI_ERROR (Status)) { 577 Memory = NULL; 578 } 579 return Memory; 580} 581 582/** 583 Allocates a buffer of type EfiRuntimeServicesData. 584 585 Allocates the number bytes specified by AllocationSize of type EfiRuntimeServicesData 586 and returns a pointer to the allocated buffer. If AllocationSize is 0, then a 587 valid buffer of 0 size is returned. If there is not enough memory remaining to 588 satisfy the request, then NULL is returned. 589 590 @param AllocationSize The number of bytes to allocate. 591 592 @return A pointer to the allocated buffer or NULL if allocation fails. 593 594**/ 595VOID * 596EFIAPI 597AllocatePool ( 598 IN UINTN AllocationSize 599 ) 600{ 601 VOID *Buffer; 602 603 Buffer = InternalAllocatePool (EfiRuntimeServicesData, AllocationSize); 604 if (Buffer != NULL) { 605 MemoryProfileLibRecord ( 606 (PHYSICAL_ADDRESS) (UINTN) RETURN_ADDRESS(0), 607 MEMORY_PROFILE_ACTION_LIB_ALLOCATE_POOL, 608 EfiRuntimeServicesData, 609 Buffer, 610 AllocationSize, 611 NULL 612 ); 613 } 614 return Buffer; 615} 616 617/** 618 Allocates a buffer of type EfiRuntimeServicesData. 619 620 Allocates the number bytes specified by AllocationSize of type EfiRuntimeServicesData 621 and returns a pointer to the allocated buffer. If AllocationSize is 0, then a 622 valid buffer of 0 size is returned. If there is not enough memory remaining to 623 satisfy the request, then NULL is returned. 624 625 @param AllocationSize The number of bytes to allocate. 626 627 @return A pointer to the allocated buffer or NULL if allocation fails. 628 629**/ 630VOID * 631EFIAPI 632AllocateRuntimePool ( 633 IN UINTN AllocationSize 634 ) 635{ 636 VOID *Buffer; 637 638 Buffer = InternalAllocatePool (EfiRuntimeServicesData, AllocationSize); 639 if (Buffer != NULL) { 640 MemoryProfileLibRecord ( 641 (PHYSICAL_ADDRESS) (UINTN) RETURN_ADDRESS(0), 642 MEMORY_PROFILE_ACTION_LIB_ALLOCATE_RUNTIME_POOL, 643 EfiRuntimeServicesData, 644 Buffer, 645 AllocationSize, 646 NULL 647 ); 648 } 649 return Buffer; 650} 651 652/** 653 Allocates a buffer of type EfiReservedMemoryType. 654 655 Allocates the number bytes specified by AllocationSize of type EfiReservedMemoryType 656 and returns a pointer to the allocated buffer. If AllocationSize is 0, then a 657 valid buffer of 0 size is returned. If there is not enough memory remaining to 658 satisfy the request, then NULL is returned. 659 660 @param AllocationSize The number of bytes to allocate. 661 662 @return A pointer to the allocated buffer or NULL if allocation fails. 663 664**/ 665VOID * 666EFIAPI 667AllocateReservedPool ( 668 IN UINTN AllocationSize 669 ) 670{ 671 return NULL; 672} 673 674/** 675 Allocates and zeros a buffer of a certain pool type. 676 677 Allocates the number bytes specified by AllocationSize of a certain pool type, 678 clears the buffer with zeros, and returns a pointer to the allocated buffer. 679 If AllocationSize is 0, then a valid buffer of 0 size is returned. If there is 680 not enough memory remaining to satisfy the request, then NULL is returned. 681 682 @param PoolType The type of memory to allocate. 683 @param AllocationSize The number of bytes to allocate and zero. 684 685 @return A pointer to the allocated buffer or NULL if allocation fails. 686 687**/ 688VOID * 689InternalAllocateZeroPool ( 690 IN EFI_MEMORY_TYPE PoolType, 691 IN UINTN AllocationSize 692 ) 693{ 694 VOID *Memory; 695 696 Memory = InternalAllocatePool (PoolType, AllocationSize); 697 if (Memory != NULL) { 698 Memory = ZeroMem (Memory, AllocationSize); 699 } 700 return Memory; 701} 702 703/** 704 Allocates and zeros a buffer of type EfiRuntimeServicesData. 705 706 Allocates the number bytes specified by AllocationSize of type EfiRuntimeServicesData, 707 clears the buffer with zeros, and returns a pointer to the allocated buffer. 708 If AllocationSize is 0, then a valid buffer of 0 size is returned. If there is 709 not enough memory remaining to satisfy the request, then NULL is returned. 710 711 @param AllocationSize The number of bytes to allocate and zero. 712 713 @return A pointer to the allocated buffer or NULL if allocation fails. 714 715**/ 716VOID * 717EFIAPI 718AllocateZeroPool ( 719 IN UINTN AllocationSize 720 ) 721{ 722 VOID *Buffer; 723 724 Buffer = InternalAllocateZeroPool (EfiRuntimeServicesData, AllocationSize); 725 if (Buffer != NULL) { 726 MemoryProfileLibRecord ( 727 (PHYSICAL_ADDRESS) (UINTN) RETURN_ADDRESS(0), 728 MEMORY_PROFILE_ACTION_LIB_ALLOCATE_ZERO_POOL, 729 EfiRuntimeServicesData, 730 Buffer, 731 AllocationSize, 732 NULL 733 ); 734 } 735 return Buffer; 736} 737 738/** 739 Allocates and zeros a buffer of type EfiRuntimeServicesData. 740 741 Allocates the number bytes specified by AllocationSize of type EfiRuntimeServicesData, 742 clears the buffer with zeros, and returns a pointer to the allocated buffer. 743 If AllocationSize is 0, then a valid buffer of 0 size is returned. If there is 744 not enough memory remaining to satisfy the request, then NULL is returned. 745 746 @param AllocationSize The number of bytes to allocate and zero. 747 748 @return A pointer to the allocated buffer or NULL if allocation fails. 749 750**/ 751VOID * 752EFIAPI 753AllocateRuntimeZeroPool ( 754 IN UINTN AllocationSize 755 ) 756{ 757 VOID *Buffer; 758 759 Buffer = InternalAllocateZeroPool (EfiRuntimeServicesData, AllocationSize); 760 if (Buffer != NULL) { 761 MemoryProfileLibRecord ( 762 (PHYSICAL_ADDRESS) (UINTN) RETURN_ADDRESS(0), 763 MEMORY_PROFILE_ACTION_LIB_ALLOCATE_RUNTIME_ZERO_POOL, 764 EfiRuntimeServicesData, 765 Buffer, 766 AllocationSize, 767 NULL 768 ); 769 } 770 return Buffer; 771} 772 773/** 774 Allocates and zeros a buffer of type EfiReservedMemoryType. 775 776 Allocates the number bytes specified by AllocationSize of type EfiReservedMemoryType, 777 clears the buffer with zeros, and returns a pointer to the allocated buffer. 778 If AllocationSize is 0, then a valid buffer of 0 size is returned. If there is 779 not enough memory remaining to satisfy the request, then NULL is returned. 780 781 @param AllocationSize The number of bytes to allocate and zero. 782 783 @return A pointer to the allocated buffer or NULL if allocation fails. 784 785**/ 786VOID * 787EFIAPI 788AllocateReservedZeroPool ( 789 IN UINTN AllocationSize 790 ) 791{ 792 return NULL; 793} 794 795/** 796 Copies a buffer to an allocated buffer of a certain pool type. 797 798 Allocates the number bytes specified by AllocationSize of a certain pool type, 799 copies AllocationSize bytes from Buffer to the newly allocated buffer, and returns 800 a pointer to the allocated buffer. If AllocationSize is 0, then a valid buffer 801 of 0 size is returned. If there is not enough memory remaining to satisfy the 802 request, then NULL is returned. If Buffer is NULL, then ASSERT(). 803 If AllocationSize is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). 804 805 @param PoolType The type of pool to allocate. 806 @param AllocationSize The number of bytes to allocate and zero. 807 @param Buffer The buffer to copy to the allocated buffer. 808 809 @return A pointer to the allocated buffer or NULL if allocation fails. 810 811**/ 812VOID * 813InternalAllocateCopyPool ( 814 IN EFI_MEMORY_TYPE PoolType, 815 IN UINTN AllocationSize, 816 IN CONST VOID *Buffer 817 ) 818{ 819 VOID *Memory; 820 821 ASSERT (Buffer != NULL); 822 ASSERT (AllocationSize <= (MAX_ADDRESS - (UINTN) Buffer + 1)); 823 824 Memory = InternalAllocatePool (PoolType, AllocationSize); 825 if (Memory != NULL) { 826 Memory = CopyMem (Memory, Buffer, AllocationSize); 827 } 828 return Memory; 829} 830 831/** 832 Copies a buffer to an allocated buffer of type EfiRuntimeServicesData. 833 834 Allocates the number bytes specified by AllocationSize of type EfiRuntimeServicesData, 835 copies AllocationSize bytes from Buffer to the newly allocated buffer, and returns 836 a pointer to the allocated buffer. If AllocationSize is 0, then a valid buffer 837 of 0 size is returned. If there is not enough memory remaining to satisfy the 838 request, then NULL is returned. 839 840 If Buffer is NULL, then ASSERT(). 841 If AllocationSize is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). 842 843 @param AllocationSize The number of bytes to allocate and zero. 844 @param Buffer The buffer to copy to the allocated buffer. 845 846 @return A pointer to the allocated buffer or NULL if allocation fails. 847 848**/ 849VOID * 850EFIAPI 851AllocateCopyPool ( 852 IN UINTN AllocationSize, 853 IN CONST VOID *Buffer 854 ) 855{ 856 VOID *NewBuffer; 857 858 NewBuffer = InternalAllocateCopyPool (EfiRuntimeServicesData, AllocationSize, Buffer); 859 if (NewBuffer != NULL) { 860 MemoryProfileLibRecord ( 861 (PHYSICAL_ADDRESS) (UINTN) RETURN_ADDRESS(0), 862 MEMORY_PROFILE_ACTION_LIB_ALLOCATE_COPY_POOL, 863 EfiRuntimeServicesData, 864 NewBuffer, 865 AllocationSize, 866 NULL 867 ); 868 } 869 return NewBuffer; 870} 871 872/** 873 Copies a buffer to an allocated buffer of type EfiRuntimeServicesData. 874 875 Allocates the number bytes specified by AllocationSize of type EfiRuntimeServicesData, 876 copies AllocationSize bytes from Buffer to the newly allocated buffer, and returns 877 a pointer to the allocated buffer. If AllocationSize is 0, then a valid buffer 878 of 0 size is returned. If there is not enough memory remaining to satisfy the 879 request, then NULL is returned. 880 881 If Buffer is NULL, then ASSERT(). 882 If AllocationSize is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). 883 884 @param AllocationSize The number of bytes to allocate and zero. 885 @param Buffer The buffer to copy to the allocated buffer. 886 887 @return A pointer to the allocated buffer or NULL if allocation fails. 888 889**/ 890VOID * 891EFIAPI 892AllocateRuntimeCopyPool ( 893 IN UINTN AllocationSize, 894 IN CONST VOID *Buffer 895 ) 896{ 897 VOID *NewBuffer; 898 899 NewBuffer = InternalAllocateCopyPool (EfiRuntimeServicesData, AllocationSize, Buffer); 900 if (NewBuffer != NULL) { 901 MemoryProfileLibRecord ( 902 (PHYSICAL_ADDRESS) (UINTN) RETURN_ADDRESS(0), 903 MEMORY_PROFILE_ACTION_LIB_ALLOCATE_RUNTIME_COPY_POOL, 904 EfiRuntimeServicesData, 905 NewBuffer, 906 AllocationSize, 907 NULL 908 ); 909 } 910 return NewBuffer; 911} 912 913/** 914 Copies a buffer to an allocated buffer of type EfiReservedMemoryType. 915 916 Allocates the number bytes specified by AllocationSize of type EfiReservedMemoryType, 917 copies AllocationSize bytes from Buffer to the newly allocated buffer, and returns 918 a pointer to the allocated buffer. If AllocationSize is 0, then a valid buffer 919 of 0 size is returned. If there is not enough memory remaining to satisfy the 920 request, then NULL is returned. 921 922 If Buffer is NULL, then ASSERT(). 923 If AllocationSize is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). 924 925 @param AllocationSize The number of bytes to allocate and zero. 926 @param Buffer The buffer to copy to the allocated buffer. 927 928 @return A pointer to the allocated buffer or NULL if allocation fails. 929 930**/ 931VOID * 932EFIAPI 933AllocateReservedCopyPool ( 934 IN UINTN AllocationSize, 935 IN CONST VOID *Buffer 936 ) 937{ 938 return NULL; 939} 940 941/** 942 Reallocates a buffer of a specified memory type. 943 944 Allocates and zeros the number bytes specified by NewSize from memory of the type 945 specified by PoolType. If OldBuffer is not NULL, then the smaller of OldSize and 946 NewSize bytes are copied from OldBuffer to the newly allocated buffer, and 947 OldBuffer is freed. A pointer to the newly allocated buffer is returned. 948 If NewSize is 0, then a valid buffer of 0 size is returned. If there is not 949 enough memory remaining to satisfy the request, then NULL is returned. 950 951 If the allocation of the new buffer is successful and the smaller of NewSize 952 and OldSize is greater than (MAX_ADDRESS - OldBuffer + 1), then ASSERT(). 953 954 @param PoolType The type of pool to allocate. 955 @param OldSize The size, in bytes, of OldBuffer. 956 @param NewSize The size, in bytes, of the buffer to reallocate. 957 @param OldBuffer The buffer to copy to the allocated buffer. This is an 958 optional parameter that may be NULL. 959 960 @return A pointer to the allocated buffer or NULL if allocation fails. 961 962**/ 963VOID * 964InternalReallocatePool ( 965 IN EFI_MEMORY_TYPE PoolType, 966 IN UINTN OldSize, 967 IN UINTN NewSize, 968 IN VOID *OldBuffer OPTIONAL 969 ) 970{ 971 VOID *NewBuffer; 972 973 NewBuffer = InternalAllocateZeroPool (PoolType, NewSize); 974 if (NewBuffer != NULL && OldBuffer != NULL) { 975 CopyMem (NewBuffer, OldBuffer, MIN (OldSize, NewSize)); 976 FreePool (OldBuffer); 977 } 978 return NewBuffer; 979} 980 981/** 982 Reallocates a buffer of type EfiRuntimeServicesData. 983 984 Allocates and zeros the number bytes specified by NewSize from memory of type 985 EfiRuntimeServicesData. If OldBuffer is not NULL, then the smaller of OldSize and 986 NewSize bytes are copied from OldBuffer to the newly allocated buffer, and 987 OldBuffer is freed. A pointer to the newly allocated buffer is returned. 988 If NewSize is 0, then a valid buffer of 0 size is returned. If there is not 989 enough memory remaining to satisfy the request, then NULL is returned. 990 991 If the allocation of the new buffer is successful and the smaller of NewSize 992 and OldSize is greater than (MAX_ADDRESS - OldBuffer + 1), then ASSERT(). 993 994 @param OldSize The size, in bytes, of OldBuffer. 995 @param NewSize The size, in bytes, of the buffer to reallocate. 996 @param OldBuffer The buffer to copy to the allocated buffer. This is an 997 optional parameter that may be NULL. 998 999 @return A pointer to the allocated buffer or NULL if allocation fails. 1000 1001**/ 1002VOID * 1003EFIAPI 1004ReallocatePool ( 1005 IN UINTN OldSize, 1006 IN UINTN NewSize, 1007 IN VOID *OldBuffer OPTIONAL 1008 ) 1009{ 1010 VOID *Buffer; 1011 1012 Buffer = InternalReallocatePool (EfiRuntimeServicesData, OldSize, NewSize, OldBuffer); 1013 if (Buffer != NULL) { 1014 MemoryProfileLibRecord ( 1015 (PHYSICAL_ADDRESS) (UINTN) RETURN_ADDRESS(0), 1016 MEMORY_PROFILE_ACTION_LIB_REALLOCATE_POOL, 1017 EfiRuntimeServicesData, 1018 Buffer, 1019 NewSize, 1020 NULL 1021 ); 1022 } 1023 return Buffer; 1024} 1025 1026/** 1027 Reallocates a buffer of type EfiRuntimeServicesData. 1028 1029 Allocates and zeros the number bytes specified by NewSize from memory of type 1030 EfiRuntimeServicesData. If OldBuffer is not NULL, then the smaller of OldSize 1031 and NewSize bytes are copied from OldBuffer to the newly allocated buffer, and 1032 OldBuffer is freed. A pointer to the newly allocated buffer is returned. 1033 If NewSize is 0, then a valid buffer of 0 size is returned. If there is not 1034 enough memory remaining to satisfy the request, then NULL is returned. 1035 1036 If the allocation of the new buffer is successful and the smaller of NewSize 1037 and OldSize is greater than (MAX_ADDRESS - OldBuffer + 1), then ASSERT(). 1038 1039 @param OldSize The size, in bytes, of OldBuffer. 1040 @param NewSize The size, in bytes, of the buffer to reallocate. 1041 @param OldBuffer The buffer to copy to the allocated buffer. This is an 1042 optional parameter that may be NULL. 1043 1044 @return A pointer to the allocated buffer or NULL if allocation fails. 1045 1046**/ 1047VOID * 1048EFIAPI 1049ReallocateRuntimePool ( 1050 IN UINTN OldSize, 1051 IN UINTN NewSize, 1052 IN VOID *OldBuffer OPTIONAL 1053 ) 1054{ 1055 VOID *Buffer; 1056 1057 Buffer = InternalReallocatePool (EfiRuntimeServicesData, OldSize, NewSize, OldBuffer); 1058 if (Buffer != NULL) { 1059 MemoryProfileLibRecord ( 1060 (PHYSICAL_ADDRESS) (UINTN) RETURN_ADDRESS(0), 1061 MEMORY_PROFILE_ACTION_LIB_REALLOCATE_RUNTIME_POOL, 1062 EfiRuntimeServicesData, 1063 Buffer, 1064 NewSize, 1065 NULL 1066 ); 1067 } 1068 return Buffer; 1069} 1070 1071/** 1072 Reallocates a buffer of type EfiReservedMemoryType. 1073 1074 Allocates and zeros the number bytes specified by NewSize from memory of type 1075 EfiReservedMemoryType. If OldBuffer is not NULL, then the smaller of OldSize 1076 and NewSize bytes are copied from OldBuffer to the newly allocated buffer, and 1077 OldBuffer is freed. A pointer to the newly allocated buffer is returned. 1078 If NewSize is 0, then a valid buffer of 0 size is returned. If there is not 1079 enough memory remaining to satisfy the request, then NULL is returned. 1080 1081 If the allocation of the new buffer is successful and the smaller of NewSize 1082 and OldSize is greater than (MAX_ADDRESS - OldBuffer + 1), then ASSERT(). 1083 1084 @param OldSize The size, in bytes, of OldBuffer. 1085 @param NewSize The size, in bytes, of the buffer to reallocate. 1086 @param OldBuffer The buffer to copy to the allocated buffer. This is an 1087 optional parameter that may be NULL. 1088 1089 @return A pointer to the allocated buffer or NULL if allocation fails. 1090 1091**/ 1092VOID * 1093EFIAPI 1094ReallocateReservedPool ( 1095 IN UINTN OldSize, 1096 IN UINTN NewSize, 1097 IN VOID *OldBuffer OPTIONAL 1098 ) 1099{ 1100 return NULL; 1101} 1102 1103/** 1104 Frees a buffer that was previously allocated with one of the pool allocation 1105 functions in the Memory Allocation Library. 1106 1107 Frees the buffer specified by Buffer. Buffer must have been allocated on a 1108 previous call to the pool allocation services of the Memory Allocation Library. 1109 If it is not possible to free pool resources, then this function will perform 1110 no actions. 1111 1112 If Buffer was not allocated with a pool allocation function in the Memory 1113 Allocation Library, then ASSERT(). 1114 1115 @param Buffer The pointer to the buffer to free. 1116 1117**/ 1118VOID 1119EFIAPI 1120FreePool ( 1121 IN VOID *Buffer 1122 ) 1123{ 1124 EFI_STATUS Status; 1125 1126 if (BufferInSmram (Buffer)) { 1127 // 1128 // When Buffer is in SMRAM range, it should be allocated by gSmst->SmmAllocatePool() service. 1129 // So, gSmst->SmmFreePool() service is used to free it. 1130 // 1131 Status = gSmst->SmmFreePool (Buffer); 1132 } else { 1133 // 1134 // When Buffer is out of SMRAM range, it should be allocated by gBS->AllocatePool() service. 1135 // So, gBS->FreePool() service is used to free it. 1136 // 1137 Status = gBS->FreePool (Buffer); 1138 } 1139 ASSERT_EFI_ERROR (Status); 1140} 1141