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