MdePkg PeiMemoryAllocationLib: Update InternalAllocateAlignedPages
authorStar Zeng <star.zeng@intel.com>
Fri, 3 Mar 2017 10:15:13 +0000 (18:15 +0800)
committerStar Zeng <star.zeng@intel.com>
Mon, 4 Sep 2017 05:45:47 +0000 (13:45 +0800)
Update InternalAllocateAlignedPages to use PeiServicesFreePages.

Let the InternalAllocateAlignedPages in PeiMemoryAllocationLib use
same algorithm with InternalAllocateAlignedPages in
UefiMemoryAllocationLib.

Cc: Liming Gao <liming.gao@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Star Zeng <star.zeng@intel.com>
Reviewed-by: Liming Gao <liming.gao@intel.com>
MdePkg/Library/PeiMemoryAllocationLib/MemoryAllocationLib.c

index 37273dde561ac45e889e8ecc33c0ef089349faf2..5cd24a38a3c66c6526618ee326453897a267fdab 100644 (file)
@@ -181,15 +181,12 @@ InternalAllocateAlignedPages (
   IN UINTN            Alignment\r
   )\r
 {\r
-  EFI_PHYSICAL_ADDRESS   Memory;\r
-  EFI_PHYSICAL_ADDRESS   AlignedMemory;\r
-  EFI_PEI_HOB_POINTERS   Hob;\r
-  BOOLEAN                SkipBeforeMemHob;\r
-  BOOLEAN                SkipAfterMemHob;\r
-  EFI_PHYSICAL_ADDRESS   HobBaseAddress;\r
-  UINT64                 HobLength;\r
-  EFI_MEMORY_TYPE        HobMemoryType;\r
-  UINTN                  TotalPages;\r
+  EFI_STATUS            Status;\r
+  EFI_PHYSICAL_ADDRESS  Memory;\r
+  UINTN                 AlignedMemory;\r
+  UINTN                 AlignmentMask;\r
+  UINTN                 UnalignedPages;\r
+  UINTN                 RealPages;\r
 \r
   //\r
   // Alignment must be a power of two or zero.\r
@@ -199,139 +196,50 @@ InternalAllocateAlignedPages (
   if (Pages == 0) {\r
     return NULL;\r
   }\r
-  //\r
-  // Make sure that Pages plus EFI_SIZE_TO_PAGES (Alignment) does not overflow.\r
-  //\r
-  ASSERT (Pages <= (MAX_ADDRESS - EFI_SIZE_TO_PAGES (Alignment))); \r
-\r
-  //\r
-  // We would rather waste some memory to save PEI code size.\r
-  // meaning in addition to the requested size for the aligned mem,\r
-  // we simply reserve an overhead memory equal to Alignmemt(page-aligned), no matter what.\r
-  // The overhead mem size could be reduced later with more involved malloc mechanisms\r
-  // (e.g., somthing that can detect the alignment boundary before allocating memory or \r
-  //  can request that memory be allocated at a certain address that is aleady aligned).\r
-  //\r
-  TotalPages = Pages + (Alignment <= EFI_PAGE_SIZE ? 0 : EFI_SIZE_TO_PAGES(Alignment));\r
-  Memory = (EFI_PHYSICAL_ADDRESS) (UINTN) InternalAllocatePages (MemoryType, TotalPages);\r
-  if (Memory == 0) {\r
-    DEBUG((DEBUG_INFO, "Out of memory resource! \n"));\r
-    return NULL;\r
-  }\r
-  DEBUG ((DEBUG_INFO, "Allocated Memory unaligned: Address = 0x%LX, Pages = 0x%X, Type = %d \n", Memory, TotalPages, (UINTN) MemoryType));\r
-\r
-  //\r
-  // Alignment calculation\r
-  //\r
-  AlignedMemory = Memory;\r
   if (Alignment > EFI_PAGE_SIZE) {\r
-    AlignedMemory = ALIGN_VALUE (Memory, Alignment);\r
-  }\r
-  DEBUG ((DEBUG_INFO, "After aligning to 0x%X bytes: Address = 0x%LX, Pages = 0x%X \n", Alignment, AlignedMemory, Pages));\r
-\r
-  //\r
-  // In general three HOBs cover the total allocated space.\r
-  // The aligned portion is covered by the aligned mem HOB and\r
-  // the unaligned(to be freed) portions before and after the aligned portion are covered by newly created HOBs.\r
-  //\r
-  // Before mem HOB covers the region between "Memory" and "AlignedMemory"\r
-  // Aligned mem HOB covers the region between "AlignedMemory" and "AlignedMemory + EFI_PAGES_TO_SIZE(Pages)"\r
-  // After mem HOB covers the region between "AlignedMemory + EFI_PAGES_TO_SIZE(Pages)" and "Memory + EFI_PAGES_TO_SIZE(TotalPages)"\r
-  //\r
-  // The before or after mem HOBs need to be skipped under special cases where the aligned portion\r
-  // touches either the top or bottom of the original allocated space.\r
-  //\r
-  SkipBeforeMemHob = FALSE;\r
-  SkipAfterMemHob  = FALSE;\r
-  if (Memory == AlignedMemory) {\r
-    SkipBeforeMemHob = TRUE;\r
-  }\r
-  if ((Memory + EFI_PAGES_TO_SIZE(TotalPages)) == (AlignedMemory + EFI_PAGES_TO_SIZE(Pages))) {\r
     //\r
-    // This condition is never met in the current implementation.\r
-    // There is always some after-mem since the overhead mem(used in TotalPages)\r
-    // is no less than Alignment.\r
+    // Calculate the total number of pages since alignment is larger than page size.\r
     //\r
-    SkipAfterMemHob = TRUE;\r
-  }\r
-\r
-  //  \r
-  // Search for the mem HOB referring to the original(unaligned) allocation \r
-  // and update the size and type if needed.\r
-  //\r
-  Hob.Raw = GetFirstHob (EFI_HOB_TYPE_MEMORY_ALLOCATION);\r
-  while (Hob.Raw != NULL) {\r
-    if (Hob.MemoryAllocation->AllocDescriptor.MemoryBaseAddress == Memory) {\r
-      break;\r
-    }\r
-    Hob.Raw = GET_NEXT_HOB (Hob);\r
-    Hob.Raw = GetNextHob (EFI_HOB_TYPE_MEMORY_ALLOCATION, Hob.Raw);\r
-  }\r
-  ASSERT (Hob.Raw != NULL);\r
-  if (SkipBeforeMemHob) {\r
+    AlignmentMask  = Alignment - 1;\r
+    RealPages      = Pages + EFI_SIZE_TO_PAGES (Alignment);\r
     //\r
-    // Use this HOB as aligned mem HOB as there is no portion before it.\r
+    // Make sure that Pages plus EFI_SIZE_TO_PAGES (Alignment) does not overflow.\r
     //\r
-    HobLength = EFI_PAGES_TO_SIZE(Pages);\r
-    Hob.MemoryAllocation->AllocDescriptor.MemoryLength = HobLength;\r
+    ASSERT (RealPages > Pages);\r
+\r
+    Status         = PeiServicesAllocatePages (MemoryType, RealPages, &Memory);\r
+    if (EFI_ERROR (Status)) {\r
+      return NULL;\r
+    }\r
+    AlignedMemory  = ((UINTN) Memory + AlignmentMask) & ~AlignmentMask;\r
+    UnalignedPages = EFI_SIZE_TO_PAGES (AlignedMemory - (UINTN) Memory);\r
+    if (UnalignedPages > 0) {\r
+      //\r
+      // Free first unaligned page(s).\r
+      //\r
+      Status = PeiServicesFreePages (Memory, UnalignedPages);\r
+      ASSERT_EFI_ERROR (Status);\r
+    }\r
+    Memory         = AlignedMemory + EFI_PAGES_TO_SIZE (Pages);\r
+    UnalignedPages = RealPages - Pages - UnalignedPages;\r
+    if (UnalignedPages > 0) {\r
+      //\r
+      // Free last unaligned page(s).\r
+      //\r
+      Status = PeiServicesFreePages (Memory, UnalignedPages);\r
+      ASSERT_EFI_ERROR (Status);\r
+    }\r
   } else {\r
     //\r
-    // Use this HOB as before mem HOB and create a new HOB for the aligned portion \r
+    // Do not over-allocate pages in this case.\r
     //\r
-    HobLength = (AlignedMemory - Memory); \r
-    Hob.MemoryAllocation->AllocDescriptor.MemoryLength = HobLength;\r
-    Hob.MemoryAllocation->AllocDescriptor.MemoryType = EfiConventionalMemory;\r
-  }\r
-\r
-  HobBaseAddress = Hob.MemoryAllocation->AllocDescriptor.MemoryBaseAddress;\r
-  HobMemoryType = Hob.MemoryAllocation->AllocDescriptor.MemoryType;\r
-\r
-  //\r
-  // Build the aligned mem HOB if needed\r
-  //\r
-  if (!SkipBeforeMemHob) {\r
-    DEBUG((DEBUG_INFO, "Updated before-mem HOB with BaseAddress = %LX, Length = %LX, MemoryType = %d \n",\r
-      HobBaseAddress, HobLength, (UINTN) HobMemoryType));\r
-\r
-    HobBaseAddress = AlignedMemory;\r
-    HobLength = EFI_PAGES_TO_SIZE(Pages);\r
-    HobMemoryType = MemoryType;\r
-\r
-    BuildMemoryAllocationHob (\r
-      HobBaseAddress,\r
-      HobLength,\r
-      HobMemoryType\r
-      );\r
-\r
-    DEBUG((DEBUG_INFO, "Created aligned-mem HOB with BaseAddress = %LX, Length = %LX, MemoryType = %d \n",\r
-      HobBaseAddress, HobLength, (UINTN) HobMemoryType));\r
-  } else {\r
-    if (HobBaseAddress != 0) {\r
-      DEBUG((DEBUG_INFO, "Updated aligned-mem HOB with BaseAddress = %LX, Length = %LX, MemoryType = %d \n",\r
-        HobBaseAddress, HobLength, (UINTN) HobMemoryType));\r
+    Status = PeiServicesAllocatePages (MemoryType, Pages, &Memory);\r
+    if (EFI_ERROR (Status)) {\r
+      return NULL;\r
     }\r
+    AlignedMemory  = (UINTN) Memory;\r
   }\r
-\r
-\r
-  //\r
-  // Build the after mem HOB if needed\r
-  //\r
-  if (!SkipAfterMemHob) {\r
-    HobBaseAddress = AlignedMemory + EFI_PAGES_TO_SIZE(Pages);\r
-    HobLength = (Memory + EFI_PAGES_TO_SIZE(TotalPages)) - (AlignedMemory + EFI_PAGES_TO_SIZE(Pages));\r
-    HobMemoryType = EfiConventionalMemory;\r
-\r
-    BuildMemoryAllocationHob (\r
-      HobBaseAddress,\r
-      HobLength,\r
-      HobMemoryType\r
-      );\r
-\r
-    DEBUG((DEBUG_INFO, "Created after-mem HOB with BaseAddress = %LX, Length = %LX, MemoryType = %d \n",\r
-      HobBaseAddress, HobLength, (UINTN) HobMemoryType));\r
-  }\r
-\r
-  return (VOID *) (UINTN) AlignedMemory;\r
+  return (VOID *) AlignedMemory;\r
 }\r
 \r
 /**\r