+ UINTN AlignmentMask;\r
+ EFI_PHYSICAL_ADDRESS Memory;\r
+ EFI_GCD_MEMORY_SPACE_DESCRIPTOR Descriptor;\r
+\r
+ // Alignment must be a power of two or zero.\r
+ ASSERT ((Alignment & (Alignment - 1)) == 0);\r
+\r
+ //\r
+ // Look in our list for the smallest page that could satisfy the new allocation\r
+ //\r
+ Node = NULL;\r
+ NewNode = NULL;\r
+ for (Link = mPageList.ForwardLink; Link != &mPageList; Link = Link->ForwardLink) {\r
+ Node = BASE_CR (Link, FREE_PAGE_NODE, Link);\r
+ if ((Node->Allocated == FALSE) && (Node->MemoryType == MemoryType)) {\r
+ // We have a node that fits our requirements\r
+ if (((UINTN)Node->Base & (Alignment - 1)) == 0) {\r
+ // We found a page that matches the page size\r
+ if (Node->Pages == Pages) {\r
+ Node->Allocated = TRUE;\r
+ Node->Allocation = (VOID*)(UINTN)Node->Base;\r
+ *Allocation = Node->Allocation;\r
+\r
+ // Update the size of the freed buffer\r
+ mFreedBufferSize -= Pages * EFI_PAGE_SIZE;\r
+ return EFI_SUCCESS;\r
+ } else if (Node->Pages > Pages) {\r
+ if (NewNode == NULL) {\r
+ // It is the first node that could contain our new allocation\r
+ NewNode = Node;\r
+ } else if (NewNode->Pages > Node->Pages) {\r
+ // This node offers a smaller number of page.\r
+ NewNode = Node;\r
+ }\r
+ }\r
+ }\r
+ }\r
+ }\r
+ // Check if we have found a node that could contain our new allocation\r
+ if (NewNode != NULL) {\r
+ NewNode->Allocated = TRUE;\r
+ NewNode->Allocation = (VOID*)(UINTN)NewNode->Base;\r
+ *Allocation = NewNode->Allocation;\r
+ mFreedBufferSize -= NewNode->Pages * EFI_PAGE_SIZE;\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ //\r
+ // Otherwise, we need to allocate a new buffer\r
+ //\r
+\r
+ // We do not want to over-allocate in case the alignment requirement does not\r
+ // require extra pages\r
+ if (Alignment > EFI_PAGE_SIZE) {\r
+ AlignmentMask = Alignment - 1;\r
+ Pages += EFI_SIZE_TO_PAGES (Alignment);\r
+ } else {\r
+ AlignmentMask = 0;\r
+ }\r
+\r
+ Status = gBS->AllocatePages (AllocateAnyPages, MemoryType, Pages, &Memory);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ Status = gDS->GetMemorySpaceDescriptor (Memory, &Descriptor);\r
+ if (EFI_ERROR (Status)) {\r
+ gBS->FreePages (Memory, Pages);\r
+ return Status;\r
+ }\r
+\r
+ Status = gDS->SetMemorySpaceAttributes (Memory, EFI_PAGES_TO_SIZE (Pages), EFI_MEMORY_WC);\r
+ if (EFI_ERROR (Status)) {\r
+ gBS->FreePages (Memory, Pages);\r
+ return Status;\r
+ }\r
+\r
+ InvalidateDataCacheRange ((VOID *)(UINTN)Memory, EFI_PAGES_TO_SIZE (Pages));\r
+\r
+ NewNode = AllocatePool (sizeof (FREE_PAGE_NODE));\r