+ if (mMapStack[mMapDepth].Link.ForwardLink != NULL) {\r
+\r
+ //\r
+ // Move this entry to general memory\r
+ //\r
+ RemoveEntryList (&mMapStack[mMapDepth].Link);\r
+ mMapStack[mMapDepth].Link.ForwardLink = NULL;\r
+\r
+ CopyMem (Entry , &mMapStack[mMapDepth], sizeof (MEMORY_MAP));\r
+ Entry->FromPages = TRUE;\r
+\r
+ //\r
+ // Find insertion location\r
+ //\r
+ for (Link2 = gMemoryMap.ForwardLink; Link2 != &gMemoryMap; Link2 = Link2->ForwardLink) {\r
+ Entry2 = CR (Link2, MEMORY_MAP, Link, MEMORY_MAP_SIGNATURE);\r
+ if (Entry2->FromPages && Entry2->Start > Entry->Start) {\r
+ break;\r
+ }\r
+ }\r
+\r
+ InsertTailList (Link2, &Entry->Link);\r
+\r
+ } else {\r
+ //\r
+ // This item of mMapStack[mMapDepth] has already been dequeued from gMemoryMap list,\r
+ // so here no need to move it to memory.\r
+ //\r
+ InsertTailList (&mFreeMemoryMapEntryList, &Entry->Link);\r
+ }\r
+ }\r
+\r
+ mFreeMapStack -= 1;\r
+}\r
+\r
+/**\r
+ Find untested but initialized memory regions in GCD map and convert them to be DXE allocatable.\r
+\r
+**/\r
+BOOLEAN\r
+PromoteMemoryResource (\r
+ VOID\r
+ )\r
+{\r
+ LIST_ENTRY *Link;\r
+ EFI_GCD_MAP_ENTRY *Entry;\r
+ BOOLEAN Promoted;\r
+\r
+ DEBUG ((DEBUG_PAGE, "Promote the memory resource\n"));\r
+\r
+ CoreAcquireGcdMemoryLock ();\r
+\r
+ Promoted = FALSE;\r
+ Link = mGcdMemorySpaceMap.ForwardLink;\r
+ while (Link != &mGcdMemorySpaceMap) {\r
+\r
+ Entry = CR (Link, EFI_GCD_MAP_ENTRY, Link, EFI_GCD_MAP_SIGNATURE);\r
+\r
+ if (Entry->GcdMemoryType == EfiGcdMemoryTypeReserved &&\r
+ Entry->EndAddress < MAX_ADDRESS &&\r
+ (Entry->Capabilities & (EFI_MEMORY_PRESENT | EFI_MEMORY_INITIALIZED | EFI_MEMORY_TESTED)) ==\r
+ (EFI_MEMORY_PRESENT | EFI_MEMORY_INITIALIZED)) {\r
+ //\r
+ // Update the GCD map\r
+ //\r
+ if ((Entry->Capabilities & EFI_MEMORY_MORE_RELIABLE) == EFI_MEMORY_MORE_RELIABLE) {\r
+ Entry->GcdMemoryType = EfiGcdMemoryTypeMoreReliable;\r
+ } else {\r
+ Entry->GcdMemoryType = EfiGcdMemoryTypeSystemMemory;\r
+ }\r
+ Entry->Capabilities |= EFI_MEMORY_TESTED;\r
+ Entry->ImageHandle = gDxeCoreImageHandle;\r
+ Entry->DeviceHandle = NULL;\r
+\r
+ //\r
+ // Add to allocable system memory resource\r
+ //\r
+\r
+ CoreAddRange (\r
+ EfiConventionalMemory,\r
+ Entry->BaseAddress,\r
+ Entry->EndAddress,\r
+ Entry->Capabilities & ~(EFI_MEMORY_PRESENT | EFI_MEMORY_INITIALIZED | EFI_MEMORY_TESTED | EFI_MEMORY_RUNTIME)\r
+ );\r
+ CoreFreeMemoryMapStack ();\r
+\r
+ Promoted = TRUE;\r
+ }\r
+\r
+ Link = Link->ForwardLink;\r
+ }\r
+\r
+ CoreReleaseGcdMemoryLock ();\r
+\r
+ return Promoted;\r
+}\r
+/**\r
+ This function try to allocate Runtime code & Boot time code memory range. If LMFA enabled, 2 patchable PCD \r
+ PcdLoadFixAddressRuntimeCodePageNumber & PcdLoadFixAddressBootTimeCodePageNumber which are set by tools will record the \r
+ size of boot time and runtime code.\r
+\r
+**/\r
+VOID\r
+CoreLoadingFixedAddressHook (\r
+ VOID\r
+ )\r
+{\r
+ UINT32 RuntimeCodePageNumber;\r
+ UINT32 BootTimeCodePageNumber;\r
+ EFI_PHYSICAL_ADDRESS RuntimeCodeBase;\r
+ EFI_PHYSICAL_ADDRESS BootTimeCodeBase;\r
+ EFI_STATUS Status;\r
+\r
+ //\r
+ // Make sure these 2 areas are not initialzied.\r
+ //\r
+ if (!gLoadFixedAddressCodeMemoryReady) { \r
+ RuntimeCodePageNumber = PcdGet32(PcdLoadFixAddressRuntimeCodePageNumber);\r
+ BootTimeCodePageNumber= PcdGet32(PcdLoadFixAddressBootTimeCodePageNumber);\r
+ RuntimeCodeBase = (EFI_PHYSICAL_ADDRESS)(gLoadModuleAtFixAddressConfigurationTable.DxeCodeTopAddress - EFI_PAGES_TO_SIZE (RuntimeCodePageNumber));\r
+ BootTimeCodeBase = (EFI_PHYSICAL_ADDRESS)(RuntimeCodeBase - EFI_PAGES_TO_SIZE (BootTimeCodePageNumber));\r
+ //\r
+ // Try to allocate runtime memory.\r
+ //\r
+ Status = CoreAllocatePages (\r
+ AllocateAddress,\r
+ EfiRuntimeServicesCode,\r
+ RuntimeCodePageNumber,\r
+ &RuntimeCodeBase\r
+ );\r
+ if (EFI_ERROR(Status)) {\r
+ //\r
+ // Runtime memory allocation failed \r
+ //\r
+ return;\r
+ }\r
+ //\r
+ // Try to allocate boot memory.\r
+ //\r
+ Status = CoreAllocatePages (\r
+ AllocateAddress,\r
+ EfiBootServicesCode,\r
+ BootTimeCodePageNumber,\r
+ &BootTimeCodeBase\r
+ );\r
+ if (EFI_ERROR(Status)) {\r
+ //\r
+ // boot memory allocation failed. Free Runtime code range and will try the allocation again when \r
+ // new memory range is installed.\r
+ //\r
+ CoreFreePages (\r
+ RuntimeCodeBase,\r
+ RuntimeCodePageNumber\r
+ );\r
+ return;\r
+ }\r
+ gLoadFixedAddressCodeMemoryReady = TRUE;\r
+ } \r
+ return;\r
+} \r
+\r
+/**\r
+ Called to initialize the memory map and add descriptors to\r
+ the current descriptor list.\r
+ The first descriptor that is added must be general usable\r
+ memory as the addition allocates heap.\r
+\r
+ @param Type The type of memory to add\r
+ @param Start The starting address in the memory range Must be\r
+ page aligned\r
+ @param NumberOfPages The number of pages in the range\r
+ @param Attribute Attributes of the memory to add\r
+\r
+ @return None. The range is added to the memory map\r
+\r
+**/\r
+VOID\r
+CoreAddMemoryDescriptor (\r
+ IN EFI_MEMORY_TYPE Type,\r
+ IN EFI_PHYSICAL_ADDRESS Start,\r
+ IN UINT64 NumberOfPages,\r
+ IN UINT64 Attribute\r
+ )\r
+{\r
+ EFI_PHYSICAL_ADDRESS End;\r
+ EFI_STATUS Status;\r
+ UINTN Index;\r
+ UINTN FreeIndex;\r
+ \r
+ if ((Start & EFI_PAGE_MASK) != 0) {\r
+ return;\r
+ }\r
+\r
+ if (Type >= EfiMaxMemoryType && Type < MEMORY_TYPE_OEM_RESERVED_MIN) {\r
+ return;\r
+ }\r
+ CoreAcquireMemoryLock ();\r
+ End = Start + LShiftU64 (NumberOfPages, EFI_PAGE_SHIFT) - 1;\r
+ CoreAddRange (Type, Start, End, Attribute);\r
+ CoreFreeMemoryMapStack ();\r
+ CoreReleaseMemoryLock ();\r
+\r
+ //\r
+ // If Loading Module At Fixed Address feature is enabled. try to allocate memory with Runtime code & Boot time code type\r
+ //\r
+ if (PcdGet64(PcdLoadModuleAtFixAddressEnable) != 0) {\r
+ CoreLoadingFixedAddressHook();\r
+ }\r
+ \r
+ //\r
+ // Check to see if the statistics for the different memory types have already been established\r
+ //\r
+ if (mMemoryTypeInformationInitialized) {\r
+ return;\r
+ }\r
+\r
+ \r
+ //\r
+ // Loop through each memory type in the order specified by the gMemoryTypeInformation[] array\r
+ //\r
+ for (Index = 0; gMemoryTypeInformation[Index].Type != EfiMaxMemoryType; Index++) {\r
+ //\r
+ // Make sure the memory type in the gMemoryTypeInformation[] array is valid\r
+ //\r
+ Type = (EFI_MEMORY_TYPE) (gMemoryTypeInformation[Index].Type);\r
+ if ((UINT32)Type > EfiMaxMemoryType) {\r
+ continue;\r
+ }\r
+ if (gMemoryTypeInformation[Index].NumberOfPages != 0) {\r
+ //\r
+ // Allocate pages for the current memory type from the top of available memory\r
+ //\r
+ Status = CoreAllocatePages (\r
+ AllocateAnyPages,\r
+ Type,\r
+ gMemoryTypeInformation[Index].NumberOfPages,\r
+ &mMemoryTypeStatistics[Type].BaseAddress\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ //\r
+ // If an error occurs allocating the pages for the current memory type, then\r
+ // free all the pages allocates for the previous memory types and return. This\r
+ // operation with be retied when/if more memory is added to the system\r
+ //\r
+ for (FreeIndex = 0; FreeIndex < Index; FreeIndex++) {\r
+ //\r
+ // Make sure the memory type in the gMemoryTypeInformation[] array is valid\r
+ //\r
+ Type = (EFI_MEMORY_TYPE) (gMemoryTypeInformation[FreeIndex].Type);\r
+ if ((UINT32)Type > EfiMaxMemoryType) {\r
+ continue;\r
+ }\r
+\r
+ if (gMemoryTypeInformation[FreeIndex].NumberOfPages != 0) {\r
+ CoreFreePages (\r
+ mMemoryTypeStatistics[Type].BaseAddress,\r
+ gMemoryTypeInformation[FreeIndex].NumberOfPages\r
+ );\r
+ mMemoryTypeStatistics[Type].BaseAddress = 0;\r
+ mMemoryTypeStatistics[Type].MaximumAddress = MAX_ADDRESS;\r
+ }\r
+ }\r
+ return;\r
+ }\r