REF: https://bugzilla.tianocore.org/show_bug.cgi?id=3737 Apply uncrustify changes to .c/.h files in the StandaloneMmPkg package Cc: Andrew Fish <afish@apple.com> Cc: Leif Lindholm <leif@nuviainc.com> Cc: Michael D Kinney <michael.d.kinney@intel.com> Signed-off-by: Michael Kubacki <michael.kubacki@microsoft.com> Reviewed-by: Sami Mujawar <sami.mujawar@arm.com>
		
			
				
	
	
		
			392 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			392 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/** @file
 | 
						|
  MM Memory page management functions.
 | 
						|
 | 
						|
  Copyright (c) 2009 - 2014, Intel Corporation. All rights reserved.<BR>
 | 
						|
  Copyright (c) 2016 - 2018, ARM Limited. All rights reserved.<BR>
 | 
						|
  SPDX-License-Identifier: BSD-2-Clause-Patent
 | 
						|
 | 
						|
**/
 | 
						|
 | 
						|
#include "StandaloneMmCore.h"
 | 
						|
 | 
						|
#define NEXT_MEMORY_DESCRIPTOR(MemoryDescriptor, Size) \
 | 
						|
  ((EFI_MEMORY_DESCRIPTOR *)((UINT8 *)(MemoryDescriptor) + (Size)))
 | 
						|
 | 
						|
#define TRUNCATE_TO_PAGES(a)  ((a) >> EFI_PAGE_SHIFT)
 | 
						|
 | 
						|
LIST_ENTRY  mMmMemoryMap = INITIALIZE_LIST_HEAD_VARIABLE (mMmMemoryMap);
 | 
						|
 | 
						|
UINTN  mMapKey;
 | 
						|
 | 
						|
/**
 | 
						|
  Internal Function. Allocate n pages from given free page node.
 | 
						|
 | 
						|
  @param  Pages                  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
 | 
						|
InternalAllocPagesOnOneNode (
 | 
						|
  IN OUT FREE_PAGE_LIST  *Pages,
 | 
						|
  IN     UINTN           NumberOfPages,
 | 
						|
  IN     UINTN           MaxAddress
 | 
						|
  )
 | 
						|
{
 | 
						|
  UINTN           Top;
 | 
						|
  UINTN           Bottom;
 | 
						|
  FREE_PAGE_LIST  *Node;
 | 
						|
 | 
						|
  Top = TRUNCATE_TO_PAGES (MaxAddress + 1 - (UINTN)Pages);
 | 
						|
  if (Top > Pages->NumberOfPages) {
 | 
						|
    Top = Pages->NumberOfPages;
 | 
						|
  }
 | 
						|
 | 
						|
  Bottom = Top - NumberOfPages;
 | 
						|
 | 
						|
  if (Top < Pages->NumberOfPages) {
 | 
						|
    Node                = (FREE_PAGE_LIST *)((UINTN)Pages + EFI_PAGES_TO_SIZE (Top));
 | 
						|
    Node->NumberOfPages = Pages->NumberOfPages - Top;
 | 
						|
    InsertHeadList (&Pages->Link, &Node->Link);
 | 
						|
  }
 | 
						|
 | 
						|
  if (Bottom > 0) {
 | 
						|
    Pages->NumberOfPages = Bottom;
 | 
						|
  } else {
 | 
						|
    RemoveEntryList (&Pages->Link);
 | 
						|
  }
 | 
						|
 | 
						|
  return (UINTN)Pages + EFI_PAGES_TO_SIZE (Bottom);
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  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);
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  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;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Allocates pages from the memory map.
 | 
						|
 | 
						|
  @param  Type                   The type of allocation to perform.
 | 
						|
  @param  MemoryType             The type of memory to turn the allocated pages
 | 
						|
                                 into.
 | 
						|
  @param  NumberOfPages          The number of pages to allocate.
 | 
						|
  @param  Memory                 A pointer to receive the base allocated memory
 | 
						|
                                 address.
 | 
						|
 | 
						|
  @retval EFI_INVALID_PARAMETER  Parameters violate checking rules defined in spec.
 | 
						|
  @retval EFI_NOT_FOUND          Could not allocate pages match the requirement.
 | 
						|
  @retval EFI_OUT_OF_RESOURCES   No enough pages to allocate.
 | 
						|
  @retval EFI_SUCCESS            Pages successfully allocated.
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
MmInternalAllocatePages (
 | 
						|
  IN  EFI_ALLOCATE_TYPE     Type,
 | 
						|
  IN  EFI_MEMORY_TYPE       MemoryType,
 | 
						|
  IN  UINTN                 NumberOfPages,
 | 
						|
  OUT EFI_PHYSICAL_ADDRESS  *Memory
 | 
						|
  )
 | 
						|
{
 | 
						|
  UINTN  RequestedAddress;
 | 
						|
 | 
						|
  if ((MemoryType != EfiRuntimeServicesCode) &&
 | 
						|
      (MemoryType != EfiRuntimeServicesData))
 | 
						|
  {
 | 
						|
    return EFI_INVALID_PARAMETER;
 | 
						|
  }
 | 
						|
 | 
						|
  if (NumberOfPages > TRUNCATE_TO_PAGES ((UINTN)-1) + 1) {
 | 
						|
    return EFI_OUT_OF_RESOURCES;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // We don't track memory type in MM
 | 
						|
  //
 | 
						|
  RequestedAddress = (UINTN)*Memory;
 | 
						|
  switch (Type) {
 | 
						|
    case AllocateAnyPages:
 | 
						|
      RequestedAddress = (UINTN)(-1);
 | 
						|
    case AllocateMaxAddress:
 | 
						|
      *Memory = InternalAllocMaxAddress (
 | 
						|
                  &mMmMemoryMap,
 | 
						|
                  NumberOfPages,
 | 
						|
                  RequestedAddress
 | 
						|
                  );
 | 
						|
      if (*Memory == (UINTN)-1) {
 | 
						|
        return EFI_OUT_OF_RESOURCES;
 | 
						|
      }
 | 
						|
 | 
						|
      break;
 | 
						|
    case AllocateAddress:
 | 
						|
      *Memory = InternalAllocAddress (
 | 
						|
                  &mMmMemoryMap,
 | 
						|
                  NumberOfPages,
 | 
						|
                  RequestedAddress
 | 
						|
                  );
 | 
						|
      if (*Memory != RequestedAddress) {
 | 
						|
        return EFI_NOT_FOUND;
 | 
						|
      }
 | 
						|
 | 
						|
      break;
 | 
						|
    default:
 | 
						|
      return EFI_INVALID_PARAMETER;
 | 
						|
  }
 | 
						|
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Allocates pages from the memory map.
 | 
						|
 | 
						|
  @param  Type                   The type of allocation to perform.
 | 
						|
  @param  MemoryType             The type of memory to turn the allocated pages
 | 
						|
                                 into.
 | 
						|
  @param  NumberOfPages          The number of pages to allocate.
 | 
						|
  @param  Memory                 A pointer to receive the base allocated memory
 | 
						|
                                 address.
 | 
						|
 | 
						|
  @retval EFI_INVALID_PARAMETER  Parameters violate checking rules defined in spec.
 | 
						|
  @retval EFI_NOT_FOUND          Could not allocate pages match the requirement.
 | 
						|
  @retval EFI_OUT_OF_RESOURCES   No enough pages to allocate.
 | 
						|
  @retval EFI_SUCCESS            Pages successfully allocated.
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
MmAllocatePages (
 | 
						|
  IN  EFI_ALLOCATE_TYPE     Type,
 | 
						|
  IN  EFI_MEMORY_TYPE       MemoryType,
 | 
						|
  IN  UINTN                 NumberOfPages,
 | 
						|
  OUT EFI_PHYSICAL_ADDRESS  *Memory
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS  Status;
 | 
						|
 | 
						|
  Status = MmInternalAllocatePages (Type, MemoryType, NumberOfPages, Memory);
 | 
						|
  return Status;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Internal Function. Merge two adjacent nodes.
 | 
						|
 | 
						|
  @param  First             The first of two nodes to merge.
 | 
						|
 | 
						|
  @return Pointer to node after merge (if success) or pointer to next node (if fail).
 | 
						|
 | 
						|
**/
 | 
						|
FREE_PAGE_LIST *
 | 
						|
InternalMergeNodes (
 | 
						|
  IN FREE_PAGE_LIST  *First
 | 
						|
  )
 | 
						|
{
 | 
						|
  FREE_PAGE_LIST  *Next;
 | 
						|
 | 
						|
  Next = BASE_CR (First->Link.ForwardLink, FREE_PAGE_LIST, Link);
 | 
						|
  ASSERT (
 | 
						|
    TRUNCATE_TO_PAGES ((UINTN)Next - (UINTN)First) >= First->NumberOfPages
 | 
						|
    );
 | 
						|
 | 
						|
  if (TRUNCATE_TO_PAGES ((UINTN)Next - (UINTN)First) == First->NumberOfPages) {
 | 
						|
    First->NumberOfPages += Next->NumberOfPages;
 | 
						|
    RemoveEntryList (&Next->Link);
 | 
						|
    Next = First;
 | 
						|
  }
 | 
						|
 | 
						|
  return Next;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Frees previous allocated pages.
 | 
						|
 | 
						|
  @param  Memory                 Base address of memory being freed.
 | 
						|
  @param  NumberOfPages          The number of pages to free.
 | 
						|
 | 
						|
  @retval EFI_NOT_FOUND          Could not find the entry that covers the range.
 | 
						|
  @retval EFI_INVALID_PARAMETER  Address not aligned.
 | 
						|
  @return EFI_SUCCESS            Pages successfully freed.
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
MmInternalFreePages (
 | 
						|
  IN EFI_PHYSICAL_ADDRESS  Memory,
 | 
						|
  IN UINTN                 NumberOfPages
 | 
						|
  )
 | 
						|
{
 | 
						|
  LIST_ENTRY      *Node;
 | 
						|
  FREE_PAGE_LIST  *Pages;
 | 
						|
 | 
						|
  if ((Memory & EFI_PAGE_MASK) != 0) {
 | 
						|
    return EFI_INVALID_PARAMETER;
 | 
						|
  }
 | 
						|
 | 
						|
  Pages = NULL;
 | 
						|
  Node  = mMmMemoryMap.ForwardLink;
 | 
						|
  while (Node != &mMmMemoryMap) {
 | 
						|
    Pages = BASE_CR (Node, FREE_PAGE_LIST, Link);
 | 
						|
    if (Memory < (UINTN)Pages) {
 | 
						|
      break;
 | 
						|
    }
 | 
						|
 | 
						|
    Node = Node->ForwardLink;
 | 
						|
  }
 | 
						|
 | 
						|
  if ((Node != &mMmMemoryMap) &&
 | 
						|
      (Memory + EFI_PAGES_TO_SIZE (NumberOfPages) > (UINTN)Pages))
 | 
						|
  {
 | 
						|
    return EFI_INVALID_PARAMETER;
 | 
						|
  }
 | 
						|
 | 
						|
  if (Node->BackLink != &mMmMemoryMap) {
 | 
						|
    Pages = BASE_CR (Node->BackLink, FREE_PAGE_LIST, Link);
 | 
						|
    if ((UINTN)Pages + EFI_PAGES_TO_SIZE (Pages->NumberOfPages) > Memory) {
 | 
						|
      return EFI_INVALID_PARAMETER;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  Pages                = (FREE_PAGE_LIST *)(UINTN)Memory;
 | 
						|
  Pages->NumberOfPages = NumberOfPages;
 | 
						|
  InsertTailList (Node, &Pages->Link);
 | 
						|
 | 
						|
  if (Pages->Link.BackLink != &mMmMemoryMap) {
 | 
						|
    Pages = InternalMergeNodes (
 | 
						|
              BASE_CR (Pages->Link.BackLink, FREE_PAGE_LIST, Link)
 | 
						|
              );
 | 
						|
  }
 | 
						|
 | 
						|
  if (Node != &mMmMemoryMap) {
 | 
						|
    InternalMergeNodes (Pages);
 | 
						|
  }
 | 
						|
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Frees previous allocated pages.
 | 
						|
 | 
						|
  @param  Memory                 Base address of memory being freed.
 | 
						|
  @param  NumberOfPages          The number of pages to free.
 | 
						|
 | 
						|
  @retval EFI_NOT_FOUND          Could not find the entry that covers the range.
 | 
						|
  @retval EFI_INVALID_PARAMETER  Address not aligned.
 | 
						|
  @return EFI_SUCCESS            Pages successfully freed.
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
MmFreePages (
 | 
						|
  IN EFI_PHYSICAL_ADDRESS  Memory,
 | 
						|
  IN UINTN                 NumberOfPages
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS  Status;
 | 
						|
 | 
						|
  Status = MmInternalFreePages (Memory, NumberOfPages);
 | 
						|
  return Status;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Add free MMRAM region for use by memory service.
 | 
						|
 | 
						|
  @param  MemBase                Base address of memory region.
 | 
						|
  @param  MemLength              Length of the memory region.
 | 
						|
  @param  Type                   Memory type.
 | 
						|
  @param  Attributes             Memory region state.
 | 
						|
 | 
						|
**/
 | 
						|
VOID
 | 
						|
MmAddMemoryRegion (
 | 
						|
  IN  EFI_PHYSICAL_ADDRESS  MemBase,
 | 
						|
  IN  UINT64                MemLength,
 | 
						|
  IN  EFI_MEMORY_TYPE       Type,
 | 
						|
  IN  UINT64                Attributes
 | 
						|
  )
 | 
						|
{
 | 
						|
  UINTN  AlignedMemBase;
 | 
						|
 | 
						|
  //
 | 
						|
  // Do not add memory regions that is already allocated, needs testing, or needs ECC initialization
 | 
						|
  //
 | 
						|
  if ((Attributes & (EFI_ALLOCATED | EFI_NEEDS_TESTING | EFI_NEEDS_ECC_INITIALIZATION)) != 0) {
 | 
						|
    return;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Align range on an EFI_PAGE_SIZE boundary
 | 
						|
  //
 | 
						|
  AlignedMemBase = (UINTN)(MemBase + EFI_PAGE_MASK) & ~EFI_PAGE_MASK;
 | 
						|
  MemLength     -= AlignedMemBase - MemBase;
 | 
						|
  MmFreePages (AlignedMemBase, TRUNCATE_TO_PAGES ((UINTN)MemLength));
 | 
						|
}
 |