/* Convert variable MTRRs to a RAW MTRR_MEMORY_RANGE array. One MTRR_MEMORY_RANGE element is created for each MTRR setting. The routine doesn't remove the overlap or combine the near-by region. */
UINT32 MtrrLibGetRawVariableRanges(IN CONST MTRR_VARIABLE_SETTINGS *VariableSettings, IN UINTN VariableMtrrCount, IN UINT64 MtrrValidBitsMask, IN UINT64 MtrrValidAddressMask, OUT MTRR_MEMORY_RANGE *VariableMtrr)
/* Convert variable MTRRs to a RAW MTRR_MEMORY_RANGE array. One MTRR_MEMORY_RANGE element is created for each MTRR setting. The routine doesn't remove the overlap or combine the near-by region. */
UINT32 MtrrLibGetRawVariableRanges(IN CONST MTRR_VARIABLE_SETTINGS *VariableSettings, IN UINTN VariableMtrrCount, IN UINT64 MtrrValidBitsMask, IN UINT64 MtrrValidAddressMask, OUT MTRR_MEMORY_RANGE *VariableMtrr)
{
  UINTN   Index;
  UINT32  UsedMtrr;
  ZeroMem (VariableMtrr, sizeof (MTRR_MEMORY_RANGE) * ARRAY_SIZE (VariableSettings->Mtrr));
  for (Index = 0, UsedMtrr = 0; Index < VariableMtrrCount; Index++) {
    if (((MSR_IA32_MTRR_PHYSMASK_REGISTER *)&VariableSettings->Mtrr[Index].Mask)->Bits.V != 0) {
      VariableMtrr[Index].BaseAddress = (VariableSettings->Mtrr[Index].Base & MtrrValidAddressMask);
      VariableMtrr[Index].Length      =
        ((~(VariableSettings->Mtrr[Index].Mask & MtrrValidAddressMask)) & MtrrValidBitsMask) + 1;
      VariableMtrr[Index].Type = (MTRR_MEMORY_CACHE_TYPE)(VariableSettings->Mtrr[Index].Base & 0x0ff);
      UsedMtrr++;
    }
  }
  return UsedMtrr;
}