X-Git-Url: https://git.proxmox.com/?p=mirror_edk2.git;a=blobdiff_plain;f=MdeModulePkg%2FCore%2FDxe%2FMem%2FPage.c;h=260a30a214c7117a148e61863c4657f6366a6c45;hp=f4ec48ff677bae01f4a1bb331d28bb7c00826143;hb=d4731a98a3a5ddc2fed73d2998884f2cbee44ba9;hpb=99730361ec4724c07f6898a59615a8d33166e62f diff --git a/MdeModulePkg/Core/Dxe/Mem/Page.c b/MdeModulePkg/Core/Dxe/Mem/Page.c index f4ec48ff67..260a30a214 100644 --- a/MdeModulePkg/Core/Dxe/Mem/Page.c +++ b/MdeModulePkg/Core/Dxe/Mem/Page.c @@ -1,7 +1,7 @@ /** @file UEFI Memory page management functions. -Copyright (c) 2007 - 2014, Intel Corporation. All rights reserved.
+Copyright (c) 2007 - 2016, Intel Corporation. All rights reserved.
This program and the accompanying materials are licensed and made available under the terms and conditions of the BSD License which accompanies this distribution. The full text of the license may be found at @@ -15,8 +15,6 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. #include "DxeMain.h" #include "Imem.h" -#define EFI_DEFAULT_PAGE_ALLOCATION_ALIGNMENT (EFI_PAGE_SIZE) - // // Entry for tracking the memory regions for each memory type to coalesce similar memory types // @@ -67,6 +65,7 @@ EFI_MEMORY_TYPE_STATISTICS mMemoryTypeStatistics[EfiMaxMemoryType + 1] = { { 0, MAX_ADDRESS, 0, 0, EfiMaxMemoryType, FALSE, FALSE }, // EfiMemoryMappedIO { 0, MAX_ADDRESS, 0, 0, EfiMaxMemoryType, FALSE, FALSE }, // EfiMemoryMappedIOPortSpace { 0, MAX_ADDRESS, 0, 0, EfiMaxMemoryType, TRUE, TRUE }, // EfiPalCode + { 0, MAX_ADDRESS, 0, 0, EfiMaxMemoryType, FALSE, FALSE }, // EfiPersistentMemory { 0, MAX_ADDRESS, 0, 0, EfiMaxMemoryType, FALSE, FALSE } // EfiMaxMemoryType }; @@ -88,6 +87,7 @@ EFI_MEMORY_TYPE_INFORMATION gMemoryTypeInformation[EfiMaxMemoryType + 1] = { { EfiMemoryMappedIO, 0 }, { EfiMemoryMappedIOPortSpace, 0 }, { EfiPalCode, 0 }, + { EfiPersistentMemory, 0 }, { EfiMaxMemoryType, 0 } }; // @@ -202,7 +202,7 @@ CoreAddRange ( // If we are in EFI 1.10 compatability mode no event groups will be // found and nothing will happen we we call this function. These events // will get signaled but since a lock is held around the call to this - // function the notificaiton events will only be called after this funciton + // function the notificaiton events will only be called after this function // returns and the lock is released. // CoreNotifySignalList (&gEfiEventMemoryMapChangeGuid); @@ -285,12 +285,14 @@ AllocateMemoryMapEntry ( // // The list is empty, to allocate one page to refuel the list // - FreeDescriptorEntries = CoreAllocatePoolPages (EfiBootServicesData, EFI_SIZE_TO_PAGES(DEFAULT_PAGE_ALLOCATION), DEFAULT_PAGE_ALLOCATION); - if(FreeDescriptorEntries != NULL) { + FreeDescriptorEntries = CoreAllocatePoolPages (EfiBootServicesData, + EFI_SIZE_TO_PAGES (DEFAULT_PAGE_ALLOCATION_GRANULARITY), + DEFAULT_PAGE_ALLOCATION_GRANULARITY); + if (FreeDescriptorEntries != NULL) { // // Enque the free memmory map entries into the list // - for (Index = 0; Index< DEFAULT_PAGE_ALLOCATION / sizeof(MEMORY_MAP); Index++) { + for (Index = 0; Index < DEFAULT_PAGE_ALLOCATION_GRANULARITY / sizeof(MEMORY_MAP); Index++) { FreeDescriptorEntries[Index].Signature = MEMORY_MAP_SIGNATURE; InsertTailList (&mFreeMemoryMapEntryList, &FreeDescriptorEntries[Index].Link); } @@ -414,7 +416,11 @@ PromoteMemoryResource ( // // Update the GCD map // - Entry->GcdMemoryType = EfiGcdMemoryTypeSystemMemory; + if ((Entry->Capabilities & EFI_MEMORY_MORE_RELIABLE) == EFI_MEMORY_MORE_RELIABLE) { + Entry->GcdMemoryType = EfiGcdMemoryTypeMoreReliable; + } else { + Entry->GcdMemoryType = EfiGcdMemoryTypeSystemMemory; + } Entry->Capabilities |= EFI_MEMORY_TESTED; Entry->ImageHandle = gDxeCoreImageHandle; Entry->DeviceHandle = NULL; @@ -538,7 +544,7 @@ CoreAddMemoryDescriptor ( return; } - if (Type >= EfiMaxMemoryType && Type <= 0x7fffffff) { + if (Type >= EfiMaxMemoryType && Type < MEMORY_TYPE_OEM_RESERVED_MIN) { return; } CoreAcquireMemoryLock (); @@ -547,6 +553,9 @@ CoreAddMemoryDescriptor ( CoreFreeMemoryMapStack (); CoreReleaseMemoryLock (); + ApplyMemoryProtectionPolicy (EfiMaxMemoryType, Type, Start, + LShiftU64 (NumberOfPages, EFI_PAGE_SHIFT)); + // // If Loading Module At Fixed Address feature is enabled. try to allocate memory with Runtime code & Boot time code type // @@ -719,7 +728,7 @@ CoreConvertPagesEx ( ASSERT_LOCKED (&gMemoryLock); ASSERT ( (ChangingType == FALSE) || (ChangingAttributes == FALSE) ); - if (NumberOfPages == 0 || ((Start & EFI_PAGE_MASK) != 0) || (Start > (Start + NumberOfBytes))) { + if (NumberOfPages == 0 || ((Start & EFI_PAGE_MASK) != 0) || (Start >= End)) { return EFI_INVALID_PARAMETER; } @@ -937,12 +946,6 @@ CoreConvertPages ( @param NumberOfPages The number of pages to convert @param NewAttributes The new attributes value for the range. - @retval EFI_INVALID_PARAMETER Invalid parameter - @retval EFI_NOT_FOUND Could not find a descriptor cover the specified - range or convertion not allowed. - @retval EFI_SUCCESS Successfully converts the memory range to the - specified attributes. - **/ VOID CoreUpdateMemoryAttributes ( @@ -1051,6 +1054,11 @@ CoreFindFreePagesI ( DescEnd = ((DescEnd + 1) & (~(Alignment - 1))) - 1; + // Skip if DescEnd is less than DescStart after alignment clipping + if (DescEnd < DescStart) { + continue; + } + // // Compute the number of bytes we can used from this // descriptor, and see it's enough to satisfy the request @@ -1196,6 +1204,8 @@ CoreInternalAllocatePages ( { EFI_STATUS Status; UINT64 Start; + UINT64 NumberOfBytes; + UINT64 End; UINT64 MaxAddress; UINTN Alignment; @@ -1203,8 +1213,8 @@ CoreInternalAllocatePages ( return EFI_INVALID_PARAMETER; } - if ((MemoryType >= EfiMaxMemoryType && MemoryType <= 0x7fffffff) || - MemoryType == EfiConventionalMemory) { + if ((MemoryType >= EfiMaxMemoryType && MemoryType < MEMORY_TYPE_OEM_RESERVED_MIN) || + (MemoryType == EfiConventionalMemory) || (MemoryType == EfiPersistentMemory)) { return EFI_INVALID_PARAMETER; } @@ -1212,14 +1222,14 @@ CoreInternalAllocatePages ( return EFI_INVALID_PARAMETER; } - Alignment = EFI_DEFAULT_PAGE_ALLOCATION_ALIGNMENT; + Alignment = DEFAULT_PAGE_ALLOCATION_GRANULARITY; if (MemoryType == EfiACPIReclaimMemory || MemoryType == EfiACPIMemoryNVS || MemoryType == EfiRuntimeServicesCode || MemoryType == EfiRuntimeServicesData) { - Alignment = EFI_ACPI_RUNTIME_PAGE_ALLOCATION_ALIGNMENT; + Alignment = RUNTIME_PAGE_ALLOCATION_GRANULARITY; } if (Type == AllocateAddress) { @@ -1241,6 +1251,30 @@ CoreInternalAllocatePages ( // MaxAddress = MAX_ADDRESS; + // + // Check for Type AllocateAddress, + // if NumberOfPages is 0 or + // if (NumberOfPages << EFI_PAGE_SHIFT) is above MAX_ADDRESS or + // if (Start + NumberOfBytes) rolls over 0 or + // if Start is above MAX_ADDRESS or + // if End is above MAX_ADDRESS, + // return EFI_NOT_FOUND. + // + if (Type == AllocateAddress) { + if ((NumberOfPages == 0) || + (NumberOfPages > RShiftU64 (MaxAddress, EFI_PAGE_SHIFT))) { + return EFI_NOT_FOUND; + } + NumberOfBytes = LShiftU64 (NumberOfPages, EFI_PAGE_SHIFT); + End = Start + NumberOfBytes - 1; + + if ((Start >= End) || + (Start > MaxAddress) || + (End > MaxAddress)) { + return EFI_NOT_FOUND; + } + } + if (Type == AllocateMaxAddress) { MaxAddress = Start; } @@ -1304,7 +1338,17 @@ CoreAllocatePages ( Status = CoreInternalAllocatePages (Type, MemoryType, NumberOfPages, Memory); if (!EFI_ERROR (Status)) { - CoreUpdateProfile ((EFI_PHYSICAL_ADDRESS) (UINTN) RETURN_ADDRESS (0), MemoryProfileActionAllocatePages, MemoryType, EFI_PAGES_TO_SIZE (NumberOfPages), (VOID *) (UINTN) *Memory); + CoreUpdateProfile ( + (EFI_PHYSICAL_ADDRESS) (UINTN) RETURN_ADDRESS (0), + MemoryProfileActionAllocatePages, + MemoryType, + EFI_PAGES_TO_SIZE (NumberOfPages), + (VOID *) (UINTN) *Memory, + NULL + ); + InstallMemoryAttributesTableOnMemoryAllocation (MemoryType); + ApplyMemoryProtectionPolicy (EfiConventionalMemory, MemoryType, *Memory, + EFI_PAGES_TO_SIZE (NumberOfPages)); } return Status; } @@ -1314,6 +1358,7 @@ CoreAllocatePages ( @param Memory Base address of memory being freed @param NumberOfPages The number of pages to free + @param MemoryType Pointer to memory type @retval EFI_NOT_FOUND Could not find the entry that covers the range @retval EFI_INVALID_PARAMETER Address not aligned @@ -1324,7 +1369,8 @@ EFI_STATUS EFIAPI CoreInternalFreePages ( IN EFI_PHYSICAL_ADDRESS Memory, - IN UINTN NumberOfPages + IN UINTN NumberOfPages, + OUT EFI_MEMORY_TYPE *MemoryType OPTIONAL ) { EFI_STATUS Status; @@ -1352,7 +1398,7 @@ CoreInternalFreePages ( goto Done; } - Alignment = EFI_DEFAULT_PAGE_ALLOCATION_ALIGNMENT; + Alignment = DEFAULT_PAGE_ALLOCATION_GRANULARITY; ASSERT (Entry != NULL); if (Entry->Type == EfiACPIReclaimMemory || @@ -1360,7 +1406,7 @@ CoreInternalFreePages ( Entry->Type == EfiRuntimeServicesCode || Entry->Type == EfiRuntimeServicesData) { - Alignment = EFI_ACPI_RUNTIME_PAGE_ALLOCATION_ALIGNMENT; + Alignment = RUNTIME_PAGE_ALLOCATION_GRANULARITY; } @@ -1372,6 +1418,10 @@ CoreInternalFreePages ( NumberOfPages += EFI_SIZE_TO_PAGES (Alignment) - 1; NumberOfPages &= ~(EFI_SIZE_TO_PAGES (Alignment) - 1); + if (MemoryType != NULL) { + *MemoryType = Entry->Type; + } + Status = CoreConvertPages (Memory, NumberOfPages, EfiConventionalMemory); if (EFI_ERROR (Status)) { @@ -1401,14 +1451,25 @@ CoreFreePages ( IN UINTN NumberOfPages ) { - EFI_STATUS Status; - - Status = CoreInternalFreePages (Memory, NumberOfPages); - if (!EFI_ERROR (Status)) { - CoreUpdateProfile ((EFI_PHYSICAL_ADDRESS) (UINTN) RETURN_ADDRESS (0), MemoryProfileActionFreePages, (EFI_MEMORY_TYPE) 0, EFI_PAGES_TO_SIZE (NumberOfPages), (VOID *) (UINTN) Memory); - } - return Status; -} + EFI_STATUS Status; + EFI_MEMORY_TYPE MemoryType; + + Status = CoreInternalFreePages (Memory, NumberOfPages, &MemoryType); + if (!EFI_ERROR (Status)) { + CoreUpdateProfile ( + (EFI_PHYSICAL_ADDRESS) (UINTN) RETURN_ADDRESS (0), + MemoryProfileActionFreePages, + MemoryType, + EFI_PAGES_TO_SIZE (NumberOfPages), + (VOID *) (UINTN) Memory, + NULL + ); + InstallMemoryAttributesTableOnMemoryAllocation (MemoryType); + ApplyMemoryProtectionPolicy (MemoryType, EfiConventionalMemory, Memory, + EFI_PAGES_TO_SIZE (NumberOfPages)); + } + return Status; +} /** This function checks to see if the last memory map descriptor in a memory map @@ -1534,10 +1595,11 @@ CoreGetMemoryMap ( EFI_STATUS Status; UINTN Size; UINTN BufferSize; - UINTN NumberOfRuntimeEntries; + UINTN NumberOfEntries; LIST_ENTRY *Link; MEMORY_MAP *Entry; EFI_GCD_MAP_ENTRY *GcdMapEntry; + EFI_GCD_MAP_ENTRY MergeGcdMapEntry; EFI_MEMORY_TYPE Type; EFI_MEMORY_DESCRIPTOR *MemoryMapStart; @@ -1551,16 +1613,17 @@ CoreGetMemoryMap ( CoreAcquireGcdMemoryLock (); // - // Count the number of Reserved and MMIO entries that are marked for runtime use + // Count the number of Reserved and runtime MMIO entries + // And, count the number of Persistent entries. // - NumberOfRuntimeEntries = 0; + NumberOfEntries = 0; for (Link = mGcdMemorySpaceMap.ForwardLink; Link != &mGcdMemorySpaceMap; Link = Link->ForwardLink) { GcdMapEntry = CR (Link, EFI_GCD_MAP_ENTRY, Link, EFI_GCD_MAP_SIGNATURE); - if ((GcdMapEntry->GcdMemoryType == EfiGcdMemoryTypeReserved) || - (GcdMapEntry->GcdMemoryType == EfiGcdMemoryTypeMemoryMappedIo)) { - if ((GcdMapEntry->Attributes & EFI_MEMORY_RUNTIME) == EFI_MEMORY_RUNTIME) { - NumberOfRuntimeEntries++; - } + if ((GcdMapEntry->GcdMemoryType == EfiGcdMemoryTypePersistentMemory) || + (GcdMapEntry->GcdMemoryType == EfiGcdMemoryTypeReserved) || + ((GcdMapEntry->GcdMemoryType == EfiGcdMemoryTypeMemoryMappedIo) && + ((GcdMapEntry->Attributes & EFI_MEMORY_RUNTIME) == EFI_MEMORY_RUNTIME))) { + NumberOfEntries ++; } } @@ -1586,7 +1649,7 @@ CoreGetMemoryMap ( // // Compute the buffer size needed to fit the entire map // - BufferSize = Size * NumberOfRuntimeEntries; + BufferSize = Size * NumberOfEntries; for (Link = gMemoryMap.ForwardLink; Link != &gMemoryMap; Link = Link->ForwardLink) { BufferSize += Size; } @@ -1648,36 +1711,98 @@ CoreGetMemoryMap ( MemoryMap = MergeMemoryMapDescriptor (MemoryMapStart, MemoryMap, Size); } - for (Link = mGcdMemorySpaceMap.ForwardLink; Link != &mGcdMemorySpaceMap; Link = Link->ForwardLink) { - GcdMapEntry = CR (Link, EFI_GCD_MAP_ENTRY, Link, EFI_GCD_MAP_SIGNATURE); - if ((GcdMapEntry->GcdMemoryType == EfiGcdMemoryTypeReserved) || - (GcdMapEntry->GcdMemoryType == EfiGcdMemoryTypeMemoryMappedIo)) { - if ((GcdMapEntry->Attributes & EFI_MEMORY_RUNTIME) == EFI_MEMORY_RUNTIME) { - // - // Create EFI_MEMORY_DESCRIPTOR for every Reserved and MMIO GCD entries - // that are marked for runtime use - // - MemoryMap->PhysicalStart = GcdMapEntry->BaseAddress; - MemoryMap->VirtualStart = 0; - MemoryMap->NumberOfPages = RShiftU64 ((GcdMapEntry->EndAddress - GcdMapEntry->BaseAddress + 1), EFI_PAGE_SHIFT); - MemoryMap->Attribute = GcdMapEntry->Attributes & ~EFI_MEMORY_PORT_IO; - - if (GcdMapEntry->GcdMemoryType == EfiGcdMemoryTypeReserved) { - MemoryMap->Type = EfiReservedMemoryType; - } else if (GcdMapEntry->GcdMemoryType == EfiGcdMemoryTypeMemoryMappedIo) { - if ((GcdMapEntry->Attributes & EFI_MEMORY_PORT_IO) == EFI_MEMORY_PORT_IO) { - MemoryMap->Type = EfiMemoryMappedIOPortSpace; - } else { - MemoryMap->Type = EfiMemoryMappedIO; - } - } + + ZeroMem (&MergeGcdMapEntry, sizeof (MergeGcdMapEntry)); + GcdMapEntry = NULL; + for (Link = mGcdMemorySpaceMap.ForwardLink; ; Link = Link->ForwardLink) { + if (Link != &mGcdMemorySpaceMap) { + // + // Merge adjacent same type and attribute GCD memory range + // + GcdMapEntry = CR (Link, EFI_GCD_MAP_ENTRY, Link, EFI_GCD_MAP_SIGNATURE); + + if ((MergeGcdMapEntry.Capabilities == GcdMapEntry->Capabilities) && + (MergeGcdMapEntry.Attributes == GcdMapEntry->Attributes) && + (MergeGcdMapEntry.GcdMemoryType == GcdMapEntry->GcdMemoryType) && + (MergeGcdMapEntry.GcdIoType == GcdMapEntry->GcdIoType)) { + MergeGcdMapEntry.EndAddress = GcdMapEntry->EndAddress; + continue; + } + } - // - // Check to see if the new Memory Map Descriptor can be merged with an - // existing descriptor if they are adjacent and have the same attributes - // - MemoryMap = MergeMemoryMapDescriptor (MemoryMapStart, MemoryMap, Size); + if ((MergeGcdMapEntry.GcdMemoryType == EfiGcdMemoryTypeReserved) || + ((MergeGcdMapEntry.GcdMemoryType == EfiGcdMemoryTypeMemoryMappedIo) && + ((MergeGcdMapEntry.Attributes & EFI_MEMORY_RUNTIME) == EFI_MEMORY_RUNTIME))) { + // + // Page Align GCD range is required. When it is converted to EFI_MEMORY_DESCRIPTOR, + // it will be recorded as page PhysicalStart and NumberOfPages. + // + ASSERT ((MergeGcdMapEntry.BaseAddress & EFI_PAGE_MASK) == 0); + ASSERT (((MergeGcdMapEntry.EndAddress - MergeGcdMapEntry.BaseAddress + 1) & EFI_PAGE_MASK) == 0); + + // + // Create EFI_MEMORY_DESCRIPTOR for every Reserved and runtime MMIO GCD entries + // + MemoryMap->PhysicalStart = MergeGcdMapEntry.BaseAddress; + MemoryMap->VirtualStart = 0; + MemoryMap->NumberOfPages = RShiftU64 ((MergeGcdMapEntry.EndAddress - MergeGcdMapEntry.BaseAddress + 1), EFI_PAGE_SHIFT); + MemoryMap->Attribute = (MergeGcdMapEntry.Attributes & ~EFI_MEMORY_PORT_IO) | + (MergeGcdMapEntry.Capabilities & (EFI_MEMORY_RP | EFI_MEMORY_WP | EFI_MEMORY_XP | EFI_MEMORY_RO | + EFI_MEMORY_UC | EFI_MEMORY_UCE | EFI_MEMORY_WC | EFI_MEMORY_WT | EFI_MEMORY_WB)); + + if (MergeGcdMapEntry.GcdMemoryType == EfiGcdMemoryTypeReserved) { + MemoryMap->Type = EfiReservedMemoryType; + } else if (MergeGcdMapEntry.GcdMemoryType == EfiGcdMemoryTypeMemoryMappedIo) { + if ((MergeGcdMapEntry.Attributes & EFI_MEMORY_PORT_IO) == EFI_MEMORY_PORT_IO) { + MemoryMap->Type = EfiMemoryMappedIOPortSpace; + } else { + MemoryMap->Type = EfiMemoryMappedIO; + } } + + // + // Check to see if the new Memory Map Descriptor can be merged with an + // existing descriptor if they are adjacent and have the same attributes + // + MemoryMap = MergeMemoryMapDescriptor (MemoryMapStart, MemoryMap, Size); + } + + if (MergeGcdMapEntry.GcdMemoryType == EfiGcdMemoryTypePersistentMemory) { + // + // Page Align GCD range is required. When it is converted to EFI_MEMORY_DESCRIPTOR, + // it will be recorded as page PhysicalStart and NumberOfPages. + // + ASSERT ((MergeGcdMapEntry.BaseAddress & EFI_PAGE_MASK) == 0); + ASSERT (((MergeGcdMapEntry.EndAddress - MergeGcdMapEntry.BaseAddress + 1) & EFI_PAGE_MASK) == 0); + + // + // Create EFI_MEMORY_DESCRIPTOR for every Persistent GCD entries + // + MemoryMap->PhysicalStart = MergeGcdMapEntry.BaseAddress; + MemoryMap->VirtualStart = 0; + MemoryMap->NumberOfPages = RShiftU64 ((MergeGcdMapEntry.EndAddress - MergeGcdMapEntry.BaseAddress + 1), EFI_PAGE_SHIFT); + MemoryMap->Attribute = MergeGcdMapEntry.Attributes | EFI_MEMORY_NV | + (MergeGcdMapEntry.Capabilities & (EFI_MEMORY_RP | EFI_MEMORY_WP | EFI_MEMORY_XP | EFI_MEMORY_RO | + EFI_MEMORY_UC | EFI_MEMORY_UCE | EFI_MEMORY_WC | EFI_MEMORY_WT | EFI_MEMORY_WB)); + MemoryMap->Type = EfiPersistentMemory; + + // + // Check to see if the new Memory Map Descriptor can be merged with an + // existing descriptor if they are adjacent and have the same attributes + // + MemoryMap = MergeMemoryMapDescriptor (MemoryMapStart, MemoryMap, Size); + } + if (Link == &mGcdMemorySpaceMap) { + // + // break loop when arrive at head. + // + break; + } + if (GcdMapEntry != NULL) { + // + // Copy new GCD map entry for the following GCD range merge + // + CopyMem (&MergeGcdMapEntry, GcdMapEntry, sizeof (MergeGcdMapEntry)); } } @@ -1796,21 +1921,20 @@ CoreTerminateMemoryMap ( for (Link = gMemoryMap.ForwardLink; Link != &gMemoryMap; Link = Link->ForwardLink) { Entry = CR(Link, MEMORY_MAP, Link, MEMORY_MAP_SIGNATURE); - if ((Entry->Attribute & EFI_MEMORY_RUNTIME) != 0) { - if (Entry->Type == EfiACPIReclaimMemory || Entry->Type == EfiACPIMemoryNVS) { - DEBUG((DEBUG_ERROR | DEBUG_PAGE, "ExitBootServices: ACPI memory entry has RUNTIME attribute set.\n")); - Status = EFI_INVALID_PARAMETER; - goto Done; - } - if ((Entry->Start & (EFI_ACPI_RUNTIME_PAGE_ALLOCATION_ALIGNMENT - 1)) != 0) { - DEBUG((DEBUG_ERROR | DEBUG_PAGE, "ExitBootServices: A RUNTIME memory entry is not on a proper alignment.\n")); - Status = EFI_INVALID_PARAMETER; - goto Done; - } - if (((Entry->End + 1) & (EFI_ACPI_RUNTIME_PAGE_ALLOCATION_ALIGNMENT - 1)) != 0) { - DEBUG((DEBUG_ERROR | DEBUG_PAGE, "ExitBootServices: A RUNTIME memory entry is not on a proper alignment.\n")); - Status = EFI_INVALID_PARAMETER; - goto Done; + if (Entry->Type < EfiMaxMemoryType) { + if (mMemoryTypeStatistics[Entry->Type].Runtime) { + ASSERT (Entry->Type != EfiACPIReclaimMemory); + ASSERT (Entry->Type != EfiACPIMemoryNVS); + if ((Entry->Start & (RUNTIME_PAGE_ALLOCATION_GRANULARITY - 1)) != 0) { + DEBUG((DEBUG_ERROR | DEBUG_PAGE, "ExitBootServices: A RUNTIME memory entry is not on a proper alignment.\n")); + Status = EFI_INVALID_PARAMETER; + goto Done; + } + if (((Entry->End + 1) & (RUNTIME_PAGE_ALLOCATION_GRANULARITY - 1)) != 0) { + DEBUG((DEBUG_ERROR | DEBUG_PAGE, "ExitBootServices: A RUNTIME memory entry is not on a proper alignment.\n")); + Status = EFI_INVALID_PARAMETER; + goto Done; + } } } }