\r
\r
/**\r
- Internal function. Converts a memory range to the specified type.\r
- The range must exist in the memory map.\r
+ Internal function. Converts a memory range to the specified type or attributes.\r
+ The range must exist in the memory map. Either ChangingType or\r
+ ChangingAttributes must be set, but not both.\r
\r
@param Start The first address of the range Must be page\r
aligned\r
@param NumberOfPages The number of pages to convert\r
+ @param ChangingType Boolean indicating that type value should be changed\r
@param NewType The new type for the memory range\r
+ @param ChangingAttributes Boolean indicating that attributes value should be changed\r
+ @param NewAttributes The new attributes for the memory range\r
\r
@retval EFI_INVALID_PARAMETER Invalid parameter\r
@retval EFI_NOT_FOUND Could not find a descriptor cover the specified\r
\r
**/\r
EFI_STATUS\r
-CoreConvertPages (\r
+CoreConvertPagesEx (\r
IN UINT64 Start,\r
IN UINT64 NumberOfPages,\r
- IN EFI_MEMORY_TYPE NewType\r
+ IN BOOLEAN ChangingType,\r
+ IN EFI_MEMORY_TYPE NewType,\r
+ IN BOOLEAN ChangingAttributes,\r
+ IN UINT64 NewAttributes\r
)\r
{\r
\r
UINT64 End;\r
UINT64 RangeEnd;\r
UINT64 Attribute;\r
+ EFI_MEMORY_TYPE MemType;\r
LIST_ENTRY *Link;\r
MEMORY_MAP *Entry;\r
\r
ASSERT ((Start & EFI_PAGE_MASK) == 0);\r
ASSERT (End > Start) ;\r
ASSERT_LOCKED (&gMemoryLock);\r
+ ASSERT ( (ChangingType == FALSE) || (ChangingAttributes == FALSE) );\r
\r
if (NumberOfPages == 0 || ((Start & EFI_PAGE_MASK) != 0) || (Start > (Start + NumberOfBytes))) {\r
return EFI_INVALID_PARAMETER;\r
RangeEnd = Entry->End;\r
}\r
\r
- DEBUG ((DEBUG_PAGE, "ConvertRange: %lx-%lx to %d\n", Start, RangeEnd, NewType));\r
-\r
- //\r
- // Debug code - verify conversion is allowed\r
- //\r
- if (!(NewType == EfiConventionalMemory ? 1 : 0) ^ (Entry->Type == EfiConventionalMemory ? 1 : 0)) {\r
- DEBUG ((DEBUG_ERROR | DEBUG_PAGE, "ConvertPages: Incompatible memory types\n"));\r
- return EFI_NOT_FOUND;\r
+ if (ChangingType) {\r
+ DEBUG ((DEBUG_PAGE, "ConvertRange: %lx-%lx to type %d\n", Start, RangeEnd, NewType));\r
+ }\r
+ if (ChangingAttributes) {\r
+ DEBUG ((DEBUG_PAGE, "ConvertRange: %lx-%lx to attr %lx\n", Start, RangeEnd, NewAttributes));\r
}\r
\r
- //\r
- // Update counters for the number of pages allocated to each memory type\r
- //\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
- mMemoryTypeStatistics[Entry->Type].CurrentNumberOfPages = 0;\r
- } else {\r
- mMemoryTypeStatistics[Entry->Type].CurrentNumberOfPages -= NumberOfPages;\r
+ if (ChangingType) {\r
+ //\r
+ // Debug code - verify conversion is allowed\r
+ //\r
+ if (!(NewType == EfiConventionalMemory ? 1 : 0) ^ (Entry->Type == EfiConventionalMemory ? 1 : 0)) {\r
+ DEBUG ((DEBUG_ERROR | DEBUG_PAGE, "ConvertPages: Incompatible memory types\n"));\r
+ return EFI_NOT_FOUND;\r
+ }\r
+\r
+ //\r
+ // Update counters for the number of pages allocated to each memory type\r
+ //\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
+ mMemoryTypeStatistics[Entry->Type].CurrentNumberOfPages = 0;\r
+ } else {\r
+ mMemoryTypeStatistics[Entry->Type].CurrentNumberOfPages -= NumberOfPages;\r
+ }\r
}\r
}\r
- }\r
\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
- if (mMemoryTypeStatistics[NewType].CurrentNumberOfPages > gMemoryTypeInformation[mMemoryTypeStatistics[NewType].InformationIndex].NumberOfPages) {\r
- gMemoryTypeInformation[mMemoryTypeStatistics[NewType].InformationIndex].NumberOfPages = (UINT32)mMemoryTypeStatistics[NewType].CurrentNumberOfPages;\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
+ if (mMemoryTypeStatistics[NewType].CurrentNumberOfPages > gMemoryTypeInformation[mMemoryTypeStatistics[NewType].InformationIndex].NumberOfPages) {\r
+ gMemoryTypeInformation[mMemoryTypeStatistics[NewType].InformationIndex].NumberOfPages = (UINT32)mMemoryTypeStatistics[NewType].CurrentNumberOfPages;\r
+ }\r
}\r
}\r
}\r
\r
//\r
// The new range inherits the same Attribute as the Entry\r
- //it is being cut out of\r
+ // it is being cut out of unless attributes are being changed\r
//\r
- Attribute = Entry->Attribute;\r
+ if (ChangingType) {\r
+ Attribute = Entry->Attribute;\r
+ MemType = NewType;\r
+ } else {\r
+ Attribute = NewAttributes;\r
+ MemType = Entry->Type;\r
+ }\r
\r
//\r
// If the descriptor is empty, then remove it from the map\r
//\r
// Add our new range in\r
//\r
- CoreAddRange (NewType, Start, RangeEnd, Attribute);\r
- if (NewType == EfiConventionalMemory) {\r
+ CoreAddRange (MemType, Start, RangeEnd, Attribute);\r
+ if (ChangingType && (MemType == EfiConventionalMemory)) {\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
}\r
\r
\r
+/**\r
+ Internal function. Converts a memory range to the specified type.\r
+ The range must exist in the memory map.\r
+\r
+ @param Start The first address of the range Must be page\r
+ aligned\r
+ @param NumberOfPages The number of pages to convert\r
+ @param NewType The new type for the memory range\r
+\r
+ @retval EFI_INVALID_PARAMETER Invalid parameter\r
+ @retval EFI_NOT_FOUND Could not find a descriptor cover the specified\r
+ range or convertion not allowed.\r
+ @retval EFI_SUCCESS Successfully converts the memory range to the\r
+ specified type.\r
+\r
+**/\r
+EFI_STATUS\r
+CoreConvertPages (\r
+ IN UINT64 Start,\r
+ IN UINT64 NumberOfPages,\r
+ IN EFI_MEMORY_TYPE NewType\r
+ )\r
+{\r
+ return CoreConvertPagesEx(Start, NumberOfPages, TRUE, NewType, FALSE, 0);\r
+}\r
+\r
+\r
+/**\r
+ Internal function. Converts a memory range to use new attributes.\r
+\r
+ @param Start The first address of the range Must be page\r
+ aligned\r
+ @param NumberOfPages The number of pages to convert\r
+ @param NewAttributes The new attributes value for the range.\r
+\r
+ @retval EFI_INVALID_PARAMETER Invalid parameter\r
+ @retval EFI_NOT_FOUND Could not find a descriptor cover the specified\r
+ range or convertion not allowed.\r
+ @retval EFI_SUCCESS Successfully converts the memory range to the\r
+ specified attributes.\r
+\r
+**/\r
+VOID\r
+CoreUpdateMemoryAttributes (\r
+ IN EFI_PHYSICAL_ADDRESS Start,\r
+ IN UINT64 NumberOfPages,\r
+ IN UINT64 NewAttributes\r
+ )\r
+{\r
+ CoreAcquireMemoryLock ();\r
+\r
+ //\r
+ // Update the attributes to the new value\r
+ //\r
+ CoreConvertPagesEx(Start, NumberOfPages, FALSE, (EFI_MEMORY_TYPE)0, TRUE, NewAttributes);\r
+\r
+ CoreReleaseMemoryLock ();\r
+}\r
+\r
\r
/**\r
Internal function. Finds a consecutive free page range below\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
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