]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdeModulePkg/Core/Dxe/Gcd/Gcd.c
Updated GCD implementation to consume the correct EFI Resources Attributes(Capabiliti...
[mirror_edk2.git] / MdeModulePkg / Core / Dxe / Gcd / Gcd.c
index 4927c67c18c6567e0371dac37b835f1c47d453de..5292d368c5a0a89a1aa6dd795fedf754dd86821b 100644 (file)
@@ -3,8 +3,8 @@
   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
-Copyright (c) 2006 - 2008, Intel Corporation. <BR>\r
-All rights reserved. This program and the accompanying materials\r
+Copyright (c) 2006 - 2011, 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
@@ -15,6 +15,7 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 **/\r
 \r
 #include "DxeMain.h"\r
+#include "Gcd.h"\r
 \r
 #define MINIMUM_INITIAL_MEMORY_SIZE 0x10000\r
 \r
@@ -85,15 +86,152 @@ GCD_ATTRIBUTE_CONVERSION_ENTRY mAttributeConversionTable[] = {
   { 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_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_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
 };\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
+  "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_EFI_ERROR (Status);\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_EFI_ERROR (Status);\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
+}\r
 \r
 /**\r
   Acquire memory lock on mGcdMemorySpaceLock.\r
@@ -275,10 +413,10 @@ CoreInsertGcdMapEntry (
   )\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
@@ -286,6 +424,8 @@ CoreInsertGcdMapEntry (
   }\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
@@ -570,11 +710,10 @@ CoreConvertSpace (
   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
@@ -582,10 +721,11 @@ CoreConvertSpace (
   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
@@ -597,6 +737,7 @@ CoreConvertSpace (
 \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
@@ -682,30 +823,26 @@ CoreConvertSpace (
     Status = EFI_OUT_OF_RESOURCES;\r
     goto Done;\r
   }\r
+  ASSERT (TopEntry != NULL && BottomEntry != NULL);\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
-      }\r
-\r
-      Status = CpuArch->SetMemoryAttributes (\r
-                          CpuArch,\r
-                          BaseAddress,\r
-                          Length,\r
-                          CpuArchAttributes\r
-                          );\r
-      if (EFI_ERROR (Status)) {\r
-        goto Done;\r
+    if (CpuArchAttributes != INVALID_CPU_ARCH_ATTRIBUTES) {\r
+      if (gCpu != NULL) {\r
+        Status = gCpu->SetMemoryAttributes (\r
+                         gCpu,\r
+                         BaseAddress,\r
+                         Length,\r
+                         CpuArchAttributes\r
+                         );\r
+        if (EFI_ERROR (Status)) {\r
+          goto Done;\r
+        }\r
       }\r
     }\r
-\r
   }\r
 \r
   //\r
@@ -764,11 +901,15 @@ CoreConvertSpace (
   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
@@ -867,24 +1008,31 @@ CoreAllocateSpace (
   // Make sure parameters are valid\r
   //\r
   if (GcdAllocateType < 0 || 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
+    DEBUG ((DEBUG_GCD, "  Status = %r\n", EFI_INVALID_PARAMETER));\r
     return EFI_INVALID_PARAMETER;\r
   }\r
   if (GcdIoType < 0 || 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
@@ -892,10 +1040,11 @@ CoreAllocateSpace (
   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
@@ -923,6 +1072,7 @@ CoreAllocateSpace (
       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
@@ -1006,6 +1156,7 @@ CoreAllocateSpace (
         Status = EFI_NOT_FOUND;\r
         goto Done;\r
       }\r
+      ASSERT (StartLink != NULL && EndLink != NULL);\r
 \r
       Link = StartLink;\r
       //\r
@@ -1041,6 +1192,7 @@ CoreAllocateSpace (
     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
@@ -1060,11 +1212,19 @@ CoreAllocateSpace (
   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
@@ -1091,6 +1251,10 @@ CoreInternalAddMemorySpace (
   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
@@ -1123,6 +1287,7 @@ CoreInternalAddMemorySpace (
 \r
 **/\r
 EFI_STATUS\r
+EFIAPI\r
 CoreAllocateMemorySpace (\r
   IN     EFI_GCD_ALLOCATE_TYPE  GcdAllocateType,\r
   IN     EFI_GCD_MEMORY_TYPE    GcdMemoryType,\r
@@ -1133,6 +1298,13 @@ CoreAllocateMemorySpace (
   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
@@ -1160,6 +1332,7 @@ CoreAllocateMemorySpace (
 \r
 **/\r
 EFI_STATUS\r
+EFIAPI\r
 CoreAddMemorySpace (\r
   IN EFI_GCD_MEMORY_TYPE   GcdMemoryType,\r
   IN EFI_PHYSICAL_ADDRESS  BaseAddress,\r
@@ -1233,11 +1406,14 @@ CoreAddMemorySpace (
 \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
@@ -1253,11 +1429,14 @@ CoreFreeMemorySpace (
 \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
@@ -1296,6 +1475,7 @@ BuildMemoryDescriptor (
 \r
 **/\r
 EFI_STATUS\r
+EFIAPI\r
 CoreGetMemorySpaceDescriptor (\r
   IN  EFI_PHYSICAL_ADDRESS             BaseAddress,\r
   OUT EFI_GCD_MEMORY_SPACE_DESCRIPTOR  *Descriptor\r
@@ -1322,6 +1502,7 @@ CoreGetMemorySpaceDescriptor (
   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
@@ -1348,12 +1529,16 @@ CoreGetMemorySpaceDescriptor (
 \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
@@ -1371,6 +1556,7 @@ CoreSetMemorySpaceAttributes (
 \r
 **/\r
 EFI_STATUS\r
+EFIAPI\r
 CoreGetMemorySpaceMap (\r
   OUT UINTN                            *NumberOfDescriptors,\r
   OUT EFI_GCD_MEMORY_SPACE_DESCRIPTOR  **MemorySpaceMap\r
@@ -1438,12 +1624,16 @@ Done:
 \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
@@ -1472,6 +1662,7 @@ CoreAddIoSpace (
 \r
 **/\r
 EFI_STATUS\r
+EFIAPI\r
 CoreAllocateIoSpace (\r
   IN     EFI_GCD_ALLOCATE_TYPE  GcdAllocateType,\r
   IN     EFI_GCD_IO_TYPE        GcdIoType,\r
@@ -1482,6 +1673,13 @@ CoreAllocateIoSpace (
   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
@@ -1507,11 +1705,14 @@ CoreAllocateIoSpace (
 \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
@@ -1527,11 +1728,14 @@ CoreFreeIoSpace (
 \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
@@ -1568,6 +1772,7 @@ BuildIoDescriptor (
 \r
 **/\r
 EFI_STATUS\r
+EFIAPI\r
 CoreGetIoSpaceDescriptor (\r
   IN  EFI_PHYSICAL_ADDRESS         BaseAddress,\r
   OUT EFI_GCD_IO_SPACE_DESCRIPTOR  *Descriptor\r
@@ -1594,6 +1799,7 @@ CoreGetIoSpaceDescriptor (
   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
@@ -1619,6 +1825,7 @@ CoreGetIoSpaceDescriptor (
 \r
 **/\r
 EFI_STATUS\r
+EFIAPI\r
 CoreGetIoSpaceMap (\r
   OUT UINTN                        *NumberOfDescriptors,\r
   OUT EFI_GCD_IO_SPACE_DESCRIPTOR  **IoSpaceMap\r
@@ -1710,12 +1917,11 @@ CoreConvertResourceDescriptorHobAttributesToCapabilities (
 \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
@@ -1746,10 +1952,11 @@ CoreInitializeMemoryServices (
   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
@@ -1767,7 +1974,6 @@ CoreInitializeMemoryServices (
   // Initialize Local Variables\r
   //\r
   PhitResourceHob       = NULL;\r
-  MaxResourceHob        = NULL;\r
   ResourceHob           = NULL;\r
   BaseAddress           = 0;\r
   Length                = 0;\r
@@ -1780,7 +1986,17 @@ CoreInitializeMemoryServices (
   // 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
@@ -1794,43 +2010,68 @@ CoreInitializeMemoryServices (
   }\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
+    // 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
-      ResourceHob = Hob.ResourceDescriptor;\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 (ResourceHob->ResourceType == EFI_RESOURCE_SYSTEM_MEMORY                                       &&\r
-          (ResourceHob->ResourceAttribute & MEMORY_ATTRIBUTE_MASK) == TESTED_MEMORY_ATTRIBUTES    ) {\r
-\r
-        if (PhitHob->EfiFreeMemoryBottom >= ResourceHob->PhysicalStart                         &&\r
-            PhitHob->EfiFreeMemoryTop    <= (ResourceHob->PhysicalStart + ResourceHob->ResourceLength)    ) {\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
+    // Cache the resource descriptor HOB for the memory region described by the PHIT HOB\r
+    //\r
+    PhitResourceHob = ResourceHob;\r
+    Found = TRUE;\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
@@ -1843,51 +2084,66 @@ CoreInitializeMemoryServices (
   // 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
+    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
-        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
-          // See if this is the highest tested system memory region below MaxAddress\r
-          //\r
-          if (ResourceHob->PhysicalStart > HighAddress) {\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
   if ((Length < MINIMUM_INITIAL_MEMORY_SIZE) ||\r
       (MaxMemoryBaseAddress > BaseAddress && MaxMemoryLength >= MINIMUM_INITIAL_MEMORY_SIZE)) {\r
     BaseAddress = MaxMemoryBaseAddress;\r
@@ -1925,11 +2181,8 @@ CoreInitializeMemoryServices (
 /**\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
@@ -1990,6 +2243,8 @@ CoreInitializeGcdServices (
 \r
   InsertHeadList (&mGcdMemorySpaceMap, &Entry->Link);\r
 \r
+  CoreDumpGcdMemorySpaceMap (TRUE);\r
+  \r
   //\r
   // Initialize the GCD I/O Space Map\r
   //\r
@@ -2000,6 +2255,8 @@ CoreInitializeGcdServices (
 \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
   //\r
@@ -2041,6 +2298,11 @@ CoreInitializeGcdServices (
       }\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
@@ -2141,6 +2403,8 @@ CoreInitializeGcdServices (
   // 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
   for (Index = 0; Index < NumberOfDescriptors; Index++) {\r
     if (MemorySpaceMap[Index].GcdMemoryType == EfiGcdMemoryTypeSystemMemory) {\r
       if (MemorySpaceMap[Index].ImageHandle == NULL) {\r