/** @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); }