/** Internal Function. Allocate n pages from free page list at given address. @param FreePageList The free page node. @param NumberOfPages Number of pages to be allocated. @param MaxAddress Request to allocate memory below this address. @return Memory address of allocated pages. **/ UINTN InternalAllocAddress ( IN OUT LIST_ENTRY *FreePageList, IN UINTN NumberOfPages, IN UINTN Address ) { UINTN EndAddress; LIST_ENTRY *Node; FREE_PAGE_LIST *Pages; if ((Address & EFI_PAGE_MASK) != 0) { return ~Address; } EndAddress = Address + EFI_PAGES_TO_SIZE (NumberOfPages); for (Node = FreePageList->BackLink; Node!= FreePageList; Node = Node->BackLink) { Pages = BASE_CR (Node, FREE_PAGE_LIST, Link); if ((UINTN)Pages <= Address) { if ((UINTN)Pages + EFI_PAGES_TO_SIZE (Pages->NumberOfPages) < EndAddress) { break; } return InternalAllocPagesOnOneNode (Pages, NumberOfPages, EndAddress); } } return ~Address; }
/** Internal Function. Allocate n pages from free page list below MaxAddress. @param FreePageList The free page node. @param NumberOfPages Number of pages to be allocated. @param MaxAddress Request to allocate memory below this address. @return Memory address of allocated pages. **/ UINTN InternalAllocMaxAddress ( IN OUT LIST_ENTRY *FreePageList, IN UINTN NumberOfPages, IN UINTN MaxAddress ) { LIST_ENTRY *Node; FREE_PAGE_LIST *Pages; for (Node = FreePageList->BackLink; Node != FreePageList; Node = Node->BackLink) { Pages = BASE_CR (Node, FREE_PAGE_LIST, Link); if (Pages->NumberOfPages >= NumberOfPages && (UINTN)Pages + EFI_PAGES_TO_SIZE (NumberOfPages) - 1 <= MaxAddress) { return InternalAllocPagesOnOneNode (Pages, NumberOfPages, MaxAddress); } } return (UINTN)(-1); }
/** Helper function of memory allocation with Guard pages. @param FreePageList The free page node. @param NumberOfPages Number of pages to be allocated. @param MaxAddress Request to allocate memory below this address. @param MemoryType Type of memory requested. @return Memory address of allocated pages. **/ UINTN InternalAllocMaxAddressWithGuard ( IN OUT LIST_ENTRY *FreePageList, IN UINTN NumberOfPages, IN UINTN MaxAddress, IN EFI_MEMORY_TYPE MemoryType ) { LIST_ENTRY *Node; FREE_PAGE_LIST *Pages; UINTN PagesToAlloc; UINTN HeadGuard; UINTN TailGuard; UINTN Address; for (Node = FreePageList->BackLink; Node != FreePageList; Node = Node->BackLink) { Pages = BASE_CR (Node, FREE_PAGE_LIST, Link); if (Pages->NumberOfPages >= NumberOfPages && (UINTN)Pages + EFI_PAGES_TO_SIZE (NumberOfPages) - 1 <= MaxAddress) { // // We may need 1 or 2 more pages for Guard. Check it out. // PagesToAlloc = NumberOfPages; TailGuard = (UINTN)Pages + EFI_PAGES_TO_SIZE (Pages->NumberOfPages); if (!IsGuardPage (TailGuard)) { // // Add one if no Guard at the end of current free memory block. // PagesToAlloc += 1; TailGuard = 0; } HeadGuard = (UINTN)Pages + EFI_PAGES_TO_SIZE (Pages->NumberOfPages - PagesToAlloc) - EFI_PAGE_SIZE; if (!IsGuardPage (HeadGuard)) { // // Add one if no Guard at the page before the address to allocate // PagesToAlloc += 1; HeadGuard = 0; } if (Pages->NumberOfPages < PagesToAlloc) { // Not enough space to allocate memory with Guards? Try next block. continue; } Address = InternalAllocPagesOnOneNode (Pages, PagesToAlloc, MaxAddress); ConvertSmmMemoryMapEntry(MemoryType, Address, PagesToAlloc, FALSE); CoreFreeMemoryMapStack(); if (HeadGuard == 0) { // Don't pass the Guard page to user. Address += EFI_PAGE_SIZE; } SetGuardForMemory (Address, NumberOfPages); return Address; } } return (UINTN)(-1); }