/** @file
Unit tests of the MtrrLib instance of the MtrrLib class
Copyright (c) 2020 - 2023, Intel Corporation. All rights reserved.
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
#include "MtrrLibUnitTest.h"
STATIC CONST MTRR_LIB_SYSTEM_PARAMETER mDefaultSystemParameter = {
42, TRUE, TRUE, CacheUncacheable, 12
};
STATIC MTRR_LIB_SYSTEM_PARAMETER mSystemParameters[] = {
{ 38, TRUE, TRUE, CacheUncacheable, 12 },
{ 38, TRUE, TRUE, CacheWriteBack, 12 },
{ 38, TRUE, TRUE, CacheWriteThrough, 12 },
{ 38, TRUE, TRUE, CacheWriteProtected, 12 },
{ 38, TRUE, TRUE, CacheWriteCombining, 12 },
{ 42, TRUE, TRUE, CacheUncacheable, 12 },
{ 42, TRUE, TRUE, CacheWriteBack, 12 },
{ 42, TRUE, TRUE, CacheWriteThrough, 12 },
{ 42, TRUE, TRUE, CacheWriteProtected, 12 },
{ 42, TRUE, TRUE, CacheWriteCombining, 12 },
{ 48, TRUE, TRUE, CacheUncacheable, 12 },
{ 48, TRUE, TRUE, CacheWriteBack, 12 },
{ 48, TRUE, TRUE, CacheWriteThrough, 12 },
{ 48, TRUE, TRUE, CacheWriteProtected, 12 },
{ 48, TRUE, TRUE, CacheWriteCombining, 12 },
{ 48, TRUE, FALSE, CacheUncacheable, 12 },
{ 48, TRUE, FALSE, CacheWriteBack, 12 },
{ 48, TRUE, FALSE, CacheWriteThrough, 12 },
{ 48, TRUE, FALSE, CacheWriteProtected, 12 },
{ 48, TRUE, FALSE, CacheWriteCombining, 12 },
{ 48, TRUE, TRUE, CacheWriteBack, 12, 7}, // 7 bits for MKTME
};
UINT32 mFixedMtrrsIndex[] = {
MSR_IA32_MTRR_FIX64K_00000,
MSR_IA32_MTRR_FIX16K_80000,
MSR_IA32_MTRR_FIX16K_A0000,
MSR_IA32_MTRR_FIX4K_C0000,
MSR_IA32_MTRR_FIX4K_C8000,
MSR_IA32_MTRR_FIX4K_D0000,
MSR_IA32_MTRR_FIX4K_D8000,
MSR_IA32_MTRR_FIX4K_E0000,
MSR_IA32_MTRR_FIX4K_E8000,
MSR_IA32_MTRR_FIX4K_F0000,
MSR_IA32_MTRR_FIX4K_F8000
};
STATIC_ASSERT (
(ARRAY_SIZE (mFixedMtrrsIndex) == MTRR_NUMBER_OF_FIXED_MTRR),
"gFixedMtrrIndex does NOT contain all the fixed MTRRs!"
);
//
// Context structure to be used for most of the test cases.
//
typedef struct {
CONST MTRR_LIB_SYSTEM_PARAMETER *SystemParameter;
} MTRR_LIB_TEST_CONTEXT;
//
// Context structure to be used for GetFirmwareVariableMtrrCount() test.
//
typedef struct {
UINT32 NumberOfReservedVariableMtrrs;
CONST MTRR_LIB_SYSTEM_PARAMETER *SystemParameter;
} MTRR_LIB_GET_FIRMWARE_VARIABLE_MTRR_COUNT_CONTEXT;
STATIC CHAR8 *mCacheDescription[] = { "UC", "WC", "N/A", "N/A", "WT", "WP", "WB" };
/**
Compare the actual memory ranges against expected memory ranges and return PASS when they match.
@param ExpectedMemoryRanges Expected memory ranges.
@param ExpectedMemoryRangeCount Count of expected memory ranges.
@param ActualRanges Actual memory ranges.
@param ActualRangeCount Count of actual memory ranges.
@retval UNIT_TEST_PASSED Test passed.
@retval others Test failed.
**/
UNIT_TEST_STATUS
VerifyMemoryRanges (
IN MTRR_MEMORY_RANGE *ExpectedMemoryRanges,
IN UINTN ExpectedMemoryRangeCount,
IN MTRR_MEMORY_RANGE *ActualRanges,
IN UINTN ActualRangeCount
)
{
UINTN Index;
UT_ASSERT_EQUAL (ExpectedMemoryRangeCount, ActualRangeCount);
for (Index = 0; Index < ExpectedMemoryRangeCount; Index++) {
UT_ASSERT_EQUAL (ExpectedMemoryRanges[Index].BaseAddress, ActualRanges[Index].BaseAddress);
UT_ASSERT_EQUAL (ExpectedMemoryRanges[Index].Length, ActualRanges[Index].Length);
UT_ASSERT_EQUAL (ExpectedMemoryRanges[Index].Type, ActualRanges[Index].Type);
}
return UNIT_TEST_PASSED;
}
/**
Dump the memory ranges.
@param Ranges Memory ranges to dump.
@param RangeCount Count of memory ranges.
**/
VOID
DumpMemoryRanges (
MTRR_MEMORY_RANGE *Ranges,
UINTN RangeCount
)
{
UINTN Index;
for (Index = 0; Index < RangeCount; Index++) {
UT_LOG_INFO ("\t{ 0x%016llx, 0x%016llx, %a },\n", Ranges[Index].BaseAddress, Ranges[Index].Length, mCacheDescription[Ranges[Index].Type]);
}
}
/**
**/
/**
Generate random count of MTRRs for each cache type.
@param TotalCount Total MTRR count.
@param UcCount Return count of Uncacheable type.
@param WtCount Return count of Write Through type.
@param WbCount Return count of Write Back type.
@param WpCount Return count of Write Protected type.
@param WcCount Return count of Write Combining type.
**/
VOID
GenerateRandomMemoryTypeCombination (
IN UINT32 TotalCount,
OUT UINT32 *UcCount,
OUT UINT32 *WtCount,
OUT UINT32 *WbCount,
OUT UINT32 *WpCount,
OUT UINT32 *WcCount
)
{
UINTN Index;
UINT32 TotalMtrrCount;
UINT32 *CountPerType[5];
CountPerType[0] = UcCount;
CountPerType[1] = WtCount;
CountPerType[2] = WbCount;
CountPerType[3] = WpCount;
CountPerType[4] = WcCount;
//
// Initialize the count of each cache type to 0.
//
for (Index = 0; Index < ARRAY_SIZE (CountPerType); Index++) {
*(CountPerType[Index]) = 0;
}
//
// Pick a random count of MTRRs
//
TotalMtrrCount = Random32 (1, TotalCount);
for (Index = 0; Index < TotalMtrrCount; Index++) {
//
// For each of them, pick a random cache type.
//
(*(CountPerType[Random32 (0, ARRAY_SIZE (CountPerType) - 1)]))++;
}
}
/**
Unit test of MtrrLib service MtrrGetMemoryAttributesInMtrrSettings() and
MtrrSetMemoryAttributesInMtrrSettings()
@param[in] Context Ignored
@retval UNIT_TEST_PASSED The Unit test has completed and the test
case was successful.
@retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has failed.
**/
UNIT_TEST_STATUS
EFIAPI
UnitTestMtrrSetAndGetMemoryAttributesInMtrrSettings (
IN UNIT_TEST_CONTEXT Context
)
{
CONST MTRR_LIB_SYSTEM_PARAMETER *SystemParameter;
RETURN_STATUS Status;
UINT32 UcCount;
UINT32 WtCount;
UINT32 WbCount;
UINT32 WpCount;
UINT32 WcCount;
UINT32 MtrrIndex;
UINT8 *Scratch;
UINTN ScratchSize;
MTRR_SETTINGS LocalMtrrs;
MTRR_MEMORY_RANGE RawMtrrRange[MTRR_NUMBER_OF_VARIABLE_MTRR];
MTRR_MEMORY_RANGE ExpectedMemoryRanges[MTRR_NUMBER_OF_FIXED_MTRR * sizeof (UINT64) + 2 * MTRR_NUMBER_OF_VARIABLE_MTRR + 1];
UINT32 ExpectedVariableMtrrUsage;
UINTN ExpectedMemoryRangesCount;
MTRR_MEMORY_RANGE ActualMemoryRanges[MTRR_NUMBER_OF_FIXED_MTRR * sizeof (UINT64) + 2 * MTRR_NUMBER_OF_VARIABLE_MTRR + 1];
UINT32 ActualVariableMtrrUsage;
UINTN ActualMemoryRangesCount;
MTRR_MEMORY_RANGE ReturnedMemoryRanges[MTRR_NUMBER_OF_FIXED_MTRR * sizeof (UINT64) + 2 * MTRR_NUMBER_OF_VARIABLE_MTRR + 1];
UINTN ReturnedMemoryRangesCount;
MTRR_SETTINGS *Mtrrs[2];
SystemParameter = (MTRR_LIB_SYSTEM_PARAMETER *)Context;
GenerateRandomMemoryTypeCombination (
SystemParameter->VariableMtrrCount - PatchPcdGet32 (PcdCpuNumberOfReservedVariableMtrrs),
&UcCount,
&WtCount,
&WbCount,
&WpCount,
&WcCount
);
GenerateValidAndConfigurableMtrrPairs (
SystemParameter->PhysicalAddressBits - SystemParameter->MkTmeKeyidBits,
RawMtrrRange,
UcCount,
WtCount,
WbCount,
WpCount,
WcCount
);
ExpectedVariableMtrrUsage = UcCount + WtCount + WbCount + WpCount + WcCount;
ExpectedMemoryRangesCount = ARRAY_SIZE (ExpectedMemoryRanges);
GetEffectiveMemoryRanges (
SystemParameter->DefaultCacheType,
SystemParameter->PhysicalAddressBits - SystemParameter->MkTmeKeyidBits,
RawMtrrRange,
ExpectedVariableMtrrUsage,
ExpectedMemoryRanges,
&ExpectedMemoryRangesCount
);
UT_LOG_INFO (
"Total MTRR [%d]: UC=%d, WT=%d, WB=%d, WP=%d, WC=%d\n",
ExpectedVariableMtrrUsage,
UcCount,
WtCount,
WbCount,
WpCount,
WcCount
);
UT_LOG_INFO ("--- Expected Memory Ranges [%d] ---\n", ExpectedMemoryRangesCount);
DumpMemoryRanges (ExpectedMemoryRanges, ExpectedMemoryRangesCount);
//
// Default cache type is always an INPUT
//
ZeroMem (&LocalMtrrs, sizeof (LocalMtrrs));
LocalMtrrs.MtrrDefType = MtrrGetDefaultMemoryType ();
ScratchSize = SCRATCH_BUFFER_SIZE;
Mtrrs[0] = &LocalMtrrs;
Mtrrs[1] = NULL;
for (MtrrIndex = 0; MtrrIndex < ARRAY_SIZE (Mtrrs); MtrrIndex++) {
Scratch = calloc (ScratchSize, sizeof (UINT8));
Status = MtrrSetMemoryAttributesInMtrrSettings (Mtrrs[MtrrIndex], Scratch, &ScratchSize, ExpectedMemoryRanges, ExpectedMemoryRangesCount);
if (Status == RETURN_BUFFER_TOO_SMALL) {
Scratch = realloc (Scratch, ScratchSize);
Status = MtrrSetMemoryAttributesInMtrrSettings (Mtrrs[MtrrIndex], Scratch, &ScratchSize, ExpectedMemoryRanges, ExpectedMemoryRangesCount);
}
UT_ASSERT_STATUS_EQUAL (Status, RETURN_SUCCESS);
if (Mtrrs[MtrrIndex] == NULL) {
ZeroMem (&LocalMtrrs, sizeof (LocalMtrrs));
MtrrGetAllMtrrs (&LocalMtrrs);
}
ActualMemoryRangesCount = ARRAY_SIZE (ActualMemoryRanges);
CollectTestResult (
SystemParameter->DefaultCacheType,
SystemParameter->PhysicalAddressBits - SystemParameter->MkTmeKeyidBits,
SystemParameter->VariableMtrrCount,
&LocalMtrrs,
ActualMemoryRanges,
&ActualMemoryRangesCount,
&ActualVariableMtrrUsage
);
UT_LOG_INFO ("--- Actual Memory Ranges [%d] ---\n", ActualMemoryRangesCount);
DumpMemoryRanges (ActualMemoryRanges, ActualMemoryRangesCount);
VerifyMemoryRanges (ExpectedMemoryRanges, ExpectedMemoryRangesCount, ActualMemoryRanges, ActualMemoryRangesCount);
UT_ASSERT_TRUE (ExpectedVariableMtrrUsage >= ActualVariableMtrrUsage);
ReturnedMemoryRangesCount = ARRAY_SIZE (ReturnedMemoryRanges);
Status = MtrrGetMemoryAttributesInMtrrSettings (
Mtrrs[MtrrIndex],
ReturnedMemoryRanges,
&ReturnedMemoryRangesCount
);
UT_ASSERT_STATUS_EQUAL (Status, RETURN_SUCCESS);
UT_LOG_INFO ("--- Returned Memory Ranges [%d] ---\n", ReturnedMemoryRangesCount);
DumpMemoryRanges (ReturnedMemoryRanges, ReturnedMemoryRangesCount);
VerifyMemoryRanges (ExpectedMemoryRanges, ExpectedMemoryRangesCount, ReturnedMemoryRanges, ReturnedMemoryRangesCount);
ZeroMem (&LocalMtrrs, sizeof (LocalMtrrs));
}
free (Scratch);
return UNIT_TEST_PASSED;
}
/**
Test routine to check whether invalid base/size can be rejected.
@param Context Pointer to MTRR_LIB_SYSTEM_PARAMETER.
@return Test status.
**/
UNIT_TEST_STATUS
EFIAPI
UnitTestInvalidMemoryLayouts (
IN UNIT_TEST_CONTEXT Context
)
{
CONST MTRR_LIB_SYSTEM_PARAMETER *SystemParameter;
MTRR_MEMORY_RANGE Ranges[MTRR_NUMBER_OF_VARIABLE_MTRR * 2 + 1];
UINTN RangeCount;
UINT64 MaxAddress;
UINT32 Index;
UINT64 BaseAddress;
UINT64 Length;
RETURN_STATUS Status;
UINTN ScratchSize;
SystemParameter = (MTRR_LIB_SYSTEM_PARAMETER *)Context;
RangeCount = Random32 (1, ARRAY_SIZE (Ranges));
MaxAddress = 1ull << (SystemParameter->PhysicalAddressBits - SystemParameter->MkTmeKeyidBits);
for (Index = 0; Index < RangeCount; Index++) {
do {
BaseAddress = Random64 (0, MaxAddress);
Length = Random64 (1, MaxAddress - BaseAddress);
} while (((BaseAddress & 0xFFF) == 0) || ((Length & 0xFFF) == 0));
Ranges[Index].BaseAddress = BaseAddress;
Ranges[Index].Length = Length;
Ranges[Index].Type = GenerateRandomCacheType ();
Status = MtrrSetMemoryAttribute (
Ranges[Index].BaseAddress,
Ranges[Index].Length,
Ranges[Index].Type
);
UT_ASSERT_TRUE (RETURN_ERROR (Status));
}
ScratchSize = 0;
Status = MtrrSetMemoryAttributesInMtrrSettings (NULL, NULL, &ScratchSize, Ranges, RangeCount);
UT_ASSERT_TRUE (RETURN_ERROR (Status));
return UNIT_TEST_PASSED;
}
/**
Unit test of MtrrLib service IsMtrrSupported()
@param[in] Context Ignored
@retval UNIT_TEST_PASSED The Unit test has completed and the test
case was successful.
@retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has failed.
**/
UNIT_TEST_STATUS
EFIAPI
UnitTestIsMtrrSupported (
IN UNIT_TEST_CONTEXT Context
)
{
MTRR_LIB_SYSTEM_PARAMETER SystemParameter;
MTRR_LIB_TEST_CONTEXT *LocalContext;
LocalContext = (MTRR_LIB_TEST_CONTEXT *)Context;
CopyMem (&SystemParameter, LocalContext->SystemParameter, sizeof (SystemParameter));
//
// MTRR capability off in CPUID leaf.
//
SystemParameter.MtrrSupported = FALSE;
InitializeMtrrRegs (&SystemParameter);
UT_ASSERT_FALSE (IsMtrrSupported ());
//
// MTRR capability on in CPUID leaf, but no variable or fixed MTRRs.
//
SystemParameter.MtrrSupported = TRUE;
SystemParameter.VariableMtrrCount = 0;
SystemParameter.FixedMtrrSupported = FALSE;
InitializeMtrrRegs (&SystemParameter);
UT_ASSERT_FALSE (IsMtrrSupported ());
//
// MTRR capability on in CPUID leaf, but no variable MTRRs.
//
SystemParameter.MtrrSupported = TRUE;
SystemParameter.VariableMtrrCount = 0;
SystemParameter.FixedMtrrSupported = TRUE;
InitializeMtrrRegs (&SystemParameter);
UT_ASSERT_TRUE (IsMtrrSupported ());
//
// MTRR capability on in CPUID leaf, but no fixed MTRRs.
//
SystemParameter.MtrrSupported = TRUE;
SystemParameter.VariableMtrrCount = 7;
SystemParameter.FixedMtrrSupported = FALSE;
InitializeMtrrRegs (&SystemParameter);
UT_ASSERT_TRUE (IsMtrrSupported ());
//
// MTRR capability on in CPUID leaf with both variable and fixed MTRRs.
//
SystemParameter.MtrrSupported = TRUE;
SystemParameter.VariableMtrrCount = 7;
SystemParameter.FixedMtrrSupported = TRUE;
InitializeMtrrRegs (&SystemParameter);
UT_ASSERT_TRUE (IsMtrrSupported ());
return UNIT_TEST_PASSED;
}
/**
Unit test of MtrrLib service GetVariableMtrrCount()
@param[in] Context Ignored
@retval UNIT_TEST_PASSED The Unit test has completed and the test
case was successful.
@retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has failed.
**/
UNIT_TEST_STATUS
EFIAPI
UnitTestGetVariableMtrrCount (
IN UNIT_TEST_CONTEXT Context
)
{
UINT32 Result;
MTRR_LIB_SYSTEM_PARAMETER SystemParameter;
MTRR_LIB_TEST_CONTEXT *LocalContext;
LocalContext = (MTRR_LIB_TEST_CONTEXT *)Context;
CopyMem (&SystemParameter, LocalContext->SystemParameter, sizeof (SystemParameter));
//
// If MTRR capability off in CPUID leaf, then the count is always 0.
//
SystemParameter.MtrrSupported = FALSE;
for (SystemParameter.VariableMtrrCount = 1; SystemParameter.VariableMtrrCount <= MTRR_NUMBER_OF_VARIABLE_MTRR; SystemParameter.VariableMtrrCount++) {
InitializeMtrrRegs (&SystemParameter);
Result = GetVariableMtrrCount ();
UT_ASSERT_EQUAL (Result, 0);
}
//
// Try all supported variable MTRR counts.
// If variable MTRR count is > MTRR_NUMBER_OF_VARIABLE_MTRR, then an ASSERT()
// is generated.
//
SystemParameter.MtrrSupported = TRUE;
for (SystemParameter.VariableMtrrCount = 1; SystemParameter.VariableMtrrCount <= MTRR_NUMBER_OF_VARIABLE_MTRR; SystemParameter.VariableMtrrCount++) {
InitializeMtrrRegs (&SystemParameter);
Result = GetVariableMtrrCount ();
UT_ASSERT_EQUAL (Result, SystemParameter.VariableMtrrCount);
}
//
// Expect ASSERT() if variable MTRR count is > MTRR_NUMBER_OF_VARIABLE_MTRR
//
SystemParameter.VariableMtrrCount = MTRR_NUMBER_OF_VARIABLE_MTRR + 1;
InitializeMtrrRegs (&SystemParameter);
UT_EXPECT_ASSERT_FAILURE (GetVariableMtrrCount (), NULL);
SystemParameter.MtrrSupported = TRUE;
SystemParameter.VariableMtrrCount = MAX_UINT8;
InitializeMtrrRegs (&SystemParameter);
UT_EXPECT_ASSERT_FAILURE (GetVariableMtrrCount (), NULL);
return UNIT_TEST_PASSED;
}
/**
Unit test of MtrrLib service GetFirmwareVariableMtrrCount()
@param[in] Context Ignored
@retval UNIT_TEST_PASSED The Unit test has completed and the test
case was successful.
@retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has failed.
**/
UNIT_TEST_STATUS
EFIAPI
UnitTestGetFirmwareVariableMtrrCount (
IN UNIT_TEST_CONTEXT Context
)
{
UINT32 Result;
UINT32 ReservedMtrrs;
MTRR_LIB_SYSTEM_PARAMETER SystemParameter;
MTRR_LIB_GET_FIRMWARE_VARIABLE_MTRR_COUNT_CONTEXT *LocalContext;
LocalContext = (MTRR_LIB_GET_FIRMWARE_VARIABLE_MTRR_COUNT_CONTEXT *)Context;
CopyMem (&SystemParameter, LocalContext->SystemParameter, sizeof (SystemParameter));
InitializeMtrrRegs (&SystemParameter);
//
// Positive test cases for VCNT = 10 and Reserved PCD in range 0..10
//
for (ReservedMtrrs = 0; ReservedMtrrs <= SystemParameter.VariableMtrrCount; ReservedMtrrs++) {
PatchPcdSet32 (PcdCpuNumberOfReservedVariableMtrrs, ReservedMtrrs);
Result = GetFirmwareVariableMtrrCount ();
UT_ASSERT_EQUAL (Result, SystemParameter.VariableMtrrCount - ReservedMtrrs);
}
//
// Negative test cases when Reserved PCD is larger than VCNT
//
for (ReservedMtrrs = SystemParameter.VariableMtrrCount + 1; ReservedMtrrs <= 255; ReservedMtrrs++) {
PatchPcdSet32 (PcdCpuNumberOfReservedVariableMtrrs, ReservedMtrrs);
Result = GetFirmwareVariableMtrrCount ();
UT_ASSERT_EQUAL (Result, 0);
}
//
// Negative test cases when Reserved PCD is larger than VCNT
//
PatchPcdSet32 (PcdCpuNumberOfReservedVariableMtrrs, MAX_UINT32);
Result = GetFirmwareVariableMtrrCount ();
UT_ASSERT_EQUAL (Result, 0);
//
// Negative test case when MTRRs are not supported
//
SystemParameter.MtrrSupported = FALSE;
InitializeMtrrRegs (&SystemParameter);
PatchPcdSet32 (PcdCpuNumberOfReservedVariableMtrrs, 2);
Result = GetFirmwareVariableMtrrCount ();
UT_ASSERT_EQUAL (Result, 0);
//
// Negative test case when Fixed MTRRs are not supported
//
SystemParameter.MtrrSupported = TRUE;
SystemParameter.FixedMtrrSupported = FALSE;
InitializeMtrrRegs (&SystemParameter);
PatchPcdSet32 (PcdCpuNumberOfReservedVariableMtrrs, 2);
Result = GetFirmwareVariableMtrrCount ();
UT_ASSERT_EQUAL (Result, SystemParameter.VariableMtrrCount - 2);
//
// Expect ASSERT() if variable MTRR count is > MTRR_NUMBER_OF_VARIABLE_MTRR
//
SystemParameter.FixedMtrrSupported = TRUE;
SystemParameter.VariableMtrrCount = MTRR_NUMBER_OF_VARIABLE_MTRR + 1;
InitializeMtrrRegs (&SystemParameter);
UT_EXPECT_ASSERT_FAILURE (GetFirmwareVariableMtrrCount (), NULL);
return UNIT_TEST_PASSED;
}
/**
Unit test of MtrrLib service MtrrGetMemoryAttribute()
@param[in] Context Ignored
@retval UNIT_TEST_PASSED The Unit test has completed and the test
case was successful.
@retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has failed.
**/
UNIT_TEST_STATUS
EFIAPI
UnitTestMtrrGetMemoryAttribute (
IN UNIT_TEST_CONTEXT Context
)
{
return UNIT_TEST_PASSED;
}
/**
Unit test of MtrrLib service MtrrGetFixedMtrr()
@param[in] Context Ignored
@retval UNIT_TEST_PASSED The Unit test has completed and the test
case was successful.
@retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has failed.
**/
UNIT_TEST_STATUS
EFIAPI
UnitTestMtrrGetFixedMtrr (
IN UNIT_TEST_CONTEXT Context
)
{
MTRR_FIXED_SETTINGS *Result;
MTRR_FIXED_SETTINGS ExpectedFixedSettings;
MTRR_FIXED_SETTINGS FixedSettings;
UINTN Index;
UINTN MsrIndex;
UINTN ByteIndex;
UINT64 MsrValue;
MTRR_LIB_SYSTEM_PARAMETER SystemParameter;
MTRR_LIB_TEST_CONTEXT *LocalContext;
LocalContext = (MTRR_LIB_TEST_CONTEXT *)Context;
CopyMem (&SystemParameter, LocalContext->SystemParameter, sizeof (SystemParameter));
InitializeMtrrRegs (&SystemParameter);
//
// Set random cache type to different ranges under 1MB and make sure
// the fixed MTRR settings are expected.
// Try 100 times.
//
for (Index = 0; Index < 100; Index++) {
for (MsrIndex = 0; MsrIndex < ARRAY_SIZE (mFixedMtrrsIndex); MsrIndex++) {
MsrValue = 0;
for (ByteIndex = 0; ByteIndex < sizeof (UINT64); ByteIndex++) {
MsrValue = MsrValue | LShiftU64 (GenerateRandomCacheType (), ByteIndex * 8);
}
ExpectedFixedSettings.Mtrr[MsrIndex] = MsrValue;
AsmWriteMsr64 (mFixedMtrrsIndex[MsrIndex], MsrValue);
}
Result = MtrrGetFixedMtrr (&FixedSettings);
UT_ASSERT_EQUAL ((UINTN)Result, (UINTN)&FixedSettings);
UT_ASSERT_MEM_EQUAL (&FixedSettings, &ExpectedFixedSettings, sizeof (FixedSettings));
}
//
// Negative test case when MTRRs are not supported
//
SystemParameter.MtrrSupported = FALSE;
InitializeMtrrRegs (&SystemParameter);
ZeroMem (&FixedSettings, sizeof (FixedSettings));
ZeroMem (&ExpectedFixedSettings, sizeof (ExpectedFixedSettings));
Result = MtrrGetFixedMtrr (&FixedSettings);
UT_ASSERT_EQUAL ((UINTN)Result, (UINTN)&FixedSettings);
UT_ASSERT_MEM_EQUAL (&ExpectedFixedSettings, &FixedSettings, sizeof (ExpectedFixedSettings));
//
// Negative test case when Fixed MTRRs are not supported
//
SystemParameter.MtrrSupported = TRUE;
SystemParameter.FixedMtrrSupported = FALSE;
InitializeMtrrRegs (&SystemParameter);
ZeroMem (&FixedSettings, sizeof (FixedSettings));
ZeroMem (&ExpectedFixedSettings, sizeof (ExpectedFixedSettings));
Result = MtrrGetFixedMtrr (&FixedSettings);
UT_ASSERT_EQUAL ((UINTN)Result, (UINTN)&FixedSettings);
UT_ASSERT_MEM_EQUAL (&ExpectedFixedSettings, &FixedSettings, sizeof (ExpectedFixedSettings));
return UNIT_TEST_PASSED;
}
/**
Set Random Variable and Fixed MTRRs Settings for
unit test of UnitTestMtrrGetAllMtrrs.
@param SystemParameter System parameter that controls the MTRR registers initialization.
@param ExpectedMtrrs Expected Fixed and Variable MTRRs.
**/
VOID
SetRandomlyGeneratedMtrrSettings (
IN MTRR_LIB_SYSTEM_PARAMETER *SystemParameter,
IN MTRR_SETTINGS *ExpectedMtrrs
)
{
UINT32 Index;
UINTN MsrIndex;
UINTN ByteIndex;
UINT64 MsrValue;
MSR_IA32_MTRR_DEF_TYPE_REGISTER Default;
AsmWriteMsr64 (MSR_IA32_MTRR_DEF_TYPE, ExpectedMtrrs->MtrrDefType);
//
// Randomly generate Variable MTRR BASE/MASK for a specified type and write to MSR.
//
for (Index = 0; Index < SystemParameter->VariableMtrrCount; Index++) {
GenerateRandomMtrrPair (SystemParameter->PhysicalAddressBits, GenerateRandomCacheType (), &ExpectedMtrrs->Variables.Mtrr[Index], NULL);
AsmWriteMsr64 (MSR_IA32_MTRR_PHYSBASE0 + (Index << 1), ExpectedMtrrs->Variables.Mtrr[Index].Base);
AsmWriteMsr64 (MSR_IA32_MTRR_PHYSMASK0 + (Index << 1), ExpectedMtrrs->Variables.Mtrr[Index].Mask);
}
//
// Set Fixed MTRRs when the Fixed MTRRs is enabled and the MTRRs is supported.
//
Default.Uint64 = AsmReadMsr64 (MSR_IA32_MTRR_DEF_TYPE);
if ((Default.Bits.FE == 1) && (SystemParameter->MtrrSupported == TRUE)) {
for (MsrIndex = 0; MsrIndex < ARRAY_SIZE (mFixedMtrrsIndex); MsrIndex++) {
MsrValue = 0;
for (ByteIndex = 0; ByteIndex < sizeof (UINT64); ByteIndex++) {
MsrValue = MsrValue | LShiftU64 (GenerateRandomCacheType (), ByteIndex * 8);
}
ExpectedMtrrs->Fixed.Mtrr[MsrIndex] = MsrValue;
AsmWriteMsr64 (mFixedMtrrsIndex[MsrIndex], MsrValue);
}
}
}
/**
Unit test of MtrrLib service MtrrGetAllMtrrs()
@param[in] Context Ignored
@retval UNIT_TEST_PASSED The Unit test has completed and the test
case was successful.
@retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has failed.
**/
UNIT_TEST_STATUS
EFIAPI
UnitTestMtrrGetAllMtrrs (
IN UNIT_TEST_CONTEXT Context
)
{
MTRR_SETTINGS *Result;
MTRR_SETTINGS Mtrrs;
MTRR_SETTINGS ExpectedMtrrs;
MTRR_LIB_SYSTEM_PARAMETER SystemParameter;
MTRR_LIB_TEST_CONTEXT *LocalContext;
MSR_IA32_MTRR_DEF_TYPE_REGISTER Default;
LocalContext = (MTRR_LIB_TEST_CONTEXT *)Context;
CopyMem (&SystemParameter, LocalContext->SystemParameter, sizeof (SystemParameter));
//
// For the case that Fixed MTRRs is NOT enabled
//
SystemParameter.MtrrSupported = TRUE;
SystemParameter.FixedMtrrSupported = FALSE;
InitializeMtrrRegs (&SystemParameter);
Default.Uint64 = 0;
Default.Bits.E = 1;
Default.Bits.FE = 0;
ZeroMem (&ExpectedMtrrs, sizeof (ExpectedMtrrs));
ExpectedMtrrs.MtrrDefType = Default.Uint64;
//
// Randomly generate expected MtrrSettings and set to MSR.
//
SetRandomlyGeneratedMtrrSettings (&SystemParameter, &ExpectedMtrrs);
Result = MtrrGetAllMtrrs (&Mtrrs);
UT_ASSERT_MEM_EQUAL (&ExpectedMtrrs.Fixed, &Mtrrs.Fixed, sizeof (MTRR_FIXED_SETTINGS));
UT_ASSERT_MEM_EQUAL (Mtrrs.Variables.Mtrr, ExpectedMtrrs.Variables.Mtrr, sizeof (MTRR_VARIABLE_SETTING) * (SystemParameter.VariableMtrrCount));
//
// For the case that Fixed MTRRs is enabled
//
SystemParameter.MtrrSupported = TRUE;
SystemParameter.FixedMtrrSupported = TRUE;
InitializeMtrrRegs (&SystemParameter);
Default.Uint64 = 0;
Default.Bits.E = 1;
Default.Bits.FE = 1;
ZeroMem (&ExpectedMtrrs, sizeof (ExpectedMtrrs));
ExpectedMtrrs.MtrrDefType = Default.Uint64;
SetRandomlyGeneratedMtrrSettings (&SystemParameter, &ExpectedMtrrs);
Result = MtrrGetAllMtrrs (&Mtrrs);
UT_ASSERT_MEM_EQUAL (&ExpectedMtrrs.Fixed, &Mtrrs.Fixed, sizeof (MTRR_FIXED_SETTINGS));
UT_ASSERT_MEM_EQUAL (Mtrrs.Variables.Mtrr, ExpectedMtrrs.Variables.Mtrr, sizeof (MTRR_VARIABLE_SETTING) * (SystemParameter.VariableMtrrCount));
//
// Negative test case when MTRRs are not supported
//
ZeroMem (&ExpectedMtrrs, sizeof (ExpectedMtrrs));
ZeroMem (&Mtrrs, sizeof (Mtrrs));
SystemParameter.MtrrSupported = FALSE;
InitializeMtrrRegs (&SystemParameter);
Result = MtrrGetAllMtrrs (&Mtrrs);
UT_ASSERT_EQUAL ((UINTN)Result, (UINTN)&Mtrrs);
UT_ASSERT_MEM_EQUAL (&ExpectedMtrrs, &Mtrrs, sizeof (ExpectedMtrrs));
//
// Expect ASSERT() if variable MTRR count is > MTRR_NUMBER_OF_VARIABLE_MTRR
//
SystemParameter.MtrrSupported = TRUE;
SystemParameter.VariableMtrrCount = MTRR_NUMBER_OF_VARIABLE_MTRR + 1;
InitializeMtrrRegs (&SystemParameter);
UT_EXPECT_ASSERT_FAILURE (MtrrGetAllMtrrs (&Mtrrs), NULL);
return UNIT_TEST_PASSED;
}
/**
Unit test of MtrrLib service MtrrSetAllMtrrs()
@param[in] Context Ignored
@retval UNIT_TEST_PASSED The Unit test has completed and the test
case was successful.
@retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has failed.
**/
UNIT_TEST_STATUS
EFIAPI
UnitTestMtrrSetAllMtrrs (
IN UNIT_TEST_CONTEXT Context
)
{
MTRR_SETTINGS *Result;
MTRR_SETTINGS ExpectedMtrrs;
UINT32 Index;
MSR_IA32_MTRR_DEF_TYPE_REGISTER Default;
MTRR_LIB_SYSTEM_PARAMETER SystemParameter;
MTRR_LIB_TEST_CONTEXT *LocalContext;
UINTN MsrIndex;
UINTN ByteIndex;
UINT64 MsrValue;
LocalContext = (MTRR_LIB_TEST_CONTEXT *)Context;
CopyMem (&SystemParameter, LocalContext->SystemParameter, sizeof (SystemParameter));
InitializeMtrrRegs (&SystemParameter);
Default.Uint64 = 0;
Default.Bits.E = 1;
Default.Bits.FE = 1;
Default.Bits.Type = GenerateRandomCacheType ();
ZeroMem (&ExpectedMtrrs, sizeof (ExpectedMtrrs));
ExpectedMtrrs.MtrrDefType = Default.Uint64;
for (Index = 0; Index < SystemParameter.VariableMtrrCount; Index++) {
GenerateRandomMtrrPair (SystemParameter.PhysicalAddressBits, GenerateRandomCacheType (), &ExpectedMtrrs.Variables.Mtrr[Index], NULL);
}
for (MsrIndex = 0; MsrIndex < ARRAY_SIZE (mFixedMtrrsIndex); MsrIndex++) {
MsrValue = 0;
for (ByteIndex = 0; ByteIndex < sizeof (UINT64); ByteIndex++) {
MsrValue = MsrValue | LShiftU64 (GenerateRandomCacheType (), ByteIndex * 8);
}
ExpectedMtrrs.Fixed.Mtrr[MsrIndex] = MsrValue;
}
Result = MtrrSetAllMtrrs (&ExpectedMtrrs);
UT_ASSERT_EQUAL ((UINTN)Result, (UINTN)&ExpectedMtrrs);
UT_ASSERT_EQUAL (AsmReadMsr64 (MSR_IA32_MTRR_DEF_TYPE), ExpectedMtrrs.MtrrDefType);
for (Index = 0; Index < SystemParameter.VariableMtrrCount; Index++) {
UT_ASSERT_EQUAL (AsmReadMsr64 (MSR_IA32_MTRR_PHYSBASE0 + (Index << 1)), ExpectedMtrrs.Variables.Mtrr[Index].Base);
UT_ASSERT_EQUAL (AsmReadMsr64 (MSR_IA32_MTRR_PHYSMASK0 + (Index << 1)), ExpectedMtrrs.Variables.Mtrr[Index].Mask);
}
return UNIT_TEST_PASSED;
}
/**
Unit test of MtrrLib service MtrrGetMemoryAttributeInVariableMtrr()
@param[in] Context Ignored
@retval UNIT_TEST_PASSED The Unit test has completed and the test
case was successful.
@retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has failed.
**/
UNIT_TEST_STATUS
EFIAPI
UnitTestMtrrGetMemoryAttributeInVariableMtrr (
IN UNIT_TEST_CONTEXT Context
)
{
MTRR_LIB_TEST_CONTEXT *LocalContext;
MTRR_LIB_SYSTEM_PARAMETER SystemParameter;
UINT32 Result;
MTRR_VARIABLE_SETTING VariableSetting[MTRR_NUMBER_OF_VARIABLE_MTRR];
VARIABLE_MTRR VariableMtrr[MTRR_NUMBER_OF_VARIABLE_MTRR];
UINT64 ValidMtrrBitsMask;
UINT64 ValidMtrrAddressMask;
UINT32 Index;
MSR_IA32_MTRR_PHYSBASE_REGISTER Base;
MSR_IA32_MTRR_PHYSMASK_REGISTER Mask;
LocalContext = (MTRR_LIB_TEST_CONTEXT *)Context;
CopyMem (&SystemParameter, LocalContext->SystemParameter, sizeof (SystemParameter));
InitializeMtrrRegs (&SystemParameter);
ValidMtrrBitsMask = (1ull << SystemParameter.PhysicalAddressBits) - 1;
ValidMtrrAddressMask = ValidMtrrBitsMask & 0xfffffffffffff000ULL;
for (Index = 0; Index < SystemParameter.VariableMtrrCount; Index++) {
GenerateRandomMtrrPair (SystemParameter.PhysicalAddressBits, GenerateRandomCacheType (), &VariableSetting[Index], NULL);
AsmWriteMsr64 (MSR_IA32_MTRR_PHYSBASE0 + (Index << 1), VariableSetting[Index].Base);
AsmWriteMsr64 (MSR_IA32_MTRR_PHYSMASK0 + (Index << 1), VariableSetting[Index].Mask);
}
Result = MtrrGetMemoryAttributeInVariableMtrr (ValidMtrrBitsMask, ValidMtrrAddressMask, VariableMtrr);
UT_ASSERT_EQUAL (Result, SystemParameter.VariableMtrrCount);
for (Index = 0; Index < SystemParameter.VariableMtrrCount; Index++) {
Base.Uint64 = VariableMtrr[Index].BaseAddress;
Base.Bits.Type = (UINT32)VariableMtrr[Index].Type;
UT_ASSERT_EQUAL (Base.Uint64, VariableSetting[Index].Base);
Mask.Uint64 = ~(VariableMtrr[Index].Length - 1) & ValidMtrrBitsMask;
Mask.Bits.V = 1;
UT_ASSERT_EQUAL (Mask.Uint64, VariableSetting[Index].Mask);
}
//
// Negative test case when MTRRs are not supported
//
SystemParameter.MtrrSupported = FALSE;
InitializeMtrrRegs (&SystemParameter);
Result = MtrrGetMemoryAttributeInVariableMtrr (ValidMtrrBitsMask, ValidMtrrAddressMask, VariableMtrr);
UT_ASSERT_EQUAL (Result, 0);
//
// Expect ASSERT() if variable MTRR count is > MTRR_NUMBER_OF_VARIABLE_MTRR
//
SystemParameter.MtrrSupported = TRUE;
SystemParameter.VariableMtrrCount = MTRR_NUMBER_OF_VARIABLE_MTRR + 1;
InitializeMtrrRegs (&SystemParameter);
UT_EXPECT_ASSERT_FAILURE (MtrrGetMemoryAttributeInVariableMtrr (ValidMtrrBitsMask, ValidMtrrAddressMask, VariableMtrr), NULL);
return UNIT_TEST_PASSED;
}
/**
Unit test of MtrrLib service MtrrDebugPrintAllMtrrs()
@param[in] Context Ignored
@retval UNIT_TEST_PASSED The Unit test has completed and the test
case was successful.
@retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has failed.
**/
UNIT_TEST_STATUS
EFIAPI
UnitTestMtrrDebugPrintAllMtrrs (
IN UNIT_TEST_CONTEXT Context
)
{
return UNIT_TEST_PASSED;
}
/**
Unit test of MtrrLib service MtrrGetDefaultMemoryType().
@param[in] Context Ignored
@retval UNIT_TEST_PASSED The Unit test has completed and the test
case was successful.
@retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has failed.
**/
UNIT_TEST_STATUS
EFIAPI
UnitTestMtrrGetDefaultMemoryType (
IN UNIT_TEST_CONTEXT Context
)
{
MTRR_LIB_TEST_CONTEXT *LocalContext;
UINTN Index;
MTRR_MEMORY_CACHE_TYPE Result;
MTRR_LIB_SYSTEM_PARAMETER SystemParameter;
MTRR_MEMORY_CACHE_TYPE CacheType[5];
CacheType[0] = CacheUncacheable;
CacheType[1] = CacheWriteCombining;
CacheType[2] = CacheWriteThrough;
CacheType[3] = CacheWriteProtected;
CacheType[4] = CacheWriteBack;
LocalContext = (MTRR_LIB_TEST_CONTEXT *)Context;
CopyMem (&SystemParameter, LocalContext->SystemParameter, sizeof (SystemParameter));
//
// If MTRRs are supported, then always return the cache type in the MSR
// MSR_IA32_MTRR_DEF_TYPE
//
for (Index = 0; Index < ARRAY_SIZE (CacheType); Index++) {
SystemParameter.DefaultCacheType = CacheType[Index];
InitializeMtrrRegs (&SystemParameter);
Result = MtrrGetDefaultMemoryType ();
UT_ASSERT_EQUAL (Result, SystemParameter.DefaultCacheType);
}
//
// If MTRRs are not supported, then always return CacheUncacheable
//
SystemParameter.MtrrSupported = FALSE;
InitializeMtrrRegs (&SystemParameter);
Result = MtrrGetDefaultMemoryType ();
UT_ASSERT_EQUAL (Result, CacheUncacheable);
//
// If MTRRs are supported, but Fixed MTRRs are not supported.
//
SystemParameter.MtrrSupported = TRUE;
SystemParameter.FixedMtrrSupported = FALSE;
InitializeMtrrRegs (&SystemParameter);
Result = MtrrGetDefaultMemoryType ();
UT_ASSERT_EQUAL (Result, SystemParameter.DefaultCacheType);
//
// If MTRRs are supported, but Variable MTRRs are not supported.
//
SystemParameter.MtrrSupported = TRUE;
SystemParameter.FixedMtrrSupported = TRUE;
SystemParameter.VariableMtrrCount = 0;
InitializeMtrrRegs (&SystemParameter);
Result = MtrrGetDefaultMemoryType ();
UT_ASSERT_EQUAL (Result, SystemParameter.DefaultCacheType);
return UNIT_TEST_PASSED;
}
/**
Unit test of MtrrLib service MtrrSetMemoryAttributeInMtrrSettings() and
MtrrGetMemoryAttributesInMtrrSettings().
@param[in] Context Ignored
@retval UNIT_TEST_PASSED The Unit test has completed and the test
case was successful.
@retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has failed.
**/
UNIT_TEST_STATUS
EFIAPI
UnitTestMtrrSetMemoryAttributeAndGetMemoryAttributesInMtrrSettings (
IN UNIT_TEST_CONTEXT Context
)
{
CONST MTRR_LIB_SYSTEM_PARAMETER *SystemParameter;
RETURN_STATUS Status;
UINT32 UcCount;
UINT32 WtCount;
UINT32 WbCount;
UINT32 WpCount;
UINT32 WcCount;
UINTN MtrrIndex;
UINTN Index;
MTRR_SETTINGS LocalMtrrs;
MTRR_MEMORY_RANGE RawMtrrRange[MTRR_NUMBER_OF_VARIABLE_MTRR];
MTRR_MEMORY_RANGE ExpectedMemoryRanges[MTRR_NUMBER_OF_FIXED_MTRR * sizeof (UINT64) + 2 * MTRR_NUMBER_OF_VARIABLE_MTRR + 1];
UINT32 ExpectedVariableMtrrUsage;
UINTN ExpectedMemoryRangesCount;
MTRR_MEMORY_RANGE ActualMemoryRanges[MTRR_NUMBER_OF_FIXED_MTRR * sizeof (UINT64) + 2 * MTRR_NUMBER_OF_VARIABLE_MTRR + 1];
UINT32 ActualVariableMtrrUsage;
UINTN ActualMemoryRangesCount;
MTRR_MEMORY_RANGE ReturnedMemoryRanges[MTRR_NUMBER_OF_FIXED_MTRR * sizeof (UINT64) + 2 * MTRR_NUMBER_OF_VARIABLE_MTRR + 1];
UINTN ReturnedMemoryRangesCount;
MTRR_SETTINGS *Mtrrs[2];
SystemParameter = (MTRR_LIB_SYSTEM_PARAMETER *)Context;
GenerateRandomMemoryTypeCombination (
SystemParameter->VariableMtrrCount - PatchPcdGet32 (PcdCpuNumberOfReservedVariableMtrrs),
&UcCount,
&WtCount,
&WbCount,
&WpCount,
&WcCount
);
GenerateValidAndConfigurableMtrrPairs (
SystemParameter->PhysicalAddressBits - SystemParameter->MkTmeKeyidBits,
RawMtrrRange,
UcCount,
WtCount,
WbCount,
WpCount,
WcCount
);
ExpectedVariableMtrrUsage = UcCount + WtCount + WbCount + WpCount + WcCount;
ExpectedMemoryRangesCount = ARRAY_SIZE (ExpectedMemoryRanges);
GetEffectiveMemoryRanges (
SystemParameter->DefaultCacheType,
SystemParameter->PhysicalAddressBits - SystemParameter->MkTmeKeyidBits,
RawMtrrRange,
ExpectedVariableMtrrUsage,
ExpectedMemoryRanges,
&ExpectedMemoryRangesCount
);
UT_LOG_INFO ("--- Expected Memory Ranges [%d] ---\n", ExpectedMemoryRangesCount);
DumpMemoryRanges (ExpectedMemoryRanges, ExpectedMemoryRangesCount);
//
// Default cache type is always an INPUT
//
ZeroMem (&LocalMtrrs, sizeof (LocalMtrrs));
LocalMtrrs.MtrrDefType = MtrrGetDefaultMemoryType ();
Mtrrs[0] = &LocalMtrrs;
Mtrrs[1] = NULL;
for (MtrrIndex = 0; MtrrIndex < ARRAY_SIZE (Mtrrs); MtrrIndex++) {
for (Index = 0; Index < ExpectedMemoryRangesCount; Index++) {
Status = MtrrSetMemoryAttributeInMtrrSettings (
Mtrrs[MtrrIndex],
ExpectedMemoryRanges[Index].BaseAddress,
ExpectedMemoryRanges[Index].Length,
ExpectedMemoryRanges[Index].Type
);
UT_ASSERT_TRUE (Status == RETURN_SUCCESS || Status == RETURN_OUT_OF_RESOURCES || Status == RETURN_BUFFER_TOO_SMALL);
if ((Status == RETURN_OUT_OF_RESOURCES) || (Status == RETURN_BUFFER_TOO_SMALL)) {
return UNIT_TEST_SKIPPED;
}
}
if (Mtrrs[MtrrIndex] == NULL) {
ZeroMem (&LocalMtrrs, sizeof (LocalMtrrs));
MtrrGetAllMtrrs (&LocalMtrrs);
}
ActualMemoryRangesCount = ARRAY_SIZE (ActualMemoryRanges);
CollectTestResult (
SystemParameter->DefaultCacheType,
SystemParameter->PhysicalAddressBits - SystemParameter->MkTmeKeyidBits,
SystemParameter->VariableMtrrCount,
&LocalMtrrs,
ActualMemoryRanges,
&ActualMemoryRangesCount,
&ActualVariableMtrrUsage
);
UT_LOG_INFO ("--- Actual Memory Ranges [%d] ---\n", ActualMemoryRangesCount);
DumpMemoryRanges (ActualMemoryRanges, ActualMemoryRangesCount);
VerifyMemoryRanges (ExpectedMemoryRanges, ExpectedMemoryRangesCount, ActualMemoryRanges, ActualMemoryRangesCount);
UT_ASSERT_TRUE (ExpectedVariableMtrrUsage >= ActualVariableMtrrUsage);
ReturnedMemoryRangesCount = ARRAY_SIZE (ReturnedMemoryRanges);
Status = MtrrGetMemoryAttributesInMtrrSettings (
&LocalMtrrs,
ReturnedMemoryRanges,
&ReturnedMemoryRangesCount
);
UT_ASSERT_STATUS_EQUAL (Status, RETURN_SUCCESS);
UT_LOG_INFO ("--- Returned Memory Ranges [%d] ---\n", ReturnedMemoryRangesCount);
DumpMemoryRanges (ReturnedMemoryRanges, ReturnedMemoryRangesCount);
VerifyMemoryRanges (ExpectedMemoryRanges, ExpectedMemoryRangesCount, ReturnedMemoryRanges, ReturnedMemoryRangesCount);
ZeroMem (&LocalMtrrs, sizeof (LocalMtrrs));
}
return UNIT_TEST_PASSED;
}
/**
Prep routine for UnitTestGetFirmwareVariableMtrrCount().
@param Context Point to a UINT32 data to save the PcdCpuNumberOfReservedVariableMtrrs.
**/
UNIT_TEST_STATUS
EFIAPI
SavePcdValue (
UNIT_TEST_CONTEXT Context
)
{
MTRR_LIB_GET_FIRMWARE_VARIABLE_MTRR_COUNT_CONTEXT *LocalContext;
LocalContext = (MTRR_LIB_GET_FIRMWARE_VARIABLE_MTRR_COUNT_CONTEXT *)Context;
LocalContext->NumberOfReservedVariableMtrrs = PatchPcdGet32 (PcdCpuNumberOfReservedVariableMtrrs);
return UNIT_TEST_PASSED;
}
/**
Clean up routine for UnitTestGetFirmwareVariableMtrrCount().
@param Context Point to a UINT32 data to save the PcdCpuNumberOfReservedVariableMtrrs.
**/
VOID
EFIAPI
RestorePcdValue (
UNIT_TEST_CONTEXT Context
)
{
MTRR_LIB_GET_FIRMWARE_VARIABLE_MTRR_COUNT_CONTEXT *LocalContext;
LocalContext = (MTRR_LIB_GET_FIRMWARE_VARIABLE_MTRR_COUNT_CONTEXT *)Context;
PatchPcdSet32 (PcdCpuNumberOfReservedVariableMtrrs, LocalContext->NumberOfReservedVariableMtrrs);
}
/**
Initialize the unit test framework, suite, and unit tests for the
ResetSystemLib and run the ResetSystemLib unit test.
@param Iteration Iteration of testing MtrrSetMemoryAttributeInMtrrSettings
and MtrrSetMemoryAttributesInMtrrSettings using random inputs.
@retval EFI_SUCCESS All test cases were dispatched.
@retval EFI_OUT_OF_RESOURCES There are not enough resources available to
initialize the unit tests.
**/
STATIC
EFI_STATUS
EFIAPI
UnitTestingEntry (
UINTN Iteration
)
{
EFI_STATUS Status;
UNIT_TEST_FRAMEWORK_HANDLE Framework;
UNIT_TEST_SUITE_HANDLE MtrrApiTests;
UINTN Index;
UINTN SystemIndex;
MTRR_LIB_TEST_CONTEXT Context;
MTRR_LIB_GET_FIRMWARE_VARIABLE_MTRR_COUNT_CONTEXT GetFirmwareVariableMtrrCountContext;
Context.SystemParameter = &mDefaultSystemParameter;
GetFirmwareVariableMtrrCountContext.SystemParameter = &mDefaultSystemParameter;
Framework = NULL;
//
// Setup the test framework for running the tests.
//
Status = InitUnitTestFramework (&Framework, UNIT_TEST_APP_NAME, gEfiCallerBaseName, UNIT_TEST_APP_VERSION);
if (EFI_ERROR (Status)) {
DEBUG ((DEBUG_ERROR, "Failed in InitUnitTestFramework. Status = %r\n", Status));
goto EXIT;
}
//
// --------------Suite-----------Description--------------Name----------Function--------Pre---Post-------------------Context-----------
//
//
// Populate the MtrrLib API Unit Test Suite.
//
Status = CreateUnitTestSuite (&MtrrApiTests, Framework, "MtrrLib API Tests", "MtrrLib.MtrrLib", NULL, NULL);
if (EFI_ERROR (Status)) {
DEBUG ((DEBUG_ERROR, "Failed in CreateUnitTestSuite for MtrrLib API Tests\n"));
Status = EFI_OUT_OF_RESOURCES;
goto EXIT;
}
AddTestCase (MtrrApiTests, "Test IsMtrrSupported", "MtrrSupported", UnitTestIsMtrrSupported, NULL, NULL, &Context);
AddTestCase (MtrrApiTests, "Test GetVariableMtrrCount", "GetVariableMtrrCount", UnitTestGetVariableMtrrCount, NULL, NULL, &Context);
AddTestCase (MtrrApiTests, "Test GetFirmwareVariableMtrrCount", "GetFirmwareVariableMtrrCount", UnitTestGetFirmwareVariableMtrrCount, SavePcdValue, RestorePcdValue, &GetFirmwareVariableMtrrCountContext);
AddTestCase (MtrrApiTests, "Test MtrrGetMemoryAttribute", "MtrrGetMemoryAttribute", UnitTestMtrrGetMemoryAttribute, NULL, NULL, &Context);
AddTestCase (MtrrApiTests, "Test MtrrGetFixedMtrr", "MtrrGetFixedMtrr", UnitTestMtrrGetFixedMtrr, NULL, NULL, &Context);
AddTestCase (MtrrApiTests, "Test MtrrGetAllMtrrs", "MtrrGetAllMtrrs", UnitTestMtrrGetAllMtrrs, NULL, NULL, &Context);
AddTestCase (MtrrApiTests, "Test MtrrSetAllMtrrs", "MtrrSetAllMtrrs", UnitTestMtrrSetAllMtrrs, NULL, NULL, &Context);
AddTestCase (MtrrApiTests, "Test MtrrGetMemoryAttributeInVariableMtrr", "MtrrGetMemoryAttributeInVariableMtrr", UnitTestMtrrGetMemoryAttributeInVariableMtrr, NULL, NULL, &Context);
AddTestCase (MtrrApiTests, "Test MtrrDebugPrintAllMtrrs", "MtrrDebugPrintAllMtrrs", UnitTestMtrrDebugPrintAllMtrrs, NULL, NULL, &Context);
AddTestCase (MtrrApiTests, "Test MtrrGetDefaultMemoryType", "MtrrGetDefaultMemoryType", UnitTestMtrrGetDefaultMemoryType, NULL, NULL, &Context);
for (SystemIndex = 0; SystemIndex < ARRAY_SIZE (mSystemParameters); SystemIndex++) {
for (Index = 0; Index < Iteration; Index++) {
AddTestCase (MtrrApiTests, "Test InvalidMemoryLayouts", "InvalidMemoryLayouts", UnitTestInvalidMemoryLayouts, InitializeSystem, NULL, &mSystemParameters[SystemIndex]);
AddTestCase (MtrrApiTests, "Test MtrrSetMemoryAttributeInMtrrSettings and MtrrGetMemoryAttributesInMtrrSettings", "MtrrSetMemoryAttributeInMtrrSettings and MtrrGetMemoryAttributesInMtrrSettings", UnitTestMtrrSetMemoryAttributeAndGetMemoryAttributesInMtrrSettings, InitializeSystem, NULL, &mSystemParameters[SystemIndex]);
AddTestCase (MtrrApiTests, "Test MtrrSetMemoryAttributesInMtrrSettings and MtrrGetMemoryAttributesInMtrrSettings", "MtrrSetMemoryAttributesInMtrrSettings and MtrrGetMemoryAttributesInMtrrSetting", UnitTestMtrrSetAndGetMemoryAttributesInMtrrSettings, InitializeSystem, NULL, &mSystemParameters[SystemIndex]);
}
}
//
// Execute the tests.
//
Status = RunAllTestSuites (Framework);
EXIT:
if (Framework != NULL) {
FreeUnitTestFramework (Framework);
}
return Status;
}
/**
Standard POSIX C entry point for host based unit test execution.
@param Argc Number of arguments.
@param Argv Array of arguments.
@return Test application exit code.
**/
INT32
main (
INT32 Argc,
CHAR8 *Argv[]
)
{
UINTN Count;
DEBUG ((DEBUG_INFO, "%a v%a\n", UNIT_TEST_APP_NAME, UNIT_TEST_APP_VERSION));
srand ((unsigned int)time (NULL));
//
// MtrrLibUnitTest generate-random-numbers
//
if ((Argc == 4) && (AsciiStriCmp ("generate-random-numbers", Argv[1]) == 0)) {
Count = atoi (Argv[3]);
DEBUG ((DEBUG_INFO, "Generate %d random numbers to %a.\n", Count, Argv[2]));
GenerateRandomNumbers (Argv[2], Count);
return 0;
}
//
// MtrrLibUnitTest []
// [fixed|random]
// Default is 10.
// Default uses fixed inputs.
//
Count = 10;
mRandomInput = FALSE;
if ((Argc == 2) || (Argc == 3)) {
Count = atoi (Argv[1]);
if (Argc == 3) {
if (AsciiStriCmp ("fixed", Argv[2]) == 0) {
mRandomInput = FALSE;
} else if (AsciiStriCmp ("random", Argv[2]) == 0) {
mRandomInput = TRUE;
}
}
}
DEBUG ((DEBUG_INFO, "Iterations = %d\n", Count));
DEBUG ((DEBUG_INFO, "Input = %a\n", mRandomInput ? "random" : "fixed"));
return UnitTestingEntry (Count);
}