Esempio n. 1
0
File: Page.c Progetto: etiago/vbox
/**
  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;
}
Esempio n. 2
0
File: Page.c Progetto: etiago/vbox
/**
  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);
}