-/** @file \r
+/** @file\r
+ The file contains the GCD related services in the EFI Boot Services Table.\r
+ The GCD services are used to manage the memory and I/O regions that\r
+ are accessible to the CPU that is executing the DXE core.\r
\r
- The file contains the GCD related services in the EFI Boot Services Table.\r
- The GCD services are used to manage the memory and I/O regions that \r
- are accessible to the CPU that is executing the DXE core.\r
+Copyright (c) 2006 - 2015, 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
+http://opensource.org/licenses/bsd-license.php\r
\r
-Copyright (c) 2006 - 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
-http://opensource.org/licenses/bsd-license.php \r
- \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
+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
**/\r
\r
-#include <DxeMain.h>\r
+#include "DxeMain.h"\r
+#include "Gcd.h"\r
\r
#define MINIMUM_INITIAL_MEMORY_SIZE 0x10000\r
\r
EFI_RESOURCE_ATTRIBUTE_READ_PROTECTED | \\r
EFI_RESOURCE_ATTRIBUTE_WRITE_PROTECTED | \\r
EFI_RESOURCE_ATTRIBUTE_EXECUTION_PROTECTED | \\r
+ EFI_RESOURCE_ATTRIBUTE_READ_ONLY_PROTECTED | \\r
EFI_RESOURCE_ATTRIBUTE_16_BIT_IO | \\r
EFI_RESOURCE_ATTRIBUTE_32_BIT_IO | \\r
- EFI_RESOURCE_ATTRIBUTE_64_BIT_IO ) \r
+ EFI_RESOURCE_ATTRIBUTE_64_BIT_IO | \\r
+ EFI_RESOURCE_ATTRIBUTE_PERSISTENT )\r
\r
#define TESTED_MEMORY_ATTRIBUTES (EFI_RESOURCE_ATTRIBUTE_PRESENT | \\r
EFI_RESOURCE_ATTRIBUTE_INITIALIZED | \\r
\r
EFI_GCD_MAP_ENTRY mGcdMemorySpaceMapEntryTemplate = {\r
EFI_GCD_MAP_SIGNATURE,\r
- { NULL, NULL },\r
+ {\r
+ NULL,\r
+ NULL\r
+ },\r
0,\r
0,\r
0,\r
\r
EFI_GCD_MAP_ENTRY mGcdIoSpaceMapEntryTemplate = {\r
EFI_GCD_MAP_SIGNATURE,\r
- { NULL, NULL },\r
+ {\r
+ NULL,\r
+ NULL\r
+ },\r
0,\r
0,\r
0,\r
};\r
\r
GCD_ATTRIBUTE_CONVERSION_ENTRY mAttributeConversionTable[] = {\r
- { EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE, EFI_MEMORY_UC, TRUE },\r
- { EFI_RESOURCE_ATTRIBUTE_UNCACHED_EXPORTED, EFI_MEMORY_UCE, TRUE }, \r
- { EFI_RESOURCE_ATTRIBUTE_WRITE_COMBINEABLE, EFI_MEMORY_WC, TRUE },\r
- { EFI_RESOURCE_ATTRIBUTE_WRITE_THROUGH_CACHEABLE, EFI_MEMORY_WT, TRUE },\r
- { EFI_RESOURCE_ATTRIBUTE_WRITE_BACK_CACHEABLE, EFI_MEMORY_WB, TRUE },\r
- { EFI_RESOURCE_ATTRIBUTE_READ_PROTECTED, EFI_MEMORY_RP, TRUE },\r
- { EFI_RESOURCE_ATTRIBUTE_WRITE_PROTECTED, EFI_MEMORY_WP, TRUE },\r
- { EFI_RESOURCE_ATTRIBUTE_EXECUTION_PROTECTED, EFI_MEMORY_XP, TRUE },\r
- { EFI_RESOURCE_ATTRIBUTE_PRESENT, EFI_MEMORY_PRESENT, FALSE },\r
- { EFI_RESOURCE_ATTRIBUTE_INITIALIZED, EFI_MEMORY_INITIALIZED, FALSE },\r
- { EFI_RESOURCE_ATTRIBUTE_TESTED, EFI_MEMORY_TESTED, FALSE },\r
- { 0, 0, FALSE }\r
+ { EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE, EFI_MEMORY_UC, TRUE },\r
+ { EFI_RESOURCE_ATTRIBUTE_UNCACHED_EXPORTED, EFI_MEMORY_UCE, TRUE },\r
+ { EFI_RESOURCE_ATTRIBUTE_WRITE_COMBINEABLE, EFI_MEMORY_WC, TRUE },\r
+ { EFI_RESOURCE_ATTRIBUTE_WRITE_THROUGH_CACHEABLE, EFI_MEMORY_WT, TRUE },\r
+ { EFI_RESOURCE_ATTRIBUTE_WRITE_BACK_CACHEABLE, EFI_MEMORY_WB, TRUE },\r
+ { EFI_RESOURCE_ATTRIBUTE_READ_PROTECTABLE, EFI_MEMORY_RP, TRUE },\r
+ { EFI_RESOURCE_ATTRIBUTE_WRITE_PROTECTABLE, EFI_MEMORY_WP, TRUE },\r
+ { EFI_RESOURCE_ATTRIBUTE_EXECUTION_PROTECTABLE, EFI_MEMORY_XP, TRUE },\r
+ { EFI_RESOURCE_ATTRIBUTE_READ_ONLY_PROTECTABLE, EFI_MEMORY_RO, TRUE },\r
+ { EFI_RESOURCE_ATTRIBUTE_PRESENT, EFI_MEMORY_PRESENT, FALSE },\r
+ { EFI_RESOURCE_ATTRIBUTE_INITIALIZED, EFI_MEMORY_INITIALIZED, FALSE },\r
+ { EFI_RESOURCE_ATTRIBUTE_TESTED, EFI_MEMORY_TESTED, FALSE },\r
+ { EFI_RESOURCE_ATTRIBUTE_PERSISTABLE, EFI_MEMORY_NV, TRUE },\r
+ { EFI_RESOURCE_ATTRIBUTE_MORE_RELIABLE, EFI_MEMORY_MORE_RELIABLE, TRUE },\r
+ { 0, 0, FALSE }\r
};\r
\r
+///\r
+/// Lookup table used to print GCD Memory Space Map\r
+///\r
+GLOBAL_REMOVE_IF_UNREFERENCED CONST CHAR8 *mGcdMemoryTypeNames[] = {\r
+ "NonExist ", // EfiGcdMemoryTypeNonExistent\r
+ "Reserved ", // EfiGcdMemoryTypeReserved\r
+ "SystemMem", // EfiGcdMemoryTypeSystemMemory\r
+ "MMIO ", // EfiGcdMemoryTypeMemoryMappedIo\r
+ "PersisMem", // EfiGcdMemoryTypePersistentMemory\r
+ "MoreRelia", // EfiGcdMemoryTypeMoreReliable\r
+ "Unknown " // EfiGcdMemoryTypeMaximum\r
+};\r
+\r
+///\r
+/// Lookup table used to print GCD I/O Space Map\r
+///\r
+GLOBAL_REMOVE_IF_UNREFERENCED CONST CHAR8 *mGcdIoTypeNames[] = {\r
+ "NonExist", // EfiGcdIoTypeNonExistent\r
+ "Reserved", // EfiGcdIoTypeReserved\r
+ "I/O ", // EfiGcdIoTypeIo\r
+ "Unknown " // EfiGcdIoTypeMaximum \r
+};\r
+\r
+///\r
+/// Lookup table used to print GCD Allocation Types\r
+///\r
+GLOBAL_REMOVE_IF_UNREFERENCED CONST CHAR8 *mGcdAllocationTypeNames[] = {\r
+ "AnySearchBottomUp ", // EfiGcdAllocateAnySearchBottomUp\r
+ "MaxAddressSearchBottomUp ", // EfiGcdAllocateMaxAddressSearchBottomUp\r
+ "AtAddress ", // EfiGcdAllocateAddress\r
+ "AnySearchTopDown ", // EfiGcdAllocateAnySearchTopDown\r
+ "MaxAddressSearchTopDown ", // EfiGcdAllocateMaxAddressSearchTopDown\r
+ "Unknown " // EfiGcdMaxAllocateType\r
+};\r
+\r
+/**\r
+ Dump the entire contents if the GCD Memory Space Map using DEBUG() macros when\r
+ PcdDebugPrintErrorLevel has the DEBUG_GCD bit set.\r
+\r
+ @param InitialMap TRUE if the initial GCD Memory Map is being dumped. Otherwise, FALSE.\r
+ \r
+**/\r
+VOID\r
+EFIAPI\r
+CoreDumpGcdMemorySpaceMap (\r
+ BOOLEAN InitialMap\r
+ )\r
+{\r
+ DEBUG_CODE (\r
+ EFI_STATUS Status;\r
+ UINTN NumberOfDescriptors;\r
+ EFI_GCD_MEMORY_SPACE_DESCRIPTOR *MemorySpaceMap;\r
+ UINTN Index;\r
+ \r
+ Status = CoreGetMemorySpaceMap (&NumberOfDescriptors, &MemorySpaceMap);\r
+ ASSERT (Status == EFI_SUCCESS && MemorySpaceMap != NULL);\r
+\r
+ if (InitialMap) {\r
+ DEBUG ((DEBUG_GCD, "GCD:Initial GCD Memory Space Map\n"));\r
+ }\r
+ DEBUG ((DEBUG_GCD, "GCDMemType Range Capabilities Attributes \n"));\r
+ DEBUG ((DEBUG_GCD, "========== ================================= ================ ================\n"));\r
+ for (Index = 0; Index < NumberOfDescriptors; Index++) {\r
+ DEBUG ((DEBUG_GCD, "%a %016lx-%016lx %016lx %016lx%c\n", \r
+ mGcdMemoryTypeNames[MIN (MemorySpaceMap[Index].GcdMemoryType, EfiGcdMemoryTypeMaximum)],\r
+ MemorySpaceMap[Index].BaseAddress, \r
+ MemorySpaceMap[Index].BaseAddress + MemorySpaceMap[Index].Length - 1,\r
+ MemorySpaceMap[Index].Capabilities, \r
+ MemorySpaceMap[Index].Attributes,\r
+ MemorySpaceMap[Index].ImageHandle == NULL ? ' ' : '*'\r
+ ));\r
+ }\r
+ DEBUG ((DEBUG_GCD, "\n"));\r
+ FreePool (MemorySpaceMap);\r
+ );\r
+}\r
+\r
+/**\r
+ Dump the entire contents if the GCD I/O Space Map using DEBUG() macros when \r
+ PcdDebugPrintErrorLevel has the DEBUG_GCD bit set.\r
+\r
+ @param InitialMap TRUE if the initial GCD I/O Map is being dumped. Otherwise, FALSE.\r
+ \r
+**/\r
+VOID\r
+EFIAPI\r
+CoreDumpGcdIoSpaceMap (\r
+ BOOLEAN InitialMap\r
+ )\r
+{\r
+ DEBUG_CODE (\r
+ EFI_STATUS Status;\r
+ UINTN NumberOfDescriptors;\r
+ EFI_GCD_IO_SPACE_DESCRIPTOR *IoSpaceMap;\r
+ UINTN Index;\r
+ \r
+ Status = CoreGetIoSpaceMap (&NumberOfDescriptors, &IoSpaceMap);\r
+ ASSERT (Status == EFI_SUCCESS && IoSpaceMap != NULL);\r
+ \r
+ if (InitialMap) {\r
+ DEBUG ((DEBUG_GCD, "GCD:Initial GCD I/O Space Map\n"));\r
+ } \r
+ \r
+ DEBUG ((DEBUG_GCD, "GCDIoType Range \n"));\r
+ DEBUG ((DEBUG_GCD, "========== =================================\n"));\r
+ for (Index = 0; Index < NumberOfDescriptors; Index++) {\r
+ DEBUG ((DEBUG_GCD, "%a %016lx-%016lx%c\n", \r
+ mGcdIoTypeNames[MIN (IoSpaceMap[Index].GcdIoType, EfiGcdIoTypeMaximum)],\r
+ IoSpaceMap[Index].BaseAddress, \r
+ IoSpaceMap[Index].BaseAddress + IoSpaceMap[Index].Length - 1,\r
+ IoSpaceMap[Index].ImageHandle == NULL ? ' ' : '*'\r
+ ));\r
+ }\r
+ DEBUG ((DEBUG_GCD, "\n"));\r
+ FreePool (IoSpaceMap);\r
+ );\r
+}\r
+ \r
+/**\r
+ Validate resource descriptor HOB's attributes.\r
+\r
+ If Attributes includes some memory resource's settings, it should include \r
+ the corresponding capabilites also.\r
+\r
+ @param Attributes Resource descriptor HOB attributes.\r
+\r
+**/\r
+VOID\r
+CoreValidateResourceDescriptorHobAttributes (\r
+ IN UINT64 Attributes\r
+ )\r
+{\r
+ ASSERT (((Attributes & EFI_RESOURCE_ATTRIBUTE_READ_PROTECTED) == 0) ||\r
+ ((Attributes & EFI_RESOURCE_ATTRIBUTE_READ_PROTECTABLE) != 0));\r
+ ASSERT (((Attributes & EFI_RESOURCE_ATTRIBUTE_WRITE_PROTECTED) == 0) ||\r
+ ((Attributes & EFI_RESOURCE_ATTRIBUTE_WRITE_PROTECTABLE) != 0));\r
+ ASSERT (((Attributes & EFI_RESOURCE_ATTRIBUTE_EXECUTION_PROTECTED) == 0) ||\r
+ ((Attributes & EFI_RESOURCE_ATTRIBUTE_EXECUTION_PROTECTABLE) != 0));\r
+ ASSERT (((Attributes & EFI_RESOURCE_ATTRIBUTE_READ_ONLY_PROTECTED) == 0) ||\r
+ ((Attributes & EFI_RESOURCE_ATTRIBUTE_READ_ONLY_PROTECTABLE) != 0));\r
+ ASSERT (((Attributes & EFI_RESOURCE_ATTRIBUTE_PERSISTENT) == 0) ||\r
+ ((Attributes & EFI_RESOURCE_ATTRIBUTE_PERSISTABLE) != 0));\r
+}\r
\r
/**\r
Acquire memory lock on mGcdMemorySpaceLock.\r
Acquire memory lock on mGcdIoSpaceLock.\r
\r
**/\r
-STATIC\r
VOID\r
CoreAcquireGcdIoLock (\r
VOID\r
Release memory lock on mGcdIoSpaceLock.\r
\r
**/\r
-STATIC\r
VOID\r
CoreReleaseGcdIoLock (\r
VOID\r
//\r
// GCD Initialization Worker Functions\r
//\r
-\r
/**\r
Aligns a value to the specified boundary.\r
\r
- @param Value 64 bit value to align \r
- @param Alignment Log base 2 of the boundary to align Value to \r
- @param RoundUp TRUE if Value is to be rounded up to the nearest \r
- aligned boundary. FALSE is Value is to be \r
- rounded down to the nearest aligned boundary. \r
+ @param Value 64 bit value to align\r
+ @param Alignment Log base 2 of the boundary to align Value to\r
+ @param RoundUp TRUE if Value is to be rounded up to the nearest\r
+ aligned boundary. FALSE is Value is to be\r
+ rounded down to the nearest aligned boundary.\r
\r
@return A 64 bit value is the aligned to the value nearest Value with an alignment by Alignment.\r
\r
**/\r
-STATIC\r
UINT64\r
AlignValue (\r
IN UINT64 Value,\r
/**\r
Aligns address to the page boundary.\r
\r
- @param Value 64 bit address to align \r
+ @param Value 64 bit address to align\r
\r
@return A 64 bit value is the aligned to the value nearest Value with an alignment by Alignment.\r
\r
**/\r
-STATIC\r
UINT64\r
PageAlignAddress (\r
IN UINT64 Value\r
/**\r
Aligns length to the page boundary.\r
\r
- @param Value 64 bit length to align \r
+ @param Value 64 bit length to align\r
\r
@return A 64 bit value is the aligned to the value nearest Value with an alignment by Alignment.\r
\r
**/\r
-STATIC\r
UINT64\r
PageAlignLength (\r
IN UINT64 Value\r
/**\r
Allocate pool for two entries.\r
\r
- @param TopEntry An entry of GCD map \r
- @param BottomEntry An entry of GCD map \r
+ @param TopEntry An entry of GCD map\r
+ @param BottomEntry An entry of GCD map\r
\r
- @retval EFI_OUT_OF_RESOURCES No enough buffer to be allocated. \r
+ @retval EFI_OUT_OF_RESOURCES No enough buffer to be allocated.\r
@retval EFI_SUCCESS Both entries successfully allocated.\r
\r
**/\r
-STATIC\r
EFI_STATUS\r
CoreAllocateGcdMapEntry (\r
IN OUT EFI_GCD_MAP_ENTRY **TopEntry,\r
IN OUT EFI_GCD_MAP_ENTRY **BottomEntry\r
)\r
{\r
- *TopEntry = CoreAllocateZeroBootServicesPool (sizeof (EFI_GCD_MAP_ENTRY));\r
+ *TopEntry = AllocateZeroPool (sizeof (EFI_GCD_MAP_ENTRY));\r
if (*TopEntry == NULL) {\r
return EFI_OUT_OF_RESOURCES;\r
}\r
\r
- *BottomEntry = CoreAllocateZeroBootServicesPool (sizeof (EFI_GCD_MAP_ENTRY));\r
+ *BottomEntry = AllocateZeroPool (sizeof (EFI_GCD_MAP_ENTRY));\r
if (*BottomEntry == NULL) {\r
CoreFreePool (*TopEntry);\r
return EFI_OUT_OF_RESOURCES;\r
/**\r
Internal function. Inserts a new descriptor into a sorted list\r
\r
- @param Link The linked list to insert the range BaseAddress \r
- and Length into \r
- @param Entry A pointer to the entry that is inserted \r
- @param BaseAddress The base address of the new range \r
- @param Length The length of the new range in bytes \r
- @param TopEntry Top pad entry to insert if needed. \r
- @param BottomEntry Bottom pad entry to insert if needed. \r
+ @param Link The linked list to insert the range BaseAddress\r
+ and Length into\r
+ @param Entry A pointer to the entry that is inserted\r
+ @param BaseAddress The base address of the new range\r
+ @param Length The length of the new range in bytes\r
+ @param TopEntry Top pad entry to insert if needed.\r
+ @param BottomEntry Bottom pad entry to insert if needed.\r
\r
@retval EFI_SUCCESS The new range was inserted into the linked list\r
\r
**/\r
-STATIC\r
EFI_STATUS\r
CoreInsertGcdMapEntry (\r
IN LIST_ENTRY *Link,\r
)\r
{\r
ASSERT (Length != 0);\r
- ASSERT (TopEntry->Signature == 0);\r
- ASSERT (BottomEntry->Signature == 0);\r
\r
if (BaseAddress > Entry->BaseAddress) {\r
+ ASSERT (BottomEntry->Signature == 0);\r
+\r
CopyMem (BottomEntry, Entry, sizeof (EFI_GCD_MAP_ENTRY));\r
Entry->BaseAddress = BaseAddress;\r
BottomEntry->EndAddress = BaseAddress - 1;\r
InsertTailList (Link, &BottomEntry->Link);\r
- } \r
+ }\r
\r
if ((BaseAddress + Length - 1) < Entry->EndAddress) {\r
+ ASSERT (TopEntry->Signature == 0);\r
+\r
CopyMem (TopEntry, Entry, sizeof (EFI_GCD_MAP_ENTRY));\r
TopEntry->BaseAddress = BaseAddress + Length;\r
Entry->EndAddress = BaseAddress + Length - 1;\r
\r
\r
/**\r
- Merge the Gcd region specified by Link and its adjacent entry\r
+ Merge the Gcd region specified by Link and its adjacent entry.\r
\r
- @param Link Specify the entry to be merged (with its \r
- adjacent entry). \r
- @param Forward Direction (forward or backward). \r
- @param Map Boundary. \r
+ @param Link Specify the entry to be merged (with its\r
+ adjacent entry).\r
+ @param Forward Direction (forward or backward).\r
+ @param Map Boundary.\r
\r
- @retval EFI_SUCCESS Successfully returned. \r
+ @retval EFI_SUCCESS Successfully returned.\r
@retval EFI_UNSUPPORTED These adjacent regions could not merge.\r
\r
**/\r
-STATIC\r
EFI_STATUS\r
CoreMergeGcdMapEntry (\r
IN LIST_ENTRY *Link,\r
/**\r
Merge adjacent entries on total chain.\r
\r
- @param TopEntry Top entry of GCD map. \r
- @param BottomEntry Bottom entry of GCD map. \r
- @param StartLink Start link of the list for this loop. \r
- @param EndLink End link of the list for this loop. \r
- @param Map Boundary. \r
+ @param TopEntry Top entry of GCD map.\r
+ @param BottomEntry Bottom entry of GCD map.\r
+ @param StartLink Start link of the list for this loop.\r
+ @param EndLink End link of the list for this loop.\r
+ @param Map Boundary.\r
\r
@retval EFI_SUCCESS GCD map successfully cleaned up.\r
\r
**/\r
-STATIC\r
EFI_STATUS\r
CoreCleanupGcdMapEntry (\r
IN EFI_GCD_MAP_ENTRY *TopEntry,\r
/**\r
Search a segment of memory space in GCD map. The result is a range of GCD entry list.\r
\r
- @param BaseAddress The start address of the segment. \r
- @param Length The length of the segment. \r
- @param StartLink The first GCD entry involves this segment of \r
- memory space. \r
- @param EndLink The first GCD entry involves this segment of \r
- memory space. \r
- @param Map Points to the start entry to search. \r
+ @param BaseAddress The start address of the segment.\r
+ @param Length The length of the segment.\r
+ @param StartLink The first GCD entry involves this segment of\r
+ memory space.\r
+ @param EndLink The first GCD entry involves this segment of\r
+ memory space.\r
+ @param Map Points to the start entry to search.\r
\r
- @retval EFI_SUCCESS Successfully found the entry. \r
+ @retval EFI_SUCCESS Successfully found the entry.\r
@retval EFI_NOT_FOUND Not found.\r
\r
**/\r
-STATIC\r
EFI_STATUS\r
CoreSearchGcdMapEntry (\r
IN EFI_PHYSICAL_ADDRESS BaseAddress,\r
*StartLink = Link;\r
}\r
if (*StartLink != NULL) {\r
- if ((BaseAddress + Length - 1) >= Entry->BaseAddress && \r
+ if ((BaseAddress + Length - 1) >= Entry->BaseAddress &&\r
(BaseAddress + Length - 1) <= Entry->EndAddress ) {\r
*EndLink = Link;\r
return EFI_SUCCESS;\r
}\r
Link = Link->ForwardLink;\r
}\r
+\r
return EFI_NOT_FOUND;\r
}\r
\r
/**\r
Count the amount of GCD map entries.\r
\r
- @param Map Points to the start entry to do the count loop. \r
+ @param Map Points to the start entry to do the count loop.\r
\r
@return The count.\r
\r
**/\r
-STATIC\r
UINTN\r
CoreCountGcdMapEntry (\r
IN LIST_ENTRY *Map\r
Count++;\r
Link = Link->ForwardLink;\r
}\r
+\r
return Count;\r
}\r
\r
/**\r
Return the memory attribute specified by Attributes\r
\r
- @param Attributes A num with some attribute bits on. \r
+ @param Attributes A num with some attribute bits on.\r
\r
@return The enum value of memory attribute.\r
\r
**/\r
-STATIC\r
UINT64\r
ConverToCpuArchAttributes (\r
UINT64 Attributes\r
- ) \r
+ )\r
{\r
if ( (Attributes & EFI_MEMORY_UC) == EFI_MEMORY_UC) {\r
return EFI_MEMORY_UC;\r
/**\r
Do operation on a segment of memory space specified (add, free, remove, change attribute ...).\r
\r
- @param Operation The type of the operation \r
- @param GcdMemoryType Additional information for the operation \r
- @param GcdIoType Additional information for the operation \r
- @param BaseAddress Start address of the segment \r
- @param Length length of the segment \r
- @param Capabilities The alterable attributes of a newly added entry \r
- @param Attributes The attributes needs to be set \r
-\r
- @retval EFI_INVALID_PARAMETER Length is 0 or address (length) not aligned when \r
- setting attribute. \r
- @retval EFI_SUCCESS Action successfully done. \r
- @retval EFI_UNSUPPORTED Could not find the proper descriptor on this \r
- segment or set an upsupported attribute. \r
- @retval EFI_ACCESS_DENIED Operate on an space non-exist or is used for an \r
- image. \r
- @retval EFI_NOT_FOUND Free a non-using space or remove a non-exist \r
- space, and so on. \r
+ @param Operation The type of the operation\r
+ @param GcdMemoryType Additional information for the operation\r
+ @param GcdIoType Additional information for the operation\r
+ @param BaseAddress Start address of the segment\r
+ @param Length length of the segment\r
+ @param Capabilities The alterable attributes of a newly added entry\r
+ @param Attributes The attributes needs to be set\r
+\r
+ @retval EFI_INVALID_PARAMETER Length is 0 or address (length) not aligned when\r
+ setting attribute.\r
+ @retval EFI_SUCCESS Action successfully done.\r
+ @retval EFI_UNSUPPORTED Could not find the proper descriptor on this\r
+ segment or set an upsupported attribute.\r
+ @retval EFI_ACCESS_DENIED Operate on an space non-exist or is used for an\r
+ image.\r
+ @retval EFI_NOT_FOUND Free a non-using space or remove a non-exist\r
+ space, and so on.\r
@retval EFI_OUT_OF_RESOURCES No buffer could be allocated.\r
-\r
+ @retval EFI_NOT_AVAILABLE_YET The attributes cannot be set because CPU architectural protocol\r
+ is not available yet.\r
**/\r
-STATIC\r
EFI_STATUS\r
CoreConvertSpace (\r
IN UINTN Operation,\r
EFI_GCD_MAP_ENTRY *BottomEntry;\r
LIST_ENTRY *StartLink;\r
LIST_ENTRY *EndLink;\r
- \r
- EFI_CPU_ARCH_PROTOCOL *CpuArch;\r
- UINT64 CpuArchAttributes;\r
+ UINT64 CpuArchAttributes;\r
\r
if (Length == 0) {\r
+ DEBUG ((DEBUG_GCD, " Status = %r\n", EFI_INVALID_PARAMETER));\r
return EFI_INVALID_PARAMETER;\r
}\r
\r
if ((Operation & GCD_MEMORY_SPACE_OPERATION) != 0) {\r
CoreAcquireGcdMemoryLock ();\r
Map = &mGcdMemorySpaceMap;\r
- }\r
- if ((Operation & GCD_IO_SPACE_OPERATION) != 0) {\r
+ } else if ((Operation & GCD_IO_SPACE_OPERATION) != 0) {\r
CoreAcquireGcdIoLock ();\r
Map = &mGcdIoSpaceMap;\r
+ } else {\r
+ ASSERT (FALSE);\r
}\r
\r
//\r
\r
goto Done;\r
}\r
+ ASSERT (StartLink != NULL && EndLink != NULL);\r
\r
//\r
// Verify that the list of descriptors are unallocated non-existent memory.\r
}\r
break;\r
//\r
- // Set attribute operations\r
+ // Set attributes operation\r
//\r
case GCD_SET_ATTRIBUTES_MEMORY_OPERATION:\r
if ((Attributes & EFI_MEMORY_RUNTIME) != 0) {\r
if ((BaseAddress & EFI_PAGE_MASK) != 0 || (Length & EFI_PAGE_MASK) != 0) {\r
Status = EFI_INVALID_PARAMETER;\r
-\r
goto Done;\r
}\r
}\r
goto Done;\r
}\r
break;\r
+ //\r
+ // Set capabilities operation\r
+ //\r
+ case GCD_SET_CAPABILITIES_MEMORY_OPERATION:\r
+ if ((BaseAddress & EFI_PAGE_MASK) != 0 || (Length & EFI_PAGE_MASK) != 0) {\r
+ Status = EFI_INVALID_PARAMETER;\r
+\r
+ goto Done;\r
+ }\r
+ //\r
+ // Current attributes must still be supported with new capabilities\r
+ //\r
+ if ((Capabilities & Entry->Attributes) != Entry->Attributes) {\r
+ Status = EFI_UNSUPPORTED;\r
+ goto Done;\r
+ }\r
+ break;\r
}\r
Link = Link->ForwardLink;\r
}\r
Status = EFI_OUT_OF_RESOURCES;\r
goto Done;\r
}\r
+ ASSERT (TopEntry != NULL && BottomEntry != NULL);\r
\r
- //\r
- //\r
- //\r
if (Operation == GCD_SET_ATTRIBUTES_MEMORY_OPERATION) {\r
//\r
// Call CPU Arch Protocol to attempt to set attributes on the range\r
//\r
CpuArchAttributes = ConverToCpuArchAttributes (Attributes);\r
- if ( CpuArchAttributes != INVALID_CPU_ARCH_ATTRIBUTES ) {\r
- Status = CoreLocateProtocol (&gEfiCpuArchProtocolGuid, NULL, (VOID **)&CpuArch);\r
- if (EFI_ERROR (Status)) {\r
- Status = EFI_ACCESS_DENIED;\r
- goto Done;\r
+ if (CpuArchAttributes != INVALID_CPU_ARCH_ATTRIBUTES) {\r
+ if (gCpu == NULL) {\r
+ Status = EFI_NOT_AVAILABLE_YET;\r
+ } else {\r
+ Status = gCpu->SetMemoryAttributes (\r
+ gCpu,\r
+ BaseAddress,\r
+ Length,\r
+ CpuArchAttributes\r
+ );\r
}\r
-\r
- Status = CpuArch->SetMemoryAttributes (\r
- CpuArch,\r
- BaseAddress,\r
- Length,\r
- CpuArchAttributes\r
- );\r
if (EFI_ERROR (Status)) {\r
+ CoreFreePool (TopEntry);\r
+ CoreFreePool (BottomEntry);\r
goto Done;\r
}\r
}\r
-\r
}\r
\r
//\r
Entry->GcdIoType = EfiGcdIoTypeNonExistent;\r
break;\r
//\r
- // Set attribute operations\r
+ // Set attributes operation\r
//\r
case GCD_SET_ATTRIBUTES_MEMORY_OPERATION:\r
Entry->Attributes = Attributes;\r
break;\r
+ //\r
+ // Set capabilities operation\r
+ //\r
+ case GCD_SET_CAPABILITIES_MEMORY_OPERATION:\r
+ Entry->Capabilities = Capabilities;\r
+ break;\r
}\r
Link = Link->ForwardLink;\r
}\r
Status = CoreCleanupGcdMapEntry (TopEntry, BottomEntry, StartLink, EndLink, Map);\r
\r
Done:\r
+ DEBUG ((DEBUG_GCD, " Status = %r\n", Status));\r
+\r
if ((Operation & GCD_MEMORY_SPACE_OPERATION) != 0) {\r
CoreReleaseGcdMemoryLock ();\r
+ CoreDumpGcdMemorySpaceMap (FALSE);\r
}\r
if ((Operation & GCD_IO_SPACE_OPERATION) != 0) {\r
CoreReleaseGcdIoLock ();\r
+ CoreDumpGcdIoSpaceMap (FALSE);\r
}\r
\r
return Status;\r
/**\r
Check whether an entry could be used to allocate space.\r
\r
- @param Operation Allocate memory or IO \r
- @param Entry The entry to be tested \r
- @param GcdMemoryType The desired memory type \r
- @param GcdIoType The desired IO type \r
+ @param Operation Allocate memory or IO\r
+ @param Entry The entry to be tested\r
+ @param GcdMemoryType The desired memory type\r
+ @param GcdIoType The desired IO type\r
\r
- @retval EFI_NOT_FOUND The memory type does not match or there's an \r
- image handle on the entry. \r
- @retval EFI_UNSUPPORTED The operation unsupported. \r
- @retval EFI_SUCCESS It's ok for this entry to be used to allocate \r
+ @retval EFI_NOT_FOUND The memory type does not match or there's an\r
+ image handle on the entry.\r
+ @retval EFI_UNSUPPORTED The operation unsupported.\r
+ @retval EFI_SUCCESS It's ok for this entry to be used to allocate\r
space.\r
\r
**/\r
-STATIC\r
EFI_STATUS\r
CoreAllocateSpaceCheckEntry (\r
IN UINTN Operation,\r
/**\r
Allocate space on specified address and length.\r
\r
- @param Operation The type of operation (memory or IO) \r
- @param GcdAllocateType The type of allocate operation \r
- @param GcdMemoryType The desired memory type \r
- @param GcdIoType The desired IO type \r
- @param Alignment Align with 2^Alignment \r
- @param Length Length to allocate \r
- @param BaseAddress Base address to allocate \r
- @param ImageHandle The image handle consume the allocated space. \r
- @param DeviceHandle The device handle consume the allocated space. \r
-\r
- @retval EFI_INVALID_PARAMETER Invalid parameter. \r
- @retval EFI_NOT_FOUND No descriptor for the desired space exists. \r
+ @param Operation The type of operation (memory or IO)\r
+ @param GcdAllocateType The type of allocate operation\r
+ @param GcdMemoryType The desired memory type\r
+ @param GcdIoType The desired IO type\r
+ @param Alignment Align with 2^Alignment\r
+ @param Length Length to allocate\r
+ @param BaseAddress Base address to allocate\r
+ @param ImageHandle The image handle consume the allocated space.\r
+ @param DeviceHandle The device handle consume the allocated space.\r
+\r
+ @retval EFI_INVALID_PARAMETER Invalid parameter.\r
+ @retval EFI_NOT_FOUND No descriptor for the desired space exists.\r
@retval EFI_SUCCESS Space successfully allocated.\r
\r
**/\r
-STATIC\r
EFI_STATUS\r
CoreAllocateSpace (\r
IN UINTN Operation,\r
//\r
// Make sure parameters are valid\r
//\r
- if (GcdAllocateType < 0 || GcdAllocateType >= EfiGcdMaxAllocateType) {\r
+ if ((UINT32)GcdAllocateType >= EfiGcdMaxAllocateType) {\r
+ DEBUG ((DEBUG_GCD, " Status = %r\n", EFI_INVALID_PARAMETER));\r
return EFI_INVALID_PARAMETER;\r
}\r
- if (GcdMemoryType < 0 || GcdMemoryType >= EfiGcdMemoryTypeMaximum) {\r
+ if ((UINT32)GcdMemoryType >= EfiGcdMemoryTypeMaximum) {\r
+ DEBUG ((DEBUG_GCD, " Status = %r\n", EFI_INVALID_PARAMETER));\r
return EFI_INVALID_PARAMETER;\r
}\r
- if (GcdIoType < 0 || GcdIoType >= EfiGcdIoTypeMaximum) {\r
+ if ((UINT32)GcdIoType >= EfiGcdIoTypeMaximum) {\r
+ DEBUG ((DEBUG_GCD, " Status = %r\n", EFI_INVALID_PARAMETER));\r
return EFI_INVALID_PARAMETER;\r
}\r
if (BaseAddress == NULL) {\r
+ DEBUG ((DEBUG_GCD, " Status = %r\n", EFI_INVALID_PARAMETER));\r
return EFI_INVALID_PARAMETER;\r
}\r
if (ImageHandle == NULL) {\r
+ DEBUG ((DEBUG_GCD, " Status = %r\n", EFI_INVALID_PARAMETER));\r
return EFI_INVALID_PARAMETER;\r
}\r
if (Alignment >= 64) {\r
+ DEBUG ((DEBUG_GCD, " Status = %r\n", EFI_NOT_FOUND));\r
return EFI_NOT_FOUND;\r
}\r
if (Length == 0) {\r
+ DEBUG ((DEBUG_GCD, " Status = %r\n", EFI_INVALID_PARAMETER));\r
return EFI_INVALID_PARAMETER;\r
}\r
\r
if ((Operation & GCD_MEMORY_SPACE_OPERATION) != 0) {\r
CoreAcquireGcdMemoryLock ();\r
Map = &mGcdMemorySpaceMap;\r
- }\r
- if ((Operation & GCD_IO_SPACE_OPERATION) != 0) {\r
+ } else if ((Operation & GCD_IO_SPACE_OPERATION) != 0) {\r
CoreAcquireGcdIoLock ();\r
Map = &mGcdIoSpaceMap;\r
+ } else {\r
+ ASSERT (FALSE);\r
}\r
\r
Found = FALSE;\r
Status = EFI_NOT_FOUND;\r
goto Done;\r
}\r
+ ASSERT (StartLink != NULL && EndLink != NULL);\r
\r
//\r
// Verify that the list of descriptors are unallocated memory matching GcdMemoryType.\r
}\r
\r
if (GcdAllocateType == EfiGcdAllocateMaxAddressSearchTopDown ||\r
- GcdAllocateType == EfiGcdAllocateAnySearchTopDown ) {\r
+ GcdAllocateType == EfiGcdAllocateAnySearchTopDown) {\r
if ((Entry->BaseAddress + Length) > MaxAddress) {\r
continue;\r
}\r
Status = EFI_NOT_FOUND;\r
goto Done;\r
}\r
+ ASSERT (StartLink != NULL && EndLink != NULL);\r
\r
Link = StartLink;\r
//\r
Status = EFI_OUT_OF_RESOURCES;\r
goto Done;\r
}\r
+ ASSERT (TopEntry != NULL && BottomEntry != NULL);\r
\r
//\r
// Convert/Insert the list of descriptors from StartLink to EndLink\r
Status = CoreCleanupGcdMapEntry (TopEntry, BottomEntry, StartLink, EndLink, Map);\r
\r
Done:\r
+ DEBUG ((DEBUG_GCD, " Status = %r", Status));\r
+ if (!EFI_ERROR (Status)) {\r
+ DEBUG ((DEBUG_GCD, " (BaseAddress = %016lx)", *BaseAddress));\r
+ }\r
+ DEBUG ((DEBUG_GCD, "\n"));\r
+ \r
if ((Operation & GCD_MEMORY_SPACE_OPERATION) != 0) {\r
CoreReleaseGcdMemoryLock ();\r
+ CoreDumpGcdMemorySpaceMap (FALSE);\r
}\r
if ((Operation & GCD_IO_SPACE_OPERATION) !=0) {\r
CoreReleaseGcdIoLock ();\r
+ CoreDumpGcdIoSpaceMap (FALSE);\r
}\r
\r
return Status;\r
/**\r
Add a segment of memory to GCD map.\r
\r
- @param GcdMemoryType Memory type of the segment. \r
- @param BaseAddress Base address of the segment. \r
- @param Length Length of the segment. \r
- @param Capabilities alterable attributes of the segment. \r
+ @param GcdMemoryType Memory type of the segment.\r
+ @param BaseAddress Base address of the segment.\r
+ @param Length Length of the segment.\r
+ @param Capabilities alterable attributes of the segment.\r
\r
- @retval EFI_INVALID_PARAMETER Invalid parameters. \r
+ @retval EFI_INVALID_PARAMETER Invalid parameters.\r
@retval EFI_SUCCESS Successfully add a segment of memory space.\r
\r
**/\r
-STATIC\r
EFI_STATUS\r
CoreInternalAddMemorySpace (\r
IN EFI_GCD_MEMORY_TYPE GcdMemoryType,\r
IN UINT64 Capabilities\r
)\r
{\r
+ DEBUG ((DEBUG_GCD, "GCD:AddMemorySpace(Base=%016lx,Length=%016lx)\n", BaseAddress, Length));\r
+ DEBUG ((DEBUG_GCD, " GcdMemoryType = %a\n", mGcdMemoryTypeNames[MIN (GcdMemoryType, EfiGcdMemoryTypeMaximum)]));\r
+ DEBUG ((DEBUG_GCD, " Capabilities = %016lx\n", Capabilities));\r
+\r
//\r
// Make sure parameters are valid\r
//\r
Allocates nonexistent memory, reserved memory, system memory, or memorymapped\r
I/O resources from the global coherency domain of the processor.\r
\r
- @param GcdAllocateType The type of allocate operation \r
- @param GcdMemoryType The desired memory type \r
- @param Alignment Align with 2^Alignment \r
- @param Length Length to allocate \r
- @param BaseAddress Base address to allocate \r
- @param ImageHandle The image handle consume the allocated space. \r
- @param DeviceHandle The device handle consume the allocated space. \r
+ @param GcdAllocateType The type of allocate operation\r
+ @param GcdMemoryType The desired memory type\r
+ @param Alignment Align with 2^Alignment\r
+ @param Length Length to allocate\r
+ @param BaseAddress Base address to allocate\r
+ @param ImageHandle The image handle consume the allocated space.\r
+ @param DeviceHandle The device handle consume the allocated space.\r
\r
- @retval EFI_INVALID_PARAMETER Invalid parameter. \r
- @retval EFI_NOT_FOUND No descriptor contains the desired space. \r
+ @retval EFI_INVALID_PARAMETER Invalid parameter.\r
+ @retval EFI_NOT_FOUND No descriptor contains the desired space.\r
@retval EFI_SUCCESS Memory space successfully allocated.\r
\r
**/\r
EFI_STATUS\r
+EFIAPI\r
CoreAllocateMemorySpace (\r
IN EFI_GCD_ALLOCATE_TYPE GcdAllocateType,\r
IN EFI_GCD_MEMORY_TYPE GcdMemoryType,\r
IN EFI_HANDLE DeviceHandle OPTIONAL\r
)\r
{\r
+ DEBUG ((DEBUG_GCD, "GCD:AllocateMemorySpace(Base=%016lx,Length=%016lx)\n", *BaseAddress, Length));\r
+ DEBUG ((DEBUG_GCD, " GcdAllocateType = %a\n", mGcdAllocationTypeNames[MIN (GcdAllocateType, EfiGcdMaxAllocateType)]));\r
+ DEBUG ((DEBUG_GCD, " GcdMemoryType = %a\n", mGcdMemoryTypeNames[MIN (GcdMemoryType, EfiGcdMemoryTypeMaximum)]));\r
+ DEBUG ((DEBUG_GCD, " Alignment = %016lx\n", LShiftU64 (1, Alignment)));\r
+ DEBUG ((DEBUG_GCD, " ImageHandle = %p\n", ImageHandle));\r
+ DEBUG ((DEBUG_GCD, " DeviceHandle = %p\n", DeviceHandle));\r
+ \r
return CoreAllocateSpace (\r
- GCD_ALLOCATE_MEMORY_OPERATION, \r
- GcdAllocateType, \r
- GcdMemoryType, \r
- (EFI_GCD_IO_TYPE) 0, \r
- Alignment, \r
- Length, \r
- BaseAddress, \r
- ImageHandle, \r
+ GCD_ALLOCATE_MEMORY_OPERATION,\r
+ GcdAllocateType,\r
+ GcdMemoryType,\r
+ (EFI_GCD_IO_TYPE) 0,\r
+ Alignment,\r
+ Length,\r
+ BaseAddress,\r
+ ImageHandle,\r
DeviceHandle\r
);\r
}\r
Adds reserved memory, system memory, or memory-mapped I/O resources to the\r
global coherency domain of the processor.\r
\r
- @param GcdMemoryType Memory type of the memory space. \r
- @param BaseAddress Base address of the memory space. \r
- @param Length Length of the memory space. \r
- @param Capabilities alterable attributes of the memory space. \r
+ @param GcdMemoryType Memory type of the memory space.\r
+ @param BaseAddress Base address of the memory space.\r
+ @param Length Length of the memory space.\r
+ @param Capabilities alterable attributes of the memory space.\r
\r
@retval EFI_SUCCESS Merged this memory space into GCD map.\r
\r
**/\r
EFI_STATUS\r
+EFIAPI\r
CoreAddMemorySpace (\r
IN EFI_GCD_MEMORY_TYPE GcdMemoryType,\r
IN EFI_PHYSICAL_ADDRESS BaseAddress,\r
\r
Status = CoreInternalAddMemorySpace (GcdMemoryType, BaseAddress, Length, Capabilities);\r
\r
- if (!EFI_ERROR (Status) && GcdMemoryType == EfiGcdMemoryTypeSystemMemory) {\r
+ if (!EFI_ERROR (Status) && ((GcdMemoryType == EfiGcdMemoryTypeSystemMemory) || (GcdMemoryType == EfiGcdMemoryTypeMoreReliable))) {\r
\r
- PageBaseAddress = PageAlignLength (BaseAddress);\r
+ PageBaseAddress = PageAlignAddress (BaseAddress);\r
PageLength = PageAlignLength (BaseAddress + Length - PageBaseAddress);\r
\r
Status = CoreAllocateMemorySpace (\r
EfiGcdAllocateAddress,\r
GcdMemoryType,\r
- EFI_PAGE_SHIFT, \r
+ EFI_PAGE_SHIFT,\r
PageLength,\r
&PageBaseAddress,\r
gDxeCoreImageHandle,\r
Status = CoreAllocateMemorySpace (\r
EfiGcdAllocateAddress,\r
GcdMemoryType,\r
- EFI_PAGE_SHIFT, \r
+ EFI_PAGE_SHIFT,\r
EFI_PAGE_SIZE,\r
&PageBaseAddress,\r
gDxeCoreImageHandle,\r
Frees nonexistent memory, reserved memory, system memory, or memory-mapped\r
I/O resources from the global coherency domain of the processor.\r
\r
- @param BaseAddress Base address of the memory space. \r
- @param Length Length of the memory space. \r
+ @param BaseAddress Base address of the memory space.\r
+ @param Length Length of the memory space.\r
\r
@retval EFI_SUCCESS Space successfully freed.\r
\r
**/\r
EFI_STATUS\r
+EFIAPI\r
CoreFreeMemorySpace (\r
IN EFI_PHYSICAL_ADDRESS BaseAddress,\r
IN UINT64 Length\r
)\r
{\r
+ DEBUG ((DEBUG_GCD, "GCD:FreeMemorySpace(Base=%016lx,Length=%016lx)\n", BaseAddress, Length));\r
+\r
return CoreConvertSpace (GCD_FREE_MEMORY_OPERATION, (EFI_GCD_MEMORY_TYPE) 0, (EFI_GCD_IO_TYPE) 0, BaseAddress, Length, 0, 0);\r
}\r
\r
Removes reserved memory, system memory, or memory-mapped I/O resources from\r
the global coherency domain of the processor.\r
\r
- @param BaseAddress Base address of the memory space. \r
- @param Length Length of the memory space. \r
+ @param BaseAddress Base address of the memory space.\r
+ @param Length Length of the memory space.\r
\r
@retval EFI_SUCCESS Successfully remove a segment of memory space.\r
\r
**/\r
EFI_STATUS\r
+EFIAPI\r
CoreRemoveMemorySpace (\r
IN EFI_PHYSICAL_ADDRESS BaseAddress,\r
IN UINT64 Length\r
)\r
{\r
+ DEBUG ((DEBUG_GCD, "GCD:RemoveMemorySpace(Base=%016lx,Length=%016lx)\n", BaseAddress, Length));\r
+ \r
return CoreConvertSpace (GCD_REMOVE_MEMORY_OPERATION, (EFI_GCD_MEMORY_TYPE) 0, (EFI_GCD_IO_TYPE) 0, BaseAddress, Length, 0, 0);\r
}\r
\r
/**\r
Build a memory descriptor according to an entry.\r
\r
- @param Descriptor The descriptor to be built \r
+ @param Descriptor The descriptor to be built\r
@param Entry According to this entry\r
\r
**/\r
-STATIC\r
VOID\r
BuildMemoryDescriptor (\r
IN OUT EFI_GCD_MEMORY_SPACE_DESCRIPTOR *Descriptor,\r
/**\r
Retrieves the descriptor for a memory region containing a specified address.\r
\r
- @param BaseAddress Specified start address \r
- @param Descriptor Specified length \r
+ @param BaseAddress Specified start address\r
+ @param Descriptor Specified length\r
\r
- @retval EFI_INVALID_PARAMETER Invalid parameter \r
+ @retval EFI_INVALID_PARAMETER Invalid parameter\r
@retval EFI_SUCCESS Successfully get memory space descriptor.\r
\r
**/\r
EFI_STATUS\r
+EFIAPI\r
CoreGetMemorySpaceDescriptor (\r
IN EFI_PHYSICAL_ADDRESS BaseAddress,\r
OUT EFI_GCD_MEMORY_SPACE_DESCRIPTOR *Descriptor\r
CoreAcquireGcdMemoryLock ();\r
\r
//\r
- // Search for the list of descriptors that contain BaseAddress \r
+ // Search for the list of descriptors that contain BaseAddress\r
//\r
Status = CoreSearchGcdMapEntry (BaseAddress, 1, &StartLink, &EndLink, &mGcdMemorySpaceMap);\r
if (EFI_ERROR (Status)) {\r
Status = EFI_NOT_FOUND;\r
} else {\r
+ ASSERT (StartLink != NULL && EndLink != NULL);\r
//\r
// Copy the contents of the found descriptor into Descriptor\r
//\r
Modifies the attributes for a memory region in the global coherency domain of the\r
processor.\r
\r
- @param BaseAddress Specified start address \r
- @param Length Specified length \r
- @param Attributes Specified attributes \r
-\r
- @retval EFI_SUCCESS Successfully set attribute of a segment of \r
- memory space.\r
+ @param BaseAddress Specified start address\r
+ @param Length Specified length\r
+ @param Attributes Specified attributes\r
+\r
+ @retval EFI_SUCCESS The attributes were set for the memory region.\r
+ @retval EFI_INVALID_PARAMETER Length is zero. \r
+ @retval EFI_UNSUPPORTED The processor does not support one or more bytes of the memory\r
+ resource range specified by BaseAddress and Length.\r
+ @retval EFI_UNSUPPORTED The bit mask of attributes is not support for the memory resource\r
+ range specified by BaseAddress and Length.\r
+ @retval EFI_ACCESS_DEFINED The attributes for the memory resource range specified by\r
+ BaseAddress and Length cannot be modified.\r
+ @retval EFI_OUT_OF_RESOURCES There are not enough system resources to modify the attributes of\r
+ the memory resource range.\r
+ @retval EFI_NOT_AVAILABLE_YET The attributes cannot be set because CPU architectural protocol is\r
+ not available yet.\r
\r
**/\r
EFI_STATUS\r
+EFIAPI\r
CoreSetMemorySpaceAttributes (\r
IN EFI_PHYSICAL_ADDRESS BaseAddress,\r
IN UINT64 Length,\r
IN UINT64 Attributes\r
)\r
{\r
+ DEBUG ((DEBUG_GCD, "GCD:SetMemorySpaceAttributes(Base=%016lx,Length=%016lx)\n", BaseAddress, Length));\r
+ DEBUG ((DEBUG_GCD, " Attributes = %016lx\n", Attributes));\r
+\r
return CoreConvertSpace (GCD_SET_ATTRIBUTES_MEMORY_OPERATION, (EFI_GCD_MEMORY_TYPE) 0, (EFI_GCD_IO_TYPE) 0, BaseAddress, Length, 0, Attributes);\r
}\r
\r
\r
+/**\r
+ Modifies the capabilities for a memory region in the global coherency domain of the\r
+ processor.\r
+\r
+ @param BaseAddress The physical address that is the start address of a memory region.\r
+ @param Length The size in bytes of the memory region.\r
+ @param Capabilities The bit mask of capabilities that the memory region supports.\r
+\r
+ @retval EFI_SUCCESS The capabilities were set for the memory region.\r
+ @retval EFI_INVALID_PARAMETER Length is zero.\r
+ @retval EFI_UNSUPPORTED The capabilities specified by Capabilities do not include the\r
+ memory region attributes currently in use.\r
+ @retval EFI_ACCESS_DENIED The capabilities for the memory resource range specified by\r
+ BaseAddress and Length cannot be modified.\r
+ @retval EFI_OUT_OF_RESOURCES There are not enough system resources to modify the capabilities\r
+ of the memory resource range.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+CoreSetMemorySpaceCapabilities (\r
+ IN EFI_PHYSICAL_ADDRESS BaseAddress,\r
+ IN UINT64 Length,\r
+ IN UINT64 Capabilities\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+\r
+ DEBUG ((DEBUG_GCD, "GCD:CoreSetMemorySpaceCapabilities(Base=%016lx,Length=%016lx)\n", BaseAddress, Length));\r
+ DEBUG ((DEBUG_GCD, " Capabilities = %016lx\n", Capabilities));\r
+\r
+ Status = CoreConvertSpace (GCD_SET_CAPABILITIES_MEMORY_OPERATION, (EFI_GCD_MEMORY_TYPE) 0, (EFI_GCD_IO_TYPE) 0, BaseAddress, Length, Capabilities, 0);\r
+ if (!EFI_ERROR(Status)) {\r
+ CoreUpdateMemoryAttributes(BaseAddress, RShiftU64(Length, EFI_PAGE_SHIFT), Capabilities);\r
+ }\r
+\r
+ return Status;\r
+}\r
+\r
+\r
/**\r
Returns a map of the memory resources in the global coherency domain of the\r
processor.\r
\r
- @param NumberOfDescriptors Number of descriptors. \r
- @param MemorySpaceMap Descriptor array \r
+ @param NumberOfDescriptors Number of descriptors.\r
+ @param MemorySpaceMap Descriptor array\r
\r
- @retval EFI_INVALID_PARAMETER Invalid parameter \r
- @retval EFI_OUT_OF_RESOURCES No enough buffer to allocate \r
+ @retval EFI_INVALID_PARAMETER Invalid parameter\r
+ @retval EFI_OUT_OF_RESOURCES No enough buffer to allocate\r
@retval EFI_SUCCESS Successfully get memory space map.\r
\r
**/\r
EFI_STATUS\r
+EFIAPI\r
CoreGetMemorySpaceMap (\r
OUT UINTN *NumberOfDescriptors,\r
OUT EFI_GCD_MEMORY_SPACE_DESCRIPTOR **MemorySpaceMap\r
//\r
// Allocate the MemorySpaceMap\r
//\r
- *MemorySpaceMap = CoreAllocateBootServicesPool (*NumberOfDescriptors * sizeof (EFI_GCD_MEMORY_SPACE_DESCRIPTOR));\r
+ *MemorySpaceMap = AllocatePool (*NumberOfDescriptors * sizeof (EFI_GCD_MEMORY_SPACE_DESCRIPTOR));\r
if (*MemorySpaceMap == NULL) {\r
Status = EFI_OUT_OF_RESOURCES;\r
goto Done;\r
/**\r
Adds reserved I/O or I/O resources to the global coherency domain of the processor.\r
\r
- @param GcdIoType IO type of the segment. \r
- @param BaseAddress Base address of the segment. \r
- @param Length Length of the segment. \r
+ @param GcdIoType IO type of the segment.\r
+ @param BaseAddress Base address of the segment.\r
+ @param Length Length of the segment.\r
\r
- @retval EFI_SUCCESS Merged this segment into GCD map. \r
+ @retval EFI_SUCCESS Merged this segment into GCD map.\r
@retval EFI_INVALID_PARAMETER Parameter not valid\r
\r
**/\r
EFI_STATUS\r
+EFIAPI\r
CoreAddIoSpace (\r
IN EFI_GCD_IO_TYPE GcdIoType,\r
IN EFI_PHYSICAL_ADDRESS BaseAddress,\r
IN UINT64 Length\r
)\r
{\r
+ DEBUG ((DEBUG_GCD, "GCD:AddIoSpace(Base=%016lx,Length=%016lx)\n", BaseAddress, Length));\r
+ DEBUG ((DEBUG_GCD, " GcdIoType = %a\n", mGcdIoTypeNames[MIN (GcdIoType, EfiGcdIoTypeMaximum)]));\r
+ \r
//\r
// Make sure parameters are valid\r
//\r
Allocates nonexistent I/O, reserved I/O, or I/O resources from the global coherency\r
domain of the processor.\r
\r
- @param GcdAllocateType The type of allocate operation \r
- @param GcdIoType The desired IO type \r
- @param Alignment Align with 2^Alignment \r
- @param Length Length to allocate \r
- @param BaseAddress Base address to allocate \r
- @param ImageHandle The image handle consume the allocated space. \r
- @param DeviceHandle The device handle consume the allocated space. \r
+ @param GcdAllocateType The type of allocate operation\r
+ @param GcdIoType The desired IO type\r
+ @param Alignment Align with 2^Alignment\r
+ @param Length Length to allocate\r
+ @param BaseAddress Base address to allocate\r
+ @param ImageHandle The image handle consume the allocated space.\r
+ @param DeviceHandle The device handle consume the allocated space.\r
\r
- @retval EFI_INVALID_PARAMETER Invalid parameter. \r
- @retval EFI_NOT_FOUND No descriptor contains the desired space. \r
+ @retval EFI_INVALID_PARAMETER Invalid parameter.\r
+ @retval EFI_NOT_FOUND No descriptor contains the desired space.\r
@retval EFI_SUCCESS IO space successfully allocated.\r
\r
**/\r
EFI_STATUS\r
+EFIAPI\r
CoreAllocateIoSpace (\r
IN EFI_GCD_ALLOCATE_TYPE GcdAllocateType,\r
IN EFI_GCD_IO_TYPE GcdIoType,\r
IN EFI_HANDLE DeviceHandle OPTIONAL\r
)\r
{\r
+ DEBUG ((DEBUG_GCD, "GCD:AllocateIoSpace(Base=%016lx,Length=%016lx)\n", *BaseAddress, Length));\r
+ DEBUG ((DEBUG_GCD, " GcdAllocateType = %a\n", mGcdAllocationTypeNames[MIN (GcdAllocateType, EfiGcdMaxAllocateType)]));\r
+ DEBUG ((DEBUG_GCD, " GcdIoType = %a\n", mGcdIoTypeNames[MIN (GcdIoType, EfiGcdIoTypeMaximum)]));\r
+ DEBUG ((DEBUG_GCD, " Alignment = %016lx\n", LShiftU64 (1, Alignment)));\r
+ DEBUG ((DEBUG_GCD, " ImageHandle = %p\n", ImageHandle));\r
+ DEBUG ((DEBUG_GCD, " DeviceHandle = %p\n", DeviceHandle));\r
+ \r
return CoreAllocateSpace (\r
- GCD_ALLOCATE_IO_OPERATION, \r
- GcdAllocateType, \r
- (EFI_GCD_MEMORY_TYPE) 0, \r
- GcdIoType, \r
- Alignment, \r
- Length, \r
- BaseAddress, \r
- ImageHandle, \r
+ GCD_ALLOCATE_IO_OPERATION,\r
+ GcdAllocateType,\r
+ (EFI_GCD_MEMORY_TYPE) 0,\r
+ GcdIoType,\r
+ Alignment,\r
+ Length,\r
+ BaseAddress,\r
+ ImageHandle,\r
DeviceHandle\r
);\r
}\r
Frees nonexistent I/O, reserved I/O, or I/O resources from the global coherency\r
domain of the processor.\r
\r
- @param BaseAddress Base address of the segment. \r
- @param Length Length of the segment. \r
+ @param BaseAddress Base address of the segment.\r
+ @param Length Length of the segment.\r
\r
@retval EFI_SUCCESS Space successfully freed.\r
\r
**/\r
EFI_STATUS\r
+EFIAPI\r
CoreFreeIoSpace (\r
IN EFI_PHYSICAL_ADDRESS BaseAddress,\r
IN UINT64 Length\r
)\r
{\r
+ DEBUG ((DEBUG_GCD, "GCD:FreeIoSpace(Base=%016lx,Length=%016lx)\n", BaseAddress, Length));\r
+\r
return CoreConvertSpace (GCD_FREE_IO_OPERATION, (EFI_GCD_MEMORY_TYPE) 0, (EFI_GCD_IO_TYPE) 0, BaseAddress, Length, 0, 0);\r
}\r
\r
Removes reserved I/O or I/O resources from the global coherency domain of the\r
processor.\r
\r
- @param BaseAddress Base address of the segment. \r
- @param Length Length of the segment. \r
+ @param BaseAddress Base address of the segment.\r
+ @param Length Length of the segment.\r
\r
@retval EFI_SUCCESS Successfully removed a segment of IO space.\r
\r
**/\r
EFI_STATUS\r
+EFIAPI\r
CoreRemoveIoSpace (\r
IN EFI_PHYSICAL_ADDRESS BaseAddress,\r
IN UINT64 Length\r
)\r
{\r
+ DEBUG ((DEBUG_GCD, "GCD:RemoveIoSpace(Base=%016lx,Length=%016lx)\n", BaseAddress, Length));\r
+ \r
return CoreConvertSpace (GCD_REMOVE_IO_OPERATION, (EFI_GCD_MEMORY_TYPE) 0, (EFI_GCD_IO_TYPE) 0, BaseAddress, Length, 0, 0);\r
}\r
\r
/**\r
Build a IO descriptor according to an entry.\r
\r
- @param Descriptor The descriptor to be built \r
+ @param Descriptor The descriptor to be built\r
@param Entry According to this entry\r
\r
**/\r
-STATIC\r
VOID\r
BuildIoDescriptor (\r
IN EFI_GCD_IO_SPACE_DESCRIPTOR *Descriptor,\r
/**\r
Retrieves the descriptor for an I/O region containing a specified address.\r
\r
- @param BaseAddress Specified start address \r
- @param Descriptor Specified length \r
+ @param BaseAddress Specified start address\r
+ @param Descriptor Specified length\r
\r
- @retval EFI_INVALID_PARAMETER Descriptor is NULL. \r
+ @retval EFI_INVALID_PARAMETER Descriptor is NULL.\r
@retval EFI_SUCCESS Successfully get the IO space descriptor.\r
\r
**/\r
EFI_STATUS\r
+EFIAPI\r
CoreGetIoSpaceDescriptor (\r
IN EFI_PHYSICAL_ADDRESS BaseAddress,\r
OUT EFI_GCD_IO_SPACE_DESCRIPTOR *Descriptor\r
CoreAcquireGcdIoLock ();\r
\r
//\r
- // Search for the list of descriptors that contain BaseAddress \r
+ // Search for the list of descriptors that contain BaseAddress\r
//\r
Status = CoreSearchGcdMapEntry (BaseAddress, 1, &StartLink, &EndLink, &mGcdIoSpaceMap);\r
if (EFI_ERROR (Status)) {\r
Status = EFI_NOT_FOUND;\r
} else {\r
+ ASSERT (StartLink != NULL && EndLink != NULL);\r
//\r
// Copy the contents of the found descriptor into Descriptor\r
//\r
/**\r
Returns a map of the I/O resources in the global coherency domain of the processor.\r
\r
- @param NumberOfDescriptors Number of descriptors. \r
- @param IoSpaceMap Descriptor array \r
+ @param NumberOfDescriptors Number of descriptors.\r
+ @param IoSpaceMap Descriptor array\r
\r
- @retval EFI_INVALID_PARAMETER Invalid parameter \r
- @retval EFI_OUT_OF_RESOURCES No enough buffer to allocate \r
+ @retval EFI_INVALID_PARAMETER Invalid parameter\r
+ @retval EFI_OUT_OF_RESOURCES No enough buffer to allocate\r
@retval EFI_SUCCESS Successfully get IO space map.\r
\r
**/\r
EFI_STATUS\r
+EFIAPI\r
CoreGetIoSpaceMap (\r
OUT UINTN *NumberOfDescriptors,\r
OUT EFI_GCD_IO_SPACE_DESCRIPTOR **IoSpaceMap\r
//\r
// Allocate the IoSpaceMap\r
//\r
- *IoSpaceMap = CoreAllocateBootServicesPool (*NumberOfDescriptors * sizeof (EFI_GCD_IO_SPACE_DESCRIPTOR));\r
+ *IoSpaceMap = AllocatePool (*NumberOfDescriptors * sizeof (EFI_GCD_IO_SPACE_DESCRIPTOR));\r
if (*IoSpaceMap == NULL) {\r
Status = EFI_OUT_OF_RESOURCES;\r
goto Done;\r
Done:\r
CoreReleaseGcdIoLock ();\r
return Status;\r
-} \r
+}\r
\r
\r
/**\r
Converts a Resource Descriptor HOB attributes mask to an EFI Memory Descriptor\r
capabilities mask\r
\r
- @param GcdMemoryType Type of resource in the GCD memory map. \r
- @param Attributes The attribute mask in the Resource Descriptor \r
- HOB. \r
+ @param GcdMemoryType Type of resource in the GCD memory map.\r
+ @param Attributes The attribute mask in the Resource Descriptor\r
+ HOB.\r
\r
@return The capabilities mask for an EFI Memory Descriptor.\r
\r
**/\r
-STATIC\r
UINT64\r
CoreConvertResourceDescriptorHobAttributesToCapabilities (\r
EFI_GCD_MEMORY_TYPE GcdMemoryType,\r
{\r
UINT64 Capabilities;\r
GCD_ATTRIBUTE_CONVERSION_ENTRY *Conversion;\r
- \r
+\r
//\r
// Convert the Resource HOB Attributes to an EFI Memory Capabilities mask\r
//\r
for (Capabilities = 0, Conversion = mAttributeConversionTable; Conversion->Attribute != 0; Conversion++) {\r
- if (Conversion->Memory || (GcdMemoryType != EfiGcdMemoryTypeSystemMemory)) {\r
+ if (Conversion->Memory || ((GcdMemoryType != EfiGcdMemoryTypeSystemMemory) && (GcdMemoryType != EfiGcdMemoryTypeMoreReliable))) {\r
if (Attributes & Conversion->Attribute) {\r
Capabilities |= Conversion->Capability;\r
}\r
}\r
}\r
- \r
+\r
return Capabilities;\r
}\r
\r
\r
/**\r
- External function. Initializes the GCD and memory services based on the memory\r
- descriptor HOBs. This function is responsible for priming the GCD map and the\r
- memory map, so memory allocations and resource allocations can be made. The first\r
- part of this function can not depend on any memory services until at least one\r
- memory descriptor is provided to the memory services. Then the memory services\r
- can be used to intialize the GCD map.\r
+ External function. Initializes memory services based on the memory\r
+ descriptor HOBs. This function is responsible for priming the memory\r
+ map, so memory allocations and resource allocations can be made.\r
+ The first part of this function can not depend on any memory services\r
+ until at least one memory descriptor is provided to the memory services.\r
\r
- @param HobStart The start address of the HOB. \r
- @param MemoryBaseAddress Start address of memory region found to init DXE \r
- core. \r
- @param MemoryLength Length of memory region found to init DXE core. \r
+ @param HobStart The start address of the HOB.\r
+ @param MemoryBaseAddress Start address of memory region found to init DXE\r
+ core.\r
+ @param MemoryLength Length of memory region found to init DXE core.\r
\r
@retval EFI_SUCCESS Memory services successfully initialized.\r
\r
EFI_PHYSICAL_ADDRESS MaxMemoryBaseAddress;\r
UINT64 MaxMemoryLength;\r
UINT64 MaxMemoryAttributes;\r
- EFI_PHYSICAL_ADDRESS MaxAddress;\r
+ EFI_PHYSICAL_ADDRESS TestedMemoryBaseAddress;\r
+ UINT64 TestedMemoryLength;\r
EFI_PHYSICAL_ADDRESS HighAddress;\r
- EFI_HOB_RESOURCE_DESCRIPTOR *MaxResourceHob;\r
EFI_HOB_GUID_TYPE *GuidHob;\r
+ UINT32 ReservedCodePageNumber;\r
\r
//\r
// Point at the first HOB. This must be the PHIT HOB.\r
// Initialize Local Variables\r
//\r
PhitResourceHob = NULL;\r
- MaxResourceHob = NULL;\r
ResourceHob = NULL;\r
BaseAddress = 0;\r
Length = 0;\r
// Cache the PHIT HOB for later use\r
//\r
PhitHob = Hob.HandoffInformationTable;\r
-\r
+ \r
+ if (PcdGet64(PcdLoadModuleAtFixAddressEnable) != 0) {\r
+ ReservedCodePageNumber = PcdGet32(PcdLoadFixAddressRuntimeCodePageNumber);\r
+ ReservedCodePageNumber += PcdGet32(PcdLoadFixAddressBootTimeCodePageNumber);\r
+ \r
+ //\r
+ // cache the Top address for loading modules at Fixed Address \r
+ //\r
+ gLoadModuleAtFixAddressConfigurationTable.DxeCodeTopAddress = PhitHob->EfiMemoryTop \r
+ + EFI_PAGES_TO_SIZE(ReservedCodePageNumber);\r
+ }\r
//\r
// See if a Memory Type Information HOB is available\r
//\r
}\r
\r
//\r
- // Find the Resource Descriptor HOB that contains range FreeMemoryBaseAddress..FreeMemoryLength\r
+ // Find the Resource Descriptor HOB that contains PHIT range EfiFreeMemoryBottom..EfiFreeMemoryTop\r
//\r
Length = 0;\r
Found = FALSE;\r
for (Hob.Raw = *HobStart; !END_OF_HOB_LIST(Hob); Hob.Raw = GET_NEXT_HOB(Hob)) {\r
+ //\r
+ // Skip all HOBs except Resource Descriptor HOBs\r
+ //\r
+ if (GET_HOB_TYPE (Hob) != EFI_HOB_TYPE_RESOURCE_DESCRIPTOR) {\r
+ continue;\r
+ }\r
\r
- if (GET_HOB_TYPE (Hob) == EFI_HOB_TYPE_RESOURCE_DESCRIPTOR) {\r
-\r
- ResourceHob = Hob.ResourceDescriptor;\r
+ //\r
+ // Skip Resource Descriptor HOBs that do not describe tested system memory\r
+ //\r
+ ResourceHob = Hob.ResourceDescriptor;\r
+ if (ResourceHob->ResourceType != EFI_RESOURCE_SYSTEM_MEMORY) {\r
+ continue;\r
+ }\r
+ if ((ResourceHob->ResourceAttribute & MEMORY_ATTRIBUTE_MASK) != TESTED_MEMORY_ATTRIBUTES) {\r
+ continue;\r
+ }\r
\r
- if (ResourceHob->ResourceType == EFI_RESOURCE_SYSTEM_MEMORY &&\r
- (ResourceHob->ResourceAttribute & MEMORY_ATTRIBUTE_MASK) == TESTED_MEMORY_ATTRIBUTES ) {\r
+ //\r
+ // Skip Resource Descriptor HOBs that do not contain the PHIT range EfiFreeMemoryBottom..EfiFreeMemoryTop\r
+ //\r
+ if (PhitHob->EfiFreeMemoryBottom < ResourceHob->PhysicalStart) {\r
+ continue;\r
+ }\r
+ if (PhitHob->EfiFreeMemoryTop > (ResourceHob->PhysicalStart + ResourceHob->ResourceLength)) {\r
+ continue;\r
+ }\r
\r
- if (PhitHob->EfiFreeMemoryBottom >= ResourceHob->PhysicalStart && \r
- PhitHob->EfiFreeMemoryTop <= (ResourceHob->PhysicalStart + ResourceHob->ResourceLength) ) {\r
+ //\r
+ // Cache the resource descriptor HOB for the memory region described by the PHIT HOB\r
+ //\r
+ PhitResourceHob = ResourceHob;\r
+ Found = TRUE;\r
\r
- //\r
- // Cache the resource descriptor HOB for the memory region described by the PHIT HOB\r
- //\r
- PhitResourceHob = ResourceHob;\r
- Found = TRUE;\r
-\r
- Attributes = PhitResourceHob->ResourceAttribute;\r
- BaseAddress = PageAlignAddress (PhitHob->EfiMemoryTop);\r
- Length = PageAlignLength (ResourceHob->PhysicalStart + ResourceHob->ResourceLength - BaseAddress);\r
- if (Length < MINIMUM_INITIAL_MEMORY_SIZE) {\r
- BaseAddress = PageAlignAddress (PhitHob->EfiFreeMemoryBottom);\r
- Length = PageAlignLength (PhitHob->EfiFreeMemoryTop - BaseAddress);\r
- if (Length < MINIMUM_INITIAL_MEMORY_SIZE) {\r
- BaseAddress = PageAlignAddress (ResourceHob->PhysicalStart);\r
- Length = PageAlignLength ((UINT64)((UINTN)*HobStart - BaseAddress));\r
- }\r
- }\r
- break;\r
- }\r
+ //\r
+ // Compute range between PHIT EfiFreeMemoryTop and the end of the Resource Descriptor HOB\r
+ //\r
+ Attributes = PhitResourceHob->ResourceAttribute;\r
+ BaseAddress = PageAlignAddress (PhitHob->EfiMemoryTop);\r
+ Length = PageAlignLength (ResourceHob->PhysicalStart + ResourceHob->ResourceLength - BaseAddress);\r
+ if (Length < MINIMUM_INITIAL_MEMORY_SIZE) {\r
+ //\r
+ // If that range is not large enough to intialize the DXE Core, then \r
+ // Compute range between PHIT EfiFreeMemoryBottom and PHIT EfiFreeMemoryTop\r
+ //\r
+ BaseAddress = PageAlignAddress (PhitHob->EfiFreeMemoryBottom);\r
+ Length = PageAlignLength (PhitHob->EfiFreeMemoryTop - BaseAddress);\r
+ if (Length < MINIMUM_INITIAL_MEMORY_SIZE) {\r
+ //\r
+ // If that range is not large enough to intialize the DXE Core, then \r
+ // Compute range between the start of the Resource Descriptor HOB and the start of the HOB List\r
+ //\r
+ BaseAddress = PageAlignAddress (ResourceHob->PhysicalStart);\r
+ Length = PageAlignLength ((UINT64)((UINTN)*HobStart - BaseAddress));\r
}\r
}\r
+ break;\r
}\r
\r
//\r
// region that is big enough to initialize the DXE core. Always skip the PHIT Resource HOB.\r
// The max address must be within the physically addressible range for the processor.\r
//\r
- MaxMemoryLength = 0;\r
- MaxAddress = EFI_MAX_ADDRESS;\r
- do {\r
- HighAddress = 0;\r
- Found = FALSE;\r
+ HighAddress = MAX_ADDRESS;\r
+ for (Hob.Raw = *HobStart; !END_OF_HOB_LIST(Hob); Hob.Raw = GET_NEXT_HOB(Hob)) {\r
//\r
- // Search for a tested memory region that is below MaxAddress\r
+ // Skip the Resource Descriptor HOB that contains the PHIT\r
//\r
- for (Hob.Raw = *HobStart; !END_OF_HOB_LIST(Hob); Hob.Raw = GET_NEXT_HOB(Hob)) {\r
-\r
- //\r
- // See if this is a resource descriptor HOB that does not contain the PHIT.\r
- //\r
- if (Hob.ResourceDescriptor != PhitResourceHob && GET_HOB_TYPE (Hob) == EFI_HOB_TYPE_RESOURCE_DESCRIPTOR) {\r
-\r
- ResourceHob = Hob.ResourceDescriptor;\r
- //\r
- // See if this resource descrior HOB describes tested system memory below MaxAddress\r
- //\r
- if (ResourceHob->ResourceType == EFI_RESOURCE_SYSTEM_MEMORY &&\r
- (ResourceHob->ResourceAttribute & MEMORY_ATTRIBUTE_MASK) == TESTED_MEMORY_ATTRIBUTES &&\r
- ResourceHob->PhysicalStart + ResourceHob->ResourceLength <= MaxAddress ) {\r
-\r
- //\r
- // See if this is the highest tested system memory region below MaxAddress\r
- //\r
- if (ResourceHob->PhysicalStart > HighAddress) {\r
+ if (Hob.ResourceDescriptor == PhitResourceHob) {\r
+ continue;\r
+ }\r
+ //\r
+ // Skip all HOBs except Resource Descriptor HOBs\r
+ //\r
+ if (GET_HOB_TYPE (Hob) != EFI_HOB_TYPE_RESOURCE_DESCRIPTOR) {\r
+ continue;\r
+ }\r
\r
- MaxResourceHob = ResourceHob;\r
- HighAddress = MaxResourceHob->PhysicalStart;\r
- Found = TRUE;\r
- }\r
- }\r
- }\r
+ //\r
+ // Skip Resource Descriptor HOBs that do not describe tested system memory below MAX_ADDRESS\r
+ //\r
+ ResourceHob = Hob.ResourceDescriptor;\r
+ if (ResourceHob->ResourceType != EFI_RESOURCE_SYSTEM_MEMORY) {\r
+ continue;\r
}\r
- if (Found) {\r
- //\r
- // Compute the size of the tested memory region below MaxAddrees\r
- //\r
- MaxMemoryBaseAddress = PageAlignAddress (MaxResourceHob->PhysicalStart);\r
- MaxMemoryLength = PageAlignLength (MaxResourceHob->PhysicalStart + MaxResourceHob->ResourceLength - MaxMemoryBaseAddress);\r
- MaxMemoryAttributes = MaxResourceHob->ResourceAttribute;\r
+ if ((ResourceHob->ResourceAttribute & MEMORY_ATTRIBUTE_MASK) != TESTED_MEMORY_ATTRIBUTES) {\r
+ continue;\r
+ }\r
+ if ((ResourceHob->PhysicalStart + ResourceHob->ResourceLength) > (EFI_PHYSICAL_ADDRESS)MAX_ADDRESS) {\r
+ continue;\r
+ }\r
+ \r
+ //\r
+ // Skip Resource Descriptor HOBs that are below a previously found Resource Descriptor HOB\r
+ //\r
+ if (HighAddress != (EFI_PHYSICAL_ADDRESS)MAX_ADDRESS && ResourceHob->PhysicalStart <= HighAddress) {\r
+ continue;\r
}\r
- MaxAddress = ResourceHob->PhysicalStart;\r
- } while (Found && MaxMemoryLength < MINIMUM_INITIAL_MEMORY_SIZE);\r
+\r
+ //\r
+ // Skip Resource Descriptor HOBs that are not large enough to initilize the DXE Core\r
+ //\r
+ TestedMemoryBaseAddress = PageAlignAddress (ResourceHob->PhysicalStart);\r
+ TestedMemoryLength = PageAlignLength (ResourceHob->PhysicalStart + ResourceHob->ResourceLength - TestedMemoryBaseAddress);\r
+ if (TestedMemoryLength < MINIMUM_INITIAL_MEMORY_SIZE) {\r
+ continue;\r
+ }\r
+ \r
+ //\r
+ // Save the Resource Descriptor HOB context that is large enough to initilize the DXE Core\r
+ //\r
+ MaxMemoryBaseAddress = TestedMemoryBaseAddress;\r
+ MaxMemoryLength = TestedMemoryLength;\r
+ MaxMemoryAttributes = ResourceHob->ResourceAttribute; \r
+ HighAddress = ResourceHob->PhysicalStart;\r
+ }\r
\r
//\r
+ // If Length is not large enough to initialize the DXE Core or a Resource \r
+ // Descriptor HOB was found above the PHIT HOB that is large enough to initialize \r
+ // the DXE Core, then use the range described by the Resource Descriptor \r
+ // HOB that was found above the PHIT HOB.\r
//\r
- //\r
- if ((Length < MINIMUM_INITIAL_MEMORY_SIZE) ||\r
- (MaxMemoryBaseAddress > BaseAddress && MaxMemoryLength >= MINIMUM_INITIAL_MEMORY_SIZE) ) {\r
+ if ((Length < MINIMUM_INITIAL_MEMORY_SIZE) ||\r
+ (MaxMemoryBaseAddress > BaseAddress && MaxMemoryLength >= MINIMUM_INITIAL_MEMORY_SIZE)) {\r
BaseAddress = MaxMemoryBaseAddress;\r
Length = MaxMemoryLength;\r
Attributes = MaxMemoryAttributes;\r
//\r
// Convert the Resource HOB Attributes to an EFI Memory Capabilities mask\r
//\r
- Capabilities = CoreConvertResourceDescriptorHobAttributesToCapabilities (EfiGcdMemoryTypeSystemMemory, Attributes);\r
+ if ((Attributes & EFI_RESOURCE_ATTRIBUTE_MORE_RELIABLE) == EFI_RESOURCE_ATTRIBUTE_MORE_RELIABLE) {\r
+ Capabilities = CoreConvertResourceDescriptorHobAttributesToCapabilities (EfiGcdMemoryTypeMoreReliable, Attributes);\r
+ } else {\r
+ Capabilities = CoreConvertResourceDescriptorHobAttributesToCapabilities (EfiGcdMemoryTypeSystemMemory, Attributes);\r
+ }\r
\r
//\r
// Declare the very first memory region, so the EFI Memory Services are available.\r
/**\r
External function. Initializes the GCD and memory services based on the memory\r
descriptor HOBs. This function is responsible for priming the GCD map and the\r
- memory map, so memory allocations and resource allocations can be made. The first\r
- part of this function can not depend on any memory services until at least one\r
- memory descriptor is provided to the memory services. Then the memory services\r
- can be used to intialize the GCD map. The HobStart will be relocated to a pool\r
- buffer.\r
+ memory map, so memory allocations and resource allocations can be made. The\r
+ HobStart will be relocated to a pool buffer.\r
\r
- @param HobStart The start address of the HOB \r
- @param MemoryBaseAddress Start address of memory region found to init DXE \r
- core. \r
- @param MemoryLength Length of memory region found to init DXE core. \r
+ @param HobStart The start address of the HOB\r
+ @param MemoryBaseAddress Start address of memory region found to init DXE\r
+ core.\r
+ @param MemoryLength Length of memory region found to init DXE core.\r
\r
@retval EFI_SUCCESS GCD services successfully initialized.\r
\r
**/\r
EFI_STATUS\r
CoreInitializeGcdServices (\r
- IN OUT VOID **HobStart,\r
+ IN OUT VOID **HobStart,\r
IN EFI_PHYSICAL_ADDRESS MemoryBaseAddress,\r
IN UINT64 MemoryLength\r
)\r
{\r
- EFI_PEI_HOB_POINTERS Hob;\r
+ EFI_PEI_HOB_POINTERS Hob;\r
VOID *NewHobList;\r
- EFI_HOB_HANDOFF_INFO_TABLE *PhitHob;\r
+ EFI_HOB_HANDOFF_INFO_TABLE *PhitHob;\r
UINT8 SizeOfMemorySpace;\r
UINT8 SizeOfIoSpace;\r
EFI_HOB_RESOURCE_DESCRIPTOR *ResourceHob;\r
UINTN Index;\r
UINT64 Capabilities;\r
EFI_HOB_CPU * CpuHob;\r
+ EFI_GCD_MEMORY_SPACE_DESCRIPTOR *MemorySpaceMapHobList;\r
+\r
//\r
// Cache the PHIT HOB for later use\r
//\r
ASSERT (CpuHob != NULL);\r
SizeOfMemorySpace = CpuHob->SizeOfMemorySpace;\r
SizeOfIoSpace = CpuHob->SizeOfIoSpace;\r
- \r
+\r
//\r
// Initialize the GCD Memory Space Map\r
//\r
- Entry = CoreAllocateCopyPool (sizeof (EFI_GCD_MAP_ENTRY), &mGcdMemorySpaceMapEntryTemplate);\r
+ Entry = AllocateCopyPool (sizeof (EFI_GCD_MAP_ENTRY), &mGcdMemorySpaceMapEntryTemplate);\r
ASSERT (Entry != NULL);\r
\r
Entry->EndAddress = LShiftU64 (1, SizeOfMemorySpace) - 1;\r
\r
InsertHeadList (&mGcdMemorySpaceMap, &Entry->Link);\r
\r
+ CoreDumpGcdMemorySpaceMap (TRUE);\r
+ \r
//\r
// Initialize the GCD I/O Space Map\r
//\r
- Entry = CoreAllocateCopyPool (sizeof (EFI_GCD_MAP_ENTRY), &mGcdIoSpaceMapEntryTemplate);\r
+ Entry = AllocateCopyPool (sizeof (EFI_GCD_MAP_ENTRY), &mGcdIoSpaceMapEntryTemplate);\r
ASSERT (Entry != NULL);\r
\r
Entry->EndAddress = LShiftU64 (1, SizeOfIoSpace) - 1;\r
\r
InsertHeadList (&mGcdIoSpaceMap, &Entry->Link);\r
\r
+ CoreDumpGcdIoSpaceMap (TRUE);\r
+ \r
//\r
- // Walk the HOB list and add all resource descriptors to the GCD \r
+ // Walk the HOB list and add all resource descriptors to the GCD\r
//\r
for (Hob.Raw = *HobStart; !END_OF_HOB_LIST(Hob); Hob.Raw = GET_NEXT_HOB(Hob)) {\r
\r
switch (ResourceHob->ResourceType) {\r
case EFI_RESOURCE_SYSTEM_MEMORY:\r
if ((ResourceHob->ResourceAttribute & MEMORY_ATTRIBUTE_MASK) == TESTED_MEMORY_ATTRIBUTES) {\r
- GcdMemoryType = EfiGcdMemoryTypeSystemMemory;\r
+ if ((ResourceHob->ResourceAttribute & EFI_RESOURCE_ATTRIBUTE_MORE_RELIABLE) == EFI_RESOURCE_ATTRIBUTE_MORE_RELIABLE) {\r
+ GcdMemoryType = EfiGcdMemoryTypeMoreReliable;\r
+ } else {\r
+ GcdMemoryType = EfiGcdMemoryTypeSystemMemory;\r
+ }\r
}\r
if ((ResourceHob->ResourceAttribute & MEMORY_ATTRIBUTE_MASK) == INITIALIZED_MEMORY_ATTRIBUTES) {\r
GcdMemoryType = EfiGcdMemoryTypeReserved;\r
if ((ResourceHob->ResourceAttribute & MEMORY_ATTRIBUTE_MASK) == PRESENT_MEMORY_ATTRIBUTES) {\r
GcdMemoryType = EfiGcdMemoryTypeReserved;\r
}\r
+ if ((ResourceHob->ResourceAttribute & EFI_RESOURCE_ATTRIBUTE_PERSISTENT) == EFI_RESOURCE_ATTRIBUTE_PERSISTENT) {\r
+ GcdMemoryType = EfiGcdMemoryTypePersistentMemory;\r
+ }\r
break;\r
case EFI_RESOURCE_MEMORY_MAPPED_IO:\r
case EFI_RESOURCE_FIRMWARE_DEVICE:\r
}\r
\r
if (GcdMemoryType != EfiGcdMemoryTypeNonExistent) {\r
+ //\r
+ // Validate the Resource HOB Attributes\r
+ //\r
+ CoreValidateResourceDescriptorHobAttributes (ResourceHob->ResourceAttribute);\r
\r
//\r
// Convert the Resource HOB Attributes to an EFI Memory Capabilities mask\r
//\r
// Allocate first memory region from the GCD by the DXE core\r
//\r
- Status = CoreAllocateMemorySpace (\r
- EfiGcdAllocateAddress,\r
- EfiGcdMemoryTypeSystemMemory,\r
- 0,\r
- MemoryLength,\r
- &MemoryBaseAddress,\r
- gDxeCoreImageHandle,\r
- NULL\r
- );\r
+ Status = CoreGetMemorySpaceDescriptor (MemoryBaseAddress, &Descriptor);\r
+ if (!EFI_ERROR (Status)) {\r
+ ASSERT ((Descriptor.GcdMemoryType == EfiGcdMemoryTypeSystemMemory) ||\r
+ (Descriptor.GcdMemoryType == EfiGcdMemoryTypeMoreReliable));\r
+ Status = CoreAllocateMemorySpace (\r
+ EfiGcdAllocateAddress,\r
+ Descriptor.GcdMemoryType,\r
+ 0,\r
+ MemoryLength,\r
+ &MemoryBaseAddress,\r
+ gDxeCoreImageHandle,\r
+ NULL\r
+ );\r
+ }\r
\r
//\r
// Walk the HOB list and allocate all memory space that is consumed by memory allocation HOBs,\r
if (!EFI_ERROR (Status)) {\r
Status = CoreAllocateMemorySpace (\r
EfiGcdAllocateAddress,\r
- Descriptor.GcdMemoryType, \r
+ Descriptor.GcdMemoryType,\r
0,\r
MemoryHob->AllocDescriptor.MemoryLength,\r
&BaseAddress,\r
gDxeCoreImageHandle,\r
NULL\r
);\r
- if (!EFI_ERROR (Status) && Descriptor.GcdMemoryType == EfiGcdMemoryTypeSystemMemory) {\r
+ if (!EFI_ERROR (Status) &&\r
+ ((Descriptor.GcdMemoryType == EfiGcdMemoryTypeSystemMemory) ||\r
+ (Descriptor.GcdMemoryType == EfiGcdMemoryTypeMoreReliable))) {\r
CoreAddMemoryDescriptor (\r
MemoryHob->AllocDescriptor.MemoryType,\r
MemoryHob->AllocDescriptor.MemoryBaseAddress,\r
BaseAddress = FirmwareVolumeHob->BaseAddress;\r
Status = CoreAllocateMemorySpace (\r
EfiGcdAllocateAddress,\r
- EfiGcdMemoryTypeMemoryMappedIo, \r
+ EfiGcdMemoryTypeMemoryMappedIo,\r
0,\r
FirmwareVolumeHob->Length,\r
&BaseAddress,\r
}\r
}\r
\r
- //\r
- // Relocate HOB List to an allocated pool buffer.\r
- //\r
- NewHobList = CoreAllocateCopyPool (\r
- (UINTN)PhitHob->EfiFreeMemoryBottom - (UINTN)(*HobStart), \r
- *HobStart\r
- );\r
- ASSERT (NewHobList != NULL);\r
-\r
- *HobStart = NewHobList;\r
- gHobList = NewHobList;\r
-\r
//\r
// Add and allocate the remaining unallocated system memory to the memory services.\r
//\r
Status = CoreGetMemorySpaceMap (&NumberOfDescriptors, &MemorySpaceMap);\r
+ ASSERT (Status == EFI_SUCCESS);\r
+\r
+ MemorySpaceMapHobList = NULL;\r
for (Index = 0; Index < NumberOfDescriptors; Index++) {\r
- if (MemorySpaceMap[Index].GcdMemoryType == EfiGcdMemoryTypeSystemMemory) {\r
+ if ((MemorySpaceMap[Index].GcdMemoryType == EfiGcdMemoryTypeSystemMemory) ||\r
+ (MemorySpaceMap[Index].GcdMemoryType == EfiGcdMemoryTypeMoreReliable)) {\r
if (MemorySpaceMap[Index].ImageHandle == NULL) {\r
BaseAddress = PageAlignAddress (MemorySpaceMap[Index].BaseAddress);\r
Length = PageAlignLength (MemorySpaceMap[Index].BaseAddress + MemorySpaceMap[Index].Length - BaseAddress);\r
if (Length == 0 || MemorySpaceMap[Index].BaseAddress + MemorySpaceMap[Index].Length < BaseAddress) {\r
continue;\r
}\r
+ if (((UINTN) MemorySpaceMap[Index].BaseAddress <= (UINTN) (*HobStart)) &&\r
+ ((UINTN) (MemorySpaceMap[Index].BaseAddress + MemorySpaceMap[Index].Length) >= (UINTN) PhitHob->EfiFreeMemoryBottom)) {\r
+ //\r
+ // Skip the memory space that covers HOB List, it should be processed\r
+ // after HOB List relocation to avoid the resources allocated by others\r
+ // to corrupt HOB List before its relocation.\r
+ //\r
+ MemorySpaceMapHobList = &MemorySpaceMap[Index];\r
+ continue;\r
+ }\r
CoreAddMemoryDescriptor (\r
EfiConventionalMemory,\r
BaseAddress,\r
);\r
Status = CoreAllocateMemorySpace (\r
EfiGcdAllocateAddress,\r
- EfiGcdMemoryTypeSystemMemory,\r
+ MemorySpaceMap[Index].GcdMemoryType,\r
0,\r
Length,\r
&BaseAddress,\r
}\r
}\r
}\r
+\r
+ //\r
+ // Relocate HOB List to an allocated pool buffer.\r
+ // The relocation should be at after all the tested memory resources added\r
+ // (except the memory space that covers HOB List) to the memory services,\r
+ // because the memory resource found in CoreInitializeMemoryServices()\r
+ // may have not enough remaining resource for HOB List.\r
+ //\r
+ NewHobList = AllocateCopyPool (\r
+ (UINTN) PhitHob->EfiFreeMemoryBottom - (UINTN) (*HobStart),\r
+ *HobStart\r
+ );\r
+ ASSERT (NewHobList != NULL);\r
+\r
+ *HobStart = NewHobList;\r
+ gHobList = NewHobList;\r
+\r
+ if (MemorySpaceMapHobList != NULL) {\r
+ //\r
+ // Add and allocate the memory space that covers HOB List to the memory services\r
+ // after HOB List relocation.\r
+ //\r
+ BaseAddress = PageAlignAddress (MemorySpaceMapHobList->BaseAddress);\r
+ Length = PageAlignLength (MemorySpaceMapHobList->BaseAddress + MemorySpaceMapHobList->Length - BaseAddress);\r
+ CoreAddMemoryDescriptor (\r
+ EfiConventionalMemory,\r
+ BaseAddress,\r
+ RShiftU64 (Length, EFI_PAGE_SHIFT),\r
+ MemorySpaceMapHobList->Capabilities & (~EFI_MEMORY_RUNTIME)\r
+ );\r
+ Status = CoreAllocateMemorySpace (\r
+ EfiGcdAllocateAddress,\r
+ MemorySpaceMapHobList->GcdMemoryType,\r
+ 0,\r
+ Length,\r
+ &BaseAddress,\r
+ gDxeCoreImageHandle,\r
+ NULL\r
+ );\r
+ }\r
+\r
CoreFreePool (MemorySpaceMap);\r
\r
return EFI_SUCCESS;\r