/** @file\r
UEFI Memory page management functions.\r
\r
-Copyright (c) 2007 - 2010, Intel Corporation. All rights reserved.<BR>\r
+Copyright (c) 2007 - 2014, Intel Corporation. All rights reserved.<BR>\r
This program and the accompanying materials\r
are licensed and made available under the terms and conditions of the BSD License\r
which accompanies this distribution. The full text of the license may be found at\r
UINTN InformationIndex;\r
BOOLEAN Special;\r
BOOLEAN Runtime;\r
-} EFI_MEMORY_TYPE_STAISTICS;\r
+} EFI_MEMORY_TYPE_STATISTICS;\r
\r
//\r
// MemoryMap - The current memory map\r
LIST_ENTRY mFreeMemoryMapEntryList = INITIALIZE_LIST_HEAD_VARIABLE (mFreeMemoryMapEntryList);\r
BOOLEAN mMemoryTypeInformationInitialized = FALSE;\r
\r
-EFI_MEMORY_TYPE_STAISTICS mMemoryTypeStatistics[EfiMaxMemoryType + 1] = {\r
+EFI_MEMORY_TYPE_STATISTICS mMemoryTypeStatistics[EfiMaxMemoryType + 1] = {\r
{ 0, MAX_ADDRESS, 0, 0, EfiMaxMemoryType, TRUE, FALSE }, // EfiReservedMemoryType\r
{ 0, MAX_ADDRESS, 0, 0, EfiMaxMemoryType, FALSE, FALSE }, // EfiLoaderCode\r
{ 0, MAX_ADDRESS, 0, 0, EfiMaxMemoryType, FALSE, FALSE }, // EfiLoaderData\r
ASSERT_LOCKED (&gMemoryLock);\r
\r
DEBUG ((DEBUG_PAGE, "AddRange: %lx-%lx to %d\n", Start, End, Type));\r
-\r
+ \r
+ //\r
+ // If memory of type EfiConventionalMemory is being added that includes the page \r
+ // starting at address 0, then zero the page starting at address 0. This has \r
+ // two benifits. It helps find NULL pointer bugs and it also maximizes \r
+ // compatibility with operating systems that may evaluate memory in this page \r
+ // for legacy data structures. If memory of any other type is added starting \r
+ // at address 0, then do not zero the page at address 0 because the page is being \r
+ // used for other purposes.\r
+ // \r
+ if (Type == EfiConventionalMemory && Start == 0 && (End >= EFI_PAGE_SIZE - 1)) {\r
+ SetMem ((VOID *)(UINTN)Start, EFI_PAGE_SIZE, 0);\r
+ }\r
+ \r
//\r
// Memory map being altered so updated key\r
//\r
// Make sure the memory type in the gMemoryTypeInformation[] array is valid\r
//\r
Type = (EFI_MEMORY_TYPE) (gMemoryTypeInformation[Index].Type);\r
- if (Type < 0 || Type > EfiMaxMemoryType) {\r
+ if ((UINT32)Type > EfiMaxMemoryType) {\r
continue;\r
}\r
if (gMemoryTypeInformation[Index].NumberOfPages != 0) {\r
// Make sure the memory type in the gMemoryTypeInformation[] array is valid\r
//\r
Type = (EFI_MEMORY_TYPE) (gMemoryTypeInformation[FreeIndex].Type);\r
- if (Type < 0 || Type > EfiMaxMemoryType) {\r
+ if ((UINT32)Type > EfiMaxMemoryType) {\r
continue;\r
}\r
\r
// Make sure the memory type in the gMemoryTypeInformation[] array is valid\r
//\r
Type = (EFI_MEMORY_TYPE) (gMemoryTypeInformation[Index].Type);\r
- if (Type < 0 || Type > EfiMaxMemoryType) {\r
+ if ((UINT32)Type > EfiMaxMemoryType) {\r
continue;\r
}\r
if (gMemoryTypeInformation[Index].NumberOfPages != 0) {\r
//\r
// Update counters for the number of pages allocated to each memory type\r
//\r
- if (Entry->Type >= 0 && Entry->Type < EfiMaxMemoryType) {\r
+ if ((UINT32)Entry->Type < EfiMaxMemoryType) {\r
if ((Start >= mMemoryTypeStatistics[Entry->Type].BaseAddress && Start <= mMemoryTypeStatistics[Entry->Type].MaximumAddress) ||\r
(Start >= mDefaultBaseAddress && Start <= mDefaultMaximumAddress) ) {\r
if (NumberOfPages > mMemoryTypeStatistics[Entry->Type].CurrentNumberOfPages) {\r
}\r
}\r
\r
- if (NewType >= 0 && NewType < EfiMaxMemoryType) {\r
+ if ((UINT32)NewType < EfiMaxMemoryType) {\r
if ((Start >= mMemoryTypeStatistics[NewType].BaseAddress && Start <= mMemoryTypeStatistics[NewType].MaximumAddress) ||\r
(Start >= mDefaultBaseAddress && Start <= mDefaultMaximumAddress) ) {\r
mMemoryTypeStatistics[NewType].CurrentNumberOfPages += NumberOfPages;\r
//\r
CoreAddRange (NewType, Start, RangeEnd, Attribute);\r
if (NewType == EfiConventionalMemory) {\r
- DEBUG_CLEAR_MEMORY ((VOID *)(UINTN) Start, (UINTN) (RangeEnd - Start + 1));\r
+ //\r
+ // Avoid calling DEBUG_CLEAR_MEMORY() for an address of 0 because this\r
+ // macro will ASSERT() if address is 0. Instead, CoreAddRange() guarantees\r
+ // that the page starting at address 0 is always filled with zeros.\r
+ //\r
+ if (Start == 0) {\r
+ if (RangeEnd > EFI_PAGE_SIZE) {\r
+ DEBUG_CLEAR_MEMORY ((VOID *)(UINTN) EFI_PAGE_SIZE, (UINTN) (RangeEnd - EFI_PAGE_SIZE + 1));\r
+ }\r
+ } else {\r
+ DEBUG_CLEAR_MEMORY ((VOID *)(UINTN) Start, (UINTN) (RangeEnd - Start + 1));\r
+ }\r
}\r
\r
//\r
//\r
// Set MaxAddress to a page boundary\r
//\r
- MaxAddress &= ~EFI_PAGE_MASK;\r
+ MaxAddress &= ~(UINT64)EFI_PAGE_MASK;\r
\r
//\r
// Set MaxAddress to end of the page\r
//\r
// Attempt to find free pages in the preferred bin based on the requested memory type\r
//\r
- if (NewType >= 0 && NewType < EfiMaxMemoryType && MaxAddress >= mMemoryTypeStatistics[NewType].MaximumAddress) {\r
+ if ((UINT32)NewType < EfiMaxMemoryType && MaxAddress >= mMemoryTypeStatistics[NewType].MaximumAddress) {\r
Start = CoreFindFreePagesI (\r
mMemoryTypeStatistics[NewType].MaximumAddress, \r
mMemoryTypeStatistics[NewType].BaseAddress, \r
**/\r
EFI_STATUS\r
EFIAPI\r
-CoreAllocatePages (\r
+CoreInternalAllocatePages (\r
IN EFI_ALLOCATE_TYPE Type,\r
IN EFI_MEMORY_TYPE MemoryType,\r
IN UINTN NumberOfPages,\r
UINT64 MaxAddress;\r
UINTN Alignment;\r
\r
- if (Type < AllocateAnyPages || Type >= (UINTN) MaxAllocateType) {\r
+ if ((UINT32)Type >= MaxAllocateType) {\r
return EFI_INVALID_PARAMETER;\r
}\r
\r
return EFI_INVALID_PARAMETER;\r
}\r
\r
+ if (Memory == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
Alignment = EFI_DEFAULT_PAGE_ALLOCATION_ALIGNMENT;\r
\r
if (MemoryType == EfiACPIReclaimMemory ||\r
return Status;\r
}\r
\r
+/**\r
+ Allocates pages from the memory map.\r
+\r
+ @param Type The type of allocation to perform\r
+ @param MemoryType The type of memory to turn the allocated pages\r
+ into\r
+ @param NumberOfPages The number of pages to allocate\r
+ @param Memory A pointer to receive the base allocated memory\r
+ address\r
+\r
+ @return Status. On success, Memory is filled in with the base address allocated\r
+ @retval EFI_INVALID_PARAMETER Parameters violate checking rules defined in\r
+ spec.\r
+ @retval EFI_NOT_FOUND Could not allocate pages match the requirement.\r
+ @retval EFI_OUT_OF_RESOURCES No enough pages to allocate.\r
+ @retval EFI_SUCCESS Pages successfully allocated.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+CoreAllocatePages (\r
+ IN EFI_ALLOCATE_TYPE Type,\r
+ IN EFI_MEMORY_TYPE MemoryType,\r
+ IN UINTN NumberOfPages,\r
+ OUT EFI_PHYSICAL_ADDRESS *Memory\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+\r
+ Status = CoreInternalAllocatePages (Type, MemoryType, NumberOfPages, Memory);\r
+ if (!EFI_ERROR (Status)) {\r
+ CoreUpdateProfile ((EFI_PHYSICAL_ADDRESS) (UINTN) RETURN_ADDRESS (0), MemoryProfileActionAllocatePages, MemoryType, EFI_PAGES_TO_SIZE (NumberOfPages), (VOID *) (UINTN) *Memory);\r
+ }\r
+ return Status;\r
+}\r
\r
/**\r
Frees previous allocated pages.\r
**/\r
EFI_STATUS\r
EFIAPI\r
-CoreFreePages (\r
+CoreInternalFreePages (\r
IN EFI_PHYSICAL_ADDRESS Memory,\r
IN UINTN NumberOfPages\r
)\r
return Status;\r
}\r
\r
+/**\r
+ Frees previous allocated pages.\r
+\r
+ @param Memory Base address of memory being freed\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
+ @return EFI_SUCCESS -Pages successfully freed.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+CoreFreePages (\r
+ IN EFI_PHYSICAL_ADDRESS Memory,\r
+ IN UINTN NumberOfPages\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+\r
+ Status = CoreInternalFreePages (Memory, NumberOfPages);\r
+ if (!EFI_ERROR (Status)) {\r
+ CoreUpdateProfile ((EFI_PHYSICAL_ADDRESS) (UINTN) RETURN_ADDRESS (0), MemoryProfileActionFreePages, 0, EFI_PAGES_TO_SIZE (NumberOfPages), (VOID *) (UINTN) Memory);\r
+ }\r
+ return Status;\r
+}\r
+\r
/**\r
This function checks to see if the last memory map descriptor in a memory map\r
can be merged with any of the other memory map descriptors in a memorymap.\r
}\r
}\r
MemoryMap->Attribute = Entry->Attribute;\r
- if (mMemoryTypeStatistics[MemoryMap->Type].Runtime) {\r
- MemoryMap->Attribute |= EFI_MEMORY_RUNTIME;\r
+ if (MemoryMap->Type < EfiMaxMemoryType) {\r
+ if (mMemoryTypeStatistics[MemoryMap->Type].Runtime) {\r
+ MemoryMap->Attribute |= EFI_MEMORY_RUNTIME;\r
+ }\r
}\r
\r
//\r
Status = EFI_SUCCESS;\r
\r
Done:\r
-\r
- CoreReleaseMemoryLock ();\r
-\r
- CoreReleaseGcdMemoryLock ();\r
-\r
//\r
// Update the map key finally\r
//\r
*MapKey = mMemoryMapKey;\r
}\r
\r
+ CoreReleaseMemoryLock ();\r
+\r
+ CoreReleaseGcdMemoryLock ();\r
+\r
*MemoryMapSize = BufferSize;\r
\r
return Status;\r