-/*++\r
+/** @file\r
+\r
+ UEFI Memory page management functions.\r
\r
-Copyright (c) 2007, Intel Corporation \r
+Copyright (c) 2007 - 2008, Intel Corporation \r
All rights reserved. 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
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
\r
-Module Name:\r
-\r
- page.c\r
-\r
-Abstract:\r
-\r
- EFI Memory page management\r
-\r
-\r
-Revision History\r
-\r
---*/\r
+**/\r
\r
#include <DxeMain.h>\r
\r
EFI_PHYSICAL_ADDRESS BaseAddress;\r
EFI_PHYSICAL_ADDRESS MaximumAddress;\r
UINT64 CurrentNumberOfPages;\r
+ UINT64 NumberOfPages;\r
UINTN InformationIndex;\r
+ BOOLEAN Special;\r
+ BOOLEAN Runtime;\r
} EFI_MEMORY_TYPE_STAISTICS;\r
\r
//\r
BOOLEAN mMemoryTypeInformationInitialized = FALSE;\r
\r
EFI_MEMORY_TYPE_STAISTICS mMemoryTypeStatistics[EfiMaxMemoryType + 1] = {\r
- { 0, EFI_MAX_ADDRESS, 0, EfiMaxMemoryType }, // EfiReservedMemoryType\r
- { 0, EFI_MAX_ADDRESS, 0, EfiMaxMemoryType }, // EfiLoaderCode\r
- { 0, EFI_MAX_ADDRESS, 0, EfiMaxMemoryType }, // EfiLoaderData\r
- { 0, EFI_MAX_ADDRESS, 0, EfiMaxMemoryType }, // EfiBootServicesCode\r
- { 0, EFI_MAX_ADDRESS, 0, EfiMaxMemoryType }, // EfiBootServicesData\r
- { 0, EFI_MAX_ADDRESS, 0, EfiMaxMemoryType }, // EfiRuntimeServicesCode\r
- { 0, EFI_MAX_ADDRESS, 0, EfiMaxMemoryType }, // EfiRuntimeServicesData\r
- { 0, EFI_MAX_ADDRESS, 0, EfiMaxMemoryType }, // EfiConventionalMemory\r
- { 0, EFI_MAX_ADDRESS, 0, EfiMaxMemoryType }, // EfiUnusableMemory\r
- { 0, EFI_MAX_ADDRESS, 0, EfiMaxMemoryType }, // EfiACPIReclaimMemory\r
- { 0, EFI_MAX_ADDRESS, 0, EfiMaxMemoryType }, // EfiACPIMemoryNVS\r
- { 0, EFI_MAX_ADDRESS, 0, EfiMaxMemoryType }, // EfiMemoryMappedIO\r
- { 0, EFI_MAX_ADDRESS, 0, EfiMaxMemoryType }, // EfiMemoryMappedIOPortSpace\r
- { 0, EFI_MAX_ADDRESS, 0, EfiMaxMemoryType }, // EfiPalCode\r
- { 0, EFI_MAX_ADDRESS, 0, EfiMaxMemoryType } // EfiMaxMemoryType\r
+ { 0, EFI_MAX_ADDRESS, 0, 0, EfiMaxMemoryType, TRUE, FALSE }, // EfiReservedMemoryType\r
+ { 0, EFI_MAX_ADDRESS, 0, 0, EfiMaxMemoryType, FALSE, FALSE }, // EfiLoaderCode\r
+ { 0, EFI_MAX_ADDRESS, 0, 0, EfiMaxMemoryType, FALSE, FALSE }, // EfiLoaderData\r
+ { 0, EFI_MAX_ADDRESS, 0, 0, EfiMaxMemoryType, FALSE, FALSE }, // EfiBootServicesCode\r
+ { 0, EFI_MAX_ADDRESS, 0, 0, EfiMaxMemoryType, FALSE, FALSE }, // EfiBootServicesData\r
+ { 0, EFI_MAX_ADDRESS, 0, 0, EfiMaxMemoryType, TRUE, TRUE }, // EfiRuntimeServicesCode\r
+ { 0, EFI_MAX_ADDRESS, 0, 0, EfiMaxMemoryType, TRUE, TRUE }, // EfiRuntimeServicesData\r
+ { 0, EFI_MAX_ADDRESS, 0, 0, EfiMaxMemoryType, FALSE, FALSE }, // EfiConventionalMemory\r
+ { 0, EFI_MAX_ADDRESS, 0, 0, EfiMaxMemoryType, FALSE, FALSE }, // EfiUnusableMemory\r
+ { 0, EFI_MAX_ADDRESS, 0, 0, EfiMaxMemoryType, TRUE, FALSE }, // EfiACPIReclaimMemory\r
+ { 0, EFI_MAX_ADDRESS, 0, 0, EfiMaxMemoryType, TRUE, FALSE }, // EfiACPIMemoryNVS\r
+ { 0, EFI_MAX_ADDRESS, 0, 0, EfiMaxMemoryType, FALSE, FALSE }, // EfiMemoryMappedIO\r
+ { 0, EFI_MAX_ADDRESS, 0, 0, EfiMaxMemoryType, FALSE, FALSE }, // EfiMemoryMappedIOPortSpace\r
+ { 0, EFI_MAX_ADDRESS, 0, 0, EfiMaxMemoryType, TRUE, TRUE }, // EfiPalCode\r
+ { 0, EFI_MAX_ADDRESS, 0, 0, EfiMaxMemoryType, FALSE, FALSE } // EfiMaxMemoryType\r
};\r
\r
EFI_PHYSICAL_ADDRESS mDefaultMaximumAddress = EFI_MAX_ADDRESS;\r
mMemoryTypeStatistics[Type].BaseAddress, \r
gMemoryTypeInformation[Index].NumberOfPages\r
);\r
+ mMemoryTypeStatistics[Type].NumberOfPages = gMemoryTypeInformation[Index].NumberOfPages;\r
gMemoryTypeInformation[Index].NumberOfPages = 0;\r
}\r
}\r
LIST_ENTRY *Link;\r
MEMORY_MAP *Entry; \r
EFI_GCD_MAP_ENTRY *GcdMapEntry; \r
+ EFI_MEMORY_TYPE Type;\r
\r
//\r
// Make sure the parameters are valid\r
//\r
// Build the map\r
//\r
- ZeroMem (MemoryMap, Size);\r
+ ZeroMem (MemoryMap, BufferSize);\r
for (Link = gMemoryMap.ForwardLink; Link != &gMemoryMap; Link = Link->ForwardLink) {\r
Entry = CR (Link, MEMORY_MAP, Link, MEMORY_MAP_SIGNATURE);\r
ASSERT (Entry->VirtualStart == 0);\r
\r
+ //\r
+ // Convert internal map into an EFI_MEMORY_DESCRIPTOR\r
+ //\r
MemoryMap->Type = Entry->Type;\r
MemoryMap->PhysicalStart = Entry->Start;\r
MemoryMap->VirtualStart = Entry->VirtualStart;\r
MemoryMap->NumberOfPages = RShiftU64 (Entry->End - Entry->Start + 1, EFI_PAGE_SHIFT);\r
- \r
- switch (Entry->Type) {\r
- case EfiRuntimeServicesCode:\r
- case EfiRuntimeServicesData:\r
- case EfiPalCode:\r
- MemoryMap->Attribute = Entry->Attribute | EFI_MEMORY_RUNTIME;\r
- break;\r
-\r
- default:\r
- MemoryMap->Attribute = Entry->Attribute;\r
- break;\r
+ //\r
+ // If the memory type is EfiConventionalMemory, then determine if the range is part of a\r
+ // memory type bin and needs to be converted to the same memory type as the rest of the \r
+ // memory type bin in order to minimize EFI Memory Map changes across reboots. This \r
+ // improves the chances for a successful S4 resume in the presence of minor page allocation\r
+ // differences across reboots.\r
+ //\r
+ if (MemoryMap->Type == EfiConventionalMemory) {\r
+ for (Type = (EFI_MEMORY_TYPE) 0; Type < EfiMaxMemoryType; Type++) {\r
+ if (mMemoryTypeStatistics[Type].Special &&\r
+ mMemoryTypeStatistics[Type].NumberOfPages > 0 &&\r
+ Entry->Start >= mMemoryTypeStatistics[Type].BaseAddress &&\r
+ Entry->End <= mMemoryTypeStatistics[Type].MaximumAddress ) {\r
+ MemoryMap->Type = Type;\r
+ }\r
+ }\r
+ }\r
+ MemoryMap->Attribute = Entry->Attribute;\r
+ if (mMemoryTypeStatistics[MemoryMap->Type].Runtime) {\r
+ MemoryMap->Attribute |= EFI_MEMORY_RUNTIME;\r
}\r
\r
MemoryMap = NextMemoryDescriptor (MemoryMap, Size);\r