Home | History | Annotate | Download | only in PiSmmCoreMemoryAllocationLib
      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