+ VectorCount = VectorIndex + 1;\r
+ DEBUG ((\r
+ DEBUG_CACHE, "VectorCount (%016lx - %016lx) = %d\n", \r
+ Ranges[0].BaseAddress, Ranges[RangeCount - 1].BaseAddress + Ranges[RangeCount - 1].Length, VectorCount\r
+ ));\r
+ ASSERT (VectorCount < MAX_UINT16);\r
+\r
+ RequiredScratchSize = VectorCount * sizeof (*Vector) + VectorCount * VectorCount * sizeof (*Weight);\r
+ if (*ScratchSize < RequiredScratchSize) {\r
+ *ScratchSize = RequiredScratchSize;\r
+ return RETURN_BUFFER_TOO_SMALL;\r
+ }\r
+ Vector[VectorCount - 1].Address = Base1;\r
+\r
+ Weight = (UINT8 *) &Vector[VectorCount];\r
+ //\r
+ // Set mandatory weight between any vector to max\r
+ // Set optional weight and between any vector and self->self to 0\r
+ // E.g.:\r
+ // 00 FF FF FF\r
+ // 00 00 FF FF\r
+ // 00 00 00 FF\r
+ // 00 00 00 00\r
+ //\r
+ for (VectorIndex = 0; VectorIndex < VectorCount; VectorIndex++) {\r
+ SetMem (&Weight[M(VectorIndex, 0)], VectorIndex + 1, 0);\r
+ if (VectorIndex != VectorCount - 1) {\r
+ Weight[M (VectorIndex, VectorIndex + 1)] = (DefaultType == Vector[VectorIndex].Type) ? 0 : 1;\r
+ SetMem (&Weight[M (VectorIndex, VectorIndex + 2)], VectorCount - VectorIndex - 2, MAX_WEIGHT);\r
+ }\r
+ }\r
+\r
+ for (TypeCount = 2; TypeCount <= 3; TypeCount++) {\r
+ for (Start = 0; Start < VectorCount; Start++) {\r
+ for (Stop = Start + 2; Stop < VectorCount; Stop++) {\r
+ ASSERT (Vector[Stop].Address > Vector[Start].Address);\r
+ Length = Vector[Stop].Address - Vector[Start].Address;\r
+ if (Length > Vector[Start].Alignment) {\r
+ //\r
+ // Pickup a new Start when [Start, Stop) cannot be described by one MTRR.\r
+ //\r
+ break;\r
+ }\r
+ if ((Weight[M(Start, Stop)] == MAX_WEIGHT) && MtrrLibIsPowerOfTwo (Length)) {\r
+ if (MtrrLibGetNumberOfTypes (\r
+ Ranges, RangeCount, Vector[Start].Address, Vector[Stop].Address - Vector[Start].Address, &Type\r
+ ) == TypeCount) {\r
+ //\r
+ // Update the Weight[Start, Stop] using subtractive path.\r
+ //\r
+ MtrrLibCalculateSubtractivePath (\r
+ DefaultType, A0,\r
+ Ranges, RangeCount,\r
+ (UINT16)VectorCount, Vector, Weight,\r
+ Start, Stop, Type, TypeCount,\r
+ NULL, 0, NULL\r
+ );\r
+ } else if (TypeCount == 2) {\r
+ //\r
+ // Pick up a new Start when we expect 2-type range, but 3-type range is met.\r
+ // Because no matter how Stop is increased, we always meet 3-type range.\r
+ //\r
+ break;\r
+ }\r
+ }\r
+ }\r
+ }\r
+ }\r
+\r
+ Status = RETURN_SUCCESS;\r
+ MtrrLibCalculateLeastMtrrs ((UINT16) VectorCount, Vector, Weight, 0, (UINT16) VectorCount - 1, FALSE);\r
+ Stop = (UINT16) VectorCount - 1;\r
+ while (Stop != 0) {\r
+ Start = Vector[Stop].Previous;\r
+ TypeCount = MAX_UINT8;\r
+ Type = 0;\r
+ if (Weight[M(Start, Stop)] != 0) {\r
+ TypeCount = MtrrLibGetNumberOfTypes (Ranges, RangeCount, Vector[Start].Address, Vector[Stop].Address - Vector[Start].Address, &Type);\r
+ Status = MtrrLibAppendVariableMtrr (\r
+ Mtrrs, MtrrCapacity, MtrrCount,\r
+ Vector[Start].Address, Vector[Stop].Address - Vector[Start].Address, \r
+ MtrrLibLowestType (Type)\r
+ );\r
+ if (RETURN_ERROR (Status)) {\r
+ break;\r
+ }\r
+ }\r
+\r
+ if (Start != Stop - 1) {\r