REF: https://bugzilla.tianocore.org/show_bug.cgi?id=3737 Apply uncrustify changes to .c/.h files in the MdeModulePkg 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: Liming Gao <gaoliming@byosoft.com.cn>
		
			
				
	
	
		
			1100 lines
		
	
	
		
			32 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			1100 lines
		
	
	
		
			32 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/** @file
 | 
						|
  SMM Memory page management functions.
 | 
						|
 | 
						|
  Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.<BR>
 | 
						|
  SPDX-License-Identifier: BSD-2-Clause-Patent
 | 
						|
 | 
						|
**/
 | 
						|
 | 
						|
#include "PiSmmCore.h"
 | 
						|
#include <Library/SmmServicesTableLib.h>
 | 
						|
 | 
						|
#define TRUNCATE_TO_PAGES(a)  ((a) >> EFI_PAGE_SHIFT)
 | 
						|
 | 
						|
LIST_ENTRY  mSmmMemoryMap = INITIALIZE_LIST_HEAD_VARIABLE (mSmmMemoryMap);
 | 
						|
 | 
						|
//
 | 
						|
// For GetMemoryMap()
 | 
						|
//
 | 
						|
 | 
						|
#define MEMORY_MAP_SIGNATURE  SIGNATURE_32('m','m','a','p')
 | 
						|
typedef struct {
 | 
						|
  UINTN              Signature;
 | 
						|
  LIST_ENTRY         Link;
 | 
						|
 | 
						|
  BOOLEAN            FromStack;
 | 
						|
  EFI_MEMORY_TYPE    Type;
 | 
						|
  UINT64             Start;
 | 
						|
  UINT64             End;
 | 
						|
} MEMORY_MAP;
 | 
						|
 | 
						|
LIST_ENTRY  gMemoryMap = INITIALIZE_LIST_HEAD_VARIABLE (gMemoryMap);
 | 
						|
 | 
						|
#define MAX_MAP_DEPTH  6
 | 
						|
 | 
						|
///
 | 
						|
/// mMapDepth - depth of new descriptor stack
 | 
						|
///
 | 
						|
UINTN  mMapDepth = 0;
 | 
						|
///
 | 
						|
/// mMapStack - space to use as temp storage to build new map descriptors
 | 
						|
///
 | 
						|
MEMORY_MAP  mMapStack[MAX_MAP_DEPTH];
 | 
						|
UINTN       mFreeMapStack = 0;
 | 
						|
///
 | 
						|
/// This list maintain the free memory map list
 | 
						|
///
 | 
						|
LIST_ENTRY  mFreeMemoryMapEntryList = INITIALIZE_LIST_HEAD_VARIABLE (mFreeMemoryMapEntryList);
 | 
						|
 | 
						|
/**
 | 
						|
  Allocates pages from the memory map.
 | 
						|
 | 
						|
  @param[in]   Type                   The type of allocation to perform.
 | 
						|
  @param[in]   MemoryType             The type of memory to turn the allocated pages
 | 
						|
                                      into.
 | 
						|
  @param[in]   NumberOfPages          The number of pages to allocate.
 | 
						|
  @param[out]  Memory                 A pointer to receive the base allocated memory
 | 
						|
                                      address.
 | 
						|
  @param[in]   AddRegion              If this memory is new added region.
 | 
						|
  @param[in]   NeedGuard              Flag to indicate Guard page is needed
 | 
						|
                                      or not
 | 
						|
 | 
						|
  @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
 | 
						|
SmmInternalAllocatePagesEx (
 | 
						|
  IN  EFI_ALLOCATE_TYPE     Type,
 | 
						|
  IN  EFI_MEMORY_TYPE       MemoryType,
 | 
						|
  IN  UINTN                 NumberOfPages,
 | 
						|
  OUT EFI_PHYSICAL_ADDRESS  *Memory,
 | 
						|
  IN  BOOLEAN               AddRegion,
 | 
						|
  IN  BOOLEAN               NeedGuard
 | 
						|
  );
 | 
						|
 | 
						|
/**
 | 
						|
  Internal function.  Deque a descriptor entry from the mFreeMemoryMapEntryList.
 | 
						|
  If the list is emtry, then allocate a new page to refuel the list.
 | 
						|
  Please Note this algorithm to allocate the memory map descriptor has a property
 | 
						|
  that the memory allocated for memory entries always grows, and will never really be freed.
 | 
						|
 | 
						|
  @return The Memory map descriptor dequeued from the mFreeMemoryMapEntryList
 | 
						|
 | 
						|
**/
 | 
						|
MEMORY_MAP *
 | 
						|
AllocateMemoryMapEntry (
 | 
						|
  VOID
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_PHYSICAL_ADDRESS  Mem;
 | 
						|
  EFI_STATUS            Status;
 | 
						|
  MEMORY_MAP            *FreeDescriptorEntries;
 | 
						|
  MEMORY_MAP            *Entry;
 | 
						|
  UINTN                 Index;
 | 
						|
 | 
						|
  // DEBUG((DEBUG_INFO, "AllocateMemoryMapEntry\n"));
 | 
						|
 | 
						|
  if (IsListEmpty (&mFreeMemoryMapEntryList)) {
 | 
						|
    // DEBUG((DEBUG_INFO, "mFreeMemoryMapEntryList is empty\n"));
 | 
						|
    //
 | 
						|
    // The list is empty, to allocate one page to refuel the list
 | 
						|
    //
 | 
						|
    Status = SmmInternalAllocatePagesEx (
 | 
						|
               AllocateAnyPages,
 | 
						|
               EfiRuntimeServicesData,
 | 
						|
               EFI_SIZE_TO_PAGES (RUNTIME_PAGE_ALLOCATION_GRANULARITY),
 | 
						|
               &Mem,
 | 
						|
               TRUE,
 | 
						|
               FALSE
 | 
						|
               );
 | 
						|
    ASSERT_EFI_ERROR (Status);
 | 
						|
    if (!EFI_ERROR (Status)) {
 | 
						|
      FreeDescriptorEntries = (MEMORY_MAP *)(UINTN)Mem;
 | 
						|
      // DEBUG((DEBUG_INFO, "New FreeDescriptorEntries - 0x%x\n", FreeDescriptorEntries));
 | 
						|
      //
 | 
						|
      // Enqueue the free memory map entries into the list
 | 
						|
      //
 | 
						|
      for (Index = 0; Index < RUNTIME_PAGE_ALLOCATION_GRANULARITY / sizeof (MEMORY_MAP); Index++) {
 | 
						|
        FreeDescriptorEntries[Index].Signature = MEMORY_MAP_SIGNATURE;
 | 
						|
        InsertTailList (&mFreeMemoryMapEntryList, &FreeDescriptorEntries[Index].Link);
 | 
						|
      }
 | 
						|
    } else {
 | 
						|
      return NULL;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // dequeue the first descriptor from the list
 | 
						|
  //
 | 
						|
  Entry = CR (mFreeMemoryMapEntryList.ForwardLink, MEMORY_MAP, Link, MEMORY_MAP_SIGNATURE);
 | 
						|
  RemoveEntryList (&Entry->Link);
 | 
						|
 | 
						|
  return Entry;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Internal function.  Moves any memory descriptors that are on the
 | 
						|
  temporary descriptor stack to heap.
 | 
						|
 | 
						|
**/
 | 
						|
VOID
 | 
						|
CoreFreeMemoryMapStack (
 | 
						|
  VOID
 | 
						|
  )
 | 
						|
{
 | 
						|
  MEMORY_MAP  *Entry;
 | 
						|
 | 
						|
  //
 | 
						|
  // If already freeing the map stack, then return
 | 
						|
  //
 | 
						|
  if (mFreeMapStack != 0) {
 | 
						|
    ASSERT (FALSE);
 | 
						|
    return;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Move the temporary memory descriptor stack into pool
 | 
						|
  //
 | 
						|
  mFreeMapStack += 1;
 | 
						|
 | 
						|
  while (mMapDepth != 0) {
 | 
						|
    //
 | 
						|
    // Deque an memory map entry from mFreeMemoryMapEntryList
 | 
						|
    //
 | 
						|
    Entry = AllocateMemoryMapEntry ();
 | 
						|
    ASSERT (Entry);
 | 
						|
 | 
						|
    //
 | 
						|
    // Update to proper entry
 | 
						|
    //
 | 
						|
    mMapDepth -= 1;
 | 
						|
 | 
						|
    if (mMapStack[mMapDepth].Link.ForwardLink != NULL) {
 | 
						|
      CopyMem (Entry, &mMapStack[mMapDepth], sizeof (MEMORY_MAP));
 | 
						|
      Entry->FromStack = FALSE;
 | 
						|
 | 
						|
      //
 | 
						|
      // Move this entry to general memory
 | 
						|
      //
 | 
						|
      InsertTailList (&mMapStack[mMapDepth].Link, &Entry->Link);
 | 
						|
      RemoveEntryList (&mMapStack[mMapDepth].Link);
 | 
						|
      mMapStack[mMapDepth].Link.ForwardLink = NULL;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  mFreeMapStack -= 1;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Insert new entry from memory map.
 | 
						|
 | 
						|
  @param[in]  Link       The old memory map entry to be linked.
 | 
						|
  @param[in]  Start      The start address of new memory map entry.
 | 
						|
  @param[in]  End        The end address of new memory map entry.
 | 
						|
  @param[in]  Type       The type of new memory map entry.
 | 
						|
  @param[in]  Next       If new entry is inserted to the next of old entry.
 | 
						|
  @param[in]  AddRegion  If this memory is new added region.
 | 
						|
**/
 | 
						|
VOID
 | 
						|
InsertNewEntry (
 | 
						|
  IN LIST_ENTRY       *Link,
 | 
						|
  IN UINT64           Start,
 | 
						|
  IN UINT64           End,
 | 
						|
  IN EFI_MEMORY_TYPE  Type,
 | 
						|
  IN BOOLEAN          Next,
 | 
						|
  IN BOOLEAN          AddRegion
 | 
						|
  )
 | 
						|
{
 | 
						|
  MEMORY_MAP  *Entry;
 | 
						|
 | 
						|
  Entry      = &mMapStack[mMapDepth];
 | 
						|
  mMapDepth += 1;
 | 
						|
  ASSERT (mMapDepth < MAX_MAP_DEPTH);
 | 
						|
  Entry->FromStack = TRUE;
 | 
						|
 | 
						|
  Entry->Signature = MEMORY_MAP_SIGNATURE;
 | 
						|
  Entry->Type      = Type;
 | 
						|
  Entry->Start     = Start;
 | 
						|
  Entry->End       = End;
 | 
						|
  if (Next) {
 | 
						|
    InsertHeadList (Link, &Entry->Link);
 | 
						|
  } else {
 | 
						|
    InsertTailList (Link, &Entry->Link);
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Remove old entry from memory map.
 | 
						|
 | 
						|
  @param[in] Entry Memory map entry to be removed.
 | 
						|
**/
 | 
						|
VOID
 | 
						|
RemoveOldEntry (
 | 
						|
  IN MEMORY_MAP  *Entry
 | 
						|
  )
 | 
						|
{
 | 
						|
  RemoveEntryList (&Entry->Link);
 | 
						|
  Entry->Link.ForwardLink = NULL;
 | 
						|
 | 
						|
  if (!Entry->FromStack) {
 | 
						|
    InsertTailList (&mFreeMemoryMapEntryList, &Entry->Link);
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Update SMM memory map entry.
 | 
						|
 | 
						|
  @param[in]  Type                   The type of allocation to perform.
 | 
						|
  @param[in]  Memory                 The base of memory address.
 | 
						|
  @param[in]  NumberOfPages          The number of pages to allocate.
 | 
						|
  @param[in]  AddRegion              If this memory is new added region.
 | 
						|
**/
 | 
						|
VOID
 | 
						|
ConvertSmmMemoryMapEntry (
 | 
						|
  IN EFI_MEMORY_TYPE       Type,
 | 
						|
  IN EFI_PHYSICAL_ADDRESS  Memory,
 | 
						|
  IN UINTN                 NumberOfPages,
 | 
						|
  IN BOOLEAN               AddRegion
 | 
						|
  )
 | 
						|
{
 | 
						|
  LIST_ENTRY            *Link;
 | 
						|
  MEMORY_MAP            *Entry;
 | 
						|
  MEMORY_MAP            *NextEntry;
 | 
						|
  LIST_ENTRY            *NextLink;
 | 
						|
  MEMORY_MAP            *PreviousEntry;
 | 
						|
  LIST_ENTRY            *PreviousLink;
 | 
						|
  EFI_PHYSICAL_ADDRESS  Start;
 | 
						|
  EFI_PHYSICAL_ADDRESS  End;
 | 
						|
 | 
						|
  Start = Memory;
 | 
						|
  End   = Memory + EFI_PAGES_TO_SIZE (NumberOfPages) - 1;
 | 
						|
 | 
						|
  //
 | 
						|
  // Exclude memory region
 | 
						|
  //
 | 
						|
  Link = gMemoryMap.ForwardLink;
 | 
						|
  while (Link != &gMemoryMap) {
 | 
						|
    Entry = CR (Link, MEMORY_MAP, Link, MEMORY_MAP_SIGNATURE);
 | 
						|
    Link  = Link->ForwardLink;
 | 
						|
 | 
						|
    //
 | 
						|
    // ---------------------------------------------------
 | 
						|
    // |  +----------+   +------+   +------+   +------+  |
 | 
						|
    // ---|gMemoryMep|---|Entry1|---|Entry2|---|Entry3|---
 | 
						|
    //    +----------+ ^ +------+   +------+   +------+
 | 
						|
    //                 |
 | 
						|
    //              +------+
 | 
						|
    //              |EntryX|
 | 
						|
    //              +------+
 | 
						|
    //
 | 
						|
    if (Entry->Start > End) {
 | 
						|
      if ((Entry->Start == End + 1) && (Entry->Type == Type)) {
 | 
						|
        Entry->Start = Start;
 | 
						|
        return;
 | 
						|
      }
 | 
						|
 | 
						|
      InsertNewEntry (
 | 
						|
        &Entry->Link,
 | 
						|
        Start,
 | 
						|
        End,
 | 
						|
        Type,
 | 
						|
        FALSE,
 | 
						|
        AddRegion
 | 
						|
        );
 | 
						|
      return;
 | 
						|
    }
 | 
						|
 | 
						|
    if ((Entry->Start <= Start) && (Entry->End >= End)) {
 | 
						|
      if (Entry->Type != Type) {
 | 
						|
        if (Entry->Start < Start) {
 | 
						|
          //
 | 
						|
          // ---------------------------------------------------
 | 
						|
          // |  +----------+   +------+   +------+   +------+  |
 | 
						|
          // ---|gMemoryMep|---|Entry1|---|EntryX|---|Entry3|---
 | 
						|
          //    +----------+   +------+ ^ +------+   +------+
 | 
						|
          //                            |
 | 
						|
          //                         +------+
 | 
						|
          //                         |EntryA|
 | 
						|
          //                         +------+
 | 
						|
          //
 | 
						|
          InsertNewEntry (
 | 
						|
            &Entry->Link,
 | 
						|
            Entry->Start,
 | 
						|
            Start - 1,
 | 
						|
            Entry->Type,
 | 
						|
            FALSE,
 | 
						|
            AddRegion
 | 
						|
            );
 | 
						|
        }
 | 
						|
 | 
						|
        if (Entry->End > End) {
 | 
						|
          //
 | 
						|
          // ---------------------------------------------------
 | 
						|
          // |  +----------+   +------+   +------+   +------+  |
 | 
						|
          // ---|gMemoryMep|---|Entry1|---|EntryX|---|Entry3|---
 | 
						|
          //    +----------+   +------+   +------+ ^ +------+
 | 
						|
          //                                       |
 | 
						|
          //                                    +------+
 | 
						|
          //                                    |EntryZ|
 | 
						|
          //                                    +------+
 | 
						|
          //
 | 
						|
          InsertNewEntry (
 | 
						|
            &Entry->Link,
 | 
						|
            End + 1,
 | 
						|
            Entry->End,
 | 
						|
            Entry->Type,
 | 
						|
            TRUE,
 | 
						|
            AddRegion
 | 
						|
            );
 | 
						|
        }
 | 
						|
 | 
						|
        //
 | 
						|
        // Update this node
 | 
						|
        //
 | 
						|
        Entry->Start = Start;
 | 
						|
        Entry->End   = End;
 | 
						|
        Entry->Type  = Type;
 | 
						|
 | 
						|
        //
 | 
						|
        // Check adjacent
 | 
						|
        //
 | 
						|
        NextLink = Entry->Link.ForwardLink;
 | 
						|
        if (NextLink != &gMemoryMap) {
 | 
						|
          NextEntry = CR (NextLink, MEMORY_MAP, Link, MEMORY_MAP_SIGNATURE);
 | 
						|
          //
 | 
						|
          // ---------------------------------------------------
 | 
						|
          // |  +----------+   +------+   +-----------------+  |
 | 
						|
          // ---|gMemoryMep|---|Entry1|---|EntryX     Entry3|---
 | 
						|
          //    +----------+   +------+   +-----------------+
 | 
						|
          //
 | 
						|
          if ((Entry->Type == NextEntry->Type) && (Entry->End + 1 == NextEntry->Start)) {
 | 
						|
            Entry->End = NextEntry->End;
 | 
						|
            RemoveOldEntry (NextEntry);
 | 
						|
          }
 | 
						|
        }
 | 
						|
 | 
						|
        PreviousLink = Entry->Link.BackLink;
 | 
						|
        if (PreviousLink != &gMemoryMap) {
 | 
						|
          PreviousEntry = CR (PreviousLink, MEMORY_MAP, Link, MEMORY_MAP_SIGNATURE);
 | 
						|
          //
 | 
						|
          // ---------------------------------------------------
 | 
						|
          // |  +----------+   +-----------------+   +------+  |
 | 
						|
          // ---|gMemoryMep|---|Entry1     EntryX|---|Entry3|---
 | 
						|
          //    +----------+   +-----------------+   +------+
 | 
						|
          //
 | 
						|
          if ((PreviousEntry->Type == Entry->Type) && (PreviousEntry->End + 1 == Entry->Start)) {
 | 
						|
            PreviousEntry->End = Entry->End;
 | 
						|
            RemoveOldEntry (Entry);
 | 
						|
          }
 | 
						|
        }
 | 
						|
      }
 | 
						|
 | 
						|
      return;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // ---------------------------------------------------
 | 
						|
  // |  +----------+   +------+   +------+   +------+  |
 | 
						|
  // ---|gMemoryMep|---|Entry1|---|Entry2|---|Entry3|---
 | 
						|
  //    +----------+   +------+   +------+   +------+ ^
 | 
						|
  //                                                  |
 | 
						|
  //                                               +------+
 | 
						|
  //                                               |EntryX|
 | 
						|
  //                                               +------+
 | 
						|
  //
 | 
						|
  Link = gMemoryMap.BackLink;
 | 
						|
  if (Link != &gMemoryMap) {
 | 
						|
    Entry = CR (Link, MEMORY_MAP, Link, MEMORY_MAP_SIGNATURE);
 | 
						|
    if ((Entry->End + 1 == Start) && (Entry->Type == Type)) {
 | 
						|
      Entry->End = End;
 | 
						|
      return;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  InsertNewEntry (
 | 
						|
    &gMemoryMap,
 | 
						|
    Start,
 | 
						|
    End,
 | 
						|
    Type,
 | 
						|
    FALSE,
 | 
						|
    AddRegion
 | 
						|
    );
 | 
						|
  return;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Return the count of Smm memory map entry.
 | 
						|
 | 
						|
  @return The count of Smm memory map entry.
 | 
						|
**/
 | 
						|
UINTN
 | 
						|
GetSmmMemoryMapEntryCount (
 | 
						|
  VOID
 | 
						|
  )
 | 
						|
{
 | 
						|
  LIST_ENTRY  *Link;
 | 
						|
  UINTN       Count;
 | 
						|
 | 
						|
  Count = 0;
 | 
						|
  Link  = gMemoryMap.ForwardLink;
 | 
						|
  while (Link != &gMemoryMap) {
 | 
						|
    Link = Link->ForwardLink;
 | 
						|
    Count++;
 | 
						|
  }
 | 
						|
 | 
						|
  return Count;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  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[in]   Type                   The type of allocation to perform.
 | 
						|
  @param[in]   MemoryType             The type of memory to turn the allocated pages
 | 
						|
                                      into.
 | 
						|
  @param[in]   NumberOfPages          The number of pages to allocate.
 | 
						|
  @param[out]  Memory                 A pointer to receive the base allocated memory
 | 
						|
                                      address.
 | 
						|
  @param[in]   AddRegion              If this memory is new added region.
 | 
						|
  @param[in]   NeedGuard              Flag to indicate Guard page is needed
 | 
						|
                                      or not
 | 
						|
 | 
						|
  @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
 | 
						|
SmmInternalAllocatePagesEx (
 | 
						|
  IN  EFI_ALLOCATE_TYPE     Type,
 | 
						|
  IN  EFI_MEMORY_TYPE       MemoryType,
 | 
						|
  IN  UINTN                 NumberOfPages,
 | 
						|
  OUT EFI_PHYSICAL_ADDRESS  *Memory,
 | 
						|
  IN  BOOLEAN               AddRegion,
 | 
						|
  IN  BOOLEAN               NeedGuard
 | 
						|
  )
 | 
						|
{
 | 
						|
  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 SMM
 | 
						|
  //
 | 
						|
  RequestedAddress = (UINTN)*Memory;
 | 
						|
  switch (Type) {
 | 
						|
    case AllocateAnyPages:
 | 
						|
      RequestedAddress = (UINTN)(-1);
 | 
						|
    case AllocateMaxAddress:
 | 
						|
      if (NeedGuard) {
 | 
						|
        *Memory = InternalAllocMaxAddressWithGuard (
 | 
						|
                    &mSmmMemoryMap,
 | 
						|
                    NumberOfPages,
 | 
						|
                    RequestedAddress,
 | 
						|
                    MemoryType
 | 
						|
                    );
 | 
						|
        if (*Memory == (UINTN)-1) {
 | 
						|
          return EFI_OUT_OF_RESOURCES;
 | 
						|
        } else {
 | 
						|
          ASSERT (VerifyMemoryGuard (*Memory, NumberOfPages) == TRUE);
 | 
						|
          return EFI_SUCCESS;
 | 
						|
        }
 | 
						|
      }
 | 
						|
 | 
						|
      *Memory = InternalAllocMaxAddress (
 | 
						|
                  &mSmmMemoryMap,
 | 
						|
                  NumberOfPages,
 | 
						|
                  RequestedAddress
 | 
						|
                  );
 | 
						|
      if (*Memory == (UINTN)-1) {
 | 
						|
        return EFI_OUT_OF_RESOURCES;
 | 
						|
      }
 | 
						|
 | 
						|
      break;
 | 
						|
    case AllocateAddress:
 | 
						|
      *Memory = InternalAllocAddress (
 | 
						|
                  &mSmmMemoryMap,
 | 
						|
                  NumberOfPages,
 | 
						|
                  RequestedAddress
 | 
						|
                  );
 | 
						|
      if (*Memory != RequestedAddress) {
 | 
						|
        return EFI_NOT_FOUND;
 | 
						|
      }
 | 
						|
 | 
						|
      break;
 | 
						|
    default:
 | 
						|
      return EFI_INVALID_PARAMETER;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Update SmmMemoryMap here.
 | 
						|
  //
 | 
						|
  ConvertSmmMemoryMapEntry (MemoryType, *Memory, NumberOfPages, AddRegion);
 | 
						|
  if (!AddRegion) {
 | 
						|
    CoreFreeMemoryMapStack ();
 | 
						|
  }
 | 
						|
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Allocates pages from the memory map.
 | 
						|
 | 
						|
  @param[in]   Type                   The type of allocation to perform.
 | 
						|
  @param[in]   MemoryType             The type of memory to turn the allocated pages
 | 
						|
                                      into.
 | 
						|
  @param[in]   NumberOfPages          The number of pages to allocate.
 | 
						|
  @param[out]  Memory                 A pointer to receive the base allocated memory
 | 
						|
                                      address.
 | 
						|
  @param[in]   NeedGuard              Flag to indicate Guard page is needed
 | 
						|
                                      or not
 | 
						|
 | 
						|
  @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
 | 
						|
SmmInternalAllocatePages (
 | 
						|
  IN  EFI_ALLOCATE_TYPE     Type,
 | 
						|
  IN  EFI_MEMORY_TYPE       MemoryType,
 | 
						|
  IN  UINTN                 NumberOfPages,
 | 
						|
  OUT EFI_PHYSICAL_ADDRESS  *Memory,
 | 
						|
  IN  BOOLEAN               NeedGuard
 | 
						|
  )
 | 
						|
{
 | 
						|
  return SmmInternalAllocatePagesEx (
 | 
						|
           Type,
 | 
						|
           MemoryType,
 | 
						|
           NumberOfPages,
 | 
						|
           Memory,
 | 
						|
           FALSE,
 | 
						|
           NeedGuard
 | 
						|
           );
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  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
 | 
						|
SmmAllocatePages (
 | 
						|
  IN  EFI_ALLOCATE_TYPE     Type,
 | 
						|
  IN  EFI_MEMORY_TYPE       MemoryType,
 | 
						|
  IN  UINTN                 NumberOfPages,
 | 
						|
  OUT EFI_PHYSICAL_ADDRESS  *Memory
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS  Status;
 | 
						|
  BOOLEAN     NeedGuard;
 | 
						|
 | 
						|
  NeedGuard = IsPageTypeToGuard (MemoryType, Type);
 | 
						|
  Status    = SmmInternalAllocatePages (
 | 
						|
                Type,
 | 
						|
                MemoryType,
 | 
						|
                NumberOfPages,
 | 
						|
                Memory,
 | 
						|
                NeedGuard
 | 
						|
                );
 | 
						|
  if (!EFI_ERROR (Status)) {
 | 
						|
    SmmCoreUpdateProfile (
 | 
						|
      (EFI_PHYSICAL_ADDRESS)(UINTN)RETURN_ADDRESS (0),
 | 
						|
      MemoryProfileActionAllocatePages,
 | 
						|
      MemoryType,
 | 
						|
      EFI_PAGES_TO_SIZE (NumberOfPages),
 | 
						|
      (VOID *)(UINTN)*Memory,
 | 
						|
      NULL
 | 
						|
      );
 | 
						|
  }
 | 
						|
 | 
						|
  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[in]  Memory                 Base address of memory being freed.
 | 
						|
  @param[in]  NumberOfPages          The number of pages to free.
 | 
						|
  @param[in]  AddRegion              If this memory is new added region.
 | 
						|
 | 
						|
  @retval EFI_NOT_FOUND          Could not find the entry that covers the range.
 | 
						|
  @retval EFI_INVALID_PARAMETER  Address not aligned, Address is zero or NumberOfPages is zero.
 | 
						|
  @return EFI_SUCCESS            Pages successfully freed.
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
SmmInternalFreePagesEx (
 | 
						|
  IN EFI_PHYSICAL_ADDRESS  Memory,
 | 
						|
  IN UINTN                 NumberOfPages,
 | 
						|
  IN BOOLEAN               AddRegion
 | 
						|
  )
 | 
						|
{
 | 
						|
  LIST_ENTRY      *Node;
 | 
						|
  FREE_PAGE_LIST  *Pages;
 | 
						|
 | 
						|
  if (((Memory & EFI_PAGE_MASK) != 0) || (Memory == 0) || (NumberOfPages == 0)) {
 | 
						|
    return EFI_INVALID_PARAMETER;
 | 
						|
  }
 | 
						|
 | 
						|
  Pages = NULL;
 | 
						|
  Node  = mSmmMemoryMap.ForwardLink;
 | 
						|
  while (Node != &mSmmMemoryMap) {
 | 
						|
    Pages = BASE_CR (Node, FREE_PAGE_LIST, Link);
 | 
						|
    if (Memory < (UINTN)Pages) {
 | 
						|
      break;
 | 
						|
    }
 | 
						|
 | 
						|
    Node = Node->ForwardLink;
 | 
						|
  }
 | 
						|
 | 
						|
  if ((Node != &mSmmMemoryMap) &&
 | 
						|
      (Memory + EFI_PAGES_TO_SIZE (NumberOfPages) > (UINTN)Pages))
 | 
						|
  {
 | 
						|
    return EFI_INVALID_PARAMETER;
 | 
						|
  }
 | 
						|
 | 
						|
  if (Node->BackLink != &mSmmMemoryMap) {
 | 
						|
    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 != &mSmmMemoryMap) {
 | 
						|
    Pages = InternalMergeNodes (
 | 
						|
              BASE_CR (Pages->Link.BackLink, FREE_PAGE_LIST, Link)
 | 
						|
              );
 | 
						|
  }
 | 
						|
 | 
						|
  if (Node != &mSmmMemoryMap) {
 | 
						|
    InternalMergeNodes (Pages);
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Update SmmMemoryMap here.
 | 
						|
  //
 | 
						|
  ConvertSmmMemoryMapEntry (EfiConventionalMemory, Memory, NumberOfPages, AddRegion);
 | 
						|
  if (!AddRegion) {
 | 
						|
    CoreFreeMemoryMapStack ();
 | 
						|
  }
 | 
						|
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Frees previous allocated pages.
 | 
						|
 | 
						|
  @param[in]  Memory                 Base address of memory being freed.
 | 
						|
  @param[in]  NumberOfPages          The number of pages to free.
 | 
						|
  @param[in]  IsGuarded              Is the memory to free guarded or not.
 | 
						|
 | 
						|
  @retval EFI_NOT_FOUND          Could not find the entry that covers the range.
 | 
						|
  @retval EFI_INVALID_PARAMETER  Address not aligned, Address is zero or NumberOfPages is zero.
 | 
						|
  @return EFI_SUCCESS            Pages successfully freed.
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
SmmInternalFreePages (
 | 
						|
  IN EFI_PHYSICAL_ADDRESS  Memory,
 | 
						|
  IN UINTN                 NumberOfPages,
 | 
						|
  IN BOOLEAN               IsGuarded
 | 
						|
  )
 | 
						|
{
 | 
						|
  if (IsGuarded) {
 | 
						|
    return SmmInternalFreePagesExWithGuard (Memory, NumberOfPages, FALSE);
 | 
						|
  }
 | 
						|
 | 
						|
  return SmmInternalFreePagesEx (Memory, NumberOfPages, FALSE);
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Check whether the input range is in memory map.
 | 
						|
 | 
						|
  @param  Memory                 Base address of memory being inputed.
 | 
						|
  @param  NumberOfPages          The number of pages.
 | 
						|
 | 
						|
  @retval TRUE   In memory map.
 | 
						|
  @retval FALSE  Not in memory map.
 | 
						|
 | 
						|
**/
 | 
						|
BOOLEAN
 | 
						|
InMemMap (
 | 
						|
  IN EFI_PHYSICAL_ADDRESS  Memory,
 | 
						|
  IN UINTN                 NumberOfPages
 | 
						|
  )
 | 
						|
{
 | 
						|
  LIST_ENTRY            *Link;
 | 
						|
  MEMORY_MAP            *Entry;
 | 
						|
  EFI_PHYSICAL_ADDRESS  Last;
 | 
						|
 | 
						|
  Last = Memory + EFI_PAGES_TO_SIZE (NumberOfPages) - 1;
 | 
						|
 | 
						|
  Link = gMemoryMap.ForwardLink;
 | 
						|
  while (Link != &gMemoryMap) {
 | 
						|
    Entry = CR (Link, MEMORY_MAP, Link, MEMORY_MAP_SIGNATURE);
 | 
						|
    Link  = Link->ForwardLink;
 | 
						|
 | 
						|
    if ((Entry->Start <= Memory) && (Entry->End >= Last)) {
 | 
						|
      return TRUE;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  return FALSE;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  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, Address is zero or NumberOfPages is zero.
 | 
						|
  @return EFI_SUCCESS            Pages successfully freed.
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
SmmFreePages (
 | 
						|
  IN EFI_PHYSICAL_ADDRESS  Memory,
 | 
						|
  IN UINTN                 NumberOfPages
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS  Status;
 | 
						|
  BOOLEAN     IsGuarded;
 | 
						|
 | 
						|
  if (!InMemMap (Memory, NumberOfPages)) {
 | 
						|
    return EFI_NOT_FOUND;
 | 
						|
  }
 | 
						|
 | 
						|
  IsGuarded = IsHeapGuardEnabled () && IsMemoryGuarded (Memory);
 | 
						|
  Status    = SmmInternalFreePages (Memory, NumberOfPages, IsGuarded);
 | 
						|
  if (!EFI_ERROR (Status)) {
 | 
						|
    SmmCoreUpdateProfile (
 | 
						|
      (EFI_PHYSICAL_ADDRESS)(UINTN)RETURN_ADDRESS (0),
 | 
						|
      MemoryProfileActionFreePages,
 | 
						|
      EfiMaxMemoryType,
 | 
						|
      EFI_PAGES_TO_SIZE (NumberOfPages),
 | 
						|
      (VOID *)(UINTN)Memory,
 | 
						|
      NULL
 | 
						|
      );
 | 
						|
  }
 | 
						|
 | 
						|
  return Status;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Add free SMRAM 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
 | 
						|
SmmAddMemoryRegion (
 | 
						|
  IN  EFI_PHYSICAL_ADDRESS  MemBase,
 | 
						|
  IN  UINT64                MemLength,
 | 
						|
  IN  EFI_MEMORY_TYPE       Type,
 | 
						|
  IN  UINT64                Attributes
 | 
						|
  )
 | 
						|
{
 | 
						|
  UINTN  AlignedMemBase;
 | 
						|
 | 
						|
  //
 | 
						|
  // Add EfiRuntimeServicesData for memory regions that is already allocated, needs testing, or needs ECC initialization
 | 
						|
  //
 | 
						|
  if ((Attributes & (EFI_ALLOCATED | EFI_NEEDS_TESTING | EFI_NEEDS_ECC_INITIALIZATION)) != 0) {
 | 
						|
    Type = EfiRuntimeServicesData;
 | 
						|
  } else {
 | 
						|
    Type = EfiConventionalMemory;
 | 
						|
  }
 | 
						|
 | 
						|
  DEBUG ((DEBUG_INFO, "SmmAddMemoryRegion\n"));
 | 
						|
  DEBUG ((DEBUG_INFO, "  MemBase    - 0x%lx\n", MemBase));
 | 
						|
  DEBUG ((DEBUG_INFO, "  MemLength  - 0x%lx\n", MemLength));
 | 
						|
  DEBUG ((DEBUG_INFO, "  Type       - 0x%x\n", Type));
 | 
						|
  DEBUG ((DEBUG_INFO, "  Attributes - 0x%lx\n", Attributes));
 | 
						|
 | 
						|
  //
 | 
						|
  // Align range on an EFI_PAGE_SIZE boundary
 | 
						|
  //
 | 
						|
  AlignedMemBase = (UINTN)(MemBase + EFI_PAGE_MASK) & ~EFI_PAGE_MASK;
 | 
						|
  MemLength     -= AlignedMemBase - MemBase;
 | 
						|
  if (Type == EfiConventionalMemory) {
 | 
						|
    SmmInternalFreePagesEx (AlignedMemBase, TRUNCATE_TO_PAGES ((UINTN)MemLength), TRUE);
 | 
						|
  } else {
 | 
						|
    ConvertSmmMemoryMapEntry (EfiRuntimeServicesData, AlignedMemBase, TRUNCATE_TO_PAGES ((UINTN)MemLength), TRUE);
 | 
						|
  }
 | 
						|
 | 
						|
  CoreFreeMemoryMapStack ();
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  This function returns a copy of the current memory map. The map is an array of
 | 
						|
  memory descriptors, each of which describes a contiguous block of memory.
 | 
						|
 | 
						|
  @param[in, out]  MemoryMapSize          A pointer to the size, in bytes, of the
 | 
						|
                                          MemoryMap buffer. On input, this is the size of
 | 
						|
                                          the buffer allocated by the caller.  On output,
 | 
						|
                                          it is the size of the buffer returned by the
 | 
						|
                                          firmware  if the buffer was large enough, or the
 | 
						|
                                          size of the buffer needed  to contain the map if
 | 
						|
                                          the buffer was too small.
 | 
						|
  @param[in, out]  MemoryMap              A pointer to the buffer in which firmware places
 | 
						|
                                          the current memory map.
 | 
						|
  @param[out]      MapKey                 A pointer to the location in which firmware
 | 
						|
                                          returns the key for the current memory map.
 | 
						|
  @param[out]      DescriptorSize         A pointer to the location in which firmware
 | 
						|
                                          returns the size, in bytes, of an individual
 | 
						|
                                          EFI_MEMORY_DESCRIPTOR.
 | 
						|
  @param[out]      DescriptorVersion      A pointer to the location in which firmware
 | 
						|
                                          returns the version number associated with the
 | 
						|
                                          EFI_MEMORY_DESCRIPTOR.
 | 
						|
 | 
						|
  @retval EFI_SUCCESS            The memory map was returned in the MemoryMap
 | 
						|
                                 buffer.
 | 
						|
  @retval EFI_BUFFER_TOO_SMALL   The MemoryMap buffer was too small. The current
 | 
						|
                                 buffer size needed to hold the memory map is
 | 
						|
                                 returned in MemoryMapSize.
 | 
						|
  @retval EFI_INVALID_PARAMETER  One of the parameters has an invalid value.
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
SmmCoreGetMemoryMap (
 | 
						|
  IN OUT UINTN                  *MemoryMapSize,
 | 
						|
  IN OUT EFI_MEMORY_DESCRIPTOR  *MemoryMap,
 | 
						|
  OUT UINTN                     *MapKey,
 | 
						|
  OUT UINTN                     *DescriptorSize,
 | 
						|
  OUT UINT32                    *DescriptorVersion
 | 
						|
  )
 | 
						|
{
 | 
						|
  UINTN       Count;
 | 
						|
  LIST_ENTRY  *Link;
 | 
						|
  MEMORY_MAP  *Entry;
 | 
						|
  UINTN       Size;
 | 
						|
  UINTN       BufferSize;
 | 
						|
 | 
						|
  Size = sizeof (EFI_MEMORY_DESCRIPTOR);
 | 
						|
 | 
						|
  //
 | 
						|
  // Make sure Size != sizeof(EFI_MEMORY_DESCRIPTOR). This will
 | 
						|
  // prevent people from having pointer math bugs in their code.
 | 
						|
  // now you have to use *DescriptorSize to make things work.
 | 
						|
  //
 | 
						|
  Size += sizeof (UINT64) - (Size % sizeof (UINT64));
 | 
						|
 | 
						|
  if (DescriptorSize != NULL) {
 | 
						|
    *DescriptorSize = Size;
 | 
						|
  }
 | 
						|
 | 
						|
  if (DescriptorVersion != NULL) {
 | 
						|
    *DescriptorVersion = EFI_MEMORY_DESCRIPTOR_VERSION;
 | 
						|
  }
 | 
						|
 | 
						|
  Count      = GetSmmMemoryMapEntryCount ();
 | 
						|
  BufferSize = Size * Count;
 | 
						|
  if (*MemoryMapSize < BufferSize) {
 | 
						|
    *MemoryMapSize = BufferSize;
 | 
						|
    return EFI_BUFFER_TOO_SMALL;
 | 
						|
  }
 | 
						|
 | 
						|
  *MemoryMapSize = BufferSize;
 | 
						|
  if (MemoryMap == NULL) {
 | 
						|
    return EFI_INVALID_PARAMETER;
 | 
						|
  }
 | 
						|
 | 
						|
  ZeroMem (MemoryMap, BufferSize);
 | 
						|
  Link = gMemoryMap.ForwardLink;
 | 
						|
  while (Link != &gMemoryMap) {
 | 
						|
    Entry = CR (Link, MEMORY_MAP, Link, MEMORY_MAP_SIGNATURE);
 | 
						|
    Link  = Link->ForwardLink;
 | 
						|
 | 
						|
    MemoryMap->Type          = Entry->Type;
 | 
						|
    MemoryMap->PhysicalStart = Entry->Start;
 | 
						|
    MemoryMap->NumberOfPages = RShiftU64 (Entry->End - Entry->Start + 1, EFI_PAGE_SHIFT);
 | 
						|
 | 
						|
    MemoryMap = NEXT_MEMORY_DESCRIPTOR (MemoryMap, Size);
 | 
						|
  }
 | 
						|
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 |