/** @file\r
SMM Memory page management functions.\r
\r
- Copyright (c) 2009 - 2016, Intel Corporation. All rights reserved.<BR>\r
- This program and the accompanying materials are licensed and made available\r
- under the terms and conditions of the BSD License which accompanies this\r
- distribution. The full text of the license may be found at\r
- http://opensource.org/licenses/bsd-license.php\r
-\r
- THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
- WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+ Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.<BR>\r
+ SPDX-License-Identifier: BSD-2-Clause-Patent\r
\r
**/\r
\r
@param[out] Memory A pointer to receive the base allocated memory\r
address.\r
@param[in] AddRegion If this memory is new added region.\r
+ @param[in] NeedGuard Flag to indicate Guard page is needed\r
+ or not\r
\r
@retval EFI_INVALID_PARAMETER Parameters violate checking rules defined in spec.\r
@retval EFI_NOT_FOUND Could not allocate pages match the requirement.\r
IN EFI_MEMORY_TYPE MemoryType,\r
IN UINTN NumberOfPages,\r
OUT EFI_PHYSICAL_ADDRESS *Memory,\r
- IN BOOLEAN AddRegion\r
+ IN BOOLEAN AddRegion,\r
+ IN BOOLEAN NeedGuard\r
);\r
\r
/**\r
Status = SmmInternalAllocatePagesEx (\r
AllocateAnyPages,\r
EfiRuntimeServicesData,\r
- EFI_SIZE_TO_PAGES(DEFAULT_PAGE_ALLOCATION),\r
+ EFI_SIZE_TO_PAGES (RUNTIME_PAGE_ALLOCATION_GRANULARITY),\r
&Mem,\r
- TRUE\r
+ TRUE,\r
+ FALSE\r
);\r
ASSERT_EFI_ERROR (Status);\r
if(!EFI_ERROR (Status)) {\r
//\r
// Enque the free memmory map entries into the list\r
//\r
- for (Index = 0; Index< DEFAULT_PAGE_ALLOCATION / sizeof(MEMORY_MAP); Index++) {\r
+ for (Index = 0; Index< RUNTIME_PAGE_ALLOCATION_GRANULARITY / sizeof(MEMORY_MAP); Index++) {\r
FreeDescriptorEntries[Index].Signature = MEMORY_MAP_SIGNATURE;\r
InsertTailList (&mFreeMemoryMapEntryList, &FreeDescriptorEntries[Index].Link);\r
}\r
)\r
{\r
RemoveEntryList (&Entry->Link);\r
+ Entry->Link.ForwardLink = NULL;\r
+\r
if (!Entry->FromStack) {\r
InsertTailList (&mFreeMemoryMapEntryList, &Entry->Link);\r
}\r
return Count;\r
}\r
\r
-/**\r
- Dump Smm memory map entry.\r
-**/\r
-VOID\r
-DumpSmmMemoryMapEntry (\r
- VOID\r
- )\r
-{\r
- LIST_ENTRY *Link;\r
- MEMORY_MAP *Entry;\r
- EFI_PHYSICAL_ADDRESS Last;\r
-\r
- Last = 0;\r
- DEBUG ((DEBUG_INFO, "DumpSmmMemoryMapEntry:\n"));\r
- Link = gMemoryMap.ForwardLink;\r
- while (Link != &gMemoryMap) {\r
- Entry = CR (Link, MEMORY_MAP, Link, MEMORY_MAP_SIGNATURE);\r
- Link = Link->ForwardLink;\r
-\r
- if ((Last != 0) && (Last != (UINT64)-1)) {\r
- if (Last + 1 != Entry->Start) {\r
- Last = (UINT64)-1;\r
- } else {\r
- Last = Entry->End;\r
- }\r
- } else if (Last == 0) {\r
- Last = Entry->End;\r
- }\r
-\r
- DEBUG ((DEBUG_INFO, "Entry (Link - 0x%x)\n", &Entry->Link));\r
- DEBUG ((DEBUG_INFO, " Signature - 0x%x\n", Entry->Signature));\r
- DEBUG ((DEBUG_INFO, " Link.ForwardLink - 0x%x\n", Entry->Link.ForwardLink));\r
- DEBUG ((DEBUG_INFO, " Link.BackLink - 0x%x\n", Entry->Link.BackLink));\r
- DEBUG ((DEBUG_INFO, " Type - 0x%x\n", Entry->Type));\r
- DEBUG ((DEBUG_INFO, " Start - 0x%016lx\n", Entry->Start));\r
- DEBUG ((DEBUG_INFO, " End - 0x%016lx\n", Entry->End));\r
- }\r
-\r
- ASSERT (Last != (UINT64)-1);\r
-}\r
-\r
-/**\r
- Dump Smm memory map.\r
-**/\r
-VOID\r
-DumpSmmMemoryMap (\r
- VOID\r
- )\r
-{\r
- LIST_ENTRY *Node;\r
- FREE_PAGE_LIST *Pages;\r
-\r
- DEBUG ((DEBUG_INFO, "DumpSmmMemoryMap\n"));\r
-\r
- Pages = NULL;\r
- Node = mSmmMemoryMap.ForwardLink;\r
- while (Node != &mSmmMemoryMap) {\r
- Pages = BASE_CR (Node, FREE_PAGE_LIST, Link);\r
- DEBUG ((DEBUG_INFO, "Pages - 0x%x\n", Pages));\r
- DEBUG ((DEBUG_INFO, "Pages->NumberOfPages - 0x%x\n", Pages->NumberOfPages));\r
- Node = Node->ForwardLink;\r
- }\r
-}\r
-\r
-/**\r
- Check if a Smm base~length is in Smm memory map.\r
-\r
- @param[in] Base The base address of Smm memory to be checked.\r
- @param[in] Length THe length of Smm memory to be checked.\r
-\r
- @retval TRUE Smm base~length is in smm memory map.\r
- @retval FALSE Smm base~length is in smm memory map.\r
-**/\r
-BOOLEAN\r
-SmmMemoryMapConsistencyCheckRange (\r
- IN EFI_PHYSICAL_ADDRESS Base,\r
- IN UINTN Length\r
- )\r
-{\r
- LIST_ENTRY *Link;\r
- MEMORY_MAP *Entry;\r
- BOOLEAN Result;\r
-\r
- Result = FALSE;\r
- Link = gMemoryMap.ForwardLink;\r
- while (Link != &gMemoryMap) {\r
- Entry = CR (Link, MEMORY_MAP, Link, MEMORY_MAP_SIGNATURE);\r
- Link = Link->ForwardLink;\r
-\r
- if (Entry->Type != EfiConventionalMemory) {\r
- continue;\r
- }\r
- if (Entry->Start == Base && Entry->End == Base + Length - 1) {\r
- Result = TRUE;\r
- break;\r
- }\r
- }\r
-\r
- return Result;\r
-}\r
-\r
-/**\r
- Check the consistency of Smm memory map.\r
-**/\r
-VOID\r
-SmmMemoryMapConsistencyCheck (\r
- VOID\r
- )\r
-{\r
- LIST_ENTRY *Node;\r
- FREE_PAGE_LIST *Pages;\r
- BOOLEAN Result;\r
\r
- Pages = NULL;\r
- Node = mSmmMemoryMap.ForwardLink;\r
- while (Node != &mSmmMemoryMap) {\r
- Pages = BASE_CR (Node, FREE_PAGE_LIST, Link);\r
- Result = SmmMemoryMapConsistencyCheckRange ((EFI_PHYSICAL_ADDRESS)(UINTN)Pages, (UINTN)EFI_PAGES_TO_SIZE(Pages->NumberOfPages));\r
- ASSERT (Result);\r
- Node = Node->ForwardLink;\r
- }\r
-}\r
\r
/**\r
Internal Function. Allocate n pages from given free page node.\r
@param[out] Memory A pointer to receive the base allocated memory\r
address.\r
@param[in] AddRegion If this memory is new added region.\r
+ @param[in] NeedGuard Flag to indicate Guard page is needed\r
+ or not\r
\r
@retval EFI_INVALID_PARAMETER Parameters violate checking rules defined in spec.\r
@retval EFI_NOT_FOUND Could not allocate pages match the requirement.\r
IN EFI_MEMORY_TYPE MemoryType,\r
IN UINTN NumberOfPages,\r
OUT EFI_PHYSICAL_ADDRESS *Memory,\r
- IN BOOLEAN AddRegion\r
+ IN BOOLEAN AddRegion,\r
+ IN BOOLEAN NeedGuard\r
)\r
{\r
UINTN RequestedAddress;\r
case AllocateAnyPages:\r
RequestedAddress = (UINTN)(-1);\r
case AllocateMaxAddress:\r
+ if (NeedGuard) {\r
+ *Memory = InternalAllocMaxAddressWithGuard (\r
+ &mSmmMemoryMap,\r
+ NumberOfPages,\r
+ RequestedAddress,\r
+ MemoryType\r
+ );\r
+ if (*Memory == (UINTN)-1) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ } else {\r
+ ASSERT (VerifyMemoryGuard (*Memory, NumberOfPages) == TRUE);\r
+ return EFI_SUCCESS;\r
+ }\r
+ }\r
+\r
*Memory = InternalAllocMaxAddress (\r
&mSmmMemoryMap,\r
NumberOfPages,\r
@param[in] NumberOfPages The number of pages to allocate.\r
@param[out] Memory A pointer to receive the base allocated memory\r
address.\r
+ @param[in] NeedGuard Flag to indicate Guard page is needed\r
+ or not\r
\r
@retval EFI_INVALID_PARAMETER Parameters violate checking rules defined in spec.\r
@retval EFI_NOT_FOUND Could not allocate pages match the requirement.\r
IN EFI_ALLOCATE_TYPE Type,\r
IN EFI_MEMORY_TYPE MemoryType,\r
IN UINTN NumberOfPages,\r
- OUT EFI_PHYSICAL_ADDRESS *Memory\r
+ OUT EFI_PHYSICAL_ADDRESS *Memory,\r
+ IN BOOLEAN NeedGuard\r
)\r
{\r
- return SmmInternalAllocatePagesEx (Type, MemoryType, NumberOfPages, Memory, FALSE);\r
+ return SmmInternalAllocatePagesEx (Type, MemoryType, NumberOfPages, Memory,\r
+ FALSE, NeedGuard);\r
}\r
\r
/**\r
)\r
{\r
EFI_STATUS Status;\r
+ BOOLEAN NeedGuard;\r
\r
- Status = SmmInternalAllocatePages (Type, MemoryType, NumberOfPages, Memory);\r
+ NeedGuard = IsPageTypeToGuard (MemoryType, Type);\r
+ Status = SmmInternalAllocatePages (Type, MemoryType, NumberOfPages, Memory,\r
+ NeedGuard);\r
if (!EFI_ERROR (Status)) {\r
SmmCoreUpdateProfile (\r
(EFI_PHYSICAL_ADDRESS) (UINTN) RETURN_ADDRESS (0),\r
@param[in] AddRegion If this memory is new added region.\r
\r
@retval EFI_NOT_FOUND Could not find the entry that covers the range.\r
- @retval EFI_INVALID_PARAMETER Address not aligned.\r
+ @retval EFI_INVALID_PARAMETER Address not aligned, Address is zero or NumberOfPages is zero.\r
@return EFI_SUCCESS Pages successfully freed.\r
\r
**/\r
LIST_ENTRY *Node;\r
FREE_PAGE_LIST *Pages;\r
\r
- if ((Memory & EFI_PAGE_MASK) != 0) {\r
+ if (((Memory & EFI_PAGE_MASK) != 0) || (Memory == 0) || (NumberOfPages == 0)) {\r
return EFI_INVALID_PARAMETER;\r
}\r
\r
\r
@param[in] Memory Base address of memory being freed.\r
@param[in] NumberOfPages The number of pages to free.\r
+ @param[in] IsGuarded Is the memory to free guarded or not.\r
\r
@retval EFI_NOT_FOUND Could not find the entry that covers the range.\r
- @retval EFI_INVALID_PARAMETER Address not aligned.\r
+ @retval EFI_INVALID_PARAMETER Address not aligned, Address is zero or NumberOfPages is zero.\r
@return EFI_SUCCESS Pages successfully freed.\r
\r
**/\r
EFIAPI\r
SmmInternalFreePages (\r
IN EFI_PHYSICAL_ADDRESS Memory,\r
- IN UINTN NumberOfPages\r
+ IN UINTN NumberOfPages,\r
+ IN BOOLEAN IsGuarded\r
)\r
{\r
+ if (IsGuarded) {\r
+ return SmmInternalFreePagesExWithGuard (Memory, NumberOfPages, FALSE);\r
+ }\r
return SmmInternalFreePagesEx (Memory, NumberOfPages, FALSE);\r
}\r
\r
+/**\r
+ Check whether the input range is in memory map.\r
+\r
+ @param Memory Base address of memory being inputed.\r
+ @param NumberOfPages The number of pages.\r
+\r
+ @retval TRUE In memory map.\r
+ @retval FALSE Not in memory map.\r
+\r
+**/\r
+BOOLEAN\r
+InMemMap (\r
+ IN EFI_PHYSICAL_ADDRESS Memory,\r
+ IN UINTN NumberOfPages\r
+ )\r
+{\r
+ LIST_ENTRY *Link;\r
+ MEMORY_MAP *Entry;\r
+ EFI_PHYSICAL_ADDRESS Last;\r
+\r
+ Last = Memory + EFI_PAGES_TO_SIZE (NumberOfPages) - 1;\r
+\r
+ Link = gMemoryMap.ForwardLink;\r
+ while (Link != &gMemoryMap) {\r
+ Entry = CR (Link, MEMORY_MAP, Link, MEMORY_MAP_SIGNATURE);\r
+ Link = Link->ForwardLink;\r
+\r
+ if ((Entry->Start <= Memory) && (Entry->End >= Last)) {\r
+ return TRUE;\r
+ }\r
+ }\r
+\r
+ return FALSE;\r
+}\r
+\r
/**\r
Frees previous allocated pages.\r
\r
@param NumberOfPages The number of pages to free.\r
\r
@retval EFI_NOT_FOUND Could not find the entry that covers the range.\r
- @retval EFI_INVALID_PARAMETER Address not aligned.\r
+ @retval EFI_INVALID_PARAMETER Address not aligned, Address is zero or NumberOfPages is zero.\r
@return EFI_SUCCESS Pages successfully freed.\r
\r
**/\r
)\r
{\r
EFI_STATUS Status;\r
+ BOOLEAN IsGuarded;\r
+\r
+ if (!InMemMap(Memory, NumberOfPages)) {\r
+ return EFI_NOT_FOUND;\r
+ }\r
\r
- Status = SmmInternalFreePages (Memory, NumberOfPages);\r
+ IsGuarded = IsHeapGuardEnabled () && IsMemoryGuarded (Memory);\r
+ Status = SmmInternalFreePages (Memory, NumberOfPages, IsGuarded);\r
if (!EFI_ERROR (Status)) {\r
SmmCoreUpdateProfile (\r
(EFI_PHYSICAL_ADDRESS) (UINTN) RETURN_ADDRESS (0),\r