/** Internal function. Used by the pool functions to allocate pages to back pool allocation requests. @param PoolType The type of memory for the new pool pages @param NoPages No of pages to allocate @param Granularity Bits to align. @param NeedGuard Flag to indicate Guard page is needed or not @return The allocated memory, or NULL **/ STATIC VOID * CoreAllocatePoolPagesI ( IN EFI_MEMORY_TYPE PoolType, IN UINTN NoPages, IN UINTN Granularity, IN BOOLEAN NeedGuard ) { VOID *Buffer; EFI_STATUS Status; Status = CoreAcquireLockOrFail (&gMemoryLock); if (EFI_ERROR (Status)) { return NULL; } Buffer = CoreAllocatePoolPages (PoolType, NoPages, Granularity, NeedGuard); CoreReleaseMemoryLock (); if (Buffer != NULL) { if (NeedGuard) { SetGuardForMemory ((EFI_PHYSICAL_ADDRESS)(UINTN)Buffer, NoPages); } ApplyMemoryProtectionPolicy(EfiConventionalMemory, PoolType, (EFI_PHYSICAL_ADDRESS)(UINTN)Buffer, EFI_PAGES_TO_SIZE (NoPages)); } return Buffer; }
/** 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); }