Mike,
I resent V2 patch and reduced most of the global variable references.

Furtherly, I added more CONST modifier to avoid test case accidently modifies 
the system parameter structure.

I submitted a Bugzilla https://bugzilla.tianocore.org/show_bug.cgi?id=2863 to 
capture what you suggested below.

Thanks,
Ray

> -----Original Message-----
> From: Kinney, Michael D <michael.d.kin...@intel.com>
> Sent: Friday, July 24, 2020 9:34 AM
> To: Ni, Ray <ray...@intel.com>; devel@edk2.groups.io; Kinney, Michael D 
> <michael.d.kin...@intel.com>
> Cc: Shao, Ming <ming.s...@intel.com>; Dong, Eric <eric.d...@intel.com>; 
> Laszlo Ersek <ler...@redhat.com>; Sean Brogan
> <sean.bro...@microsoft.com>; Bret Barkelew <bret.barke...@microsoft.com>; 
> Yao, Jiewen <jiewen....@intel.com>
> Subject: RE: [PATCH] UefiCpuPkg/MtrrLib/UnitTest: Add host based unit test
> 
> Hi Ray,
> 
> In the following Unit Test Functions, I recommend passing in
> mDefaultSystemParameter as the Context parameter to reduce the
> use of a global variables.
> 
> * UnitTestIsMtrrSupported()
> * UnitTestGetVariableMtrrCount()
> * UnitTestGetFirmwareVariableMtrrCount()
> * UnitTestMtrrGetFixedMtrr()
> * UnitTestMtrrGetAllMtrrs()
> * UnitTestMtrrSetAllMtrrs()
> * UnitTestMtrrGetMemoryAttributeInVariableMtrr()
> * UnitTestMtrrGetDefaultMemoryType()
> 
> The use of random memory maps is a good way to test complex
> services like these.  However, the issues with random test
> vectors is that a test failure is difficult to reproduce.
> You can also have cases where one run through CI fails and
> the next run with different random values passes.
> 
> I like the idea of using code that generates random test
> vectors to generate a fixed set of test vectors that are
> built into the unit test so we have the same test vectors
> for every CI check.
> 
> Then, we can split out the unit test that does random test
> vectors into its own test that a developer can choose to
> run with a high number of iterations when there is an algo
> change or we are doing release testing.  This unit test
> would not be use for CI testing.
> 
> I am ok with the first version using random, but please
> enter a BZ to split it out.
> 
> Thanks,
> 
> Mike
> 
> > -----Original Message-----
> > From: Ni, Ray <ray...@intel.com>
> > Sent: Friday, July 17, 2020 12:33 AM
> > To: devel@edk2.groups.io
> > Cc: Kinney, Michael D <michael.d.kin...@intel.com>;
> > Shao, Ming <ming.s...@intel.com>; Dong, Eric
> > <eric.d...@intel.com>; Laszlo Ersek
> > <ler...@redhat.com>; Sean Brogan
> > <sean.bro...@microsoft.com>; Bret Barkelew
> > <bret.barke...@microsoft.com>; Yao, Jiewen
> > <jiewen....@intel.com>
> > Subject: [PATCH] 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...@intel.com>
> > Signed-off-by: Michael D Kinney
> > <michael.d.kin...@intel.com>
> > Signed-off-by: Ming Shao <ming.s...@intel.com>
> > Cc: Michael D Kinney <michael.d.kin...@intel.com>
> > Cc: Ming Shao <ming.s...@intel.com>
> > Cc: Eric Dong <eric.d...@intel.com>
> > Cc: Ray Ni <ray...@intel.com>
> > Cc: Laszlo Ersek <ler...@redhat.com>
> > Cc: Sean Brogan <sean.bro...@microsoft.com>
> > Cc: Bret Barkelew <bret.barke...@microsoft.com>
> > Cc: Jiewen Yao <jiewen....@intel.com>
> > ---
> >  .../MtrrLib/UnitTest/MtrrLibUnitTest.c        | 1094
> > +++++++++++++++++
> >  .../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, 2248 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..b0623ddea7
> > --- /dev/null
> > +++
> > b/UefiCpuPkg/Library/MtrrLib/UnitTest/MtrrLibUnitTest.c
> > @@ -0,0 +1,1094 @@
> > +/** @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"
> >
> > +
> >
> > +CONST MTRR_LIB_SYSTEM_PARAMETER
> > mDefaultSystemParameter = {
> >
> > +  42, TRUE, TRUE, CacheUncacheable, 12
> >
> > +  };
> >
> > +
> >
> > +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!"
> >
> > +  );
> >
> > +
> >
> > +
> >
> > +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
> >
> > +  )
> >
> > +{
> >
> > +  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
> >
> > +  )
> >
> > +{
> >
> > +  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;
> >
> > +
> >
> > +  CopyMem (&SystemParameter, &mDefaultSystemParameter,
> > 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;
> >
> > +
> >
> > +  CopyMem (&SystemParameter, &mDefaultSystemParameter,
> > 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;
> >
> > +
> >
> > +  CopyMem (&SystemParameter, &mDefaultSystemParameter,
> > 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;
> >
> > +
> >
> > +  CopyMem (&SystemParameter, &mDefaultSystemParameter,
> > 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;
> >
> > +
> >
> > +  CopyMem (&SystemParameter, &mDefaultSystemParameter,
> > 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;
> >
> > +
> >
> > +  CopyMem (&SystemParameter, &mDefaultSystemParameter,
> > 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_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;
> >
> > +
> >
> > +  CopyMem (&SystemParameter, &mDefaultSystemParameter,
> > 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
> >
> > +  )
> >
> > +{
> >
> > +  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;
> >
> > +
> >
> > +  CopyMem (&SystemParameter, &mDefaultSystemParameter,
> > 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
> >
> > +  )
> >
> > +{
> >
> > +  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
> >
> > +  )
> >
> > +{
> >
> > +  *(UINT32 *) Context = 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
> >
> > +  )
> >
> > +{
> >
> > +  PatchPcdSet32 (PcdCpuNumberOfReservedVariableMtrrs,
> > *(UINT32 *) Context);
> >
> > +  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;
> >
> > +  UINT32                      OriginalPcdValue;
> >
> > +
> >
> > +  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, NULL);
> >
> > +  AddTestCase (MtrrApiTests, "Test
> > GetVariableMtrrCount",
> > "GetVariableMtrrCount",
> > UnitTestGetVariableMtrrCount,                 NULL,
> > NULL, NULL);
> >
> > +  AddTestCase (MtrrApiTests, "Test
> > GetFirmwareVariableMtrrCount",
> > "GetFirmwareVariableMtrrCount",
> > UnitTestGetFirmwareVariableMtrrCount,
> > SavePcdValue, RestorePcdValue, &OriginalPcdValue);
> >
> > +  AddTestCase (MtrrApiTests, "Test
> > MtrrGetMemoryAttribute",
> > "MtrrGetMemoryAttribute",
> > UnitTestMtrrGetMemoryAttribute,               NULL,
> > NULL, NULL);
> >
> > +  AddTestCase (MtrrApiTests, "Test MtrrGetFixedMtrr",
> > "MtrrGetFixedMtrr",
> > UnitTestMtrrGetFixedMtrr,                     NULL,
> > NULL, NULL);
> >
> > +  AddTestCase (MtrrApiTests, "Test MtrrGetAllMtrrs",
> > "MtrrGetAllMtrrs",
> > UnitTestMtrrGetAllMtrrs,                      NULL,
> > NULL, NULL);
> >
> > +  AddTestCase (MtrrApiTests, "Test MtrrSetAllMtrrs",
> > "MtrrSetAllMtrrs",
> > UnitTestMtrrSetAllMtrrs,                      NULL,
> > NULL, NULL);
> >
> > +  AddTestCase (MtrrApiTests, "Test
> > MtrrGetMemoryAttributeInVariableMtrr",
> > "MtrrGetMemoryAttributeInVariableMtrr",
> > UnitTestMtrrGetMemoryAttributeInVariableMtrr, NULL,
> > NULL, NULL);
> >
> > +  AddTestCase (MtrrApiTests, "Test
> > MtrrDebugPrintAllMtrrs",
> > "MtrrDebugPrintAllMtrrs",
> > UnitTestMtrrDebugPrintAllMtrrs,               NULL,
> > NULL, NULL);
> >
> > +  AddTestCase (MtrrApiTests, "Test
> > MtrrGetDefaultMemoryType",
> > "MtrrGetDefaultMemoryType",
> > UnitTestMtrrGetDefaultMemoryType,             NULL,
> > NULL, NULL);
> >
> > +
> >
> > +  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
> 


-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.

View/Reply Online (#63228): https://edk2.groups.io/g/devel/message/63228
Mute This Topic: https://groups.io/mt/75607707/21656
Group Owner: devel+ow...@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub  [arch...@mail-archive.com]
-=-=-=-=-=-=-=-=-=-=-=-

Reply via email to