]> git.proxmox.com Git - mirror_edk2.git/blobdiff - UefiCpuPkg/Library/MtrrLib/MtrrLib.c
Add DEBUG() macros for DEBUG_CACHE to MTRR Library show all changes memory caches...
[mirror_edk2.git] / UefiCpuPkg / Library / MtrrLib / MtrrLib.c
index dcd99b9084addfc963cfe74e59617a70ebc78bed..3cf5f1392a652b00c54de71afb44ffed62b0eaa7 100644 (file)
@@ -1,8 +1,8 @@
 /** @file\r
   MTRR setting library\r
 \r
 /** @file\r
   MTRR setting library\r
 \r
-  Copyright (c) 2008 - 2009, Intel Corporation\r
-  All rights reserved. This program and the accompanying materials\r
+  Copyright (c) 2008 - 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
   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
@@ -23,8 +23,7 @@
 //\r
 // This table defines the offset, base and length of the fixed MTRRs\r
 //\r
 //\r
 // This table defines the offset, base and length of the fixed MTRRs\r
 //\r
-STATIC\r
-FIXED_MTRR    MtrrLibFixedMtrrTable[] = {\r
+CONST FIXED_MTRR  mMtrrLibFixedMtrrTable[] = {\r
   {\r
     MTRR_LIB_IA32_MTRR_FIX64K_00000,\r
     0,\r
   {\r
     MTRR_LIB_IA32_MTRR_FIX64K_00000,\r
     0,\r
@@ -82,6 +81,65 @@ FIXED_MTRR    MtrrLibFixedMtrrTable[] = {
   },\r
 };\r
 \r
   },\r
 };\r
 \r
+//\r
+// Lookup table used to print MTRRs\r
+//\r
+GLOBAL_REMOVE_IF_UNREFERENCED CONST CHAR8 *mMtrrMemoryCacheTypeShortName[] = {\r
+  "UC",  // CacheUncacheable\r
+  "WC",  // CacheWriteCombining\r
+  "R*",  // Invalid\r
+  "R*",  // Invalid\r
+  "WT",  // CacheWriteThrough\r
+  "WP",  // CacheWriteProtected\r
+  "WB",  // CacheWriteBack\r
+  "R*"   // Invalid\r
+};\r
+\r
+/**\r
+  Returns the variable MTRR count for the CPU.\r
+\r
+  @return Variable MTRR count\r
+\r
+**/\r
+UINT32\r
+EFIAPI\r
+GetVariableMtrrCount (\r
+  VOID\r
+  )\r
+{\r
+  UINT32  VariableMtrrCount;\r
+\r
+  if (!IsMtrrSupported ()) {\r
+    return 0;\r
+  }\r
+\r
+  VariableMtrrCount = (UINT32)(AsmReadMsr64 (MTRR_LIB_IA32_MTRR_CAP) & MTRR_LIB_IA32_MTRR_CAP_VCNT_MASK);\r
+  ASSERT (VariableMtrrCount <= MTRR_NUMBER_OF_VARIABLE_MTRR);\r
+\r
+  return VariableMtrrCount;\r
+}\r
+\r
+/**\r
+  Returns the firmware usable variable MTRR count for the CPU.\r
+\r
+  @return Firmware usable variable MTRR count\r
+\r
+**/\r
+UINT32\r
+EFIAPI\r
+GetFirmwareVariableMtrrCount (\r
+  VOID\r
+  )\r
+{\r
+  UINT32  VariableMtrrCount;\r
+\r
+  VariableMtrrCount = GetVariableMtrrCount ();\r
+  if (VariableMtrrCount < RESERVED_FIRMWARE_VARIABLE_MTRR_NUMBER) {\r
+    return 0;\r
+  }\r
+\r
+  return VariableMtrrCount - RESERVED_FIRMWARE_VARIABLE_MTRR_NUMBER;\r
+}\r
 \r
 /**\r
   Returns the default MTRR cache type for the system.\r
 \r
 /**\r
   Returns the default MTRR cache type for the system.\r
@@ -117,28 +175,27 @@ PreMtrrChange (
   //\r
   // Enter no fill cache mode, CD=1(Bit30), NW=0 (Bit29)\r
   //\r
   //\r
   // Enter no fill cache mode, CD=1(Bit30), NW=0 (Bit29)\r
   //\r
-  Value = AsmReadCr0 ();\r
-  Value = (UINTN) BitFieldWrite64 (Value, 30, 30, 1);\r
-  Value = (UINTN) BitFieldWrite64 (Value, 29, 29, 0);\r
-  AsmWriteCr0 (Value);\r
-  //\r
-  // Flush cache\r
-  //\r
-  AsmWbinvd ();\r
+  AsmDisableCache ();\r
+\r
   //\r
   //\r
-  // Clear PGE flag Bit 7\r
+  // Save original CR4 value and clear PGE flag (Bit 7)\r
   //\r
   Value = AsmReadCr4 ();\r
   //\r
   Value = AsmReadCr4 ();\r
-  AsmWriteCr4 ((UINTN) BitFieldWrite64 (Value, 7, 7, 0));\r
+  AsmWriteCr4 (Value & (~BIT7));\r
+\r
   //\r
   // Flush all TLBs\r
   //\r
   CpuFlushTlb ();\r
   //\r
   // Flush all TLBs\r
   //\r
   CpuFlushTlb ();\r
+\r
   //\r
   // Disable Mtrrs\r
   //\r
   AsmMsrBitFieldWrite64 (MTRR_LIB_IA32_MTRR_DEF_TYPE, 10, 11, 0);\r
 \r
   //\r
   // Disable Mtrrs\r
   //\r
   AsmMsrBitFieldWrite64 (MTRR_LIB_IA32_MTRR_DEF_TYPE, 10, 11, 0);\r
 \r
+  //\r
+  // Return original CR4 value\r
+  //\r
   return Value;\r
 }\r
 \r
   return Value;\r
 }\r
 \r
@@ -157,30 +214,25 @@ PostMtrrChange (
   UINTN Cr4\r
   )\r
 {\r
   UINTN Cr4\r
   )\r
 {\r
-  UINTN  Value;\r
-\r
   //\r
   // Enable Cache MTRR\r
   //\r
   AsmMsrBitFieldWrite64 (MTRR_LIB_IA32_MTRR_DEF_TYPE, 10, 11, 3);\r
 \r
   //\r
   //\r
   // Enable Cache MTRR\r
   //\r
   AsmMsrBitFieldWrite64 (MTRR_LIB_IA32_MTRR_DEF_TYPE, 10, 11, 3);\r
 \r
   //\r
-  // Flush all TLBs and cache the second time\r
+  // Flush all TLBs \r
   //\r
   //\r
-  AsmWbinvd ();\r
   CpuFlushTlb ();\r
 \r
   //\r
   // Enable Normal Mode caching CD=NW=0, CD(Bit30), NW(Bit29)\r
   //\r
   CpuFlushTlb ();\r
 \r
   //\r
   // Enable Normal Mode caching CD=NW=0, CD(Bit30), NW(Bit29)\r
   //\r
-  Value = AsmReadCr0 ();\r
-  Value = (UINTN) BitFieldWrite64 (Value, 30, 30, 0);\r
-  Value = (UINTN) BitFieldWrite64 (Value, 29, 29, 0);\r
-  AsmWriteCr0 (Value);\r
+  AsmEnableCache ();\r
 \r
 \r
+  //\r
+  // Restore original CR4 value\r
+  //\r
   AsmWriteCr4 (Cr4);\r
   AsmWriteCr4 (Cr4);\r
-\r
-  return ;\r
 }\r
 \r
 \r
 }\r
 \r
 \r
@@ -214,11 +266,11 @@ ProgramFixedMtrr (
   ClearMask = 0;\r
 \r
   for (MsrNum = 0; MsrNum < MTRR_NUMBER_OF_FIXED_MTRR; MsrNum++) {\r
   ClearMask = 0;\r
 \r
   for (MsrNum = 0; MsrNum < MTRR_NUMBER_OF_FIXED_MTRR; MsrNum++) {\r
-    if ((*Base >= MtrrLibFixedMtrrTable[MsrNum].BaseAddress) &&\r
+    if ((*Base >= mMtrrLibFixedMtrrTable[MsrNum].BaseAddress) &&\r
         (*Base <\r
             (\r
         (*Base <\r
             (\r
-              MtrrLibFixedMtrrTable[MsrNum].BaseAddress +\r
-              (8 * MtrrLibFixedMtrrTable[MsrNum].Length)\r
+              mMtrrLibFixedMtrrTable[MsrNum].BaseAddress +\r
+              (8 * mMtrrLibFixedMtrrTable[MsrNum].Length)\r
             )\r
           )\r
         ) {\r
             )\r
           )\r
         ) {\r
@@ -236,8 +288,8 @@ ProgramFixedMtrr (
   for (ByteShift = 0; ByteShift < 8; ByteShift++) {\r
     if (*Base ==\r
          (\r
   for (ByteShift = 0; ByteShift < 8; ByteShift++) {\r
     if (*Base ==\r
          (\r
-           MtrrLibFixedMtrrTable[MsrNum].BaseAddress +\r
-           (ByteShift * MtrrLibFixedMtrrTable[MsrNum].Length)\r
+           mMtrrLibFixedMtrrTable[MsrNum].BaseAddress +\r
+           (ByteShift * mMtrrLibFixedMtrrTable[MsrNum].Length)\r
          )\r
        ) {\r
       break;\r
          )\r
        ) {\r
       break;\r
@@ -250,13 +302,13 @@ ProgramFixedMtrr (
 \r
   for (\r
         ;\r
 \r
   for (\r
         ;\r
-        ((ByteShift < 8) && (*Length >= MtrrLibFixedMtrrTable[MsrNum].Length));\r
+        ((ByteShift < 8) && (*Length >= mMtrrLibFixedMtrrTable[MsrNum].Length));\r
         ByteShift++\r
       ) {\r
     OrMask |= LShiftU64 ((UINT64) MemoryCacheType, (UINT32) (ByteShift * 8));\r
     ClearMask |= LShiftU64 ((UINT64) 0xFF, (UINT32) (ByteShift * 8));\r
         ByteShift++\r
       ) {\r
     OrMask |= LShiftU64 ((UINT64) MemoryCacheType, (UINT32) (ByteShift * 8));\r
     ClearMask |= LShiftU64 ((UINT64) 0xFF, (UINT32) (ByteShift * 8));\r
-    *Length -= MtrrLibFixedMtrrTable[MsrNum].Length;\r
-    *Base += MtrrLibFixedMtrrTable[MsrNum].Length;\r
+    *Length -= mMtrrLibFixedMtrrTable[MsrNum].Length;\r
+    *Base += mMtrrLibFixedMtrrTable[MsrNum].Length;\r
   }\r
 \r
   if (ByteShift < 8 && (*Length != 0)) {\r
   }\r
 \r
   if (ByteShift < 8 && (*Length != 0)) {\r
@@ -264,8 +316,8 @@ ProgramFixedMtrr (
   }\r
 \r
   TempQword =\r
   }\r
 \r
   TempQword =\r
-    (AsmReadMsr64 (MtrrLibFixedMtrrTable[MsrNum].Msr) & ~ClearMask) | OrMask;\r
-  AsmWriteMsr64 (MtrrLibFixedMtrrTable[MsrNum].Msr, TempQword);\r
+    (AsmReadMsr64 (mMtrrLibFixedMtrrTable[MsrNum].Msr) & ~ClearMask) | OrMask;\r
+  AsmWriteMsr64 (mMtrrLibFixedMtrrTable[MsrNum].Msr, TempQword);\r
   return RETURN_SUCCESS;\r
 }\r
 \r
   return RETURN_SUCCESS;\r
 }\r
 \r
@@ -295,14 +347,23 @@ MtrrGetMemoryAttributeInVariableMtrr (
   UINTN   Index;\r
   UINT32  MsrNum;\r
   UINT32  UsedMtrr;\r
   UINTN   Index;\r
   UINT32  MsrNum;\r
   UINT32  UsedMtrr;\r
+  UINT32  FirmwareVariableMtrrCount;\r
+  UINT32  VariableMtrrEnd;\r
+\r
+  if (!IsMtrrSupported ()) {\r
+    return 0;\r
+  }\r
+\r
+  FirmwareVariableMtrrCount = GetFirmwareVariableMtrrCount ();\r
+  VariableMtrrEnd = MTRR_LIB_IA32_VARIABLE_MTRR_BASE + (2 * GetVariableMtrrCount ()) - 1;\r
 \r
   ZeroMem (VariableMtrr, sizeof (VARIABLE_MTRR) * MTRR_NUMBER_OF_VARIABLE_MTRR);\r
   UsedMtrr = 0;\r
 \r
   for (MsrNum = MTRR_LIB_IA32_VARIABLE_MTRR_BASE, Index = 0;\r
        (\r
 \r
   ZeroMem (VariableMtrr, sizeof (VARIABLE_MTRR) * MTRR_NUMBER_OF_VARIABLE_MTRR);\r
   UsedMtrr = 0;\r
 \r
   for (MsrNum = MTRR_LIB_IA32_VARIABLE_MTRR_BASE, Index = 0;\r
        (\r
-         (MsrNum < MTRR_LIB_IA32_VARIABLE_MTRR_END) &&\r
-         (Index < FIRMWARE_VARIABLE_MTRR_NUMBER)\r
+         (MsrNum < VariableMtrrEnd) &&\r
+         (Index < FirmwareVariableMtrrCount)\r
        );\r
        MsrNum += 2\r
       ) {\r
        );\r
        MsrNum += 2\r
       ) {\r
@@ -415,11 +476,14 @@ CombineMemoryAttribute (
   UINT64  CombineEnd;\r
   UINT64  MtrrEnd;\r
   UINT64  EndAddress;\r
   UINT64  CombineEnd;\r
   UINT64  MtrrEnd;\r
   UINT64  EndAddress;\r
+  UINT32  FirmwareVariableMtrrCount;\r
+\r
+  FirmwareVariableMtrrCount = GetFirmwareVariableMtrrCount ();\r
 \r
   *OverwriteExistingMtrr = FALSE;\r
   EndAddress = *Base +*Length - 1;\r
 \r
 \r
   *OverwriteExistingMtrr = FALSE;\r
   EndAddress = *Base +*Length - 1;\r
 \r
-  for (Index = 0; Index < FIRMWARE_VARIABLE_MTRR_NUMBER; Index++) {\r
+  for (Index = 0; Index < FirmwareVariableMtrrCount; Index++) {\r
 \r
     MtrrEnd = VariableMtrr[Index].BaseAddress + VariableMtrr[Index].Length - 1;\r
     if (\r
 \r
     MtrrEnd = VariableMtrr[Index].BaseAddress + VariableMtrr[Index].Length - 1;\r
     if (\r
@@ -506,7 +570,7 @@ Power2MaxMemory (
 {\r
   UINT64  Result;\r
 \r
 {\r
   UINT64  Result;\r
 \r
-  if (RShiftU64 (MemoryLength, 32)) {\r
+  if (RShiftU64 (MemoryLength, 32) != 0) {\r
     Result = LShiftU64 (\r
                (UINT64) GetPowerOfTwo32 (\r
                           (UINT32) RShiftU64 (MemoryLength, 32)\r
     Result = LShiftU64 (\r
                (UINT64) GetPowerOfTwo32 (\r
                           (UINT32) RShiftU64 (MemoryLength, 32)\r
@@ -578,7 +642,6 @@ GetDirection (
   @param  VariableMtrr   The array to shadow variable MTRRs content\r
 \r
 **/\r
   @param  VariableMtrr   The array to shadow variable MTRRs content\r
 \r
 **/\r
-STATIC\r
 VOID\r
 InvalidateMtrr (\r
    IN     VARIABLE_MTRR      *VariableMtrr\r
 VOID\r
 InvalidateMtrr (\r
    IN     VARIABLE_MTRR      *VariableMtrr\r
@@ -586,11 +649,13 @@ InvalidateMtrr (
 {\r
   UINTN Index;\r
   UINTN Cr4;\r
 {\r
   UINTN Index;\r
   UINTN Cr4;\r
+  UINTN VariableMtrrCount;\r
 \r
   Cr4 = PreMtrrChange ();\r
   Index = 0;\r
 \r
   Cr4 = PreMtrrChange ();\r
   Index = 0;\r
-  while (Index < MTRR_NUMBER_OF_VARIABLE_MTRR) {\r
-    if (VariableMtrr[Index].Valid == FALSE && VariableMtrr[Index].Used == TRUE ) {\r
+  VariableMtrrCount = GetVariableMtrrCount ();\r
+  while (Index < VariableMtrrCount) {\r
+    if (!VariableMtrr[Index].Valid && VariableMtrr[Index].Used) {\r
        AsmWriteMsr64 (VariableMtrr[Index].Msr, 0);\r
        AsmWriteMsr64 (VariableMtrr[Index].Msr + 1, 0);\r
        VariableMtrr[Index].Used = FALSE;\r
        AsmWriteMsr64 (VariableMtrr[Index].Msr, 0);\r
        AsmWriteMsr64 (VariableMtrr[Index].Msr + 1, 0);\r
        VariableMtrr[Index].Used = FALSE;\r
@@ -613,7 +678,6 @@ InvalidateMtrr (
   @param  MtrrValidAddressMask  The valid address mask for MTRR\r
 \r
 **/\r
   @param  MtrrValidAddressMask  The valid address mask for MTRR\r
 \r
 **/\r
-STATIC\r
 VOID\r
 ProgramVariableMtrr (\r
   IN UINTN                    MtrrNumber,\r
 VOID\r
 ProgramVariableMtrr (\r
   IN UINTN                    MtrrNumber,\r
@@ -655,7 +719,6 @@ ProgramVariableMtrr (
   @return The enum item in MTRR_MEMORY_CACHE_TYPE\r
 \r
 **/\r
   @return The enum item in MTRR_MEMORY_CACHE_TYPE\r
 \r
 **/\r
-STATIC\r
 MTRR_MEMORY_CACHE_TYPE\r
 GetMemoryCacheTypeFromMtrrType (\r
   IN UINT64                MtrrType\r
 MTRR_MEMORY_CACHE_TYPE\r
 GetMemoryCacheTypeFromMtrrType (\r
   IN UINT64                MtrrType\r
@@ -690,15 +753,14 @@ GetMemoryCacheTypeFromMtrrType (
   @param  MtrrValidAddressMask  The valid address mask for the MTRR\r
 \r
 **/\r
   @param  MtrrValidAddressMask  The valid address mask for the MTRR\r
 \r
 **/\r
-STATIC\r
 VOID\r
 MtrrLibInitializeMtrrMask (\r
   OUT UINT64 *MtrrValidBitsMask,\r
   OUT UINT64 *MtrrValidAddressMask\r
   )\r
 {\r
 VOID\r
 MtrrLibInitializeMtrrMask (\r
   OUT UINT64 *MtrrValidBitsMask,\r
   OUT UINT64 *MtrrValidAddressMask\r
   )\r
 {\r
-  UINT32                              RegEax;\r
-  UINT8                               PhysicalAddressBits;\r
+  UINT32  RegEax;\r
+  UINT8   PhysicalAddressBits;\r
 \r
   AsmCpuid (0x80000000, &RegEax, NULL, NULL, NULL);\r
 \r
 \r
   AsmCpuid (0x80000000, &RegEax, NULL, NULL, NULL);\r
 \r
@@ -836,6 +898,18 @@ MtrrSetMemoryAttribute (
   UINT64                    MtrrValidAddressMask;\r
   UINTN                     Cr4;\r
   BOOLEAN                   OverwriteExistingMtrr;\r
   UINT64                    MtrrValidAddressMask;\r
   UINTN                     Cr4;\r
   BOOLEAN                   OverwriteExistingMtrr;\r
+  UINT32                    FirmwareVariableMtrrCount;\r
+  UINT32                    VariableMtrrEnd;\r
+\r
+  DEBUG((DEBUG_CACHE, "MtrrSetMemoryAttribute() %a:%016lx-%016lx\n", mMtrrMemoryCacheTypeShortName[Attribute], BaseAddress, Length));\r
+\r
+  if (!IsMtrrSupported ()) {\r
+    Status = RETURN_UNSUPPORTED;\r
+    goto Done;\r
+  }\r
+\r
+  FirmwareVariableMtrrCount = GetFirmwareVariableMtrrCount ();\r
+  VariableMtrrEnd = MTRR_LIB_IA32_VARIABLE_MTRR_BASE + (2 * GetVariableMtrrCount ()) - 1;\r
 \r
   MtrrLibInitializeMtrrMask(&MtrrValidBitsMask, &MtrrValidAddressMask);\r
 \r
 \r
   MtrrLibInitializeMtrrMask(&MtrrValidBitsMask, &MtrrValidAddressMask);\r
 \r
@@ -847,14 +921,16 @@ MtrrSetMemoryAttribute (
   // Check for an invalid parameter\r
   //\r
   if (Length == 0) {\r
   // Check for an invalid parameter\r
   //\r
   if (Length == 0) {\r
-    return RETURN_INVALID_PARAMETER;\r
+    Status = RETURN_INVALID_PARAMETER;\r
+    goto Done;\r
   }\r
 \r
   if (\r
   }\r
 \r
   if (\r
-       (BaseAddress &~MtrrValidAddressMask) != 0 ||\r
-       (Length &~MtrrValidAddressMask) != 0\r
+       (BaseAddress & ~MtrrValidAddressMask) != 0 ||\r
+       (Length & ~MtrrValidAddressMask) != 0\r
      ) {\r
      ) {\r
-    return RETURN_UNSUPPORTED;\r
+    Status = RETURN_UNSUPPORTED;\r
+    goto Done;\r
   }\r
 \r
   //\r
   }\r
 \r
   //\r
@@ -866,7 +942,7 @@ MtrrSetMemoryAttribute (
     Status = ProgramFixedMtrr (MemoryType, &BaseAddress, &Length);\r
     PostMtrrChange (Cr4);\r
     if (RETURN_ERROR (Status)) {\r
     Status = ProgramFixedMtrr (MemoryType, &BaseAddress, &Length);\r
     PostMtrrChange (Cr4);\r
     if (RETURN_ERROR (Status)) {\r
-      return Status;\r
+      goto Done;\r
     }\r
   }\r
 \r
     }\r
   }\r
 \r
@@ -881,7 +957,7 @@ MtrrSetMemoryAttribute (
 \r
   //\r
   // Since memory ranges below 1MB will be overridden by the fixed MTRRs,\r
 \r
   //\r
   // Since memory ranges below 1MB will be overridden by the fixed MTRRs,\r
-  // we can set the bade to 0 to save variable MTRRs.\r
+  // we can set the base to 0 to save variable MTRRs.\r
   //\r
   if (BaseAddress == BASE_1MB) {\r
     BaseAddress = 0;\r
   //\r
   if (BaseAddress == BASE_1MB) {\r
     BaseAddress = 0;\r
@@ -925,7 +1001,7 @@ MtrrSetMemoryAttribute (
   //\r
   // Avoid hardcode here and read data dynamically\r
   //\r
   //\r
   // Avoid hardcode here and read data dynamically\r
   //\r
-  if (UsedMtrr >= FIRMWARE_VARIABLE_MTRR_NUMBER) {\r
+  if (UsedMtrr >= FirmwareVariableMtrrCount) {\r
     Status = RETURN_OUT_OF_RESOURCES;\r
     goto Done;\r
   }\r
     Status = RETURN_OUT_OF_RESOURCES;\r
     goto Done;\r
   }\r
@@ -955,7 +1031,7 @@ MtrrSetMemoryAttribute (
     // Find first unused MTRR\r
     //\r
     for (MsrNum = MTRR_LIB_IA32_VARIABLE_MTRR_BASE;\r
     // Find first unused MTRR\r
     //\r
     for (MsrNum = MTRR_LIB_IA32_VARIABLE_MTRR_BASE;\r
-         MsrNum < MTRR_LIB_IA32_VARIABLE_MTRR_END;\r
+         MsrNum < VariableMtrrEnd;\r
          MsrNum += 2\r
         ) {\r
       if ((AsmReadMsr64 (MsrNum + 1) & MTRR_LIB_CACHE_MTRR_ENABLED) == 0) {\r
          MsrNum += 2\r
         ) {\r
       if ((AsmReadMsr64 (MsrNum + 1) & MTRR_LIB_CACHE_MTRR_ENABLED) == 0) {\r
@@ -974,7 +1050,7 @@ MtrrSetMemoryAttribute (
 \r
     Positive = GetDirection (TempQword, &MtrrNumber);\r
 \r
 \r
     Positive = GetDirection (TempQword, &MtrrNumber);\r
 \r
-    if ((UsedMtrr + MtrrNumber) > FIRMWARE_VARIABLE_MTRR_NUMBER) {\r
+    if ((UsedMtrr + MtrrNumber) > FirmwareVariableMtrrCount) {\r
       Status = RETURN_OUT_OF_RESOURCES;\r
       goto Done;\r
     }\r
       Status = RETURN_OUT_OF_RESOURCES;\r
       goto Done;\r
     }\r
@@ -988,7 +1064,7 @@ MtrrSetMemoryAttribute (
     // Find first unused MTRR\r
     //\r
     for (MsrNum = MTRR_LIB_IA32_VARIABLE_MTRR_BASE;\r
     // Find first unused MTRR\r
     //\r
     for (MsrNum = MTRR_LIB_IA32_VARIABLE_MTRR_BASE;\r
-         MsrNum < MTRR_LIB_IA32_VARIABLE_MTRR_END;\r
+         MsrNum < VariableMtrrEnd;\r
          MsrNum += 2\r
         ) {\r
       if ((AsmReadMsr64 (MsrNum + 1) & MTRR_LIB_CACHE_MTRR_ENABLED) == 0) {\r
          MsrNum += 2\r
         ) {\r
       if ((AsmReadMsr64 (MsrNum + 1) & MTRR_LIB_CACHE_MTRR_ENABLED) == 0) {\r
@@ -1014,7 +1090,7 @@ MtrrSetMemoryAttribute (
       //\r
       // Find unused MTRR\r
       //\r
       //\r
       // Find unused MTRR\r
       //\r
-      for (; MsrNum < MTRR_LIB_IA32_VARIABLE_MTRR_END; MsrNum += 2) {\r
+      for (; MsrNum < VariableMtrrEnd; MsrNum += 2) {\r
         if ((AsmReadMsr64 (MsrNum + 1) & MTRR_LIB_CACHE_MTRR_ENABLED) == 0) {\r
           break;\r
         }\r
         if ((AsmReadMsr64 (MsrNum + 1) & MTRR_LIB_CACHE_MTRR_ENABLED) == 0) {\r
           break;\r
         }\r
@@ -1042,8 +1118,12 @@ MtrrSetMemoryAttribute (
   }\r
 \r
 Done:\r
   }\r
 \r
 Done:\r
-  return Status;\r
+  DEBUG((DEBUG_CACHE, "  Status = %r\n", Status));\r
+  if (!RETURN_ERROR (Status)) {\r
+    MtrrDebugPrintAllMtrrs ();\r
+  }\r
 \r
 \r
+  return Status;\r
 }\r
 \r
 \r
 }\r
 \r
 \r
@@ -1072,6 +1152,11 @@ MtrrGetMemoryAttribute (
   VARIABLE_MTRR           VariableMtrr[MTRR_NUMBER_OF_VARIABLE_MTRR];\r
   UINT64                  MtrrValidBitsMask;\r
   UINT64                  MtrrValidAddressMask;\r
   VARIABLE_MTRR           VariableMtrr[MTRR_NUMBER_OF_VARIABLE_MTRR];\r
   UINT64                  MtrrValidBitsMask;\r
   UINT64                  MtrrValidAddressMask;\r
+  UINTN                   VariableMtrrCount;\r
+\r
+  if (!IsMtrrSupported ()) {\r
+    return CacheUncacheable;\r
+  }\r
 \r
   //\r
   // Check if MTRR is enabled, if not, return UC as attribute\r
 \r
   //\r
   // Check if MTRR is enabled, if not, return UC as attribute\r
@@ -1092,16 +1177,16 @@ MtrrGetMemoryAttribute (
       // Go through the fixed MTRR\r
       //\r
       for (Index = 0; Index < MTRR_NUMBER_OF_FIXED_MTRR; Index++) {\r
       // Go through the fixed MTRR\r
       //\r
       for (Index = 0; Index < MTRR_NUMBER_OF_FIXED_MTRR; Index++) {\r
-         if (Address >= MtrrLibFixedMtrrTable[Index].BaseAddress &&\r
+         if (Address >= mMtrrLibFixedMtrrTable[Index].BaseAddress &&\r
              Address  < (\r
              Address  < (\r
-                          MtrrLibFixedMtrrTable[Index].BaseAddress +\r
-                          (MtrrLibFixedMtrrTable[Index].Length * 8)\r
+                          mMtrrLibFixedMtrrTable[Index].BaseAddress +\r
+                          (mMtrrLibFixedMtrrTable[Index].Length * 8)\r
                         )\r
             ) {\r
            SubIndex =\r
                         )\r
             ) {\r
            SubIndex =\r
-             ((UINTN)Address - MtrrLibFixedMtrrTable[Index].BaseAddress) /\r
-               MtrrLibFixedMtrrTable[Index].Length;\r
-           TempQword = AsmReadMsr64 (MtrrLibFixedMtrrTable[Index].Msr);\r
+             ((UINTN)Address - mMtrrLibFixedMtrrTable[Index].BaseAddress) /\r
+               mMtrrLibFixedMtrrTable[Index].Length;\r
+           TempQword = AsmReadMsr64 (mMtrrLibFixedMtrrTable[Index].Msr);\r
            MtrrType =  RShiftU64 (TempQword, SubIndex * 8) & 0xFF;\r
            return GetMemoryCacheTypeFromMtrrType (MtrrType);\r
          }\r
            MtrrType =  RShiftU64 (TempQword, SubIndex * 8) & 0xFF;\r
            return GetMemoryCacheTypeFromMtrrType (MtrrType);\r
          }\r
@@ -1118,7 +1203,10 @@ MtrrGetMemoryAttribute (
   //\r
   // Go through the variable MTRR\r
   //\r
   //\r
   // Go through the variable MTRR\r
   //\r
-  for (Index = 0; Index < MTRR_NUMBER_OF_VARIABLE_MTRR; Index++) {\r
+  VariableMtrrCount = GetVariableMtrrCount ();\r
+  ASSERT (VariableMtrrCount <= MTRR_NUMBER_OF_VARIABLE_MTRR);\r
+\r
+  for (Index = 0; Index < VariableMtrrCount; Index++) {\r
     if (VariableMtrr[Index].Valid) {\r
       if (Address >= VariableMtrr[Index].BaseAddress &&\r
           Address < VariableMtrr[Index].BaseAddress+VariableMtrr[Index].Length) {\r
     if (VariableMtrr[Index].Valid) {\r
       if (Address >= VariableMtrr[Index].BaseAddress &&\r
           Address < VariableMtrr[Index].BaseAddress+VariableMtrr[Index].Length) {\r
@@ -1148,8 +1236,16 @@ MtrrGetVariableMtrr (
   )\r
 {\r
   UINT32  Index;\r
   )\r
 {\r
   UINT32  Index;\r
+  UINT32  VariableMtrrCount;\r
+\r
+  if (!IsMtrrSupported ()) {\r
+    return VariableSettings;\r
+  }\r
+\r
+  VariableMtrrCount = GetVariableMtrrCount ();\r
+  ASSERT (VariableMtrrCount <= MTRR_NUMBER_OF_VARIABLE_MTRR);\r
 \r
 \r
-  for (Index = 0; Index < MTRR_NUMBER_OF_VARIABLE_MTRR; Index++) {\r
+  for (Index = 0; Index < VariableMtrrCount; Index++) {\r
     VariableSettings->Mtrr[Index].Base =\r
       AsmReadMsr64 (MTRR_LIB_IA32_VARIABLE_MTRR_BASE + (Index << 1));\r
     VariableSettings->Mtrr[Index].Mask =\r
     VariableSettings->Mtrr[Index].Base =\r
       AsmReadMsr64 (MTRR_LIB_IA32_VARIABLE_MTRR_BASE + (Index << 1));\r
     VariableSettings->Mtrr[Index].Mask =\r
@@ -1172,8 +1268,12 @@ MtrrSetVariableMtrrWorker (
   )\r
 {\r
   UINT32  Index;\r
   )\r
 {\r
   UINT32  Index;\r
+  UINT32  VariableMtrrCount;\r
 \r
 \r
-  for (Index = 0; Index < MTRR_NUMBER_OF_VARIABLE_MTRR; Index++) {\r
+  VariableMtrrCount = GetVariableMtrrCount ();\r
+  ASSERT (VariableMtrrCount <= MTRR_NUMBER_OF_VARIABLE_MTRR);\r
+\r
+  for (Index = 0; Index < VariableMtrrCount; Index++) {\r
     AsmWriteMsr64 (\r
       MTRR_LIB_IA32_VARIABLE_MTRR_BASE + (Index << 1),\r
       VariableSettings->Mtrr[Index].Base\r
     AsmWriteMsr64 (\r
       MTRR_LIB_IA32_VARIABLE_MTRR_BASE + (Index << 1),\r
       VariableSettings->Mtrr[Index].Base\r
@@ -1202,6 +1302,10 @@ MtrrSetVariableMtrr (
 {\r
   UINTN  Cr4;\r
 \r
 {\r
   UINTN  Cr4;\r
 \r
+  if (!IsMtrrSupported ()) {\r
+    return VariableSettings;\r
+  }\r
+\r
   Cr4 = PreMtrrChange ();\r
   MtrrSetVariableMtrrWorker (VariableSettings);\r
   PostMtrrChange (Cr4);\r
   Cr4 = PreMtrrChange ();\r
   MtrrSetVariableMtrrWorker (VariableSettings);\r
   PostMtrrChange (Cr4);\r
@@ -1225,9 +1329,13 @@ MtrrGetFixedMtrr (
 {\r
   UINT32  Index;\r
 \r
 {\r
   UINT32  Index;\r
 \r
+  if (!IsMtrrSupported ()) {\r
+    return FixedSettings;\r
+  }\r
+\r
   for (Index = 0; Index < MTRR_NUMBER_OF_FIXED_MTRR; Index++) {\r
       FixedSettings->Mtrr[Index] =\r
   for (Index = 0; Index < MTRR_NUMBER_OF_FIXED_MTRR; Index++) {\r
       FixedSettings->Mtrr[Index] =\r
-        AsmReadMsr64 (MtrrLibFixedMtrrTable[Index].Msr);\r
+        AsmReadMsr64 (mMtrrLibFixedMtrrTable[Index].Msr);\r
   };\r
 \r
   return FixedSettings;\r
   };\r
 \r
   return FixedSettings;\r
@@ -1248,7 +1356,7 @@ MtrrSetFixedMtrrWorker (
 \r
   for (Index = 0; Index < MTRR_NUMBER_OF_FIXED_MTRR; Index++) {\r
      AsmWriteMsr64 (\r
 \r
   for (Index = 0; Index < MTRR_NUMBER_OF_FIXED_MTRR; Index++) {\r
      AsmWriteMsr64 (\r
-       MtrrLibFixedMtrrTable[Index].Msr,\r
+       mMtrrLibFixedMtrrTable[Index].Msr,\r
        FixedSettings->Mtrr[Index]\r
        );\r
   }\r
        FixedSettings->Mtrr[Index]\r
        );\r
   }\r
@@ -1271,6 +1379,10 @@ MtrrSetFixedMtrr (
 {\r
   UINTN  Cr4;\r
 \r
 {\r
   UINTN  Cr4;\r
 \r
+  if (!IsMtrrSupported ()) {\r
+    return FixedSettings;\r
+  }\r
+\r
   Cr4 = PreMtrrChange ();\r
   MtrrSetFixedMtrrWorker (FixedSettings);\r
   PostMtrrChange (Cr4);\r
   Cr4 = PreMtrrChange ();\r
   MtrrSetFixedMtrrWorker (FixedSettings);\r
   PostMtrrChange (Cr4);\r
@@ -1293,6 +1405,10 @@ MtrrGetAllMtrrs (
   OUT MTRR_SETTINGS                *MtrrSetting\r
   )\r
 {\r
   OUT MTRR_SETTINGS                *MtrrSetting\r
   )\r
 {\r
+  if (!IsMtrrSupported ()) {\r
+    return MtrrSetting;\r
+  }\r
+\r
   //\r
   // Get fixed MTRRs\r
   //\r
   //\r
   // Get fixed MTRRs\r
   //\r
@@ -1328,6 +1444,10 @@ MtrrSetAllMtrrs (
 {\r
   UINTN  Cr4;\r
 \r
 {\r
   UINTN  Cr4;\r
 \r
+  if (!IsMtrrSupported ()) {\r
+    return MtrrSetting;\r
+  }\r
+\r
   Cr4 = PreMtrrChange ();\r
 \r
   //\r
   Cr4 = PreMtrrChange ();\r
 \r
   //\r
@@ -1350,37 +1470,188 @@ MtrrSetAllMtrrs (
   return MtrrSetting;\r
 }\r
 \r
   return MtrrSetting;\r
 }\r
 \r
-\r
 /**\r
   This function prints all MTRRs for debugging.\r
 **/\r
 VOID\r
 /**\r
   This function prints all MTRRs for debugging.\r
 **/\r
 VOID\r
+EFIAPI\r
 MtrrDebugPrintAllMtrrs (\r
 MtrrDebugPrintAllMtrrs (\r
+  VOID\r
   )\r
 {\r
   DEBUG_CODE (\r
     {\r
       MTRR_SETTINGS  MtrrSettings;\r
       UINTN          Index;\r
   )\r
 {\r
   DEBUG_CODE (\r
     {\r
       MTRR_SETTINGS  MtrrSettings;\r
       UINTN          Index;\r
+      UINTN          Index1;\r
+      UINTN          VariableMtrrCount;\r
+      UINT64         Base;\r
+      UINT64         Limit;\r
+      UINT64         MtrrBase;\r
+      UINT64         MtrrLimit;\r
+      UINT64         RangeBase;\r
+      UINT64         RangeLimit;\r
+      UINT64         NoRangeBase;\r
+      UINT64         NoRangeLimit;\r
+      UINT32         RegEax;\r
+      UINTN          MemoryType;\r
+      UINTN          PreviousMemoryType;\r
+      BOOLEAN        Found;\r
+\r
+      if (!IsMtrrSupported ()) {\r
+        return;\r
+      }\r
 \r
 \r
+      DEBUG((DEBUG_CACHE, "MTRR Settings\n"));\r
+      DEBUG((DEBUG_CACHE, "=============\n"));\r
+      \r
       MtrrGetAllMtrrs (&MtrrSettings);\r
       MtrrGetAllMtrrs (&MtrrSettings);\r
-      DEBUG((EFI_D_ERROR, "DefaultType = %016lx\n", MtrrSettings.MtrrDefType));\r
+      DEBUG((DEBUG_CACHE, "MTRR Default Type: %016lx\n", MtrrSettings.MtrrDefType));\r
       for (Index = 0; Index < MTRR_NUMBER_OF_FIXED_MTRR; Index++) {\r
       for (Index = 0; Index < MTRR_NUMBER_OF_FIXED_MTRR; Index++) {\r
-        DEBUG((\r
-          EFI_D_ERROR, "Fixed[%02d] = %016lx\n",\r
-          Index,\r
-          MtrrSettings.Fixed.Mtrr[Index]\r
-          ));\r
+        DEBUG((DEBUG_CACHE, "Fixed MTRR[%02d]   : %016lx\n", Index, MtrrSettings.Fixed.Mtrr[Index]));\r
       }\r
       }\r
-      for (Index = 0; Index < MTRR_NUMBER_OF_VARIABLE_MTRR; Index++) {\r
-        DEBUG((\r
-          EFI_D_ERROR, "Variable[%02d] = %016lx, %016lx\n",\r
+\r
+      VariableMtrrCount = GetVariableMtrrCount ();\r
+      for (Index = 0; Index < VariableMtrrCount; Index++) {\r
+        DEBUG((DEBUG_CACHE, "Variable MTRR[%02d]: Base=%016lx Mask=%016lx\n",\r
           Index,\r
           MtrrSettings.Variables.Mtrr[Index].Base,\r
           MtrrSettings.Variables.Mtrr[Index].Mask\r
           ));\r
       }\r
           Index,\r
           MtrrSettings.Variables.Mtrr[Index].Base,\r
           MtrrSettings.Variables.Mtrr[Index].Mask\r
           ));\r
       }\r
+      DEBUG((DEBUG_CACHE, "\n"));\r
+      DEBUG((DEBUG_CACHE, "MTRR Ranges\n"));\r
+      DEBUG((DEBUG_CACHE, "====================================\n"));\r
+\r
+      Base = 0;\r
+      PreviousMemoryType = MTRR_CACHE_INVALID_TYPE;\r
+      for (Index = 0; Index < MTRR_NUMBER_OF_FIXED_MTRR; Index++) {\r
+        Base = mMtrrLibFixedMtrrTable[Index].BaseAddress;\r
+        for (Index1 = 0; Index1 < 8; Index1++) {\r
+          MemoryType = RShiftU64 (MtrrSettings.Fixed.Mtrr[Index], Index1 * 8) & 0xff;\r
+          if (MemoryType > CacheWriteBack) {\r
+            MemoryType = MTRR_CACHE_INVALID_TYPE;\r
+          }            \r
+          if (MemoryType != PreviousMemoryType) {\r
+            if (PreviousMemoryType != MTRR_CACHE_INVALID_TYPE) {\r
+              DEBUG((DEBUG_CACHE, "%016lx\n", Base - 1));\r
+            }\r
+            PreviousMemoryType = MemoryType;\r
+            DEBUG((DEBUG_CACHE, "%a:%016lx-", mMtrrMemoryCacheTypeShortName[MemoryType], Base));\r
+          }\r
+          Base += mMtrrLibFixedMtrrTable[Index].Length;\r
+        }\r
+      }\r
+      DEBUG((DEBUG_CACHE, "%016lx\n", Base - 1));\r
+\r
+      VariableMtrrCount = GetVariableMtrrCount ();\r
+\r
+      Base = BASE_1MB;\r
+      PreviousMemoryType = MTRR_CACHE_INVALID_TYPE;\r
+      do {\r
+        MemoryType = MtrrGetMemoryAttribute (Base);\r
+        if (MemoryType > CacheWriteBack) {\r
+          MemoryType = MTRR_CACHE_INVALID_TYPE;\r
+        }\r
+\r
+        if (MemoryType != PreviousMemoryType) {\r
+          if (PreviousMemoryType != MTRR_CACHE_INVALID_TYPE) {\r
+            DEBUG((DEBUG_CACHE, "%016lx\n", Base - 1));\r
+          }\r
+          PreviousMemoryType = MemoryType;\r
+          DEBUG((DEBUG_CACHE, "%a:%016lx-", mMtrrMemoryCacheTypeShortName[MemoryType], Base));\r
+        }\r
+        \r
+        RangeBase    = BASE_1MB;        \r
+        NoRangeBase  = BASE_1MB;\r
+        Limit        = BIT36 - 1;\r
+        AsmCpuid (0x80000000, &RegEax, NULL, NULL, NULL);\r
+        if (RegEax >= 0x80000008) {\r
+          AsmCpuid (0x80000008, &RegEax, NULL, NULL, NULL);\r
+          Limit = LShiftU64 (1, RegEax & 0xff) - 1;\r
+        }\r
+        RangeLimit   = Limit;\r
+        NoRangeLimit = Limit;\r
+        \r
+        for (Index = 0, Found = FALSE; Index < VariableMtrrCount; Index++) {\r
+          if ((MtrrSettings.Variables.Mtrr[Index].Mask & BIT11) == 0) {\r
+            //\r
+            // If mask is not valid, then do not display range\r
+            //\r
+            continue;\r
+          }\r
+          MtrrBase  = (MtrrSettings.Variables.Mtrr[Index].Base & (~(SIZE_4KB - 1)));\r
+          MtrrLimit = MtrrBase + ((~(MtrrSettings.Variables.Mtrr[Index].Mask & (~(SIZE_4KB - 1)))) & Limit);\r
+\r
+          if (Base >= MtrrBase && Base < MtrrLimit) {\r
+            Found = TRUE;\r
+          }\r
+          \r
+          if (Base >= MtrrBase && MtrrBase > RangeBase) {\r
+            RangeBase = MtrrBase;\r
+          }\r
+          if (Base > MtrrLimit && MtrrLimit > RangeBase) {\r
+            RangeBase = MtrrLimit + 1;\r
+          }\r
+          if (Base < MtrrBase && MtrrBase < RangeLimit) {\r
+            RangeLimit = MtrrBase - 1;\r
+          }\r
+          if (Base < MtrrLimit && MtrrLimit <= RangeLimit) {\r
+            RangeLimit = MtrrLimit;\r
+          }\r
+          \r
+          if (Base > MtrrLimit && NoRangeBase < MtrrLimit) {\r
+            NoRangeBase = MtrrLimit + 1;\r
+          }\r
+          if (Base < MtrrBase && NoRangeLimit > MtrrBase) {\r
+            NoRangeLimit = MtrrBase - 1;\r
+          }\r
+        }\r
+        \r
+        if (Found) {\r
+          Base = RangeLimit + 1;\r
+        } else {\r
+          Base = NoRangeLimit + 1;\r
+        }\r
+      } while (Found);\r
+      DEBUG((DEBUG_CACHE, "%016lx\n\n", Base - 1));\r
     }\r
   );\r
 }\r
 \r
     }\r
   );\r
 }\r
 \r
+/**\r
+  Checks if MTRR is supported.\r
+\r
+  @retval TRUE  MTRR is supported.\r
+  @retval FALSE MTRR is not supported.\r
+\r
+**/\r
+BOOLEAN\r
+EFIAPI\r
+IsMtrrSupported (\r
+  VOID\r
+  )\r
+{\r
+  UINT32  RegEdx;\r
+  UINT64  MtrrCap;\r
+\r
+  //\r
+  // Check CPUID(1).EDX[12] for MTRR capability\r
+  //\r
+  AsmCpuid (1, NULL, NULL, NULL, &RegEdx);\r
+  if (BitFieldRead32 (RegEdx, 12, 12) == 0) {\r
+    return FALSE;\r
+  }\r
+\r
+  //\r
+  // Check IA32_MTRRCAP.[0..7] for number of variable MTRRs and IA32_MTRRCAP[8] for\r
+  // fixed MTRRs existence. If number of variable MTRRs is zero, or fixed MTRRs do not\r
+  // exist, return false.\r
+  //\r
+  MtrrCap = AsmReadMsr64 (MTRR_LIB_IA32_MTRR_CAP);\r
+  if  ((BitFieldRead64 (MtrrCap, 0, 7) == 0) || (BitFieldRead64 (MtrrCap, 8, 8) == 0)) {\r
+    return FALSE;\r
+  }\r
+\r
+  return TRUE;\r
+}\r