+ if (Length != Ranges[End].Length) {\r
+ Ranges[End].BaseAddress = Base1;\r
+ Ranges[End].Length = Length - Ranges[End].Length;\r
+ Index = End;\r
+ } else {\r
+ Index = End + 1;\r
+ }\r
+ }\r
+\r
+ if (*ScratchSize < BiggestScratchSize) {\r
+ *ScratchSize = BiggestScratchSize;\r
+ return RETURN_BUFFER_TOO_SMALL;\r
+ }\r
+ return RETURN_SUCCESS;\r
+}\r
+\r
+/**\r
+ Set the below-1MB memory attribute to fixed MTRR buffer.\r
+ Modified flag array indicates which fixed MTRR is modified.\r
+\r
+ @param [in, out] FixedSettings Fixed MTRR buffer.\r
+ @param [out] Modified Flag array indicating which MTRR is modified.\r
+ @param [in] BaseAddress Base address.\r
+ @param [in] Length Length.\r
+ @param [in] Type Memory type.\r
+\r
+ @retval RETURN_SUCCESS The memory attribute is set successfully.\r
+ @retval RETURN_UNSUPPORTED The requested range or cache type was invalid\r
+ for the fixed MTRRs.\r
+**/\r
+RETURN_STATUS\r
+MtrrLibSetBelow1MBMemoryAttribute (\r
+ IN OUT MTRR_FIXED_SETTINGS *FixedSettings,\r
+ OUT BOOLEAN *Modified,\r
+ IN PHYSICAL_ADDRESS BaseAddress,\r
+ IN UINT64 Length,\r
+ IN MTRR_MEMORY_CACHE_TYPE Type\r
+ )\r
+{\r
+ RETURN_STATUS Status;\r
+ UINT32 MsrIndex;\r
+ UINT64 ClearMask;\r
+ UINT64 OrMask;\r
+ UINT64 ClearMasks[ARRAY_SIZE (mMtrrLibFixedMtrrTable)];\r
+ UINT64 OrMasks[ARRAY_SIZE (mMtrrLibFixedMtrrTable)];\r
+ BOOLEAN LocalModified[ARRAY_SIZE (mMtrrLibFixedMtrrTable)];\r
+\r
+ ASSERT (BaseAddress < BASE_1MB);\r
+\r
+ SetMem (LocalModified, sizeof (LocalModified), FALSE);\r
+\r
+ //\r
+ // (Value & ~0 | 0) still equals to (Value)\r
+ //\r
+ SetMem64 (ClearMasks, sizeof (ClearMasks), 0);\r
+ SetMem64 (OrMasks, sizeof (OrMasks), 0);\r
+\r
+ MsrIndex = (UINT32)-1;\r
+ while ((BaseAddress < BASE_1MB) && (Length != 0)) {\r
+ Status = MtrrLibProgramFixedMtrr (Type, &BaseAddress, &Length, &MsrIndex, &ClearMask, &OrMask);\r
+ if (RETURN_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ ClearMasks[MsrIndex] = ClearMask;\r
+ OrMasks[MsrIndex] = OrMask;\r
+ Modified[MsrIndex] = TRUE;\r
+ LocalModified[MsrIndex] = TRUE;\r
+ }\r
+\r
+ for (MsrIndex = 0; MsrIndex < ARRAY_SIZE (mMtrrLibFixedMtrrTable); MsrIndex++) {\r
+ if (LocalModified[MsrIndex]) {\r
+ FixedSettings->Mtrr[MsrIndex] = (FixedSettings->Mtrr[MsrIndex] & ~ClearMasks[MsrIndex]) | OrMasks[MsrIndex];\r
+ }\r
+ }\r
+ return RETURN_SUCCESS;\r
+}\r
+\r
+/**\r
+ This function attempts to set the attributes into MTRR setting buffer for multiple memory ranges.\r
+\r
+ @param[in, out] MtrrSetting MTRR setting buffer to be set.\r
+ @param[in] Scratch A temporary scratch buffer that is used to perform the calculation.\r
+ @param[in, out] ScratchSize Pointer to the size in bytes of the scratch buffer.\r
+ It may be updated to the actual required size when the calculation\r
+ needs more scratch buffer.\r
+ @param[in] Ranges Pointer to an array of MTRR_MEMORY_RANGE.\r
+ When range overlap happens, the last one takes higher priority.\r
+ When the function returns, either all the attributes are set successfully,\r
+ or none of them is set.\r
+ @param[in] Count of MTRR_MEMORY_RANGE.\r
+\r
+ @retval RETURN_SUCCESS The attributes were set for all the memory ranges.\r
+ @retval RETURN_INVALID_PARAMETER Length in any range 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 in any range.\r
+ @retval RETURN_UNSUPPORTED The bit mask of attributes is not support for the memory resource\r
+ range specified by BaseAddress and Length in any range.\r
+ @retval RETURN_OUT_OF_RESOURCES There are not enough system resources to modify the attributes of\r
+ the memory resource ranges.\r
+ @retval RETURN_ACCESS_DENIED The attributes for the memory resource range specified by\r
+ BaseAddress and Length cannot be modified.\r
+ @retval RETURN_BUFFER_TOO_SMALL The scratch buffer is too small for MTRR calculation.\r
+**/\r
+RETURN_STATUS\r
+EFIAPI\r
+MtrrSetMemoryAttributesInMtrrSettings (\r
+ IN OUT MTRR_SETTINGS *MtrrSetting,\r
+ IN VOID *Scratch,\r
+ IN OUT UINTN *ScratchSize,\r
+ IN CONST MTRR_MEMORY_RANGE *Ranges,\r
+ IN UINTN RangeCount\r
+ )\r
+{\r
+ RETURN_STATUS Status;\r
+ UINT32 Index;\r
+ UINT64 BaseAddress;\r
+ UINT64 Length;\r
+ BOOLEAN Above1MbExist;\r
+\r
+ UINT64 MtrrValidBitsMask;\r
+ UINT64 MtrrValidAddressMask;\r
+ MTRR_MEMORY_CACHE_TYPE DefaultType;\r
+ MTRR_VARIABLE_SETTINGS VariableSettings;\r
+ MTRR_MEMORY_RANGE WorkingRanges[2 * ARRAY_SIZE (MtrrSetting->Variables.Mtrr) + 2];\r
+ UINTN WorkingRangeCount;\r
+ BOOLEAN Modified;\r
+ MTRR_VARIABLE_SETTING VariableSetting;\r
+ UINT32 OriginalVariableMtrrCount;\r
+ UINT32 FirmwareVariableMtrrCount;\r
+ UINT32 WorkingVariableMtrrCount;\r
+ MTRR_MEMORY_RANGE OriginalVariableMtrr[ARRAY_SIZE (MtrrSetting->Variables.Mtrr)];\r
+ MTRR_MEMORY_RANGE WorkingVariableMtrr[ARRAY_SIZE (MtrrSetting->Variables.Mtrr)];\r
+ BOOLEAN VariableSettingModified[ARRAY_SIZE (MtrrSetting->Variables.Mtrr)];\r
+\r
+ BOOLEAN FixedSettingsModified[ARRAY_SIZE (mMtrrLibFixedMtrrTable)];\r
+ MTRR_FIXED_SETTINGS WorkingFixedSettings;\r
+\r
+ MTRR_CONTEXT MtrrContext;\r
+ BOOLEAN MtrrContextValid;\r
+\r
+ MtrrLibInitializeMtrrMask (&MtrrValidBitsMask, &MtrrValidAddressMask);\r