+ CopyMem (&Ranges[EndIndex + 1 - DeltaCount], &Ranges[EndIndex + 1], (*Count - EndIndex - 1) * sizeof (Ranges[0]));\r
+ *Count -= DeltaCount;\r
+\r
+ if (LengthLeft != 0) {\r
+ Ranges[StartIndex].Length = LengthLeft;\r
+ StartIndex++;\r
+ }\r
+ if (LengthRight != 0) {\r
+ Ranges[EndIndex - DeltaCount].BaseAddress = BaseAddress + Length;\r
+ Ranges[EndIndex - DeltaCount].Length = LengthRight;\r
+ Ranges[EndIndex - DeltaCount].Type = Ranges[EndIndex].Type;\r
+ }\r
+ Ranges[StartIndex].BaseAddress = BaseAddress;\r
+ Ranges[StartIndex].Length = Length;\r
+ Ranges[StartIndex].Type = Type;\r
+ return RETURN_SUCCESS;\r
+}\r
+\r
+/**\r
+ Allocate one or more variable MTRR to cover the range identified by\r
+ BaseAddress and Length.\r
+\r
+ @param Ranges Memory range array holding the memory type\r
+ settings for all memory address.\r
+ @param RangeCount Count of memory ranges.\r
+ @param VariableMtrr Variable MTRR array.\r
+ @param VariableMtrrCapacity Capacity of variable MTRR array.\r
+ @param VariableMtrrCount Count of variable MTRR.\r
+ @param BaseAddress Base address of the memory range.\r
+ @param Length Length of the memory range.\r
+ @param Type MTRR type of the memory range.\r
+ @param Alignment0 Alignment of 0.\r
+\r
+ @retval RETURN_SUCCESS Variable MTRRs are allocated successfully.\r
+ @retval RETURN_OUT_OF_RESOURCES Count of variable MTRRs exceeds capacity.\r
+**/\r
+RETURN_STATUS\r
+MtrrLibSetMemoryAttributeInVariableMtrr (\r
+ IN CONST MEMORY_RANGE *Ranges,\r
+ IN UINT32 RangeCount,\r
+ IN OUT VARIABLE_MTRR *VariableMtrr,\r
+ IN UINT32 VariableMtrrCapacity,\r
+ IN OUT UINT32 *VariableMtrrCount,\r
+ IN UINT64 BaseAddress,\r
+ IN UINT64 Length,\r
+ IN MTRR_MEMORY_CACHE_TYPE Type,\r
+ IN UINT64 Alignment0\r
+ );\r
+\r
+/**\r
+ Allocate one or more variable MTRR to cover the range identified by\r
+ BaseAddress and Length.\r
+\r
+ The routine recursively calls MtrrLibSetMemoryAttributeInVariableMtrr()\r
+ to allocate variable MTRRs when the range contains several sub-ranges\r
+ with different attributes.\r
+\r
+ @param Ranges Memory range array holding the memory type\r
+ settings for all memory address.\r
+ @param RangeCount Count of memory ranges.\r
+ @param VariableMtrr Variable MTRR array.\r
+ @param VariableMtrrCapacity Capacity of variable MTRR array.\r
+ @param VariableMtrrCount Count of variable MTRR.\r
+ @param BaseAddress Base address of the memory range.\r
+ @param Length Length of the memory range.\r
+ @param Type MTRR type of the range.\r
+ If it's CacheInvalid, the memory range may\r
+ contains several sub-ranges with different\r
+ attributes.\r
+ @param Alignment0 Alignment of 0.\r
+\r
+ @retval RETURN_SUCCESS Variable MTRRs are allocated successfully.\r
+ @retval RETURN_OUT_OF_RESOURCES Count of variable MTRRs exceeds capacity.\r
+**/\r
+RETURN_STATUS\r
+MtrrLibAddVariableMtrr (\r
+ IN CONST MEMORY_RANGE *Ranges,\r
+ IN UINT32 RangeCount,\r
+ IN OUT VARIABLE_MTRR *VariableMtrr,\r
+ IN UINT32 VariableMtrrCapacity,\r
+ IN OUT UINT32 *VariableMtrrCount,\r
+ IN PHYSICAL_ADDRESS BaseAddress,\r
+ IN UINT64 Length,\r
+ IN MTRR_MEMORY_CACHE_TYPE Type,\r
+ IN UINT64 Alignment0\r
+)\r
+{\r
+ RETURN_STATUS Status;\r
+ UINT32 Index;\r
+ UINT64 SubLength;\r
+\r
+ MTRR_LIB_ASSERT_ALIGNED (BaseAddress, Length);\r
+ if (Type == CacheInvalid) {\r
+ for (Index = 0; Index < RangeCount; Index++) {\r
+ if (Ranges[Index].BaseAddress <= BaseAddress && BaseAddress < Ranges[Index].BaseAddress + Ranges[Index].Length) {\r
+\r
+ //\r
+ // Because the Length may not be aligned to BaseAddress, below code calls\r
+ // MtrrLibSetMemoryAttributeInVariableMtrr() instead of itself.\r
+ // MtrrLibSetMemoryAttributeInVariableMtrr() splits the range to several\r
+ // aligned ranges.\r
+ //\r
+ if (Ranges[Index].BaseAddress + Ranges[Index].Length >= BaseAddress + Length) {\r
+ return MtrrLibSetMemoryAttributeInVariableMtrr (\r
+ Ranges, RangeCount, VariableMtrr, VariableMtrrCapacity, VariableMtrrCount,\r
+ BaseAddress, Length, Ranges[Index].Type, Alignment0\r
+ );\r
+ } else {\r
+ SubLength = Ranges[Index].BaseAddress + Ranges[Index].Length - BaseAddress;\r
+ Status = MtrrLibSetMemoryAttributeInVariableMtrr (\r
+ Ranges, RangeCount, VariableMtrr, VariableMtrrCapacity, VariableMtrrCount,\r
+ BaseAddress, SubLength, Ranges[Index].Type, Alignment0\r
+ );\r
+ if (RETURN_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ BaseAddress += SubLength;\r
+ Length -= SubLength;\r
+ }\r
+ }\r
+ }\r
+\r
+ //\r
+ // Because memory ranges cover all the memory addresses, it's impossible to be here.\r
+ //\r
+ ASSERT (FALSE);\r
+ return RETURN_DEVICE_ERROR;\r
+ } else {\r
+ for (Index = 0; Index < *VariableMtrrCount; Index++) {\r
+ if (VariableMtrr[Index].BaseAddress == BaseAddress && VariableMtrr[Index].Length == Length) {\r
+ ASSERT (VariableMtrr[Index].Type == Type);\r
+ break;\r
+ }\r
+ }\r
+ if (Index == *VariableMtrrCount) {\r
+ if (*VariableMtrrCount == VariableMtrrCapacity) {\r
+ return RETURN_OUT_OF_RESOURCES;\r
+ }\r
+ VariableMtrr[Index].BaseAddress = BaseAddress;\r
+ VariableMtrr[Index].Length = Length;\r
+ VariableMtrr[Index].Type = Type;\r
+ VariableMtrr[Index].Valid = TRUE;\r
+ VariableMtrr[Index].Used = TRUE;\r
+ (*VariableMtrrCount)++;\r
+ }\r
+ return RETURN_SUCCESS;\r
+ }\r
+}\r
+\r
+/**\r
+ Allocate one or more variable MTRR to cover the range identified by\r
+ BaseAddress and Length.\r
+\r
+ @param Ranges Memory range array holding the memory type\r
+ settings for all memory address.\r
+ @param RangeCount Count of memory ranges.\r
+ @param VariableMtrr Variable MTRR array.\r
+ @param VariableMtrrCapacity Capacity of variable MTRR array.\r
+ @param VariableMtrrCount Count of variable MTRR.\r
+ @param BaseAddress Base address of the memory range.\r
+ @param Length Length of the memory range.\r
+ @param Type MTRR type of the memory range.\r
+ @param Alignment0 Alignment of 0.\r
+\r
+ @retval RETURN_SUCCESS Variable MTRRs are allocated successfully.\r
+ @retval RETURN_OUT_OF_RESOURCES Count of variable MTRRs exceeds capacity.\r
+**/\r
+RETURN_STATUS\r
+MtrrLibSetMemoryAttributeInVariableMtrr (\r
+ IN CONST MEMORY_RANGE *Ranges,\r
+ IN UINT32 RangeCount,\r
+ IN OUT VARIABLE_MTRR *VariableMtrr,\r
+ IN UINT32 VariableMtrrCapacity,\r
+ IN OUT UINT32 *VariableMtrrCount,\r
+ IN UINT64 BaseAddress,\r
+ IN UINT64 Length,\r
+ IN MTRR_MEMORY_CACHE_TYPE Type,\r
+ IN UINT64 Alignment0\r
+)\r
+{\r
+ UINT64 Alignment;\r
+ UINT32 MtrrNumber;\r
+ UINT32 SubtractiveLeft;\r
+ UINT32 SubtractiveRight;\r
+ BOOLEAN UseLeastAlignment;\r
+\r
+ MtrrNumber = MtrrLibGetMtrrNumber (Ranges, RangeCount, VariableMtrr, *VariableMtrrCount,\r
+ BaseAddress, Length, Type, Alignment0, &SubtractiveLeft, &SubtractiveRight);\r
+\r
+ if (MtrrNumber + *VariableMtrrCount > VariableMtrrCapacity) {\r
+ return RETURN_OUT_OF_RESOURCES;\r