diff --git a/UefiCpuPkg/Include/Library/MtrrLib.h b/UefiCpuPkg/Include/Library/MtrrLib.h index 94cf615901..86cc1aab3b 100644 --- a/UefiCpuPkg/Include/Library/MtrrLib.h +++ b/UefiCpuPkg/Include/Library/MtrrLib.h @@ -359,4 +359,27 @@ MtrrSetMemoryAttributesInMtrrSettings ( IN UINTN RangeCount ); +/** + This function returns a Ranges array containing the memory cache types + of all memory addresses. + + @param[in] MtrrSetting MTRR setting buffer to parse. + @param[out] Ranges Pointer to an array of MTRR_MEMORY_RANGE. + @param[in,out] RangeCount Count of MTRR_MEMORY_RANGE. + On input, the maximum entries the Ranges can hold. + On output, the actual entries that the function returns. + + @retval RETURN_INVALID_PARAMETER RangeCount is NULL. + @retval RETURN_INVALID_PARAMETER *RangeCount is not 0 but Ranges is NULL. + @retval RETURN_BUFFER_TOO_SMALL *RangeCount is too small. + @retval RETURN_SUCCESS Ranges are successfully returned. +**/ +RETURN_STATUS +EFIAPI +MtrrGetMemoryAttributesInMtrrSettings ( + IN CONST MTRR_SETTINGS *MtrrSetting OPTIONAL, + OUT MTRR_MEMORY_RANGE *Ranges, + IN OUT UINTN *RangeCount + ); + #endif // _MTRR_LIB_H_ diff --git a/UefiCpuPkg/Library/MtrrLib/MtrrLib.c b/UefiCpuPkg/Library/MtrrLib/MtrrLib.c index 010c15affe..96474f6f9b 100644 --- a/UefiCpuPkg/Library/MtrrLib/MtrrLib.c +++ b/UefiCpuPkg/Library/MtrrLib/MtrrLib.c @@ -292,7 +292,7 @@ GetFirmwareVariableMtrrCount ( **/ MTRR_MEMORY_CACHE_TYPE MtrrGetDefaultMemoryTypeWorker ( - IN MTRR_SETTINGS *MtrrSetting + IN CONST MTRR_SETTINGS *MtrrSetting ) { MSR_IA32_MTRR_DEF_TYPE_REGISTER DefType; @@ -690,11 +690,11 @@ MtrrGetMemoryAttributeInVariableMtrrWorker ( **/ UINT32 MtrrLibGetRawVariableRanges ( - IN MTRR_VARIABLE_SETTINGS *VariableSettings, - IN UINTN VariableMtrrCount, - IN UINT64 MtrrValidBitsMask, - IN UINT64 MtrrValidAddressMask, - OUT MTRR_MEMORY_RANGE *VariableMtrr + IN CONST MTRR_VARIABLE_SETTINGS *VariableSettings, + IN UINTN VariableMtrrCount, + IN UINT64 MtrrValidBitsMask, + IN UINT64 MtrrValidAddressMask, + OUT MTRR_MEMORY_RANGE *VariableMtrr ) { UINTN Index; @@ -1824,10 +1824,10 @@ MtrrLibCalculateMtrrs ( **/ RETURN_STATUS MtrrLibApplyFixedMtrrs ( - IN MTRR_FIXED_SETTINGS *Fixed, - IN OUT MTRR_MEMORY_RANGE *Ranges, - IN UINTN RangeCapacity, - IN OUT UINTN *RangeCount + IN CONST MTRR_FIXED_SETTINGS *Fixed, + IN OUT MTRR_MEMORY_RANGE *Ranges, + IN UINTN RangeCapacity, + IN OUT UINTN *RangeCount ) { RETURN_STATUS Status; @@ -2957,6 +2957,103 @@ IsMtrrSupported ( return MtrrLibIsMtrrSupported (NULL, NULL); } +/** + This function returns a Ranges array containing the memory cache types + of all memory addresses. + + @param[in] MtrrSetting MTRR setting buffer to parse. + @param[out] Ranges Pointer to an array of MTRR_MEMORY_RANGE. + @param[in,out] RangeCount Count of MTRR_MEMORY_RANGE. + On input, the maximum entries the Ranges can hold. + On output, the actual entries that the function returns. + + @retval RETURN_INVALID_PARAMETER RangeCount is NULL. + @retval RETURN_INVALID_PARAMETER *RangeCount is not 0 but Ranges is NULL. + @retval RETURN_BUFFER_TOO_SMALL *RangeCount is too small. + @retval RETURN_SUCCESS Ranges are successfully returned. +**/ +RETURN_STATUS +EFIAPI +MtrrGetMemoryAttributesInMtrrSettings ( + IN CONST MTRR_SETTINGS *MtrrSetting OPTIONAL, + OUT MTRR_MEMORY_RANGE *Ranges, + IN OUT UINTN *RangeCount + ) +{ + RETURN_STATUS Status; + MTRR_SETTINGS LocalMtrrs; + CONST MTRR_SETTINGS *Mtrrs; + MSR_IA32_MTRR_DEF_TYPE_REGISTER *MtrrDefType; + UINTN LocalRangeCount; + UINT64 MtrrValidBitsMask; + UINT64 MtrrValidAddressMask; + UINT32 VariableMtrrCount; + MTRR_MEMORY_RANGE RawVariableRanges[ARRAY_SIZE (Mtrrs->Variables.Mtrr)]; + MTRR_MEMORY_RANGE LocalRanges[ + ARRAY_SIZE (mMtrrLibFixedMtrrTable) * sizeof (UINT64) + 2 * ARRAY_SIZE (Mtrrs->Variables.Mtrr) + 1 + ]; + + if (RangeCount == NULL) { + return RETURN_INVALID_PARAMETER; + } + + if ((*RangeCount != 0) && (Ranges == NULL)) { + return RETURN_INVALID_PARAMETER; + } + + if (MtrrSetting != NULL) { + Mtrrs = MtrrSetting; + } else { + MtrrGetAllMtrrs (&LocalMtrrs); + Mtrrs = &LocalMtrrs; + } + + MtrrDefType = (MSR_IA32_MTRR_DEF_TYPE_REGISTER *)&Mtrrs->MtrrDefType; + + LocalRangeCount = 1; + MtrrLibInitializeMtrrMask (&MtrrValidBitsMask, &MtrrValidAddressMask); + LocalRanges[0].BaseAddress = 0; + LocalRanges[0].Length = MtrrValidBitsMask + 1; + + if (MtrrDefType->Bits.E == 0) { + LocalRanges[0].Type = CacheUncacheable; + } else { + LocalRanges[0].Type = MtrrGetDefaultMemoryTypeWorker (Mtrrs); + + VariableMtrrCount = GetVariableMtrrCountWorker (); + ASSERT (VariableMtrrCount <= ARRAY_SIZE (MtrrSetting->Variables.Mtrr)); + + MtrrLibGetRawVariableRanges ( + &Mtrrs->Variables, + VariableMtrrCount, + MtrrValidBitsMask, + MtrrValidAddressMask, + RawVariableRanges + ); + Status = MtrrLibApplyVariableMtrrs ( + RawVariableRanges, + VariableMtrrCount, + LocalRanges, + ARRAY_SIZE (LocalRanges), + &LocalRangeCount + ); + ASSERT_RETURN_ERROR (Status); + + if (MtrrDefType->Bits.FE == 1) { + MtrrLibApplyFixedMtrrs (&Mtrrs->Fixed, LocalRanges, ARRAY_SIZE (LocalRanges), &LocalRangeCount); + } + } + + if (*RangeCount < LocalRangeCount) { + *RangeCount = LocalRangeCount; + return RETURN_BUFFER_TOO_SMALL; + } + + CopyMem (Ranges, LocalRanges, LocalRangeCount * sizeof (LocalRanges[0])); + *RangeCount = LocalRangeCount; + return RETURN_SUCCESS; +} + /** Worker function prints all MTRRs for debugging.