* Re: [PATCH v2] UefiCpuPkg/MtrrLib/UnitTest: Add host based unit test
2020-07-24 6:41 [PATCH v2] UefiCpuPkg/MtrrLib/UnitTest: Add host based unit test Ni, Ray
@ 2020-07-24 16:04 ` Laszlo Ersek
2020-07-24 16:23 ` Michael D Kinney
2020-07-27 2:58 ` Dong, Eric
2 siblings, 0 replies; 4+ messages in thread
From: Laszlo Ersek @ 2020-07-24 16:04 UTC (permalink / raw)
To: Ray Ni, devel
Cc: Michael D Kinney, Ming Shao, Eric Dong, Sean Brogan,
Bret Barkelew, Jiewen Yao
On 07/24/20 08:41, Ray Ni wrote:
> Add host based unit tests for the MtrrLib services.
> The BaseLib services AsmCpuid(), AsmReadMsr64(), and
> AsmWriteMsr64() are hooked and provide simple emulation
> of the CPUID leafs and MSRs required by the MtrrLib to
> run as a host based unit test.
>
> Test cases are developed for each of the API.
>
> For the most important APIs MtrrSetMemoryAttributesInMtrrSettings()
> and MtrrSetMemoryAttributeInMtrrSettings(), random inputs are
> generated and fed to the APIs to make sure the implementation is
> good. The test application accepts an optional parameter which
> specifies how many iterations of feeding random inputs to the two
> APIs. The overall number of test cases increases when the iteration
> increases. Default iteration is 10 when no parameter is specified.
>
> Signed-off-by: Ray Ni <ray.ni@intel.com>
> Signed-off-by: Michael D Kinney <michael.d.kinney@intel.com>
> Signed-off-by: Ming Shao <ming.shao@intel.com>
> Cc: Michael D Kinney <michael.d.kinney@intel.com>
> Cc: Ming Shao <ming.shao@intel.com>
> Cc: Eric Dong <eric.dong@intel.com>
> Cc: Ray Ni <ray.ni@intel.com>
> Cc: Laszlo Ersek <lersek@redhat.com>
> Cc: Sean Brogan <sean.brogan@microsoft.com>
> Cc: Bret Barkelew <Bret.Barkelew@microsoft.com>
> Cc: Jiewen Yao <jiewen.yao@intel.com>
> ---
> .../MtrrLib/UnitTest/MtrrLibUnitTest.c | 1140 +++++++++++++++++
> .../MtrrLib/UnitTest/MtrrLibUnitTest.h | 171 +++
> .../MtrrLib/UnitTest/MtrrLibUnitTestHost.inf | 39 +
> UefiCpuPkg/Library/MtrrLib/UnitTest/Support.c | 913 +++++++++++++
> UefiCpuPkg/Test/UefiCpuPkgHostTest.dsc | 31 +
> 5 files changed, 2294 insertions(+)
> create mode 100644 UefiCpuPkg/Library/MtrrLib/UnitTest/MtrrLibUnitTest.c
> create mode 100644 UefiCpuPkg/Library/MtrrLib/UnitTest/MtrrLibUnitTest.h
> create mode 100644 UefiCpuPkg/Library/MtrrLib/UnitTest/MtrrLibUnitTestHost.inf
> create mode 100644 UefiCpuPkg/Library/MtrrLib/UnitTest/Support.c
> create mode 100644 UefiCpuPkg/Test/UefiCpuPkgHostTest.dsc
Acked-by: Laszlo Ersek <lersek@redhat.com>
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH v2] UefiCpuPkg/MtrrLib/UnitTest: Add host based unit test
2020-07-24 6:41 [PATCH v2] UefiCpuPkg/MtrrLib/UnitTest: Add host based unit test Ni, Ray
2020-07-24 16:04 ` Laszlo Ersek
@ 2020-07-24 16:23 ` Michael D Kinney
2020-07-27 2:58 ` Dong, Eric
2 siblings, 0 replies; 4+ messages in thread
From: Michael D Kinney @ 2020-07-24 16:23 UTC (permalink / raw)
To: Ni, Ray, devel@edk2.groups.io, Kinney, Michael D
Cc: Shao, Ming, Dong, Eric, Laszlo Ersek, Sean Brogan, Bret Barkelew,
Yao, Jiewen
Reviewed-by: Michael D Kinney <michael.d.kinney@intel.com>
> -----Original Message-----
> From: Ni, Ray <ray.ni@intel.com>
> Sent: Thursday, July 23, 2020 11:42 PM
> To: devel@edk2.groups.io
> Cc: Kinney, Michael D <michael.d.kinney@intel.com>;
> Shao, Ming <ming.shao@intel.com>; Dong, Eric
> <eric.dong@intel.com>; Laszlo Ersek
> <lersek@redhat.com>; Sean Brogan
> <sean.brogan@microsoft.com>; Bret Barkelew
> <Bret.Barkelew@microsoft.com>; Yao, Jiewen
> <jiewen.yao@intel.com>
> Subject: [PATCH v2] UefiCpuPkg/MtrrLib/UnitTest: Add
> host based unit test
>
> Add host based unit tests for the MtrrLib services.
> The BaseLib services AsmCpuid(), AsmReadMsr64(), and
> AsmWriteMsr64() are hooked and provide simple emulation
> of the CPUID leafs and MSRs required by the MtrrLib to
> run as a host based unit test.
>
> Test cases are developed for each of the API.
>
> For the most important APIs
> MtrrSetMemoryAttributesInMtrrSettings()
> and MtrrSetMemoryAttributeInMtrrSettings(), random
> inputs are
> generated and fed to the APIs to make sure the
> implementation is
> good. The test application accepts an optional
> parameter which
> specifies how many iterations of feeding random inputs
> to the two
> APIs. The overall number of test cases increases when
> the iteration
> increases. Default iteration is 10 when no parameter is
> specified.
>
> Signed-off-by: Ray Ni <ray.ni@intel.com>
> Signed-off-by: Michael D Kinney
> <michael.d.kinney@intel.com>
> Signed-off-by: Ming Shao <ming.shao@intel.com>++
> Cc: Michael D Kinney <michael.d.kinney@intel.com>
> Cc: Ming Shao <ming.shao@intel.com>
> Cc: Eric Dong <eric.dong@intel.com>
> Cc: Ray Ni <ray.ni@intel.com>
> Cc: Laszlo Ersek <lersek@redhat.com>
> Cc: Sean Brogan <sean.brogan@microsoft.com>
> Cc: Bret Barkelew <Bret.Barkelew@microsoft.com>
> Cc: Jiewen Yao <jiewen.yao@intel.com>
> ---
> .../MtrrLib/UnitTest/MtrrLibUnitTest.c | 1140
> +++++++++++++++++
> .../MtrrLib/UnitTest/MtrrLibUnitTest.h | 171
> +++
> .../MtrrLib/UnitTest/MtrrLibUnitTestHost.inf | 39 +
> UefiCpuPkg/Library/MtrrLib/UnitTest/Support.c | 913
> +++++++++++++
> UefiCpuPkg/Test/UefiCpuPkgHostTest.dsc | 31 +
> 5 files changed, 2294 insertions(+)
> create mode 100644
> UefiCpuPkg/Library/MtrrLib/UnitTest/MtrrLibUnitTest.c
> create mode 100644
> UefiCpuPkg/Library/MtrrLib/UnitTest/MtrrLibUnitTest.h
> create mode 100644
> UefiCpuPkg/Library/MtrrLib/UnitTest/MtrrLibUnitTestHost
> .inf
> create mode 100644
> UefiCpuPkg/Library/MtrrLib/UnitTest/Support.c
> create mode 100644
> UefiCpuPkg/Test/UefiCpuPkgHostTest.dsc
>
> diff --git
> a/UefiCpuPkg/Library/MtrrLib/UnitTest/MtrrLibUnitTest.c
> b/UefiCpuPkg/Library/MtrrLib/UnitTest/MtrrLibUnitTest.c
> new file mode 100644
> index 0000000000..2eac41fc74
> --- /dev/null
> +++
> b/UefiCpuPkg/Library/MtrrLib/UnitTest/MtrrLibUnitTest.c
> @@ -0,0 +1,1140 @@
> +/** @file
>
> + Unit tests of the MtrrLib instance of the MtrrLib
> class
>
> +
>
> + Copyright (c) 2020, Intel Corporation. All rights
> reserved.<BR>
>
> + 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 },
>
> +};
>
> +
>
> +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
> MtrrSetMemoryAttribute()
>
> +
>
> + @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
>
> +UnitTestMtrrSetMemoryAttributesInMtrrSettings (
>
> + 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_SETTINGS *Mtrrs[2];
>
> +
>
> + SystemParameter = (MTRR_LIB_SYSTEM_PARAMETER *)
> Context;
>
> + GenerateRandomMemoryTypeCombination (
>
> + SystemParameter->VariableMtrrCount - PatchPcdGet32
> (PcdCpuNumberOfReservedVariableMtrrs),
>
> + &UcCount, &WtCount, &WbCount, &WpCount, &WcCount
>
> + );
>
> + GenerateValidAndConfigurableMtrrPairs (
>
> + SystemParameter->PhysicalAddressBits,
> RawMtrrRange,
>
> + UcCount, WtCount, WbCount, WpCount, WcCount
>
> + );
>
> +
>
> + ExpectedVariableMtrrUsage = UcCount + WtCount +
> WbCount + WpCount + WcCount;
>
> + ExpectedMemoryRangesCount = ARRAY_SIZE
> (ExpectedMemoryRanges);
>
> + GetEffectiveMemoryRanges (
>
> + SystemParameter->DefaultCacheType,
>
> + SystemParameter->PhysicalAddressBits,
>
> + 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-
> >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);
>
> +
>
> + 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;
>
> +
>
> + 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_FALSE (IsMtrrSupported ());
>
> +
>
> + //
>
> + // MTRR capability on in CPUID leaf, but no fixed
> MTRRs.
>
> + //
>
> + SystemParameter.MtrrSupported = TRUE;
>
> + SystemParameter.VariableMtrrCount = 7;
>
> + SystemParameter.FixedMtrrSupported = FALSE;
>
> + InitializeMtrrRegs (&SystemParameter);
>
> + UT_ASSERT_FALSE (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, 0);
>
> +
>
> + //
>
> + // 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 (Result, &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 (Result, &FixedSettings);
>
> + UT_ASSERT_MEM_EQUAL (&ExpectedFixedSettings,
> &FixedSettings, sizeof (ExpectedFixedSettings));
>
> +
>
> + return UNIT_TEST_PASSED;
>
> +}
>
> +
>
> +/**
>
> + 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_VARIABLE_SETTING
> VariableMtrr[MTRR_NUMBER_OF_VARIABLE_MTRR];
>
> + UINT32 Index;
>
> + MTRR_LIB_SYSTEM_PARAMETER SystemParameter;
>
> + MTRR_LIB_TEST_CONTEXT *LocalContext;
>
> +
>
> + LocalContext = (MTRR_LIB_TEST_CONTEXT *) Context;
>
> +
>
> + CopyMem (&SystemParameter, LocalContext-
> >SystemParameter, sizeof (SystemParameter));
>
> + InitializeMtrrRegs (&SystemParameter);
>
> +
>
> + for (Index = 0; Index <
> SystemParameter.VariableMtrrCount; Index++) {
>
> + GenerateRandomMtrrPair
> (SystemParameter.PhysicalAddressBits,
> GenerateRandomCacheType (), &VariableMtrr[Index],
> NULL);
>
> + AsmWriteMsr64 (MSR_IA32_MTRR_PHYSBASE0 + (Index <<
> 1), VariableMtrr[Index].Base);
>
> + AsmWriteMsr64 (MSR_IA32_MTRR_PHYSMASK0 + (Index <<
> 1), VariableMtrr[Index].Mask);
>
> + }
>
> + Result = MtrrGetAllMtrrs (&Mtrrs);
>
> + UT_ASSERT_EQUAL (Result, &Mtrrs);
>
> + UT_ASSERT_MEM_EQUAL (Mtrrs.Variables.Mtrr,
> VariableMtrr, 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 (Result, &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 Mtrrs;
>
> + UINT32 Index;
>
> + MSR_IA32_MTRR_DEF_TYPE_REGISTER Default;
>
> + MTRR_LIB_SYSTEM_PARAMETER SystemParameter;
>
> + MTRR_LIB_TEST_CONTEXT *LocalContext;
>
> +
>
> + 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 (&Mtrrs, sizeof (Mtrrs));
>
> + Mtrrs.MtrrDefType = Default.Uint64;
>
> + for (Index = 0; Index <
> SystemParameter.VariableMtrrCount; Index++) {
>
> + GenerateRandomMtrrPair
> (SystemParameter.PhysicalAddressBits,
> GenerateRandomCacheType (),
> &Mtrrs.Variables.Mtrr[Index], NULL);
>
> + }
>
> + Result = MtrrSetAllMtrrs (&Mtrrs);
>
> + UT_ASSERT_EQUAL (Result, &Mtrrs);
>
> +
>
> + UT_ASSERT_EQUAL (AsmReadMsr64
> (MSR_IA32_MTRR_DEF_TYPE), Mtrrs.MtrrDefType);
>
> + for (Index = 0; Index <
> SystemParameter.VariableMtrrCount; Index++) {
>
> + UT_ASSERT_EQUAL (AsmReadMsr64
> (MSR_IA32_MTRR_PHYSBASE0 + (Index << 1)),
> Mtrrs.Variables.Mtrr[Index].Base);
>
> + UT_ASSERT_EQUAL (AsmReadMsr64
> (MSR_IA32_MTRR_PHYSMASK0 + (Index << 1)),
> Mtrrs.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);
>
> +
>
> + SystemParameter.MtrrSupported = TRUE;
>
> + SystemParameter.FixedMtrrSupported = FALSE;
>
> + InitializeMtrrRegs (&SystemParameter);
>
> + Result = MtrrGetDefaultMemoryType ();
>
> + UT_ASSERT_EQUAL (Result, CacheUncacheable);
>
> +
>
> + SystemParameter.MtrrSupported = TRUE;
>
> + SystemParameter.FixedMtrrSupported = TRUE;
>
> + SystemParameter.VariableMtrrCount = 0;
>
> + InitializeMtrrRegs (&SystemParameter);
>
> + Result = MtrrGetDefaultMemoryType ();
>
> + UT_ASSERT_EQUAL (Result, CacheUncacheable);
>
> +
>
> + return UNIT_TEST_PASSED;
>
> +}
>
> +
>
> +/**
>
> + Unit test of MtrrLib service
> MtrrSetMemoryAttributeInMtrrSettings().
>
> +
>
> + @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
>
> +UnitTestMtrrSetMemoryAttributeInMtrrSettings (
>
> + 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_SETTINGS *Mtrrs[2];
>
> +
>
> + SystemParameter = (MTRR_LIB_SYSTEM_PARAMETER *)
> Context;
>
> + GenerateRandomMemoryTypeCombination (
>
> + SystemParameter->VariableMtrrCount - PatchPcdGet32
> (PcdCpuNumberOfReservedVariableMtrrs),
>
> + &UcCount, &WtCount, &WbCount, &WpCount, &WcCount
>
> + );
>
> + GenerateValidAndConfigurableMtrrPairs (
>
> + SystemParameter->PhysicalAddressBits,
> RawMtrrRange,
>
> + UcCount, WtCount, WbCount, WpCount, WcCount
>
> + );
>
> +
>
> + ExpectedVariableMtrrUsage = UcCount + WtCount +
> WbCount + WpCount + WcCount;
>
> + ExpectedMemoryRangesCount = ARRAY_SIZE
> (ExpectedMemoryRanges);
>
> + GetEffectiveMemoryRanges (
>
> + SystemParameter->DefaultCacheType,
>
> + SystemParameter->PhysicalAddressBits,
>
> + 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-
> >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);
>
> +
>
> + 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.
>
> +**/
>
> +UNIT_TEST_STATUS
>
> +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);
>
> + return UNIT_TEST_PASSED;
>
> +}
>
> +
>
> +/**
>
> + 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;
>
> +
>
> + DEBUG ((DEBUG_INFO, "%a v%a\n", UNIT_TEST_APP_NAME,
> UNIT_TEST_APP_VERSION));
>
> +
>
> + //
>
> + // 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,
> InitializeMtrrRegs, NULL,
> &mSystemParameters[SystemIndex]);
>
> + AddTestCase (MtrrApiTests, "Test
> MtrrSetMemoryAttributeInMtrrSettings",
> "MtrrSetMemoryAttributeInMtrrSettings",
> UnitTestMtrrSetMemoryAttributeInMtrrSettings,
> InitializeMtrrRegs, NULL,
> &mSystemParameters[SystemIndex]);
>
> + AddTestCase (MtrrApiTests, "Test
> MtrrSetMemoryAttributesInMtrrSettings",
> "MtrrSetMemoryAttributesInMtrrSettings",
> UnitTestMtrrSetMemoryAttributesInMtrrSettings,
> InitializeMtrrRegs, NULL,
> &mSystemParameters[SystemIndex]);
>
> + }
>
> + }
>
> + //
>
> + // Execute the tests.
>
> + //
>
> + srand ((unsigned int) time (NULL));
>
> + 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 Iteration;
>
> +
>
> + //
>
> + // First parameter specifies the test iterations.
>
> + // Default is 10.
>
> + //
>
> + Iteration = 10;
>
> + if (Argc == 2) {
>
> + Iteration = atoi (Argv[1]);
>
> + }
>
> + return UnitTestingEntry (Iteration);
>
> +}
>
> diff --git
> a/UefiCpuPkg/Library/MtrrLib/UnitTest/MtrrLibUnitTest.h
> b/UefiCpuPkg/Library/MtrrLib/UnitTest/MtrrLibUnitTest.h
> new file mode 100644
> index 0000000000..25d4269589
> --- /dev/null
> +++
> b/UefiCpuPkg/Library/MtrrLib/UnitTest/MtrrLibUnitTest.h
> @@ -0,0 +1,171 @@
> +/** @file
>
> +
>
> + Copyright (c) 2020, Intel Corporation. All rights
> reserved.<BR>
>
> + SPDX-License-Identifier: BSD-2-Clause-Patent
>
> +
>
> +**/
>
> +
>
> +#ifndef _MTRR_SUPPORT_H_
>
> +#define _MTRR_SUPPORT_H_
>
> +
>
> +#include <stdio.h>
>
> +#include <stdlib.h>
>
> +#include <string.h>
>
> +#include <stdarg.h>
>
> +#include <stddef.h>
>
> +#include <setjmp.h>
>
> +#include <cmocka.h>
>
> +#include <time.h>
>
> +
>
> +#include <Uefi.h>
>
> +#include <Library/BaseLib.h>
>
> +#include <Library/BaseMemoryLib.h>
>
> +#include <Library/DebugLib.h>
>
> +#include <Library/UnitTestLib.h>
>
> +#include <Library/MtrrLib.h>
>
> +#include <Library/UnitTestHostBaseLib.h>
>
> +
>
> +#include <Register/ArchitecturalMsr.h>
>
> +#include <Register/Cpuid.h>
>
> +#include <Register/Msr.h>
>
> +
>
> +#define UNIT_TEST_APP_NAME "MtrrLib Unit Tests"
>
> +#define UNIT_TEST_APP_VERSION "1.0"
>
> +
>
> +#define SCRATCH_BUFFER_SIZE SIZE_16KB
>
> +
>
> +typedef struct {
>
> + UINT8 PhysicalAddressBits;
>
> + BOOLEAN MtrrSupported;
>
> + BOOLEAN FixedMtrrSupported;
>
> + MTRR_MEMORY_CACHE_TYPE DefaultCacheType;
>
> + UINT32 VariableMtrrCount;
>
> +} MTRR_LIB_SYSTEM_PARAMETER;
>
> +
>
> +extern UINT32
> mFixedMtrrsIndex[];
>
> +
>
> +/**
>
> + Initialize the MTRR registers.
>
> +
>
> + @param SystemParameter System parameter that
> controls the MTRR registers initialization.
>
> +**/
>
> +UNIT_TEST_STATUS
>
> +EFIAPI
>
> +InitializeMtrrRegs (
>
> + IN MTRR_LIB_SYSTEM_PARAMETER *SystemParameter
>
> + );
>
> +
>
> +/**
>
> + Return a random memory cache type.
>
> +**/
>
> +MTRR_MEMORY_CACHE_TYPE
>
> +GenerateRandomCacheType (
>
> + VOID
>
> + );
>
> +
>
> +/**
>
> + Generate random MTRRs.
>
> +
>
> + @param PhysicalAddressBits Physical address bits.
>
> + @param RawMemoryRanges Return the randomly
> generated MTRRs.
>
> + @param UcCount Count of Uncacheable
> MTRRs.
>
> + @param WtCount Count of Write Through
> MTRRs.
>
> + @param WbCount Count of Write Back
> MTRRs.
>
> + @param WpCount Count of Write Protected
> MTRRs.
>
> + @param WcCount Count of Write Combining
> MTRRs.
>
> +**/
>
> +VOID
>
> +GenerateValidAndConfigurableMtrrPairs (
>
> + IN UINT32
> PhysicalAddressBits,
>
> + IN OUT MTRR_MEMORY_RANGE *RawMemoryRanges,
>
> + IN UINT32 UcCount,
>
> + IN UINT32 WtCount,
>
> + IN UINT32 WbCount,
>
> + IN UINT32 WpCount,
>
> + IN UINT32 WcCount
>
> + );
>
> +
>
> +/**
>
> + Convert the MTRR BASE/MASK array to memory ranges.
>
> +
>
> + @param DefaultType Default memory type.
>
> + @param PhysicalAddressBits Physical address bits.
>
> + @param RawMemoryRanges Raw memory ranges.
>
> + @param RawMemoryRangeCount Count of raw memory
> ranges.
>
> + @param MemoryRanges Memory ranges.
>
> + @param MemoryRangeCount Count of memory ranges.
>
> +**/
>
> +VOID
>
> +GetEffectiveMemoryRanges (
>
> + IN MTRR_MEMORY_CACHE_TYPE DefaultType,
>
> + IN UINT32 PhysicalAddressBits,
>
> + IN MTRR_MEMORY_RANGE *RawMemoryRanges,
>
> + IN UINT32 RawMemoryRangeCount,
>
> + OUT MTRR_MEMORY_RANGE *MemoryRanges,
>
> + OUT UINTN *MemoryRangeCount
>
> + );
>
> +
>
> +/**
>
> + Generate random MTRR BASE/MASK for a specified type.
>
> +
>
> + @param PhysicalAddressBits Physical address bits.
>
> + @param CacheType Cache type.
>
> + @param MtrrPair Return the random MTRR.
>
> + @param MtrrMemoryRange Return the random memory
> range.
>
> +**/
>
> +VOID
>
> +GenerateRandomMtrrPair (
>
> + IN UINT32 PhysicalAddressBits,
>
> + IN MTRR_MEMORY_CACHE_TYPE CacheType,
>
> + OUT MTRR_VARIABLE_SETTING *MtrrPair, OPTIONAL
>
> + OUT MTRR_MEMORY_RANGE *MtrrMemoryRange OPTIONAL
>
> + );
>
> +
>
> +/**
>
> + Collect the test result.
>
> +
>
> + @param DefaultType Default memory type.
>
> + @param PhysicalAddressBits Physical address bits.
>
> + @param VariableMtrrCount Count of variable MTRRs.
>
> + @param Mtrrs MTRR settings to collect
> from.
>
> + @param Ranges Return the memory
> ranges.
>
> + @param RangeCount Return the count of
> memory ranges.
>
> + @param MtrrCount Return the count of
> variable MTRRs being used.
>
> +**/
>
> +VOID
>
> +CollectTestResult (
>
> + IN MTRR_MEMORY_CACHE_TYPE DefaultType,
>
> + IN UINT32 PhysicalAddressBits,
>
> + IN UINT32 VariableMtrrCount,
>
> + IN MTRR_SETTINGS *Mtrrs,
>
> + OUT MTRR_MEMORY_RANGE *Ranges,
>
> + IN OUT UINTN *RangeCount,
>
> + OUT UINT32 *MtrrCount
>
> + );
>
> +
>
> +/**
>
> + Return a 64bit random number.
>
> +
>
> + @param Start Start of the random number range.
>
> + @param Limit Limit of the random number range.
>
> + @return 64bit random number
>
> +**/
>
> +UINT64
>
> +Random64 (
>
> + UINT64 Start,
>
> + UINT64 Limit
>
> + );
>
> +
>
> +/**
>
> + Return a 32bit random number.
>
> +
>
> + @param Start Start of the random number range.
>
> + @param Limit Limit of the random number range.
>
> + @return 32bit random number
>
> +**/
>
> +UINT32
>
> +Random32 (
>
> + UINT32 Start,
>
> + UINT32 Limit
>
> + );
>
> +#endif
>
> diff --git
> a/UefiCpuPkg/Library/MtrrLib/UnitTest/MtrrLibUnitTestHo
> st.inf
> b/UefiCpuPkg/Library/MtrrLib/UnitTest/MtrrLibUnitTestHo
> st.inf
> new file mode 100644
> index 0000000000..447238dc81
> --- /dev/null
> +++
> b/UefiCpuPkg/Library/MtrrLib/UnitTest/MtrrLibUnitTestHo
> st.inf
> @@ -0,0 +1,39 @@
> +## @file
>
> +# Unit tests of the MtrrLib instance of the MtrrLib
> class
>
> +#
>
> +# Copyright (c) 2020, Intel Corporation. All rights
> reserved.<BR>
>
> +# SPDX-License-Identifier: BSD-2-Clause-Patent
>
> +##
>
> +
>
> +[Defines]
>
> + INF_VERSION = 0x00010006
>
> + BASE_NAME = MtrrLibUnitTestHost
>
> + FILE_GUID = A1542D84-B64D-4847-
> 885E-0509084376AB
>
> + MODULE_TYPE = HOST_APPLICATION
>
> + VERSION_STRING = 1.0
>
> +
>
> +#
>
> +# The following information is for reference only and
> not required by the build tools.
>
> +#
>
> +# VALID_ARCHITECTURES = IA32 X64
>
> +#
>
> +
>
> +[Sources]
>
> + MtrrLibUnitTest.c
>
> + MtrrLibUnitTest.h
>
> + Support.c
>
> +
>
> +[Packages]
>
> + MdePkg/MdePkg.dec
>
> + UefiCpuPkg/UefiCpuPkg.dec
>
> + UnitTestFrameworkPkg/UnitTestFrameworkPkg.dec
>
> +
>
> +[LibraryClasses]
>
> + BaseLib
>
> + BaseMemoryLib
>
> + DebugLib
>
> + MtrrLib
>
> + UnitTestLib
>
> +
>
> +[Pcd]
>
> +
> gUefiCpuPkgTokenSpaceGuid.PcdCpuNumberOfReservedVariabl
> eMtrrs ## SOMETIMES_CONSUMES
>
> diff --git
> a/UefiCpuPkg/Library/MtrrLib/UnitTest/Support.c
> b/UefiCpuPkg/Library/MtrrLib/UnitTest/Support.c
> new file mode 100644
> index 0000000000..9fe4b0278e
> --- /dev/null
> +++ b/UefiCpuPkg/Library/MtrrLib/UnitTest/Support.c
> @@ -0,0 +1,913 @@
> +/** @file
>
> + Unit tests of the MtrrLib instance of the MtrrLib
> class
>
> +
>
> + Copyright (c) 2018 - 2020, Intel Corporation. All
> rights reserved.<BR>
>
> + SPDX-License-Identifier: BSD-2-Clause-Patent
>
> +
>
> +**/
>
> +
>
> +#include "MtrrLibUnitTest.h"
>
> +
>
> +MTRR_MEMORY_CACHE_TYPE mMemoryCacheTypes[] = {
>
> + CacheUncacheable, CacheWriteCombining,
> CacheWriteThrough, CacheWriteProtected, CacheWriteBack
>
> + };
>
> +
>
> +UINT64
> mFixedMtrrsValue[MTRR_NUMBER_OF_FIXED_MTRR];
>
> +MSR_IA32_MTRR_PHYSBASE_REGISTER
> mVariableMtrrsPhysBase[MTRR_NUMBER_OF_VARIABLE_MTRR];
>
> +MSR_IA32_MTRR_PHYSMASK_REGISTER
> mVariableMtrrsPhysMask[MTRR_NUMBER_OF_VARIABLE_MTRR];
>
> +MSR_IA32_MTRR_DEF_TYPE_REGISTER mDefTypeMsr;
>
> +MSR_IA32_MTRRCAP_REGISTER mMtrrCapMsr;
>
> +CPUID_VERSION_INFO_EDX mCpuidVersionInfoEdx;
>
> +CPUID_VIR_PHY_ADDRESS_SIZE_EAX
> mCpuidVirPhyAddressSizeEax;
>
> +
>
> +/**
>
> + Retrieves CPUID information.
>
> +
>
> + Executes the CPUID instruction with EAX set to the
> value specified by Index.
>
> + This function always returns Index.
>
> + If Eax is not NULL, then the value of EAX after
> CPUID is returned in Eax.
>
> + If Ebx is not NULL, then the value of EBX after
> CPUID is returned in Ebx.
>
> + If Ecx is not NULL, then the value of ECX after
> CPUID is returned in Ecx.
>
> + If Edx is not NULL, then the value of EDX after
> CPUID is returned in Edx.
>
> + This function is only available on IA-32 and x64.
>
> +
>
> + @param Index The 32-bit value to load into EAX
> prior to invoking the CPUID
>
> + instruction.
>
> + @param Eax The pointer to the 32-bit EAX value
> returned by the CPUID
>
> + instruction. This is an optional
> parameter that may be NULL.
>
> + @param Ebx The pointer to the 32-bit EBX value
> returned by the CPUID
>
> + instruction. This is an optional
> parameter that may be NULL.
>
> + @param Ecx The pointer to the 32-bit ECX value
> returned by the CPUID
>
> + instruction. This is an optional
> parameter that may be NULL.
>
> + @param Edx The pointer to the 32-bit EDX value
> returned by the CPUID
>
> + instruction. This is an optional
> parameter that may be NULL.
>
> +
>
> + @return Index.
>
> +
>
> +**/
>
> +UINT32
>
> +EFIAPI
>
> +UnitTestMtrrLibAsmCpuid (
>
> + IN UINT32 Index,
>
> + OUT UINT32 *Eax, OPTIONAL
>
> + OUT UINT32 *Ebx, OPTIONAL
>
> + OUT UINT32 *Ecx, OPTIONAL
>
> + OUT UINT32 *Edx OPTIONAL
>
> + )
>
> +{
>
> + switch (Index) {
>
> + case CPUID_VERSION_INFO:
>
> + if (Edx != NULL) {
>
> + *Edx = mCpuidVersionInfoEdx.Uint32;
>
> + }
>
> + return Index;
>
> + break;
>
> + case CPUID_EXTENDED_FUNCTION:
>
> + if (Eax != NULL) {
>
> + *Eax = CPUID_VIR_PHY_ADDRESS_SIZE;
>
> + }
>
> + return Index;
>
> + break;
>
> + case CPUID_VIR_PHY_ADDRESS_SIZE:
>
> + if (Eax != NULL) {
>
> + *Eax = mCpuidVirPhyAddressSizeEax.Uint32;
>
> + }
>
> + return Index;
>
> + break;
>
> + }
>
> +
>
> + //
>
> + // Should never fall through to here
>
> + //
>
> + ASSERT(FALSE);
>
> + return Index;
>
> +}
>
> +
>
> +/**
>
> + Returns a 64-bit Machine Specific Register(MSR).
>
> +
>
> + Reads and returns the 64-bit MSR specified by Index.
> No parameter checking is
>
> + performed on Index, and some Index values may cause
> CPU exceptions. The
>
> + caller must either guarantee that Index is valid, or
> the caller must set up
>
> + exception handlers to catch the exceptions. This
> function is only available
>
> + on IA-32 and x64.
>
> +
>
> + @param MsrIndex The 32-bit MSR index to read.
>
> +
>
> + @return The value of the MSR identified by MsrIndex.
>
> +
>
> +**/
>
> +UINT64
>
> +EFIAPI
>
> +UnitTestMtrrLibAsmReadMsr64(
>
> + IN UINT32 MsrIndex
>
> + )
>
> +{
>
> + UINT32 Index;
>
> +
>
> + for (Index = 0; Index < ARRAY_SIZE
> (mFixedMtrrsValue); Index++) {
>
> + if (MsrIndex == mFixedMtrrsIndex[Index]) {
>
> + return mFixedMtrrsValue[Index];
>
> + }
>
> + }
>
> +
>
> + if ((MsrIndex >= MSR_IA32_MTRR_PHYSBASE0) &&
>
> + (MsrIndex <= MSR_IA32_MTRR_PHYSMASK0 +
> (MTRR_NUMBER_OF_VARIABLE_MTRR << 1))) {
>
> + if (MsrIndex % 2 == 0) {
>
> + Index = (MsrIndex - MSR_IA32_MTRR_PHYSBASE0) >>
> 1;
>
> + return mVariableMtrrsPhysBase[Index].Uint64;
>
> + } else {
>
> + Index = (MsrIndex - MSR_IA32_MTRR_PHYSMASK0) >>
> 1;
>
> + return mVariableMtrrsPhysMask[Index].Uint64;
>
> + }
>
> + }
>
> +
>
> + if (MsrIndex == MSR_IA32_MTRR_DEF_TYPE) {
>
> + return mDefTypeMsr.Uint64;
>
> + }
>
> +
>
> + if (MsrIndex == MSR_IA32_MTRRCAP) {
>
> + return mMtrrCapMsr.Uint64;
>
> + }
>
> +
>
> + //
>
> + // Should never fall through to here
>
> + //
>
> + ASSERT(FALSE);
>
> + return 0;
>
> +}
>
> +
>
> +/**
>
> + Writes a 64-bit value to a Machine Specific
> Register(MSR), and returns the
>
> + value.
>
> +
>
> + Writes the 64-bit value specified by Value to the
> MSR specified by Index. The
>
> + 64-bit value written to the MSR is returned. No
> parameter checking is
>
> + performed on Index or Value, and some of these may
> cause CPU exceptions. The
>
> + caller must either guarantee that Index and Value
> are valid, or the caller
>
> + must establish proper exception handlers. This
> function is only available on
>
> + IA-32 and x64.
>
> +
>
> + @param MsrIndex The 32-bit MSR index to write.
>
> + @param Value The 64-bit value to write to the MSR.
>
> +
>
> + @return Value
>
> +
>
> +**/
>
> +UINT64
>
> +EFIAPI
>
> +UnitTestMtrrLibAsmWriteMsr64(
>
> + IN UINT32 MsrIndex,
>
> + IN UINT64 Value
>
> + )
>
> +{
>
> + UINT32 Index;
>
> +
>
> + for (Index = 0; Index < ARRAY_SIZE
> (mFixedMtrrsValue); Index++) {
>
> + if (MsrIndex == mFixedMtrrsIndex[Index]) {
>
> + mFixedMtrrsValue[Index] = Value;
>
> + return Value;
>
> + }
>
> + }
>
> +
>
> + if ((MsrIndex >= MSR_IA32_MTRR_PHYSBASE0) &&
>
> + (MsrIndex <= MSR_IA32_MTRR_PHYSMASK0 +
> (MTRR_NUMBER_OF_VARIABLE_MTRR << 1))) {
>
> + if (MsrIndex % 2 == 0) {
>
> + Index = (MsrIndex - MSR_IA32_MTRR_PHYSBASE0) >>
> 1;
>
> + mVariableMtrrsPhysBase[Index].Uint64 = Value;
>
> + return Value;
>
> + } else {
>
> + Index = (MsrIndex - MSR_IA32_MTRR_PHYSMASK0) >>
> 1;
>
> + mVariableMtrrsPhysMask[Index].Uint64 = Value;
>
> + return Value;
>
> + }
>
> + }
>
> +
>
> + if (MsrIndex == MSR_IA32_MTRR_DEF_TYPE) {
>
> + mDefTypeMsr.Uint64 = Value;
>
> + return Value;
>
> + }
>
> +
>
> + if (MsrIndex == MSR_IA32_MTRRCAP) {
>
> + mMtrrCapMsr.Uint64 = Value;
>
> + return Value;
>
> + }
>
> +
>
> + //
>
> + // Should never fall through to here
>
> + //
>
> + ASSERT(FALSE);
>
> + return 0;
>
> +}
>
> +
>
> +/**
>
> + Initialize MTRR registers.
>
> +**/
>
> +
>
> +/**
>
> + Initialize the MTRR registers.
>
> +
>
> + @param SystemParameter System parameter that
> controls the MTRR registers initialization.
>
> +**/
>
> +UNIT_TEST_STATUS
>
> +EFIAPI
>
> +InitializeMtrrRegs (
>
> + IN MTRR_LIB_SYSTEM_PARAMETER *SystemParameter
>
> + )
>
> +{
>
> + UINT32 Index;
>
> +
>
> + SetMem (mFixedMtrrsValue, sizeof (mFixedMtrrsValue),
> SystemParameter->DefaultCacheType);
>
> +
>
> + for (Index = 0; Index < ARRAY_SIZE
> (mVariableMtrrsPhysBase); Index++) {
>
> + mVariableMtrrsPhysBase[Index].Uint64 = 0;
>
> + mVariableMtrrsPhysBase[Index].Bits.Type =
> SystemParameter->DefaultCacheType;
>
> + mVariableMtrrsPhysBase[Index].Bits.Reserved1 = 0;
>
> +
>
> + mVariableMtrrsPhysMask[Index].Uint64 = 0;
>
> + mVariableMtrrsPhysMask[Index].Bits.V = 0;
>
> + mVariableMtrrsPhysMask[Index].Bits.Reserved1 = 0;
>
> + }
>
> +
>
> + mDefTypeMsr.Bits.E = 1;
>
> + mDefTypeMsr.Bits.FE = 1;
>
> + mDefTypeMsr.Bits.Type = SystemParameter-
> >DefaultCacheType;
>
> + mDefTypeMsr.Bits.Reserved1 = 0;
>
> + mDefTypeMsr.Bits.Reserved2 = 0;
>
> + mDefTypeMsr.Bits.Reserved3 = 0;
>
> +
>
> + mMtrrCapMsr.Bits.SMRR = 0;
>
> + mMtrrCapMsr.Bits.WC = 0;
>
> + mMtrrCapMsr.Bits.VCNT = SystemParameter-
> >VariableMtrrCount;
>
> + mMtrrCapMsr.Bits.FIX = SystemParameter-
> >FixedMtrrSupported;
>
> + mMtrrCapMsr.Bits.Reserved1 = 0;
>
> + mMtrrCapMsr.Bits.Reserved2 = 0;
>
> + mMtrrCapMsr.Bits.Reserved3 = 0;
>
> +
>
> + mCpuidVersionInfoEdx.Bits.MTRR
> = SystemParameter->MtrrSupported;
>
> + mCpuidVirPhyAddressSizeEax.Bits.PhysicalAddressBits
> = SystemParameter->PhysicalAddressBits;
>
> +
>
> + //
>
> + // Hook BaseLib functions used by MtrrLib that
> require some emulation.
>
> + //
>
> + gUnitTestHostBaseLib.X86->AsmCpuid =
> UnitTestMtrrLibAsmCpuid;
>
> + gUnitTestHostBaseLib.X86->AsmReadMsr64 =
> UnitTestMtrrLibAsmReadMsr64;
>
> + gUnitTestHostBaseLib.X86->AsmWriteMsr64 =
> UnitTestMtrrLibAsmWriteMsr64;
>
> +
>
> + return UNIT_TEST_PASSED;
>
> +}
>
> +
>
> +/**
>
> + Collect the test result.
>
> +
>
> + @param DefaultType Default memory type.
>
> + @param PhysicalAddressBits Physical address bits.
>
> + @param VariableMtrrCount Count of variable MTRRs.
>
> + @param Mtrrs MTRR settings to collect
> from.
>
> + @param Ranges Return the memory
> ranges.
>
> + @param RangeCount Return the count of
> memory ranges.
>
> + @param MtrrCount Return the count of
> variable MTRRs being used.
>
> +**/
>
> +VOID
>
> +CollectTestResult (
>
> + IN MTRR_MEMORY_CACHE_TYPE DefaultType,
>
> + IN UINT32 PhysicalAddressBits,
>
> + IN UINT32 VariableMtrrCount,
>
> + IN MTRR_SETTINGS *Mtrrs,
>
> + OUT MTRR_MEMORY_RANGE *Ranges,
>
> + IN OUT UINTN *RangeCount,
>
> + OUT UINT32 *MtrrCount
>
> + )
>
> +{
>
> + UINTN Index;
>
> + UINT64 MtrrValidBitsMask;
>
> + UINT64 MtrrValidAddressMask;
>
> + MTRR_MEMORY_RANGE RawMemoryRanges[ARRAY_SIZE (Mtrrs-
> >Variables.Mtrr)];
>
> +
>
> + ASSERT (Mtrrs != NULL);
>
> + ASSERT (VariableMtrrCount <= ARRAY_SIZE (Mtrrs-
> >Variables.Mtrr));
>
> +
>
> + MtrrValidBitsMask = (1ull << PhysicalAddressBits) -
> 1;
>
> + MtrrValidAddressMask = MtrrValidBitsMask &
> ~0xFFFull;
>
> +
>
> + *MtrrCount = 0;
>
> + for (Index = 0; Index < VariableMtrrCount; Index++)
> {
>
> + if (((MSR_IA32_MTRR_PHYSMASK_REGISTER *) &Mtrrs-
> >Variables.Mtrr[Index].Mask)->Bits.V == 1) {
>
> + RawMemoryRanges[*MtrrCount].BaseAddress = Mtrrs-
> >Variables.Mtrr[Index].Base & MtrrValidAddressMask;
>
> + RawMemoryRanges[*MtrrCount].Type =
>
> + ((MSR_IA32_MTRR_PHYSBASE_REGISTER *) &Mtrrs-
> >Variables.Mtrr[Index].Base)->Bits.Type;
>
> + RawMemoryRanges[*MtrrCount].Length =
>
> + ((~(Mtrrs->Variables.Mtrr[Index].Mask &
> MtrrValidAddressMask)) & MtrrValidBitsMask) + 1;
>
> + (*MtrrCount)++;
>
> + }
>
> + }
>
> +
>
> + GetEffectiveMemoryRanges (DefaultType,
> PhysicalAddressBits, RawMemoryRanges, *MtrrCount,
> Ranges, RangeCount);
>
> +}
>
> +
>
> +/**
>
> + Return a 32bit random number.
>
> +
>
> + @param Start Start of the random number range.
>
> + @param Limit Limit of the random number range.
>
> + @return 32bit random number
>
> +**/
>
> +UINT32
>
> +Random32 (
>
> + UINT32 Start,
>
> + UINT32 Limit
>
> + )
>
> +{
>
> + return (UINT32) (((double) rand () / RAND_MAX) *
> (Limit - Start)) + Start;
>
> +}
>
> +
>
> +/**
>
> + Return a 64bit random number.
>
> +
>
> + @param Start Start of the random number range.
>
> + @param Limit Limit of the random number range.
>
> + @return 64bit random number
>
> +**/
>
> +UINT64
>
> +Random64 (
>
> + UINT64 Start,
>
> + UINT64 Limit
>
> + )
>
> +{
>
> + return (UINT64) (((double) rand () / RAND_MAX) *
> (Limit - Start)) + Start;
>
> +}
>
> +
>
> +/**
>
> + Generate random MTRR BASE/MASK for a specified type.
>
> +
>
> + @param PhysicalAddressBits Physical address bits.
>
> + @param CacheType Cache type.
>
> + @param MtrrPair Return the random MTRR.
>
> + @param MtrrMemoryRange Return the random memory
> range.
>
> +**/
>
> +VOID
>
> +GenerateRandomMtrrPair (
>
> + IN UINT32 PhysicalAddressBits,
>
> + IN MTRR_MEMORY_CACHE_TYPE CacheType,
>
> + OUT MTRR_VARIABLE_SETTING *MtrrPair, OPTIONAL
>
> + OUT MTRR_MEMORY_RANGE *MtrrMemoryRange OPTIONAL
>
> + )
>
> +{
>
> + MSR_IA32_MTRR_PHYSBASE_REGISTER PhysBase;
>
> + MSR_IA32_MTRR_PHYSMASK_REGISTER PhysMask;
>
> + UINT32 SizeShift;
>
> + UINT32 BaseShift;
>
> + UINT64 RandomBoundary;
>
> + UINT64 MaxPhysicalAddress;
>
> + UINT64 RangeSize;
>
> + UINT64 RangeBase;
>
> + UINT64
> PhysBasePhyMaskValidBitsMask;
>
> +
>
> + MaxPhysicalAddress = 1ull << PhysicalAddressBits;
>
> + do {
>
> + SizeShift = Random32 (12, PhysicalAddressBits -
> 1);
>
> + RangeSize = 1ull << SizeShift;
>
> +
>
> + BaseShift = Random32 (SizeShift,
> PhysicalAddressBits - 1);
>
> + RandomBoundary = Random64 (0, 1ull <<
> (PhysicalAddressBits - BaseShift));
>
> + RangeBase = RandomBoundary << BaseShift;
>
> + } while (RangeBase < SIZE_1MB || RangeBase >
> MaxPhysicalAddress - 1);
>
> +
>
> + PhysBasePhyMaskValidBitsMask = (MaxPhysicalAddress -
> 1) & 0xfffffffffffff000ULL;
>
> +
>
> + PhysBase.Uint64 = 0;
>
> + PhysBase.Bits.Type = CacheType;
>
> + PhysBase.Uint64 |= RangeBase &
> PhysBasePhyMaskValidBitsMask;
>
> + PhysMask.Uint64 = 0;
>
> + PhysMask.Bits.V = 1;
>
> + PhysMask.Uint64 |= ((~RangeSize) + 1) &
> PhysBasePhyMaskValidBitsMask;
>
> +
>
> + if (MtrrPair != NULL) {
>
> + MtrrPair->Base = PhysBase.Uint64;
>
> + MtrrPair->Mask = PhysMask.Uint64;
>
> + }
>
> +
>
> + if (MtrrMemoryRange != NULL) {
>
> + MtrrMemoryRange->BaseAddress = RangeBase;
>
> + MtrrMemoryRange->Length = RangeSize;
>
> + MtrrMemoryRange->Type = CacheType;
>
> + }
>
> +}
>
> +
>
> +
>
> +/**
>
> + Check whether the Range overlaps with any one in
> Ranges.
>
> +
>
> + @param Range The memory range to check.
>
> + @param Ranges The memory ranges.
>
> + @param Count Count of memory ranges.
>
> +
>
> + @return TRUE when overlap exists.
>
> +**/
>
> +BOOLEAN
>
> +RangesOverlap (
>
> + IN MTRR_MEMORY_RANGE *Range,
>
> + IN MTRR_MEMORY_RANGE *Ranges,
>
> + IN UINTN Count
>
> + )
>
> +{
>
> + while (Count-- != 0) {
>
> + //
>
> + // Two ranges overlap when:
>
> + // 1. range#2.base is in the middle of range#1
>
> + // 2. range#1.base is in the middle of range#2
>
> + //
>
> + if ((Range->BaseAddress <=
> Ranges[Count].BaseAddress && Ranges[Count].BaseAddress
> < Range->BaseAddress + Range->Length)
>
> + || (Ranges[Count].BaseAddress <= Range-
> >BaseAddress && Range->BaseAddress <
> Ranges[Count].BaseAddress + Ranges[Count].Length)) {
>
> + return TRUE;
>
> + }
>
> + }
>
> + return FALSE;
>
> +}
>
> +
>
> +/**
>
> + Generate random MTRRs.
>
> +
>
> + @param PhysicalAddressBits Physical address bits.
>
> + @param RawMemoryRanges Return the randomly
> generated MTRRs.
>
> + @param UcCount Count of Uncacheable
> MTRRs.
>
> + @param WtCount Count of Write Through
> MTRRs.
>
> + @param WbCount Count of Write Back
> MTRRs.
>
> + @param WpCount Count of Write Protected
> MTRRs.
>
> + @param WcCount Count of Write Combine
> MTRRs.
>
> +**/
>
> +VOID
>
> +GenerateValidAndConfigurableMtrrPairs (
>
> + IN UINT32
> PhysicalAddressBits,
>
> + IN OUT MTRR_MEMORY_RANGE *RawMemoryRanges,
>
> + IN UINT32 UcCount,
>
> + IN UINT32 WtCount,
>
> + IN UINT32 WbCount,
>
> + IN UINT32 WpCount,
>
> + IN UINT32 WcCount
>
> + )
>
> +{
>
> + UINT32 Index;
>
> +
>
> + //
>
> + // 1. Generate UC, WT, WB in order.
>
> + //
>
> + for (Index = 0; Index < UcCount; Index++) {
>
> + GenerateRandomMtrrPair (PhysicalAddressBits,
> CacheUncacheable, NULL, &RawMemoryRanges[Index]);
>
> + }
>
> +
>
> + for (Index = UcCount; Index < UcCount + WtCount;
> Index++) {
>
> + GenerateRandomMtrrPair (PhysicalAddressBits,
> CacheWriteThrough, NULL, &RawMemoryRanges[Index]);
>
> + }
>
> +
>
> + for (Index = UcCount + WtCount; Index < UcCount +
> WtCount + WbCount; Index++) {
>
> + GenerateRandomMtrrPair (PhysicalAddressBits,
> CacheWriteBack, NULL, &RawMemoryRanges[Index]);
>
> + }
>
> +
>
> + //
>
> + // 2. Generate WP MTRR and DO NOT overlap with WT,
> WB.
>
> + //
>
> + for (Index = UcCount + WtCount + WbCount; Index <
> UcCount + WtCount + WbCount + WpCount; Index++) {
>
> + GenerateRandomMtrrPair (PhysicalAddressBits,
> CacheWriteProtected, NULL, &RawMemoryRanges[Index]);
>
> + while (RangesOverlap (&RawMemoryRanges[Index],
> &RawMemoryRanges[UcCount], WtCount + WbCount)) {
>
> + GenerateRandomMtrrPair (PhysicalAddressBits,
> CacheWriteProtected, NULL, &RawMemoryRanges[Index]);
>
> + }
>
> + }
>
> +
>
> + //
>
> + // 3. Generate WC MTRR and DO NOT overlap with WT,
> WB, WP.
>
> + //
>
> + for (Index = UcCount + WtCount + WbCount + WpCount;
> Index < UcCount + WtCount + WbCount + WpCount +
> WcCount; Index++) {
>
> + GenerateRandomMtrrPair (PhysicalAddressBits,
> CacheWriteCombining, NULL, &RawMemoryRanges[Index]);
>
> + while (RangesOverlap (&RawMemoryRanges[Index],
> &RawMemoryRanges[UcCount], WtCount + WbCount +
> WpCount)) {
>
> + GenerateRandomMtrrPair (PhysicalAddressBits,
> CacheWriteCombining, NULL, &RawMemoryRanges[Index]);
>
> + }
>
> + }
>
> +}
>
> +
>
> +/**
>
> + Return a random memory cache type.
>
> +**/
>
> +MTRR_MEMORY_CACHE_TYPE
>
> +GenerateRandomCacheType (
>
> + VOID
>
> + )
>
> +{
>
> + return mMemoryCacheTypes[Random32 (0, ARRAY_SIZE
> (mMemoryCacheTypes) - 1)];
>
> +}
>
> +
>
> +/**
>
> + Compare function used by qsort().
>
> +**/
>
> +
>
> +/**
>
> + Compare function used by qsort().
>
> +
>
> + @param Left Left operand to compare.
>
> + @param Right Right operand to compare.
>
> +
>
> + @retval 0 Left == Right
>
> + @retval -1 Left < Right
>
> + @retval 1 Left > Right
>
> +**/
>
> +INT32
>
> +CompareFuncUint64 (
>
> + CONST VOID * Left,
>
> + CONST VOID * Right
>
> + )
>
> +{
>
> + INT64 Delta;
>
> + Delta = (*(UINT64*)Left - *(UINT64*)Right);
>
> + if (Delta > 0) {
>
> + return 1;
>
> + } else if (Delta == 0) {
>
> + return 0;
>
> + } else {
>
> + return -1;
>
> + }
>
> +}
>
> +
>
> +/**
>
> + Determin the memory cache type for the Range.
>
> +
>
> + @param DefaultType Default cache type.
>
> + @param Range The memory range to determin the
> cache type.
>
> + @param Ranges The entire memory ranges.
>
> + @param RangeCount Count of the entire memory
> ranges.
>
> +**/
>
> +VOID
>
> +DetermineMemoryCacheType (
>
> + IN MTRR_MEMORY_CACHE_TYPE DefaultType,
>
> + IN OUT MTRR_MEMORY_RANGE *Range,
>
> + IN MTRR_MEMORY_RANGE *Ranges,
>
> + IN UINT32 RangeCount
>
> + )
>
> +{
>
> + UINT32 Index;
>
> + Range->Type = CacheInvalid;
>
> + for (Index = 0; Index < RangeCount; Index++) {
>
> + if (RangesOverlap (Range, &Ranges[Index], 1)) {
>
> + if (Ranges[Index].Type < Range->Type) {
>
> + Range->Type = Ranges[Index].Type;
>
> + }
>
> + }
>
> + }
>
> +
>
> + if (Range->Type == CacheInvalid) {
>
> + Range->Type = DefaultType;
>
> + }
>
> +}
>
> +
>
> +/**
>
> + Get the index of the element that does NOT equals to
> Array[Index].
>
> +
>
> + @param Index Current element.
>
> + @param Array Array to scan.
>
> + @param Count Count of the array.
>
> +
>
> + @return Next element that doesn't equal to current
> one.
>
> +**/
>
> +UINT32
>
> +GetNextDifferentElementInSortedArray (
>
> + IN UINT32 Index,
>
> + IN UINT64 *Array,
>
> + IN UINT32 Count
>
> + )
>
> +{
>
> + UINT64 CurrentElement;
>
> + CurrentElement = Array[Index];
>
> + while (CurrentElement == Array[Index] && Index <
> Count) {
>
> + Index++;
>
> + }
>
> + return Index;
>
> +}
>
> +
>
> +/**
>
> + Remove the duplicates from the array.
>
> +
>
> + @param Array The array to operate on.
>
> + @param Count Count of the array.
>
> +**/
>
> +VOID
>
> +RemoveDuplicatesInSortedArray (
>
> + IN OUT UINT64 *Array,
>
> + IN OUT UINT32 *Count
>
> + )
>
> +{
>
> + UINT32 Index;
>
> + UINT32 NewCount;
>
> +
>
> + Index = 0;
>
> + NewCount = 0;
>
> + while (Index < *Count) {
>
> + Array[NewCount] = Array[Index];
>
> + NewCount++;
>
> + Index = GetNextDifferentElementInSortedArray
> (Index, Array, *Count);
>
> + }
>
> + *Count = NewCount;
>
> +}
>
> +
>
> +/**
>
> + Return TRUE when Address is in the Range.
>
> +
>
> + @param Address The address to check.
>
> + @param Range The range to check.
>
> + @return TRUE when Address is in the Range.
>
> +**/
>
> +BOOLEAN
>
> +AddressInRange (
>
> + IN UINT64 Address,
>
> + IN MTRR_MEMORY_RANGE Range
>
> + )
>
> +{
>
> + return (Address >= Range.BaseAddress) && (Address
> <= Range.BaseAddress + Range.Length - 1);
>
> +}
>
> +
>
> +/**
>
> + Get the overlap bit flag.
>
> +
>
> + @param RawMemoryRanges Raw memory ranges.
>
> + @param RawMemoryRangeCount Count of raw memory
> ranges.
>
> + @param Address The address to check.
>
> +**/
>
> +UINT64
>
> +GetOverlapBitFlag (
>
> + IN MTRR_MEMORY_RANGE *RawMemoryRanges,
>
> + IN UINT32 RawMemoryRangeCount,
>
> + IN UINT64 Address
>
> + )
>
> +{
>
> + UINT64 OverlapBitFlag;
>
> + UINT32 Index;
>
> + OverlapBitFlag = 0;
>
> + for (Index = 0; Index < RawMemoryRangeCount;
> Index++) {
>
> + if (AddressInRange (Address,
> RawMemoryRanges[Index])) {
>
> + OverlapBitFlag |= (1ull << Index);
>
> + }
>
> + }
>
> +
>
> + return OverlapBitFlag;
>
> +}
>
> +
>
> +/**
>
> + Return the relationship between flags.
>
> +
>
> + @param Flag1 Flag 1
>
> + @param Flag2 Flag 2
>
> +
>
> + @retval 0 Flag1 == Flag2
>
> + @retval 1 Flag1 is a subset of Flag2
>
> + @retval 2 Flag2 is a subset of Flag1
>
> + @retval 3 No subset relations between Flag1 and
> Flag2.
>
> +**/
>
> +UINT32
>
> +CheckOverlapBitFlagsRelation (
>
> + IN UINT64 Flag1,
>
> + IN UINT64 Flag2
>
> + )
>
> +{
>
> + if (Flag1 == Flag2) return 0;
>
> + if ((Flag1 | Flag2) == Flag2) return 1;
>
> + if ((Flag1 | Flag2) == Flag1) return 2;
>
> + return 3;
>
> +}
>
> +
>
> +/**
>
> + Return TRUE when the Endpoint is in any of the
> Ranges.
>
> +
>
> + @param Endpoint The endpoint to check.
>
> + @param Ranges The memory ranges.
>
> + @param RangeCount Count of memory ranges.
>
> +
>
> + @retval TRUE Endpoint is in one of the range.
>
> + @retval FALSE Endpoint is not in any of the ranges.
>
> +**/
>
> +BOOLEAN
>
> +IsEndpointInRanges (
>
> + IN UINT64 Endpoint,
>
> + IN MTRR_MEMORY_RANGE *Ranges,
>
> + IN UINTN RangeCount
>
> + )
>
> +{
>
> + UINT32 Index;
>
> + for (Index = 0; Index < RangeCount; Index++) {
>
> + if (AddressInRange (Endpoint, Ranges[Index])) {
>
> + return TRUE;
>
> + }
>
> + }
>
> + return FALSE;
>
> +}
>
> +
>
> +
>
> +/**
>
> + Compact adjacent ranges of the same type.
>
> +
>
> + @param DefaultType Default memory
> type.
>
> + @param PhysicalAddressBits Physical
> address bits.
>
> + @param EffectiveMtrrMemoryRanges Memory ranges
> to compact.
>
> + @param EffectiveMtrrMemoryRangesCount Return the new
> count of memory ranges.
>
> +**/
>
> +VOID
>
> +CompactAndExtendEffectiveMtrrMemoryRanges (
>
> + IN MTRR_MEMORY_CACHE_TYPE DefaultType,
>
> + IN UINT32 PhysicalAddressBits,
>
> + IN OUT MTRR_MEMORY_RANGE
> **EffectiveMtrrMemoryRanges,
>
> + IN OUT UINTN
> *EffectiveMtrrMemoryRangesCount
>
> + )
>
> +{
>
> + UINT64 MaxAddress;
>
> + UINTN NewRangesCountAtMost;
>
> + MTRR_MEMORY_RANGE *NewRanges;
>
> + UINTN NewRangesCountActual;
>
> + MTRR_MEMORY_RANGE
> *CurrentRangeInNewRanges;
>
> + MTRR_MEMORY_CACHE_TYPE
> CurrentRangeTypeInOldRanges;
>
> +
>
> + MTRR_MEMORY_RANGE *OldRanges;
>
> + MTRR_MEMORY_RANGE OldLastRange;
>
> + UINTN OldRangesIndex;
>
> +
>
> + NewRangesCountActual = 0;
>
> + NewRangesCountAtMost =
> *EffectiveMtrrMemoryRangesCount + 2; // At most with
> 2 more range entries.
>
> + NewRanges = (MTRR_MEMORY_RANGE *) calloc
> (NewRangesCountAtMost, sizeof (MTRR_MEMORY_RANGE));
>
> + OldRanges = *EffectiveMtrrMemoryRanges;
>
> + if (OldRanges[0].BaseAddress > 0) {
>
> + NewRanges[NewRangesCountActual].BaseAddress = 0;
>
> + NewRanges[NewRangesCountActual].Length =
> OldRanges[0].BaseAddress;
>
> + NewRanges[NewRangesCountActual].Type =
> DefaultType;
>
> + NewRangesCountActual++;
>
> + }
>
> +
>
> + OldRangesIndex = 0;
>
> + while (OldRangesIndex <
> *EffectiveMtrrMemoryRangesCount) {
>
> + CurrentRangeTypeInOldRanges =
> OldRanges[OldRangesIndex].Type;
>
> + CurrentRangeInNewRanges = NULL;
>
> + if (NewRangesCountActual > 0) // We need to
> check CurrentNewRange first before generate a new
> NewRange.
>
> + {
>
> + CurrentRangeInNewRanges =
> &NewRanges[NewRangesCountActual - 1];
>
> + }
>
> + if (CurrentRangeInNewRanges != NULL &&
> CurrentRangeInNewRanges->Type ==
> CurrentRangeTypeInOldRanges) {
>
> + CurrentRangeInNewRanges->Length +=
> OldRanges[OldRangesIndex].Length;
>
> + } else {
>
> + NewRanges[NewRangesCountActual].BaseAddress =
> OldRanges[OldRangesIndex].BaseAddress;
>
> + NewRanges[NewRangesCountActual].Length +=
> OldRanges[OldRangesIndex].Length;
>
> + NewRanges[NewRangesCountActual].Type =
> CurrentRangeTypeInOldRanges;
>
> + while (OldRangesIndex + 1 <
> *EffectiveMtrrMemoryRangesCount &&
> OldRanges[OldRangesIndex + 1].Type ==
> CurrentRangeTypeInOldRanges)
>
> + {
>
> + OldRangesIndex++;
>
> + NewRanges[NewRangesCountActual].Length +=
> OldRanges[OldRangesIndex].Length;
>
> + }
>
> + NewRangesCountActual++;
>
> + }
>
> +
>
> + OldRangesIndex++;
>
> + }
>
> +
>
> + MaxAddress = (1ull << PhysicalAddressBits) - 1;
>
> + OldLastRange =
> OldRanges[(*EffectiveMtrrMemoryRangesCount) - 1];
>
> + CurrentRangeInNewRanges =
> &NewRanges[NewRangesCountActual - 1];
>
> + if (OldLastRange.BaseAddress + OldLastRange.Length -
> 1 < MaxAddress) {
>
> + if (CurrentRangeInNewRanges->Type == DefaultType)
> {
>
> + CurrentRangeInNewRanges->Length = MaxAddress -
> CurrentRangeInNewRanges->BaseAddress + 1;
>
> + } else {
>
> + NewRanges[NewRangesCountActual].BaseAddress =
> OldLastRange.BaseAddress + OldLastRange.Length;
>
> + NewRanges[NewRangesCountActual].Length =
> MaxAddress -
> NewRanges[NewRangesCountActual].BaseAddress + 1;
>
> + NewRanges[NewRangesCountActual].Type =
> DefaultType;
>
> + NewRangesCountActual++;
>
> + }
>
> + }
>
> +
>
> + free (*EffectiveMtrrMemoryRanges);
>
> + *EffectiveMtrrMemoryRanges = NewRanges;
>
> + *EffectiveMtrrMemoryRangesCount =
> NewRangesCountActual;
>
> +}
>
> +
>
> +/**
>
> + Collect all the endpoints in the raw memory ranges.
>
> +
>
> + @param Endpoints Return the collected
> endpoints.
>
> + @param EndPointCount Return the count of
> endpoints.
>
> + @param RawMemoryRanges Raw memory ranges.
>
> + @param RawMemoryRangeCount Count of raw memory
> ranges.
>
> +**/
>
> +VOID
>
> +CollectEndpoints (
>
> + IN OUT UINT64 *Endpoints,
>
> + IN OUT UINT32 *EndPointCount,
>
> + IN MTRR_MEMORY_RANGE *RawMemoryRanges,
>
> + IN UINT32 RawMemoryRangeCount
>
> + )
>
> +{
>
> + UINT32 Index;
>
> + UINT32 RawRangeIndex;
>
> +
>
> + ASSERT ((RawMemoryRangeCount << 1) ==
> *EndPointCount);
>
> +
>
> + for (Index = 0; Index < *EndPointCount; Index += 2)
> {
>
> + RawRangeIndex = Index >> 1;
>
> + Endpoints[Index] =
> RawMemoryRanges[RawRangeIndex].BaseAddress;
>
> + Endpoints[Index + 1] =
> RawMemoryRanges[RawRangeIndex].BaseAddress +
> RawMemoryRanges[RawRangeIndex].Length - 1;
>
> + }
>
> +
>
> + qsort (Endpoints, *EndPointCount, sizeof (UINT64),
> CompareFuncUint64);
>
> + RemoveDuplicatesInSortedArray (Endpoints,
> EndPointCount);
>
> +}
>
> +
>
> +/**
>
> + Convert the MTRR BASE/MASK array to memory ranges.
>
> +
>
> + @param DefaultType Default memory type.
>
> + @param PhysicalAddressBits Physical address bits.
>
> + @param RawMemoryRanges Raw memory ranges.
>
> + @param RawMemoryRangeCount Count of raw memory
> ranges.
>
> + @param MemoryRanges Memory ranges.
>
> + @param MemoryRangeCount Count of memory ranges.
>
> +**/
>
> +VOID
>
> +GetEffectiveMemoryRanges (
>
> + IN MTRR_MEMORY_CACHE_TYPE DefaultType,
>
> + IN UINT32 PhysicalAddressBits,
>
> + IN MTRR_MEMORY_RANGE *RawMemoryRanges,
>
> + IN UINT32 RawMemoryRangeCount,
>
> + OUT MTRR_MEMORY_RANGE *MemoryRanges,
>
> + OUT UINTN *MemoryRangeCount
>
> + )
>
> +{
>
> + UINTN Index;
>
> + UINT32 AllEndPointsCount;
>
> + UINT64 *AllEndPointsInclusive;
>
> + UINT32 AllRangePiecesCountMax;
>
> + MTRR_MEMORY_RANGE *AllRangePieces;
>
> + UINTN AllRangePiecesCountActual;
>
> + UINT64 OverlapBitFlag1;
>
> + UINT64 OverlapBitFlag2;
>
> + INT32 OverlapFlagRelation;
>
> +
>
> + if (RawMemoryRangeCount == 0) {
>
> + MemoryRanges[0].BaseAddress = 0;
>
> + MemoryRanges[0].Length = (1ull <<
> PhysicalAddressBits);
>
> + MemoryRanges[0].Type = DefaultType;
>
> + *MemoryRangeCount = 1;
>
> + return;
>
> + }
>
> +
>
> + AllEndPointsCount = RawMemoryRangeCount <<
> 1;
>
> + AllEndPointsInclusive = calloc
> (AllEndPointsCount, sizeof (UINT64));
>
> + AllRangePiecesCountMax = RawMemoryRangeCount * 3
> + 1;
>
> + AllRangePieces = calloc
> (AllRangePiecesCountMax, sizeof (MTRR_MEMORY_RANGE));
>
> + CollectEndpoints (AllEndPointsInclusive,
> &AllEndPointsCount, RawMemoryRanges,
> RawMemoryRangeCount);
>
> +
>
> + for (Index = 0, AllRangePiecesCountActual = 0; Index
> < AllEndPointsCount - 1; Index++) {
>
> + OverlapBitFlag1 = GetOverlapBitFlag
> (RawMemoryRanges, RawMemoryRangeCount,
> AllEndPointsInclusive[Index]);
>
> + OverlapBitFlag2 = GetOverlapBitFlag
> (RawMemoryRanges, RawMemoryRangeCount,
> AllEndPointsInclusive[Index + 1]);
>
> + OverlapFlagRelation = CheckOverlapBitFlagsRelation
> (OverlapBitFlag1, OverlapBitFlag2);
>
> + switch (OverlapFlagRelation) {
>
> + case 0: // [1, 2]
>
> +
> AllRangePieces[AllRangePiecesCountActual].BaseAddress =
> AllEndPointsInclusive[Index];
>
> +
> AllRangePieces[AllRangePiecesCountActual].Length =
> AllEndPointsInclusive[Index + 1] -
> AllEndPointsInclusive[Index] + 1;
>
> + AllRangePiecesCountActual++;
>
> + break;
>
> + case 1: // [1, 2)
>
> +
> AllRangePieces[AllRangePiecesCountActual].BaseAddress =
> AllEndPointsInclusive[Index];
>
> +
> AllRangePieces[AllRangePiecesCountActual].Length =
> (AllEndPointsInclusive[Index + 1] - 1) -
> AllEndPointsInclusive[Index] + 1;
>
> + AllRangePiecesCountActual++;
>
> + break;
>
> + case 2: // (1, 2]
>
> +
> AllRangePieces[AllRangePiecesCountActual].BaseAddress =
> AllEndPointsInclusive[Index] + 1;
>
> +
> AllRangePieces[AllRangePiecesCountActual].Length =
> AllEndPointsInclusive[Index + 1] -
> (AllEndPointsInclusive[Index] + 1) + 1;
>
> + AllRangePiecesCountActual++;
>
> +
>
> + if (!IsEndpointInRanges
> (AllEndPointsInclusive[Index], AllRangePieces,
> AllRangePiecesCountActual)) {
>
> +
> AllRangePieces[AllRangePiecesCountActual].BaseAddress =
> AllEndPointsInclusive[Index];
>
> +
> AllRangePieces[AllRangePiecesCountActual].Length =
> 1;
>
> + AllRangePiecesCountActual++;
>
> + }
>
> + break;
>
> + case 3: // (1, 2)
>
> +
> AllRangePieces[AllRangePiecesCountActual].BaseAddress =
> AllEndPointsInclusive[Index] + 1;
>
> +
> AllRangePieces[AllRangePiecesCountActual].Length =
> (AllEndPointsInclusive[Index + 1] - 1) -
> (AllEndPointsInclusive[Index] + 1) + 1;
>
> + if
> (AllRangePieces[AllRangePiecesCountActual].Length == 0)
> // Only in case 3 can exists Length=0, we should skip
> such "segment".
>
> + break;
>
> + AllRangePiecesCountActual++;
>
> + if (!IsEndpointInRanges
> (AllEndPointsInclusive[Index], AllRangePieces,
> AllRangePiecesCountActual)) {
>
> +
> AllRangePieces[AllRangePiecesCountActual].BaseAddress =
> AllEndPointsInclusive[Index];
>
> +
> AllRangePieces[AllRangePiecesCountActual].Length =
> 1;
>
> + AllRangePiecesCountActual++;
>
> + }
>
> + break;
>
> + default:
>
> + ASSERT (FALSE);
>
> + }
>
> + }
>
> +
>
> + for (Index = 0; Index < AllRangePiecesCountActual;
> Index++) {
>
> + DetermineMemoryCacheType (DefaultType,
> &AllRangePieces[Index], RawMemoryRanges,
> RawMemoryRangeCount);
>
> + }
>
> +
>
> + CompactAndExtendEffectiveMtrrMemoryRanges
> (DefaultType, PhysicalAddressBits, &AllRangePieces,
> &AllRangePiecesCountActual);
>
> + ASSERT (*MemoryRangeCount >=
> AllRangePiecesCountActual);
>
> + memcpy (MemoryRanges, AllRangePieces,
> AllRangePiecesCountActual * sizeof
> (MTRR_MEMORY_RANGE));
>
> + *MemoryRangeCount = AllRangePiecesCountActual;
>
> +
>
> + free (AllEndPointsInclusive);
>
> + free (AllRangePieces);
>
> +}
>
> diff --git a/UefiCpuPkg/Test/UefiCpuPkgHostTest.dsc
> b/UefiCpuPkg/Test/UefiCpuPkgHostTest.dsc
> new file mode 100644
> index 0000000000..8a5c456830
> --- /dev/null
> +++ b/UefiCpuPkg/Test/UefiCpuPkgHostTest.dsc
> @@ -0,0 +1,31 @@
> +## @file
>
> +# UefiCpuPkg DSC file used to build host-based unit
> tests.
>
> +#
>
> +# Copyright (c) 2020, Intel Corporation. All rights
> reserved.<BR>
>
> +# SPDX-License-Identifier: BSD-2-Clause-Patent
>
> +#
>
> +##
>
> +
>
> +[Defines]
>
> + PLATFORM_NAME = UefiCpuPkgHostTest
>
> + PLATFORM_GUID = E00B9599-5B74-4FF7-AB9F-
> 8183FB13B2F9
>
> + PLATFORM_VERSION = 0.1
>
> + DSC_SPECIFICATION = 0x00010005
>
> + OUTPUT_DIRECTORY = Build/UefiCpuPkg/HostTest
>
> + SUPPORTED_ARCHITECTURES = IA32|X64
>
> + BUILD_TARGETS = NOOPT
>
> + SKUID_IDENTIFIER = DEFAULT
>
> +
>
> +!include
> UnitTestFrameworkPkg/UnitTestFrameworkPkgHost.dsc.inc
>
> +
>
> +[LibraryClasses]
>
> + MtrrLib|UefiCpuPkg/Library/MtrrLib/MtrrLib.inf
>
> +
>
> +[PcdsPatchableInModule]
>
> +
> gUefiCpuPkgTokenSpaceGuid.PcdCpuNumberOfReservedVariabl
> eMtrrs|0
>
> +
>
> +[Components]
>
> + #
>
> + # Build HOST_APPLICATION that tests the MtrrLib
>
> + #
>
> +
> UefiCpuPkg/Library/MtrrLib/UnitTest/MtrrLibUnitTestHost
> .inf
>
> --
> 2.27.0.windows.1
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH v2] UefiCpuPkg/MtrrLib/UnitTest: Add host based unit test
2020-07-24 6:41 [PATCH v2] UefiCpuPkg/MtrrLib/UnitTest: Add host based unit test Ni, Ray
2020-07-24 16:04 ` Laszlo Ersek
2020-07-24 16:23 ` Michael D Kinney
@ 2020-07-27 2:58 ` Dong, Eric
2 siblings, 0 replies; 4+ messages in thread
From: Dong, Eric @ 2020-07-27 2:58 UTC (permalink / raw)
To: Ni, Ray, devel@edk2.groups.io
Cc: Kinney, Michael D, Shao, Ming, Laszlo Ersek, Sean Brogan,
Bret Barkelew, Yao, Jiewen
Reviewed-by: Eric Dong <eric.dong@intel.com>
> -----Original Message-----
> From: Ni, Ray <ray.ni@intel.com>
> Sent: Friday, July 24, 2020 2:42 PM
> To: devel@edk2.groups.io
> Cc: Kinney, Michael D <michael.d.kinney@intel.com>; Shao, Ming
> <ming.shao@intel.com>; Dong, Eric <eric.dong@intel.com>; Laszlo Ersek
> <lersek@redhat.com>; Sean Brogan <sean.brogan@microsoft.com>; Bret
> Barkelew <Bret.Barkelew@microsoft.com>; Yao, Jiewen
> <jiewen.yao@intel.com>
> Subject: [PATCH v2] UefiCpuPkg/MtrrLib/UnitTest: Add host based unit test
>
> Add host based unit tests for the MtrrLib services.
> The BaseLib services AsmCpuid(), AsmReadMsr64(), and
> AsmWriteMsr64() are hooked and provide simple emulation
> of the CPUID leafs and MSRs required by the MtrrLib to
> run as a host based unit test.
>
> Test cases are developed for each of the API.
>
> For the most important APIs MtrrSetMemoryAttributesInMtrrSettings()
> and MtrrSetMemoryAttributeInMtrrSettings(), random inputs are
> generated and fed to the APIs to make sure the implementation is
> good. The test application accepts an optional parameter which
> specifies how many iterations of feeding random inputs to the two
> APIs. The overall number of test cases increases when the iteration
> increases. Default iteration is 10 when no parameter is specified.
>
> Signed-off-by: Ray Ni <ray.ni@intel.com>
> Signed-off-by: Michael D Kinney <michael.d.kinney@intel.com>
> Signed-off-by: Ming Shao <ming.shao@intel.com>
> Cc: Michael D Kinney <michael.d.kinney@intel.com>
> Cc: Ming Shao <ming.shao@intel.com>
> Cc: Eric Dong <eric.dong@intel.com>
> Cc: Ray Ni <ray.ni@intel.com>
> Cc: Laszlo Ersek <lersek@redhat.com>
> Cc: Sean Brogan <sean.brogan@microsoft.com>
> Cc: Bret Barkelew <Bret.Barkelew@microsoft.com>
> Cc: Jiewen Yao <jiewen.yao@intel.com>
> ---
> .../MtrrLib/UnitTest/MtrrLibUnitTest.c | 1140 +++++++++++++++++
> .../MtrrLib/UnitTest/MtrrLibUnitTest.h | 171 +++
> .../MtrrLib/UnitTest/MtrrLibUnitTestHost.inf | 39 +
> UefiCpuPkg/Library/MtrrLib/UnitTest/Support.c | 913 +++++++++++++
> UefiCpuPkg/Test/UefiCpuPkgHostTest.dsc | 31 +
> 5 files changed, 2294 insertions(+)
> create mode 100644 UefiCpuPkg/Library/MtrrLib/UnitTest/MtrrLibUnitTest.c
> create mode 100644
> UefiCpuPkg/Library/MtrrLib/UnitTest/MtrrLibUnitTest.h
> create mode 100644
> UefiCpuPkg/Library/MtrrLib/UnitTest/MtrrLibUnitTestHost.inf
> create mode 100644 UefiCpuPkg/Library/MtrrLib/UnitTest/Support.c
> create mode 100644 UefiCpuPkg/Test/UefiCpuPkgHostTest.dsc
>
> diff --git a/UefiCpuPkg/Library/MtrrLib/UnitTest/MtrrLibUnitTest.c
> b/UefiCpuPkg/Library/MtrrLib/UnitTest/MtrrLibUnitTest.c
> new file mode 100644
> index 0000000000..2eac41fc74
> --- /dev/null
> +++ b/UefiCpuPkg/Library/MtrrLib/UnitTest/MtrrLibUnitTest.c
> @@ -0,0 +1,1140 @@
> +/** @file
>
> + Unit tests of the MtrrLib instance of the MtrrLib class
>
> +
>
> + Copyright (c) 2020, Intel Corporation. All rights reserved.<BR>
>
> + 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 },
>
> +};
>
> +
>
> +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 MtrrSetMemoryAttribute()
>
> +
>
> + @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
>
> +UnitTestMtrrSetMemoryAttributesInMtrrSettings (
>
> + 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_SETTINGS *Mtrrs[2];
>
> +
>
> + SystemParameter = (MTRR_LIB_SYSTEM_PARAMETER *) Context;
>
> + GenerateRandomMemoryTypeCombination (
>
> + SystemParameter->VariableMtrrCount - PatchPcdGet32
> (PcdCpuNumberOfReservedVariableMtrrs),
>
> + &UcCount, &WtCount, &WbCount, &WpCount, &WcCount
>
> + );
>
> + GenerateValidAndConfigurableMtrrPairs (
>
> + SystemParameter->PhysicalAddressBits, RawMtrrRange,
>
> + UcCount, WtCount, WbCount, WpCount, WcCount
>
> + );
>
> +
>
> + ExpectedVariableMtrrUsage = UcCount + WtCount + WbCount + WpCount
> + WcCount;
>
> + ExpectedMemoryRangesCount = ARRAY_SIZE (ExpectedMemoryRanges);
>
> + GetEffectiveMemoryRanges (
>
> + SystemParameter->DefaultCacheType,
>
> + SystemParameter->PhysicalAddressBits,
>
> + 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->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);
>
> +
>
> + 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;
>
> +
>
> + 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_FALSE (IsMtrrSupported ());
>
> +
>
> + //
>
> + // MTRR capability on in CPUID leaf, but no fixed MTRRs.
>
> + //
>
> + SystemParameter.MtrrSupported = TRUE;
>
> + SystemParameter.VariableMtrrCount = 7;
>
> + SystemParameter.FixedMtrrSupported = FALSE;
>
> + InitializeMtrrRegs (&SystemParameter);
>
> + UT_ASSERT_FALSE (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, 0);
>
> +
>
> + //
>
> + // 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 (Result, &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 (Result, &FixedSettings);
>
> + UT_ASSERT_MEM_EQUAL (&ExpectedFixedSettings, &FixedSettings,
> sizeof (ExpectedFixedSettings));
>
> +
>
> + return UNIT_TEST_PASSED;
>
> +}
>
> +
>
> +/**
>
> + 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_VARIABLE_SETTING
> VariableMtrr[MTRR_NUMBER_OF_VARIABLE_MTRR];
>
> + UINT32 Index;
>
> + MTRR_LIB_SYSTEM_PARAMETER SystemParameter;
>
> + MTRR_LIB_TEST_CONTEXT *LocalContext;
>
> +
>
> + LocalContext = (MTRR_LIB_TEST_CONTEXT *) Context;
>
> +
>
> + CopyMem (&SystemParameter, LocalContext->SystemParameter, sizeof
> (SystemParameter));
>
> + InitializeMtrrRegs (&SystemParameter);
>
> +
>
> + for (Index = 0; Index < SystemParameter.VariableMtrrCount; Index++) {
>
> + GenerateRandomMtrrPair (SystemParameter.PhysicalAddressBits,
> GenerateRandomCacheType (), &VariableMtrr[Index], NULL);
>
> + AsmWriteMsr64 (MSR_IA32_MTRR_PHYSBASE0 + (Index << 1),
> VariableMtrr[Index].Base);
>
> + AsmWriteMsr64 (MSR_IA32_MTRR_PHYSMASK0 + (Index << 1),
> VariableMtrr[Index].Mask);
>
> + }
>
> + Result = MtrrGetAllMtrrs (&Mtrrs);
>
> + UT_ASSERT_EQUAL (Result, &Mtrrs);
>
> + UT_ASSERT_MEM_EQUAL (Mtrrs.Variables.Mtrr, VariableMtrr, 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 (Result, &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 Mtrrs;
>
> + UINT32 Index;
>
> + MSR_IA32_MTRR_DEF_TYPE_REGISTER Default;
>
> + MTRR_LIB_SYSTEM_PARAMETER SystemParameter;
>
> + MTRR_LIB_TEST_CONTEXT *LocalContext;
>
> +
>
> + 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 (&Mtrrs, sizeof (Mtrrs));
>
> + Mtrrs.MtrrDefType = Default.Uint64;
>
> + for (Index = 0; Index < SystemParameter.VariableMtrrCount; Index++) {
>
> + GenerateRandomMtrrPair (SystemParameter.PhysicalAddressBits,
> GenerateRandomCacheType (), &Mtrrs.Variables.Mtrr[Index], NULL);
>
> + }
>
> + Result = MtrrSetAllMtrrs (&Mtrrs);
>
> + UT_ASSERT_EQUAL (Result, &Mtrrs);
>
> +
>
> + UT_ASSERT_EQUAL (AsmReadMsr64 (MSR_IA32_MTRR_DEF_TYPE),
> Mtrrs.MtrrDefType);
>
> + for (Index = 0; Index < SystemParameter.VariableMtrrCount; Index++) {
>
> + UT_ASSERT_EQUAL (AsmReadMsr64 (MSR_IA32_MTRR_PHYSBASE0 +
> (Index << 1)), Mtrrs.Variables.Mtrr[Index].Base);
>
> + UT_ASSERT_EQUAL (AsmReadMsr64 (MSR_IA32_MTRR_PHYSMASK0 +
> (Index << 1)), Mtrrs.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);
>
> +
>
> + SystemParameter.MtrrSupported = TRUE;
>
> + SystemParameter.FixedMtrrSupported = FALSE;
>
> + InitializeMtrrRegs (&SystemParameter);
>
> + Result = MtrrGetDefaultMemoryType ();
>
> + UT_ASSERT_EQUAL (Result, CacheUncacheable);
>
> +
>
> + SystemParameter.MtrrSupported = TRUE;
>
> + SystemParameter.FixedMtrrSupported = TRUE;
>
> + SystemParameter.VariableMtrrCount = 0;
>
> + InitializeMtrrRegs (&SystemParameter);
>
> + Result = MtrrGetDefaultMemoryType ();
>
> + UT_ASSERT_EQUAL (Result, CacheUncacheable);
>
> +
>
> + return UNIT_TEST_PASSED;
>
> +}
>
> +
>
> +/**
>
> + Unit test of MtrrLib service MtrrSetMemoryAttributeInMtrrSettings().
>
> +
>
> + @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
>
> +UnitTestMtrrSetMemoryAttributeInMtrrSettings (
>
> + 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_SETTINGS *Mtrrs[2];
>
> +
>
> + SystemParameter = (MTRR_LIB_SYSTEM_PARAMETER *) Context;
>
> + GenerateRandomMemoryTypeCombination (
>
> + SystemParameter->VariableMtrrCount - PatchPcdGet32
> (PcdCpuNumberOfReservedVariableMtrrs),
>
> + &UcCount, &WtCount, &WbCount, &WpCount, &WcCount
>
> + );
>
> + GenerateValidAndConfigurableMtrrPairs (
>
> + SystemParameter->PhysicalAddressBits, RawMtrrRange,
>
> + UcCount, WtCount, WbCount, WpCount, WcCount
>
> + );
>
> +
>
> + ExpectedVariableMtrrUsage = UcCount + WtCount + WbCount + WpCount
> + WcCount;
>
> + ExpectedMemoryRangesCount = ARRAY_SIZE (ExpectedMemoryRanges);
>
> + GetEffectiveMemoryRanges (
>
> + SystemParameter->DefaultCacheType,
>
> + SystemParameter->PhysicalAddressBits,
>
> + 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->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);
>
> +
>
> + 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.
>
> +**/
>
> +UNIT_TEST_STATUS
>
> +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);
>
> + return UNIT_TEST_PASSED;
>
> +}
>
> +
>
> +/**
>
> + 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;
>
> +
>
> + DEBUG ((DEBUG_INFO, "%a v%a\n", UNIT_TEST_APP_NAME,
> UNIT_TEST_APP_VERSION));
>
> +
>
> + //
>
> + // 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,
> InitializeMtrrRegs, NULL, &mSystemParameters[SystemIndex]);
>
> + AddTestCase (MtrrApiTests, "Test
> MtrrSetMemoryAttributeInMtrrSettings",
> "MtrrSetMemoryAttributeInMtrrSettings",
> UnitTestMtrrSetMemoryAttributeInMtrrSettings, InitializeMtrrRegs, NULL,
> &mSystemParameters[SystemIndex]);
>
> + AddTestCase (MtrrApiTests, "Test
> MtrrSetMemoryAttributesInMtrrSettings",
> "MtrrSetMemoryAttributesInMtrrSettings",
> UnitTestMtrrSetMemoryAttributesInMtrrSettings, InitializeMtrrRegs, NULL,
> &mSystemParameters[SystemIndex]);
>
> + }
>
> + }
>
> + //
>
> + // Execute the tests.
>
> + //
>
> + srand ((unsigned int) time (NULL));
>
> + 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 Iteration;
>
> +
>
> + //
>
> + // First parameter specifies the test iterations.
>
> + // Default is 10.
>
> + //
>
> + Iteration = 10;
>
> + if (Argc == 2) {
>
> + Iteration = atoi (Argv[1]);
>
> + }
>
> + return UnitTestingEntry (Iteration);
>
> +}
>
> diff --git a/UefiCpuPkg/Library/MtrrLib/UnitTest/MtrrLibUnitTest.h
> b/UefiCpuPkg/Library/MtrrLib/UnitTest/MtrrLibUnitTest.h
> new file mode 100644
> index 0000000000..25d4269589
> --- /dev/null
> +++ b/UefiCpuPkg/Library/MtrrLib/UnitTest/MtrrLibUnitTest.h
> @@ -0,0 +1,171 @@
> +/** @file
>
> +
>
> + Copyright (c) 2020, Intel Corporation. All rights reserved.<BR>
>
> + SPDX-License-Identifier: BSD-2-Clause-Patent
>
> +
>
> +**/
>
> +
>
> +#ifndef _MTRR_SUPPORT_H_
>
> +#define _MTRR_SUPPORT_H_
>
> +
>
> +#include <stdio.h>
>
> +#include <stdlib.h>
>
> +#include <string.h>
>
> +#include <stdarg.h>
>
> +#include <stddef.h>
>
> +#include <setjmp.h>
>
> +#include <cmocka.h>
>
> +#include <time.h>
>
> +
>
> +#include <Uefi.h>
>
> +#include <Library/BaseLib.h>
>
> +#include <Library/BaseMemoryLib.h>
>
> +#include <Library/DebugLib.h>
>
> +#include <Library/UnitTestLib.h>
>
> +#include <Library/MtrrLib.h>
>
> +#include <Library/UnitTestHostBaseLib.h>
>
> +
>
> +#include <Register/ArchitecturalMsr.h>
>
> +#include <Register/Cpuid.h>
>
> +#include <Register/Msr.h>
>
> +
>
> +#define UNIT_TEST_APP_NAME "MtrrLib Unit Tests"
>
> +#define UNIT_TEST_APP_VERSION "1.0"
>
> +
>
> +#define SCRATCH_BUFFER_SIZE SIZE_16KB
>
> +
>
> +typedef struct {
>
> + UINT8 PhysicalAddressBits;
>
> + BOOLEAN MtrrSupported;
>
> + BOOLEAN FixedMtrrSupported;
>
> + MTRR_MEMORY_CACHE_TYPE DefaultCacheType;
>
> + UINT32 VariableMtrrCount;
>
> +} MTRR_LIB_SYSTEM_PARAMETER;
>
> +
>
> +extern UINT32 mFixedMtrrsIndex[];
>
> +
>
> +/**
>
> + Initialize the MTRR registers.
>
> +
>
> + @param SystemParameter System parameter that controls the MTRR
> registers initialization.
>
> +**/
>
> +UNIT_TEST_STATUS
>
> +EFIAPI
>
> +InitializeMtrrRegs (
>
> + IN MTRR_LIB_SYSTEM_PARAMETER *SystemParameter
>
> + );
>
> +
>
> +/**
>
> + Return a random memory cache type.
>
> +**/
>
> +MTRR_MEMORY_CACHE_TYPE
>
> +GenerateRandomCacheType (
>
> + VOID
>
> + );
>
> +
>
> +/**
>
> + Generate random MTRRs.
>
> +
>
> + @param PhysicalAddressBits Physical address bits.
>
> + @param RawMemoryRanges Return the randomly generated MTRRs.
>
> + @param UcCount Count of Uncacheable MTRRs.
>
> + @param WtCount Count of Write Through MTRRs.
>
> + @param WbCount Count of Write Back MTRRs.
>
> + @param WpCount Count of Write Protected MTRRs.
>
> + @param WcCount Count of Write Combining MTRRs.
>
> +**/
>
> +VOID
>
> +GenerateValidAndConfigurableMtrrPairs (
>
> + IN UINT32 PhysicalAddressBits,
>
> + IN OUT MTRR_MEMORY_RANGE *RawMemoryRanges,
>
> + IN UINT32 UcCount,
>
> + IN UINT32 WtCount,
>
> + IN UINT32 WbCount,
>
> + IN UINT32 WpCount,
>
> + IN UINT32 WcCount
>
> + );
>
> +
>
> +/**
>
> + Convert the MTRR BASE/MASK array to memory ranges.
>
> +
>
> + @param DefaultType Default memory type.
>
> + @param PhysicalAddressBits Physical address bits.
>
> + @param RawMemoryRanges Raw memory ranges.
>
> + @param RawMemoryRangeCount Count of raw memory ranges.
>
> + @param MemoryRanges Memory ranges.
>
> + @param MemoryRangeCount Count of memory ranges.
>
> +**/
>
> +VOID
>
> +GetEffectiveMemoryRanges (
>
> + IN MTRR_MEMORY_CACHE_TYPE DefaultType,
>
> + IN UINT32 PhysicalAddressBits,
>
> + IN MTRR_MEMORY_RANGE *RawMemoryRanges,
>
> + IN UINT32 RawMemoryRangeCount,
>
> + OUT MTRR_MEMORY_RANGE *MemoryRanges,
>
> + OUT UINTN *MemoryRangeCount
>
> + );
>
> +
>
> +/**
>
> + Generate random MTRR BASE/MASK for a specified type.
>
> +
>
> + @param PhysicalAddressBits Physical address bits.
>
> + @param CacheType Cache type.
>
> + @param MtrrPair Return the random MTRR.
>
> + @param MtrrMemoryRange Return the random memory range.
>
> +**/
>
> +VOID
>
> +GenerateRandomMtrrPair (
>
> + IN UINT32 PhysicalAddressBits,
>
> + IN MTRR_MEMORY_CACHE_TYPE CacheType,
>
> + OUT MTRR_VARIABLE_SETTING *MtrrPair, OPTIONAL
>
> + OUT MTRR_MEMORY_RANGE *MtrrMemoryRange OPTIONAL
>
> + );
>
> +
>
> +/**
>
> + Collect the test result.
>
> +
>
> + @param DefaultType Default memory type.
>
> + @param PhysicalAddressBits Physical address bits.
>
> + @param VariableMtrrCount Count of variable MTRRs.
>
> + @param Mtrrs MTRR settings to collect from.
>
> + @param Ranges Return the memory ranges.
>
> + @param RangeCount Return the count of memory ranges.
>
> + @param MtrrCount Return the count of variable MTRRs being used.
>
> +**/
>
> +VOID
>
> +CollectTestResult (
>
> + IN MTRR_MEMORY_CACHE_TYPE DefaultType,
>
> + IN UINT32 PhysicalAddressBits,
>
> + IN UINT32 VariableMtrrCount,
>
> + IN MTRR_SETTINGS *Mtrrs,
>
> + OUT MTRR_MEMORY_RANGE *Ranges,
>
> + IN OUT UINTN *RangeCount,
>
> + OUT UINT32 *MtrrCount
>
> + );
>
> +
>
> +/**
>
> + Return a 64bit random number.
>
> +
>
> + @param Start Start of the random number range.
>
> + @param Limit Limit of the random number range.
>
> + @return 64bit random number
>
> +**/
>
> +UINT64
>
> +Random64 (
>
> + UINT64 Start,
>
> + UINT64 Limit
>
> + );
>
> +
>
> +/**
>
> + Return a 32bit random number.
>
> +
>
> + @param Start Start of the random number range.
>
> + @param Limit Limit of the random number range.
>
> + @return 32bit random number
>
> +**/
>
> +UINT32
>
> +Random32 (
>
> + UINT32 Start,
>
> + UINT32 Limit
>
> + );
>
> +#endif
>
> diff --git a/UefiCpuPkg/Library/MtrrLib/UnitTest/MtrrLibUnitTestHost.inf
> b/UefiCpuPkg/Library/MtrrLib/UnitTest/MtrrLibUnitTestHost.inf
> new file mode 100644
> index 0000000000..447238dc81
> --- /dev/null
> +++ b/UefiCpuPkg/Library/MtrrLib/UnitTest/MtrrLibUnitTestHost.inf
> @@ -0,0 +1,39 @@
> +## @file
>
> +# Unit tests of the MtrrLib instance of the MtrrLib class
>
> +#
>
> +# Copyright (c) 2020, Intel Corporation. All rights reserved.<BR>
>
> +# SPDX-License-Identifier: BSD-2-Clause-Patent
>
> +##
>
> +
>
> +[Defines]
>
> + INF_VERSION = 0x00010006
>
> + BASE_NAME = MtrrLibUnitTestHost
>
> + FILE_GUID = A1542D84-B64D-4847-885E-0509084376AB
>
> + MODULE_TYPE = HOST_APPLICATION
>
> + VERSION_STRING = 1.0
>
> +
>
> +#
>
> +# The following information is for reference only and not required by the
> build tools.
>
> +#
>
> +# VALID_ARCHITECTURES = IA32 X64
>
> +#
>
> +
>
> +[Sources]
>
> + MtrrLibUnitTest.c
>
> + MtrrLibUnitTest.h
>
> + Support.c
>
> +
>
> +[Packages]
>
> + MdePkg/MdePkg.dec
>
> + UefiCpuPkg/UefiCpuPkg.dec
>
> + UnitTestFrameworkPkg/UnitTestFrameworkPkg.dec
>
> +
>
> +[LibraryClasses]
>
> + BaseLib
>
> + BaseMemoryLib
>
> + DebugLib
>
> + MtrrLib
>
> + UnitTestLib
>
> +
>
> +[Pcd]
>
> + gUefiCpuPkgTokenSpaceGuid.PcdCpuNumberOfReservedVariableMtrrs
> ## SOMETIMES_CONSUMES
>
> diff --git a/UefiCpuPkg/Library/MtrrLib/UnitTest/Support.c
> b/UefiCpuPkg/Library/MtrrLib/UnitTest/Support.c
> new file mode 100644
> index 0000000000..9fe4b0278e
> --- /dev/null
> +++ b/UefiCpuPkg/Library/MtrrLib/UnitTest/Support.c
> @@ -0,0 +1,913 @@
> +/** @file
>
> + Unit tests of the MtrrLib instance of the MtrrLib class
>
> +
>
> + Copyright (c) 2018 - 2020, Intel Corporation. All rights reserved.<BR>
>
> + SPDX-License-Identifier: BSD-2-Clause-Patent
>
> +
>
> +**/
>
> +
>
> +#include "MtrrLibUnitTest.h"
>
> +
>
> +MTRR_MEMORY_CACHE_TYPE mMemoryCacheTypes[] = {
>
> + CacheUncacheable, CacheWriteCombining, CacheWriteThrough,
> CacheWriteProtected, CacheWriteBack
>
> + };
>
> +
>
> +UINT64 mFixedMtrrsValue[MTRR_NUMBER_OF_FIXED_MTRR];
>
> +MSR_IA32_MTRR_PHYSBASE_REGISTER
> mVariableMtrrsPhysBase[MTRR_NUMBER_OF_VARIABLE_MTRR];
>
> +MSR_IA32_MTRR_PHYSMASK_REGISTER
> mVariableMtrrsPhysMask[MTRR_NUMBER_OF_VARIABLE_MTRR];
>
> +MSR_IA32_MTRR_DEF_TYPE_REGISTER mDefTypeMsr;
>
> +MSR_IA32_MTRRCAP_REGISTER mMtrrCapMsr;
>
> +CPUID_VERSION_INFO_EDX mCpuidVersionInfoEdx;
>
> +CPUID_VIR_PHY_ADDRESS_SIZE_EAX mCpuidVirPhyAddressSizeEax;
>
> +
>
> +/**
>
> + Retrieves CPUID information.
>
> +
>
> + Executes the CPUID instruction with EAX set to the value specified by
> Index.
>
> + This function always returns Index.
>
> + If Eax is not NULL, then the value of EAX after CPUID is returned in Eax.
>
> + If Ebx is not NULL, then the value of EBX after CPUID is returned in Ebx.
>
> + If Ecx is not NULL, then the value of ECX after CPUID is returned in Ecx.
>
> + If Edx is not NULL, then the value of EDX after CPUID is returned in Edx.
>
> + This function is only available on IA-32 and x64.
>
> +
>
> + @param Index The 32-bit value to load into EAX prior to invoking the
> CPUID
>
> + instruction.
>
> + @param Eax The pointer to the 32-bit EAX value returned by the CPUID
>
> + instruction. This is an optional parameter that may be NULL.
>
> + @param Ebx The pointer to the 32-bit EBX value returned by the CPUID
>
> + instruction. This is an optional parameter that may be NULL.
>
> + @param Ecx The pointer to the 32-bit ECX value returned by the CPUID
>
> + instruction. This is an optional parameter that may be NULL.
>
> + @param Edx The pointer to the 32-bit EDX value returned by the CPUID
>
> + instruction. This is an optional parameter that may be NULL.
>
> +
>
> + @return Index.
>
> +
>
> +**/
>
> +UINT32
>
> +EFIAPI
>
> +UnitTestMtrrLibAsmCpuid (
>
> + IN UINT32 Index,
>
> + OUT UINT32 *Eax, OPTIONAL
>
> + OUT UINT32 *Ebx, OPTIONAL
>
> + OUT UINT32 *Ecx, OPTIONAL
>
> + OUT UINT32 *Edx OPTIONAL
>
> + )
>
> +{
>
> + switch (Index) {
>
> + case CPUID_VERSION_INFO:
>
> + if (Edx != NULL) {
>
> + *Edx = mCpuidVersionInfoEdx.Uint32;
>
> + }
>
> + return Index;
>
> + break;
>
> + case CPUID_EXTENDED_FUNCTION:
>
> + if (Eax != NULL) {
>
> + *Eax = CPUID_VIR_PHY_ADDRESS_SIZE;
>
> + }
>
> + return Index;
>
> + break;
>
> + case CPUID_VIR_PHY_ADDRESS_SIZE:
>
> + if (Eax != NULL) {
>
> + *Eax = mCpuidVirPhyAddressSizeEax.Uint32;
>
> + }
>
> + return Index;
>
> + break;
>
> + }
>
> +
>
> + //
>
> + // Should never fall through to here
>
> + //
>
> + ASSERT(FALSE);
>
> + return Index;
>
> +}
>
> +
>
> +/**
>
> + Returns a 64-bit Machine Specific Register(MSR).
>
> +
>
> + Reads and returns the 64-bit MSR specified by Index. No parameter
> checking is
>
> + performed on Index, and some Index values may cause CPU exceptions.
> The
>
> + caller must either guarantee that Index is valid, or the caller must set up
>
> + exception handlers to catch the exceptions. This function is only available
>
> + on IA-32 and x64.
>
> +
>
> + @param MsrIndex The 32-bit MSR index to read.
>
> +
>
> + @return The value of the MSR identified by MsrIndex.
>
> +
>
> +**/
>
> +UINT64
>
> +EFIAPI
>
> +UnitTestMtrrLibAsmReadMsr64(
>
> + IN UINT32 MsrIndex
>
> + )
>
> +{
>
> + UINT32 Index;
>
> +
>
> + for (Index = 0; Index < ARRAY_SIZE (mFixedMtrrsValue); Index++) {
>
> + if (MsrIndex == mFixedMtrrsIndex[Index]) {
>
> + return mFixedMtrrsValue[Index];
>
> + }
>
> + }
>
> +
>
> + if ((MsrIndex >= MSR_IA32_MTRR_PHYSBASE0) &&
>
> + (MsrIndex <= MSR_IA32_MTRR_PHYSMASK0 +
> (MTRR_NUMBER_OF_VARIABLE_MTRR << 1))) {
>
> + if (MsrIndex % 2 == 0) {
>
> + Index = (MsrIndex - MSR_IA32_MTRR_PHYSBASE0) >> 1;
>
> + return mVariableMtrrsPhysBase[Index].Uint64;
>
> + } else {
>
> + Index = (MsrIndex - MSR_IA32_MTRR_PHYSMASK0) >> 1;
>
> + return mVariableMtrrsPhysMask[Index].Uint64;
>
> + }
>
> + }
>
> +
>
> + if (MsrIndex == MSR_IA32_MTRR_DEF_TYPE) {
>
> + return mDefTypeMsr.Uint64;
>
> + }
>
> +
>
> + if (MsrIndex == MSR_IA32_MTRRCAP) {
>
> + return mMtrrCapMsr.Uint64;
>
> + }
>
> +
>
> + //
>
> + // Should never fall through to here
>
> + //
>
> + ASSERT(FALSE);
>
> + return 0;
>
> +}
>
> +
>
> +/**
>
> + Writes a 64-bit value to a Machine Specific Register(MSR), and returns the
>
> + value.
>
> +
>
> + Writes the 64-bit value specified by Value to the MSR specified by Index.
> The
>
> + 64-bit value written to the MSR is returned. No parameter checking is
>
> + performed on Index or Value, and some of these may cause CPU
> exceptions. The
>
> + caller must either guarantee that Index and Value are valid, or the caller
>
> + must establish proper exception handlers. This function is only available on
>
> + IA-32 and x64.
>
> +
>
> + @param MsrIndex The 32-bit MSR index to write.
>
> + @param Value The 64-bit value to write to the MSR.
>
> +
>
> + @return Value
>
> +
>
> +**/
>
> +UINT64
>
> +EFIAPI
>
> +UnitTestMtrrLibAsmWriteMsr64(
>
> + IN UINT32 MsrIndex,
>
> + IN UINT64 Value
>
> + )
>
> +{
>
> + UINT32 Index;
>
> +
>
> + for (Index = 0; Index < ARRAY_SIZE (mFixedMtrrsValue); Index++) {
>
> + if (MsrIndex == mFixedMtrrsIndex[Index]) {
>
> + mFixedMtrrsValue[Index] = Value;
>
> + return Value;
>
> + }
>
> + }
>
> +
>
> + if ((MsrIndex >= MSR_IA32_MTRR_PHYSBASE0) &&
>
> + (MsrIndex <= MSR_IA32_MTRR_PHYSMASK0 +
> (MTRR_NUMBER_OF_VARIABLE_MTRR << 1))) {
>
> + if (MsrIndex % 2 == 0) {
>
> + Index = (MsrIndex - MSR_IA32_MTRR_PHYSBASE0) >> 1;
>
> + mVariableMtrrsPhysBase[Index].Uint64 = Value;
>
> + return Value;
>
> + } else {
>
> + Index = (MsrIndex - MSR_IA32_MTRR_PHYSMASK0) >> 1;
>
> + mVariableMtrrsPhysMask[Index].Uint64 = Value;
>
> + return Value;
>
> + }
>
> + }
>
> +
>
> + if (MsrIndex == MSR_IA32_MTRR_DEF_TYPE) {
>
> + mDefTypeMsr.Uint64 = Value;
>
> + return Value;
>
> + }
>
> +
>
> + if (MsrIndex == MSR_IA32_MTRRCAP) {
>
> + mMtrrCapMsr.Uint64 = Value;
>
> + return Value;
>
> + }
>
> +
>
> + //
>
> + // Should never fall through to here
>
> + //
>
> + ASSERT(FALSE);
>
> + return 0;
>
> +}
>
> +
>
> +/**
>
> + Initialize MTRR registers.
>
> +**/
>
> +
>
> +/**
>
> + Initialize the MTRR registers.
>
> +
>
> + @param SystemParameter System parameter that controls the MTRR
> registers initialization.
>
> +**/
>
> +UNIT_TEST_STATUS
>
> +EFIAPI
>
> +InitializeMtrrRegs (
>
> + IN MTRR_LIB_SYSTEM_PARAMETER *SystemParameter
>
> + )
>
> +{
>
> + UINT32 Index;
>
> +
>
> + SetMem (mFixedMtrrsValue, sizeof (mFixedMtrrsValue),
> SystemParameter->DefaultCacheType);
>
> +
>
> + for (Index = 0; Index < ARRAY_SIZE (mVariableMtrrsPhysBase); Index++) {
>
> + mVariableMtrrsPhysBase[Index].Uint64 = 0;
>
> + mVariableMtrrsPhysBase[Index].Bits.Type = SystemParameter-
> >DefaultCacheType;
>
> + mVariableMtrrsPhysBase[Index].Bits.Reserved1 = 0;
>
> +
>
> + mVariableMtrrsPhysMask[Index].Uint64 = 0;
>
> + mVariableMtrrsPhysMask[Index].Bits.V = 0;
>
> + mVariableMtrrsPhysMask[Index].Bits.Reserved1 = 0;
>
> + }
>
> +
>
> + mDefTypeMsr.Bits.E = 1;
>
> + mDefTypeMsr.Bits.FE = 1;
>
> + mDefTypeMsr.Bits.Type = SystemParameter->DefaultCacheType;
>
> + mDefTypeMsr.Bits.Reserved1 = 0;
>
> + mDefTypeMsr.Bits.Reserved2 = 0;
>
> + mDefTypeMsr.Bits.Reserved3 = 0;
>
> +
>
> + mMtrrCapMsr.Bits.SMRR = 0;
>
> + mMtrrCapMsr.Bits.WC = 0;
>
> + mMtrrCapMsr.Bits.VCNT = SystemParameter->VariableMtrrCount;
>
> + mMtrrCapMsr.Bits.FIX = SystemParameter->FixedMtrrSupported;
>
> + mMtrrCapMsr.Bits.Reserved1 = 0;
>
> + mMtrrCapMsr.Bits.Reserved2 = 0;
>
> + mMtrrCapMsr.Bits.Reserved3 = 0;
>
> +
>
> + mCpuidVersionInfoEdx.Bits.MTRR = SystemParameter-
> >MtrrSupported;
>
> + mCpuidVirPhyAddressSizeEax.Bits.PhysicalAddressBits =
> SystemParameter->PhysicalAddressBits;
>
> +
>
> + //
>
> + // Hook BaseLib functions used by MtrrLib that require some emulation.
>
> + //
>
> + gUnitTestHostBaseLib.X86->AsmCpuid = UnitTestMtrrLibAsmCpuid;
>
> + gUnitTestHostBaseLib.X86->AsmReadMsr64 =
> UnitTestMtrrLibAsmReadMsr64;
>
> + gUnitTestHostBaseLib.X86->AsmWriteMsr64 =
> UnitTestMtrrLibAsmWriteMsr64;
>
> +
>
> + return UNIT_TEST_PASSED;
>
> +}
>
> +
>
> +/**
>
> + Collect the test result.
>
> +
>
> + @param DefaultType Default memory type.
>
> + @param PhysicalAddressBits Physical address bits.
>
> + @param VariableMtrrCount Count of variable MTRRs.
>
> + @param Mtrrs MTRR settings to collect from.
>
> + @param Ranges Return the memory ranges.
>
> + @param RangeCount Return the count of memory ranges.
>
> + @param MtrrCount Return the count of variable MTRRs being used.
>
> +**/
>
> +VOID
>
> +CollectTestResult (
>
> + IN MTRR_MEMORY_CACHE_TYPE DefaultType,
>
> + IN UINT32 PhysicalAddressBits,
>
> + IN UINT32 VariableMtrrCount,
>
> + IN MTRR_SETTINGS *Mtrrs,
>
> + OUT MTRR_MEMORY_RANGE *Ranges,
>
> + IN OUT UINTN *RangeCount,
>
> + OUT UINT32 *MtrrCount
>
> + )
>
> +{
>
> + UINTN Index;
>
> + UINT64 MtrrValidBitsMask;
>
> + UINT64 MtrrValidAddressMask;
>
> + MTRR_MEMORY_RANGE RawMemoryRanges[ARRAY_SIZE (Mtrrs-
> >Variables.Mtrr)];
>
> +
>
> + ASSERT (Mtrrs != NULL);
>
> + ASSERT (VariableMtrrCount <= ARRAY_SIZE (Mtrrs->Variables.Mtrr));
>
> +
>
> + MtrrValidBitsMask = (1ull << PhysicalAddressBits) - 1;
>
> + MtrrValidAddressMask = MtrrValidBitsMask & ~0xFFFull;
>
> +
>
> + *MtrrCount = 0;
>
> + for (Index = 0; Index < VariableMtrrCount; Index++) {
>
> + if (((MSR_IA32_MTRR_PHYSMASK_REGISTER *) &Mtrrs-
> >Variables.Mtrr[Index].Mask)->Bits.V == 1) {
>
> + RawMemoryRanges[*MtrrCount].BaseAddress = Mtrrs-
> >Variables.Mtrr[Index].Base & MtrrValidAddressMask;
>
> + RawMemoryRanges[*MtrrCount].Type =
>
> + ((MSR_IA32_MTRR_PHYSBASE_REGISTER *) &Mtrrs-
> >Variables.Mtrr[Index].Base)->Bits.Type;
>
> + RawMemoryRanges[*MtrrCount].Length =
>
> + ((~(Mtrrs->Variables.Mtrr[Index].Mask & MtrrValidAddressMask)) &
> MtrrValidBitsMask) + 1;
>
> + (*MtrrCount)++;
>
> + }
>
> + }
>
> +
>
> + GetEffectiveMemoryRanges (DefaultType, PhysicalAddressBits,
> RawMemoryRanges, *MtrrCount, Ranges, RangeCount);
>
> +}
>
> +
>
> +/**
>
> + Return a 32bit random number.
>
> +
>
> + @param Start Start of the random number range.
>
> + @param Limit Limit of the random number range.
>
> + @return 32bit random number
>
> +**/
>
> +UINT32
>
> +Random32 (
>
> + UINT32 Start,
>
> + UINT32 Limit
>
> + )
>
> +{
>
> + return (UINT32) (((double) rand () / RAND_MAX) * (Limit - Start)) + Start;
>
> +}
>
> +
>
> +/**
>
> + Return a 64bit random number.
>
> +
>
> + @param Start Start of the random number range.
>
> + @param Limit Limit of the random number range.
>
> + @return 64bit random number
>
> +**/
>
> +UINT64
>
> +Random64 (
>
> + UINT64 Start,
>
> + UINT64 Limit
>
> + )
>
> +{
>
> + return (UINT64) (((double) rand () / RAND_MAX) * (Limit - Start)) + Start;
>
> +}
>
> +
>
> +/**
>
> + Generate random MTRR BASE/MASK for a specified type.
>
> +
>
> + @param PhysicalAddressBits Physical address bits.
>
> + @param CacheType Cache type.
>
> + @param MtrrPair Return the random MTRR.
>
> + @param MtrrMemoryRange Return the random memory range.
>
> +**/
>
> +VOID
>
> +GenerateRandomMtrrPair (
>
> + IN UINT32 PhysicalAddressBits,
>
> + IN MTRR_MEMORY_CACHE_TYPE CacheType,
>
> + OUT MTRR_VARIABLE_SETTING *MtrrPair, OPTIONAL
>
> + OUT MTRR_MEMORY_RANGE *MtrrMemoryRange OPTIONAL
>
> + )
>
> +{
>
> + MSR_IA32_MTRR_PHYSBASE_REGISTER PhysBase;
>
> + MSR_IA32_MTRR_PHYSMASK_REGISTER PhysMask;
>
> + UINT32 SizeShift;
>
> + UINT32 BaseShift;
>
> + UINT64 RandomBoundary;
>
> + UINT64 MaxPhysicalAddress;
>
> + UINT64 RangeSize;
>
> + UINT64 RangeBase;
>
> + UINT64 PhysBasePhyMaskValidBitsMask;
>
> +
>
> + MaxPhysicalAddress = 1ull << PhysicalAddressBits;
>
> + do {
>
> + SizeShift = Random32 (12, PhysicalAddressBits - 1);
>
> + RangeSize = 1ull << SizeShift;
>
> +
>
> + BaseShift = Random32 (SizeShift, PhysicalAddressBits - 1);
>
> + RandomBoundary = Random64 (0, 1ull << (PhysicalAddressBits -
> BaseShift));
>
> + RangeBase = RandomBoundary << BaseShift;
>
> + } while (RangeBase < SIZE_1MB || RangeBase > MaxPhysicalAddress - 1);
>
> +
>
> + PhysBasePhyMaskValidBitsMask = (MaxPhysicalAddress - 1) &
> 0xfffffffffffff000ULL;
>
> +
>
> + PhysBase.Uint64 = 0;
>
> + PhysBase.Bits.Type = CacheType;
>
> + PhysBase.Uint64 |= RangeBase & PhysBasePhyMaskValidBitsMask;
>
> + PhysMask.Uint64 = 0;
>
> + PhysMask.Bits.V = 1;
>
> + PhysMask.Uint64 |= ((~RangeSize) + 1) &
> PhysBasePhyMaskValidBitsMask;
>
> +
>
> + if (MtrrPair != NULL) {
>
> + MtrrPair->Base = PhysBase.Uint64;
>
> + MtrrPair->Mask = PhysMask.Uint64;
>
> + }
>
> +
>
> + if (MtrrMemoryRange != NULL) {
>
> + MtrrMemoryRange->BaseAddress = RangeBase;
>
> + MtrrMemoryRange->Length = RangeSize;
>
> + MtrrMemoryRange->Type = CacheType;
>
> + }
>
> +}
>
> +
>
> +
>
> +/**
>
> + Check whether the Range overlaps with any one in Ranges.
>
> +
>
> + @param Range The memory range to check.
>
> + @param Ranges The memory ranges.
>
> + @param Count Count of memory ranges.
>
> +
>
> + @return TRUE when overlap exists.
>
> +**/
>
> +BOOLEAN
>
> +RangesOverlap (
>
> + IN MTRR_MEMORY_RANGE *Range,
>
> + IN MTRR_MEMORY_RANGE *Ranges,
>
> + IN UINTN Count
>
> + )
>
> +{
>
> + while (Count-- != 0) {
>
> + //
>
> + // Two ranges overlap when:
>
> + // 1. range#2.base is in the middle of range#1
>
> + // 2. range#1.base is in the middle of range#2
>
> + //
>
> + if ((Range->BaseAddress <= Ranges[Count].BaseAddress &&
> Ranges[Count].BaseAddress < Range->BaseAddress + Range->Length)
>
> + || (Ranges[Count].BaseAddress <= Range->BaseAddress && Range-
> >BaseAddress < Ranges[Count].BaseAddress + Ranges[Count].Length)) {
>
> + return TRUE;
>
> + }
>
> + }
>
> + return FALSE;
>
> +}
>
> +
>
> +/**
>
> + Generate random MTRRs.
>
> +
>
> + @param PhysicalAddressBits Physical address bits.
>
> + @param RawMemoryRanges Return the randomly generated MTRRs.
>
> + @param UcCount Count of Uncacheable MTRRs.
>
> + @param WtCount Count of Write Through MTRRs.
>
> + @param WbCount Count of Write Back MTRRs.
>
> + @param WpCount Count of Write Protected MTRRs.
>
> + @param WcCount Count of Write Combine MTRRs.
>
> +**/
>
> +VOID
>
> +GenerateValidAndConfigurableMtrrPairs (
>
> + IN UINT32 PhysicalAddressBits,
>
> + IN OUT MTRR_MEMORY_RANGE *RawMemoryRanges,
>
> + IN UINT32 UcCount,
>
> + IN UINT32 WtCount,
>
> + IN UINT32 WbCount,
>
> + IN UINT32 WpCount,
>
> + IN UINT32 WcCount
>
> + )
>
> +{
>
> + UINT32 Index;
>
> +
>
> + //
>
> + // 1. Generate UC, WT, WB in order.
>
> + //
>
> + for (Index = 0; Index < UcCount; Index++) {
>
> + GenerateRandomMtrrPair (PhysicalAddressBits, CacheUncacheable,
> NULL, &RawMemoryRanges[Index]);
>
> + }
>
> +
>
> + for (Index = UcCount; Index < UcCount + WtCount; Index++) {
>
> + GenerateRandomMtrrPair (PhysicalAddressBits, CacheWriteThrough,
> NULL, &RawMemoryRanges[Index]);
>
> + }
>
> +
>
> + for (Index = UcCount + WtCount; Index < UcCount + WtCount + WbCount;
> Index++) {
>
> + GenerateRandomMtrrPair (PhysicalAddressBits, CacheWriteBack, NULL,
> &RawMemoryRanges[Index]);
>
> + }
>
> +
>
> + //
>
> + // 2. Generate WP MTRR and DO NOT overlap with WT, WB.
>
> + //
>
> + for (Index = UcCount + WtCount + WbCount; Index < UcCount + WtCount
> + WbCount + WpCount; Index++) {
>
> + GenerateRandomMtrrPair (PhysicalAddressBits, CacheWriteProtected,
> NULL, &RawMemoryRanges[Index]);
>
> + while (RangesOverlap (&RawMemoryRanges[Index],
> &RawMemoryRanges[UcCount], WtCount + WbCount)) {
>
> + GenerateRandomMtrrPair (PhysicalAddressBits, CacheWriteProtected,
> NULL, &RawMemoryRanges[Index]);
>
> + }
>
> + }
>
> +
>
> + //
>
> + // 3. Generate WC MTRR and DO NOT overlap with WT, WB, WP.
>
> + //
>
> + for (Index = UcCount + WtCount + WbCount + WpCount; Index < UcCount
> + WtCount + WbCount + WpCount + WcCount; Index++) {
>
> + GenerateRandomMtrrPair (PhysicalAddressBits, CacheWriteCombining,
> NULL, &RawMemoryRanges[Index]);
>
> + while (RangesOverlap (&RawMemoryRanges[Index],
> &RawMemoryRanges[UcCount], WtCount + WbCount + WpCount)) {
>
> + GenerateRandomMtrrPair (PhysicalAddressBits, CacheWriteCombining,
> NULL, &RawMemoryRanges[Index]);
>
> + }
>
> + }
>
> +}
>
> +
>
> +/**
>
> + Return a random memory cache type.
>
> +**/
>
> +MTRR_MEMORY_CACHE_TYPE
>
> +GenerateRandomCacheType (
>
> + VOID
>
> + )
>
> +{
>
> + return mMemoryCacheTypes[Random32 (0, ARRAY_SIZE
> (mMemoryCacheTypes) - 1)];
>
> +}
>
> +
>
> +/**
>
> + Compare function used by qsort().
>
> +**/
>
> +
>
> +/**
>
> + Compare function used by qsort().
>
> +
>
> + @param Left Left operand to compare.
>
> + @param Right Right operand to compare.
>
> +
>
> + @retval 0 Left == Right
>
> + @retval -1 Left < Right
>
> + @retval 1 Left > Right
>
> +**/
>
> +INT32
>
> +CompareFuncUint64 (
>
> + CONST VOID * Left,
>
> + CONST VOID * Right
>
> + )
>
> +{
>
> + INT64 Delta;
>
> + Delta = (*(UINT64*)Left - *(UINT64*)Right);
>
> + if (Delta > 0) {
>
> + return 1;
>
> + } else if (Delta == 0) {
>
> + return 0;
>
> + } else {
>
> + return -1;
>
> + }
>
> +}
>
> +
>
> +/**
>
> + Determin the memory cache type for the Range.
>
> +
>
> + @param DefaultType Default cache type.
>
> + @param Range The memory range to determin the cache type.
>
> + @param Ranges The entire memory ranges.
>
> + @param RangeCount Count of the entire memory ranges.
>
> +**/
>
> +VOID
>
> +DetermineMemoryCacheType (
>
> + IN MTRR_MEMORY_CACHE_TYPE DefaultType,
>
> + IN OUT MTRR_MEMORY_RANGE *Range,
>
> + IN MTRR_MEMORY_RANGE *Ranges,
>
> + IN UINT32 RangeCount
>
> + )
>
> +{
>
> + UINT32 Index;
>
> + Range->Type = CacheInvalid;
>
> + for (Index = 0; Index < RangeCount; Index++) {
>
> + if (RangesOverlap (Range, &Ranges[Index], 1)) {
>
> + if (Ranges[Index].Type < Range->Type) {
>
> + Range->Type = Ranges[Index].Type;
>
> + }
>
> + }
>
> + }
>
> +
>
> + if (Range->Type == CacheInvalid) {
>
> + Range->Type = DefaultType;
>
> + }
>
> +}
>
> +
>
> +/**
>
> + Get the index of the element that does NOT equals to Array[Index].
>
> +
>
> + @param Index Current element.
>
> + @param Array Array to scan.
>
> + @param Count Count of the array.
>
> +
>
> + @return Next element that doesn't equal to current one.
>
> +**/
>
> +UINT32
>
> +GetNextDifferentElementInSortedArray (
>
> + IN UINT32 Index,
>
> + IN UINT64 *Array,
>
> + IN UINT32 Count
>
> + )
>
> +{
>
> + UINT64 CurrentElement;
>
> + CurrentElement = Array[Index];
>
> + while (CurrentElement == Array[Index] && Index < Count) {
>
> + Index++;
>
> + }
>
> + return Index;
>
> +}
>
> +
>
> +/**
>
> + Remove the duplicates from the array.
>
> +
>
> + @param Array The array to operate on.
>
> + @param Count Count of the array.
>
> +**/
>
> +VOID
>
> +RemoveDuplicatesInSortedArray (
>
> + IN OUT UINT64 *Array,
>
> + IN OUT UINT32 *Count
>
> + )
>
> +{
>
> + UINT32 Index;
>
> + UINT32 NewCount;
>
> +
>
> + Index = 0;
>
> + NewCount = 0;
>
> + while (Index < *Count) {
>
> + Array[NewCount] = Array[Index];
>
> + NewCount++;
>
> + Index = GetNextDifferentElementInSortedArray (Index, Array, *Count);
>
> + }
>
> + *Count = NewCount;
>
> +}
>
> +
>
> +/**
>
> + Return TRUE when Address is in the Range.
>
> +
>
> + @param Address The address to check.
>
> + @param Range The range to check.
>
> + @return TRUE when Address is in the Range.
>
> +**/
>
> +BOOLEAN
>
> +AddressInRange (
>
> + IN UINT64 Address,
>
> + IN MTRR_MEMORY_RANGE Range
>
> + )
>
> +{
>
> + return (Address >= Range.BaseAddress) && (Address <=
> Range.BaseAddress + Range.Length - 1);
>
> +}
>
> +
>
> +/**
>
> + Get the overlap bit flag.
>
> +
>
> + @param RawMemoryRanges Raw memory ranges.
>
> + @param RawMemoryRangeCount Count of raw memory ranges.
>
> + @param Address The address to check.
>
> +**/
>
> +UINT64
>
> +GetOverlapBitFlag (
>
> + IN MTRR_MEMORY_RANGE *RawMemoryRanges,
>
> + IN UINT32 RawMemoryRangeCount,
>
> + IN UINT64 Address
>
> + )
>
> +{
>
> + UINT64 OverlapBitFlag;
>
> + UINT32 Index;
>
> + OverlapBitFlag = 0;
>
> + for (Index = 0; Index < RawMemoryRangeCount; Index++) {
>
> + if (AddressInRange (Address, RawMemoryRanges[Index])) {
>
> + OverlapBitFlag |= (1ull << Index);
>
> + }
>
> + }
>
> +
>
> + return OverlapBitFlag;
>
> +}
>
> +
>
> +/**
>
> + Return the relationship between flags.
>
> +
>
> + @param Flag1 Flag 1
>
> + @param Flag2 Flag 2
>
> +
>
> + @retval 0 Flag1 == Flag2
>
> + @retval 1 Flag1 is a subset of Flag2
>
> + @retval 2 Flag2 is a subset of Flag1
>
> + @retval 3 No subset relations between Flag1 and Flag2.
>
> +**/
>
> +UINT32
>
> +CheckOverlapBitFlagsRelation (
>
> + IN UINT64 Flag1,
>
> + IN UINT64 Flag2
>
> + )
>
> +{
>
> + if (Flag1 == Flag2) return 0;
>
> + if ((Flag1 | Flag2) == Flag2) return 1;
>
> + if ((Flag1 | Flag2) == Flag1) return 2;
>
> + return 3;
>
> +}
>
> +
>
> +/**
>
> + Return TRUE when the Endpoint is in any of the Ranges.
>
> +
>
> + @param Endpoint The endpoint to check.
>
> + @param Ranges The memory ranges.
>
> + @param RangeCount Count of memory ranges.
>
> +
>
> + @retval TRUE Endpoint is in one of the range.
>
> + @retval FALSE Endpoint is not in any of the ranges.
>
> +**/
>
> +BOOLEAN
>
> +IsEndpointInRanges (
>
> + IN UINT64 Endpoint,
>
> + IN MTRR_MEMORY_RANGE *Ranges,
>
> + IN UINTN RangeCount
>
> + )
>
> +{
>
> + UINT32 Index;
>
> + for (Index = 0; Index < RangeCount; Index++) {
>
> + if (AddressInRange (Endpoint, Ranges[Index])) {
>
> + return TRUE;
>
> + }
>
> + }
>
> + return FALSE;
>
> +}
>
> +
>
> +
>
> +/**
>
> + Compact adjacent ranges of the same type.
>
> +
>
> + @param DefaultType Default memory type.
>
> + @param PhysicalAddressBits Physical address bits.
>
> + @param EffectiveMtrrMemoryRanges Memory ranges to compact.
>
> + @param EffectiveMtrrMemoryRangesCount Return the new count of
> memory ranges.
>
> +**/
>
> +VOID
>
> +CompactAndExtendEffectiveMtrrMemoryRanges (
>
> + IN MTRR_MEMORY_CACHE_TYPE DefaultType,
>
> + IN UINT32 PhysicalAddressBits,
>
> + IN OUT MTRR_MEMORY_RANGE **EffectiveMtrrMemoryRanges,
>
> + IN OUT UINTN *EffectiveMtrrMemoryRangesCount
>
> + )
>
> +{
>
> + UINT64 MaxAddress;
>
> + UINTN NewRangesCountAtMost;
>
> + MTRR_MEMORY_RANGE *NewRanges;
>
> + UINTN NewRangesCountActual;
>
> + MTRR_MEMORY_RANGE *CurrentRangeInNewRanges;
>
> + MTRR_MEMORY_CACHE_TYPE CurrentRangeTypeInOldRanges;
>
> +
>
> + MTRR_MEMORY_RANGE *OldRanges;
>
> + MTRR_MEMORY_RANGE OldLastRange;
>
> + UINTN OldRangesIndex;
>
> +
>
> + NewRangesCountActual = 0;
>
> + NewRangesCountAtMost = *EffectiveMtrrMemoryRangesCount + 2; //
> At most with 2 more range entries.
>
> + NewRanges = (MTRR_MEMORY_RANGE *) calloc
> (NewRangesCountAtMost, sizeof (MTRR_MEMORY_RANGE));
>
> + OldRanges = *EffectiveMtrrMemoryRanges;
>
> + if (OldRanges[0].BaseAddress > 0) {
>
> + NewRanges[NewRangesCountActual].BaseAddress = 0;
>
> + NewRanges[NewRangesCountActual].Length =
> OldRanges[0].BaseAddress;
>
> + NewRanges[NewRangesCountActual].Type = DefaultType;
>
> + NewRangesCountActual++;
>
> + }
>
> +
>
> + OldRangesIndex = 0;
>
> + while (OldRangesIndex < *EffectiveMtrrMemoryRangesCount) {
>
> + CurrentRangeTypeInOldRanges = OldRanges[OldRangesIndex].Type;
>
> + CurrentRangeInNewRanges = NULL;
>
> + if (NewRangesCountActual > 0) // We need to check CurrentNewRange
> first before generate a new NewRange.
>
> + {
>
> + CurrentRangeInNewRanges = &NewRanges[NewRangesCountActual - 1];
>
> + }
>
> + if (CurrentRangeInNewRanges != NULL && CurrentRangeInNewRanges-
> >Type == CurrentRangeTypeInOldRanges) {
>
> + CurrentRangeInNewRanges->Length +=
> OldRanges[OldRangesIndex].Length;
>
> + } else {
>
> + NewRanges[NewRangesCountActual].BaseAddress =
> OldRanges[OldRangesIndex].BaseAddress;
>
> + NewRanges[NewRangesCountActual].Length +=
> OldRanges[OldRangesIndex].Length;
>
> + NewRanges[NewRangesCountActual].Type =
> CurrentRangeTypeInOldRanges;
>
> + while (OldRangesIndex + 1 < *EffectiveMtrrMemoryRangesCount &&
> OldRanges[OldRangesIndex + 1].Type == CurrentRangeTypeInOldRanges)
>
> + {
>
> + OldRangesIndex++;
>
> + NewRanges[NewRangesCountActual].Length +=
> OldRanges[OldRangesIndex].Length;
>
> + }
>
> + NewRangesCountActual++;
>
> + }
>
> +
>
> + OldRangesIndex++;
>
> + }
>
> +
>
> + MaxAddress = (1ull << PhysicalAddressBits) - 1;
>
> + OldLastRange = OldRanges[(*EffectiveMtrrMemoryRangesCount) - 1];
>
> + CurrentRangeInNewRanges = &NewRanges[NewRangesCountActual - 1];
>
> + if (OldLastRange.BaseAddress + OldLastRange.Length - 1 < MaxAddress) {
>
> + if (CurrentRangeInNewRanges->Type == DefaultType) {
>
> + CurrentRangeInNewRanges->Length = MaxAddress -
> CurrentRangeInNewRanges->BaseAddress + 1;
>
> + } else {
>
> + NewRanges[NewRangesCountActual].BaseAddress =
> OldLastRange.BaseAddress + OldLastRange.Length;
>
> + NewRanges[NewRangesCountActual].Length = MaxAddress -
> NewRanges[NewRangesCountActual].BaseAddress + 1;
>
> + NewRanges[NewRangesCountActual].Type = DefaultType;
>
> + NewRangesCountActual++;
>
> + }
>
> + }
>
> +
>
> + free (*EffectiveMtrrMemoryRanges);
>
> + *EffectiveMtrrMemoryRanges = NewRanges;
>
> + *EffectiveMtrrMemoryRangesCount = NewRangesCountActual;
>
> +}
>
> +
>
> +/**
>
> + Collect all the endpoints in the raw memory ranges.
>
> +
>
> + @param Endpoints Return the collected endpoints.
>
> + @param EndPointCount Return the count of endpoints.
>
> + @param RawMemoryRanges Raw memory ranges.
>
> + @param RawMemoryRangeCount Count of raw memory ranges.
>
> +**/
>
> +VOID
>
> +CollectEndpoints (
>
> + IN OUT UINT64 *Endpoints,
>
> + IN OUT UINT32 *EndPointCount,
>
> + IN MTRR_MEMORY_RANGE *RawMemoryRanges,
>
> + IN UINT32 RawMemoryRangeCount
>
> + )
>
> +{
>
> + UINT32 Index;
>
> + UINT32 RawRangeIndex;
>
> +
>
> + ASSERT ((RawMemoryRangeCount << 1) == *EndPointCount);
>
> +
>
> + for (Index = 0; Index < *EndPointCount; Index += 2) {
>
> + RawRangeIndex = Index >> 1;
>
> + Endpoints[Index] = RawMemoryRanges[RawRangeIndex].BaseAddress;
>
> + Endpoints[Index + 1] =
> RawMemoryRanges[RawRangeIndex].BaseAddress +
> RawMemoryRanges[RawRangeIndex].Length - 1;
>
> + }
>
> +
>
> + qsort (Endpoints, *EndPointCount, sizeof (UINT64), CompareFuncUint64);
>
> + RemoveDuplicatesInSortedArray (Endpoints, EndPointCount);
>
> +}
>
> +
>
> +/**
>
> + Convert the MTRR BASE/MASK array to memory ranges.
>
> +
>
> + @param DefaultType Default memory type.
>
> + @param PhysicalAddressBits Physical address bits.
>
> + @param RawMemoryRanges Raw memory ranges.
>
> + @param RawMemoryRangeCount Count of raw memory ranges.
>
> + @param MemoryRanges Memory ranges.
>
> + @param MemoryRangeCount Count of memory ranges.
>
> +**/
>
> +VOID
>
> +GetEffectiveMemoryRanges (
>
> + IN MTRR_MEMORY_CACHE_TYPE DefaultType,
>
> + IN UINT32 PhysicalAddressBits,
>
> + IN MTRR_MEMORY_RANGE *RawMemoryRanges,
>
> + IN UINT32 RawMemoryRangeCount,
>
> + OUT MTRR_MEMORY_RANGE *MemoryRanges,
>
> + OUT UINTN *MemoryRangeCount
>
> + )
>
> +{
>
> + UINTN Index;
>
> + UINT32 AllEndPointsCount;
>
> + UINT64 *AllEndPointsInclusive;
>
> + UINT32 AllRangePiecesCountMax;
>
> + MTRR_MEMORY_RANGE *AllRangePieces;
>
> + UINTN AllRangePiecesCountActual;
>
> + UINT64 OverlapBitFlag1;
>
> + UINT64 OverlapBitFlag2;
>
> + INT32 OverlapFlagRelation;
>
> +
>
> + if (RawMemoryRangeCount == 0) {
>
> + MemoryRanges[0].BaseAddress = 0;
>
> + MemoryRanges[0].Length = (1ull << PhysicalAddressBits);
>
> + MemoryRanges[0].Type = DefaultType;
>
> + *MemoryRangeCount = 1;
>
> + return;
>
> + }
>
> +
>
> + AllEndPointsCount = RawMemoryRangeCount << 1;
>
> + AllEndPointsInclusive = calloc (AllEndPointsCount, sizeof (UINT64));
>
> + AllRangePiecesCountMax = RawMemoryRangeCount * 3 + 1;
>
> + AllRangePieces = calloc (AllRangePiecesCountMax, sizeof
> (MTRR_MEMORY_RANGE));
>
> + CollectEndpoints (AllEndPointsInclusive, &AllEndPointsCount,
> RawMemoryRanges, RawMemoryRangeCount);
>
> +
>
> + for (Index = 0, AllRangePiecesCountActual = 0; Index < AllEndPointsCount -
> 1; Index++) {
>
> + OverlapBitFlag1 = GetOverlapBitFlag (RawMemoryRanges,
> RawMemoryRangeCount, AllEndPointsInclusive[Index]);
>
> + OverlapBitFlag2 = GetOverlapBitFlag (RawMemoryRanges,
> RawMemoryRangeCount, AllEndPointsInclusive[Index + 1]);
>
> + OverlapFlagRelation = CheckOverlapBitFlagsRelation (OverlapBitFlag1,
> OverlapBitFlag2);
>
> + switch (OverlapFlagRelation) {
>
> + case 0: // [1, 2]
>
> + AllRangePieces[AllRangePiecesCountActual].BaseAddress =
> AllEndPointsInclusive[Index];
>
> + AllRangePieces[AllRangePiecesCountActual].Length =
> AllEndPointsInclusive[Index + 1] - AllEndPointsInclusive[Index] + 1;
>
> + AllRangePiecesCountActual++;
>
> + break;
>
> + case 1: // [1, 2)
>
> + AllRangePieces[AllRangePiecesCountActual].BaseAddress =
> AllEndPointsInclusive[Index];
>
> + AllRangePieces[AllRangePiecesCountActual].Length =
> (AllEndPointsInclusive[Index + 1] - 1) - AllEndPointsInclusive[Index] + 1;
>
> + AllRangePiecesCountActual++;
>
> + break;
>
> + case 2: // (1, 2]
>
> + AllRangePieces[AllRangePiecesCountActual].BaseAddress =
> AllEndPointsInclusive[Index] + 1;
>
> + AllRangePieces[AllRangePiecesCountActual].Length =
> AllEndPointsInclusive[Index + 1] - (AllEndPointsInclusive[Index] + 1) + 1;
>
> + AllRangePiecesCountActual++;
>
> +
>
> + if (!IsEndpointInRanges (AllEndPointsInclusive[Index], AllRangePieces,
> AllRangePiecesCountActual)) {
>
> + AllRangePieces[AllRangePiecesCountActual].BaseAddress =
> AllEndPointsInclusive[Index];
>
> + AllRangePieces[AllRangePiecesCountActual].Length = 1;
>
> + AllRangePiecesCountActual++;
>
> + }
>
> + break;
>
> + case 3: // (1, 2)
>
> + AllRangePieces[AllRangePiecesCountActual].BaseAddress =
> AllEndPointsInclusive[Index] + 1;
>
> + AllRangePieces[AllRangePiecesCountActual].Length =
> (AllEndPointsInclusive[Index + 1] - 1) - (AllEndPointsInclusive[Index] + 1) + 1;
>
> + if (AllRangePieces[AllRangePiecesCountActual].Length == 0) // Only in
> case 3 can exists Length=0, we should skip such "segment".
>
> + break;
>
> + AllRangePiecesCountActual++;
>
> + if (!IsEndpointInRanges (AllEndPointsInclusive[Index], AllRangePieces,
> AllRangePiecesCountActual)) {
>
> + AllRangePieces[AllRangePiecesCountActual].BaseAddress =
> AllEndPointsInclusive[Index];
>
> + AllRangePieces[AllRangePiecesCountActual].Length = 1;
>
> + AllRangePiecesCountActual++;
>
> + }
>
> + break;
>
> + default:
>
> + ASSERT (FALSE);
>
> + }
>
> + }
>
> +
>
> + for (Index = 0; Index < AllRangePiecesCountActual; Index++) {
>
> + DetermineMemoryCacheType (DefaultType, &AllRangePieces[Index],
> RawMemoryRanges, RawMemoryRangeCount);
>
> + }
>
> +
>
> + CompactAndExtendEffectiveMtrrMemoryRanges (DefaultType,
> PhysicalAddressBits, &AllRangePieces, &AllRangePiecesCountActual);
>
> + ASSERT (*MemoryRangeCount >= AllRangePiecesCountActual);
>
> + memcpy (MemoryRanges, AllRangePieces, AllRangePiecesCountActual *
> sizeof (MTRR_MEMORY_RANGE));
>
> + *MemoryRangeCount = AllRangePiecesCountActual;
>
> +
>
> + free (AllEndPointsInclusive);
>
> + free (AllRangePieces);
>
> +}
>
> diff --git a/UefiCpuPkg/Test/UefiCpuPkgHostTest.dsc
> b/UefiCpuPkg/Test/UefiCpuPkgHostTest.dsc
> new file mode 100644
> index 0000000000..8a5c456830
> --- /dev/null
> +++ b/UefiCpuPkg/Test/UefiCpuPkgHostTest.dsc
> @@ -0,0 +1,31 @@
> +## @file
>
> +# UefiCpuPkg DSC file used to build host-based unit tests.
>
> +#
>
> +# Copyright (c) 2020, Intel Corporation. All rights reserved.<BR>
>
> +# SPDX-License-Identifier: BSD-2-Clause-Patent
>
> +#
>
> +##
>
> +
>
> +[Defines]
>
> + PLATFORM_NAME = UefiCpuPkgHostTest
>
> + PLATFORM_GUID = E00B9599-5B74-4FF7-AB9F-8183FB13B2F9
>
> + PLATFORM_VERSION = 0.1
>
> + DSC_SPECIFICATION = 0x00010005
>
> + OUTPUT_DIRECTORY = Build/UefiCpuPkg/HostTest
>
> + SUPPORTED_ARCHITECTURES = IA32|X64
>
> + BUILD_TARGETS = NOOPT
>
> + SKUID_IDENTIFIER = DEFAULT
>
> +
>
> +!include UnitTestFrameworkPkg/UnitTestFrameworkPkgHost.dsc.inc
>
> +
>
> +[LibraryClasses]
>
> + MtrrLib|UefiCpuPkg/Library/MtrrLib/MtrrLib.inf
>
> +
>
> +[PcdsPatchableInModule]
>
> + gUefiCpuPkgTokenSpaceGuid.PcdCpuNumberOfReservedVariableMtrrs|0
>
> +
>
> +[Components]
>
> + #
>
> + # Build HOST_APPLICATION that tests the MtrrLib
>
> + #
>
> + UefiCpuPkg/Library/MtrrLib/UnitTest/MtrrLibUnitTestHost.inf
>
> --
> 2.27.0.windows.1
^ permalink raw reply [flat|nested] 4+ messages in thread