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