]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdeModulePkg/Core/Dxe/Mem/Pool.c
MdeModulePkg DxeCore/PiSmmCore: Add UEFI memory and SMRAM profile support.
[mirror_edk2.git] / MdeModulePkg / Core / Dxe / Mem / Pool.c
index 1adaa1f26970536ae97381617165b5b852112283..1891bb73876aa94029e8455c1c1c7c57b89d3675 100644 (file)
@@ -1,21 +1,21 @@
-/** @file \r
-\r
+/** @file\r
   UEFI Memory pool management functions.\r
 \r
-Copyright (c) 2006 - 2008, Intel Corporation                                                         \r
-All rights reserved. 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
+Copyright (c) 2006 - 2014, 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
 \r
 **/\r
 \r
-#include <DxeMain.h>\r
+#include "DxeMain.h"\r
+#include "Imem.h"\r
 \r
-#define POOL_FREE_SIGNATURE   EFI_SIGNATURE_32('p','f','r','0')\r
+#define POOL_FREE_SIGNATURE   SIGNATURE_32('p','f','r','0')\r
 typedef struct {\r
   UINT32          Signature;\r
   UINT32          Index;\r
@@ -23,21 +23,22 @@ typedef struct {
 } POOL_FREE;\r
 \r
 \r
-#define POOL_HEAD_SIGNATURE   EFI_SIGNATURE_32('p','h','d','0')\r
+#define POOL_HEAD_SIGNATURE   SIGNATURE_32('p','h','d','0')\r
 typedef struct {\r
   UINT32          Signature;\r
-  UINT32          Size;\r
+  UINT32          Reserved;\r
   EFI_MEMORY_TYPE Type;\r
-  UINTN           Reserved;\r
+  UINTN           Size;\r
   CHAR8           Data[1];\r
 } POOL_HEAD;\r
 \r
-#define SIZE_OF_POOL_HEAD EFI_FIELD_OFFSET(POOL_HEAD,Data)\r
+#define SIZE_OF_POOL_HEAD OFFSET_OF(POOL_HEAD,Data)\r
 \r
-#define POOL_TAIL_SIGNATURE   EFI_SIGNATURE_32('p','t','a','l')\r
+#define POOL_TAIL_SIGNATURE   SIGNATURE_32('p','t','a','l')\r
 typedef struct {\r
   UINT32      Signature;\r
-  UINT32      Size;\r
+  UINT32      Reserved;\r
+  UINTN       Size;\r
 } POOL_TAIL;\r
 \r
 \r
@@ -60,22 +61,24 @@ typedef struct {
 // Globals\r
 //\r
 \r
-#define POOL_SIGNATURE  EFI_SIGNATURE_32('p','l','s','t')\r
+#define POOL_SIGNATURE  SIGNATURE_32('p','l','s','t')\r
 typedef struct {\r
     INTN             Signature;\r
     UINTN            Used;\r
     EFI_MEMORY_TYPE  MemoryType;\r
     LIST_ENTRY       FreeList[MAX_POOL_LIST];\r
     LIST_ENTRY       Link;\r
-} POOL; \r
-\r
-\r
-POOL            PoolHead[EfiMaxMemoryType];\r
-LIST_ENTRY      PoolHeadList;\r
+} POOL;\r
 \r
 //\r
+// Pool header for each memory type.\r
+//\r
+POOL            mPoolHead[EfiMaxMemoryType];\r
+\r
 //\r
+// List of pool header to search for the appropriate memory type.\r
 //\r
+LIST_ENTRY      mPoolHeadList = INITIALIZE_LIST_HEAD_VARIABLE (mPoolHeadList);\r
 \r
 \r
 /**\r
@@ -91,26 +94,24 @@ CoreInitializePool (
   UINTN  Index;\r
 \r
   for (Type=0; Type < EfiMaxMemoryType; Type++) {\r
-    PoolHead[Type].Signature  = 0;\r
-    PoolHead[Type].Used       = 0;\r
-    PoolHead[Type].MemoryType = (EFI_MEMORY_TYPE) Type;\r
+    mPoolHead[Type].Signature  = 0;\r
+    mPoolHead[Type].Used       = 0;\r
+    mPoolHead[Type].MemoryType = (EFI_MEMORY_TYPE) Type;\r
     for (Index=0; Index < MAX_POOL_LIST; Index++) {\r
-        InitializeListHead (&PoolHead[Type].FreeList[Index]);\r
+      InitializeListHead (&mPoolHead[Type].FreeList[Index]);\r
     }\r
   }\r
-  InitializeListHead (&PoolHeadList);\r
 }\r
 \r
 \r
 /**\r
   Look up pool head for specified memory type.\r
 \r
-  @param  MemoryType             Memory type of which pool head is looked for \r
+  @param  MemoryType             Memory type of which pool head is looked for\r
 \r
   @return Pointer of Corresponding pool head.\r
 \r
 **/\r
-STATIC\r
 POOL *\r
 LookupPoolHead (\r
   IN EFI_MEMORY_TYPE  MemoryType\r
@@ -120,13 +121,17 @@ LookupPoolHead (
   POOL            *Pool;\r
   UINTN           Index;\r
 \r
-  if (MemoryType >= 0 && MemoryType < EfiMaxMemoryType) {\r
-    return &PoolHead[MemoryType];\r
+  if ((UINT32)MemoryType < EfiMaxMemoryType) {\r
+    return &mPoolHead[MemoryType];\r
   }\r
 \r
-  if (MemoryType < 0) {\r
+  //\r
+  // MemoryType values in the range 0x80000000..0xFFFFFFFF are reserved for use by UEFI \r
+  // OS loaders that are provided by operating system vendors\r
+  //\r
+  if ((INT32)MemoryType < 0) {\r
 \r
-    for (Link = PoolHeadList.ForwardLink; Link != &PoolHeadList; Link = Link->ForwardLink) {\r
+    for (Link = mPoolHeadList.ForwardLink; Link != &mPoolHeadList; Link = Link->ForwardLink) {\r
       Pool = CR(Link, POOL, Link, POOL_SIGNATURE);\r
       if (Pool->MemoryType == MemoryType) {\r
         return Pool;\r
@@ -145,7 +150,7 @@ LookupPoolHead (
       InitializeListHead (&Pool->FreeList[Index]);\r
     }\r
 \r
-    InsertHeadList (&PoolHeadList, &Pool->Link);\r
+    InsertHeadList (&mPoolHeadList, &Pool->Link);\r
 \r
     return Pool;\r
   }\r
@@ -153,25 +158,24 @@ LookupPoolHead (
   return NULL;\r
 }\r
 \r
\r
 \r
 \r
 /**\r
   Allocate pool of a particular type.\r
 \r
-  @param  PoolType               Type of pool to allocate \r
-  @param  Size                   The amount of pool to allocate \r
-  @param  Buffer                 The address to return a pointer to the allocated \r
-                                 pool \r
+  @param  PoolType               Type of pool to allocate\r
+  @param  Size                   The amount of pool to allocate\r
+  @param  Buffer                 The address to return a pointer to the allocated\r
+                                 pool\r
 \r
-  @retval EFI_INVALID_PARAMETER  PoolType not valid \r
-  @retval EFI_OUT_OF_RESOURCES   Size exceeds max pool size or allocation failed. \r
+  @retval EFI_INVALID_PARAMETER  PoolType not valid or Buffer is NULL. \r
+  @retval EFI_OUT_OF_RESOURCES   Size exceeds max pool size or allocation failed.\r
   @retval EFI_SUCCESS            Pool successfully allocated.\r
 \r
 **/\r
 EFI_STATUS\r
 EFIAPI\r
-CoreAllocatePool (\r
+CoreInternalAllocatePool (\r
   IN EFI_MEMORY_TYPE  PoolType,\r
   IN UINTN            Size,\r
   OUT VOID            **Buffer\r
@@ -186,9 +190,13 @@ CoreAllocatePool (
        PoolType == EfiConventionalMemory) {\r
     return EFI_INVALID_PARAMETER;\r
   }\r
-  \r
+\r
+  if (Buffer == NULL) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
   *Buffer = NULL;\r
-  \r
+\r
   //\r
   // If size is too large, fail it\r
   // Base on the EFI spec, return status of EFI_OUT_OF_RESOURCES\r
@@ -210,14 +218,42 @@ CoreAllocatePool (
   return (*Buffer != NULL) ? EFI_SUCCESS : EFI_OUT_OF_RESOURCES;\r
 }\r
 \r
+/**\r
+  Allocate pool of a particular type.\r
+\r
+  @param  PoolType               Type of pool to allocate\r
+  @param  Size                   The amount of pool to allocate\r
+  @param  Buffer                 The address to return a pointer to the allocated\r
+                                 pool\r
+\r
+  @retval EFI_INVALID_PARAMETER  PoolType not valid or Buffer is NULL. \r
+  @retval EFI_OUT_OF_RESOURCES   Size exceeds max pool size or allocation failed.\r
+  @retval EFI_SUCCESS            Pool successfully allocated.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+CoreAllocatePool (\r
+  IN EFI_MEMORY_TYPE  PoolType,\r
+  IN UINTN            Size,\r
+  OUT VOID            **Buffer\r
+  )\r
+{\r
+  EFI_STATUS  Status;\r
 \r
+  Status = CoreInternalAllocatePool (PoolType, Size, Buffer);\r
+  if (!EFI_ERROR (Status)) {\r
+    CoreUpdateProfile ((EFI_PHYSICAL_ADDRESS) (UINTN) RETURN_ADDRESS (0), MemoryProfileActionAllocatePool, PoolType, Size, *Buffer);\r
+  }\r
+  return Status;\r
+}\r
 \r
 /**\r
   Internal function to allocate pool of a particular type.\r
   Caller must have the memory lock held\r
 \r
-  @param  PoolType               Type of pool to allocate \r
-  @param  Size                   The amount of pool to allocate \r
+  @param  PoolType               Type of pool to allocate\r
+  @param  Size                   The amount of pool to allocate\r
 \r
   @return The allocate pool, or NULL\r
 \r
@@ -237,7 +273,6 @@ CoreAllocatePoolI (
   UINTN       Index;\r
   UINTN       FSize;\r
   UINTN       Offset;\r
-  UINTN       Adjustment;\r
   UINTN       NoPages;\r
 \r
   ASSERT_LOCKED (&gMemoryLock);\r
@@ -245,13 +280,13 @@ CoreAllocatePoolI (
   //\r
   // Adjust the size by the pool header & tail overhead\r
   //\r
-  \r
+\r
   //\r
   // Adjusting the Size to be of proper alignment so that\r
   // we don't get an unaligned access fault later when\r
   // pool_Tail is being initialized\r
   //\r
-  ALIGN_VARIABLE (Size, Adjustment);\r
+  Size = ALIGN_VARIABLE (Size);\r
 \r
   Size += POOL_OVERHEAD;\r
   Index = SIZE_TO_LIST(Size);\r
@@ -267,7 +302,7 @@ CoreAllocatePoolI (
   //\r
   if (Index >= MAX_POOL_LIST) {\r
     NoPages = EFI_SIZE_TO_PAGES(Size) + EFI_SIZE_TO_PAGES (DEFAULT_PAGE_ALLOCATION) - 1;\r
-    NoPages &= ~(EFI_SIZE_TO_PAGES (DEFAULT_PAGE_ALLOCATION) - 1);\r
+    NoPages &= ~(UINTN)(EFI_SIZE_TO_PAGES (DEFAULT_PAGE_ALLOCATION) - 1);\r
     Head = CoreAllocatePoolPages (PoolType, NoPages, DEFAULT_PAGE_ALLOCATION);\r
     goto Done;\r
   }\r
@@ -294,7 +329,7 @@ CoreAllocatePoolI (
       FSize = LIST_TO_SIZE(Index);\r
 \r
       while (Offset + FSize <= DEFAULT_PAGE_ALLOCATION) {\r
-        Free = (POOL_FREE *) &NewPage[Offset];          \r
+        Free = (POOL_FREE *) &NewPage[Offset];\r
         Free->Signature = POOL_FREE_SIGNATURE;\r
         Free->Index     = (UINT32)Index;\r
         InsertHeadList (&Pool->FreeList[Index], &Free->Link);\r
@@ -320,27 +355,26 @@ Done:
   Buffer = NULL;\r
 \r
   if (Head != NULL) {\r
-    \r
+\r
     //\r
     // If we have a pool buffer, fill in the header & tail info\r
     //\r
     Head->Signature = POOL_HEAD_SIGNATURE;\r
-    Head->Size      = (UINT32) Size;\r
+    Head->Size      = Size;\r
     Head->Type      = (EFI_MEMORY_TYPE) PoolType;\r
     Tail            = HEAD_TO_TAIL (Head);\r
     Tail->Signature = POOL_TAIL_SIGNATURE;\r
-    Tail->Size      = (UINT32) Size;\r
+    Tail->Size      = Size;\r
     Buffer          = Head->Data;\r
     DEBUG_CLEAR_MEMORY (Buffer, Size - POOL_OVERHEAD);\r
 \r
-    DEBUG (\r
-      (DEBUG_POOL,\r
-      "AllocatePoolI: Type %x, Addr %x (len %x) %,d\n",\r
-       PoolType, \r
-       Buffer, \r
-       Size - POOL_OVERHEAD, \r
-      Pool->Used)\r
-      );\r
+    DEBUG ((\r
+      DEBUG_POOL,\r
+      "AllocatePoolI: Type %x, Addr %p (len %lx) %,ld\n", PoolType,\r
+      Buffer,\r
+      (UINT64)(Size - POOL_OVERHEAD),\r
+      (UINT64) Pool->Used\r
+      ));\r
 \r
     //\r
     // Account the allocation\r
@@ -348,33 +382,32 @@ Done:
     Pool->Used += Size;\r
 \r
   } else {\r
-    DEBUG ((DEBUG_ERROR | DEBUG_POOL, "AllocatePool: failed to allocate %d bytes\n", Size));\r
+    DEBUG ((DEBUG_ERROR | DEBUG_POOL, "AllocatePool: failed to allocate %ld bytes\n", (UINT64) Size));\r
   }\r
 \r
   return Buffer;\r
 }\r
-  \r
 \r
 \r
 \r
 /**\r
   Frees pool.\r
 \r
-  @param  Buffer                 The allocated pool entry to free \r
+  @param  Buffer                 The allocated pool entry to free\r
 \r
-  @retval EFI_INVALID_PARAMETER  Buffer is not a valid value. \r
+  @retval EFI_INVALID_PARAMETER  Buffer is not a valid value.\r
   @retval EFI_SUCCESS            Pool successfully freed.\r
 \r
 **/\r
 EFI_STATUS\r
 EFIAPI\r
-CoreFreePool (\r
+CoreInternalFreePool (\r
   IN VOID        *Buffer\r
   )\r
 {\r
   EFI_STATUS Status;\r
 \r
-  if (NULL == Buffer) {\r
+  if (Buffer == NULL) {\r
     return EFI_INVALID_PARAMETER;\r
   }\r
 \r
@@ -384,15 +417,37 @@ CoreFreePool (
   return Status;\r
 }\r
 \r
+/**\r
+  Frees pool.\r
 \r
+  @param  Buffer                 The allocated pool entry to free\r
+\r
+  @retval EFI_INVALID_PARAMETER  Buffer is not a valid value.\r
+  @retval EFI_SUCCESS            Pool successfully freed.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+CoreFreePool (\r
+  IN VOID  *Buffer\r
+  )\r
+{\r
+  EFI_STATUS  Status;\r
+\r
+  Status = CoreInternalFreePool (Buffer);\r
+  if (!EFI_ERROR (Status)) {\r
+    CoreUpdateProfile ((EFI_PHYSICAL_ADDRESS) (UINTN) RETURN_ADDRESS (0), MemoryProfileActionFreePool, 0, 0, Buffer);\r
+  }\r
+  return Status;\r
+}\r
 \r
 /**\r
   Internal function to free a pool entry.\r
   Caller must have the memory lock held\r
 \r
-  @param  Buffer                 The allocated pool entry to free \r
+  @param  Buffer                 The allocated pool entry to free\r
 \r
-  @retval EFI_INVALID_PARAMETER  Buffer not valid \r
+  @retval EFI_INVALID_PARAMETER  Buffer not valid\r
   @retval EFI_SUCCESS            Buffer successfully freed.\r
 \r
 **/\r
@@ -413,19 +468,19 @@ CoreFreePoolI (
   UINTN       Offset;\r
   BOOLEAN     AllFree;\r
 \r
-  ASSERT(NULL != Buffer);\r
+  ASSERT(Buffer != NULL);\r
   //\r
   // Get the head & tail of the pool entry\r
   //\r
   Head = CR (Buffer, POOL_HEAD, Data, POOL_HEAD_SIGNATURE);\r
-  ASSERT(NULL != Head);\r
+  ASSERT(Head != NULL);\r
 \r
   if (Head->Signature != POOL_HEAD_SIGNATURE) {\r
     return EFI_INVALID_PARAMETER;\r
   }\r
 \r
   Tail = HEAD_TO_TAIL (Head);\r
-  ASSERT(NULL != Tail);\r
+  ASSERT(Tail != NULL);\r
 \r
   //\r
   // Debug\r
@@ -451,10 +506,10 @@ CoreFreePoolI (
     return EFI_INVALID_PARAMETER;\r
   }\r
   Pool->Used -= Size;\r
-  DEBUG ((DEBUG_POOL, "FreePool: %x (len %x) %,d\n", Head->Data, Head->Size - POOL_OVERHEAD, Pool->Used));\r
+  DEBUG ((DEBUG_POOL, "FreePool: %p (len %lx) %,ld\n", Head->Data, (UINT64)(Head->Size - POOL_OVERHEAD), (UINT64) Pool->Used));\r
 \r
   //\r
-  // Determine the pool list \r
+  // Determine the pool list\r
   //\r
   Index = SIZE_TO_LIST(Size);\r
   DEBUG_CLEAR_MEMORY (Head, Size);\r
@@ -468,7 +523,7 @@ CoreFreePoolI (
     // Return the memory pages back to free memory\r
     //\r
     NoPages = EFI_SIZE_TO_PAGES(Size) + EFI_SIZE_TO_PAGES (DEFAULT_PAGE_ALLOCATION) - 1;\r
-    NoPages &= ~(EFI_SIZE_TO_PAGES (DEFAULT_PAGE_ALLOCATION) - 1);\r
+    NoPages &= ~(UINTN)(EFI_SIZE_TO_PAGES (DEFAULT_PAGE_ALLOCATION) - 1);\r
     CoreFreePoolPages ((EFI_PHYSICAL_ADDRESS) (UINTN) Head, NoPages);\r
 \r
   } else {\r
@@ -477,18 +532,18 @@ CoreFreePoolI (
     // Put the pool entry onto the free pool list\r
     //\r
     Free = (POOL_FREE *) Head;\r
-    ASSERT(NULL != Free);\r
+    ASSERT(Free != NULL);\r
     Free->Signature = POOL_FREE_SIGNATURE;\r
     Free->Index     = (UINT32)Index;\r
     InsertHeadList (&Pool->FreeList[Index], &Free->Link);\r
 \r
     //\r
-    // See if all the pool entries in the same page as Free are freed pool \r
+    // See if all the pool entries in the same page as Free are freed pool\r
     // entries\r
     //\r
     NewPage = (CHAR8 *)((UINTN)Free & ~((DEFAULT_PAGE_ALLOCATION) -1));\r
     Free = (POOL_FREE *) &NewPage[0];\r
-    ASSERT(NULL != Free);\r
+    ASSERT(Free != NULL);\r
 \r
     if (Free->Signature == POOL_FREE_SIGNATURE) {\r
 \r
@@ -496,12 +551,12 @@ CoreFreePoolI (
 \r
       AllFree = TRUE;\r
       Offset = 0;\r
-      \r
+\r
       while ((Offset < DEFAULT_PAGE_ALLOCATION) && (AllFree)) {\r
         FSize = LIST_TO_SIZE(Index);\r
         while (Offset + FSize <= DEFAULT_PAGE_ALLOCATION) {\r
           Free = (POOL_FREE *) &NewPage[Offset];\r
-          ASSERT(NULL != Free);\r
+          ASSERT(Free != NULL);\r
           if (Free->Signature != POOL_FREE_SIGNATURE) {\r
             AllFree = FALSE;\r
           }\r
@@ -513,20 +568,20 @@ CoreFreePoolI (
       if (AllFree) {\r
 \r
         //\r
-        // All of the pool entries in the same page as Free are free pool \r
+        // All of the pool entries in the same page as Free are free pool\r
         // entries\r
         // Remove all of these pool entries from the free loop lists.\r
         //\r
         Free = (POOL_FREE *) &NewPage[0];\r
-        ASSERT(NULL != Free);\r
+        ASSERT(Free != NULL);\r
         Index = Free->Index;\r
         Offset = 0;\r
-        \r
+\r
         while (Offset < DEFAULT_PAGE_ALLOCATION) {\r
           FSize = LIST_TO_SIZE(Index);\r
           while (Offset + FSize <= DEFAULT_PAGE_ALLOCATION) {\r
             Free = (POOL_FREE *) &NewPage[Offset];\r
-            ASSERT(NULL != Free);\r
+            ASSERT(Free != NULL);\r
             RemoveEntryList (&Free->Link);\r
             Offset += FSize;\r
           }\r
@@ -542,14 +597,15 @@ CoreFreePoolI (
   }\r
 \r
   //\r
-  // If this is an OS specific memory type, then check to see if the last \r
+  // If this is an OS specific memory type, then check to see if the last\r
   // portion of that memory type has been freed.  If it has, then free the\r
   // list entry for that memory type\r
   //\r
-  if (Pool->MemoryType < 0 && Pool->Used == 0) {\r
+  if ((INT32)Pool->MemoryType < 0 && Pool->Used == 0) {\r
     RemoveEntryList (&Pool->Link);\r
     CoreFreePoolI (Pool);\r
   }\r
 \r
   return EFI_SUCCESS;\r
 }\r
+\r