]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdePkg/Library/SmmMemoryAllocationLib/MemoryAllocationLib.c
MdePkg: Replace BSD License with BSD+Patent License
[mirror_edk2.git] / MdePkg / Library / SmmMemoryAllocationLib / MemoryAllocationLib.c
index 3a539e36432aa6903c2fd5a398ce22a85d9819bc..c0247a3a42374372301a6db91af58b20ee6ff5c8 100644 (file)
 /** @file\r
-  Support routines for memory allocation routines based \r
+  Support routines for memory allocation routines based\r
   on SMM Services Table services for SMM phase drivers.\r
-  \r
+\r
   The PI System Management Mode Core Interface Specification only allows the use\r
-  of EfiRuntimeServicesCode and EfiRuntimeServicesData memory types for memory \r
-  allocations through the SMM Services Table.  The functions in the Memory \r
-  Allocation Library use EfiBootServicesData as the default memory allocation\r
-  type.  For this SMM specific instance of the Memory Allocation Library, \r
-  EfiRuntimeServicesData is used as the default memory type for all allocations.\r
-  In addition, allocation for the Reserved memory types are not supported and \r
-  will always return NULL.\r
-\r
-  Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR>\r
-  This program and the accompanying materials                          \r
-  are licensed and made available under the terms and conditions of the BSD License         \r
-  which accompanies this distribution.  The full text of the license may be found at        \r
-  http://opensource.org/licenses/bsd-license.php.                                            \r
-\r
-  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     \r
-  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             \r
+  of EfiRuntimeServicesCode and EfiRuntimeServicesData memory types for memory\r
+  allocations through the SMM Services Table as the SMRAM space should be\r
+  reserved after BDS phase.  The functions in the Memory Allocation Library use\r
+  EfiBootServicesData as the default memory allocation type.  For this SMM\r
+  specific instance of the Memory Allocation Library, EfiRuntimeServicesData\r
+  is used as the default memory type for all allocations. In addition,\r
+  allocation for the Reserved memory types are not supported and will always\r
+  return NULL.\r
+\r
+  Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>\r
+  SPDX-License-Identifier: BSD-2-Clause-Patent\r
 \r
 **/\r
 \r
 #include <PiSmm.h>\r
 \r
+#include <Protocol/SmmAccess2.h>\r
 #include <Library/MemoryAllocationLib.h>\r
+#include <Library/UefiBootServicesTableLib.h>\r
 #include <Library/SmmServicesTableLib.h>\r
 #include <Library/BaseMemoryLib.h>\r
 #include <Library/DebugLib.h>\r
 \r
+EFI_SMRAM_DESCRIPTOR  *mSmramRanges;\r
+UINTN                 mSmramRangeCount;\r
+\r
+/**\r
+  The constructor function caches SMRAM ranges that are present in the system.\r
+\r
+  It will ASSERT() if SMM Access2 Protocol doesn't exist.\r
+  It will ASSERT() if SMRAM ranges can't be got.\r
+  It will ASSERT() if Resource can't be allocated for cache SMRAM range.\r
+  It will always return EFI_SUCCESS.\r
+\r
+  @param  ImageHandle   The firmware allocated handle for the EFI image.\r
+  @param  SystemTable   A pointer to the EFI System Table.\r
+\r
+  @retval EFI_SUCCESS   The constructor always returns EFI_SUCCESS.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+SmmMemoryAllocationLibConstructor (\r
+  IN EFI_HANDLE        ImageHandle,\r
+  IN EFI_SYSTEM_TABLE  *SystemTable\r
+  )\r
+{\r
+  EFI_STATUS                Status;\r
+  EFI_SMM_ACCESS2_PROTOCOL  *SmmAccess;\r
+  UINTN                     Size;\r
+\r
+  //\r
+  // Locate SMM Access2 Protocol\r
+  //\r
+  Status = gBS->LocateProtocol (\r
+                  &gEfiSmmAccess2ProtocolGuid,\r
+                  NULL,\r
+                  (VOID **)&SmmAccess\r
+                  );\r
+  ASSERT_EFI_ERROR (Status);\r
+\r
+  //\r
+  // Get SMRAM range information\r
+  //\r
+  Size = 0;\r
+  Status = SmmAccess->GetCapabilities (SmmAccess, &Size, NULL);\r
+  ASSERT (Status == EFI_BUFFER_TOO_SMALL);\r
+\r
+  mSmramRanges = (EFI_SMRAM_DESCRIPTOR *) AllocatePool (Size);\r
+  ASSERT (mSmramRanges != NULL);\r
+\r
+  Status = SmmAccess->GetCapabilities (SmmAccess, &Size, mSmramRanges);\r
+  ASSERT_EFI_ERROR (Status);\r
+\r
+  mSmramRangeCount = Size / sizeof (EFI_SMRAM_DESCRIPTOR);\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  If SMM driver exits with an error, it must call this routine\r
+  to free the allocated resource before the exiting.\r
+\r
+  @param[in]  ImageHandle   The firmware allocated handle for the EFI image.\r
+  @param[in]  SystemTable   A pointer to the EFI System Table.\r
+\r
+  @retval     EFI_SUCCESS   The deconstructor always returns EFI_SUCCESS.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+SmmMemoryAllocationLibDestructor (\r
+  IN EFI_HANDLE        ImageHandle,\r
+  IN EFI_SYSTEM_TABLE  *SystemTable\r
+  )\r
+{\r
+  FreePool (mSmramRanges);\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  Check whether the start address of buffer is within any of the SMRAM ranges.\r
+\r
+  @param[in]  Buffer   The pointer to the buffer to be checked.\r
+\r
+  @retval     TRUE     The buffer is in SMRAM ranges.\r
+  @retval     FALSE    The buffer is out of SMRAM ranges.\r
+**/\r
+BOOLEAN\r
+EFIAPI\r
+BufferInSmram (\r
+  IN VOID *Buffer\r
+  )\r
+{\r
+  UINTN  Index;\r
+\r
+  for (Index = 0; Index < mSmramRangeCount; Index ++) {\r
+    if (((EFI_PHYSICAL_ADDRESS) (UINTN) Buffer >= mSmramRanges[Index].CpuStart) &&\r
+        ((EFI_PHYSICAL_ADDRESS) (UINTN) Buffer < (mSmramRanges[Index].CpuStart + mSmramRanges[Index].PhysicalSize))) {\r
+      return TRUE;\r
+    }\r
+  }\r
+\r
+  return FALSE;\r
+}\r
+\r
 /**\r
   Allocates one or more 4KB pages of a certain memory type.\r
 \r
-  Allocates the number of 4KB pages of a certain memory type and returns a pointer to the allocated\r
-  buffer.  The buffer returned is aligned on a 4KB boundary.  If Pages is 0, then NULL is returned.\r
-  If there is not enough memory remaining to satisfy the request, then NULL is returned.\r
+  Allocates the number of 4KB pages of a certain memory type and returns a pointer\r
+  to the allocated buffer.  The buffer returned is aligned on a 4KB boundary.  If\r
+  Pages is 0, then NULL is returned.   If there is not enough memory remaining to\r
+  satisfy the request, then NULL is returned.\r
 \r
   @param  MemoryType            The type of memory to allocate.\r
   @param  Pages                 The number of 4 KB pages to allocate.\r
 **/\r
 VOID *\r
 InternalAllocatePages (\r
-  IN EFI_MEMORY_TYPE  MemoryType,  \r
+  IN EFI_MEMORY_TYPE  MemoryType,\r
   IN UINTN            Pages\r
   )\r
 {\r
   EFI_STATUS            Status;\r
-  EFI_PHYSICAL_ADDRESS  Memory; \r
+  EFI_PHYSICAL_ADDRESS  Memory;\r
 \r
   if (Pages == 0) {\r
     return NULL;\r
@@ -63,12 +164,12 @@ InternalAllocatePages (
 }\r
 \r
 /**\r
-  Allocates one or more 4KB pages of type EfiBootServicesData.\r
+  Allocates one or more 4KB pages of type EfiRuntimeServicesData.\r
 \r
-  Allocates the number of 4KB pages of type EfiBootServicesData and returns a pointer to the\r
-  allocated buffer.  The buffer returned is aligned on a 4KB boundary.  If Pages is 0, then NULL\r
-  is returned.  If there is not enough memory remaining to satisfy the request, then NULL is\r
-  returned.\r
+  Allocates the number of 4KB pages of type EfiRuntimeServicesData and returns a pointer\r
+  to the allocated buffer.  The buffer returned is aligned on a 4KB boundary.  If\r
+  Pages is 0, then NULL is returned.  If there is not enough memory remaining to\r
+  satisfy the request, then NULL is returned.\r
 \r
   @param  Pages                 The number of 4 KB pages to allocate.\r
 \r
@@ -87,10 +188,10 @@ AllocatePages (
 /**\r
   Allocates one or more 4KB pages of type EfiRuntimeServicesData.\r
 \r
-  Allocates the number of 4KB pages of type EfiRuntimeServicesData and returns a pointer to the\r
-  allocated buffer.  The buffer returned is aligned on a 4KB boundary.  If Pages is 0, then NULL\r
-  is returned.  If there is not enough memory remaining to satisfy the request, then NULL is\r
-  returned.\r
+  Allocates the number of 4KB pages of type EfiRuntimeServicesData and returns a\r
+  pointer to the allocated buffer.  The buffer returned is aligned on a 4KB boundary.\r
+  If Pages is 0, then NULL is returned.  If there is not enough memory remaining\r
+  to satisfy the request, then NULL is returned.\r
 \r
   @param  Pages                 The number of 4 KB pages to allocate.\r
 \r
@@ -109,10 +210,10 @@ AllocateRuntimePages (
 /**\r
   Allocates one or more 4KB pages of type EfiReservedMemoryType.\r
 \r
-  Allocates the number of 4KB pages of type EfiReservedMemoryType and returns a pointer to the\r
-  allocated buffer.  The buffer returned is aligned on a 4KB boundary.  If Pages is 0, then NULL\r
-  is returned.  If there is not enough memory remaining to satisfy the request, then NULL is\r
-  returned.\r
+  Allocates the number of 4KB pages of type EfiReservedMemoryType and returns a\r
+  pointer to the allocated buffer.  The buffer returned is aligned on a 4KB boundary.\r
+  If Pages is 0, then NULL is returned.  If there is not enough memory remaining\r
+  to satisfy the request, then NULL is returned.\r
 \r
   @param  Pages                 The number of 4 KB pages to allocate.\r
 \r
@@ -132,15 +233,15 @@ AllocateReservedPages (
   Frees one or more 4KB pages that were previously allocated with one of the page allocation\r
   functions in the Memory Allocation Library.\r
 \r
-  Frees the number of 4KB pages specified by Pages from the buffer specified by Buffer.  Buffer\r
-  must have been allocated on a previous call to the page allocation services of the Memory\r
-  Allocation Library.  If it is not possible to free allocated pages, then this function will\r
-  perform no actions.\r
-  \r
-  If Buffer was not allocated with a page allocation function in the Memory Allocation Library,\r
-  then ASSERT().\r
+  Frees the number of 4KB pages specified by Pages from the buffer specified by Buffer.\r
+  Buffer must have been allocated on a previous call to the page allocation services\r
+  of the Memory Allocation Library.  If it is not possible to free allocated pages,\r
+  then this function will perform no actions.\r
+\r
+  If Buffer was not allocated with a page allocation function in the Memory Allocation\r
+  Library, then ASSERT().\r
   If Pages is zero, then ASSERT().\r
\r
+\r
   @param  Buffer                The pointer to the buffer of pages to free.\r
   @param  Pages                 The number of 4 KB pages to free.\r
 \r
@@ -155,22 +256,36 @@ FreePages (
   EFI_STATUS  Status;\r
 \r
   ASSERT (Pages != 0);\r
-  Status = gSmst->SmmFreePages ((EFI_PHYSICAL_ADDRESS) (UINTN) Buffer, Pages);\r
+  if (BufferInSmram (Buffer)) {\r
+    //\r
+    // When Buffer is in SMRAM range, it should be allocated by gSmst->SmmAllocatePages() service.\r
+    // So, gSmst->SmmFreePages() service is used to free it.\r
+    //\r
+    Status = gSmst->SmmFreePages ((EFI_PHYSICAL_ADDRESS) (UINTN) Buffer, Pages);\r
+  } else {\r
+    //\r
+    // When Buffer is out of SMRAM range, it should be allocated by gBS->AllocatePages() service.\r
+    // So, gBS->FreePages() service is used to free it.\r
+    //\r
+    Status = gBS->FreePages ((EFI_PHYSICAL_ADDRESS) (UINTN) Buffer, Pages);\r
+  }\r
   ASSERT_EFI_ERROR (Status);\r
 }\r
 \r
 /**\r
   Allocates one or more 4KB pages of a certain memory type at a specified alignment.\r
 \r
-  Allocates the number of 4KB pages specified by Pages of a certain memory type with an alignment\r
-  specified by Alignment.  The allocated buffer is returned.  If Pages is 0, then NULL is returned.\r
-  If there is not enough memory at the specified alignment remaining to satisfy the request, then\r
-  NULL is returned.\r
+  Allocates the number of 4KB pages specified by Pages of a certain memory type\r
+  with an alignment specified by Alignment.  The allocated buffer is returned.\r
+  If Pages is 0, then NULL is returned. If there is not enough memory at the\r
+  specified alignment remaining to satisfy the request, then NULL is returned.\r
   If Alignment is not a power of two and Alignment is not zero, then ASSERT().\r
+  If Pages plus EFI_SIZE_TO_PAGES (Alignment) overflows, then ASSERT().\r
 \r
   @param  MemoryType            The type of memory to allocate.\r
   @param  Pages                 The number of 4 KB pages to allocate.\r
-  @param  Alignment             The requested alignment of the allocation.  Must be a power of two.\r
+  @param  Alignment             The requested alignment of the allocation.\r
+                                Must be a power of two.\r
                                 If Alignment is zero, then byte alignment is used.\r
 \r
   @return A pointer to the allocated buffer or NULL if allocation fails.\r
@@ -178,7 +293,7 @@ FreePages (
 **/\r
 VOID *\r
 InternalAllocateAlignedPages (\r
-  IN EFI_MEMORY_TYPE  MemoryType,  \r
+  IN EFI_MEMORY_TYPE  MemoryType,\r
   IN UINTN            Pages,\r
   IN UINTN            Alignment\r
   )\r
@@ -194,13 +309,13 @@ InternalAllocateAlignedPages (
   // Alignment must be a power of two or zero.\r
   //\r
   ASSERT ((Alignment & (Alignment - 1)) == 0);\r
\r
+\r
   if (Pages == 0) {\r
     return NULL;\r
   }\r
   if (Alignment > EFI_PAGE_SIZE) {\r
     //\r
-    // Caculate the total number of pages since alignment is larger than page size.\r
+    // Calculate the total number of pages since alignment is larger than page size.\r
     //\r
     AlignmentMask  = Alignment - 1;\r
     RealPages      = Pages + EFI_SIZE_TO_PAGES (Alignment);\r
@@ -208,7 +323,7 @@ InternalAllocateAlignedPages (
     // Make sure that Pages plus EFI_SIZE_TO_PAGES (Alignment) does not overflow.\r
     //\r
     ASSERT (RealPages > Pages);\r
\r
+\r
     Status         = gSmst->SmmAllocatePages (AllocateAnyPages, MemoryType, RealPages, &Memory);\r
     if (EFI_ERROR (Status)) {\r
       return NULL;\r
@@ -222,7 +337,7 @@ InternalAllocateAlignedPages (
       Status = gSmst->SmmFreePages (Memory, UnalignedPages);\r
       ASSERT_EFI_ERROR (Status);\r
     }\r
-    Memory         = (EFI_PHYSICAL_ADDRESS) (AlignedMemory + EFI_PAGES_TO_SIZE (Pages));\r
+    Memory         = AlignedMemory + EFI_PAGES_TO_SIZE (Pages);\r
     UnalignedPages = RealPages - Pages - UnalignedPages;\r
     if (UnalignedPages > 0) {\r
       //\r
@@ -245,17 +360,19 @@ InternalAllocateAlignedPages (
 }\r
 \r
 /**\r
-  Allocates one or more 4KB pages of type EfiBootServicesData at a specified alignment.\r
+  Allocates one or more 4KB pages of type EfiRuntimeServicesData at a specified alignment.\r
+\r
+  Allocates the number of 4KB pages specified by Pages of type EfiRuntimeServicesData\r
+  with an alignment specified by Alignment.  The allocated buffer is returned.\r
+  If Pages is 0, then NULL is returned.  If there is not enough memory at the\r
+  specified alignment remaining to satisfy the request, then NULL is returned.\r
 \r
-  Allocates the number of 4KB pages specified by Pages of type EfiBootServicesData with an\r
-  alignment specified by Alignment.  The allocated buffer is returned.  If Pages is 0, then NULL is\r
-  returned.  If there is not enough memory at the specified alignment remaining to satisfy the\r
-  request, then NULL is returned.\r
-  \r
   If Alignment is not a power of two and Alignment is not zero, then ASSERT().\r
+  If Pages plus EFI_SIZE_TO_PAGES (Alignment) overflows, then ASSERT().\r
 \r
   @param  Pages                 The number of 4 KB pages to allocate.\r
-  @param  Alignment             The requested alignment of the allocation.  Must be a power of two.\r
+  @param  Alignment             The requested alignment of the allocation.\r
+                                Must be a power of two.\r
                                 If Alignment is zero, then byte alignment is used.\r
 \r
   @return A pointer to the allocated buffer or NULL if allocation fails.\r
@@ -274,15 +391,17 @@ AllocateAlignedPages (
 /**\r
   Allocates one or more 4KB pages of type EfiRuntimeServicesData at a specified alignment.\r
 \r
-  Allocates the number of 4KB pages specified by Pages of type EfiRuntimeServicesData with an\r
-  alignment specified by Alignment.  The allocated buffer is returned.  If Pages is 0, then NULL is\r
-  returned.  If there is not enough memory at the specified alignment remaining to satisfy the\r
-  request, then NULL is returned.\r
-  \r
+  Allocates the number of 4KB pages specified by Pages of type EfiRuntimeServicesData\r
+  with an alignment specified by Alignment.  The allocated buffer is returned.\r
+  If Pages is 0, then NULL is returned.  If there is not enough memory at the\r
+  specified alignment remaining to satisfy the request, then NULL is returned.\r
+\r
   If Alignment is not a power of two and Alignment is not zero, then ASSERT().\r
+  If Pages plus EFI_SIZE_TO_PAGES (Alignment) overflows, then ASSERT().\r
 \r
   @param  Pages                 The number of 4 KB pages to allocate.\r
-  @param  Alignment             The requested alignment of the allocation.  Must be a power of two.\r
+  @param  Alignment             The requested alignment of the allocation.\r
+                                Must be a power of two.\r
                                 If Alignment is zero, then byte alignment is used.\r
 \r
   @return A pointer to the allocated buffer or NULL if allocation fails.\r
@@ -301,15 +420,17 @@ AllocateAlignedRuntimePages (
 /**\r
   Allocates one or more 4KB pages of type EfiReservedMemoryType at a specified alignment.\r
 \r
-  Allocates the number of 4KB pages specified by Pages of type EfiReservedMemoryType with an\r
-  alignment specified by Alignment.  The allocated buffer is returned.  If Pages is 0, then NULL is\r
-  returned.  If there is not enough memory at the specified alignment remaining to satisfy the\r
-  request, then NULL is returned.\r
-  \r
+  Allocates the number of 4KB pages specified by Pages of type EfiReservedMemoryType\r
+  with an alignment specified by Alignment.  The allocated buffer is returned.\r
+  If Pages is 0, then NULL is returned.  If there is not enough memory at the\r
+  specified alignment remaining to satisfy the request, then NULL is returned.\r
+\r
   If Alignment is not a power of two and Alignment is not zero, then ASSERT().\r
+  If Pages plus EFI_SIZE_TO_PAGES (Alignment) overflows, then ASSERT().\r
 \r
   @param  Pages                 The number of 4 KB pages to allocate.\r
-  @param  Alignment             The requested alignment of the allocation.  Must be a power of two.\r
+  @param  Alignment             The requested alignment of the allocation.\r
+                                Must be a power of two.\r
                                 If Alignment is zero, then byte alignment is used.\r
 \r
   @return A pointer to the allocated buffer or NULL if allocation fails.\r
@@ -329,15 +450,15 @@ AllocateAlignedReservedPages (
   Frees one or more 4KB pages that were previously allocated with one of the aligned page\r
   allocation functions in the Memory Allocation Library.\r
 \r
-  Frees the number of 4KB pages specified by Pages from the buffer specified by Buffer.  Buffer\r
-  must have been allocated on a previous call to the aligned page allocation services of the Memory\r
-  Allocation Library.  If it is not possible to free allocated pages, then this function will \r
-  perform no actions.\r
-  \r
-  If Buffer was not allocated with an aligned page allocation function in the Memory Allocation\r
-  Library, then ASSERT().\r
+  Frees the number of 4KB pages specified by Pages from the buffer specified by\r
+  Buffer.  Buffer must have been allocated on a previous call to the aligned page\r
+  allocation services of the Memory Allocation Library.  If it is not possible to\r
+  free allocated pages, then this function will perform no actions.\r
+\r
+  If Buffer was not allocated with an aligned page allocation function in the\r
+  Memory Allocation Library, then ASSERT().\r
   If Pages is zero, then ASSERT().\r
-  \r
+\r
   @param  Buffer                The pointer to the buffer of pages to free.\r
   @param  Pages                 The number of 4 KB pages to free.\r
 \r
@@ -352,16 +473,29 @@ FreeAlignedPages (
   EFI_STATUS  Status;\r
 \r
   ASSERT (Pages != 0);\r
-  Status = gSmst->SmmFreePages ((EFI_PHYSICAL_ADDRESS) (UINTN) Buffer, Pages);\r
+  if (BufferInSmram (Buffer)) {\r
+    //\r
+    // When Buffer is in SMRAM range, it should be allocated by gSmst->SmmAllocatePages() service.\r
+    // So, gSmst->SmmFreePages() service is used to free it.\r
+    //\r
+    Status = gSmst->SmmFreePages ((EFI_PHYSICAL_ADDRESS) (UINTN) Buffer, Pages);\r
+  } else {\r
+    //\r
+    // When Buffer is out of SMRAM range, it should be allocated by gBS->AllocatePages() service.\r
+    // So, gBS->FreePages() service is used to free it.\r
+    //\r
+    Status = gBS->FreePages ((EFI_PHYSICAL_ADDRESS) (UINTN) Buffer, Pages);\r
+  }\r
   ASSERT_EFI_ERROR (Status);\r
 }\r
 \r
 /**\r
   Allocates a buffer of a certain pool type.\r
 \r
-  Allocates the number bytes specified by AllocationSize of a certain pool type and returns a\r
-  pointer to the allocated buffer.  If AllocationSize is 0, then a valid buffer of 0 size is\r
-  returned.  If there is not enough memory remaining to satisfy the request, then NULL is returned.\r
+  Allocates the number bytes specified by AllocationSize of a certain pool type\r
+  and returns a pointer to the allocated buffer.  If AllocationSize is 0, then a\r
+  valid buffer of 0 size is returned.  If there is not enough memory remaining to\r
+  satisfy the request, then NULL is returned.\r
 \r
   @param  MemoryType            The type of memory to allocate.\r
   @param  AllocationSize        The number of bytes to allocate.\r
@@ -371,7 +505,7 @@ FreeAlignedPages (
 **/\r
 VOID *\r
 InternalAllocatePool (\r
-  IN EFI_MEMORY_TYPE  MemoryType,  \r
+  IN EFI_MEMORY_TYPE  MemoryType,\r
   IN UINTN            AllocationSize\r
   )\r
 {\r
@@ -386,11 +520,12 @@ InternalAllocatePool (
 }\r
 \r
 /**\r
-  Allocates a buffer of type EfiBootServicesData.\r
+  Allocates a buffer of type EfiRuntimeServicesData.\r
 \r
-  Allocates the number bytes specified by AllocationSize of type EfiBootServicesData and returns a\r
-  pointer to the allocated buffer.  If AllocationSize is 0, then a valid buffer of 0 size is\r
-  returned.  If there is not enough memory remaining to satisfy the request, then NULL is returned.\r
+  Allocates the number bytes specified by AllocationSize of type EfiRuntimeServicesData\r
+  and returns a pointer to the allocated buffer.  If AllocationSize is 0, then a\r
+  valid buffer of 0 size is returned.  If there is not enough memory remaining to\r
+  satisfy the request, then NULL is returned.\r
 \r
   @param  AllocationSize        The number of bytes to allocate.\r
 \r
@@ -409,9 +544,10 @@ AllocatePool (
 /**\r
   Allocates a buffer of type EfiRuntimeServicesData.\r
 \r
-  Allocates the number bytes specified by AllocationSize of type EfiRuntimeServicesData and returns\r
-  a pointer to the allocated buffer.  If AllocationSize is 0, then a valid buffer of 0 size is\r
-  returned.  If there is not enough memory remaining to satisfy the request, then NULL is returned.\r
+  Allocates the number bytes specified by AllocationSize of type EfiRuntimeServicesData\r
+  and returns a pointer to the allocated buffer.  If AllocationSize is 0, then a\r
+  valid buffer of 0 size is returned.  If there is not enough memory remaining to\r
+  satisfy the request, then NULL is returned.\r
 \r
   @param  AllocationSize        The number of bytes to allocate.\r
 \r
@@ -430,9 +566,10 @@ AllocateRuntimePool (
 /**\r
   Allocates a buffer of type EfiReservedMemoryType.\r
 \r
-  Allocates the number bytes specified by AllocationSize of type EfiReservedMemoryType and returns\r
-  a pointer to the allocated buffer.  If AllocationSize is 0, then a valid buffer of 0 size is\r
-  returned.  If there is not enough memory remaining to satisfy the request, then NULL is returned.\r
+  Allocates the number bytes specified by AllocationSize of type EfiReservedMemoryType\r
+  and returns a pointer to the allocated buffer.  If AllocationSize is 0, then a\r
+  valid buffer of 0 size is returned.  If there is not enough memory remaining to\r
+  satisfy the request, then NULL is returned.\r
 \r
   @param  AllocationSize        The number of bytes to allocate.\r
 \r
@@ -451,10 +588,10 @@ AllocateReservedPool (
 /**\r
   Allocates and zeros a buffer of a certain pool type.\r
 \r
-  Allocates the number bytes specified by AllocationSize of a certain pool type, clears the buffer\r
-  with zeros, and returns a pointer to the allocated buffer.  If AllocationSize is 0, then a valid\r
-  buffer of 0 size is returned.  If there is not enough memory remaining to satisfy the request,\r
-  then NULL is returned.\r
+  Allocates the number bytes specified by AllocationSize of a certain pool type,\r
+  clears the buffer with zeros, and returns a pointer to the allocated buffer.\r
+  If AllocationSize is 0, then a valid buffer of 0 size is returned.  If there is\r
+  not enough memory remaining to satisfy the request, then NULL is returned.\r
 \r
   @param  PoolType              The type of memory to allocate.\r
   @param  AllocationSize        The number of bytes to allocate and zero.\r
@@ -464,9 +601,9 @@ AllocateReservedPool (
 **/\r
 VOID *\r
 InternalAllocateZeroPool (\r
-  IN EFI_MEMORY_TYPE  PoolType,  \r
+  IN EFI_MEMORY_TYPE  PoolType,\r
   IN UINTN            AllocationSize\r
-  ) \r
+  )\r
 {\r
   VOID  *Memory;\r
 \r
@@ -478,12 +615,12 @@ InternalAllocateZeroPool (
 }\r
 \r
 /**\r
-  Allocates and zeros a buffer of type EfiBootServicesData.\r
+  Allocates and zeros a buffer of type EfiRuntimeServicesData.\r
 \r
-  Allocates the number bytes specified by AllocationSize of type EfiBootServicesData, clears the\r
-  buffer with zeros, and returns a pointer to the allocated buffer.  If AllocationSize is 0, then a\r
-  valid buffer of 0 size is returned.  If there is not enough memory remaining to satisfy the\r
-  request, then NULL is returned.\r
+  Allocates the number bytes specified by AllocationSize of type EfiRuntimeServicesData,\r
+  clears the buffer with zeros, and returns a pointer to the allocated buffer.\r
+  If AllocationSize is 0, then a valid buffer of 0 size is returned.  If there is\r
+  not enough memory remaining to satisfy the request, then NULL is returned.\r
 \r
   @param  AllocationSize        The number of bytes to allocate and zero.\r
 \r
@@ -502,10 +639,10 @@ AllocateZeroPool (
 /**\r
   Allocates and zeros a buffer of type EfiRuntimeServicesData.\r
 \r
-  Allocates the number bytes specified by AllocationSize of type EfiRuntimeServicesData, clears the\r
-  buffer with zeros, and returns a pointer to the allocated buffer.  If AllocationSize is 0, then a\r
-  valid buffer of 0 size is returned.  If there is not enough memory remaining to satisfy the\r
-  request, then NULL is returned.\r
+  Allocates the number bytes specified by AllocationSize of type EfiRuntimeServicesData,\r
+  clears the buffer with zeros, and returns a pointer to the allocated buffer.\r
+  If AllocationSize is 0, then a valid buffer of 0 size is returned.  If there is\r
+  not enough memory remaining to satisfy the request, then NULL is returned.\r
 \r
   @param  AllocationSize        The number of bytes to allocate and zero.\r
 \r
@@ -524,10 +661,10 @@ AllocateRuntimeZeroPool (
 /**\r
   Allocates and zeros a buffer of type EfiReservedMemoryType.\r
 \r
-  Allocates the number bytes specified by AllocationSize of type EfiReservedMemoryType, clears the\r
-  buffer with zeros, and returns a pointer to the allocated buffer.  If AllocationSize is 0, then a\r
-  valid buffer of 0 size is returned.  If there is not enough memory remaining to satisfy the\r
-  request, then NULL is returned.\r
+  Allocates the number bytes specified by AllocationSize of type EfiReservedMemoryType,\r
+  clears the   buffer with zeros, and returns a pointer to the allocated buffer.\r
+  If AllocationSize is 0, then a valid buffer of 0 size is returned.  If there is\r
+  not enough memory remaining to satisfy the request, then NULL is returned.\r
 \r
   @param  AllocationSize        The number of bytes to allocate and zero.\r
 \r
@@ -546,12 +683,12 @@ AllocateReservedZeroPool (
 /**\r
   Copies a buffer to an allocated buffer of a certain pool type.\r
 \r
-  Allocates the number bytes specified by AllocationSize of a certain pool type, copies\r
-  AllocationSize bytes from Buffer to the newly allocated buffer, and returns a pointer to the\r
-  allocated buffer.  If AllocationSize is 0, then a valid buffer of 0 size is returned.  If there\r
-  is not enough memory remaining to satisfy the request, then NULL is returned.\r
-  If Buffer is NULL, then ASSERT().\r
-  If AllocationSize is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). \r
+  Allocates the number bytes specified by AllocationSize of a certain pool type,\r
+  copies AllocationSize bytes from Buffer to the newly allocated buffer, and returns\r
+  a pointer to the allocated buffer.  If AllocationSize is 0, then a valid buffer\r
+  of 0 size is returned.  If there is not enough memory remaining to satisfy the\r
+  request, then NULL is returned. If Buffer is NULL, then ASSERT().\r
+  If AllocationSize is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT().\r
 \r
   @param  PoolType              The type of pool to allocate.\r
   @param  AllocationSize        The number of bytes to allocate and zero.\r
@@ -562,10 +699,10 @@ AllocateReservedZeroPool (
 **/\r
 VOID *\r
 InternalAllocateCopyPool (\r
-  IN EFI_MEMORY_TYPE  PoolType,  \r
+  IN EFI_MEMORY_TYPE  PoolType,\r
   IN UINTN            AllocationSize,\r
   IN CONST VOID       *Buffer\r
-  ) \r
+  )\r
 {\r
   VOID  *Memory;\r
 \r
@@ -577,18 +714,19 @@ InternalAllocateCopyPool (
      Memory = CopyMem (Memory, Buffer, AllocationSize);\r
   }\r
   return Memory;\r
-} \r
+}\r
 \r
 /**\r
-  Copies a buffer to an allocated buffer of type EfiBootServicesData.\r
+  Copies a buffer to an allocated buffer of type EfiRuntimeServicesData.\r
+\r
+  Allocates the number bytes specified by AllocationSize of type EfiRuntimeServicesData,\r
+  copies AllocationSize bytes from Buffer to the newly allocated buffer, and returns\r
+  a pointer to the allocated buffer.  If AllocationSize is 0, then a valid buffer\r
+  of 0 size is returned.  If there is not enough memory remaining to satisfy the\r
+  request, then NULL is returned.\r
 \r
-  Allocates the number bytes specified by AllocationSize of type EfiBootServicesData, copies\r
-  AllocationSize bytes from Buffer to the newly allocated buffer, and returns a pointer to the\r
-  allocated buffer.  If AllocationSize is 0, then a valid buffer of 0 size is returned.  If there\r
-  is not enough memory remaining to satisfy the request, then NULL is returned.\r
-  \r
   If Buffer is NULL, then ASSERT().\r
-  If AllocationSize is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). \r
+  If AllocationSize is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT().\r
 \r
   @param  AllocationSize        The number of bytes to allocate and zero.\r
   @param  Buffer                The buffer to copy to the allocated buffer.\r
@@ -609,13 +747,14 @@ AllocateCopyPool (
 /**\r
   Copies a buffer to an allocated buffer of type EfiRuntimeServicesData.\r
 \r
-  Allocates the number bytes specified by AllocationSize of type EfiRuntimeServicesData, copies\r
-  AllocationSize bytes from Buffer to the newly allocated buffer, and returns a pointer to the\r
-  allocated buffer.  If AllocationSize is 0, then a valid buffer of 0 size is returned.  If there\r
-  is not enough memory remaining to satisfy the request, then NULL is returned.\r
-  \r
+  Allocates the number bytes specified by AllocationSize of type EfiRuntimeServicesData,\r
+  copies AllocationSize bytes from Buffer to the newly allocated buffer, and returns\r
+  a pointer to the allocated buffer.  If AllocationSize is 0, then a valid buffer\r
+  of 0 size is returned.  If there is not enough memory remaining to satisfy the\r
+  request, then NULL is returned.\r
+\r
   If Buffer is NULL, then ASSERT().\r
-  If AllocationSize is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). \r
+  If AllocationSize is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT().\r
 \r
   @param  AllocationSize        The number of bytes to allocate and zero.\r
   @param  Buffer                The buffer to copy to the allocated buffer.\r
@@ -636,13 +775,14 @@ AllocateRuntimeCopyPool (
 /**\r
   Copies a buffer to an allocated buffer of type EfiReservedMemoryType.\r
 \r
-  Allocates the number bytes specified by AllocationSize of type EfiReservedMemoryType, copies\r
-  AllocationSize bytes from Buffer to the newly allocated buffer, and returns a pointer to the\r
-  allocated buffer.  If AllocationSize is 0, then a valid buffer of 0 size is returned.  If there\r
-  is not enough memory remaining to satisfy the request, then NULL is returned.\r
-  \r
+  Allocates the number bytes specified by AllocationSize of type EfiReservedMemoryType,\r
+  copies AllocationSize bytes from Buffer to the newly allocated buffer, and returns\r
+  a pointer to the allocated buffer.  If AllocationSize is 0, then a valid buffer\r
+  of 0 size is returned.  If there is not enough memory remaining to satisfy the\r
+  request, then NULL is returned.\r
+\r
   If Buffer is NULL, then ASSERT().\r
-  If AllocationSize is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). \r
+  If AllocationSize is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT().\r
 \r
   @param  AllocationSize        The number of bytes to allocate and zero.\r
   @param  Buffer                The buffer to copy to the allocated buffer.\r
@@ -664,27 +804,27 @@ AllocateReservedCopyPool (
   Reallocates a buffer of a specified memory type.\r
 \r
   Allocates and zeros the number bytes specified by NewSize from memory of the type\r
-  specified by PoolType.  If OldBuffer is not NULL, then the smaller of OldSize and \r
-  NewSize bytes are copied from OldBuffer to the newly allocated buffer, and \r
-  OldBuffer is freed.  A pointer to the newly allocated buffer is returned.  \r
-  If NewSize is 0, then a valid buffer of 0 size is  returned.  If there is not \r
+  specified by PoolType.  If OldBuffer is not NULL, then the smaller of OldSize and\r
+  NewSize bytes are copied from OldBuffer to the newly allocated buffer, and\r
+  OldBuffer is freed.  A pointer to the newly allocated buffer is returned.\r
+  If NewSize is 0, then a valid buffer of 0 size is  returned.  If there is not\r
   enough memory remaining to satisfy the request, then NULL is returned.\r
-  \r
-  If the allocation of the new buffer is successful and the smaller of NewSize and OldSize\r
-  is greater than (MAX_ADDRESS - OldBuffer + 1), then ASSERT().\r
+\r
+  If the allocation of the new buffer is successful and the smaller of NewSize\r
+  and OldSize is greater than (MAX_ADDRESS - OldBuffer + 1), then ASSERT().\r
 \r
   @param  PoolType       The type of pool to allocate.\r
   @param  OldSize        The size, in bytes, of OldBuffer.\r
   @param  NewSize        The size, in bytes, of the buffer to reallocate.\r
-  @param  OldBuffer      The buffer to copy to the allocated buffer.  This is an optional \r
-                         parameter that may be NULL.\r
+  @param  OldBuffer      The buffer to copy to the allocated buffer.  This is an\r
+                         optional parameter that may be NULL.\r
 \r
   @return A pointer to the allocated buffer or NULL if allocation fails.\r
 \r
 **/\r
 VOID *\r
 InternalReallocatePool (\r
-  IN EFI_MEMORY_TYPE  PoolType,  \r
+  IN EFI_MEMORY_TYPE  PoolType,\r
   IN UINTN            OldSize,\r
   IN UINTN            NewSize,\r
   IN VOID             *OldBuffer  OPTIONAL\r
@@ -701,22 +841,22 @@ InternalReallocatePool (
 }\r
 \r
 /**\r
-  Reallocates a buffer of type EfiBootServicesData.\r
+  Reallocates a buffer of type EfiRuntimeServicesData.\r
 \r
   Allocates and zeros the number bytes specified by NewSize from memory of type\r
-  EfiBootServicesData.  If OldBuffer is not NULL, then the smaller of OldSize and \r
-  NewSize bytes are copied from OldBuffer to the newly allocated buffer, and \r
-  OldBuffer is freed.  A pointer to the newly allocated buffer is returned.  \r
-  If NewSize is 0, then a valid buffer of 0 size is  returned.  If there is not \r
+  EfiRuntimeServicesData.  If OldBuffer is not NULL, then the smaller of OldSize and\r
+  NewSize bytes are copied from OldBuffer to the newly allocated buffer, and\r
+  OldBuffer is freed.  A pointer to the newly allocated buffer is returned.\r
+  If NewSize is 0, then a valid buffer of 0 size is  returned.  If there is not\r
   enough memory remaining to satisfy the request, then NULL is returned.\r
-  \r
-  If the allocation of the new buffer is successful and the smaller of NewSize and OldSize\r
-  is greater than (MAX_ADDRESS - OldBuffer + 1), then ASSERT().\r
+\r
+  If the allocation of the new buffer is successful and the smaller of NewSize\r
+  and OldSize is greater than (MAX_ADDRESS - OldBuffer + 1), then ASSERT().\r
 \r
   @param  OldSize        The size, in bytes, of OldBuffer.\r
   @param  NewSize        The size, in bytes, of the buffer to reallocate.\r
-  @param  OldBuffer      The buffer to copy to the allocated buffer.  This is an optional \r
-                         parameter that may be NULL.\r
+  @param  OldBuffer      The buffer to copy to the allocated buffer.  This is an\r
+                         optional parameter that may be NULL.\r
 \r
   @return A pointer to the allocated buffer or NULL if allocation fails.\r
 \r
@@ -736,19 +876,19 @@ ReallocatePool (
   Reallocates a buffer of type EfiRuntimeServicesData.\r
 \r
   Allocates and zeros the number bytes specified by NewSize from memory of type\r
-  EfiRuntimeServicesData.  If OldBuffer is not NULL, then the smaller of OldSize and \r
-  NewSize bytes are copied from OldBuffer to the newly allocated buffer, and \r
-  OldBuffer is freed.  A pointer to the newly allocated buffer is returned.  \r
-  If NewSize is 0, then a valid buffer of 0 size is  returned.  If there is not \r
+  EfiRuntimeServicesData.  If OldBuffer is not NULL, then the smaller of OldSize\r
+  and NewSize bytes are copied from OldBuffer to the newly allocated buffer, and\r
+  OldBuffer is freed.  A pointer to the newly allocated buffer is returned.\r
+  If NewSize is 0, then a valid buffer of 0 size is  returned.  If there is not\r
   enough memory remaining to satisfy the request, then NULL is returned.\r
 \r
-  If the allocation of the new buffer is successful and the smaller of NewSize and OldSize\r
-  is greater than (MAX_ADDRESS - OldBuffer + 1), then ASSERT().\r
+  If the allocation of the new buffer is successful and the smaller of NewSize\r
+  and OldSize is greater than (MAX_ADDRESS - OldBuffer + 1), then ASSERT().\r
 \r
   @param  OldSize        The size, in bytes, of OldBuffer.\r
   @param  NewSize        The size, in bytes, of the buffer to reallocate.\r
-  @param  OldBuffer      The buffer to copy to the allocated buffer.  This is an optional \r
-                         parameter that may be NULL.\r
+  @param  OldBuffer      The buffer to copy to the allocated buffer.  This is an\r
+                         optional parameter that may be NULL.\r
 \r
   @return A pointer to the allocated buffer or NULL if allocation fails.\r
 \r
@@ -768,19 +908,19 @@ ReallocateRuntimePool (
   Reallocates a buffer of type EfiReservedMemoryType.\r
 \r
   Allocates and zeros the number bytes specified by NewSize from memory of type\r
-  EfiReservedMemoryType.  If OldBuffer is not NULL, then the smaller of OldSize and \r
-  NewSize bytes are copied from OldBuffer to the newly allocated buffer, and \r
-  OldBuffer is freed.  A pointer to the newly allocated buffer is returned.  \r
-  If NewSize is 0, then a valid buffer of 0 size is  returned.  If there is not \r
+  EfiReservedMemoryType.  If OldBuffer is not NULL, then the smaller of OldSize\r
+  and NewSize bytes are copied from OldBuffer to the newly allocated buffer, and\r
+  OldBuffer is freed.  A pointer to the newly allocated buffer is returned.\r
+  If NewSize is 0, then a valid buffer of 0 size is  returned.  If there is not\r
   enough memory remaining to satisfy the request, then NULL is returned.\r
 \r
-  If the allocation of the new buffer is successful and the smaller of NewSize and OldSize\r
-  is greater than (MAX_ADDRESS - OldBuffer + 1), then ASSERT().\r
+  If the allocation of the new buffer is successful and the smaller of NewSize\r
+  and OldSize is greater than (MAX_ADDRESS - OldBuffer + 1), then ASSERT().\r
 \r
   @param  OldSize        The size, in bytes, of OldBuffer.\r
   @param  NewSize        The size, in bytes, of the buffer to reallocate.\r
-  @param  OldBuffer      The buffer to copy to the allocated buffer.  This is an optional \r
-                         parameter that may be NULL.\r
+  @param  OldBuffer      The buffer to copy to the allocated buffer.  This is an\r
+                         optional parameter that may be NULL.\r
 \r
   @return A pointer to the allocated buffer or NULL if allocation fails.\r
 \r
@@ -797,15 +937,16 @@ ReallocateReservedPool (
 }\r
 \r
 /**\r
-  Frees a buffer that was previously allocated with one of the pool allocation functions in the\r
-  Memory Allocation Library.\r
+  Frees a buffer that was previously allocated with one of the pool allocation\r
+  functions in the Memory Allocation Library.\r
+\r
+  Frees the buffer specified by Buffer.  Buffer must have been allocated on a\r
+  previous call to the pool allocation services of the Memory Allocation Library.\r
+  If it is not possible to free pool resources, then this function will perform\r
+  no actions.\r
 \r
-  Frees the buffer specified by Buffer.  Buffer must have been allocated on a previous call to the\r
-  pool allocation services of the Memory Allocation Library.  If it is not possible to free pool\r
-  resources, then this function will perform no actions.\r
-  \r
-  If Buffer was not allocated with a pool allocation function in the Memory Allocation Library,\r
-  then ASSERT().\r
+  If Buffer was not allocated with a pool allocation function in the Memory\r
+  Allocation Library, then ASSERT().\r
 \r
   @param  Buffer                The pointer to the buffer to free.\r
 \r
@@ -818,6 +959,18 @@ FreePool (
 {\r
   EFI_STATUS    Status;\r
 \r
-  Status = gSmst->SmmFreePool (Buffer);\r
+  if (BufferInSmram (Buffer)) {\r
+    //\r
+    // When Buffer is in SMRAM range, it should be allocated by gSmst->SmmAllocatePool() service.\r
+    // So, gSmst->SmmFreePool() service is used to free it.\r
+    //\r
+    Status = gSmst->SmmFreePool (Buffer);\r
+  } else {\r
+    //\r
+    // When Buffer is out of SMRAM range, it should be allocated by gBS->AllocatePool() service.\r
+    // So, gBS->FreePool() service is used to free it.\r
+    //\r
+    Status = gBS->FreePool (Buffer);\r
+  }\r
   ASSERT_EFI_ERROR (Status);\r
 }\r