]> git.proxmox.com Git - mirror_edk2.git/blobdiff - UefiCpuPkg/Library/MtrrLib/MtrrLib.c
UefiCpuPkg/MtrrLib: Fixed bug if length is less than Fixed-MTRR range
[mirror_edk2.git] / UefiCpuPkg / Library / MtrrLib / MtrrLib.c
index 0358fffb28a2482d4aa87b23e74f28e5a11257e7..6a6bf765c2befbdaa1285bdb1bb1662d9f09411f 100644 (file)
@@ -1,7 +1,7 @@
 /** @file\r
   MTRR setting library\r
 \r
-  Copyright (c) 2008 - 2015, Intel Corporation. All rights reserved.<BR>\r
+  Copyright (c) 2008 - 2016, 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
@@ -20,6 +20,9 @@
 #include <Library/BaseMemoryLib.h>\r
 #include <Library/DebugLib.h>\r
 \r
+#define OR_SEED      0x0101010101010101ull\r
+#define CLEAR_SEED   0xFFFFFFFFFFFFFFFFull\r
+\r
 //\r
 // Context to save and restore when MTRRs are programmed\r
 //\r
@@ -183,15 +186,25 @@ GetFirmwareVariableMtrrCount (
 /**\r
   Worker function returns the default MTRR cache type for the system.\r
 \r
+  If MtrrSetting is not NULL, returns the default MTRR cache type from input\r
+  MTRR settings buffer.\r
+  If MtrrSetting is NULL, returns the default MTRR cache type from MSR.\r
+\r
+  @param[in]  MtrrSetting    A buffer holding all MTRRs content.\r
+\r
   @return  The default MTRR cache type.\r
 \r
 **/\r
 MTRR_MEMORY_CACHE_TYPE\r
 MtrrGetDefaultMemoryTypeWorker (\r
-  VOID\r
+  IN MTRR_SETTINGS      *MtrrSetting\r
   )\r
 {\r
-  return (MTRR_MEMORY_CACHE_TYPE) (AsmReadMsr64 (MTRR_LIB_IA32_MTRR_DEF_TYPE) & 0x7);\r
+  if (MtrrSetting == NULL) {\r
+    return (MTRR_MEMORY_CACHE_TYPE) (AsmReadMsr64 (MTRR_LIB_IA32_MTRR_DEF_TYPE) & 0x7);\r
+  } else {\r
+    return (MTRR_MEMORY_CACHE_TYPE) (MtrrSetting->MtrrDefType & 0x7);\r
+  }\r
 }\r
 \r
 \r
@@ -210,7 +223,7 @@ MtrrGetDefaultMemoryType (
   if (!IsMtrrSupported ()) {\r
     return CacheUncacheable;\r
   }\r
-  return MtrrGetDefaultMemoryTypeWorker ();\r
+  return MtrrGetDefaultMemoryTypeWorker (NULL);\r
 }\r
 \r
 /**\r
@@ -360,6 +373,12 @@ MtrrGetFixedMtrr (
 /**\r
   Worker function will get the raw value in variable MTRRs\r
 \r
+  If MtrrSetting is not NULL, gets the variable MTRRs raw value from input\r
+  MTRR settings buffer.\r
+  If MtrrSetting is NULL, gets the variable MTRRs raw value from MTRRs.\r
+\r
+  @param[in]  MtrrSetting        A buffer holding all MTRRs content.\r
+  @param[in]  VariableMtrrCount  Number of variable MTRRs.\r
   @param[out] VariableSettings   A buffer to hold variable MTRRs content.\r
 \r
   @return The VariableSettings input pointer\r
@@ -367,6 +386,7 @@ MtrrGetFixedMtrr (
 **/\r
 MTRR_VARIABLE_SETTINGS*\r
 MtrrGetVariableMtrrWorker (\r
+  IN  MTRR_SETTINGS           *MtrrSetting,\r
   IN  UINT32                  VariableMtrrCount,\r
   OUT MTRR_VARIABLE_SETTINGS  *VariableSettings\r
   )\r
@@ -376,10 +396,15 @@ MtrrGetVariableMtrrWorker (
   ASSERT (VariableMtrrCount <= MTRR_NUMBER_OF_VARIABLE_MTRR);\r
 \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
-      AsmReadMsr64 (MTRR_LIB_IA32_VARIABLE_MTRR_BASE + (Index << 1) + 1);\r
+    if (MtrrSetting == NULL) {\r
+      VariableSettings->Mtrr[Index].Base =\r
+        AsmReadMsr64 (MTRR_LIB_IA32_VARIABLE_MTRR_BASE + (Index << 1));\r
+      VariableSettings->Mtrr[Index].Mask =\r
+        AsmReadMsr64 (MTRR_LIB_IA32_VARIABLE_MTRR_BASE + (Index << 1) + 1);\r
+    } else {\r
+      VariableSettings->Mtrr[Index].Base = MtrrSetting->Variables.Mtrr[Index].Base;\r
+      VariableSettings->Mtrr[Index].Mask = MtrrSetting->Variables.Mtrr[Index].Mask;\r
+    }\r
   }\r
 \r
   return  VariableSettings;\r
@@ -404,6 +429,7 @@ MtrrGetVariableMtrr (
   }\r
 \r
   return MtrrGetVariableMtrrWorker (\r
+           NULL,\r
            GetVariableMtrrCountWorker (),\r
            VariableSettings\r
            );\r
@@ -415,6 +441,10 @@ MtrrGetVariableMtrr (
   @param[in]      MemoryCacheType  The memory type to set.\r
   @param[in, out] Base             The base address of memory range.\r
   @param[in, out] Length           The length of memory range.\r
+  @param[in, out] LastMsrNum       On input, the last index of the fixed MTRR MSR to program.\r
+                                   On return, the current index of the fixed MTRR MSR to program.\r
+  @param[out]     ReturnClearMask  The bits to clear in the fixed MTRR MSR.\r
+  @param[out]     ReturnOrMask     The bits to set in the fixed MTRR MSR.\r
 \r
   @retval RETURN_SUCCESS      The cache type was updated successfully\r
   @retval RETURN_UNSUPPORTED  The requested range or cache type was invalid\r
@@ -423,22 +453,25 @@ MtrrGetVariableMtrr (
 **/\r
 RETURN_STATUS\r
 ProgramFixedMtrr (\r
-  IN     UINT64     MemoryCacheType,\r
-  IN OUT UINT64     *Base,\r
-  IN OUT UINT64     *Length\r
+  IN     UINT64               MemoryCacheType,\r
+  IN OUT UINT64               *Base,\r
+  IN OUT UINT64               *Length,\r
+  IN OUT UINT32               *LastMsrNum,\r
+  OUT    UINT64               *ReturnClearMask,\r
+  OUT    UINT64               *ReturnOrMask\r
   )\r
 {\r
   UINT32  MsrNum;\r
-  UINT32  ByteShift;\r
-  UINT64  TempQword;\r
+  UINT32  LeftByteShift;\r
+  UINT32  RightByteShift;\r
   UINT64  OrMask;\r
   UINT64  ClearMask;\r
+  UINT64  SubLength;\r
 \r
-  TempQword = 0;\r
-  OrMask    = 0;\r
-  ClearMask = 0;\r
-\r
-  for (MsrNum = 0; MsrNum < MTRR_NUMBER_OF_FIXED_MTRR; MsrNum++) {\r
+  //\r
+  // Find the fixed MTRR index to be programmed\r
+  //\r
+  for (MsrNum = *LastMsrNum + 1; MsrNum < MTRR_NUMBER_OF_FIXED_MTRR; MsrNum++) {\r
     if ((*Base >= mMtrrLibFixedMtrrTable[MsrNum].BaseAddress) &&\r
         (*Base <\r
             (\r
@@ -451,50 +484,114 @@ ProgramFixedMtrr (
     }\r
   }\r
 \r
-  if (MsrNum == MTRR_NUMBER_OF_FIXED_MTRR) {\r
+  if (MsrNum >= MTRR_NUMBER_OF_FIXED_MTRR) {\r
     return RETURN_UNSUPPORTED;\r
   }\r
 \r
   //\r
-  // We found the fixed MTRR to be programmed\r
+  // Find the begin offset in fixed MTRR and calculate byte offset of left shift\r
   //\r
-  for (ByteShift = 0; ByteShift < 8; ByteShift++) {\r
-    if (*Base ==\r
-         (\r
-           mMtrrLibFixedMtrrTable[MsrNum].BaseAddress +\r
-           (ByteShift * mMtrrLibFixedMtrrTable[MsrNum].Length)\r
-         )\r
-       ) {\r
-      break;\r
-    }\r
-  }\r
+  LeftByteShift = ((UINT32)*Base - mMtrrLibFixedMtrrTable[MsrNum].BaseAddress)\r
+               / mMtrrLibFixedMtrrTable[MsrNum].Length;\r
 \r
-  if (ByteShift == 8) {\r
+  if (LeftByteShift >= 8) {\r
     return RETURN_UNSUPPORTED;\r
   }\r
 \r
-  for (\r
-        ;\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
-    *Length -= mMtrrLibFixedMtrrTable[MsrNum].Length;\r
-    *Base += mMtrrLibFixedMtrrTable[MsrNum].Length;\r
+  //\r
+  // Find the end offset in fixed MTRR and calculate byte offset of right shift\r
+  //\r
+  SubLength = mMtrrLibFixedMtrrTable[MsrNum].Length * (8 - LeftByteShift);\r
+  if (*Length >= SubLength) {\r
+    RightByteShift = 0;\r
+  } else {\r
+    RightByteShift = 8 - LeftByteShift -\r
+                (UINT32)(*Length) / mMtrrLibFixedMtrrTable[MsrNum].Length;\r
+    if ((LeftByteShift >= 8) ||\r
+        (((UINT32)(*Length) % mMtrrLibFixedMtrrTable[MsrNum].Length) != 0)\r
+        ) {\r
+      return RETURN_UNSUPPORTED;\r
+    }\r
+    //\r
+    // Update SubLength by actual length\r
+    //\r
+    SubLength = *Length;\r
   }\r
 \r
-  if (ByteShift < 8 && (*Length != 0)) {\r
-    return RETURN_UNSUPPORTED;\r
+  ClearMask = CLEAR_SEED;\r
+  OrMask    = MultU64x32 (OR_SEED, (UINT32)MemoryCacheType);\r
+\r
+  if (LeftByteShift != 0) {\r
+    //\r
+    // Clear the low bits by LeftByteShift\r
+    //\r
+    ClearMask &= LShiftU64 (ClearMask, LeftByteShift * 8);\r
+    OrMask    &= LShiftU64 (OrMask, LeftByteShift * 8);\r
+  }\r
+\r
+  if (RightByteShift != 0) {\r
+    //\r
+    // Clear the high bits by RightByteShift\r
+    //\r
+    ClearMask &= RShiftU64 (ClearMask, RightByteShift * 8);\r
+    OrMask    &= RShiftU64 (OrMask, RightByteShift * 8);\r
   }\r
 \r
-  TempQword =\r
-    (AsmReadMsr64 (mMtrrLibFixedMtrrTable[MsrNum].Msr) & ~ClearMask) | OrMask;\r
-  AsmWriteMsr64 (mMtrrLibFixedMtrrTable[MsrNum].Msr, TempQword);\r
+  *Length -= SubLength;\r
+  *Base   += SubLength;\r
+\r
+  *LastMsrNum      = MsrNum;\r
+  *ReturnClearMask = ClearMask;\r
+  *ReturnOrMask    = OrMask;\r
+\r
   return RETURN_SUCCESS;\r
 }\r
 \r
 \r
+/**\r
+  Worker function gets the attribute of variable MTRRs.\r
+\r
+  This function shadows the content of variable MTRRs into an\r
+  internal array: VariableMtrr.\r
+\r
+  @param[in]   VariableSettings           The variable MTRR values to shadow\r
+  @param[in]   FirmwareVariableMtrrCount  The number of variable MTRRs available to firmware\r
+  @param[in]   MtrrValidBitsMask          The mask for the valid bit of the MTRR\r
+  @param[in]   MtrrValidAddressMask       The valid address mask for MTRR\r
+  @param[out]  VariableMtrr               The array to shadow variable MTRRs content\r
+\r
+  @return                       The return value of this parameter indicates the\r
+                                number of MTRRs which has been used.\r
+\r
+**/\r
+UINT32\r
+MtrrGetMemoryAttributeInVariableMtrrWorker (\r
+  IN  MTRR_VARIABLE_SETTINGS  *VariableSettings,\r
+  IN  UINTN                   FirmwareVariableMtrrCount,\r
+  IN  UINT64                  MtrrValidBitsMask,\r
+  IN  UINT64                  MtrrValidAddressMask,\r
+  OUT VARIABLE_MTRR           *VariableMtrr\r
+  )\r
+{\r
+  UINTN   Index;\r
+  UINT32  UsedMtrr;\r
+\r
+  ZeroMem (VariableMtrr, sizeof (VARIABLE_MTRR) * MTRR_NUMBER_OF_VARIABLE_MTRR);\r
+  for (Index = 0, UsedMtrr = 0; Index < FirmwareVariableMtrrCount; Index++) {\r
+    if ((VariableSettings->Mtrr[Index].Mask & MTRR_LIB_CACHE_MTRR_ENABLED) != 0) {\r
+      VariableMtrr[Index].Msr         = (UINT32)Index;\r
+      VariableMtrr[Index].BaseAddress = (VariableSettings->Mtrr[Index].Base & MtrrValidAddressMask);\r
+      VariableMtrr[Index].Length      = ((~(VariableSettings->Mtrr[Index].Mask & MtrrValidAddressMask)) & MtrrValidBitsMask) + 1;\r
+      VariableMtrr[Index].Type        = (VariableSettings->Mtrr[Index].Base & 0x0ff);\r
+      VariableMtrr[Index].Valid       = TRUE;\r
+      VariableMtrr[Index].Used        = TRUE;\r
+      UsedMtrr++;\r
+    }\r
+  }\r
+  return UsedMtrr;\r
+}\r
+\r
+\r
 /**\r
   Gets the attribute of variable MTRRs.\r
 \r
@@ -517,46 +614,25 @@ MtrrGetMemoryAttributeInVariableMtrr (
   OUT VARIABLE_MTRR             *VariableMtrr\r
   )\r
 {\r
-  UINTN   Index;\r
-  UINT32  MsrNum;\r
-  UINT32  UsedMtrr;\r
-  UINT32  FirmwareVariableMtrrCount;\r
-  UINT32  VariableMtrrEnd;\r
+  MTRR_VARIABLE_SETTINGS  VariableSettings;\r
 \r
   if (!IsMtrrSupported ()) {\r
     return 0;\r
   }\r
 \r
-  FirmwareVariableMtrrCount = GetFirmwareVariableMtrrCountWorker ();\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
+  MtrrGetVariableMtrrWorker (\r
+    NULL,\r
+    GetVariableMtrrCountWorker (),\r
+    &VariableSettings\r
+    );\r
 \r
-  for (MsrNum = MTRR_LIB_IA32_VARIABLE_MTRR_BASE, Index = 0;\r
-       (\r
-         (MsrNum < VariableMtrrEnd) &&\r
-         (Index < FirmwareVariableMtrrCount)\r
-       );\r
-       MsrNum += 2\r
-      ) {\r
-    if ((AsmReadMsr64 (MsrNum + 1) & MTRR_LIB_CACHE_MTRR_ENABLED) != 0) {\r
-      VariableMtrr[Index].Msr          = MsrNum;\r
-      VariableMtrr[Index].BaseAddress  = (AsmReadMsr64 (MsrNum) &\r
-                                          MtrrValidAddressMask);\r
-      VariableMtrr[Index].Length       = ((~(AsmReadMsr64 (MsrNum + 1) &\r
-                                             MtrrValidAddressMask)\r
-                                          ) &\r
-                                          MtrrValidBitsMask\r
-                                         ) + 1;\r
-      VariableMtrr[Index].Type         = (AsmReadMsr64 (MsrNum) & 0x0ff);\r
-      VariableMtrr[Index].Valid        = TRUE;\r
-      VariableMtrr[Index].Used         = TRUE;\r
-      UsedMtrr = UsedMtrr  + 1;\r
-      Index++;\r
-    }\r
-  }\r
-  return UsedMtrr;\r
+  return MtrrGetMemoryAttributeInVariableMtrrWorker (\r
+           &VariableSettings,\r
+           GetFirmwareVariableMtrrCountWorker (),\r
+           MtrrValidBitsMask,\r
+           MtrrValidAddressMask,\r
+           VariableMtrr\r
+           );\r
 }\r
 \r
 \r
@@ -854,30 +930,27 @@ GetMtrrNumberAndDirection (
   This function programs MTRRs according to the values specified\r
   in the shadow array.\r
 \r
+  @param[in, out]  VariableSettings   Variable MTRR settings\r
   @param[in]       VariableMtrrCount  Number of variable MTRRs\r
   @param[in, out]  VariableMtrr       Shadow of variable MTRR contents\r
 \r
 **/\r
 VOID\r
 InvalidateMtrr (\r
+  IN OUT MTRR_VARIABLE_SETTINGS  *VariableSettings,\r
   IN     UINTN                   VariableMtrrCount,\r
   IN OUT VARIABLE_MTRR           *VariableMtrr\r
   )\r
 {\r
   UINTN         Index;\r
-  MTRR_CONTEXT  MtrrContext;\r
 \r
-  PreMtrrChange (&MtrrContext);\r
-  Index = 0;\r
-  while (Index < VariableMtrrCount) {\r
+  for (Index = 0; Index < VariableMtrrCount; Index++) {\r
     if (!VariableMtrr[Index].Valid && VariableMtrr[Index].Used) {\r
-       AsmWriteMsr64 (VariableMtrr[Index].Msr, 0);\r
-       AsmWriteMsr64 (VariableMtrr[Index].Msr + 1, 0);\r
+       VariableSettings->Mtrr[Index].Base = 0;\r
+       VariableSettings->Mtrr[Index].Mask = 0;\r
        VariableMtrr[Index].Used = FALSE;\r
     }\r
-    Index ++;\r
   }\r
-  PostMtrrChange (&MtrrContext);\r
 }\r
 \r
 \r
@@ -886,6 +959,7 @@ InvalidateMtrr (
 \r
   This function programs variable MTRRs\r
 \r
+  @param[in, out]  VariableSettings      Variable MTRR settings.\r
   @param[in]       MtrrNumber            Index of MTRR to program.\r
   @param[in]       BaseAddress           Base address of memory region.\r
   @param[in]       Length                Length of memory region.\r
@@ -895,40 +969,38 @@ InvalidateMtrr (
 **/\r
 VOID\r
 ProgramVariableMtrr (\r
-  IN UINTN                    MtrrNumber,\r
-  IN PHYSICAL_ADDRESS         BaseAddress,\r
-  IN UINT64                   Length,\r
-  IN UINT64                   MemoryCacheType,\r
-  IN UINT64                   MtrrValidAddressMask\r
+  IN OUT MTRR_VARIABLE_SETTINGS  *VariableSettings,\r
+  IN     UINTN                   MtrrNumber,\r
+  IN     PHYSICAL_ADDRESS        BaseAddress,\r
+  IN     UINT64                  Length,\r
+  IN     UINT64                  MemoryCacheType,\r
+  IN     UINT64                  MtrrValidAddressMask\r
   )\r
 {\r
   UINT64        TempQword;\r
-  MTRR_CONTEXT  MtrrContext;\r
-\r
-  PreMtrrChange (&MtrrContext);\r
 \r
   //\r
   // MTRR Physical Base\r
   //\r
   TempQword = (BaseAddress & MtrrValidAddressMask) | MemoryCacheType;\r
-  AsmWriteMsr64 ((UINT32) MtrrNumber, TempQword);\r
+  VariableSettings->Mtrr[MtrrNumber].Base = TempQword;\r
 \r
   //\r
   // MTRR Physical Mask\r
   //\r
   TempQword = ~(Length - 1);\r
-  AsmWriteMsr64 (\r
-    (UINT32) (MtrrNumber + 1),\r
-    (TempQword & MtrrValidAddressMask) | MTRR_LIB_CACHE_MTRR_ENABLED\r
-    );\r
-\r
-  PostMtrrChange (&MtrrContext);\r
+  VariableSettings->Mtrr[MtrrNumber].Mask = (TempQword & MtrrValidAddressMask) | MTRR_LIB_CACHE_MTRR_ENABLED;\r
 }\r
 \r
 \r
 /**\r
   Converts the Memory attribute value to MTRR_MEMORY_CACHE_TYPE.\r
 \r
+  If MtrrSetting is not NULL, gets the default memory attribute from input\r
+  MTRR settings buffer.\r
+  If MtrrSetting is NULL, gets the default memory attribute from MSR.\r
+\r
+  @param[in]  MtrrSetting        A buffer holding all MTRRs content.\r
   @param[in]  MtrrType           MTRR memory type\r
 \r
   @return The enum item in MTRR_MEMORY_CACHE_TYPE\r
@@ -936,6 +1008,7 @@ ProgramVariableMtrr (
 **/\r
 MTRR_MEMORY_CACHE_TYPE\r
 GetMemoryCacheTypeFromMtrrType (\r
+  IN MTRR_SETTINGS         *MtrrSetting,\r
   IN UINT64                MtrrType\r
   )\r
 {\r
@@ -955,7 +1028,7 @@ GetMemoryCacheTypeFromMtrrType (
     // MtrrType is MTRR_CACHE_INVALID_TYPE, that means\r
     // no MTRR covers the range\r
     //\r
-    return MtrrGetDefaultMemoryType ();\r
+    return MtrrGetDefaultMemoryTypeWorker (MtrrSetting);\r
   }\r
 }\r
 \r
@@ -1064,21 +1137,22 @@ MtrrPrecedence (
   return MtrrType;\r
 }\r
 \r
-\r
-\r
 /**\r
-  This function will get the memory cache type of the specific address.\r
+  Worker function will get the memory cache type of the specific address.\r
 \r
-  This function is mainly for debug purpose.\r
+  If MtrrSetting is not NULL, gets the memory cache type from input\r
+  MTRR settings buffer.\r
+  If MtrrSetting is NULL, gets the memory cache type from MTRRs.\r
 \r
+  @param[in]  MtrrSetting        A buffer holding all MTRRs content.\r
   @param[in]  Address            The specific address\r
 \r
   @return Memory cache type of the specific address\r
 \r
 **/\r
 MTRR_MEMORY_CACHE_TYPE\r
-EFIAPI\r
-MtrrGetMemoryAttribute (\r
+MtrrGetMemoryAttributeByAddressWorker (\r
+  IN MTRR_SETTINGS      *MtrrSetting,\r
   IN PHYSICAL_ADDRESS   Address\r
   )\r
 {\r
@@ -1092,15 +1166,16 @@ MtrrGetMemoryAttribute (
   UINT64                  MtrrValidBitsMask;\r
   UINT64                  MtrrValidAddressMask;\r
   UINTN                   VariableMtrrCount;\r
-\r
-  if (!IsMtrrSupported ()) {\r
-    return CacheUncacheable;\r
-  }\r
+  MTRR_VARIABLE_SETTINGS  VariableSettings;\r
 \r
   //\r
   // Check if MTRR is enabled, if not, return UC as attribute\r
   //\r
-  TempQword = AsmReadMsr64 (MTRR_LIB_IA32_MTRR_DEF_TYPE);\r
+  if (MtrrSetting == NULL) {\r
+    TempQword = AsmReadMsr64 (MTRR_LIB_IA32_MTRR_DEF_TYPE);\r
+  } else {\r
+    TempQword = MtrrSetting->MtrrDefType;\r
+  }\r
   MtrrType = MTRR_CACHE_INVALID_TYPE;\r
 \r
   if ((TempQword & MTRR_LIB_CACHE_MTRR_ENABLED) == 0) {\r
@@ -1125,20 +1200,33 @@ MtrrGetMemoryAttribute (
            SubIndex =\r
              ((UINTN)Address - mMtrrLibFixedMtrrTable[Index].BaseAddress) /\r
                mMtrrLibFixedMtrrTable[Index].Length;\r
-           TempQword = AsmReadMsr64 (mMtrrLibFixedMtrrTable[Index].Msr);\r
+           if (MtrrSetting == NULL) {\r
+             TempQword = AsmReadMsr64 (mMtrrLibFixedMtrrTable[Index].Msr);\r
+           } else {\r
+             TempQword = MtrrSetting->Fixed.Mtrr[Index];\r
+           }\r
            MtrrType =  RShiftU64 (TempQword, SubIndex * 8) & 0xFF;\r
-           return GetMemoryCacheTypeFromMtrrType (MtrrType);\r
+           return GetMemoryCacheTypeFromMtrrType (MtrrSetting, MtrrType);\r
          }\r
       }\r
     }\r
   }\r
   MtrrLibInitializeMtrrMask(&MtrrValidBitsMask, &MtrrValidAddressMask);\r
-  MtrrGetMemoryAttributeInVariableMtrr(\r
-    MtrrValidBitsMask,\r
-    MtrrValidAddressMask,\r
-    VariableMtrr\r
+\r
+  MtrrGetVariableMtrrWorker (\r
+    MtrrSetting,\r
+    GetVariableMtrrCountWorker (),\r
+    &VariableSettings\r
     );\r
 \r
+  MtrrGetMemoryAttributeInVariableMtrrWorker (\r
+           &VariableSettings,\r
+           GetFirmwareVariableMtrrCountWorker (),\r
+           MtrrValidBitsMask,\r
+           MtrrValidAddressMask,\r
+           VariableMtrr\r
+           );\r
+\r
   //\r
   // Go through the variable MTRR\r
   //\r
@@ -1154,24 +1242,52 @@ MtrrGetMemoryAttribute (
       }\r
     }\r
   }\r
-  CacheType = GetMemoryCacheTypeFromMtrrType (MtrrType);\r
+  CacheType = GetMemoryCacheTypeFromMtrrType (MtrrSetting, MtrrType);\r
 \r
   return CacheType;\r
 }\r
 \r
 \r
+/**\r
+  This function will get the memory cache type of the specific address.\r
+\r
+  This function is mainly for debug purpose.\r
+\r
+  @param[in]  Address   The specific address\r
+\r
+  @return Memory cache type of the specific address\r
+\r
+**/\r
+MTRR_MEMORY_CACHE_TYPE\r
+EFIAPI\r
+MtrrGetMemoryAttribute (\r
+  IN PHYSICAL_ADDRESS   Address\r
+  )\r
+{\r
+  if (!IsMtrrSupported ()) {\r
+    return CacheUncacheable;\r
+  }\r
+\r
+  return MtrrGetMemoryAttributeByAddressWorker (NULL, Address);\r
+}\r
 \r
 /**\r
-  This function prints all MTRRs for debugging.\r
+  Worker function prints all MTRRs for debugging.\r
+\r
+  If MtrrSetting is not NULL, print MTRR settings from from input MTRR\r
+  settings buffer.\r
+  If MtrrSetting is NULL, print MTRR settings from MTRRs.\r
+\r
+  @param  MtrrSetting    A buffer holding all MTRRs content.\r
 **/\r
 VOID\r
-EFIAPI\r
-MtrrDebugPrintAllMtrrs (\r
-  VOID\r
+MtrrDebugPrintAllMtrrsWorker (\r
+  IN MTRR_SETTINGS    *MtrrSetting\r
   )\r
 {\r
   DEBUG_CODE (\r
-    MTRR_SETTINGS  MtrrSettings;\r
+    MTRR_SETTINGS  LocalMtrrs;\r
+    MTRR_SETTINGS  *Mtrrs;\r
     UINTN          Index;\r
     UINTN          Index1;\r
     UINTN          VariableMtrrCount;\r
@@ -1195,18 +1311,24 @@ MtrrDebugPrintAllMtrrs (
     DEBUG((DEBUG_CACHE, "MTRR Settings\n"));\r
     DEBUG((DEBUG_CACHE, "=============\n"));\r
 \r
-    MtrrGetAllMtrrs (&MtrrSettings);\r
-    DEBUG((DEBUG_CACHE, "MTRR Default Type: %016lx\n", MtrrSettings.MtrrDefType));\r
+    if (MtrrSetting != NULL) {\r
+      Mtrrs = MtrrSetting;\r
+    } else {\r
+      MtrrGetAllMtrrs (&LocalMtrrs);\r
+      Mtrrs = &LocalMtrrs;\r
+    }\r
+\r
+    DEBUG((DEBUG_CACHE, "MTRR Default Type: %016lx\n", Mtrrs->MtrrDefType));\r
     for (Index = 0; Index < MTRR_NUMBER_OF_FIXED_MTRR; Index++) {\r
-      DEBUG((DEBUG_CACHE, "Fixed MTRR[%02d]   : %016lx\n", Index, MtrrSettings.Fixed.Mtrr[Index]));\r
+      DEBUG((DEBUG_CACHE, "Fixed MTRR[%02d]   : %016lx\n", Index, Mtrrs->Fixed.Mtrr[Index]));\r
     }\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
+        Mtrrs->Variables.Mtrr[Index].Base,\r
+        Mtrrs->Variables.Mtrr[Index].Mask\r
         ));\r
     }\r
     DEBUG((DEBUG_CACHE, "\n"));\r
@@ -1218,7 +1340,7 @@ MtrrDebugPrintAllMtrrs (
     for (Index = 0; Index < MTRR_NUMBER_OF_FIXED_MTRR; Index++) {\r
       Base = mMtrrLibFixedMtrrTable[Index].BaseAddress;\r
       for (Index1 = 0; Index1 < 8; Index1++) {\r
-      MemoryType = (UINTN)(RShiftU64 (MtrrSettings.Fixed.Mtrr[Index], Index1 * 8) & 0xff);\r
+      MemoryType = (UINTN)(RShiftU64 (Mtrrs->Fixed.Mtrr[Index], Index1 * 8) & 0xff);\r
         if (MemoryType > CacheWriteBack) {\r
           MemoryType = MTRR_CACHE_INVALID_TYPE;\r
         }\r
@@ -1245,7 +1367,7 @@ MtrrDebugPrintAllMtrrs (
     Base = BASE_1MB;\r
     PreviousMemoryType = MTRR_CACHE_INVALID_TYPE;\r
     do {\r
-      MemoryType = MtrrGetMemoryAttribute (Base);\r
+      MemoryType = MtrrGetMemoryAttributeByAddressWorker (Mtrrs, Base);\r
       if (MemoryType > CacheWriteBack) {\r
         MemoryType = MTRR_CACHE_INVALID_TYPE;\r
       }\r
@@ -1264,14 +1386,14 @@ MtrrDebugPrintAllMtrrs (
       NoRangeLimit = Limit;\r
 \r
       for (Index = 0, Found = FALSE; Index < VariableMtrrCount; Index++) {\r
-        if ((MtrrSettings.Variables.Mtrr[Index].Mask & BIT11) == 0) {\r
+        if ((Mtrrs->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
+        MtrrBase  = (Mtrrs->Variables.Mtrr[Index].Base & (~(SIZE_4KB - 1)));\r
+        MtrrLimit = MtrrBase + ((~(Mtrrs->Variables.Mtrr[Index].Mask & (~(SIZE_4KB - 1)))) & Limit);\r
 \r
         if (Base >= MtrrBase && Base < MtrrLimit) {\r
           Found = TRUE;\r
@@ -1307,9 +1429,29 @@ MtrrDebugPrintAllMtrrs (
     DEBUG((DEBUG_CACHE, "%016lx\n\n", Base - 1));\r
   );\r
 }\r
+\r
+\r
 /**\r
-  This function attempts to set the attributes for a memory range.\r
+  This function prints all MTRRs for debugging.\r
+**/\r
+VOID\r
+EFIAPI\r
+MtrrDebugPrintAllMtrrs (\r
+  VOID\r
+  )\r
+{\r
+  MtrrDebugPrintAllMtrrsWorker (NULL);\r
+}\r
+\r
+\r
+/**\r
+  Worker function attempts to set the attributes for a memory range.\r
+\r
+  If MtrrSettings is not NULL, set the attributes into the input MTRR\r
+  settings buffer.\r
+  If MtrrSettings is NULL, set the attributes into MTRRs registers.\r
 \r
+  @param[in, out]  MtrrSetting       A buffer holding all MTRRs content.\r
   @param[in]       BaseAddress       The physical address that is the start\r
                                      address of a memory region.\r
   @param[in]       Length            The size in bytes of the memory region.\r
@@ -1334,11 +1476,11 @@ MtrrDebugPrintAllMtrrs (
 \r
 **/\r
 RETURN_STATUS\r
-EFIAPI\r
-MtrrSetMemoryAttribute (\r
-  IN PHYSICAL_ADDRESS        BaseAddress,\r
-  IN UINT64                  Length,\r
-  IN MTRR_MEMORY_CACHE_TYPE  Attribute\r
+MtrrSetMemoryAttributeWorker (\r
+  IN OUT MTRR_SETTINGS           *MtrrSetting,\r
+  IN PHYSICAL_ADDRESS            BaseAddress,\r
+  IN UINT64                      Length,\r
+  IN MTRR_MEMORY_CACHE_TYPE      Attribute\r
   )\r
 {\r
   UINT64                    TempQword;\r
@@ -1355,21 +1497,36 @@ MtrrSetMemoryAttribute (
   UINT64                    MtrrValidAddressMask;\r
   BOOLEAN                   OverwriteExistingMtrr;\r
   UINT32                    FirmwareVariableMtrrCount;\r
-  UINT32                    VariableMtrrEnd;\r
   MTRR_CONTEXT              MtrrContext;\r
+  BOOLEAN                   MtrrContextValid;\r
+  BOOLEAN                   FixedSettingsValid[MTRR_NUMBER_OF_FIXED_MTRR];\r
+  BOOLEAN                   FixedSettingsModified[MTRR_NUMBER_OF_FIXED_MTRR];\r
+  MTRR_FIXED_SETTINGS       WorkingFixedSettings;\r
   UINT32                    VariableMtrrCount;\r
-\r
-  DEBUG((DEBUG_CACHE, "MtrrSetMemoryAttribute() %a:%016lx-%016lx\n", mMtrrMemoryCacheTypeShortName[Attribute], BaseAddress, Length));\r
+  MTRR_VARIABLE_SETTINGS    OriginalVariableSettings;\r
+  BOOLEAN                   ProgramVariableSettings;\r
+  MTRR_VARIABLE_SETTINGS    WorkingVariableSettings;\r
+  UINT32                    Index;\r
+  UINT64                    ClearMask;\r
+  UINT64                    OrMask;\r
+  UINT64                    NewValue;\r
+  MTRR_VARIABLE_SETTINGS    *VariableSettings;\r
+\r
+  MtrrContextValid  = FALSE;\r
+  VariableMtrrCount = 0;\r
+  ZeroMem (&WorkingFixedSettings, sizeof (WorkingFixedSettings));\r
+  for (Index = 0; Index < MTRR_NUMBER_OF_FIXED_MTRR; Index++) {\r
+    FixedSettingsValid[Index]    = FALSE;\r
+    FixedSettingsModified[Index] = FALSE;\r
+  }\r
+  ProgramVariableSettings = FALSE;\r
 \r
   if (!IsMtrrSupported ()) {\r
     Status = RETURN_UNSUPPORTED;\r
     goto Done;\r
   }\r
 \r
-  FirmwareVariableMtrrCount = GetFirmwareVariableMtrrCountWorker ();\r
-  VariableMtrrEnd = MTRR_LIB_IA32_VARIABLE_MTRR_BASE + (2 * GetVariableMtrrCount ()) - 1;\r
-\r
-  MtrrLibInitializeMtrrMask(&MtrrValidBitsMask, &MtrrValidAddressMask);\r
+  MtrrLibInitializeMtrrMask (&MtrrValidBitsMask, &MtrrValidAddressMask);\r
 \r
   TempQword = 0;\r
   MemoryType = (UINT64)Attribute;\r
@@ -1395,22 +1552,37 @@ MtrrSetMemoryAttribute (
   // Check if Fixed MTRR\r
   //\r
   Status = RETURN_SUCCESS;\r
-  while ((BaseAddress < BASE_1MB) && (Length > 0) && Status == RETURN_SUCCESS) {\r
-    PreMtrrChange (&MtrrContext);\r
-    Status = ProgramFixedMtrr (MemoryType, &BaseAddress, &Length);\r
-    PostMtrrChange (&MtrrContext);\r
-    if (RETURN_ERROR (Status)) {\r
-      goto Done;\r
+  if (BaseAddress < BASE_1MB) {\r
+    MsrNum = (UINT32)-1;\r
+    while ((BaseAddress < BASE_1MB) && (Length > 0) && Status == RETURN_SUCCESS) {\r
+      Status = ProgramFixedMtrr (MemoryType, &BaseAddress, &Length, &MsrNum, &ClearMask, &OrMask);\r
+      if (RETURN_ERROR (Status)) {\r
+        goto Done;\r
+      }\r
+      if (MtrrSetting != NULL) {\r
+        MtrrSetting->Fixed.Mtrr[MsrNum] = (MtrrSetting->Fixed.Mtrr[MsrNum] & ~ClearMask) | OrMask;\r
+        MtrrSetting->MtrrDefType |= MTRR_LIB_CACHE_FIXED_MTRR_ENABLED;\r
+      } else {\r
+        if (!FixedSettingsValid[MsrNum]) {\r
+          WorkingFixedSettings.Mtrr[MsrNum] = AsmReadMsr64 (mMtrrLibFixedMtrrTable[MsrNum].Msr);\r
+          FixedSettingsValid[MsrNum] = TRUE;\r
+        }\r
+        NewValue = (WorkingFixedSettings.Mtrr[MsrNum] & ~ClearMask) | OrMask;\r
+        if (WorkingFixedSettings.Mtrr[MsrNum] != NewValue) {\r
+          WorkingFixedSettings.Mtrr[MsrNum] = NewValue;\r
+          FixedSettingsModified[MsrNum] = TRUE;\r
+        }\r
+      }\r
     }\r
-  }\r
 \r
-  if (Length == 0) {\r
-    //\r
-    // A Length of 0 can only make sense for fixed MTTR ranges.\r
-    // Since we just handled the fixed MTRRs, we can skip the\r
-    // variable MTRR section.\r
-    //\r
-    goto Done;\r
+    if (Length == 0) {\r
+      //\r
+      // A Length of 0 can only make sense for fixed MTTR ranges.\r
+      // Since we just handled the fixed MTRRs, we can skip the\r
+      // variable MTRR section.\r
+      //\r
+      goto Done;\r
+    }\r
   }\r
 \r
   //\r
@@ -1426,18 +1598,32 @@ MtrrSetMemoryAttribute (
   // Read all variable MTRRs\r
   //\r
   VariableMtrrCount = GetVariableMtrrCountWorker ();\r
+  FirmwareVariableMtrrCount = GetFirmwareVariableMtrrCountWorker ();\r
+  if (MtrrSetting != NULL) {\r
+    VariableSettings = &MtrrSetting->Variables;\r
+  } else {\r
+    MtrrGetVariableMtrrWorker (NULL, VariableMtrrCount, &OriginalVariableSettings);\r
+    CopyMem (&WorkingVariableSettings, &OriginalVariableSettings, sizeof (WorkingVariableSettings));\r
+    ProgramVariableSettings = TRUE;\r
+    VariableSettings = &WorkingVariableSettings;\r
+  }\r
 \r
   //\r
   // Check for overlap\r
   //\r
-  UsedMtrr = MtrrGetMemoryAttributeInVariableMtrr (MtrrValidBitsMask, MtrrValidAddressMask, VariableMtrr);\r
+  UsedMtrr = MtrrGetMemoryAttributeInVariableMtrrWorker (\r
+               VariableSettings,\r
+               FirmwareVariableMtrrCount,\r
+               MtrrValidBitsMask,\r
+               MtrrValidAddressMask,\r
+               VariableMtrr\r
+               );\r
   OverLap = CheckMemoryAttributeOverlap (\r
               FirmwareVariableMtrrCount,\r
               BaseAddress,\r
               BaseAddress + Length - 1,\r
               VariableMtrr\r
               );\r
-\r
   if (OverLap) {\r
     Status = CombineMemoryAttribute (\r
                FirmwareVariableMtrrCount,\r
@@ -1456,7 +1642,7 @@ MtrrSetMemoryAttribute (
       //\r
       // Combined successfully, invalidate the now-unused MTRRs\r
       //\r
-      InvalidateMtrr(VariableMtrrCount, VariableMtrr);\r
+      InvalidateMtrr (VariableSettings, VariableMtrrCount, VariableMtrr);\r
       Status = RETURN_SUCCESS;\r
       goto Done;\r
     }\r
@@ -1466,11 +1652,11 @@ MtrrSetMemoryAttribute (
   // The memory type is the same with the type specified by\r
   // MTRR_LIB_IA32_MTRR_DEF_TYPE.\r
   //\r
-  if ((!OverwriteExistingMtrr) && (Attribute == MtrrGetDefaultMemoryType ())) {\r
+  if ((!OverwriteExistingMtrr) && (Attribute == MtrrGetDefaultMemoryTypeWorker (MtrrSetting))) {\r
     //\r
     // Invalidate the now-unused MTRRs\r
     //\r
-    InvalidateMtrr(VariableMtrrCount, VariableMtrr);\r
+    InvalidateMtrr (VariableSettings, VariableMtrrCount, VariableMtrr);\r
     goto Done;\r
   }\r
 \r
@@ -1484,16 +1670,13 @@ MtrrSetMemoryAttribute (
   //\r
   // Invalidate the now-unused MTRRs\r
   //\r
-  InvalidateMtrr(VariableMtrrCount, VariableMtrr);\r
+  InvalidateMtrr (VariableSettings, VariableMtrrCount, VariableMtrr);\r
 \r
   //\r
   // Find first unused MTRR\r
   //\r
-  for (MsrNum = MTRR_LIB_IA32_VARIABLE_MTRR_BASE;\r
-       MsrNum < VariableMtrrEnd;\r
-       MsrNum += 2\r
-      ) {\r
-    if ((AsmReadMsr64 (MsrNum + 1) & MTRR_LIB_CACHE_MTRR_ENABLED) == 0) {\r
+  for (MsrNum = 0; MsrNum < VariableMtrrCount; MsrNum++) {\r
+    if ((VariableSettings->Mtrr[MsrNum].Mask & MTRR_LIB_CACHE_MTRR_ENABLED) == 0) {\r
       break;\r
     }\r
   }\r
@@ -1512,13 +1695,14 @@ MtrrSetMemoryAttribute (
       //\r
       // Find unused MTRR\r
       //\r
-      for (; MsrNum < VariableMtrrEnd; MsrNum += 2) {\r
-        if ((AsmReadMsr64 (MsrNum + 1) & MTRR_LIB_CACHE_MTRR_ENABLED) == 0) {\r
+      for (; MsrNum < VariableMtrrCount; MsrNum++) {\r
+        if ((VariableSettings->Mtrr[MsrNum].Mask & MTRR_LIB_CACHE_MTRR_ENABLED) == 0) {\r
           break;\r
         }\r
       }\r
 \r
       ProgramVariableMtrr (\r
+        VariableSettings,\r
         MsrNum,\r
         BaseAddress,\r
         Alignment,\r
@@ -1542,13 +1726,14 @@ MtrrSetMemoryAttribute (
     //\r
     // Find unused MTRR\r
     //\r
-    for (; MsrNum < VariableMtrrEnd; MsrNum += 2) {\r
-      if ((AsmReadMsr64 (MsrNum + 1) & MTRR_LIB_CACHE_MTRR_ENABLED) == 0) {\r
+    for (; MsrNum < VariableMtrrCount; MsrNum++) {\r
+      if ((VariableSettings->Mtrr[MsrNum].Mask & MTRR_LIB_CACHE_MTRR_ENABLED) == 0) {\r
         break;\r
       }\r
     }\r
 \r
     ProgramVariableMtrr (\r
+      VariableSettings,\r
       MsrNum,\r
       BaseAddress,\r
       Length,\r
@@ -1564,8 +1749,8 @@ MtrrSetMemoryAttribute (
     //\r
     // Find unused MTRR\r
     //\r
-    for (; MsrNum < VariableMtrrEnd; MsrNum += 2) {\r
-      if ((AsmReadMsr64 (MsrNum + 1) & MTRR_LIB_CACHE_MTRR_ENABLED) == 0) {\r
+    for (; MsrNum < VariableMtrrCount; MsrNum++) {\r
+      if ((VariableSettings->Mtrr[MsrNum].Mask & MTRR_LIB_CACHE_MTRR_ENABLED) == 0) {\r
         break;\r
       }\r
     }\r
@@ -1576,6 +1761,7 @@ MtrrSetMemoryAttribute (
     }\r
 \r
     ProgramVariableMtrr (\r
+      VariableSettings,\r
       MsrNum,\r
       BaseAddress,\r
       Length,\r
@@ -1591,13 +1777,143 @@ MtrrSetMemoryAttribute (
   } while (TempQword > 0);\r
 \r
 Done:\r
+\r
+  //\r
+  // Write fixed MTRRs that have been modified\r
+  //\r
+  for (Index = 0; Index < MTRR_NUMBER_OF_FIXED_MTRR; Index++) {\r
+    if (FixedSettingsModified[Index]) {\r
+      if (!MtrrContextValid) {\r
+        PreMtrrChange (&MtrrContext);\r
+        MtrrContextValid = TRUE;\r
+      }\r
+      AsmWriteMsr64 (\r
+        mMtrrLibFixedMtrrTable[Index].Msr,\r
+        WorkingFixedSettings.Mtrr[Index]\r
+        );\r
+    }\r
+  }\r
+\r
+  //\r
+  // Write variable MTRRs\r
+  //\r
+  if (ProgramVariableSettings) {\r
+    for (Index = 0; Index < VariableMtrrCount; Index++) {\r
+      if (WorkingVariableSettings.Mtrr[Index].Base != OriginalVariableSettings.Mtrr[Index].Base ||\r
+          WorkingVariableSettings.Mtrr[Index].Mask != OriginalVariableSettings.Mtrr[Index].Mask    ) {\r
+        if (!MtrrContextValid) {\r
+          PreMtrrChange (&MtrrContext);\r
+          MtrrContextValid = TRUE;\r
+        }\r
+        AsmWriteMsr64 (\r
+          MTRR_LIB_IA32_VARIABLE_MTRR_BASE + (Index << 1),\r
+          WorkingVariableSettings.Mtrr[Index].Base\r
+          );\r
+        AsmWriteMsr64 (\r
+          MTRR_LIB_IA32_VARIABLE_MTRR_BASE + (Index << 1) + 1,\r
+          WorkingVariableSettings.Mtrr[Index].Mask\r
+          );\r
+      }\r
+    }\r
+  }\r
+  if (MtrrContextValid) {\r
+    PostMtrrChange (&MtrrContext);\r
+  }\r
+\r
   DEBUG((DEBUG_CACHE, "  Status = %r\n", Status));\r
   if (!RETURN_ERROR (Status)) {\r
-    MtrrDebugPrintAllMtrrs ();\r
+    if (MtrrSetting != NULL) {\r
+      MtrrSetting->MtrrDefType |= MTRR_LIB_CACHE_MTRR_ENABLED;\r
+    }\r
+    MtrrDebugPrintAllMtrrsWorker (MtrrSetting);\r
   }\r
 \r
   return Status;\r
 }\r
+\r
+/**\r
+  This function attempts to set the attributes for a memory range.\r
+\r
+  @param[in]  BaseAddress        The physical address that is the start\r
+                                 address of a memory region.\r
+  @param[in]  Length             The size in bytes of the memory region.\r
+  @param[in]  Attributes         The bit mask of attributes to set for the\r
+                                 memory region.\r
+\r
+  @retval RETURN_SUCCESS            The attributes were set for the memory\r
+                                    region.\r
+  @retval RETURN_INVALID_PARAMETER  Length is zero.\r
+  @retval RETURN_UNSUPPORTED        The processor does not support one or\r
+                                    more bytes of the memory resource range\r
+                                    specified by BaseAddress and Length.\r
+  @retval RETURN_UNSUPPORTED        The bit mask of attributes is not support\r
+                                    for the memory resource range specified\r
+                                    by BaseAddress and Length.\r
+  @retval RETURN_ACCESS_DENIED      The attributes for the memory resource\r
+                                    range specified by BaseAddress and Length\r
+                                    cannot be modified.\r
+  @retval RETURN_OUT_OF_RESOURCES   There are not enough system resources to\r
+                                    modify the attributes of the memory\r
+                                    resource range.\r
+\r
+**/\r
+RETURN_STATUS\r
+EFIAPI\r
+MtrrSetMemoryAttribute (\r
+  IN PHYSICAL_ADDRESS        BaseAddress,\r
+  IN UINT64                  Length,\r
+  IN MTRR_MEMORY_CACHE_TYPE  Attribute\r
+  )\r
+{\r
+  DEBUG((DEBUG_CACHE, "MtrrSetMemoryAttribute() %a:%016lx-%016lx\n", mMtrrMemoryCacheTypeShortName[Attribute], BaseAddress, Length));\r
+  return MtrrSetMemoryAttributeWorker (\r
+           NULL,\r
+           BaseAddress,\r
+           Length,\r
+           Attribute\r
+           );\r
+}\r
+\r
+/**\r
+  This function attempts to set the attributes into MTRR setting buffer for a memory range.\r
+\r
+  @param[in, out]  MtrrSetting  MTRR setting buffer to be set.\r
+  @param[in]       BaseAddress  The physical address that is the start address\r
+                                of a memory region.\r
+  @param[in]       Length       The size in bytes of the memory region.\r
+  @param[in]       Attribute    The bit mask of attributes to set for the\r
+                                memory region.\r
+\r
+  @retval RETURN_SUCCESS            The attributes were set for the memory region.\r
+  @retval RETURN_INVALID_PARAMETER  Length is zero.\r
+  @retval RETURN_UNSUPPORTED        The processor does not support one or more bytes of the\r
+                                    memory resource range specified by BaseAddress and Length.\r
+  @retval RETURN_UNSUPPORTED        The bit mask of attributes is not support for the memory resource\r
+                                    range specified by BaseAddress and Length.\r
+  @retval RETURN_ACCESS_DENIED      The attributes for the memory resource range specified by\r
+                                    BaseAddress and Length cannot be modified.\r
+  @retval RETURN_OUT_OF_RESOURCES   There are not enough system resources to modify the attributes of\r
+                                    the memory resource range.\r
+\r
+**/\r
+RETURN_STATUS\r
+EFIAPI\r
+MtrrSetMemoryAttributeInMtrrSettings (\r
+  IN OUT MTRR_SETTINGS       *MtrrSetting,\r
+  IN PHYSICAL_ADDRESS        BaseAddress,\r
+  IN UINT64                  Length,\r
+  IN MTRR_MEMORY_CACHE_TYPE  Attribute\r
+  )\r
+{\r
+  DEBUG((DEBUG_CACHE, "MtrrSetMemoryAttributeMtrrSettings(%p) %a:%016lx-%016lx\n", MtrrSetting, mMtrrMemoryCacheTypeShortName[Attribute], BaseAddress, Length));\r
+  return MtrrSetMemoryAttributeWorker (\r
+           MtrrSetting,\r
+           BaseAddress,\r
+           Length,\r
+           Attribute\r
+           );\r
+}\r
+\r
 /**\r
   Worker function setting variable MTRRs\r
 \r
@@ -1651,6 +1967,8 @@ MtrrSetVariableMtrr (
   PreMtrrChange (&MtrrContext);\r
   MtrrSetVariableMtrrWorker (VariableSettings);\r
   PostMtrrChange (&MtrrContext);\r
+  MtrrDebugPrintAllMtrrs ();\r
+\r
   return  VariableSettings;\r
 }\r
 \r
@@ -1699,6 +2017,7 @@ MtrrSetFixedMtrr (
   PreMtrrChange (&MtrrContext);\r
   MtrrSetFixedMtrrWorker (FixedSettings);\r
   PostMtrrChange (&MtrrContext);\r
+  MtrrDebugPrintAllMtrrs ();\r
 \r
   return FixedSettings;\r
 }\r
@@ -1731,6 +2050,7 @@ MtrrGetAllMtrrs (
   // Get variable MTRRs\r
   //\r
   MtrrGetVariableMtrrWorker (\r
+    NULL,\r
     GetVariableMtrrCountWorker (),\r
     &MtrrSetting->Variables\r
     );\r
@@ -1783,9 +2103,12 @@ MtrrSetAllMtrrs (
 \r
   PostMtrrChangeEnableCache (&MtrrContext);\r
 \r
+  MtrrDebugPrintAllMtrrs ();\r
+\r
   return MtrrSetting;\r
 }\r
 \r
+\r
 /**\r
   Checks if MTRR is supported.\r
 \r