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