Home | History | Annotate | Download | only in SmmMemoryAllocationLib
      1 /** @file
      2   Support routines for memory allocation routines based
      3   on SMM Services Table services for SMM phase drivers.
      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 - 2015, 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 EFI_SMRAM_DESCRIPTOR  *mSmramRanges;
     36 UINTN                 mSmramRangeCount;
     37 
     38 /**
     39   The constructor function caches SMRAM ranges that are present in the system.
     40 
     41   It will ASSERT() if SMM Access2 Protocol doesn't exist.
     42   It will ASSERT() if SMRAM ranges can't be got.
     43   It will ASSERT() if Resource can't be allocated for cache SMRAM range.
     44   It will always return EFI_SUCCESS.
     45 
     46   @param  ImageHandle   The firmware allocated handle for the EFI image.
     47   @param  SystemTable   A pointer to the EFI System Table.
     48 
     49   @retval EFI_SUCCESS   The constructor always returns EFI_SUCCESS.
     50 
     51 **/
     52 EFI_STATUS
     53 EFIAPI
     54 SmmMemoryAllocationLibConstructor (
     55   IN EFI_HANDLE        ImageHandle,
     56   IN EFI_SYSTEM_TABLE  *SystemTable
     57   )
     58 {
     59   EFI_STATUS                Status;
     60   EFI_SMM_ACCESS2_PROTOCOL  *SmmAccess;
     61   UINTN                     Size;
     62 
     63   //
     64   // Locate SMM Access2 Protocol
     65   //
     66   Status = gBS->LocateProtocol (
     67                   &gEfiSmmAccess2ProtocolGuid,
     68                   NULL,
     69                   (VOID **)&SmmAccess
     70                   );
     71   ASSERT_EFI_ERROR (Status);
     72 
     73   //
     74   // Get SMRAM range information
     75   //
     76   Size = 0;
     77   Status = SmmAccess->GetCapabilities (SmmAccess, &Size, NULL);
     78   ASSERT (Status == EFI_BUFFER_TOO_SMALL);
     79 
     80   mSmramRanges = (EFI_SMRAM_DESCRIPTOR *) AllocatePool (Size);
     81   ASSERT (mSmramRanges != NULL);
     82 
     83   Status = SmmAccess->GetCapabilities (SmmAccess, &Size, mSmramRanges);
     84   ASSERT_EFI_ERROR (Status);
     85 
     86   mSmramRangeCount = Size / sizeof (EFI_SMRAM_DESCRIPTOR);
     87 
     88   return EFI_SUCCESS;
     89 }
     90 
     91 /**
     92   If SMM driver exits with an error, it must call this routine
     93   to free the allocated resource before the exiting.
     94 
     95   @param[in]  ImageHandle   The firmware allocated handle for the EFI image.
     96   @param[in]  SystemTable   A pointer to the EFI System Table.
     97 
     98   @retval     EFI_SUCCESS   The deconstructor always returns EFI_SUCCESS.
     99 **/
    100 EFI_STATUS
    101 EFIAPI
    102 SmmMemoryAllocationLibDestructor (
    103   IN EFI_HANDLE        ImageHandle,
    104   IN EFI_SYSTEM_TABLE  *SystemTable
    105   )
    106 {
    107   FreePool (mSmramRanges);
    108 
    109   return EFI_SUCCESS;
    110 }
    111 
    112 /**
    113   Check whether the start address of buffer is within any of the SMRAM ranges.
    114 
    115   @param[in]  Buffer   The pointer to the buffer to be checked.
    116 
    117   @retval     TURE     The buffer is in SMRAM ranges.
    118   @retval     FALSE    The buffer is out of SMRAM ranges.
    119 **/
    120 BOOLEAN
    121 EFIAPI
    122 BufferInSmram (
    123   IN VOID *Buffer
    124   )
    125 {
    126   UINTN  Index;
    127 
    128   for (Index = 0; Index < mSmramRangeCount; Index ++) {
    129     if (((EFI_PHYSICAL_ADDRESS) (UINTN) Buffer >= mSmramRanges[Index].CpuStart) &&
    130         ((EFI_PHYSICAL_ADDRESS) (UINTN) Buffer < (mSmramRanges[Index].CpuStart + mSmramRanges[Index].PhysicalSize))) {
    131       return TRUE;
    132     }
    133   }
    134 
    135   return FALSE;
    136 }
    137 
    138 /**
    139   Allocates one or more 4KB pages of a certain memory type.
    140 
    141   Allocates the number of 4KB pages of a certain memory type and returns a pointer
    142   to the allocated buffer.  The buffer returned is aligned on a 4KB boundary.  If
    143   Pages is 0, then NULL is returned.   If there is not enough memory remaining to
    144   satisfy the request, then NULL is returned.
    145 
    146   @param  MemoryType            The type of memory to allocate.
    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 InternalAllocatePages (
    154   IN EFI_MEMORY_TYPE  MemoryType,
    155   IN UINTN            Pages
    156   )
    157 {
    158   EFI_STATUS            Status;
    159   EFI_PHYSICAL_ADDRESS  Memory;
    160 
    161   if (Pages == 0) {
    162     return NULL;
    163   }
    164 
    165   Status = gSmst->SmmAllocatePages (AllocateAnyPages, MemoryType, Pages, &Memory);
    166   if (EFI_ERROR (Status)) {
    167     return NULL;
    168   }
    169   return (VOID *) (UINTN) Memory;
    170 }
    171 
    172 /**
    173   Allocates one or more 4KB pages of type EfiRuntimeServicesData.
    174 
    175   Allocates the number of 4KB pages of type EfiRuntimeServicesData and returns a pointer
    176   to the allocated buffer.  The buffer returned is aligned on a 4KB boundary.  If
    177   Pages is 0, then NULL is returned.  If there is not enough memory remaining to
    178   satisfy the request, then NULL is returned.
    179 
    180   @param  Pages                 The number of 4 KB pages to allocate.
    181 
    182   @return A pointer to the allocated buffer or NULL if allocation fails.
    183 
    184 **/
    185 VOID *
    186 EFIAPI
    187 AllocatePages (
    188   IN UINTN  Pages
    189   )
    190 {
    191   return InternalAllocatePages (EfiRuntimeServicesData, Pages);
    192 }
    193 
    194 /**
    195   Allocates one or more 4KB pages of type EfiRuntimeServicesData.
    196 
    197   Allocates the number of 4KB pages of type EfiRuntimeServicesData and returns a
    198   pointer to the allocated buffer.  The buffer returned is aligned on a 4KB boundary.
    199   If Pages is 0, then NULL is returned.  If there is not enough memory remaining
    200   to satisfy the request, then NULL is returned.
    201 
    202   @param  Pages                 The number of 4 KB pages to allocate.
    203 
    204   @return A pointer to the allocated buffer or NULL if allocation fails.
    205 
    206 **/
    207 VOID *
    208 EFIAPI
    209 AllocateRuntimePages (
    210   IN UINTN  Pages
    211   )
    212 {
    213   return InternalAllocatePages (EfiRuntimeServicesData, Pages);
    214 }
    215 
    216 /**
    217   Allocates one or more 4KB pages of type EfiReservedMemoryType.
    218 
    219   Allocates the number of 4KB pages of type EfiReservedMemoryType and returns a
    220   pointer to the allocated buffer.  The buffer returned is aligned on a 4KB boundary.
    221   If Pages is 0, then NULL is returned.  If there is not enough memory remaining
    222   to satisfy the request, then NULL is returned.
    223 
    224   @param  Pages                 The number of 4 KB pages to allocate.
    225 
    226   @return A pointer to the allocated buffer or NULL if allocation fails.
    227 
    228 **/
    229 VOID *
    230 EFIAPI
    231 AllocateReservedPages (
    232   IN UINTN  Pages
    233   )
    234 {
    235   return NULL;
    236 }
    237 
    238 /**
    239   Frees one or more 4KB pages that were previously allocated with one of the page allocation
    240   functions in the Memory Allocation Library.
    241 
    242   Frees the number of 4KB pages specified by Pages from the buffer specified by Buffer.
    243   Buffer must have been allocated on a previous call to the page allocation services
    244   of the Memory Allocation Library.  If it is not possible to free allocated pages,
    245   then this function will perform no actions.
    246 
    247   If Buffer was not allocated with a page allocation function in the Memory Allocation
    248   Library, then ASSERT().
    249   If Pages is zero, then ASSERT().
    250 
    251   @param  Buffer                The pointer to the buffer of pages to free.
    252   @param  Pages                 The number of 4 KB pages to free.
    253 
    254 **/
    255 VOID
    256 EFIAPI
    257 FreePages (
    258   IN VOID   *Buffer,
    259   IN UINTN  Pages
    260   )
    261 {
    262   EFI_STATUS  Status;
    263 
    264   ASSERT (Pages != 0);
    265   if (BufferInSmram (Buffer)) {
    266     //
    267     // When Buffer is in SMRAM range, it should be allocated by gSmst->SmmAllocatePages() service.
    268     // So, gSmst->SmmFreePages() service is used to free it.
    269     //
    270     Status = gSmst->SmmFreePages ((EFI_PHYSICAL_ADDRESS) (UINTN) Buffer, Pages);
    271   } else {
    272     //
    273     // When Buffer is out of SMRAM range, it should be allocated by gBS->AllocatePages() service.
    274     // So, gBS->FreePages() service is used to free it.
    275     //
    276     Status = gBS->FreePages ((EFI_PHYSICAL_ADDRESS) (UINTN) Buffer, Pages);
    277   }
    278   ASSERT_EFI_ERROR (Status);
    279 }
    280 
    281 /**
    282   Allocates one or more 4KB pages of a certain memory type at a specified alignment.
    283 
    284   Allocates the number of 4KB pages specified by Pages of a certain memory type
    285   with an alignment specified by Alignment.  The allocated buffer is returned.
    286   If Pages is 0, then NULL is returned. If there is not enough memory at the
    287   specified alignment remaining to satisfy the request, then NULL is returned.
    288   If Alignment is not a power of two and Alignment is not zero, then ASSERT().
    289   If Pages plus EFI_SIZE_TO_PAGES (Alignment) overflows, then ASSERT().
    290 
    291   @param  MemoryType            The type of memory to allocate.
    292   @param  Pages                 The number of 4 KB pages to allocate.
    293   @param  Alignment             The requested alignment of the allocation.
    294                                 Must be a power of two.
    295                                 If Alignment is zero, then byte alignment is used.
    296 
    297   @return A pointer to the allocated buffer or NULL if allocation fails.
    298 
    299 **/
    300 VOID *
    301 InternalAllocateAlignedPages (
    302   IN EFI_MEMORY_TYPE  MemoryType,
    303   IN UINTN            Pages,
    304   IN UINTN            Alignment
    305   )
    306 {
    307   EFI_STATUS            Status;
    308   EFI_PHYSICAL_ADDRESS  Memory;
    309   UINTN                 AlignedMemory;
    310   UINTN                 AlignmentMask;
    311   UINTN                 UnalignedPages;
    312   UINTN                 RealPages;
    313 
    314   //
    315   // Alignment must be a power of two or zero.
    316   //
    317   ASSERT ((Alignment & (Alignment - 1)) == 0);
    318 
    319   if (Pages == 0) {
    320     return NULL;
    321   }
    322   if (Alignment > EFI_PAGE_SIZE) {
    323     //
    324     // Calculate the total number of pages since alignment is larger than page size.
    325     //
    326     AlignmentMask  = Alignment - 1;
    327     RealPages      = Pages + EFI_SIZE_TO_PAGES (Alignment);
    328     //
    329     // Make sure that Pages plus EFI_SIZE_TO_PAGES (Alignment) does not overflow.
    330     //
    331     ASSERT (RealPages > Pages);
    332 
    333     Status         = gSmst->SmmAllocatePages (AllocateAnyPages, MemoryType, RealPages, &Memory);
    334     if (EFI_ERROR (Status)) {
    335       return NULL;
    336     }
    337     AlignedMemory  = ((UINTN) Memory + AlignmentMask) & ~AlignmentMask;
    338     UnalignedPages = EFI_SIZE_TO_PAGES (AlignedMemory - (UINTN) Memory);
    339     if (UnalignedPages > 0) {
    340       //
    341       // Free first unaligned page(s).
    342       //
    343       Status = gSmst->SmmFreePages (Memory, UnalignedPages);
    344       ASSERT_EFI_ERROR (Status);
    345     }
    346     Memory         = (EFI_PHYSICAL_ADDRESS) (AlignedMemory + EFI_PAGES_TO_SIZE (Pages));
    347     UnalignedPages = RealPages - Pages - UnalignedPages;
    348     if (UnalignedPages > 0) {
    349       //
    350       // Free last unaligned page(s).
    351       //
    352       Status = gSmst->SmmFreePages (Memory, UnalignedPages);
    353       ASSERT_EFI_ERROR (Status);
    354     }
    355   } else {
    356     //
    357     // Do not over-allocate pages in this case.
    358     //
    359     Status = gSmst->SmmAllocatePages (AllocateAnyPages, MemoryType, Pages, &Memory);
    360     if (EFI_ERROR (Status)) {
    361       return NULL;
    362     }
    363     AlignedMemory  = (UINTN) Memory;
    364   }
    365   return (VOID *) AlignedMemory;
    366 }
    367 
    368 /**
    369   Allocates one or more 4KB pages of type EfiRuntimeServicesData at a specified alignment.
    370 
    371   Allocates the number of 4KB pages specified by Pages of type EfiRuntimeServicesData
    372   with an alignment specified by Alignment.  The allocated buffer is returned.
    373   If Pages is 0, then NULL is returned.  If there is not enough memory at the
    374   specified alignment remaining to satisfy the request, then NULL is returned.
    375 
    376   If Alignment is not a power of two and Alignment is not zero, then ASSERT().
    377   If Pages plus EFI_SIZE_TO_PAGES (Alignment) overflows, then ASSERT().
    378 
    379   @param  Pages                 The number of 4 KB pages to allocate.
    380   @param  Alignment             The requested alignment of the allocation.
    381                                 Must be a power of two.
    382                                 If Alignment is zero, then byte alignment is used.
    383 
    384   @return A pointer to the allocated buffer or NULL if allocation fails.
    385 
    386 **/
    387 VOID *
    388 EFIAPI
    389 AllocateAlignedPages (
    390   IN UINTN  Pages,
    391   IN UINTN  Alignment
    392   )
    393 {
    394   return InternalAllocateAlignedPages (EfiRuntimeServicesData, Pages, Alignment);
    395 }
    396 
    397 /**
    398   Allocates one or more 4KB pages of type EfiRuntimeServicesData at a specified alignment.
    399 
    400   Allocates the number of 4KB pages specified by Pages of type EfiRuntimeServicesData
    401   with an alignment specified by Alignment.  The allocated buffer is returned.
    402   If Pages is 0, then NULL is returned.  If there is not enough memory at the
    403   specified alignment remaining to satisfy the request, then NULL is returned.
    404 
    405   If Alignment is not a power of two and Alignment is not zero, then ASSERT().
    406   If Pages plus EFI_SIZE_TO_PAGES (Alignment) overflows, then ASSERT().
    407 
    408   @param  Pages                 The number of 4 KB pages to allocate.
    409   @param  Alignment             The requested alignment of the allocation.
    410                                 Must be a power of two.
    411                                 If Alignment is zero, then byte alignment is used.
    412 
    413   @return A pointer to the allocated buffer or NULL if allocation fails.
    414 
    415 **/
    416 VOID *
    417 EFIAPI
    418 AllocateAlignedRuntimePages (
    419   IN UINTN  Pages,
    420   IN UINTN  Alignment
    421   )
    422 {
    423   return InternalAllocateAlignedPages (EfiRuntimeServicesData, Pages, Alignment);
    424 }
    425 
    426 /**
    427   Allocates one or more 4KB pages of type EfiReservedMemoryType at a specified alignment.
    428 
    429   Allocates the number of 4KB pages specified by Pages of type EfiReservedMemoryType
    430   with an alignment specified by Alignment.  The allocated buffer is returned.
    431   If Pages is 0, then NULL is returned.  If there is not enough memory at the
    432   specified alignment remaining to satisfy the request, then NULL is returned.
    433 
    434   If Alignment is not a power of two and Alignment is not zero, then ASSERT().
    435   If Pages plus EFI_SIZE_TO_PAGES (Alignment) overflows, then ASSERT().
    436 
    437   @param  Pages                 The number of 4 KB pages to allocate.
    438   @param  Alignment             The requested alignment of the allocation.
    439                                 Must be a power of two.
    440                                 If Alignment is zero, then byte alignment is used.
    441 
    442   @return A pointer to the allocated buffer or NULL if allocation fails.
    443 
    444 **/
    445 VOID *
    446 EFIAPI
    447 AllocateAlignedReservedPages (
    448   IN UINTN  Pages,
    449   IN UINTN  Alignment
    450   )
    451 {
    452   return NULL;
    453 }
    454 
    455 /**
    456   Frees one or more 4KB pages that were previously allocated with one of the aligned page
    457   allocation functions in the Memory Allocation Library.
    458 
    459   Frees the number of 4KB pages specified by Pages from the buffer specified by
    460   Buffer.  Buffer must have been allocated on a previous call to the aligned page
    461   allocation services of the Memory Allocation Library.  If it is not possible to
    462   free allocated pages, then this function will perform no actions.
    463 
    464   If Buffer was not allocated with an aligned page allocation function in the
    465   Memory Allocation Library, then ASSERT().
    466   If Pages is zero, then ASSERT().
    467 
    468   @param  Buffer                The pointer to the buffer of pages to free.
    469   @param  Pages                 The number of 4 KB pages to free.
    470 
    471 **/
    472 VOID
    473 EFIAPI
    474 FreeAlignedPages (
    475   IN VOID   *Buffer,
    476   IN UINTN  Pages
    477   )
    478 {
    479   EFI_STATUS  Status;
    480 
    481   ASSERT (Pages != 0);
    482   if (BufferInSmram (Buffer)) {
    483     //
    484     // When Buffer is in SMRAM range, it should be allocated by gSmst->SmmAllocatePages() service.
    485     // So, gSmst->SmmFreePages() service is used to free it.
    486     //
    487     Status = gSmst->SmmFreePages ((EFI_PHYSICAL_ADDRESS) (UINTN) Buffer, Pages);
    488   } else {
    489     //
    490     // When Buffer is out of SMRAM range, it should be allocated by gBS->AllocatePages() service.
    491     // So, gBS->FreePages() service is used to free it.
    492     //
    493     Status = gBS->FreePages ((EFI_PHYSICAL_ADDRESS) (UINTN) Buffer, Pages);
    494   }
    495   ASSERT_EFI_ERROR (Status);
    496 }
    497 
    498 /**
    499   Allocates a buffer of a certain pool type.
    500 
    501   Allocates the number bytes specified by AllocationSize of a certain pool type
    502   and returns a pointer to the allocated buffer.  If AllocationSize is 0, then a
    503   valid buffer of 0 size is returned.  If there is not enough memory remaining to
    504   satisfy the request, then NULL is returned.
    505 
    506   @param  MemoryType            The type of memory to allocate.
    507   @param  AllocationSize        The number of bytes to allocate.
    508 
    509   @return A pointer to the allocated buffer or NULL if allocation fails.
    510 
    511 **/
    512 VOID *
    513 InternalAllocatePool (
    514   IN EFI_MEMORY_TYPE  MemoryType,
    515   IN UINTN            AllocationSize
    516   )
    517 {
    518   EFI_STATUS  Status;
    519   VOID        *Memory;
    520 
    521   Status = gSmst->SmmAllocatePool (MemoryType, AllocationSize, &Memory);
    522   if (EFI_ERROR (Status)) {
    523     Memory = NULL;
    524   }
    525   return Memory;
    526 }
    527 
    528 /**
    529   Allocates a buffer of type EfiRuntimeServicesData.
    530 
    531   Allocates the number bytes specified by AllocationSize of type EfiRuntimeServicesData
    532   and returns a pointer to the allocated buffer.  If AllocationSize is 0, then a
    533   valid buffer of 0 size is returned.  If there is not enough memory remaining to
    534   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 AllocatePool (
    544   IN UINTN  AllocationSize
    545   )
    546 {
    547   return InternalAllocatePool (EfiRuntimeServicesData, AllocationSize);
    548 }
    549 
    550 /**
    551   Allocates a buffer of type EfiRuntimeServicesData.
    552 
    553   Allocates the number bytes specified by AllocationSize of type EfiRuntimeServicesData
    554   and returns a pointer to the allocated buffer.  If AllocationSize is 0, then a
    555   valid buffer of 0 size is returned.  If there is not enough memory remaining to
    556   satisfy the request, then NULL is returned.
    557 
    558   @param  AllocationSize        The number of bytes to allocate.
    559 
    560   @return A pointer to the allocated buffer or NULL if allocation fails.
    561 
    562 **/
    563 VOID *
    564 EFIAPI
    565 AllocateRuntimePool (
    566   IN UINTN  AllocationSize
    567   )
    568 {
    569   return InternalAllocatePool (EfiRuntimeServicesData, AllocationSize);
    570 }
    571 
    572 /**
    573   Allocates a buffer of type EfiReservedMemoryType.
    574 
    575   Allocates the number bytes specified by AllocationSize of type EfiReservedMemoryType
    576   and returns a pointer to the allocated buffer.  If AllocationSize is 0, then a
    577   valid buffer of 0 size is returned.  If there is not enough memory remaining to
    578   satisfy the request, then NULL is returned.
    579 
    580   @param  AllocationSize        The number of bytes to allocate.
    581 
    582   @return A pointer to the allocated buffer or NULL if allocation fails.
    583 
    584 **/
    585 VOID *
    586 EFIAPI
    587 AllocateReservedPool (
    588   IN UINTN  AllocationSize
    589   )
    590 {
    591   return NULL;
    592 }
    593 
    594 /**
    595   Allocates and zeros a buffer of a certain pool type.
    596 
    597   Allocates the number bytes specified by AllocationSize of a certain pool type,
    598   clears the buffer with zeros, and returns a pointer to the allocated buffer.
    599   If AllocationSize is 0, then a valid buffer of 0 size is returned.  If there is
    600   not enough memory remaining to satisfy the request, then NULL is returned.
    601 
    602   @param  PoolType              The type of memory to allocate.
    603   @param  AllocationSize        The number of bytes to allocate and zero.
    604 
    605   @return A pointer to the allocated buffer or NULL if allocation fails.
    606 
    607 **/
    608 VOID *
    609 InternalAllocateZeroPool (
    610   IN EFI_MEMORY_TYPE  PoolType,
    611   IN UINTN            AllocationSize
    612   )
    613 {
    614   VOID  *Memory;
    615 
    616   Memory = InternalAllocatePool (PoolType, AllocationSize);
    617   if (Memory != NULL) {
    618     Memory = ZeroMem (Memory, AllocationSize);
    619   }
    620   return Memory;
    621 }
    622 
    623 /**
    624   Allocates and zeros a buffer of type EfiRuntimeServicesData.
    625 
    626   Allocates the number bytes specified by AllocationSize of type EfiRuntimeServicesData,
    627   clears the buffer with zeros, and returns a pointer to the allocated buffer.
    628   If AllocationSize is 0, then a valid buffer of 0 size is returned.  If there is
    629   not enough memory remaining to satisfy the request, then NULL is returned.
    630 
    631   @param  AllocationSize        The number of bytes to allocate and zero.
    632 
    633   @return A pointer to the allocated buffer or NULL if allocation fails.
    634 
    635 **/
    636 VOID *
    637 EFIAPI
    638 AllocateZeroPool (
    639   IN UINTN  AllocationSize
    640   )
    641 {
    642   return InternalAllocateZeroPool (EfiRuntimeServicesData, AllocationSize);
    643 }
    644 
    645 /**
    646   Allocates and zeros a buffer of type EfiRuntimeServicesData.
    647 
    648   Allocates the number bytes specified by AllocationSize of type EfiRuntimeServicesData,
    649   clears the buffer with zeros, and returns a pointer to the allocated buffer.
    650   If AllocationSize is 0, then a valid buffer of 0 size is returned.  If there is
    651   not enough memory remaining to satisfy the request, then NULL is returned.
    652 
    653   @param  AllocationSize        The number of bytes to allocate and zero.
    654 
    655   @return A pointer to the allocated buffer or NULL if allocation fails.
    656 
    657 **/
    658 VOID *
    659 EFIAPI
    660 AllocateRuntimeZeroPool (
    661   IN UINTN  AllocationSize
    662   )
    663 {
    664   return InternalAllocateZeroPool (EfiRuntimeServicesData, AllocationSize);
    665 }
    666 
    667 /**
    668   Allocates and zeros a buffer of type EfiReservedMemoryType.
    669 
    670   Allocates the number bytes specified by AllocationSize of type EfiReservedMemoryType,
    671   clears the   buffer with zeros, and returns a pointer to the allocated buffer.
    672   If AllocationSize is 0, then a valid buffer of 0 size is returned.  If there is
    673   not enough memory remaining to satisfy the request, then NULL is returned.
    674 
    675   @param  AllocationSize        The number of bytes to allocate and zero.
    676 
    677   @return A pointer to the allocated buffer or NULL if allocation fails.
    678 
    679 **/
    680 VOID *
    681 EFIAPI
    682 AllocateReservedZeroPool (
    683   IN UINTN  AllocationSize
    684   )
    685 {
    686   return NULL;
    687 }
    688 
    689 /**
    690   Copies a buffer to an allocated buffer of a certain pool type.
    691 
    692   Allocates the number bytes specified by AllocationSize of a certain pool type,
    693   copies AllocationSize bytes from Buffer to the newly allocated buffer, and returns
    694   a pointer to the allocated buffer.  If AllocationSize is 0, then a valid buffer
    695   of 0 size is returned.  If there is not enough memory remaining to satisfy the
    696   request, then NULL is returned. If Buffer is NULL, then ASSERT().
    697   If AllocationSize is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT().
    698 
    699   @param  PoolType              The type of pool to allocate.
    700   @param  AllocationSize        The number of bytes to allocate and zero.
    701   @param  Buffer                The buffer to copy to the allocated buffer.
    702 
    703   @return A pointer to the allocated buffer or NULL if allocation fails.
    704 
    705 **/
    706 VOID *
    707 InternalAllocateCopyPool (
    708   IN EFI_MEMORY_TYPE  PoolType,
    709   IN UINTN            AllocationSize,
    710   IN CONST VOID       *Buffer
    711   )
    712 {
    713   VOID  *Memory;
    714 
    715   ASSERT (Buffer != NULL);
    716   ASSERT (AllocationSize <= (MAX_ADDRESS - (UINTN) Buffer + 1));
    717 
    718   Memory = InternalAllocatePool (PoolType, AllocationSize);
    719   if (Memory != NULL) {
    720      Memory = CopyMem (Memory, Buffer, AllocationSize);
    721   }
    722   return Memory;
    723 }
    724 
    725 /**
    726   Copies a buffer to an allocated buffer of type EfiRuntimeServicesData.
    727 
    728   Allocates the number bytes specified by AllocationSize of type EfiRuntimeServicesData,
    729   copies AllocationSize bytes from Buffer to the newly allocated buffer, and returns
    730   a pointer to the allocated buffer.  If AllocationSize is 0, then a valid buffer
    731   of 0 size is returned.  If there is not enough memory remaining to satisfy the
    732   request, then NULL is returned.
    733 
    734   If Buffer is NULL, then ASSERT().
    735   If AllocationSize is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT().
    736 
    737   @param  AllocationSize        The number of bytes to allocate and zero.
    738   @param  Buffer                The buffer to copy to the allocated buffer.
    739 
    740   @return A pointer to the allocated buffer or NULL if allocation fails.
    741 
    742 **/
    743 VOID *
    744 EFIAPI
    745 AllocateCopyPool (
    746   IN UINTN       AllocationSize,
    747   IN CONST VOID  *Buffer
    748   )
    749 {
    750   return InternalAllocateCopyPool (EfiRuntimeServicesData, AllocationSize, Buffer);
    751 }
    752 
    753 /**
    754   Copies a buffer to an allocated buffer of type EfiRuntimeServicesData.
    755 
    756   Allocates the number bytes specified by AllocationSize of type EfiRuntimeServicesData,
    757   copies AllocationSize bytes from Buffer to the newly allocated buffer, and returns
    758   a pointer to the allocated buffer.  If AllocationSize is 0, then a valid buffer
    759   of 0 size is returned.  If there is not enough memory remaining to satisfy the
    760   request, then NULL is returned.
    761 
    762   If Buffer is NULL, then ASSERT().
    763   If AllocationSize is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT().
    764 
    765   @param  AllocationSize        The number of bytes to allocate and zero.
    766   @param  Buffer                The buffer to copy to the allocated buffer.
    767 
    768   @return A pointer to the allocated buffer or NULL if allocation fails.
    769 
    770 **/
    771 VOID *
    772 EFIAPI
    773 AllocateRuntimeCopyPool (
    774   IN UINTN       AllocationSize,
    775   IN CONST VOID  *Buffer
    776   )
    777 {
    778   return InternalAllocateCopyPool (EfiRuntimeServicesData, AllocationSize, Buffer);
    779 }
    780 
    781 /**
    782   Copies a buffer to an allocated buffer of type EfiReservedMemoryType.
    783 
    784   Allocates the number bytes specified by AllocationSize of type EfiReservedMemoryType,
    785   copies AllocationSize bytes from Buffer to the newly allocated buffer, and returns
    786   a pointer to the allocated buffer.  If AllocationSize is 0, then a valid buffer
    787   of 0 size is returned.  If there is not enough memory remaining to satisfy the
    788   request, then NULL is returned.
    789 
    790   If Buffer is NULL, then ASSERT().
    791   If AllocationSize is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT().
    792 
    793   @param  AllocationSize        The number of bytes to allocate and zero.
    794   @param  Buffer                The buffer to copy to the allocated buffer.
    795 
    796   @return A pointer to the allocated buffer or NULL if allocation fails.
    797 
    798 **/
    799 VOID *
    800 EFIAPI
    801 AllocateReservedCopyPool (
    802   IN UINTN       AllocationSize,
    803   IN CONST VOID  *Buffer
    804   )
    805 {
    806   return NULL;
    807 }
    808 
    809 /**
    810   Reallocates a buffer of a specified memory type.
    811 
    812   Allocates and zeros the number bytes specified by NewSize from memory of the type
    813   specified by PoolType.  If OldBuffer is not NULL, then the smaller of OldSize and
    814   NewSize bytes are copied from OldBuffer to the newly allocated buffer, and
    815   OldBuffer is freed.  A pointer to the newly allocated buffer is returned.
    816   If NewSize is 0, then a valid buffer of 0 size is  returned.  If there is not
    817   enough memory remaining to satisfy the request, then NULL is returned.
    818 
    819   If the allocation of the new buffer is successful and the smaller of NewSize
    820   and OldSize is greater than (MAX_ADDRESS - OldBuffer + 1), then ASSERT().
    821 
    822   @param  PoolType       The type of pool to allocate.
    823   @param  OldSize        The size, in bytes, of OldBuffer.
    824   @param  NewSize        The size, in bytes, of the buffer to reallocate.
    825   @param  OldBuffer      The buffer to copy to the allocated buffer.  This is an
    826                          optional parameter that may be NULL.
    827 
    828   @return A pointer to the allocated buffer or NULL if allocation fails.
    829 
    830 **/
    831 VOID *
    832 InternalReallocatePool (
    833   IN EFI_MEMORY_TYPE  PoolType,
    834   IN UINTN            OldSize,
    835   IN UINTN            NewSize,
    836   IN VOID             *OldBuffer  OPTIONAL
    837   )
    838 {
    839   VOID  *NewBuffer;
    840 
    841   NewBuffer = InternalAllocateZeroPool (PoolType, NewSize);
    842   if (NewBuffer != NULL && OldBuffer != NULL) {
    843     CopyMem (NewBuffer, OldBuffer, MIN (OldSize, NewSize));
    844     FreePool (OldBuffer);
    845   }
    846   return NewBuffer;
    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
    860   and OldSize 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
    865                          optional 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 ReallocatePool (
    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 EfiRuntimeServicesData.
    883 
    884   Allocates and zeros the number bytes specified by NewSize from memory of type
    885   EfiRuntimeServicesData.  If OldBuffer is not NULL, then the smaller of OldSize
    886   and 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
    892   and OldSize 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 ReallocateRuntimePool (
    905   IN UINTN  OldSize,
    906   IN UINTN  NewSize,
    907   IN VOID   *OldBuffer  OPTIONAL
    908   )
    909 {
    910   return InternalReallocatePool (EfiRuntimeServicesData, OldSize, NewSize, OldBuffer);
    911 }
    912 
    913 /**
    914   Reallocates a buffer of type EfiReservedMemoryType.
    915 
    916   Allocates and zeros the number bytes specified by NewSize from memory of type
    917   EfiReservedMemoryType.  If OldBuffer is not NULL, then the smaller of OldSize
    918   and NewSize bytes are copied from OldBuffer to the newly allocated buffer, and
    919   OldBuffer is freed.  A pointer to the newly allocated buffer is returned.
    920   If NewSize is 0, then a valid buffer of 0 size is  returned.  If there is not
    921   enough memory remaining to satisfy the request, then NULL is returned.
    922 
    923   If the allocation of the new buffer is successful and the smaller of NewSize
    924   and OldSize is greater than (MAX_ADDRESS - OldBuffer + 1), then ASSERT().
    925 
    926   @param  OldSize        The size, in bytes, of OldBuffer.
    927   @param  NewSize        The size, in bytes, of the buffer to reallocate.
    928   @param  OldBuffer      The buffer to copy to the allocated buffer.  This is an
    929                          optional parameter that may be NULL.
    930 
    931   @return A pointer to the allocated buffer or NULL if allocation fails.
    932 
    933 **/
    934 VOID *
    935 EFIAPI
    936 ReallocateReservedPool (
    937   IN UINTN  OldSize,
    938   IN UINTN  NewSize,
    939   IN VOID   *OldBuffer  OPTIONAL
    940   )
    941 {
    942   return NULL;
    943 }
    944 
    945 /**
    946   Frees a buffer that was previously allocated with one of the pool allocation
    947   functions in the Memory Allocation Library.
    948 
    949   Frees the buffer specified by Buffer.  Buffer must have been allocated on a
    950   previous call to the pool allocation services of the Memory Allocation Library.
    951   If it is not possible to free pool resources, then this function will perform
    952   no actions.
    953 
    954   If Buffer was not allocated with a pool allocation function in the Memory
    955   Allocation Library, then ASSERT().
    956 
    957   @param  Buffer                The pointer to the buffer to free.
    958 
    959 **/
    960 VOID
    961 EFIAPI
    962 FreePool (
    963   IN VOID   *Buffer
    964   )
    965 {
    966   EFI_STATUS    Status;
    967 
    968   if (BufferInSmram (Buffer)) {
    969     //
    970     // When Buffer is in SMRAM range, it should be allocated by gSmst->SmmAllocatePool() service.
    971     // So, gSmst->SmmFreePool() service is used to free it.
    972     //
    973     Status = gSmst->SmmFreePool (Buffer);
    974   } else {
    975     //
    976     // When Buffer is out of SMRAM range, it should be allocated by gBS->AllocatePool() service.
    977     // So, gBS->FreePool() service is used to free it.
    978     //
    979     Status = gBS->FreePool (Buffer);
    980   }
    981   ASSERT_EFI_ERROR (Status);
    982 }
    983