From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from out04.hibox.biz (out04.hibox.biz [210.71.195.43]) by mx.groups.io with SMTP id smtpd.web12.1372.1595966946298894064 for ; Tue, 28 Jul 2020 13:09:07 -0700 Authentication-Results: mx.groups.io; dkim=missing; spf=pass (domain: insyde.com, ip: 210.71.195.43, mailfrom: tim.lewis@insyde.com) IronPort-SDR: e766o2A1SNx8mZlxOVSwXLVmV5ey9XR/ZuVtg47QgZhmHMF+C1pgYcpz2a0iKJKZl9m7Bxwwx4 /RpD8GYnBjcQ== X-IronPort-Anti-Spam-Filtered: true X-IronPort-Anti-Spam-Result: A2CgBAAXgyBf/ws0GKzBQ0scAwYE4j8 X-IronPort-AV: E=Sophos;i="5.75,407,1589212800"; d="scan'208,217";a="29669704" Received: from unknown (HELO hb3-BKT201.hibox.biz) ([172.24.52.11]) by out04.hibox.biz with ESMTP; 29 Jul 2020 04:09:02 +0800 IronPort-SDR: 6gCyCZYt7cWZogi49isizo11cuYl03cEycRXvgLg5/8RyeIWtHUFmlEqMpT5+7ANOJWRKsKzH6 nZrkDDD1cwiw== Received: from unknown (HELO hb3-BKT101.hibox.biz) ([172.24.51.11]) by hb3-BKT201.hibox.biz with ESMTP; 29 Jul 2020 04:09:03 +0800 IronPort-SDR: K7VaC8DLTJ768qEF4/Ty+5l2H0N1z9V77P08wkQzO0Z7+bwkgWZ2iLmB7IjOTah8lFGOPln/6s QoongHdIdkrg== Received: from unknown (HELO hb3-IN01.hibox.biz) ([172.24.12.11]) by hb3-BKT101.hibox.biz with ESMTP; 29 Jul 2020 04:09:02 +0800 IronPort-SDR: 3ofYNg9W0AxHBd/YFTw2B/4sKXD/1twNt1BF4c9KFJqctzN0Wg3NH8InJBMZQv0fpZEd+07SLz zX1ct8OSR7/g== X-Remote-IP: 73.116.1.175 X-Remote-Host: c-73-116-1-175.hsd1.ca.comcast.net X-SBRS: -10.0 X-MID: 40701746 X-Auth-ID: tim.lewis@insyde.com X-EnvelopeFrom: tim.lewis@insyde.com Received: from c-73-116-1-175.hsd1.ca.comcast.net (HELO DESKTOPHG9V3E8) ([73.116.1.175]) by hb3-IN01.hibox.biz with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 29 Jul 2020 04:08:58 +0800 From: "Tim Lewis" To: , , Cc: , "'Ni, Ray'" , "'Mike Kinney'" , "'Ming Shao'" , "'Dong, Eric'" , "'Laszlo Ersek'" , "'Sean Brogan'" , "'Yao, Jiewen'" In-Reply-To: Subject: Re: [EXTERNAL] [edk2-devel] [PATCH v4] UefiCpuPkg/MtrrLib/UnitTest: Add host based unit test Date: Tue, 28 Jul 2020 13:08:56 -0700 Message-ID: <067501d6651a$eeda3040$cc8e90c0$@insyde.com> MIME-Version: 1.0 X-Mailer: Microsoft Outlook 16.0 Thread-Index: AQDlz5NIRep+7YodTBPrC5cUU346P6r+lnCQ Content-Type: multipart/alternative; boundary="----=_NextPart_000_0676_01D664E0.42A09380" Content-Language: en-us ------=_NextPart_000_0676_01D664E0.42A09380 Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable Andrew =E2=80=93 =20 You would have to include the random number code directly in the unit test= to handle your cross-environment portability issues. =20 Tim =20 From: devel@edk2.groups.io On Behalf Of Andrew Fish= via groups.io Sent: Tuesday, July 28, 2020 11:59 AM To: devel@edk2.groups.io; bret.barkelew@microsoft.com Cc: tim.lewis@insyde.com; spbrogan@outlook.com; Ni, Ray = ; Mike Kinney ; Ming Shao = ; Dong, Eric ; Laszlo Ersek ; Sean = Brogan ; Yao, Jiewen Subject: Re: [EXTERNAL] [edk2-devel] [PATCH v4] UefiCpuPkg/MtrrLib/UnitTes= t: Add host based unit test =20 On Jul 28, 2020, at 10:53 AM, Bret Barkelew via groups.io > wrote: =20 In this strategy, the seed would function like a meta =E2=80=9Ccase=E2=80= =9D? We could add extra =E2=80=9Ccases=E2=80=9D as isolated testing expose= s problem sets? =20 =20 Bret, =20 >>From a quick skim of the test it looks like it always generates random dat= a? Not sure if I missed something.=20 I think the idea is interesting. =20 What is the advantage of this approach over: * Run fuzzers in isolation. * When a break occurs, isolate the inputs as a new test case for the exist= ing structured test cases. =20 =20 The fixed seed is an interesting idea, but I=E2=80=99m not sure that is re= ally portable. What if the CI is running on Windows and the developer is de= bugging on macOS or Linux? Seems like you could get different results. So I= think that is a plus for there being more of a structured set of tests as = you advocate.=20 =20 It would also be nice If developer could force the failed test case in iso= lation. Adding a CpuBreakpoint() or DEBUG prints can be painful if it is th= e 10,000 iteration of the test loop that fails.=20 =20 Thanks, =20 Andrew Fish Thanks! =20 - Bret =20 From: tim.lewis@insyde.com =20 Sent: Tuesday, July 28, 2020 10:13 AM To: devel@edk2.groups.io ; spbrogan@outlook.= com ; Ni, Ray =20 Cc: Kinney, Michael D ; 'Ming Shao' ; Dong, Eric ; 'Las= zlo Ersek' ; Sean Brogan ; Bret Barkelew ; Yao, Jie= wen =20 Subject: [EXTERNAL] RE: [edk2-devel] [PATCH v4] UefiCpuPkg/MtrrLib/UnitTes= t: Add host based unit test =20 Sean -- What I have seen done for fuzz testing is to (a) report the seed used to i= nitialize the RNG in the log and then (b) provide an option to force the se= ed to that value. Using a static seed might actually be the default for CI = runs, but stand-alone runs could use a random value.=20 Just a thought. Tim -----Original Message----- From: devel@edk2.groups.io > On Behalf Of Sean Sent: Tuesday, July 28, 2020 9:38 AM To: devel@edk2.groups.io ; ray.ni@intel.com = =20 Cc: Michael D Kinney >; Ming Shao >= ; Eric Dong >; Laszlo Ers= ek >; Sean Brogan >; Bret Barkelew >; Jiewen Yao > Subject: Re: [edk2-devel] [PATCH v4] UefiCpuPkg/MtrrLib/UnitTest: Add host= based unit test Ray, I worry that this style of testing will lead to inconsistant results.=20 Generating random test cases means that the test cases on any given run=20 could find a bug in this code without this code changing. I think this= =20 type of testing (fuzz testing like) is great but I think we might want=20 to consider this a different test type and treat it differently. For unit testing the mtrr lib it would make more sense to identify a few= =20 unique passing and failing tests and statically add those. If there are= =20 edge cases or more cases needed to get full code coverage then=20 developing those would be great. Another point is once we start tracking code coverage your random test=20 generation will lead to different results which will make it hard to=20 track the metrics reliably. Finally, if edk2 community wants to support fuzz testing (which i think=20 is good) we should add details about how to add fuzz testing to edk2 and= =20 how to exclude it from PR/CI test runs. Thoughts? Thanks Sean On 7/28/2020 1:43 AM, Ni, Ray wrote: > Add host based unit tests for the MtrrLib services. > The BaseLib services AsmCpuid(), AsmReadMsr64(), and > AsmWriteMsr64() are hooked and provide simple emulation > of the CPUID leafs and MSRs required by the MtrrLib to > run as a host based unit test. >=20 > Test cases are developed for each of the API. >=20 > 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. >=20 > Signed-off-by: Ray Ni > > Signed-off-by: Michael D Kinney > > Signed-off-by: Ming Shao > > Cc: Michael D Kinney > > Cc: Eric Dong > > Cc: Laszlo Ersek > > Cc: Ming Shao > > Cc: Sean Brogan > > Cc: Bret Barkelew > > Cc: Jiewen Yao > > --- > .../MtrrLib/UnitTest/MtrrLibUnitTest.c | 1139 +++++++++++++++++ > .../MtrrLib/UnitTest/MtrrLibUnitTest.h | 182 +++ > .../MtrrLib/UnitTest/MtrrLibUnitTestHost.inf | 39 + > UefiCpuPkg/Library/MtrrLib/UnitTest/Support.c | 923 +++++++++++++ > UefiCpuPkg/Test/UefiCpuPkgHostTest.dsc | 31 + > UefiCpuPkg/UefiCpuPkg.ci.yaml | 12 +- > 6 files changed, 2325 insertions(+), 1 deletion(-) > 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/MtrrLibUnitTest= Host.inf > create mode 100644 UefiCpuPkg/Library/MtrrLib/UnitTest/Support.c > create mode 100644 UefiCpuPkg/Test/UefiCpuPkgHostTest.dsc >=20 > diff --git a/UefiCpuPkg/Library/MtrrLib/UnitTest/MtrrLibUnitTest.c b/Uef= iCpuPkg/Library/MtrrLib/UnitTest/MtrrLibUnitTest.c > new file mode 100644 > index 0000000000..123e1c741a > --- /dev/null > +++ b/UefiCpuPkg/Library/MtrrLib/UnitTest/MtrrLibUnitTest.c > @@ -0,0 +1,1139 @@ > +/** @file >=20 > + Unit tests of the MtrrLib instance of the MtrrLib class >=20 > + >=20 > + Copyright (c) 2020, Intel Corporation. All rights reserved.
>=20 > + SPDX-License-Identifier: BSD-2-Clause-Patent >=20 > + >=20 > +**/ >=20 > + >=20 > +#include "MtrrLibUnitTest.h" >=20 > + >=20 > +STATIC CONST MTRR_LIB_SYSTEM_PARAMETER mDefaultSystemParameter =3D { >=20 > + 42, TRUE, TRUE, CacheUncacheable, 12 >=20 > +}; >=20 > + >=20 > +STATIC MTRR_LIB_SYSTEM_PARAMETER mSystemParameters[] =3D { >=20 > + { 38, TRUE, TRUE, CacheUncacheable, 12 }, >=20 > + { 38, TRUE, TRUE, CacheWriteBack, 12 }, >=20 > + { 38, TRUE, TRUE, CacheWriteThrough, 12 }, >=20 > + { 38, TRUE, TRUE, CacheWriteProtected, 12 }, >=20 > + { 38, TRUE, TRUE, CacheWriteCombining, 12 }, >=20 > + >=20 > + { 42, TRUE, TRUE, CacheUncacheable, 12 }, >=20 > + { 42, TRUE, TRUE, CacheWriteBack, 12 }, >=20 > + { 42, TRUE, TRUE, CacheWriteThrough, 12 }, >=20 > + { 42, TRUE, TRUE, CacheWriteProtected, 12 }, >=20 > + { 42, TRUE, TRUE, CacheWriteCombining, 12 }, >=20 > + >=20 > + { 48, TRUE, TRUE, CacheUncacheable, 12 }, >=20 > + { 48, TRUE, TRUE, CacheWriteBack, 12 }, >=20 > + { 48, TRUE, TRUE, CacheWriteThrough, 12 }, >=20 > + { 48, TRUE, TRUE, CacheWriteProtected, 12 }, >=20 > + { 48, TRUE, TRUE, CacheWriteCombining, 12 }, >=20 > +}; >=20 > + >=20 > +UINT32 mFixedMtrrsIndex[] =3D { >=20 > + MSR_IA32_MTRR_FIX64K_00000, >=20 > + MSR_IA32_MTRR_FIX16K_80000, >=20 > + MSR_IA32_MTRR_FIX16K_A0000, >=20 > + MSR_IA32_MTRR_FIX4K_C0000, >=20 > + MSR_IA32_MTRR_FIX4K_C8000, >=20 > + MSR_IA32_MTRR_FIX4K_D0000, >=20 > + MSR_IA32_MTRR_FIX4K_D8000, >=20 > + MSR_IA32_MTRR_FIX4K_E0000, >=20 > + MSR_IA32_MTRR_FIX4K_E8000, >=20 > + MSR_IA32_MTRR_FIX4K_F0000, >=20 > + MSR_IA32_MTRR_FIX4K_F8000 >=20 > +}; >=20 > +STATIC_ASSERT ( >=20 > + (ARRAY_SIZE (mFixedMtrrsIndex) =3D=3D MTRR_NUMBER_OF_FIXED_MTRR), >=20 > + "gFixedMtrrIndex does NOT contain all the fixed MTRRs!" >=20 > + ); >=20 > + >=20 > +// >=20 > +// Context structure to be used for most of the test cases. >=20 > +// >=20 > +typedef struct { >=20 > + CONST MTRR_LIB_SYSTEM_PARAMETER *SystemParameter; >=20 > +} MTRR_LIB_TEST_CONTEXT; >=20 > + >=20 > +// >=20 > +// Context structure to be used for GetFirmwareVariableMtrrCount() test= . >=20 > +// >=20 > +typedef struct { >=20 > + UINT32 NumberOfReservedVariableMtrrs; >=20 > + CONST MTRR_LIB_SYSTEM_PARAMETER *SystemParameter; >=20 > +} MTRR_LIB_GET_FIRMWARE_VARIABLE_MTRR_COUNT_CONTEXT; >=20 > + >=20 > +STATIC CHAR8 *mCacheDescription[] =3D { "UC", "WC", "N/A", "N/A", "WT",= "WP", "WB" }; >=20 > + >=20 > +/** >=20 > + Compare the actual memory ranges against expected memory ranges and r= eturn PASS when they match. >=20 > + >=20 > + @param ExpectedMemoryRanges Expected memory ranges. >=20 > + @param ExpectedMemoryRangeCount Count of expected memory ranges. >=20 > + @param ActualRanges Actual memory ranges. >=20 > + @param ActualRangeCount Count of actual memory ranges. >=20 > + >=20 > + @retval UNIT_TEST_PASSED Test passed. >=20 > + @retval others Test failed. >=20 > +**/ >=20 > +UNIT_TEST_STATUS >=20 > +VerifyMemoryRanges ( >=20 > + IN MTRR_MEMORY_RANGE *ExpectedMemoryRanges, >=20 > + IN UINTN ExpectedMemoryRangeCount, >=20 > + IN MTRR_MEMORY_RANGE *ActualRanges, >=20 > + IN UINTN ActualRangeCount >=20 > + ) >=20 > +{ >=20 > + UINTN Index; >=20 > + UT_ASSERT_EQUAL (ExpectedMemoryRangeCount, ActualRangeCount); >=20 > + for (Index =3D 0; Index < ExpectedMemoryRangeCount; Index++) { >=20 > + UT_ASSERT_EQUAL (ExpectedMemoryRanges[Index].BaseAddress, ActualRan= ges[Index].BaseAddress); >=20 > + UT_ASSERT_EQUAL (ExpectedMemoryRanges[Index].Length, ActualRanges[I= ndex].Length); >=20 > + UT_ASSERT_EQUAL (ExpectedMemoryRanges[Index].Type, ActualRanges[Ind= ex].Type); >=20 > + } >=20 > + >=20 > + return UNIT_TEST_PASSED; >=20 > +} >=20 > + >=20 > +/** >=20 > + Dump the memory ranges. >=20 > + >=20 > + @param Ranges Memory ranges to dump. >=20 > + @param RangeCount Count of memory ranges. >=20 > +**/ >=20 > +VOID >=20 > +DumpMemoryRanges ( >=20 > + MTRR_MEMORY_RANGE *Ranges, >=20 > + UINTN RangeCount >=20 > + ) >=20 > +{ >=20 > + UINTN Index; >=20 > + for (Index =3D 0; Index < RangeCount; Index++) { >=20 > + UT_LOG_INFO ("\t{ 0x%016llx, 0x%016llx, %a },\n", Ranges[Index].Bas= eAddress, Ranges[Index].Length, mCacheDescription[Ranges[Index].Type]); >=20 > + } >=20 > +} >=20 > + >=20 > +/** >=20 > +**/ >=20 > + >=20 > +/** >=20 > + Generate random count of MTRRs for each cache type. >=20 > + >=20 > + @param TotalCount Total MTRR count. >=20 > + @param UcCount Return count of Uncacheable type. >=20 > + @param WtCount Return count of Write Through type. >=20 > + @param WbCount Return count of Write Back type. >=20 > + @param WpCount Return count of Write Protected type. >=20 > + @param WcCount Return count of Write Combining type. >=20 > +**/ >=20 > +VOID >=20 > +GenerateRandomMemoryTypeCombination ( >=20 > + IN UINT32 TotalCount, >=20 > + OUT UINT32 *UcCount, >=20 > + OUT UINT32 *WtCount, >=20 > + OUT UINT32 *WbCount, >=20 > + OUT UINT32 *WpCount, >=20 > + OUT UINT32 *WcCount >=20 > + ) >=20 > +{ >=20 > + UINTN Index; >=20 > + UINT32 TotalMtrrCount; >=20 > + UINT32 *CountPerType[5]; >=20 > + >=20 > + CountPerType[0] =3D UcCount; >=20 > + CountPerType[1] =3D WtCount; >=20 > + CountPerType[2] =3D WbCount; >=20 > + CountPerType[3] =3D WpCount; >=20 > + CountPerType[4] =3D WcCount; >=20 > + >=20 > + // >=20 > + // Initialize the count of each cache type to 0. >=20 > + // >=20 > + for (Index =3D 0; Index < ARRAY_SIZE (CountPerType); Index++) { >=20 > + *(CountPerType[Index]) =3D 0; >=20 > + } >=20 > + >=20 > + // >=20 > + // Pick a random count of MTRRs >=20 > + // >=20 > + TotalMtrrCount =3D Random32 (1, TotalCount); >=20 > + for (Index =3D 0; Index < TotalMtrrCount; Index++) { >=20 > + // >=20 > + // For each of them, pick a random cache type. >=20 > + // >=20 > + (*(CountPerType[Random32 (0, ARRAY_SIZE (CountPerType) - 1)]))++; >=20 > + } >=20 > +} >=20 > + >=20 > +/** >=20 > + Unit test of MtrrLib service MtrrSetMemoryAttribute() >=20 > + >=20 > + @param[in] Context Ignored >=20 > + >=20 > + @retval UNIT_TEST_PASSED The Unit test has completed and= the test >=20 > + case was successful. >=20 > + @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has faile= d. >=20 > + >=20 > +**/ >=20 > +UNIT_TEST_STATUS >=20 > +EFIAPI >=20 > +UnitTestMtrrSetMemoryAttributesInMtrrSettings ( >=20 > + IN UNIT_TEST_CONTEXT Context >=20 > + ) >=20 > +{ >=20 > + CONST MTRR_LIB_SYSTEM_PARAMETER *SystemParameter; >=20 > + RETURN_STATUS Status; >=20 > + UINT32 UcCount; >=20 > + UINT32 WtCount; >=20 > + UINT32 WbCount; >=20 > + UINT32 WpCount; >=20 > + UINT32 WcCount; >=20 > + >=20 > + UINT32 MtrrIndex; >=20 > + UINT8 *Scratch; >=20 > + UINTN ScratchSize; >=20 > + MTRR_SETTINGS LocalMtrrs; >=20 > + >=20 > + MTRR_MEMORY_RANGE RawMtrrRange[MTRR_NUMBER_OF_VARIABLE_= MTRR]; >=20 > + MTRR_MEMORY_RANGE ExpectedMemoryRanges[MTRR_NUMBER_OF_F= IXED_MTRR * sizeof (UINT64) + 2 * MTRR_NUMBER_OF_VARIABLE_MTRR + 1]; >=20 > + UINT32 ExpectedVariableMtrrUsage; >=20 > + UINTN ExpectedMemoryRangesCount; >=20 > + >=20 > + MTRR_MEMORY_RANGE ActualMemoryRanges[MTRR_NUMBER_OF_FIX= ED_MTRR * sizeof (UINT64) + 2 * MTRR_NUMBER_OF_VARIABLE_MTRR + 1]; >=20 > + UINT32 ActualVariableMtrrUsage; >=20 > + UINTN ActualMemoryRangesCount; >=20 > + >=20 > + MTRR_SETTINGS *Mtrrs[2]; >=20 > + >=20 > + SystemParameter =3D (MTRR_LIB_SYSTEM_PARAMETER *) Context; >=20 > + GenerateRandomMemoryTypeCombination ( >=20 > + SystemParameter->VariableMtrrCount - PatchPcdGet32 (PcdCpuNumberOfR= eservedVariableMtrrs), >=20 > + &UcCount, &WtCount, &WbCount, &WpCount, &WcCount >=20 > + ); >=20 > + GenerateValidAndConfigurableMtrrPairs ( >=20 > + SystemParameter->PhysicalAddressBits, RawMtrrRange, >=20 > + UcCount, WtCount, WbCount, WpCount, WcCount >=20 > + ); >=20 > + >=20 > + ExpectedVariableMtrrUsage =3D UcCount + WtCount + WbCount + WpCount += WcCount; >=20 > + ExpectedMemoryRangesCount =3D ARRAY_SIZE (ExpectedMemoryRanges); >=20 > + GetEffectiveMemoryRanges ( >=20 > + SystemParameter->DefaultCacheType, >=20 > + SystemParameter->PhysicalAddressBits, >=20 > + RawMtrrRange, ExpectedVariableMtrrUsage, >=20 > + ExpectedMemoryRanges, &ExpectedMemoryRangesCount >=20 > + ); >=20 > + >=20 > + UT_LOG_INFO ( >=20 > + "Total MTRR [%d]: UC=3D%d, WT=3D%d, WB=3D%d, WP=3D%d, WC=3D%d\n", >=20 > + ExpectedVariableMtrrUsage, UcCount, WtCount, WbCount, WpCount, WcCo= unt >=20 > + ); >=20 > + UT_LOG_INFO ("--- Expected Memory Ranges [%d] ---\n", ExpectedMemoryR= angesCount); >=20 > + DumpMemoryRanges (ExpectedMemoryRanges, ExpectedMemoryRangesCount); >=20 > + >=20 > + // >=20 > + // Default cache type is always an INPUT >=20 > + // >=20 > + ZeroMem (&LocalMtrrs, sizeof (LocalMtrrs)); >=20 > + LocalMtrrs.MtrrDefType =3D MtrrGetDefaultMemoryType (); >=20 > + ScratchSize =3D SCRATCH_BUFFER_SIZE; >=20 > + Mtrrs[0] =3D &LocalMtrrs; >=20 > + Mtrrs[1] =3D NULL; >=20 > + >=20 > + for (MtrrIndex =3D 0; MtrrIndex < ARRAY_SIZE (Mtrrs); MtrrIndex++) { >=20 > + Scratch =3D calloc (ScratchSize, sizeof (UINT8)); >=20 > + Status =3D MtrrSetMemoryAttributesInMtrrSettings (Mtrrs[MtrrIndex],= Scratch, &ScratchSize, ExpectedMemoryRanges, ExpectedMemoryRangesCount); >=20 > + if (Status =3D=3D RETURN_BUFFER_TOO_SMALL) { >=20 > + Scratch =3D realloc (Scratch, ScratchSize); >=20 > + Status =3D MtrrSetMemoryAttributesInMtrrSettings (Mtrrs[MtrrIndex= ], Scratch, &ScratchSize, ExpectedMemoryRanges, ExpectedMemoryRangesCount); >=20 > + } >=20 > + UT_ASSERT_STATUS_EQUAL (Status, RETURN_SUCCESS); >=20 > + >=20 > + if (Mtrrs[MtrrIndex] =3D=3D NULL) { >=20 > + ZeroMem (&LocalMtrrs, sizeof (LocalMtrrs)); >=20 > + MtrrGetAllMtrrs (&LocalMtrrs); >=20 > + } >=20 > + ActualMemoryRangesCount =3D ARRAY_SIZE (ActualMemoryRanges); >=20 > + CollectTestResult ( >=20 > + SystemParameter->DefaultCacheType, SystemParameter->PhysicalAddre= ssBits, SystemParameter->VariableMtrrCount, >=20 > + &LocalMtrrs, ActualMemoryRanges, &ActualMemoryRangesCount, &Actua= lVariableMtrrUsage >=20 > + ); >=20 > + >=20 > + UT_LOG_INFO ("--- Actual Memory Ranges [%d] ---\n", ActualMemoryRan= gesCount); >=20 > + DumpMemoryRanges (ActualMemoryRanges, ActualMemoryRangesCount); >=20 > + VerifyMemoryRanges (ExpectedMemoryRanges, ExpectedMemoryRangesCount= , ActualMemoryRanges, ActualMemoryRangesCount); >=20 > + UT_ASSERT_TRUE (ExpectedVariableMtrrUsage >=3D ActualVariableMtrrUs= age); >=20 > + >=20 > + ZeroMem (&LocalMtrrs, sizeof (LocalMtrrs)); >=20 > + } >=20 > + >=20 > + free (Scratch); >=20 > + >=20 > + return UNIT_TEST_PASSED; >=20 > +} >=20 > + >=20 > +/** >=20 > + Test routine to check whether invalid base/size can be rejected. >=20 > + >=20 > + @param Context Pointer to MTRR_LIB_SYSTEM_PARAMETER. >=20 > + >=20 > + @return Test status. >=20 > +**/ >=20 > +UNIT_TEST_STATUS >=20 > +EFIAPI >=20 > +UnitTestInvalidMemoryLayouts ( >=20 > + IN UNIT_TEST_CONTEXT Context >=20 > + ) >=20 > +{ >=20 > + CONST MTRR_LIB_SYSTEM_PARAMETER *SystemParameter; >=20 > + MTRR_MEMORY_RANGE Ranges[MTRR_NUMBER_OF_VARIABLE_MTRR *= 2 + 1]; >=20 > + UINTN RangeCount; >=20 > + UINT64 MaxAddress; >=20 > + UINT32 Index; >=20 > + UINT64 BaseAddress; >=20 > + UINT64 Length; >=20 > + RETURN_STATUS Status; >=20 > + UINTN ScratchSize; >=20 > + >=20 > + SystemParameter =3D (MTRR_LIB_SYSTEM_PARAMETER *) Context; >=20 > + >=20 > + RangeCount =3D Random32 (1, ARRAY_SIZE (Ranges)); >=20 > + MaxAddress =3D 1ull << SystemParameter->PhysicalAddressBits; >=20 > + >=20 > + for (Index =3D 0; Index < RangeCount; Index++) { >=20 > + do { >=20 > + BaseAddress =3D Random64 (0, MaxAddress); >=20 > + Length =3D Random64 (1, MaxAddress - BaseAddress); >=20 > + } while (((BaseAddress & 0xFFF) =3D=3D 0) || ((Length & 0xFFF) =3D= =3D 0)); >=20 > + >=20 > + Ranges[Index].BaseAddress =3D BaseAddress; >=20 > + Ranges[Index].Length =3D Length; >=20 > + Ranges[Index].Type =3D GenerateRandomCacheType (); >=20 > + >=20 > + Status =3D MtrrSetMemoryAttribute ( >=20 > + Ranges[Index].BaseAddress, Ranges[Index].Length, Ranges[Index].Ty= pe >=20 > + ); >=20 > + UT_ASSERT_TRUE (RETURN_ERROR (Status)); >=20 > + } >=20 > + >=20 > + ScratchSize =3D 0; >=20 > + Status =3D MtrrSetMemoryAttributesInMtrrSettings (NULL, NULL, &Scratc= hSize, Ranges, RangeCount); >=20 > + UT_ASSERT_TRUE (RETURN_ERROR (Status)); >=20 > + >=20 > + return UNIT_TEST_PASSED; >=20 > +} >=20 > + >=20 > +/** >=20 > + Unit test of MtrrLib service IsMtrrSupported() >=20 > + >=20 > + @param[in] Context Ignored >=20 > + >=20 > + @retval UNIT_TEST_PASSED The Unit test has completed and= the test >=20 > + case was successful. >=20 > + @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has faile= d. >=20 > + >=20 > +**/ >=20 > +UNIT_TEST_STATUS >=20 > +EFIAPI >=20 > +UnitTestIsMtrrSupported ( >=20 > + IN UNIT_TEST_CONTEXT Context >=20 > + ) >=20 > +{ >=20 > + MTRR_LIB_SYSTEM_PARAMETER SystemParameter; >=20 > + MTRR_LIB_TEST_CONTEXT *LocalContext; >=20 > + >=20 > + LocalContext =3D (MTRR_LIB_TEST_CONTEXT *) Context; >=20 > + >=20 > + CopyMem (&SystemParameter, LocalContext->SystemParameter, sizeof (Sys= temParameter)); >=20 > + // >=20 > + // MTRR capability off in CPUID leaf. >=20 > + // >=20 > + SystemParameter.MtrrSupported =3D FALSE; >=20 > + InitializeMtrrRegs (&SystemParameter); >=20 > + UT_ASSERT_FALSE (IsMtrrSupported ()); >=20 > + >=20 > + // >=20 > + // MTRR capability on in CPUID leaf, but no variable or fixed MTRRs. >=20 > + // >=20 > + SystemParameter.MtrrSupported =3D TRUE; >=20 > + SystemParameter.VariableMtrrCount =3D 0; >=20 > + SystemParameter.FixedMtrrSupported =3D FALSE; >=20 > + InitializeMtrrRegs (&SystemParameter); >=20 > + UT_ASSERT_FALSE (IsMtrrSupported ()); >=20 > + >=20 > + // >=20 > + // MTRR capability on in CPUID leaf, but no variable MTRRs. >=20 > + // >=20 > + SystemParameter.MtrrSupported =3D TRUE; >=20 > + SystemParameter.VariableMtrrCount =3D 0; >=20 > + SystemParameter.FixedMtrrSupported =3D TRUE; >=20 > + InitializeMtrrRegs (&SystemParameter); >=20 > + UT_ASSERT_FALSE (IsMtrrSupported ()); >=20 > + >=20 > + // >=20 > + // MTRR capability on in CPUID leaf, but no fixed MTRRs. >=20 > + // >=20 > + SystemParameter.MtrrSupported =3D TRUE; >=20 > + SystemParameter.VariableMtrrCount =3D 7; >=20 > + SystemParameter.FixedMtrrSupported =3D FALSE; >=20 > + InitializeMtrrRegs (&SystemParameter); >=20 > + UT_ASSERT_FALSE (IsMtrrSupported ()); >=20 > + >=20 > + // >=20 > + // MTRR capability on in CPUID leaf with both variable and fixed MTRR= s. >=20 > + // >=20 > + SystemParameter.MtrrSupported =3D TRUE; >=20 > + SystemParameter.VariableMtrrCount =3D 7; >=20 > + SystemParameter.FixedMtrrSupported =3D TRUE; >=20 > + InitializeMtrrRegs (&SystemParameter); >=20 > + UT_ASSERT_TRUE (IsMtrrSupported ()); >=20 > + >=20 > + return UNIT_TEST_PASSED; >=20 > +} >=20 > + >=20 > +/** >=20 > + Unit test of MtrrLib service GetVariableMtrrCount() >=20 > + >=20 > + @param[in] Context Ignored >=20 > + >=20 > + @retval UNIT_TEST_PASSED The Unit test has completed and= the test >=20 > + case was successful. >=20 > + @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has faile= d. >=20 > + >=20 > +**/ >=20 > +UNIT_TEST_STATUS >=20 > +EFIAPI >=20 > +UnitTestGetVariableMtrrCount ( >=20 > + IN UNIT_TEST_CONTEXT Context >=20 > + ) >=20 > +{ >=20 > + UINT32 Result; >=20 > + MTRR_LIB_SYSTEM_PARAMETER SystemParameter; >=20 > + MTRR_LIB_TEST_CONTEXT *LocalContext; >=20 > + >=20 > + LocalContext =3D (MTRR_LIB_TEST_CONTEXT *) Context; >=20 > + >=20 > + CopyMem (&SystemParameter, LocalContext->SystemParameter, sizeof (Sys= temParameter)); >=20 > + // >=20 > + // If MTRR capability off in CPUID leaf, then the count is always 0. >=20 > + // >=20 > + SystemParameter.MtrrSupported =3D FALSE; >=20 > + for (SystemParameter.VariableMtrrCount =3D 1; SystemParameter.Variabl= eMtrrCount <=3D MTRR_NUMBER_OF_VARIABLE_MTRR; SystemParameter.VariableMtrrC= ount++) { >=20 > + InitializeMtrrRegs (&SystemParameter); >=20 > + Result =3D GetVariableMtrrCount (); >=20 > + UT_ASSERT_EQUAL (Result, 0); >=20 > + } >=20 > + >=20 > + // >=20 > + // Try all supported variable MTRR counts. >=20 > + // If variable MTRR count is > MTRR_NUMBER_OF_VARIABLE_MTRR, then an = ASSERT() >=20 > + // is generated. >=20 > + // >=20 > + SystemParameter.MtrrSupported =3D TRUE; >=20 > + for (SystemParameter.VariableMtrrCount =3D 1; SystemParameter.Variabl= eMtrrCount <=3D MTRR_NUMBER_OF_VARIABLE_MTRR; SystemParameter.VariableMtrrC= ount++) { >=20 > + InitializeMtrrRegs (&SystemParameter); >=20 > + Result =3D GetVariableMtrrCount (); >=20 > + UT_ASSERT_EQUAL (Result, SystemParameter.VariableMtrrCount); >=20 > + } >=20 > + >=20 > + // >=20 > + // Expect ASSERT() if variable MTRR count is > MTRR_NUMBER_OF_VARIABL= E_MTRR >=20 > + // >=20 > + SystemParameter.VariableMtrrCount =3D MTRR_NUMBER_OF_VARIABLE_MTRR + = 1; >=20 > + InitializeMtrrRegs (&SystemParameter); >=20 > + UT_EXPECT_ASSERT_FAILURE (GetVariableMtrrCount (), NULL); >=20 > + >=20 > + SystemParameter.MtrrSupported =3D TRUE; >=20 > + SystemParameter.VariableMtrrCount =3D MAX_UINT8; >=20 > + InitializeMtrrRegs (&SystemParameter); >=20 > + UT_EXPECT_ASSERT_FAILURE (GetVariableMtrrCount (), NULL); >=20 > + >=20 > + return UNIT_TEST_PASSED; >=20 > +} >=20 > + >=20 > +/** >=20 > + Unit test of MtrrLib service GetFirmwareVariableMtrrCount() >=20 > + >=20 > + @param[in] Context Ignored >=20 > + >=20 > + @retval UNIT_TEST_PASSED The Unit test has completed and= the test >=20 > + case was successful. >=20 > + @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has faile= d. >=20 > + >=20 > +**/ >=20 > +UNIT_TEST_STATUS >=20 > +EFIAPI >=20 > +UnitTestGetFirmwareVariableMtrrCount ( >=20 > + IN UNIT_TEST_CONTEXT Context >=20 > + ) >=20 > +{ >=20 > + UINT32 Result; >=20 > + UINT32 ReservedMtrrs; >=20 > + MTRR_LIB_SYSTEM_PARAMETER SystemParameter; >=20 > + MTRR_LIB_GET_FIRMWARE_VARIABLE_MTRR_COUNT_CONTEXT *LocalContext; >=20 > + >=20 > + LocalContext =3D (MTRR_LIB_GET_FIRMWARE_VARIABLE_MTRR_COUNT_CONTEXT *= ) Context; >=20 > + >=20 > + CopyMem (&SystemParameter, LocalContext->SystemParameter, sizeof (Sys= temParameter)); >=20 > + >=20 > + InitializeMtrrRegs (&SystemParameter); >=20 > + // >=20 > + // Positive test cases for VCNT =3D 10 and Reserved PCD in range 0..1= 0 >=20 > + // >=20 > + for (ReservedMtrrs =3D 0; ReservedMtrrs <=3D SystemParameter.Variable= MtrrCount; ReservedMtrrs++) { >=20 > + PatchPcdSet32 (PcdCpuNumberOfReservedVariableMtrrs, ReservedMtrrs); >=20 > + Result =3D GetFirmwareVariableMtrrCount (); >=20 > + UT_ASSERT_EQUAL (Result, SystemParameter.VariableMtrrCount - Reserv= edMtrrs); >=20 > + } >=20 > + >=20 > + // >=20 > + // Negative test cases when Reserved PCD is larger than VCNT >=20 > + // >=20 > + for (ReservedMtrrs =3D SystemParameter.VariableMtrrCount + 1; Reserve= dMtrrs <=3D 255; ReservedMtrrs++) { >=20 > + PatchPcdSet32 (PcdCpuNumberOfReservedVariableMtrrs, ReservedMtrrs); >=20 > + Result =3D GetFirmwareVariableMtrrCount (); >=20 > + UT_ASSERT_EQUAL (Result, 0); >=20 > + } >=20 > + >=20 > + // >=20 > + // Negative test cases when Reserved PCD is larger than VCNT >=20 > + // >=20 > + PatchPcdSet32 (PcdCpuNumberOfReservedVariableMtrrs, MAX_UINT32); >=20 > + Result =3D GetFirmwareVariableMtrrCount (); >=20 > + UT_ASSERT_EQUAL (Result, 0); >=20 > + >=20 > + // >=20 > + // Negative test case when MTRRs are not supported >=20 > + // >=20 > + SystemParameter.MtrrSupported =3D FALSE; >=20 > + InitializeMtrrRegs (&SystemParameter); >=20 > + PatchPcdSet32 (PcdCpuNumberOfReservedVariableMtrrs, 2); >=20 > + Result =3D GetFirmwareVariableMtrrCount (); >=20 > + UT_ASSERT_EQUAL (Result, 0); >=20 > + >=20 > + // >=20 > + // Negative test case when Fixed MTRRs are not supported >=20 > + // >=20 > + SystemParameter.MtrrSupported =3D TRUE; >=20 > + SystemParameter.FixedMtrrSupported =3D FALSE; >=20 > + InitializeMtrrRegs (&SystemParameter); >=20 > + PatchPcdSet32 (PcdCpuNumberOfReservedVariableMtrrs, 2); >=20 > + Result =3D GetFirmwareVariableMtrrCount (); >=20 > + UT_ASSERT_EQUAL (Result, 0); >=20 > + >=20 > + // >=20 > + // Expect ASSERT() if variable MTRR count is > MTRR_NUMBER_OF_VARIABL= E_MTRR >=20 > + // >=20 > + SystemParameter.FixedMtrrSupported =3D TRUE; >=20 > + SystemParameter.VariableMtrrCount =3D MTRR_NUMBER_OF_VARIABLE_MTRR + = 1; >=20 > + InitializeMtrrRegs (&SystemParameter); >=20 > + UT_EXPECT_ASSERT_FAILURE (GetFirmwareVariableMtrrCount (), NULL); >=20 > + >=20 > + return UNIT_TEST_PASSED; >=20 > +} >=20 > + >=20 > +/** >=20 > + Unit test of MtrrLib service MtrrGetMemoryAttribute() >=20 > + >=20 > + @param[in] Context Ignored >=20 > + >=20 > + @retval UNIT_TEST_PASSED The Unit test has completed and= the test >=20 > + case was successful. >=20 > + @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has faile= d. >=20 > + >=20 > +**/ >=20 > +UNIT_TEST_STATUS >=20 > +EFIAPI >=20 > +UnitTestMtrrGetMemoryAttribute ( >=20 > + IN UNIT_TEST_CONTEXT Context >=20 > + ) >=20 > +{ >=20 > + return UNIT_TEST_PASSED; >=20 > +} >=20 > + >=20 > +/** >=20 > + Unit test of MtrrLib service MtrrGetFixedMtrr() >=20 > + >=20 > + @param[in] Context Ignored >=20 > + >=20 > + @retval UNIT_TEST_PASSED The Unit test has completed and= the test >=20 > + case was successful. >=20 > + @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has faile= d. >=20 > + >=20 > +**/ >=20 > +UNIT_TEST_STATUS >=20 > +EFIAPI >=20 > +UnitTestMtrrGetFixedMtrr ( >=20 > + IN UNIT_TEST_CONTEXT Context >=20 > + ) >=20 > +{ >=20 > + MTRR_FIXED_SETTINGS *Result; >=20 > + MTRR_FIXED_SETTINGS ExpectedFixedSettings; >=20 > + MTRR_FIXED_SETTINGS FixedSettings; >=20 > + UINTN Index; >=20 > + UINTN MsrIndex; >=20 > + UINTN ByteIndex; >=20 > + UINT64 MsrValue; >=20 > + MTRR_LIB_SYSTEM_PARAMETER SystemParameter; >=20 > + MTRR_LIB_TEST_CONTEXT *LocalContext; >=20 > + >=20 > + LocalContext =3D (MTRR_LIB_TEST_CONTEXT *) Context; >=20 > + >=20 > + CopyMem (&SystemParameter, LocalContext->SystemParameter, sizeof (Sys= temParameter)); >=20 > + InitializeMtrrRegs (&SystemParameter); >=20 > + // >=20 > + // Set random cache type to different ranges under 1MB and make sure >=20 > + // the fixed MTRR settings are expected. >=20 > + // Try 100 times. >=20 > + // >=20 > + for (Index =3D 0; Index < 100; Index++) { >=20 > + for (MsrIndex =3D 0; MsrIndex < ARRAY_SIZE (mFixedMtrrsIndex); MsrI= ndex++) { >=20 > + MsrValue =3D 0; >=20 > + for (ByteIndex =3D 0; ByteIndex < sizeof (UINT64); ByteIndex++) { >=20 > + MsrValue =3D MsrValue | LShiftU64 (GenerateRandomCacheType (), = ByteIndex * 8); >=20 > + } >=20 > + ExpectedFixedSettings.Mtrr[MsrIndex] =3D MsrValue; >=20 > + AsmWriteMsr64 (mFixedMtrrsIndex[MsrIndex], MsrValue); >=20 > + } >=20 > + >=20 > + Result =3D MtrrGetFixedMtrr (&FixedSettings); >=20 > + UT_ASSERT_EQUAL (Result, &FixedSettings); >=20 > + UT_ASSERT_MEM_EQUAL (&FixedSettings, &ExpectedFixedSettings, sizeof= (FixedSettings)); >=20 > + } >=20 > + >=20 > + // >=20 > + // Negative test case when MTRRs are not supported >=20 > + // >=20 > + SystemParameter.MtrrSupported =3D FALSE; >=20 > + InitializeMtrrRegs (&SystemParameter); >=20 > + >=20 > + ZeroMem (&FixedSettings, sizeof (FixedSettings)); >=20 > + ZeroMem (&ExpectedFixedSettings, sizeof (ExpectedFixedSettings)); >=20 > + Result =3D MtrrGetFixedMtrr (&FixedSettings); >=20 > + UT_ASSERT_EQUAL (Result, &FixedSettings); >=20 > + UT_ASSERT_MEM_EQUAL (&ExpectedFixedSettings, &FixedSettings, sizeof (= ExpectedFixedSettings)); >=20 > + >=20 > + return UNIT_TEST_PASSED; >=20 > +} >=20 > + >=20 > +/** >=20 > + Unit test of MtrrLib service MtrrGetAllMtrrs() >=20 > + >=20 > + @param[in] Context Ignored >=20 > + >=20 > + @retval UNIT_TEST_PASSED The Unit test has completed and= the test >=20 > + case was successful. >=20 > + @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has faile= d. >=20 > + >=20 > +**/ >=20 > +UNIT_TEST_STATUS >=20 > +EFIAPI >=20 > +UnitTestMtrrGetAllMtrrs ( >=20 > + IN UNIT_TEST_CONTEXT Context >=20 > + ) >=20 > +{ >=20 > + MTRR_SETTINGS *Result; >=20 > + MTRR_SETTINGS Mtrrs; >=20 > + MTRR_SETTINGS ExpectedMtrrs; >=20 > + MTRR_VARIABLE_SETTING VariableMtrr[MTRR_NUMBER_OF_VARIABLE_MTRR]; >=20 > + UINT32 Index; >=20 > + MTRR_LIB_SYSTEM_PARAMETER SystemParameter; >=20 > + MTRR_LIB_TEST_CONTEXT *LocalContext; >=20 > + >=20 > + LocalContext =3D (MTRR_LIB_TEST_CONTEXT *) Context; >=20 > + >=20 > + CopyMem (&SystemParameter, LocalContext->SystemParameter, sizeof (Sys= temParameter)); >=20 > + InitializeMtrrRegs (&SystemParameter); >=20 > + >=20 > + for (Index =3D 0; Index < SystemParameter.VariableMtrrCount; Index++)= { >=20 > + GenerateRandomMtrrPair (SystemParameter.PhysicalAddressBits, Genera= teRandomCacheType (), &VariableMtrr[Index], NULL); >=20 > + AsmWriteMsr64 (MSR_IA32_MTRR_PHYSBASE0 + (Index << 1), VariableMtrr= [Index].Base); >=20 > + AsmWriteMsr64 (MSR_IA32_MTRR_PHYSMASK0 + (Index << 1), VariableMtrr= [Index].Mask); >=20 > + } >=20 > + Result =3D MtrrGetAllMtrrs (&Mtrrs); >=20 > + UT_ASSERT_EQUAL (Result, &Mtrrs); >=20 > + UT_ASSERT_MEM_EQUAL (Mtrrs.Variables.Mtrr, VariableMtrr, sizeof (MTRR= _VARIABLE_SETTING) * SystemParameter.VariableMtrrCount); >=20 > + >=20 > + // >=20 > + // Negative test case when MTRRs are not supported >=20 > + // >=20 > + ZeroMem (&ExpectedMtrrs, sizeof (ExpectedMtrrs)); >=20 > + ZeroMem (&Mtrrs, sizeof (Mtrrs)); >=20 > + >=20 > + SystemParameter.MtrrSupported =3D FALSE; >=20 > + InitializeMtrrRegs (&SystemParameter); >=20 > + Result =3D MtrrGetAllMtrrs (&Mtrrs); >=20 > + UT_ASSERT_EQUAL (Result, &Mtrrs); >=20 > + UT_ASSERT_MEM_EQUAL (&ExpectedMtrrs, &Mtrrs, sizeof (ExpectedMtrrs)); >=20 > + >=20 > + // >=20 > + // Expect ASSERT() if variable MTRR count is > MTRR_NUMBER_OF_VARIABL= E_MTRR >=20 > + // >=20 > + SystemParameter.MtrrSupported =3D TRUE; >=20 > + SystemParameter.VariableMtrrCount =3D MTRR_NUMBER_OF_VARIABLE_MTRR + = 1; >=20 > + InitializeMtrrRegs (&SystemParameter); >=20 > + UT_EXPECT_ASSERT_FAILURE (MtrrGetAllMtrrs (&Mtrrs), NULL); >=20 > + >=20 > + return UNIT_TEST_PASSED; >=20 > +} >=20 > + >=20 > +/** >=20 > + Unit test of MtrrLib service MtrrSetAllMtrrs() >=20 > + >=20 > + @param[in] Context Ignored >=20 > + >=20 > + @retval UNIT_TEST_PASSED The Unit test has completed and= the test >=20 > + case was successful. >=20 > + @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has faile= d. >=20 > + >=20 > +**/ >=20 > +UNIT_TEST_STATUS >=20 > +EFIAPI >=20 > +UnitTestMtrrSetAllMtrrs ( >=20 > + IN UNIT_TEST_CONTEXT Context >=20 > + ) >=20 > +{ >=20 > + MTRR_SETTINGS *Result; >=20 > + MTRR_SETTINGS Mtrrs; >=20 > + UINT32 Index; >=20 > + MSR_IA32_MTRR_DEF_TYPE_REGISTER Default; >=20 > + MTRR_LIB_SYSTEM_PARAMETER SystemParameter; >=20 > + MTRR_LIB_TEST_CONTEXT *LocalContext; >=20 > + >=20 > + LocalContext =3D (MTRR_LIB_TEST_CONTEXT *) Context; >=20 > + >=20 > + CopyMem (&SystemParameter, LocalContext->SystemParameter, sizeof (Sys= temParameter)); >=20 > + InitializeMtrrRegs (&SystemParameter); >=20 > + >=20 > + Default.Uint64 =3D 0; >=20 > + Default.Bits.E =3D 1; >=20 > + Default.Bits.FE =3D 1; >=20 > + Default.Bits.Type =3D GenerateRandomCacheType (); >=20 > + >=20 > + ZeroMem (&Mtrrs, sizeof (Mtrrs)); >=20 > + Mtrrs.MtrrDefType =3D Default.Uint64; >=20 > + for (Index =3D 0; Index < SystemParameter.VariableMtrrCount; Index++)= { >=20 > + GenerateRandomMtrrPair (SystemParameter.PhysicalAddressBits, Genera= teRandomCacheType (), &Mtrrs.Variables.Mtrr[Index], NULL); >=20 > + } >=20 > + Result =3D MtrrSetAllMtrrs (&Mtrrs); >=20 > + UT_ASSERT_EQUAL (Result, &Mtrrs); >=20 > + >=20 > + UT_ASSERT_EQUAL (AsmReadMsr64 (MSR_IA32_MTRR_DEF_TYPE), Mtrrs.MtrrDef= Type); >=20 > + for (Index =3D 0; Index < SystemParameter.VariableMtrrCount; Index++)= { >=20 > + UT_ASSERT_EQUAL (AsmReadMsr64 (MSR_IA32_MTRR_PHYSBASE0 + (Index << = 1)), Mtrrs.Variables.Mtrr[Index].Base); >=20 > + UT_ASSERT_EQUAL (AsmReadMsr64 (MSR_IA32_MTRR_PHYSMASK0 + (Index << = 1)), Mtrrs.Variables.Mtrr[Index].Mask); >=20 > + } >=20 > + >=20 > + return UNIT_TEST_PASSED; >=20 > +} >=20 > + >=20 > +/** >=20 > + Unit test of MtrrLib service MtrrGetMemoryAttributeInVariableMtrr() >=20 > + >=20 > + @param[in] Context Ignored >=20 > + >=20 > + @retval UNIT_TEST_PASSED The Unit test has completed and= the test >=20 > + case was successful. >=20 > + @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has faile= d. >=20 > + >=20 > +**/ >=20 > +UNIT_TEST_STATUS >=20 > +EFIAPI >=20 > +UnitTestMtrrGetMemoryAttributeInVariableMtrr ( >=20 > + IN UNIT_TEST_CONTEXT Context >=20 > + ) >=20 > +{ >=20 > + MTRR_LIB_TEST_CONTEXT *LocalContext; >=20 > + MTRR_LIB_SYSTEM_PARAMETER SystemParameter; >=20 > + UINT32 Result; >=20 > + MTRR_VARIABLE_SETTING VariableSetting[MTRR_NUMBER_OF_VARIAB= LE_MTRR]; >=20 > + VARIABLE_MTRR VariableMtrr[MTRR_NUMBER_OF_VARIABLE_= MTRR]; >=20 > + UINT64 ValidMtrrBitsMask; >=20 > + UINT64 ValidMtrrAddressMask; >=20 > + UINT32 Index; >=20 > + MSR_IA32_MTRR_PHYSBASE_REGISTER Base; >=20 > + MSR_IA32_MTRR_PHYSMASK_REGISTER Mask; >=20 > + >=20 > + LocalContext =3D (MTRR_LIB_TEST_CONTEXT *) Context; >=20 > + >=20 > + CopyMem (&SystemParameter, LocalContext->SystemParameter, sizeof (Sys= temParameter)); >=20 > + >=20 > + InitializeMtrrRegs (&SystemParameter); >=20 > + >=20 > + ValidMtrrBitsMask =3D (1ull << SystemParameter.PhysicalAddressBits= ) - 1; >=20 > + ValidMtrrAddressMask =3D ValidMtrrBitsMask & 0xfffffffffffff000ULL; >=20 > + >=20 > + for (Index =3D 0; Index < SystemParameter.VariableMtrrCount; Index++)= { >=20 > + GenerateRandomMtrrPair (SystemParameter.PhysicalAddressBits, Genera= teRandomCacheType (), &VariableSetting[Index], NULL); >=20 > + AsmWriteMsr64 (MSR_IA32_MTRR_PHYSBASE0 + (Index << 1), VariableSett= ing[Index].Base); >=20 > + AsmWriteMsr64 (MSR_IA32_MTRR_PHYSMASK0 + (Index << 1), VariableSett= ing[Index].Mask); >=20 > + } >=20 > + Result =3D MtrrGetMemoryAttributeInVariableMtrr (ValidMtrrBitsMask, V= alidMtrrAddressMask, VariableMtrr); >=20 > + UT_ASSERT_EQUAL (Result, SystemParameter.VariableMtrrCount); >=20 > + >=20 > + for (Index =3D 0; Index < SystemParameter.VariableMtrrCount; Index++)= { >=20 > + Base.Uint64 =3D VariableMtrr[Index].BaseAddress; >=20 > + Base.Bits.Type =3D (UINT32) VariableMtrr[Index].Type; >=20 > + UT_ASSERT_EQUAL (Base.Uint64, VariableSetting[Index].Base); >=20 > + >=20 > + Mask.Uint64 =3D ~(VariableMtrr[Index].Length - 1) & ValidMtrrBit= sMask; >=20 > + Mask.Bits.V =3D 1; >=20 > + UT_ASSERT_EQUAL (Mask.Uint64, VariableSetting[Index].Mask); >=20 > + } >=20 > + >=20 > + // >=20 > + // Negative test case when MTRRs are not supported >=20 > + // >=20 > + SystemParameter.MtrrSupported =3D FALSE; >=20 > + InitializeMtrrRegs (&SystemParameter); >=20 > + Result =3D MtrrGetMemoryAttributeInVariableMtrr (ValidMtrrBitsMask, V= alidMtrrAddressMask, VariableMtrr); >=20 > + UT_ASSERT_EQUAL (Result, 0); >=20 > + >=20 > + // >=20 > + // Expect ASSERT() if variable MTRR count is > MTRR_NUMBER_OF_VARIABL= E_MTRR >=20 > + // >=20 > + SystemParameter.MtrrSupported =3D TRUE; >=20 > + SystemParameter.VariableMtrrCount =3D MTRR_NUMBER_OF_VARIABLE_MTRR + = 1; >=20 > + InitializeMtrrRegs (&SystemParameter); >=20 > + UT_EXPECT_ASSERT_FAILURE (MtrrGetMemoryAttributeInVariableMtrr (Valid= MtrrBitsMask, ValidMtrrAddressMask, VariableMtrr), NULL); >=20 > + >=20 > + return UNIT_TEST_PASSED; >=20 > +} >=20 > + >=20 > +/** >=20 > + Unit test of MtrrLib service MtrrDebugPrintAllMtrrs() >=20 > + >=20 > + @param[in] Context Ignored >=20 > + >=20 > + @retval UNIT_TEST_PASSED The Unit test has completed and= the test >=20 > + case was successful. >=20 > + @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has faile= d. >=20 > + >=20 > +**/ >=20 > +UNIT_TEST_STATUS >=20 > +EFIAPI >=20 > +UnitTestMtrrDebugPrintAllMtrrs ( >=20 > + IN UNIT_TEST_CONTEXT Context >=20 > + ) >=20 > +{ >=20 > + return UNIT_TEST_PASSED; >=20 > +} >=20 > + >=20 > +/** >=20 > + Unit test of MtrrLib service MtrrGetDefaultMemoryType(). >=20 > + >=20 > + @param[in] Context Ignored >=20 > + >=20 > + @retval UNIT_TEST_PASSED The Unit test has completed and= the test >=20 > + case was successful. >=20 > + @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has faile= d. >=20 > + >=20 > +**/ >=20 > +UNIT_TEST_STATUS >=20 > +EFIAPI >=20 > +UnitTestMtrrGetDefaultMemoryType ( >=20 > + IN UNIT_TEST_CONTEXT Context >=20 > + ) >=20 > +{ >=20 > + MTRR_LIB_TEST_CONTEXT *LocalContext; >=20 > + UINTN Index; >=20 > + MTRR_MEMORY_CACHE_TYPE Result; >=20 > + MTRR_LIB_SYSTEM_PARAMETER SystemParameter; >=20 > + MTRR_MEMORY_CACHE_TYPE CacheType[5]; >=20 > + >=20 > + CacheType[0] =3D CacheUncacheable; >=20 > + CacheType[1] =3D CacheWriteCombining; >=20 > + CacheType[2] =3D CacheWriteThrough; >=20 > + CacheType[3] =3D CacheWriteProtected; >=20 > + CacheType[4] =3D CacheWriteBack; >=20 > + >=20 > + LocalContext =3D (MTRR_LIB_TEST_CONTEXT *) Context; >=20 > + >=20 > + CopyMem (&SystemParameter, LocalContext->SystemParameter, sizeof (Sys= temParameter)); >=20 > + // >=20 > + // If MTRRs are supported, then always return the cache type in the M= SR >=20 > + // MSR_IA32_MTRR_DEF_TYPE >=20 > + // >=20 > + for (Index =3D 0; Index < ARRAY_SIZE (CacheType); Index++) { >=20 > + SystemParameter.DefaultCacheType =3D CacheType[Index]; >=20 > + InitializeMtrrRegs (&SystemParameter); >=20 > + Result =3D MtrrGetDefaultMemoryType (); >=20 > + UT_ASSERT_EQUAL (Result, SystemParameter.DefaultCacheType); >=20 > + } >=20 > + >=20 > + // >=20 > + // If MTRRs are not supported, then always return CacheUncacheable >=20 > + // >=20 > + SystemParameter.MtrrSupported =3D FALSE; >=20 > + InitializeMtrrRegs (&SystemParameter); >=20 > + Result =3D MtrrGetDefaultMemoryType (); >=20 > + UT_ASSERT_EQUAL (Result, CacheUncacheable); >=20 > + >=20 > + SystemParameter.MtrrSupported =3D TRUE; >=20 > + SystemParameter.FixedMtrrSupported =3D FALSE; >=20 > + InitializeMtrrRegs (&SystemParameter); >=20 > + Result =3D MtrrGetDefaultMemoryType (); >=20 > + UT_ASSERT_EQUAL (Result, CacheUncacheable); >=20 > + >=20 > + SystemParameter.MtrrSupported =3D TRUE; >=20 > + SystemParameter.FixedMtrrSupported =3D TRUE; >=20 > + SystemParameter.VariableMtrrCount =3D 0; >=20 > + InitializeMtrrRegs (&SystemParameter); >=20 > + Result =3D MtrrGetDefaultMemoryType (); >=20 > + UT_ASSERT_EQUAL (Result, CacheUncacheable); >=20 > + >=20 > + return UNIT_TEST_PASSED; >=20 > +} >=20 > + >=20 > +/** >=20 > + Unit test of MtrrLib service MtrrSetMemoryAttributeInMtrrSettings(). >=20 > + >=20 > + @param[in] Context Ignored >=20 > + >=20 > + @retval UNIT_TEST_PASSED The Unit test has completed and= the test >=20 > + case was successful. >=20 > + @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has faile= d. >=20 > + >=20 > +**/ >=20 > +UNIT_TEST_STATUS >=20 > +EFIAPI >=20 > +UnitTestMtrrSetMemoryAttributeInMtrrSettings ( >=20 > + IN UNIT_TEST_CONTEXT Context >=20 > + ) >=20 > +{ >=20 > + CONST MTRR_LIB_SYSTEM_PARAMETER *SystemParameter; >=20 > + RETURN_STATUS Status; >=20 > + UINT32 UcCount; >=20 > + UINT32 WtCount; >=20 > + UINT32 WbCount; >=20 > + UINT32 WpCount; >=20 > + UINT32 WcCount; >=20 > + >=20 > + UINTN MtrrIndex; >=20 > + UINTN Index; >=20 > + MTRR_SETTINGS LocalMtrrs; >=20 > + >=20 > + MTRR_MEMORY_RANGE RawMtrrRange[MTRR_NUMBER_OF_VARIABLE_= MTRR]; >=20 > + MTRR_MEMORY_RANGE ExpectedMemoryRanges[MTRR_NUMBER_OF_F= IXED_MTRR * sizeof (UINT64) + 2 * MTRR_NUMBER_OF_VARIABLE_MTRR + 1]; >=20 > + UINT32 ExpectedVariableMtrrUsage; >=20 > + UINTN ExpectedMemoryRangesCount; >=20 > + >=20 > + MTRR_MEMORY_RANGE ActualMemoryRanges[MTRR_NUMBER_OF_FIX= ED_MTRR * sizeof (UINT64) + 2 * MTRR_NUMBER_OF_VARIABLE_MTRR + 1]; >=20 > + UINT32 ActualVariableMtrrUsage; >=20 > + UINTN ActualMemoryRangesCount; >=20 > + >=20 > + MTRR_SETTINGS *Mtrrs[2]; >=20 > + >=20 > + SystemParameter =3D (MTRR_LIB_SYSTEM_PARAMETER *) Context; >=20 > + GenerateRandomMemoryTypeCombination ( >=20 > + SystemParameter->VariableMtrrCount - PatchPcdGet32 (PcdCpuNumberOfR= eservedVariableMtrrs), >=20 > + &UcCount, &WtCount, &WbCount, &WpCount, &WcCount >=20 > + ); >=20 > + GenerateValidAndConfigurableMtrrPairs ( >=20 > + SystemParameter->PhysicalAddressBits, RawMtrrRange, >=20 > + UcCount, WtCount, WbCount, WpCount, WcCount >=20 > + ); >=20 > + >=20 > + ExpectedVariableMtrrUsage =3D UcCount + WtCount + WbCount + WpCount += WcCount; >=20 > + ExpectedMemoryRangesCount =3D ARRAY_SIZE (ExpectedMemoryRanges); >=20 > + GetEffectiveMemoryRanges ( >=20 > + SystemParameter->DefaultCacheType, >=20 > + SystemParameter->PhysicalAddressBits, >=20 > + RawMtrrRange, ExpectedVariableMtrrUsage, >=20 > + ExpectedMemoryRanges, &ExpectedMemoryRangesCount >=20 > + ); >=20 > + >=20 > + UT_LOG_INFO ("--- Expected Memory Ranges [%d] ---\n", ExpectedMemoryR= angesCount); >=20 > + DumpMemoryRanges (ExpectedMemoryRanges, ExpectedMemoryRangesCount); >=20 > + // >=20 > + // Default cache type is always an INPUT >=20 > + // >=20 > + ZeroMem (&LocalMtrrs, sizeof (LocalMtrrs)); >=20 > + LocalMtrrs.MtrrDefType =3D MtrrGetDefaultMemoryType (); >=20 > + Mtrrs[0] =3D &LocalMtrrs; >=20 > + Mtrrs[1] =3D NULL; >=20 > + >=20 > + for (MtrrIndex =3D 0; MtrrIndex < ARRAY_SIZE (Mtrrs); MtrrIndex++) { >=20 > + for (Index =3D 0; Index < ExpectedMemoryRangesCount; Index++) { >=20 > + Status =3D MtrrSetMemoryAttributeInMtrrSettings ( >=20 > + Mtrrs[MtrrIndex], >=20 > + ExpectedMemoryRanges[Index].BaseAddress, >=20 > + ExpectedMemoryRanges[Index].Length, >=20 > + ExpectedMemoryRanges[Index].Type >=20 > + ); >=20 > + UT_ASSERT_TRUE (Status =3D=3D RETURN_SUCCESS || Status =3D=3D RET= URN_OUT_OF_RESOURCES || Status =3D=3D RETURN_BUFFER_TOO_SMALL); >=20 > + if (Status =3D=3D RETURN_OUT_OF_RESOURCES || Status =3D=3D RETURN= _BUFFER_TOO_SMALL) { >=20 > + return UNIT_TEST_SKIPPED; >=20 > + } >=20 > + } >=20 > + >=20 > + if (Mtrrs[MtrrIndex] =3D=3D NULL) { >=20 > + ZeroMem (&LocalMtrrs, sizeof (LocalMtrrs)); >=20 > + MtrrGetAllMtrrs (&LocalMtrrs); >=20 > + } >=20 > + ActualMemoryRangesCount =3D ARRAY_SIZE (ActualMemoryRanges); >=20 > + CollectTestResult ( >=20 > + SystemParameter->DefaultCacheType, SystemParameter->PhysicalAddre= ssBits, SystemParameter->VariableMtrrCount, >=20 > + &LocalMtrrs, ActualMemoryRanges, &ActualMemoryRangesCount, &Actua= lVariableMtrrUsage >=20 > + ); >=20 > + UT_LOG_INFO ("--- Actual Memory Ranges [%d] ---\n", ActualMemoryRan= gesCount); >=20 > + DumpMemoryRanges (ActualMemoryRanges, ActualMemoryRangesCount); >=20 > + VerifyMemoryRanges (ExpectedMemoryRanges, ExpectedMemoryRangesCount= , ActualMemoryRanges, ActualMemoryRangesCount); >=20 > + UT_ASSERT_TRUE (ExpectedVariableMtrrUsage >=3D ActualVariableMtrrUs= age); >=20 > + >=20 > + ZeroMem (&LocalMtrrs, sizeof (LocalMtrrs)); >=20 > + } >=20 > + >=20 > + return UNIT_TEST_PASSED; >=20 > +} >=20 > + >=20 > + >=20 > +/** >=20 > + Prep routine for UnitTestGetFirmwareVariableMtrrCount(). >=20 > + >=20 > + @param Context Point to a UINT32 data to save the PcdCpuNumberOfRese= rvedVariableMtrrs. >=20 > +**/ >=20 > +UNIT_TEST_STATUS >=20 > +EFIAPI >=20 > +SavePcdValue ( >=20 > + UNIT_TEST_CONTEXT Context >=20 > + ) >=20 > +{ >=20 > + MTRR_LIB_GET_FIRMWARE_VARIABLE_MTRR_COUNT_CONTEXT *LocalContext; >=20 > + >=20 > + LocalContext =3D (MTRR_LIB_GET_FIRMWARE_VARIABLE_MTRR_COUNT_CONTEXT *= ) Context; >=20 > + LocalContext->NumberOfReservedVariableMtrrs =3D PatchPcdGet32 (PcdCpu= NumberOfReservedVariableMtrrs); >=20 > + return UNIT_TEST_PASSED; >=20 > +} >=20 > + >=20 > +/** >=20 > + Clean up routine for UnitTestGetFirmwareVariableMtrrCount(). >=20 > + >=20 > + @param Context Point to a UINT32 data to save the PcdCpuNumberOfRese= rvedVariableMtrrs. >=20 > +**/ >=20 > +VOID >=20 > +EFIAPI >=20 > +RestorePcdValue ( >=20 > + UNIT_TEST_CONTEXT Context >=20 > + ) >=20 > +{ >=20 > + MTRR_LIB_GET_FIRMWARE_VARIABLE_MTRR_COUNT_CONTEXT *LocalContext; >=20 > + >=20 > + LocalContext =3D (MTRR_LIB_GET_FIRMWARE_VARIABLE_MTRR_COUNT_CONTEXT *= ) Context; >=20 > + PatchPcdSet32 (PcdCpuNumberOfReservedVariableMtrrs, LocalContext->Num= berOfReservedVariableMtrrs); >=20 > +} >=20 > + >=20 > +/** >=20 > + Initialize the unit test framework, suite, and unit tests for the >=20 > + ResetSystemLib and run the ResetSystemLib unit test. >=20 > + >=20 > + @param Iteration Iteration of testing MtrrSetMemoryAttr= ibuteInMtrrSettings >=20 > + and MtrrSetMemoryAttributesInMtrrSetti= ngs using random inputs. >=20 > + >=20 > + @retval EFI_SUCCESS All test cases were dispatched. >=20 > + @retval EFI_OUT_OF_RESOURCES There are not enough resources availab= le to >=20 > + initialize the unit tests. >=20 > +**/ >=20 > +STATIC >=20 > +EFI_STATUS >=20 > +EFIAPI >=20 > +UnitTestingEntry ( >=20 > + UINTN Iteration >=20 > + ) >=20 > +{ >=20 > + EFI_STATUS Status; >=20 > + UNIT_TEST_FRAMEWORK_HANDLE Framework; >=20 > + UNIT_TEST_SUITE_HANDLE MtrrApiTests; >=20 > + UINTN Index; >=20 > + UINTN SystemIndex; >=20 > + MTRR_LIB_TEST_CONTEXT Context; >=20 > + MTRR_LIB_GET_FIRMWARE_VARIABLE_MTRR_COUNT_CONTEXT GetFirmwareVariable= MtrrCountContext; >=20 > + >=20 > + Context.SystemParameter =3D &mDefaultSyst= emParameter; >=20 > + GetFirmwareVariableMtrrCountContext.SystemParameter =3D &mDefaultSyst= emParameter; >=20 > + Framework =3D NULL; >=20 > + >=20 > + DEBUG ((DEBUG_INFO, "%a v%a\n", UNIT_TEST_APP_NAME, UNIT_TEST_APP_VER= SION)); >=20 > + >=20 > + // >=20 > + // Setup the test framework for running the tests. >=20 > + // >=20 > + Status =3D InitUnitTestFramework (&Framework, UNIT_TEST_APP_NAME, gEf= iCallerBaseName, UNIT_TEST_APP_VERSION); >=20 > + if (EFI_ERROR (Status)) { >=20 > + DEBUG ((DEBUG_ERROR, "Failed in InitUnitTestFramework. Status =3D %= r\n", Status)); >=20 > + goto EXIT; >=20 > + } >=20 > + >=20 > + // >=20 > + // --------------Suite-----------Description--------------Name-------= ---Function--------Pre---Post-------------------Context----------- >=20 > + // >=20 > + >=20 > + // >=20 > + // Populate the MtrrLib API Unit Test Suite. >=20 > + // >=20 > + Status =3D CreateUnitTestSuite (&MtrrApiTests, Framework, "MtrrLib AP= I Tests", "MtrrLib.MtrrLib", NULL, NULL); >=20 > + if (EFI_ERROR (Status)) { >=20 > + DEBUG ((DEBUG_ERROR, "Failed in CreateUnitTestSuite for MtrrLib API= Tests\n")); >=20 > + Status =3D EFI_OUT_OF_RESOURCES; >=20 > + goto EXIT; >=20 > + } >=20 > + AddTestCase (MtrrApiTests, "Test IsMtrrSupported", = "MtrrSupported", UnitTestIsMtrrSupported, = NULL, NULL, &Context); >=20 > + AddTestCase (MtrrApiTests, "Test GetVariableMtrrCount", = "GetVariableMtrrCount", UnitTestGetVariableMtrrCount, = NULL, NULL, &Context); >=20 > + AddTestCase (MtrrApiTests, "Test GetFirmwareVariableMtrrCount", = "GetFirmwareVariableMtrrCount", UnitTestGetFirmwareVariableMtrrC= ount, SavePcdValue, RestorePcdValue, &GetFirmwareVariableMtrrCountC= ontext); >=20 > + AddTestCase (MtrrApiTests, "Test MtrrGetMemoryAttribute", = "MtrrGetMemoryAttribute", UnitTestMtrrGetMemoryAttribute, = NULL, NULL, &Context); >=20 > + AddTestCase (MtrrApiTests, "Test MtrrGetFixedMtrr", = "MtrrGetFixedMtrr", UnitTestMtrrGetFixedMtrr, = NULL, NULL, &Context); >=20 > + AddTestCase (MtrrApiTests, "Test MtrrGetAllMtrrs", = "MtrrGetAllMtrrs", UnitTestMtrrGetAllMtrrs, = NULL, NULL, &Context); >=20 > + AddTestCase (MtrrApiTests, "Test MtrrSetAllMtrrs", = "MtrrSetAllMtrrs", UnitTestMtrrSetAllMtrrs, = NULL, NULL, &Context); >=20 > + AddTestCase (MtrrApiTests, "Test MtrrGetMemoryAttributeInVariableMtrr= ", "MtrrGetMemoryAttributeInVariableMtrr", UnitTestMtrrGetMemoryAttributeIn= VariableMtrr, NULL, NULL, &Context); >=20 > + AddTestCase (MtrrApiTests, "Test MtrrDebugPrintAllMtrrs", = "MtrrDebugPrintAllMtrrs", UnitTestMtrrDebugPrintAllMtrrs, = NULL, NULL, &Context); >=20 > + AddTestCase (MtrrApiTests, "Test MtrrGetDefaultMemoryType", = "MtrrGetDefaultMemoryType", UnitTestMtrrGetDefaultMemoryType= , NULL, NULL, &Context); >=20 > + >=20 > + for (SystemIndex =3D 0; SystemIndex < ARRAY_SIZE (mSystemParameters);= SystemIndex++) { >=20 > + for (Index =3D 0; Index < Iteration; Index++) { >=20 > + AddTestCase (MtrrApiTests, "Test InvalidMemoryLayouts", = "InvalidMemoryLayouts", UnitTestInvalidMemoryLayou= ts, InitializeSystem, NULL, &mSystemParameters[SystemIndex= ]); >=20 > + AddTestCase (MtrrApiTests, "Test MtrrSetMemoryAttributeInMtrrSett= ings", "MtrrSetMemoryAttributeInMtrrSettings", UnitTestMtrrSetMemoryAttri= buteInMtrrSettings, InitializeSystem, NULL, &mSystemParameters[SystemIndex= ]); >=20 > + AddTestCase (MtrrApiTests, "Test MtrrSetMemoryAttributesInMtrrSet= tings", "MtrrSetMemoryAttributesInMtrrSettings", UnitTestMtrrSetMemoryAttri= butesInMtrrSettings, InitializeSystem, NULL, &mSystemParameters[SystemIndex= ]); >=20 > + } >=20 > + } >=20 > + // >=20 > + // Execute the tests. >=20 > + // >=20 > + srand ((unsigned int) time (NULL)); >=20 > + Status =3D RunAllTestSuites (Framework); >=20 > + >=20 > +EXIT: >=20 > + if (Framework !=3D NULL) { >=20 > + FreeUnitTestFramework (Framework); >=20 > + } >=20 > + >=20 > + return Status; >=20 > +} >=20 > + >=20 > +/** >=20 > + Standard POSIX C entry point for host based unit test execution. >=20 > + >=20 > + @param Argc Number of arguments. >=20 > + @param Argv Array of arguments. >=20 > + >=20 > + @return Test application exit code. >=20 > +**/ >=20 > +INT32 >=20 > +main ( >=20 > + INT32 Argc, >=20 > + CHAR8 *Argv[] >=20 > + ) >=20 > +{ >=20 > + UINTN Iteration; >=20 > + >=20 > + // >=20 > + // First parameter specifies the test iterations. >=20 > + // Default is 10. >=20 > + // >=20 > + Iteration =3D 10; >=20 > + if (Argc =3D=3D 2) { >=20 > + Iteration =3D atoi (Argv[1]); >=20 > + } >=20 > + return UnitTestingEntry (Iteration); >=20 > +} >=20 > diff --git a/UefiCpuPkg/Library/MtrrLib/UnitTest/MtrrLibUnitTest.h b/Uef= iCpuPkg/Library/MtrrLib/UnitTest/MtrrLibUnitTest.h > new file mode 100644 > index 0000000000..9750523133 > --- /dev/null > +++ b/UefiCpuPkg/Library/MtrrLib/UnitTest/MtrrLibUnitTest.h > @@ -0,0 +1,182 @@ > +/** @file >=20 > + >=20 > + Copyright (c) 2020, Intel Corporation. All rights reserved.
>=20 > + SPDX-License-Identifier: BSD-2-Clause-Patent >=20 > + >=20 > +**/ >=20 > + >=20 > +#ifndef _MTRR_SUPPORT_H_ >=20 > +#define _MTRR_SUPPORT_H_ >=20 > + >=20 > +#include >=20 > +#include >=20 > +#include >=20 > +#include >=20 > +#include >=20 > +#include >=20 > +#include >=20 > +#include >=20 > + >=20 > +#include >=20 > +#include >=20 > +#include >=20 > +#include >=20 > +#include >=20 > +#include >=20 > +#include >=20 > + >=20 > +#include >=20 > +#include >=20 > +#include >=20 > + >=20 > +#define UNIT_TEST_APP_NAME "MtrrLib Unit Tests" >=20 > +#define UNIT_TEST_APP_VERSION "1.0" >=20 > + >=20 > +#define SCRATCH_BUFFER_SIZE SIZE_16KB >=20 > + >=20 > +typedef struct { >=20 > + UINT8 PhysicalAddressBits; >=20 > + BOOLEAN MtrrSupported; >=20 > + BOOLEAN FixedMtrrSupported; >=20 > + MTRR_MEMORY_CACHE_TYPE DefaultCacheType; >=20 > + UINT32 VariableMtrrCount; >=20 > +} MTRR_LIB_SYSTEM_PARAMETER; >=20 > + >=20 > +extern UINT32 mFixedMtrrsIndex[]; >=20 > + >=20 > +/** >=20 > + Initialize the MTRR registers. >=20 > + >=20 > + @param SystemParameter System parameter that controls the MTRR regist= ers initialization. >=20 > +**/ >=20 > +UNIT_TEST_STATUS >=20 > +EFIAPI >=20 > +InitializeMtrrRegs ( >=20 > + IN MTRR_LIB_SYSTEM_PARAMETER *SystemParameter >=20 > + ); >=20 > + >=20 > +/** >=20 > + Initialize the MTRR registers. >=20 > + >=20 > + @param Context System parameter that controls the MTRR registers init= ialization. >=20 > +**/ >=20 > +UNIT_TEST_STATUS >=20 > +EFIAPI >=20 > +InitializeSystem ( >=20 > + IN UNIT_TEST_CONTEXT Context >=20 > + ); >=20 > + >=20 > +/** >=20 > + Return a random memory cache type. >=20 > +**/ >=20 > +MTRR_MEMORY_CACHE_TYPE >=20 > +GenerateRandomCacheType ( >=20 > + VOID >=20 > + ); >=20 > + >=20 > +/** >=20 > + Generate random MTRRs. >=20 > + >=20 > + @param PhysicalAddressBits Physical address bits. >=20 > + @param RawMemoryRanges Return the randomly generated MTRRs. >=20 > + @param UcCount Count of Uncacheable MTRRs. >=20 > + @param WtCount Count of Write Through MTRRs. >=20 > + @param WbCount Count of Write Back MTRRs. >=20 > + @param WpCount Count of Write Protected MTRRs. >=20 > + @param WcCount Count of Write Combining MTRRs. >=20 > +**/ >=20 > +VOID >=20 > +GenerateValidAndConfigurableMtrrPairs ( >=20 > + IN UINT32 PhysicalAddressBits, >=20 > + IN OUT MTRR_MEMORY_RANGE *RawMemoryRanges, >=20 > + IN UINT32 UcCount, >=20 > + IN UINT32 WtCount, >=20 > + IN UINT32 WbCount, >=20 > + IN UINT32 WpCount, >=20 > + IN UINT32 WcCount >=20 > + ); >=20 > + >=20 > +/** >=20 > + Convert the MTRR BASE/MASK array to memory ranges. >=20 > + >=20 > + @param DefaultType Default memory type. >=20 > + @param PhysicalAddressBits Physical address bits. >=20 > + @param RawMemoryRanges Raw memory ranges. >=20 > + @param RawMemoryRangeCount Count of raw memory ranges. >=20 > + @param MemoryRanges Memory ranges. >=20 > + @param MemoryRangeCount Count of memory ranges. >=20 > +**/ >=20 > +VOID >=20 > +GetEffectiveMemoryRanges ( >=20 > + IN MTRR_MEMORY_CACHE_TYPE DefaultType, >=20 > + IN UINT32 PhysicalAddressBits, >=20 > + IN MTRR_MEMORY_RANGE *RawMemoryRanges, >=20 > + IN UINT32 RawMemoryRangeCount, >=20 > + OUT MTRR_MEMORY_RANGE *MemoryRanges, >=20 > + OUT UINTN *MemoryRangeCount >=20 > + ); >=20 > + >=20 > +/** >=20 > + Generate random MTRR BASE/MASK for a specified type. >=20 > + >=20 > + @param PhysicalAddressBits Physical address bits. >=20 > + @param CacheType Cache type. >=20 > + @param MtrrPair Return the random MTRR. >=20 > + @param MtrrMemoryRange Return the random memory range. >=20 > +**/ >=20 > +VOID >=20 > +GenerateRandomMtrrPair ( >=20 > + IN UINT32 PhysicalAddressBits, >=20 > + IN MTRR_MEMORY_CACHE_TYPE CacheType, >=20 > + OUT MTRR_VARIABLE_SETTING *MtrrPair, OPTIONAL >=20 > + OUT MTRR_MEMORY_RANGE *MtrrMemoryRange OPTIONAL >=20 > + ); >=20 > + >=20 > +/** >=20 > + Collect the test result. >=20 > + >=20 > + @param DefaultType Default memory type. >=20 > + @param PhysicalAddressBits Physical address bits. >=20 > + @param VariableMtrrCount Count of variable MTRRs. >=20 > + @param Mtrrs MTRR settings to collect from. >=20 > + @param Ranges Return the memory ranges. >=20 > + @param RangeCount Return the count of memory ranges. >=20 > + @param MtrrCount Return the count of variable MTRRs being = used. >=20 > +**/ >=20 > +VOID >=20 > +CollectTestResult ( >=20 > + IN MTRR_MEMORY_CACHE_TYPE DefaultType, >=20 > + IN UINT32 PhysicalAddressBits, >=20 > + IN UINT32 VariableMtrrCount, >=20 > + IN MTRR_SETTINGS *Mtrrs, >=20 > + OUT MTRR_MEMORY_RANGE *Ranges, >=20 > + IN OUT UINTN *RangeCount, >=20 > + OUT UINT32 *MtrrCount >=20 > + ); >=20 > + >=20 > +/** >=20 > + Return a 64bit random number. >=20 > + >=20 > + @param Start Start of the random number range. >=20 > + @param Limit Limit of the random number range. >=20 > + @return 64bit random number >=20 > +**/ >=20 > +UINT64 >=20 > +Random64 ( >=20 > + UINT64 Start, >=20 > + UINT64 Limit >=20 > + ); >=20 > + >=20 > +/** >=20 > + Return a 32bit random number. >=20 > + >=20 > + @param Start Start of the random number range. >=20 > + @param Limit Limit of the random number range. >=20 > + @return 32bit random number >=20 > +**/ >=20 > +UINT32 >=20 > +Random32 ( >=20 > + UINT32 Start, >=20 > + UINT32 Limit >=20 > + ); >=20 > +#endif >=20 > diff --git a/UefiCpuPkg/Library/MtrrLib/UnitTest/MtrrLibUnitTestHost.inf= b/UefiCpuPkg/Library/MtrrLib/UnitTest/MtrrLibUnitTestHost.inf > new file mode 100644 > index 0000000000..447238dc81 > --- /dev/null > +++ b/UefiCpuPkg/Library/MtrrLib/UnitTest/MtrrLibUnitTestHost.inf > @@ -0,0 +1,39 @@ > +## @file >=20 > +# Unit tests of the MtrrLib instance of the MtrrLib class >=20 > +# >=20 > +# Copyright (c) 2020, Intel Corporation. All rights reserved.
>=20 > +# SPDX-License-Identifier: BSD-2-Clause-Patent >=20 > +## >=20 > + >=20 > +[Defines] >=20 > + INF_VERSION =3D 0x00010006 >=20 > + BASE_NAME =3D MtrrLibUnitTestHost >=20 > + FILE_GUID =3D A1542D84-B64D-4847-885E-0509084376= AB >=20 > + MODULE_TYPE =3D HOST_APPLICATION >=20 > + VERSION_STRING =3D 1.0 >=20 > + >=20 > +# >=20 > +# The following information is for reference only and not required by t= he build tools. >=20 > +# >=20 > +# VALID_ARCHITECTURES =3D IA32 X64 >=20 > +# >=20 > + >=20 > +[Sources] >=20 > + MtrrLibUnitTest.c >=20 > + MtrrLibUnitTest.h >=20 > + Support.c >=20 > + >=20 > +[Packages] >=20 > + MdePkg/MdePkg.dec >=20 > + UefiCpuPkg/UefiCpuPkg.dec >=20 > + UnitTestFrameworkPkg/UnitTestFrameworkPkg.dec >=20 > + >=20 > +[LibraryClasses] >=20 > + BaseLib >=20 > + BaseMemoryLib >=20 > + DebugLib >=20 > + MtrrLib >=20 > + UnitTestLib >=20 > + >=20 > +[Pcd] >=20 > + gUefiCpuPkgTokenSpaceGuid.PcdCpuNumberOfReservedVariableMtrrs ## SO= METIMES_CONSUMES >=20 > diff --git a/UefiCpuPkg/Library/MtrrLib/UnitTest/Support.c b/UefiCpuPkg/= Library/MtrrLib/UnitTest/Support.c > new file mode 100644 > index 0000000000..a7eed45940 > --- /dev/null > +++ b/UefiCpuPkg/Library/MtrrLib/UnitTest/Support.c > @@ -0,0 +1,923 @@ > +/** @file >=20 > + Unit tests of the MtrrLib instance of the MtrrLib class >=20 > + >=20 > + Copyright (c) 2018 - 2020, Intel Corporation. All rights reserved. >=20 > + SPDX-License-Identifier: BSD-2-Clause-Patent >=20 > + >=20 > +**/ >=20 > + >=20 > +#include "MtrrLibUnitTest.h" >=20 > + >=20 > +MTRR_MEMORY_CACHE_TYPE mMemoryCacheTypes[] =3D { >=20 > + CacheUncacheable, CacheWriteCombining, CacheWriteThrough, CacheWriteP= rotected, CacheWriteBack >=20 > + }; >=20 > + >=20 > +UINT64 mFixedMtrrsValue[MTRR_NUMBER_OF_FIXED_= MTRR]; >=20 > +MSR_IA32_MTRR_PHYSBASE_REGISTER mVariableMtrrsPhysBase[MTRR_NUMBER_OF_= VARIABLE_MTRR]; >=20 > +MSR_IA32_MTRR_PHYSMASK_REGISTER mVariableMtrrsPhysMask[MTRR_NUMBER_OF_= VARIABLE_MTRR]; >=20 > +MSR_IA32_MTRR_DEF_TYPE_REGISTER mDefTypeMsr; >=20 > +MSR_IA32_MTRRCAP_REGISTER mMtrrCapMsr; >=20 > +CPUID_VERSION_INFO_EDX mCpuidVersionInfoEdx; >=20 > +CPUID_VIR_PHY_ADDRESS_SIZE_EAX mCpuidVirPhyAddressSizeEax; >=20 > + >=20 > +/** >=20 > + Retrieves CPUID information. >=20 > + >=20 > + Executes the CPUID instruction with EAX set to the value specified by= Index. >=20 > + This function always returns Index. >=20 > + If Eax is not NULL, then the value of EAX after CPUID is returned in = Eax. >=20 > + If Ebx is not NULL, then the value of EBX after CPUID is returned in = Ebx. >=20 > + If Ecx is not NULL, then the value of ECX after CPUID is returned in = Ecx. >=20 > + If Edx is not NULL, then the value of EDX after CPUID is returned in = Edx. >=20 > + This function is only available on IA-32 and x64. >=20 > + >=20 > + @param Index The 32-bit value to load into EAX prior to invoking the= CPUID >=20 > + instruction. >=20 > + @param Eax The pointer to the 32-bit EAX value returned by the CPU= ID >=20 > + instruction. This is an optional parameter that may be = NULL. >=20 > + @param Ebx The pointer to the 32-bit EBX value returned by the CPU= ID >=20 > + instruction. This is an optional parameter that may be = NULL. >=20 > + @param Ecx The pointer to the 32-bit ECX value returned by the CPU= ID >=20 > + instruction. This is an optional parameter that may be = NULL. >=20 > + @param Edx The pointer to the 32-bit EDX value returned by the CPU= ID >=20 > + instruction. This is an optional parameter that may be = NULL. >=20 > + >=20 > + @return Index. >=20 > + >=20 > +**/ >=20 > +UINT32 >=20 > +EFIAPI >=20 > +UnitTestMtrrLibAsmCpuid ( >=20 > + IN UINT32 Index, >=20 > + OUT UINT32 *Eax, OPTIONAL >=20 > + OUT UINT32 *Ebx, OPTIONAL >=20 > + OUT UINT32 *Ecx, OPTIONAL >=20 > + OUT UINT32 *Edx OPTIONAL >=20 > + ) >=20 > +{ >=20 > + switch (Index) { >=20 > + case CPUID_VERSION_INFO: >=20 > + if (Edx !=3D NULL) { >=20 > + *Edx =3D mCpuidVersionInfoEdx.Uint32; >=20 > + } >=20 > + return Index; >=20 > + break; >=20 > + case CPUID_EXTENDED_FUNCTION: >=20 > + if (Eax !=3D NULL) { >=20 > + *Eax =3D CPUID_VIR_PHY_ADDRESS_SIZE; >=20 > + } >=20 > + return Index; >=20 > + break; >=20 > + case CPUID_VIR_PHY_ADDRESS_SIZE: >=20 > + if (Eax !=3D NULL) { >=20 > + *Eax =3D mCpuidVirPhyAddressSizeEax.Uint32; >=20 > + } >=20 > + return Index; >=20 > + break; >=20 > + } >=20 > + >=20 > + // >=20 > + // Should never fall through to here >=20 > + // >=20 > + ASSERT(FALSE); >=20 > + return Index; >=20 > +} >=20 > + >=20 > +/** >=20 > + Returns a 64-bit Machine Specific Register(MSR). >=20 > + >=20 > + Reads and returns the 64-bit MSR specified by Index. No parameter che= cking is >=20 > + performed on Index, and some Index values may cause CPU exceptions. T= he >=20 > + caller must either guarantee that Index is valid, or the caller must = set up >=20 > + exception handlers to catch the exceptions. This function is only ava= ilable >=20 > + on IA-32 and x64. >=20 > + >=20 > + @param MsrIndex The 32-bit MSR index to read. >=20 > + >=20 > + @return The value of the MSR identified by MsrIndex. >=20 > + >=20 > +**/ >=20 > +UINT64 >=20 > +EFIAPI >=20 > +UnitTestMtrrLibAsmReadMsr64( >=20 > + IN UINT32 MsrIndex >=20 > + ) >=20 > +{ >=20 > + UINT32 Index; >=20 > + >=20 > + for (Index =3D 0; Index < ARRAY_SIZE (mFixedMtrrsValue); Index++) { >=20 > + if (MsrIndex =3D=3D mFixedMtrrsIndex[Index]) { >=20 > + return mFixedMtrrsValue[Index]; >=20 > + } >=20 > + } >=20 > + >=20 > + if ((MsrIndex >=3D MSR_IA32_MTRR_PHYSBASE0) && >=20 > + (MsrIndex <=3D MSR_IA32_MTRR_PHYSMASK0 + (MTRR_NUMBER_OF_VARIABLE= _MTRR << 1))) { >=20 > + if (MsrIndex % 2 =3D=3D 0) { >=20 > + Index =3D (MsrIndex - MSR_IA32_MTRR_PHYSBASE0) >> 1; >=20 > + return mVariableMtrrsPhysBase[Index].Uint64; >=20 > + } else { >=20 > + Index =3D (MsrIndex - MSR_IA32_MTRR_PHYSMASK0) >> 1; >=20 > + return mVariableMtrrsPhysMask[Index].Uint64; >=20 > + } >=20 > + } >=20 > + >=20 > + if (MsrIndex =3D=3D MSR_IA32_MTRR_DEF_TYPE) { >=20 > + return mDefTypeMsr.Uint64; >=20 > + } >=20 > + >=20 > + if (MsrIndex =3D=3D MSR_IA32_MTRRCAP) { >=20 > + return mMtrrCapMsr.Uint64; >=20 > + } >=20 > + >=20 > + // >=20 > + // Should never fall through to here >=20 > + // >=20 > + ASSERT(FALSE); >=20 > + return 0; >=20 > +} >=20 > + >=20 > +/** >=20 > + Writes a 64-bit value to a Machine Specific Register(MSR), and return= s the >=20 > + value. >=20 > + >=20 > + Writes the 64-bit value specified by Value to the MSR specified by In= dex. The >=20 > + 64-bit value written to the MSR is returned. No parameter checking is >=20 > + performed on Index or Value, and some of these may cause CPU exceptio= ns. The >=20 > + caller must either guarantee that Index and Value are valid, or the c= aller >=20 > + must establish proper exception handlers. This function is only avail= able on >=20 > + IA-32 and x64. >=20 > + >=20 > + @param MsrIndex The 32-bit MSR index to write. >=20 > + @param Value The 64-bit value to write to the MSR. >=20 > + >=20 > + @return Value >=20 > + >=20 > +**/ >=20 > +UINT64 >=20 > +EFIAPI >=20 > +UnitTestMtrrLibAsmWriteMsr64( >=20 > + IN UINT32 MsrIndex, >=20 > + IN UINT64 Value >=20 > + ) >=20 > +{ >=20 > + UINT32 Index; >=20 > + >=20 > + for (Index =3D 0; Index < ARRAY_SIZE (mFixedMtrrsValue); Index++) { >=20 > + if (MsrIndex =3D=3D mFixedMtrrsIndex[Index]) { >=20 > + mFixedMtrrsValue[Index] =3D Value; >=20 > + return Value; >=20 > + } >=20 > + } >=20 > + >=20 > + if ((MsrIndex >=3D MSR_IA32_MTRR_PHYSBASE0) && >=20 > + (MsrIndex <=3D MSR_IA32_MTRR_PHYSMASK0 + (MTRR_NUMBER_OF_VARIABLE= _MTRR << 1))) { >=20 > + if (MsrIndex % 2 =3D=3D 0) { >=20 > + Index =3D (MsrIndex - MSR_IA32_MTRR_PHYSBASE0) >> 1; >=20 > + mVariableMtrrsPhysBase[Index].Uint64 =3D Value; >=20 > + return Value; >=20 > + } else { >=20 > + Index =3D (MsrIndex - MSR_IA32_MTRR_PHYSMASK0) >> 1; >=20 > + mVariableMtrrsPhysMask[Index].Uint64 =3D Value; >=20 > + return Value; >=20 > + } >=20 > + } >=20 > + >=20 > + if (MsrIndex =3D=3D MSR_IA32_MTRR_DEF_TYPE) { >=20 > + mDefTypeMsr.Uint64 =3D Value; >=20 > + return Value; >=20 > + } >=20 > + >=20 > + if (MsrIndex =3D=3D MSR_IA32_MTRRCAP) { >=20 > + mMtrrCapMsr.Uint64 =3D Value; >=20 > + return Value; >=20 > + } >=20 > + >=20 > + // >=20 > + // Should never fall through to here >=20 > + // >=20 > + ASSERT(FALSE); >=20 > + return 0; >=20 > +} >=20 > + >=20 > +/** >=20 > + Initialize the MTRR registers. >=20 > + >=20 > + @param SystemParameter System parameter that controls the MTRR regist= ers initialization. >=20 > +**/ >=20 > +UNIT_TEST_STATUS >=20 > +EFIAPI >=20 > +InitializeMtrrRegs ( >=20 > + IN MTRR_LIB_SYSTEM_PARAMETER *SystemParameter >=20 > + ) >=20 > +{ >=20 > + UINT32 Index; >=20 > + >=20 > + SetMem (mFixedMtrrsValue, sizeof (mFixedMtrrsValue), SystemParameter-= >DefaultCacheType); >=20 > + >=20 > + for (Index =3D 0; Index < ARRAY_SIZE (mVariableMtrrsPhysBase); Index+= +) { >=20 > + mVariableMtrrsPhysBase[Index].Uint64 =3D 0; >=20 > + mVariableMtrrsPhysBase[Index].Bits.Type =3D SystemParameter->D= efaultCacheType; >=20 > + mVariableMtrrsPhysBase[Index].Bits.Reserved1 =3D 0; >=20 > + >=20 > + mVariableMtrrsPhysMask[Index].Uint64 =3D 0; >=20 > + mVariableMtrrsPhysMask[Index].Bits.V =3D 0; >=20 > + mVariableMtrrsPhysMask[Index].Bits.Reserved1 =3D 0; >=20 > + } >=20 > + >=20 > + mDefTypeMsr.Bits.E =3D 1; >=20 > + mDefTypeMsr.Bits.FE =3D 1; >=20 > + mDefTypeMsr.Bits.Type =3D SystemParameter->DefaultCacheType; >=20 > + mDefTypeMsr.Bits.Reserved1 =3D 0; >=20 > + mDefTypeMsr.Bits.Reserved2 =3D 0; >=20 > + mDefTypeMsr.Bits.Reserved3 =3D 0; >=20 > + >=20 > + mMtrrCapMsr.Bits.SMRR =3D 0; >=20 > + mMtrrCapMsr.Bits.WC =3D 0; >=20 > + mMtrrCapMsr.Bits.VCNT =3D SystemParameter->VariableMtrrCount; >=20 > + mMtrrCapMsr.Bits.FIX =3D SystemParameter->FixedMtrrSupported; >=20 > + mMtrrCapMsr.Bits.Reserved1 =3D 0; >=20 > + mMtrrCapMsr.Bits.Reserved2 =3D 0; >=20 > + mMtrrCapMsr.Bits.Reserved3 =3D 0; >=20 > + >=20 > + mCpuidVersionInfoEdx.Bits.MTRR =3D SystemParamet= er->MtrrSupported; >=20 > + mCpuidVirPhyAddressSizeEax.Bits.PhysicalAddressBits =3D SystemParamet= er->PhysicalAddressBits; >=20 > + >=20 > + // >=20 > + // Hook BaseLib functions used by MtrrLib that require some emulation= . >=20 > + // >=20 > + gUnitTestHostBaseLib.X86->AsmCpuid =3D UnitTestMtrrLibAsmCpuid; >=20 > + gUnitTestHostBaseLib.X86->AsmReadMsr64 =3D UnitTestMtrrLibAsmReadMsr= 64; >=20 > + gUnitTestHostBaseLib.X86->AsmWriteMsr64 =3D UnitTestMtrrLibAsmWriteMs= r64; >=20 > + >=20 > + return UNIT_TEST_PASSED; >=20 > +} >=20 > + >=20 > +/** >=20 > + Initialize the MTRR registers. >=20 > + >=20 > + @param Context System parameter that controls the MTRR registers init= ialization. >=20 > +**/ >=20 > +UNIT_TEST_STATUS >=20 > +EFIAPI >=20 > +InitializeSystem ( >=20 > + IN UNIT_TEST_CONTEXT Context >=20 > + ) >=20 > +{ >=20 > + return InitializeMtrrRegs ((MTRR_LIB_SYSTEM_PARAMETER *) Context); >=20 > +} >=20 > + >=20 > +/** >=20 > + Collect the test result. >=20 > + >=20 > + @param DefaultType Default memory type. >=20 > + @param PhysicalAddressBits Physical address bits. >=20 > + @param VariableMtrrCount Count of variable MTRRs. >=20 > + @param Mtrrs MTRR settings to collect from. >=20 > + @param Ranges Return the memory ranges. >=20 > + @param RangeCount Return the count of memory ranges. >=20 > + @param MtrrCount Return the count of variable MTRRs being = used. >=20 > +**/ >=20 > +VOID >=20 > +CollectTestResult ( >=20 > + IN MTRR_MEMORY_CACHE_TYPE DefaultType, >=20 > + IN UINT32 PhysicalAddressBits, >=20 > + IN UINT32 VariableMtrrCount, >=20 > + IN MTRR_SETTINGS *Mtrrs, >=20 > + OUT MTRR_MEMORY_RANGE *Ranges, >=20 > + IN OUT UINTN *RangeCount, >=20 > + OUT UINT32 *MtrrCount >=20 > + ) >=20 > +{ >=20 > + UINTN Index; >=20 > + UINT64 MtrrValidBitsMask; >=20 > + UINT64 MtrrValidAddressMask; >=20 > + MTRR_MEMORY_RANGE RawMemoryRanges[ARRAY_SIZE (Mtrrs->Variables.Mtrr)]= ; >=20 > + >=20 > + ASSERT (Mtrrs !=3D NULL); >=20 > + ASSERT (VariableMtrrCount <=3D ARRAY_SIZE (Mtrrs->Variables.Mtrr)); >=20 > + >=20 > + MtrrValidBitsMask =3D (1ull << PhysicalAddressBits) - 1; >=20 > + MtrrValidAddressMask =3D MtrrValidBitsMask & ~0xFFFull; >=20 > + >=20 > + *MtrrCount =3D 0; >=20 > + for (Index =3D 0; Index < VariableMtrrCount; Index++) { >=20 > + if (((MSR_IA32_MTRR_PHYSMASK_REGISTER *) &Mtrrs->Variables.Mtrr[Ind= ex].Mask)->Bits.V =3D=3D 1) { >=20 > + RawMemoryRanges[*MtrrCount].BaseAddress =3D Mtrrs->Variables.Mtrr= [Index].Base & MtrrValidAddressMask; >=20 > + RawMemoryRanges[*MtrrCount].Type =3D >=20 > + ((MSR_IA32_MTRR_PHYSBASE_REGISTER *) &Mtrrs->Variables.Mtrr[Ind= ex].Base)->Bits.Type; >=20 > + RawMemoryRanges[*MtrrCount].Length =3D >=20 > + ((~(Mtrrs->Variables.Mtrr[Index].Mask & MtrrValidAddressMask)= ) & MtrrValidBitsMask) + 1; >=20 > + (*MtrrCount)++; >=20 > + } >=20 > + } >=20 > + >=20 > + GetEffectiveMemoryRanges (DefaultType, PhysicalAddressBits, RawMemory= Ranges, *MtrrCount, Ranges, RangeCount); >=20 > +} >=20 > + >=20 > +/** >=20 > + Return a 32bit random number. >=20 > + >=20 > + @param Start Start of the random number range. >=20 > + @param Limit Limit of the random number range. >=20 > + @return 32bit random number >=20 > +**/ >=20 > +UINT32 >=20 > +Random32 ( >=20 > + UINT32 Start, >=20 > + UINT32 Limit >=20 > + ) >=20 > +{ >=20 > + return (UINT32) (((double) rand () / RAND_MAX) * (Limit - Start)) + S= tart; >=20 > +} >=20 > + >=20 > +/** >=20 > + Return a 64bit random number. >=20 > + >=20 > + @param Start Start of the random number range. >=20 > + @param Limit Limit of the random number range. >=20 > + @return 64bit random number >=20 > +**/ >=20 > +UINT64 >=20 > +Random64 ( >=20 > + UINT64 Start, >=20 > + UINT64 Limit >=20 > + ) >=20 > +{ >=20 > + return (UINT64) (((double) rand () / RAND_MAX) * (Limit - Start)) + S= tart; >=20 > +} >=20 > + >=20 > +/** >=20 > + Generate random MTRR BASE/MASK for a specified type. >=20 > + >=20 > + @param PhysicalAddressBits Physical address bits. >=20 > + @param CacheType Cache type. >=20 > + @param MtrrPair Return the random MTRR. >=20 > + @param MtrrMemoryRange Return the random memory range. >=20 > +**/ >=20 > +VOID >=20 > +GenerateRandomMtrrPair ( >=20 > + IN UINT32 PhysicalAddressBits, >=20 > + IN MTRR_MEMORY_CACHE_TYPE CacheType, >=20 > + OUT MTRR_VARIABLE_SETTING *MtrrPair, OPTIONAL >=20 > + OUT MTRR_MEMORY_RANGE *MtrrMemoryRange OPTIONAL >=20 > + ) >=20 > +{ >=20 > + MSR_IA32_MTRR_PHYSBASE_REGISTER PhysBase; >=20 > + MSR_IA32_MTRR_PHYSMASK_REGISTER PhysMask; >=20 > + UINT32 SizeShift; >=20 > + UINT32 BaseShift; >=20 > + UINT64 RandomBoundary; >=20 > + UINT64 MaxPhysicalAddress; >=20 > + UINT64 RangeSize; >=20 > + UINT64 RangeBase; >=20 > + UINT64 PhysBasePhyMaskValidBitsMask; >=20 > + >=20 > + MaxPhysicalAddress =3D 1ull << PhysicalAddressBits; >=20 > + do { >=20 > + SizeShift =3D Random32 (12, PhysicalAddressBits - 1); >=20 > + RangeSize =3D 1ull << SizeShift; >=20 > + >=20 > + BaseShift =3D Random32 (SizeShift, PhysicalAddressBits - 1); >=20 > + RandomBoundary =3D Random64 (0, 1ull << (PhysicalAddressBits - Base= Shift)); >=20 > + RangeBase =3D RandomBoundary << BaseShift; >=20 > + } while (RangeBase < SIZE_1MB || RangeBase > MaxPhysicalAddress - 1); >=20 > + >=20 > + PhysBasePhyMaskValidBitsMask =3D (MaxPhysicalAddress - 1) & 0xfffffff= ffffff000ULL; >=20 > + >=20 > + PhysBase.Uint64 =3D 0; >=20 > + PhysBase.Bits.Type =3D CacheType; >=20 > + PhysBase.Uint64 |=3D RangeBase & PhysBasePhyMaskValidBitsMask; >=20 > + PhysMask.Uint64 =3D 0; >=20 > + PhysMask.Bits.V =3D 1; >=20 > + PhysMask.Uint64 |=3D ((~RangeSize) + 1) & PhysBasePhyMaskValidBitsM= ask; >=20 > + >=20 > + if (MtrrPair !=3D NULL) { >=20 > + MtrrPair->Base =3D PhysBase.Uint64; >=20 > + MtrrPair->Mask =3D PhysMask.Uint64; >=20 > + } >=20 > + >=20 > + if (MtrrMemoryRange !=3D NULL) { >=20 > + MtrrMemoryRange->BaseAddress =3D RangeBase; >=20 > + MtrrMemoryRange->Length =3D RangeSize; >=20 > + MtrrMemoryRange->Type =3D CacheType; >=20 > + } >=20 > +} >=20 > + >=20 > + >=20 > +/** >=20 > + Check whether the Range overlaps with any one in Ranges. >=20 > + >=20 > + @param Range The memory range to check. >=20 > + @param Ranges The memory ranges. >=20 > + @param Count Count of memory ranges. >=20 > + >=20 > + @return TRUE when overlap exists. >=20 > +**/ >=20 > +BOOLEAN >=20 > +RangesOverlap ( >=20 > + IN MTRR_MEMORY_RANGE *Range, >=20 > + IN MTRR_MEMORY_RANGE *Ranges, >=20 > + IN UINTN Count >=20 > + ) >=20 > +{ >=20 > + while (Count-- !=3D 0) { >=20 > + // >=20 > + // Two ranges overlap when: >=20 > + // 1. range#2.base is in the middle of range#1 >=20 > + // 2. range#1.base is in the middle of range#2 >=20 > + // >=20 > + if ((Range->BaseAddress <=3D Ranges[Count].BaseAddress && Ranges[Co= unt].BaseAddress < Range->BaseAddress + Range->Length) >=20 > + || (Ranges[Count].BaseAddress <=3D Range->BaseAddress && Range->Ba= seAddress < Ranges[Count].BaseAddress + Ranges[Count].Length)) { >=20 > + return TRUE; >=20 > + } >=20 > + } >=20 > + return FALSE; >=20 > +} >=20 > + >=20 > +/** >=20 > + Generate random MTRRs. >=20 > + >=20 > + @param PhysicalAddressBits Physical address bits. >=20 > + @param RawMemoryRanges Return the randomly generated MTRRs. >=20 > + @param UcCount Count of Uncacheable MTRRs. >=20 > + @param WtCount Count of Write Through MTRRs. >=20 > + @param WbCount Count of Write Back MTRRs. >=20 > + @param WpCount Count of Write Protected MTRRs. >=20 > + @param WcCount Count of Write Combine MTRRs. >=20 > +**/ >=20 > +VOID >=20 > +GenerateValidAndConfigurableMtrrPairs ( >=20 > + IN UINT32 PhysicalAddressBits, >=20 > + IN OUT MTRR_MEMORY_RANGE *RawMemoryRanges, >=20 > + IN UINT32 UcCount, >=20 > + IN UINT32 WtCount, >=20 > + IN UINT32 WbCount, >=20 > + IN UINT32 WpCount, >=20 > + IN UINT32 WcCount >=20 > + ) >=20 > +{ >=20 > + UINT32 Index; >=20 > + >=20 > + // >=20 > + // 1. Generate UC, WT, WB in order. >=20 > + // >=20 > + for (Index =3D 0; Index < UcCount; Index++) { >=20 > + GenerateRandomMtrrPair (PhysicalAddressBits, CacheUncacheable, NULL= , &RawMemoryRanges[Index]); >=20 > + } >=20 > + >=20 > + for (Index =3D UcCount; Index < UcCount + WtCount; Index++) { >=20 > + GenerateRandomMtrrPair (PhysicalAddressBits, CacheWriteThrough, NUL= L, &RawMemoryRanges[Index]); >=20 > + } >=20 > + >=20 > + for (Index =3D UcCount + WtCount; Index < UcCount + WtCount + WbCount= ; Index++) { >=20 > + GenerateRandomMtrrPair (PhysicalAddressBits, CacheWriteBack, NULL, = &RawMemoryRanges[Index]); >=20 > + } >=20 > + >=20 > + // >=20 > + // 2. Generate WP MTRR and DO NOT overlap with WT, WB. >=20 > + // >=20 > + for (Index =3D UcCount + WtCount + WbCount; Index < UcCount + WtCount= + WbCount + WpCount; Index++) { >=20 > + GenerateRandomMtrrPair (PhysicalAddressBits, CacheWriteProtected, N= ULL, &RawMemoryRanges[Index]); >=20 > + while (RangesOverlap (&RawMemoryRanges[Index], &RawMemoryRanges[UcC= ount], WtCount + WbCount)) { >=20 > + GenerateRandomMtrrPair (PhysicalAddressBits, CacheWriteProtected,= NULL, &RawMemoryRanges[Index]); >=20 > + } >=20 > + } >=20 > + >=20 > + // >=20 > + // 3. Generate WC MTRR and DO NOT overlap with WT, WB, WP. >=20 > + // >=20 > + for (Index =3D UcCount + WtCount + WbCount + WpCount; Index < UcCount= + WtCount + WbCount + WpCount + WcCount; Index++) { >=20 > + GenerateRandomMtrrPair (PhysicalAddressBits, CacheWriteCombining, N= ULL, &RawMemoryRanges[Index]); >=20 > + while (RangesOverlap (&RawMemoryRanges[Index], &RawMemoryRanges[UcC= ount], WtCount + WbCount + WpCount)) { >=20 > + GenerateRandomMtrrPair (PhysicalAddressBits, CacheWriteCombining,= NULL, &RawMemoryRanges[Index]); >=20 > + } >=20 > + } >=20 > +} >=20 > + >=20 > +/** >=20 > + Return a random memory cache type. >=20 > +**/ >=20 > +MTRR_MEMORY_CACHE_TYPE >=20 > +GenerateRandomCacheType ( >=20 > + VOID >=20 > + ) >=20 > +{ >=20 > + return mMemoryCacheTypes[Random32 (0, ARRAY_SIZE (mMemoryCacheTypes= ) - 1)]; >=20 > +} >=20 > + >=20 > +/** >=20 > + Compare function used by qsort(). >=20 > +**/ >=20 > + >=20 > +/** >=20 > + Compare function used by qsort(). >=20 > + >=20 > + @param Left Left operand to compare. >=20 > + @param Right Right operand to compare. >=20 > + >=20 > + @retval 0 Left =3D=3D Right >=20 > + @retval -1 Left < Right >=20 > + @retval 1 Left > Right >=20 > +**/ >=20 > +INT32 >=20 > +CompareFuncUint64 ( >=20 > + CONST VOID * Left, >=20 > + CONST VOID * Right >=20 > + ) >=20 > +{ >=20 > + INT64 Delta; >=20 > + Delta =3D (*(UINT64*)Left - *(UINT64*)Right); >=20 > + if (Delta > 0) { >=20 > + return 1; >=20 > + } else if (Delta =3D=3D 0) { >=20 > + return 0; >=20 > + } else { >=20 > + return -1; >=20 > + } >=20 > +} >=20 > + >=20 > +/** >=20 > + Determin the memory cache type for the Range. >=20 > + >=20 > + @param DefaultType Default cache type. >=20 > + @param Range The memory range to determin the cache type. >=20 > + @param Ranges The entire memory ranges. >=20 > + @param RangeCount Count of the entire memory ranges. >=20 > +**/ >=20 > +VOID >=20 > +DetermineMemoryCacheType ( >=20 > + IN MTRR_MEMORY_CACHE_TYPE DefaultType, >=20 > + IN OUT MTRR_MEMORY_RANGE *Range, >=20 > + IN MTRR_MEMORY_RANGE *Ranges, >=20 > + IN UINT32 RangeCount >=20 > + ) >=20 > +{ >=20 > + UINT32 Index; >=20 > + Range->Type =3D CacheInvalid; >=20 > + for (Index =3D 0; Index < RangeCount; Index++) { >=20 > + if (RangesOverlap (Range, &Ranges[Index], 1)) { >=20 > + if (Ranges[Index].Type < Range->Type) { >=20 > + Range->Type =3D Ranges[Index].Type; >=20 > + } >=20 > + } >=20 > + } >=20 > + >=20 > + if (Range->Type =3D=3D CacheInvalid) { >=20 > + Range->Type =3D DefaultType; >=20 > + } >=20 > +} >=20 > + >=20 > +/** >=20 > + Get the index of the element that does NOT equals to Array[Index]. >=20 > + >=20 > + @param Index Current element. >=20 > + @param Array Array to scan. >=20 > + @param Count Count of the array. >=20 > + >=20 > + @return Next element that doesn't equal to current one. >=20 > +**/ >=20 > +UINT32 >=20 > +GetNextDifferentElementInSortedArray ( >=20 > + IN UINT32 Index, >=20 > + IN UINT64 *Array, >=20 > + IN UINT32 Count >=20 > + ) >=20 > +{ >=20 > + UINT64 CurrentElement; >=20 > + CurrentElement =3D Array[Index]; >=20 > + while (CurrentElement =3D=3D Array[Index] && Index < Count) { >=20 > + Index++; >=20 > + } >=20 > + return Index; >=20 > +} >=20 > + >=20 > +/** >=20 > + Remove the duplicates from the array. >=20 > + >=20 > + @param Array The array to operate on. >=20 > + @param Count Count of the array. >=20 > +**/ >=20 > +VOID >=20 > +RemoveDuplicatesInSortedArray ( >=20 > + IN OUT UINT64 *Array, >=20 > + IN OUT UINT32 *Count >=20 > + ) >=20 > +{ >=20 > + UINT32 Index; >=20 > + UINT32 NewCount; >=20 > + >=20 > + Index =3D 0; >=20 > + NewCount =3D 0; >=20 > + while (Index < *Count) { >=20 > + Array[NewCount] =3D Array[Index]; >=20 > + NewCount++; >=20 > + Index =3D GetNextDifferentElementInSortedArray (Index, Array, *Coun= t); >=20 > + } >=20 > + *Count =3D NewCount; >=20 > +} >=20 > + >=20 > +/** >=20 > + Return TRUE when Address is in the Range. >=20 > + >=20 > + @param Address The address to check. >=20 > + @param Range The range to check. >=20 > + @return TRUE when Address is in the Range. >=20 > +**/ >=20 > +BOOLEAN >=20 > +AddressInRange ( >=20 > + IN UINT64 Address, >=20 > + IN MTRR_MEMORY_RANGE Range >=20 > + ) >=20 > +{ >=20 > + return (Address >=3D Range.BaseAddress) && (Address <=3D Range.Base= Address + Range.Length - 1); >=20 > +} >=20 > + >=20 > +/** >=20 > + Get the overlap bit flag. >=20 > + >=20 > + @param RawMemoryRanges Raw memory ranges. >=20 > + @param RawMemoryRangeCount Count of raw memory ranges. >=20 > + @param Address The address to check. >=20 > +**/ >=20 > +UINT64 >=20 > +GetOverlapBitFlag ( >=20 > + IN MTRR_MEMORY_RANGE *RawMemoryRanges, >=20 > + IN UINT32 RawMemoryRangeCount, >=20 > + IN UINT64 Address >=20 > + ) >=20 > +{ >=20 > + UINT64 OverlapBitFlag; >=20 > + UINT32 Index; >=20 > + OverlapBitFlag =3D 0; >=20 > + for (Index =3D 0; Index < RawMemoryRangeCount; Index++) { >=20 > + if (AddressInRange (Address, RawMemoryRanges[Index])) { >=20 > + OverlapBitFlag |=3D (1ull << Index); >=20 > + } >=20 > + } >=20 > + >=20 > + return OverlapBitFlag; >=20 > +} >=20 > + >=20 > +/** >=20 > + Return the relationship between flags. >=20 > + >=20 > + @param Flag1 Flag 1 >=20 > + @param Flag2 Flag 2 >=20 > + >=20 > + @retval 0 Flag1 =3D=3D Flag2 >=20 > + @retval 1 Flag1 is a subset of Flag2 >=20 > + @retval 2 Flag2 is a subset of Flag1 >=20 > + @retval 3 No subset relations between Flag1 and Flag2. >=20 > +**/ >=20 > +UINT32 >=20 > +CheckOverlapBitFlagsRelation ( >=20 > + IN UINT64 Flag1, >=20 > + IN UINT64 Flag2 >=20 > + ) >=20 > +{ >=20 > + if (Flag1 =3D=3D Flag2) return 0; >=20 > + if ((Flag1 | Flag2) =3D=3D Flag2) return 1; >=20 > + if ((Flag1 | Flag2) =3D=3D Flag1) return 2; >=20 > + return 3; >=20 > +} >=20 > + >=20 > +/** >=20 > + Return TRUE when the Endpoint is in any of the Ranges. >=20 > + >=20 > + @param Endpoint The endpoint to check. >=20 > + @param Ranges The memory ranges. >=20 > + @param RangeCount Count of memory ranges. >=20 > + >=20 > + @retval TRUE Endpoint is in one of the range. >=20 > + @retval FALSE Endpoint is not in any of the ranges. >=20 > +**/ >=20 > +BOOLEAN >=20 > +IsEndpointInRanges ( >=20 > + IN UINT64 Endpoint, >=20 > + IN MTRR_MEMORY_RANGE *Ranges, >=20 > + IN UINTN RangeCount >=20 > + ) >=20 > +{ >=20 > + UINT32 Index; >=20 > + for (Index =3D 0; Index < RangeCount; Index++) { >=20 > + if (AddressInRange (Endpoint, Ranges[Index])) { >=20 > + return TRUE; >=20 > + } >=20 > + } >=20 > + return FALSE; >=20 > +} >=20 > + >=20 > + >=20 > +/** >=20 > + Compact adjacent ranges of the same type. >=20 > + >=20 > + @param DefaultType Default memory type. >=20 > + @param PhysicalAddressBits Physical address bits. >=20 > + @param EffectiveMtrrMemoryRanges Memory ranges to compact. >=20 > + @param EffectiveMtrrMemoryRangesCount Return the new count of memory = ranges. >=20 > +**/ >=20 > +VOID >=20 > +CompactAndExtendEffectiveMtrrMemoryRanges ( >=20 > + IN MTRR_MEMORY_CACHE_TYPE DefaultType, >=20 > + IN UINT32 PhysicalAddressBits, >=20 > + IN OUT MTRR_MEMORY_RANGE **EffectiveMtrrMemoryRanges, >=20 > + IN OUT UINTN *EffectiveMtrrMemoryRangesCount >=20 > + ) >=20 > +{ >=20 > + UINT64 MaxAddress; >=20 > + UINTN NewRangesCountAtMost; >=20 > + MTRR_MEMORY_RANGE *NewRanges; >=20 > + UINTN NewRangesCountActual; >=20 > + MTRR_MEMORY_RANGE *CurrentRangeInNewRanges; >=20 > + MTRR_MEMORY_CACHE_TYPE CurrentRangeTypeInOldRanges; >=20 > + >=20 > + MTRR_MEMORY_RANGE *OldRanges; >=20 > + MTRR_MEMORY_RANGE OldLastRange; >=20 > + UINTN OldRangesIndex; >=20 > + >=20 > + NewRangesCountActual =3D 0; >=20 > + NewRangesCountAtMost =3D *EffectiveMtrrMemoryRangesCount + 2; // At= most with 2 more range entries. >=20 > + NewRanges =3D (MTRR_MEMORY_RANGE *) calloc (NewRangesCount= AtMost, sizeof (MTRR_MEMORY_RANGE)); >=20 > + OldRanges =3D *EffectiveMtrrMemoryRanges; >=20 > + if (OldRanges[0].BaseAddress > 0) { >=20 > + NewRanges[NewRangesCountActual].BaseAddress =3D 0; >=20 > + NewRanges[NewRangesCountActual].Length =3D OldRanges[0].BaseAd= dress; >=20 > + NewRanges[NewRangesCountActual].Type =3D DefaultType; >=20 > + NewRangesCountActual++; >=20 > + } >=20 > + >=20 > + OldRangesIndex =3D 0; >=20 > + while (OldRangesIndex < *EffectiveMtrrMemoryRangesCount) { >=20 > + CurrentRangeTypeInOldRanges =3D OldRanges[OldRangesIndex].Type; >=20 > + CurrentRangeInNewRanges =3D NULL; >=20 > + if (NewRangesCountActual > 0) // We need to check CurrentNewRange= first before generate a new NewRange. >=20 > + { >=20 > + CurrentRangeInNewRanges =3D &NewRanges[NewRangesCountActual - 1]; >=20 > + } >=20 > + if (CurrentRangeInNewRanges !=3D NULL && CurrentRangeInNewRanges->T= ype =3D=3D CurrentRangeTypeInOldRanges) { >=20 > + CurrentRangeInNewRanges->Length +=3D OldRanges[OldRangesIndex].Le= ngth; >=20 > + } else { >=20 > + NewRanges[NewRangesCountActual].BaseAddress =3D OldRanges[OldRang= esIndex].BaseAddress; >=20 > + NewRanges[NewRangesCountActual].Length +=3D OldRanges[OldRang= esIndex].Length; >=20 > + NewRanges[NewRangesCountActual].Type =3D CurrentRangeTypeI= nOldRanges; >=20 > + while (OldRangesIndex + 1 < *EffectiveMtrrMemoryRangesCount && Ol= dRanges[OldRangesIndex + 1].Type =3D=3D CurrentRangeTypeInOldRanges) >=20 > + { >=20 > + OldRangesIndex++; >=20 > + NewRanges[NewRangesCountActual].Length +=3D OldRanges[OldRanges= Index].Length; >=20 > + } >=20 > + NewRangesCountActual++; >=20 > + } >=20 > + >=20 > + OldRangesIndex++; >=20 > + } >=20 > + >=20 > + MaxAddress =3D (1ull << PhysicalAddressBits) - 1; >=20 > + OldLastRange =3D OldRanges[(*EffectiveMtrrMemoryRangesCount) - 1]; >=20 > + CurrentRangeInNewRanges =3D &NewRanges[NewRangesCountActual - 1]; >=20 > + if (OldLastRange.BaseAddress + OldLastRange.Length - 1 < MaxAddress) = { >=20 > + if (CurrentRangeInNewRanges->Type =3D=3D DefaultType) { >=20 > + CurrentRangeInNewRanges->Length =3D MaxAddress - CurrentRangeInNe= wRanges->BaseAddress + 1; >=20 > + } else { >=20 > + NewRanges[NewRangesCountActual].BaseAddress =3D OldLastRange.Base= Address + OldLastRange.Length; >=20 > + NewRanges[NewRangesCountActual].Length =3D MaxAddress - NewRanges= [NewRangesCountActual].BaseAddress + 1; >=20 > + NewRanges[NewRangesCountActual].Type =3D DefaultType; >=20 > + NewRangesCountActual++; >=20 > + } >=20 > + } >=20 > + >=20 > + free (*EffectiveMtrrMemoryRanges); >=20 > + *EffectiveMtrrMemoryRanges =3D NewRanges; >=20 > + *EffectiveMtrrMemoryRangesCount =3D NewRangesCountActual; >=20 > +} >=20 > + >=20 > +/** >=20 > + Collect all the endpoints in the raw memory ranges. >=20 > + >=20 > + @param Endpoints Return the collected endpoints. >=20 > + @param EndPointCount Return the count of endpoints. >=20 > + @param RawMemoryRanges Raw memory ranges. >=20 > + @param RawMemoryRangeCount Count of raw memory ranges. >=20 > +**/ >=20 > +VOID >=20 > +CollectEndpoints ( >=20 > + IN OUT UINT64 *Endpoints, >=20 > + IN OUT UINT32 *EndPointCount, >=20 > + IN MTRR_MEMORY_RANGE *RawMemoryRanges, >=20 > + IN UINT32 RawMemoryRangeCount >=20 > + ) >=20 > +{ >=20 > + UINT32 Index; >=20 > + UINT32 RawRangeIndex; >=20 > + >=20 > + ASSERT ((RawMemoryRangeCount << 1) =3D=3D *EndPointCount); >=20 > + >=20 > + for (Index =3D 0; Index < *EndPointCount; Index +=3D 2) { >=20 > + RawRangeIndex =3D Index >> 1; >=20 > + Endpoints[Index] =3D RawMemoryRanges[RawRangeIndex].BaseAddress; >=20 > + Endpoints[Index + 1] =3D RawMemoryRanges[RawRangeIndex].BaseAddress= + RawMemoryRanges[RawRangeIndex].Length - 1; >=20 > + } >=20 > + >=20 > + qsort (Endpoints, *EndPointCount, sizeof (UINT64), CompareFuncUint64)= ; >=20 > + RemoveDuplicatesInSortedArray (Endpoints, EndPointCount); >=20 > +} >=20 > + >=20 > +/** >=20 > + Convert the MTRR BASE/MASK array to memory ranges. >=20 > + >=20 > + @param DefaultType Default memory type. >=20 > + @param PhysicalAddressBits Physical address bits. >=20 > + @param RawMemoryRanges Raw memory ranges. >=20 > + @param RawMemoryRangeCount Count of raw memory ranges. >=20 > + @param MemoryRanges Memory ranges. >=20 > + @param MemoryRangeCount Count of memory ranges. >=20 > +**/ >=20 > +VOID >=20 > +GetEffectiveMemoryRanges ( >=20 > + IN MTRR_MEMORY_CACHE_TYPE DefaultType, >=20 > + IN UINT32 PhysicalAddressBits, >=20 > + IN MTRR_MEMORY_RANGE *RawMemoryRanges, >=20 > + IN UINT32 RawMemoryRangeCount, >=20 > + OUT MTRR_MEMORY_RANGE *MemoryRanges, >=20 > + OUT UINTN *MemoryRangeCount >=20 > + ) >=20 > +{ >=20 > + UINTN Index; >=20 > + UINT32 AllEndPointsCount; >=20 > + UINT64 *AllEndPointsInclusive; >=20 > + UINT32 AllRangePiecesCountMax; >=20 > + MTRR_MEMORY_RANGE *AllRangePieces; >=20 > + UINTN AllRangePiecesCountActual; >=20 > + UINT64 OverlapBitFlag1; >=20 > + UINT64 OverlapBitFlag2; >=20 > + INT32 OverlapFlagRelation; >=20 > + >=20 > + if (RawMemoryRangeCount =3D=3D 0) { >=20 > + MemoryRanges[0].BaseAddress =3D 0; >=20 > + MemoryRanges[0].Length =3D (1ull << PhysicalAddressBits); >=20 > + MemoryRanges[0].Type =3D DefaultType; >=20 > + *MemoryRangeCount =3D 1; >=20 > + return; >=20 > + } >=20 > + >=20 > + AllEndPointsCount =3D RawMemoryRangeCount << 1; >=20 > + AllEndPointsInclusive =3D calloc (AllEndPointsCount, sizeof (UINT= 64)); >=20 > + AllRangePiecesCountMax =3D RawMemoryRangeCount * 3 + 1; >=20 > + AllRangePieces =3D calloc (AllRangePiecesCountMax, sizeof = (MTRR_MEMORY_RANGE)); >=20 > + CollectEndpoints (AllEndPointsInclusive, &AllEndPointsCount, RawMemor= yRanges, RawMemoryRangeCount); >=20 > + >=20 > + for (Index =3D 0, AllRangePiecesCountActual =3D 0; Index < AllEndPoin= tsCount - 1; Index++) { >=20 > + OverlapBitFlag1 =3D GetOverlapBitFlag (RawMemoryRanges, RawMemoryRa= ngeCount, AllEndPointsInclusive[Index]); >=20 > + OverlapBitFlag2 =3D GetOverlapBitFlag (RawMemoryRanges, RawMemoryRa= ngeCount, AllEndPointsInclusive[Index + 1]); >=20 > + OverlapFlagRelation =3D CheckOverlapBitFlagsRelation (OverlapBitFla= g1, OverlapBitFlag2); >=20 > + switch (OverlapFlagRelation) { >=20 > + case 0: // [1, 2] >=20 > + AllRangePieces[AllRangePiecesCountActual].BaseAddress =3D AllEn= dPointsInclusive[Index]; >=20 > + AllRangePieces[AllRangePiecesCountActual].Length =3D AllEn= dPointsInclusive[Index + 1] - AllEndPointsInclusive[Index] + 1; >=20 > + AllRangePiecesCountActual++; >=20 > + break; >=20 > + case 1: // [1, 2) >=20 > + AllRangePieces[AllRangePiecesCountActual].BaseAddress =3D AllEn= dPointsInclusive[Index]; >=20 > + AllRangePieces[AllRangePiecesCountActual].Length =3D (AllE= ndPointsInclusive[Index + 1] - 1) - AllEndPointsInclusive[Index] + 1; >=20 > + AllRangePiecesCountActual++; >=20 > + break; >=20 > + case 2: // (1, 2] >=20 > + AllRangePieces[AllRangePiecesCountActual].BaseAddress =3D AllEn= dPointsInclusive[Index] + 1; >=20 > + AllRangePieces[AllRangePiecesCountActual].Length =3D AllEn= dPointsInclusive[Index + 1] - (AllEndPointsInclusive[Index] + 1) + 1; >=20 > + AllRangePiecesCountActual++; >=20 > + >=20 > + if (!IsEndpointInRanges (AllEndPointsInclusive[Index], AllRange= Pieces, AllRangePiecesCountActual)) { >=20 > + AllRangePieces[AllRangePiecesCountActual].BaseAddress =3D All= EndPointsInclusive[Index]; >=20 > + AllRangePieces[AllRangePiecesCountActual].Length =3D 1; >=20 > + AllRangePiecesCountActual++; >=20 > + } >=20 > + break; >=20 > + case 3: // (1, 2) >=20 > + AllRangePieces[AllRangePiecesCountActual].BaseAddress =3D AllEn= dPointsInclusive[Index] + 1; >=20 > + AllRangePieces[AllRangePiecesCountActual].Length =3D (AllE= ndPointsInclusive[Index + 1] - 1) - (AllEndPointsInclusive[Index] + 1) + 1; >=20 > + if (AllRangePieces[AllRangePiecesCountActual].Length =3D=3D 0) = // Only in case 3 can exists Length=3D0, we should skip such "segment". >=20 > + break; >=20 > + AllRangePiecesCountActual++; >=20 > + if (!IsEndpointInRanges (AllEndPointsInclusive[Index], AllRange= Pieces, AllRangePiecesCountActual)) { >=20 > + AllRangePieces[AllRangePiecesCountActual].BaseAddress =3D All= EndPointsInclusive[Index]; >=20 > + AllRangePieces[AllRangePiecesCountActual].Length =3D 1; >=20 > + AllRangePiecesCountActual++; >=20 > + } >=20 > + break; >=20 > + default: >=20 > + ASSERT (FALSE); >=20 > + } >=20 > + } >=20 > + >=20 > + for (Index =3D 0; Index < AllRangePiecesCountActual; Index++) { >=20 > + DetermineMemoryCacheType (DefaultType, &AllRangePieces[Index], RawM= emoryRanges, RawMemoryRangeCount); >=20 > + } >=20 > + >=20 > + CompactAndExtendEffectiveMtrrMemoryRanges (DefaultType, PhysicalAddre= ssBits, &AllRangePieces, &AllRangePiecesCountActual); >=20 > + ASSERT (*MemoryRangeCount >=3D AllRangePiecesCountActual); >=20 > + memcpy (MemoryRanges, AllRangePieces, AllRangePiecesCountActual * siz= eof (MTRR_MEMORY_RANGE)); >=20 > + *MemoryRangeCount =3D AllRangePiecesCountActual; >=20 > + >=20 > + free (AllEndPointsInclusive); >=20 > + free (AllRangePieces); >=20 > +} >=20 > diff --git a/UefiCpuPkg/Test/UefiCpuPkgHostTest.dsc b/UefiCpuPkg/Test/Ue= fiCpuPkgHostTest.dsc > new file mode 100644 > index 0000000000..8a5c456830 > --- /dev/null > +++ b/UefiCpuPkg/Test/UefiCpuPkgHostTest.dsc > @@ -0,0 +1,31 @@ > +## @file >=20 > +# UefiCpuPkg DSC file used to build host-based unit tests. >=20 > +# >=20 > +# Copyright (c) 2020, Intel Corporation. All rights reserved.
>=20 > +# SPDX-License-Identifier: BSD-2-Clause-Patent >=20 > +# >=20 > +## >=20 > + >=20 > +[Defines] >=20 > + PLATFORM_NAME =3D UefiCpuPkgHostTest >=20 > + PLATFORM_GUID =3D E00B9599-5B74-4FF7-AB9F-8183FB13B2F9 >=20 > + PLATFORM_VERSION =3D 0.1 >=20 > + DSC_SPECIFICATION =3D 0x00010005 >=20 > + OUTPUT_DIRECTORY =3D Build/UefiCpuPkg/HostTest >=20 > + SUPPORTED_ARCHITECTURES =3D IA32|X64 >=20 > + BUILD_TARGETS =3D NOOPT >=20 > + SKUID_IDENTIFIER =3D DEFAULT >=20 > + >=20 > +!include UnitTestFrameworkPkg/UnitTestFrameworkPkgHost.dsc.inc >=20 > + >=20 > +[LibraryClasses] >=20 > + MtrrLib|UefiCpuPkg/Library/MtrrLib/MtrrLib.inf >=20 > + >=20 > +[PcdsPatchableInModule] >=20 > + gUefiCpuPkgTokenSpaceGuid.PcdCpuNumberOfReservedVariableMtrrs|0 >=20 > + >=20 > +[Components] >=20 > + # >=20 > + # Build HOST_APPLICATION that tests the MtrrLib >=20 > + # >=20 > + UefiCpuPkg/Library/MtrrLib/UnitTest/MtrrLibUnitTestHost.inf >=20 > diff --git a/UefiCpuPkg/UefiCpuPkg.ci.yaml b/UefiCpuPkg/UefiCpuPkg.ci.ya= ml > index 99e460a8b0..4559b40105 100644 > --- a/UefiCpuPkg/UefiCpuPkg.ci.yaml > +++ b/UefiCpuPkg/UefiCpuPkg.ci.yaml > @@ -8,6 +8,10 @@ > "CompilerPlugin": { >=20 > "DscPath": "UefiCpuPkg.dsc" >=20 > }, >=20 > + ## options defined ci/Plugin/HostUnitTestCompilerPlugin >=20 > + "HostUnitTestCompilerPlugin": { >=20 > + "DscPath": "Test/UefiCpuPkgHostTest.dsc" >=20 > + }, >=20 > "CharEncodingCheck": { >=20 > "IgnoreFiles": [] >=20 > }, >=20 > @@ -18,7 +22,9 @@ > "UefiCpuPkg/UefiCpuPkg.dec" >=20 > ], >=20 > # For host based unit tests >=20 > - "AcceptableDependencies-HOST_APPLICATION":[], >=20 > + "AcceptableDependencies-HOST_APPLICATION":[ >=20 > + "UnitTestFrameworkPkg/UnitTestFrameworkPkg.dec" >=20 > + ], >=20 > # For UEFI shell based apps >=20 > "AcceptableDependencies-UEFI_APPLICATION":[], >=20 > "IgnoreInf": [] >=20 > @@ -30,6 +36,10 @@ > "UefiCpuPkg/ResetVector/Vtf0/Vtf0.inf" >=20 > ] >=20 > }, >=20 > + "HostUnitTestDscCompleteCheck": { >=20 > + "IgnoreInf": [""], >=20 > + "DscPath": "Test/UefiCpuPkgHostTest.dsc" >=20 > + }, >=20 > "GuidCheck": { >=20 > "IgnoreGuidName": ["SecCore", "ResetVector"], # Expected dupli= cation for gEfiFirmwareVolumeTopFileGuid >=20 > "IgnoreGuidValue": [], >=20 =20 =20 ------=_NextPart_000_0676_01D664E0.42A09380 Content-Type: text/html; charset="UTF-8" Content-Transfer-Encoding: quoted-printable

Andrew =E2=80= =93

 

You would have to include the random number code directly in the uni= t test to handle your cross-environment portability issues.

<= p class=3DMsoNormal> 

Tim

 

From: devel@edk2.groups.io <devel@edk2.groups.io> On= Behalf Of Andrew Fish via groups.io
Sent: Tuesday, July 28, = 2020 11:59 AM
To: devel@edk2.groups.io; bret.barkelew@microsoft.c= om
Cc: tim.lewis@insyde.com; spbrogan@outlook.com; Ni, Ray <ra= y.ni@intel.com>; Mike Kinney <michael.d.kinney@intel.com>; Ming Sh= ao <ming.shao@intel.com>; Dong, Eric <eric.dong@intel.com>; Las= zlo Ersek <lersek@redhat.com>; Sean Brogan <sean.brogan@microsoft.= com>; Yao, Jiewen <jiewen.yao@intel.com>
Subject: Re: [E= XTERNAL] [edk2-devel] [PATCH v4] UefiCpuPkg/MtrrLib/UnitTest: Add host base= d unit test

 



On Jul 28, = 2020, at 10:53 AM, Bret Barkelew via groups.io= <bret.ba= rkelew=3Dmicrosoft.com@groups.io> wrote:

 

In this s= trategy, the seed would function like a meta =E2=80=9Ccase=E2=80=9D? We cou= ld add extra =E2=80=9Ccases=E2=80=9D as isolated testing exposes problem se= ts?

 

 

<= div>

Bret,

 

From a quick skim of the t= est it looks like it always generates random data? Not sure if I missed som= ething. 



<= /o:p>

I think the idea is interesting.

 

What is the advantage of this approach over:

  • Run fuzzers in isolation.
  • When a break occurs, isolate the inputs as a new test case fo= r the existing structured test cases.

 

 

The fixed seed i= s an interesting idea, but I=E2=80=99m not sure that is really portable. Wh= at if the CI is running on Windows and the developer is debugging on macOS = or Linux? Seems like you could get different results. So I think that is a = plus for there being more of a structured set of tests as you advocate.&nbs= p;

 

It would also be nice If developer could force t= he failed test case in isolation. Adding a CpuBreakpoint() or DEBUG prints = can be painful if it is the 10,000 iteration of the test loop that fails.&n= bsp;

 

Thanks,

 

Andrew Fish



Thanks!

 

- Bret

 

From: tim.lewis@insyde.com
Sent: Tuesday, July 28, 2020 10:13 AM<= br>To: devel@edk2.groups.io; spbrogan@= outlook.com; Ni, Ray
Cc: Kinn= ey, Michael D; 'Ming Shao'; Dong, Eric; 'Laszlo Ersek'; <= /span>Sean Brogan; Bret Barkelew; Yao, Jiewen
Subject:=  [EXTERNAL] RE: [edk2-d= evel] [PATCH v4] UefiCpuPkg/MtrrLib/UnitTest: Add host based unit test=

 

=

Sean --

What I h= ave seen done for fuzz testing is to (a) report the seed used to initialize= the RNG in the log and then (b) provide an option to force the seed to tha= t value. Using a static seed might actually be the default for CI runs, but= stand-alone runs could use a random value. 

Just a thought.

Tim

-----Original Me= ssage-----
From: devel@edk2.groups.io <devel@edk2.groups.io> On Behalf Of Sean
Sent: Tuesday, July 28, = 2020 9:38 AM
To: devel@edk2.groups.io; ray.ni= @intel.com
Cc: Michael D Kinney <michael.d.kinney@intel.com>; Ming Shao <ming.shao@intel.com>; Eric Dong <eric.dong@intel.com>; Laszlo Erse= k <lersek@redhat.com>; Sean = Brogan <sean.brogan@microso= ft.com>; Bret Barkelew <Bret.Barkelew@microsoft.com>; Jiewen Yao <jiewen.yao@intel.com>
Subject: Re: [edk2-d= evel] [PATCH v4] UefiCpuPkg/MtrrLib/UnitTest: Add host based unit test
<= br>Ray,

I worry that this style of testing will lead to inconsistant= results. 
Generating ra= ndom test cases means that the test cases on any given run 
could find a bug in this code without t= his code changing.   I think this 
type of testing (fuzz testing like) is great but I thi= nk we might want 
to con= sider this a different test type and treat it differently.

For unit = testing the mtrr lib it would make more sense to identify a few 
unique passing and failing tests= and statically add those.  If there are 
edge cases or more cases needed to get full code cov= erage then 
developing t= hose would be great.

Another point is once we start tracking code co= verage your random test generation will lead to different results which will make it hard to 
track the metrics reliably.<= br>
Finally, if edk2 community wants to support fuzz testing (which i th= ink 
is good) we should = add details about how to add fuzz testing to edk2 and 
  how to exclude it from PR/CI test run= s.

Thoughts?

Thanks
Sean




On 7/28/2020 1= :43 AM, Ni, Ray wrote:
> Add host based unit tests for the MtrrLib se= rvices.
> The BaseLib services AsmCpuid(), AsmReadMsr64(), and
>= ; AsmWriteMsr64() are hooked and provide simple emulation
> of the CP= UID leafs and MSRs required by the MtrrLib to
> run as a host based u= nit test.
> 
> = Test cases are developed for each of the API.
> 
> For the most important APIs MtrrSetMemo= ryAttributesInMtrrSettings()
> and MtrrSetMemoryAttributeInMtrrSettin= gs(), random inputs are
> generated and fed to the APIs to make sure = the implementation is
> good. The test application accepts an optiona= l parameter which
> specifies how many iterations of feeding random i= nputs to the two
> APIs. The overall number of test cases increases w= hen the iteration
> increases. Default iteration is 10 when no parame= ter is specified.
> <= br>> Signed-off-by: Ray Ni <ray.n= i@intel.com>
> Signed-off-by: Michael D Kinney <michael.d.kinney@intel.com>
&g= t; Signed-off-by: Ming Shao <ming= .shao@intel.com>
> Cc: Michael D Kinney <michael.d.kinney@intel.com>
> Cc: = Eric Dong <eric.dong@intel.com>
> Cc: Laszlo Ersek <
ler= sek@redhat.com>
> Cc: Ming Shao <ming.shao@intel.com>
> Cc: Sean Brogan <sean.brogan@microsoft.com>> Cc: Bret Barkelew <= Bret.Barkelew@microsoft.com>
> Cc: Jiewen Yao <jiewen.yao@intel.com>
> ---
>= ;   .../MtrrLib/UnitTest/MtrrLibUnitTest.c    = ;    | 1139 +++++++++++++++++
>   .../MtrrLi= b/UnitTest/MtrrLibUnitTest.h        |&nb= sp; 182 +++
>   .../MtrrLib/UnitTest/MtrrLibUnitTestHost.in= f  |   39 +
>   UefiCpuPkg/Library/MtrrLib/U= nitTest/Support.c |  923 +++++++++++++
>   UefiCpuPkg/= Test/UefiCpuPkgHostTest.dsc        |&nbs= p;  31 +
>   UefiCpuPkg/UefiCpuPkg.ci.yaml  =             &nb= sp;  |   12 +-
>   6 files changed, 2325 ins= ertions(+), 1 deletion(-)
>   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/MtrrLibUnitTe= stHost.inf
>   create mode 100644 UefiCpuPkg/Library/MtrrLi= b/UnitTest/Support.c
>   create mode 100644 UefiCpuPkg/Test= /UefiCpuPkgHostTest.dsc
> 
> diff --git a/UefiCpuPkg/Library/MtrrLib/UnitTest/MtrrLibUnitT= est.c b/UefiCpuPkg/Library/MtrrLib/UnitTest/MtrrLibUnitTest.c
> new f= ile mode 100644
> index 0000000000..123e1c741a
> --- /dev/null<= br>> +++ b/UefiCpuPkg/Library/MtrrLib/UnitTest/MtrrLibUnitTest.c
>= @@ -0,0 +1,1139 @@
> +/** @file
> 
> +  Unit tests of the MtrrLib instance of = the MtrrLib class
> <= br>> +
> 
> = +  Copyright (c) 2020, Intel Corporation. All rights reserved.<BR&g= t;
> 
> + = SPDX-License-Identifier: BSD-2-Clause-Patent
> 
> +
> 
> +**/
> 
> +
> <= /span>
> +#include "MtrrLibUnitTest.h"
> 
> +
> 
> +STATIC CONST MTRR_LIB_SYSTEM_PARAM= ETER mDefaultSystemParameter =3D {
> 
> +  42, TRUE, TRUE, CacheUncacheable, 12
&g= t; 
> +};
> 

> +
> 
> +STATIC MTRR_LIB_SYSTEM_PAR= AMETER mSystemParameters[] =3D {
> 
> +  { 38, TRUE, TRUE, CacheUncacheable, &nb= sp;  12 },
> > +  { 38, TRUE, TRUE, CacheWriteBack,    &nbs= p; 12 },
> 
> +=   { 38, TRUE, TRUE, CacheWriteThrough,   12 },
> 
> +  { 38, TRUE, TRU= E, CacheWriteProtected, 12 },
>&n= bsp;
> +  { 38, TRUE, TRUE, CacheWriteCombining, 12 },> 
> +
> 

> +  { 42, TRUE, = TRUE, CacheUncacheable,    12 },
> 
> +  { 42, TRUE, TRUE, CacheWriteB= ack,      12 },
> 
> +  { 42, TRUE, TRUE, CacheWriteThrough,=    12 },
> =
> +  { 42, TRUE, TRUE, CacheWriteProtected, 12 },
> 
> +  { 42, TRUE, TRU= E, CacheWriteCombining, 12 },
>&n= bsp;
> +
> 
> +  { 48, TRUE, TRUE, CacheUncacheable,    1= 2 },
> 
> +&nbs= p; { 48, TRUE, TRUE, CacheWriteBack,      12 },> 
> +  { 48= , TRUE, TRUE, CacheWriteThrough,   12 },
> 
> +  { 48, TRUE, TRUE, CacheWri= teProtected, 12 },
> =
> +  { 48, TRUE, TRUE, CacheWriteCombining, 12 },
> 
> +};
> 
> +
> 
> +UINT32    &nbs= p;            &= nbsp;  mFixedMtrrsIndex[] =3D {
> 
> +  MSR_IA32_MTRR_FIX64K_00000,
> 

> +  MSR_IA32_MTRR_= FIX16K_80000,
> 
&= gt; +  MSR_IA32_MTRR_FIX16K_A0000,
> 
> +  MSR_IA32_MTRR_FIX4K_C0000,
> 
> +  MSR_IA32_MTR= R_FIX4K_C8000,
> 
= > +  MSR_IA32_MTRR_FIX4K_D0000,
> 
> +  MSR_IA32_MTRR_FIX4K_D8000,
> 
> +  MSR_IA32_MTR= R_FIX4K_E0000,
> 
= > +  MSR_IA32_MTRR_FIX4K_E8000,
> 
> +  MSR_IA32_MTRR_FIX4K_F0000,
> 
> +  MSR_IA32_MTR= R_FIX4K_F8000
> 
&= gt; +};
> 
> +S= TATIC_ASSERT (
> 
= > +  (ARRAY_SIZE (mFixedMtrrsIndex) =3D=3D MTRR_NUMBER_OF_FIXED_MTR= R),
> 
> + = ; "gFixedMtrrIndex does NOT contain all the fixed MTRRs!"
>=  
> +  );
>= ; 
> +
> 
> +//
> 
> +// Context structure to be= used for most of the test cases.
> 
> +//
>&nbs= p;
> +typedef struct {
> 
> +  CONST MTRR_LIB_SYSTEM_PARAMETER *SystemPa= rameter;
> 
> += } MTRR_LIB_TEST_CONTEXT;
> <= /span>
> +
> > +//
> 
>= +// Context structure to be used for GetFirmwareVariableMtrrCount() test.<= br>> 
> +//
>= ; 
> +typedef struct = {
> 
> +  = UINT32           &nb= sp;            =   NumberOfReservedVariableMtrrs;
> 
> +  CONST MTRR_LIB_SYSTEM_PARAMETER *System= Parameter;
> 
>= +} MTRR_LIB_GET_FIRMWARE_VARIABLE_MTRR_COUNT_CONTEXT;
> 
> +
> 
> +STATIC CHAR8 *mCacheDescription[] = = =3D { "UC", "WC", "N/A", "N/A", &q= uot;WT", "WP", "WB" };
> 
> +
> 
> +/**
> 
> +  Compare the actual memory ranges against e= xpected memory ranges and return PASS when they match.
> 
> +
> 
> +  @param ExpectedMemoryRanges=      Expected memory ranges.
> 
> +  @param ExpectedMemoryRangeCo= unt Count of expected memory ranges.
> 
> +  @param ActualRanges   &nb= sp;         Actual memory ranges.> 
> +  @pa= ram ActualRangeCount         Count = of actual memory ranges.
> <= /span>
> +
> > +  @retval UNIT_TEST_PASSED  Test passed.
> 
> +  @retval others&nbs= p;           Test failed.=
> 
> +**/
&= gt; 
> +UNIT_TEST_STA= TUS
> 
> +Verif= yMemoryRanges (
> > +  IN MTRR_MEMORY_RANGE  *ExpectedMemoryRanges,
> 

> +  IN UINTN = ;             E= xpectedMemoryRangeCount,
> <= /span>
> +  IN MTRR_MEMORY_RANGE  *ActualRanges,
> 

> +  IN UINTN&nbs= p;             = ActualRangeCount
> > +  )
> > +{
> 
> = +  UINTN  Index;
> = ;
> +  UT_ASSERT_EQUAL (ExpectedMemoryRangeCount, ActualR= angeCount);
> 
>= ; +  for (Index =3D 0; Index < ExpectedMemoryRangeCount; Index++) {=
> 
> + &n= bsp;  UT_ASSERT_EQUAL (ExpectedMemoryRanges[Index].BaseAddress, Actual= Ranges[Index].BaseAddress);
>&nbs= p;
> +    UT_ASSERT_EQUAL (ExpectedMemoryRanges= [Index].Length, ActualRanges[Index].Length);
> 
> +    UT_ASSERT_EQUAL (Exp= ectedMemoryRanges[Index].Type, ActualRanges[Index].Type);
> 
> +  }
> 
> +
> 
> +  return UNIT_TEST_PASSED;> 
> +}
> 

> +
> 
> +/**
> 
> +  Dump the memory ranges.<= br>> 
> +
><= span class=3Dapple-converted-space> 
> +  @param Ran= ges       Memory ranges to dump.
> 
> +  @param RangeCo= unt   Count of memory ranges.
> 
> +**/
> 
> +VOID
>&= nbsp;
> +DumpMemoryRanges (
> 
> +  MTRR_MEMORY_RANGE    = *Ranges,
> 
> +=   UINTN          &nb= sp;     RangeCount
> 
> +  )
> 
> +{
>=  
> +  UINTN     Index;
><= span class=3Dapple-converted-space> 
> +  for (Index= =3D 0; Index < RangeCount; Index++) {
> 
> +    UT_LOG_INFO ("\t{ = 0x%016llx, 0x%016llx, %a },\n", Ranges[Index].BaseAddress, Ranges[Inde= x].Length, mCacheDescription[Ranges[Index].Type]);
> 
> +  }
> 
> +}
> 
> +
> 
> +/**
>&= nbsp;
> +**/
> =
> +
> <= br>> +/**
> 
&g= t; +  Generate random count of MTRRs for each cache type.
> 
> +
> 
> +  @param TotalCount T= otal MTRR count.
> > +  @param UcCount    Return count of Uncacheable= type.
> 
> +&n= bsp; @param WtCount    Return count of Write Through type.> 
> +  @pa= ram 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&nb= sp; UINT32 TotalCount,
> 
> +  OUT UINT32 *UcCount,
> 
> +  OUT UINT32 *WtCount,
> 
> +  OUT UINT32 *WbCo= unt,
> 
> +&nbs= p; OUT UINT32 *WpCount,
> 
> +  OUT UINT32 *WcCount
> 
> +  )
> 
> +{
> 
> +  UINTN  Index;
> 
> +  UINT32 TotalMtrrCount;> 
> +  UINT= 32 *CountPerType[5];
> 
> +
> 
&g= t; +  CountPerType[0] =3D UcCount;
> 
> +  CountPerType[1] =3D WtCount;
><= span class=3Dapple-converted-space> 

> +  CountPerTy= pe[2] =3D WbCount;
> =
> +  CountPerType[3] =3D WpCount;
> 
> +  CountPerType[4] =3D WcCount;> 
> +
> 

> +  //
> 

> +  // Initiali= ze the count of each cache type to 0.
> 
> +  //
> 
> +  for (Index =3D 0; Index < ARRAY_SIZ= E (CountPerType); Index++) {
>&nb= sp;
> +    *(CountPerType[Index]) =3D 0;
>= ; 
> +  }
>= ; 
> +
> 
> +  //
> 
> +  // Pick a rando= m count of MTRRs
> > +  //
> <= br>> +  TotalMtrrCount =3D Random32 (1, TotalCount);
> 
> +  for (Index =3D 0= ; Index < TotalMtrrCount; Index++) {
> 
> +    //
> 
> +    // For each = of them, pick a random cache type.
> 
> +    //
> 
> +    (*(CountPerType[R= andom32 (0, ARRAY_SIZE (CountPerType) - 1)]))++;
> 
> +  }
> 
> +}
> 
> +
> 
> +/**
>&nb= sp;
> +  Unit test of MtrrLib service MtrrSetMemoryAttrib= ute()
> 
> +> 
> +  @par= am[in]  Context    Ignored
> 
> +
> 
> +  @retval  UNIT_TEST_PASSED &n= bsp;           The Unit t= est has completed and the test
>&= nbsp;
> +         = ;            &n= bsp;            = ;      case was successful.
> 
> +  @retval  UNIT_TEST_= ERROR_TEST_FAILED  A test case assertion has failed.
> 
> +
> 
> +**/
> 
> +UNIT_TEST_STATUS
> 
> +EFIAPI
> 
> +UnitTestMtrrSetMemoryAttributesIn= MtrrSettings (
> 
= > +  IN UNIT_TEST_CONTEXT  Context
> 
> +  )
> 
> +{
> 
> +  CONST MTRR_LIB_SYSTEM_PARAMETER *Sys= temParameter;
> 
&= gt; +  RETURN_STATUS        &n= bsp;          Status;
><= span class=3Dapple-converted-space> 
> +  UINT32&nbs= p;            &= nbsp;            UcC= ount;
> 
> +&nb= sp; UINT32           = ;            &n= bsp;  WtCount;
> 

> +  UINT32        &nb= sp;            =      WbCount;
> 
> +  UINT32      &= nbsp;           &nbs= p;       WpCount;
> 
> +  UINT32    = ;            &n= bsp;         WcCount;
> 
> +
> 
> +  UINT32   = ;            &n= bsp;          MtrrIndex;
&g= t; 
> +  UINT8&n= bsp;            = ;            &n= bsp; *Scratch;
> 
= > +  UINTN         &nb= sp;            =      ScratchSize;
> 
> +  MTRR_SETTINGS    &n= bsp;            = ;  LocalMtrrs;
> 

> +
> 
>= ; +  MTRR_MEMORY_RANGE        =        RawMtrrRange[MTRR_NUMBER_OF_VARIABLE_M= TRR];
> 
> +&nb= sp; MTRR_MEMORY_RANGE         =       ExpectedMemoryRanges[MTRR_NUMBER_OF_FIXED_MT= RR * sizeof (UINT64) + 2 * MTRR_NUMBER_OF_VARIABLE_MTRR + 1];
> 
> +  UINT32 &nb= sp;            =             Expected= VariableMtrrUsage;
> =
> +  UINTN         = ;            &n= bsp;     ExpectedMemoryRangesCount;
> 
> +
> 
> +  MTRR_MEMORY_RANGE &nbs= p;             = ActualMemoryRanges[MTRR_NUMBER_OF_FIXED_MTRR   * sizeof (UINT64) = + 2 * MTRR_NUMBER_OF_VARIABLE_MTRR + 1];
> 
> +  UINT32     =             &nb= sp;        ActualVariableMtrrUsage;
&= gt; 
> +  UINTN&= nbsp;           &nbs= p;            &= nbsp; ActualMemoryRangesCount;
>&= nbsp;
> +
> 
> +  MTRR_SETTINGS       = ;      *Mtrrs[2];
> 
> +
> 
> +  SystemParameter =3D (MTRR_LIB_SYSTEM_PARAM= ETER *) Context;
> > +  GenerateRandomMemoryTypeCombination (
> 
> +    SystemParame= ter->VariableMtrrCount - PatchPcdGet32 (PcdCpuNumberOfReservedVariableMt= rrs),
> 
> +&nb= sp;   &UcCount, &WtCount, &WbCount, &WpCount, &am= p;WcCount
> 
> = +    );
> 
> +  GenerateValidAndConfigurableMtrrPairs (
> 
> +    Syst= emParameter->PhysicalAddressBits, RawMtrrRange,
> 
> +    UcCount, WtCou= nt, WbCount, WpCount, WcCount
>&n= bsp;
> +    );
> 
> +
> 
> +  ExpectedVariableMtrrUsage =3D UcCount + Wt= Count + WbCount + WpCount + WcCount;
> 
> +  ExpectedMemoryRangesCount =3D ARRAY_SIZE= (ExpectedMemoryRanges);
> <= /span>
> +  GetEffectiveMemoryRanges (
> 
> +    SystemParameter= ->DefaultCacheType,
> 
> +    SystemParameter->PhysicalAddressBits,> 
> + &nbs= p;  RawMtrrRange, ExpectedVariableMtrrUsage,
> 
> +    ExpectedMemoryR= anges, &ExpectedMemoryRangesCount
> 
> +    );
> 
> +
> 
> +  UT_LOG_INFO (
> 
> +    "T= otal MTRR [%d]: UC=3D%d, WT=3D%d, WB=3D%d, WP=3D%d, WC=3D%d\n",
>= ; 
> +  &nb= sp; ExpectedVariableMtrrUsage, UcCount, WtCount, WbCount, WpCount, WcCount<= br>> 
> + &nb= sp;  );
> 
&g= t; +  UT_LOG_INFO ("--- Expected Memory Ranges [%d] ---\n", = ExpectedMemoryRangesCount);
>&nbs= p;
> +  DumpMemoryRanges (ExpectedMemoryRanges, ExpectedM= emoryRangesCount);
> =
> +
> 
>= +  //
> 
>= ; +  // Default cache type is always an INPUT
> 
> +  //
> 
> +  ZeroMem (&LocalMtrrs,= sizeof (LocalMtrrs));
> 
> +  LocalMtrrs.MtrrDefType =3D MtrrGetDefaultMemoryType ()= ;
> 
> +  = ScratchSize          &nbs= p; =3D SCRATCH_BUFFER_SIZE;
>&nbs= p;
> +  Mtrrs[0]       = ;        =3D &LocalMtrrs;
> 

> +  Mtrrs[1]&nbs= p;            &= nbsp; =3D NULL;
> > +
> 
> +&= nbsp; for (MtrrIndex =3D 0; MtrrIndex < ARRAY_SIZE (Mtrrs); MtrrIndex++)= {
> 
> + =    Scratch =3D calloc (ScratchSize, sizeof (UINT8));
> 

> +    St= atus =3D MtrrSetMemoryAttributesInMtrrSettings (Mtrrs[MtrrIndex], Scratch, = &ScratchSize, ExpectedMemoryRanges, ExpectedMemoryRangesCount);
>=  
> +  &nbs= p; if (Status =3D=3D RETURN_BUFFER_TOO_SMALL) {
> 
> +      Scrat= ch =3D realloc (Scratch, ScratchSize);
> 
> +      Status =3D Mtr= rSetMemoryAttributesInMtrrSettings (Mtrrs[MtrrIndex], Scratch, &Scratch= Size, ExpectedMemoryRanges, ExpectedMemoryRangesCount);
> 
> +    }
&g= t; 
> +  &n= bsp; UT_ASSERT_STATUS_EQUAL (Status, RETURN_SUCCESS);
> 
> +
> 
> +    if (Mtrrs[MtrrIndex= ] =3D=3D NULL) {
> > +      ZeroMem (&LocalMtrrs, sizeof (Lo= calMtrrs));
> 
>= ; +      MtrrGetAllMtrrs (&LocalMtrrs);
>= ; 
> +  &nb= sp; }
> 
> +&nb= sp;   ActualMemoryRangesCount =3D ARRAY_SIZE (ActualMemoryRanges)= ;
> 
> + &= nbsp;  CollectTestResult (
>=  
> +      SystemParameter->D= efaultCacheType, SystemParameter->PhysicalAddressBits, SystemParameter-&= gt;VariableMtrrCount,
> 

> +      &LocalMtrrs, ActualMemoryRa= nges, &ActualMemoryRangesCount, &ActualVariableMtrrUsage
> 
> +   &= nbsp;  );
> 
= > +
> 
> +&n= bsp;   UT_LOG_INFO ("--- Actual Memory Ranges [%d] ---\n&quo= t;, ActualMemoryRangesCount);
>&n= bsp;
> +    DumpMemoryRanges (ActualMemoryRange= s, ActualMemoryRangesCount);
>&nb= sp;
> +    VerifyMemoryRanges (ExpectedMemoryRa= nges, ExpectedMemoryRangesCount, ActualMemoryRanges, ActualMemoryRangesCoun= t);
> 
> + = ;   UT_ASSERT_TRUE (ExpectedVariableMtrrUsage >=3D ActualVaria= bleMtrrUsage);
> 
= > +
> 
> +&n= bsp;   ZeroMem (&LocalMtrrs, sizeof (LocalMtrrs));
> 
> +  }
> 
> +
> 
> +  free (Scratch);
= > 
> +
> 
> +  return UNIT_T= EST_PASSED;
> 
>= ; +}
> 
> +
= > 
> +/**
><= span class=3Dapple-converted-space> 
> +  Test routi= ne to check whether invalid base/size can be rejected.
> 
> +
> 
> +  @param Context   = Pointer to MTRR_LIB_SYSTEM_PARAMETER.
> 
> +
>&n= bsp;
> +  @return Test status.
> 
> +**/
> 
> +UNIT_TEST_STATUS
> 
> +EFIAPI
> 
> +UnitTestInvalidMemoryLayouts (
= > 
> +  IN UN= IT_TEST_CONTEXT          Conte= xt
> 
> + = )
> 
> +{
&= gt; 
> +  CONST = MTRR_LIB_SYSTEM_PARAMETER *SystemParameter;
> 
> +  MTRR_MEMORY_RANGE  &nbs= p;            Ranges= [MTRR_NUMBER_OF_VARIABLE_MTRR * 2 + 1];
> 
> +  UINTN     &n= bsp;            = ;         RangeCount;
> 
> +  UINT64 &nb= sp;            =             MaxAddre= ss;
> 
> + = ; UINT32           &= nbsp;           &nbs= p;  Index;
> > +  UINT64         &= nbsp;           &nbs= p;    BaseAddress;
> 
> +  UINT64      &= nbsp;           &nbs= p;       Length;
> 
> +  RETURN_STATUS   = ;            &n= bsp;   Status;
> <= /span>
> +  UINTN        = ;            &n= bsp;      ScratchSize;
> 
> +
> 
> +  SystemParameter =3D (MTRR_LIB_SYSTEM_= PARAMETER *) Context;
> 

> +
> 
&= gt; +  RangeCount =3D Random32 (1, ARRAY_SIZE (Ranges));
> 
> +  MaxAddress =3D = 1ull << SystemParameter->PhysicalAddressBits;
> 
> +
> 
> +  for (Index =3D 0; Index <= ; RangeCount; Index++) {
> <= /span>
> +    do {
> 
> +      BaseAddress = =3D Random64 (0, MaxAddress);
>&= nbsp;
> +      Length  &nbs= p;   =3D Random64 (1, MaxAddress - BaseAddress);
> 
> +    } whil= e (((BaseAddress & 0xFFF) =3D=3D 0) || ((Length & 0xFFF) =3D=3D 0))= ;
> 
> +
>= ; 
> +  &nb= sp; Ranges[Index].BaseAddress =3D BaseAddress;
> 
> +    Ranges[Index].Leng= th      =3D Length;
> 
> +    Ranges[Index].Type&n= bsp;       =3D GenerateRandomCacheType ();> 
> +
> 

> +    = Status =3D MtrrSetMemoryAttribute (
> 
> +      Ranges[Index].Bas= eAddress, Ranges[Index].Length, Ranges[Index].Type
> 
> +      );=
> 
> + &n= bsp;  UT_ASSERT_TRUE (RETURN_ERROR (Status));
> 
> +  }
> 
> +
> 
> +  ScratchSize =3D 0;
> 
> +  Status =3D MtrrSe= tMemoryAttributesInMtrrSettings (NULL, NULL, &ScratchSize, Ranges, Rang= eCount);
> 
> +=   UT_ASSERT_TRUE (RETURN_ERROR (Status));
> 
> +
> 
> +  return UNIT_TEST_PASSED;
> 
> +}
> 
> +
> 
> +/**
> 
> +  Unit test of MtrrLib service IsM= trrSupported()
> 
= > +
> 
> +&n= bsp; @param[in]  Context    Ignored
> 
> +
> 
> +  @retval  UNIT_TEST_PAS= SED            = The Unit test has completed and the test
> 
> +       =             &nb= sp;            =         case was successful.
> 
> +  @retval = UNIT_TEST_ERROR_TEST_FAILED  A test case assertion has failed.
>= ; 
> +
> 
> +**/
> 
> +UNIT_TEST_STATUS
> 
> +EFIAPI
> 
> +UnitTestIsMtrrSuppor= ted (
> 
> +&nb= sp; IN UNIT_TEST_CONTEXT  Context
> 
> +  )
> 
> +{
>=  
> +  MTRR_LIB_SYSTEM_PARAMETER  SystemParamet= er;
> 
> + = ; MTRR_LIB_TEST_CONTEXT      *LocalContext;
>= ; 
> +
> 
> +  LocalContext =3D= (MTRR_LIB_TEST_CONTEXT *) Context;
> 
> +
>&nbs= p;
> +  CopyMem (&SystemParameter, LocalContext->S= ystemParameter, sizeof (SystemParameter));
> 
> +  //
> 
> +  // MTRR capability off in CPUID l= eaf.
> 
> +&nbs= p; //
> 
> +&nb= sp; SystemParameter.MtrrSupported =3D FALSE;
> 
> +  InitializeMtrrRegs (&SystemP= arameter);
> 
>= +  UT_ASSERT_FALSE (IsMtrrSupported ());
> 
> +
> 
> +  //
> 
> +  // MTRR capability on in CPUID leaf, = but no variable or fixed MTRRs.
>=  
> +  //
> 
> +  SystemParameter.MtrrSupported =3D TRUE;
&= gt; 
> +  System= Parameter.VariableMtrrCount =3D 0;
> 
> +  SystemParameter.FixedMtrrSupported =3D FAL= SE;
> 
> + = ; InitializeMtrrRegs (&SystemParameter);
> 
> +  UT_ASSERT_FALSE (IsMtrrSupported= ());
> 
> +> 
> +  //> 
> +  // = MTRR capability on in CPUID leaf, but no variable MTRRs.
> 
> +  //
> 
> +  SystemParameter.Mt= rrSupported =3D TRUE;
> 

> +  SystemParameter.VariableMtrrCount =3D 0;
> 
> +  SystemParameter.= FixedMtrrSupported =3D TRUE;
>&nb= sp;
> +  InitializeMtrrRegs (&SystemParameter);
&g= t; 
> +  UT_ASSE= RT_FALSE (IsMtrrSupported ());
>&= nbsp;
> +
> 
> +  //
> 
> +  // MTRR capability on in CPUID leaf, but no fixed MTR= Rs.
> 
> + = ; //
> 
> +&nbs= p; SystemParameter.MtrrSupported =3D TRUE;
> 
> +  SystemParameter.VariableMtrrCount = = =3D 7;
> 
> +&= nbsp; SystemParameter.FixedMtrrSupported =3D FALSE;
> 
> +  InitializeMtrrRegs (&= SystemParameter);
> <= br>> +  UT_ASSERT_FALSE (IsMtrrSupported ());
> 
> +
> 
> +  //
> 
> +  // MTRR capability on in CPUID= leaf with both variable and fixed MTRRs.
> 
> +  //
> 
> +  SystemParameter.MtrrSupported =3D = TRUE;
> 
> +&nb= sp; SystemParameter.VariableMtrrCount =3D 7;
> 
> +  SystemParameter.FixedMtrrSupport= ed =3D TRUE;
> 
&g= t; +  InitializeMtrrRegs (&SystemParameter);
> 
> +  UT_ASSERT_TRUE (IsMtrrS= upported ());
> 
&= gt; +
> 
> +&nb= sp; return UNIT_TEST_PASSED;
>&nb= sp;
> +}
> 

> +
> 
&= gt; +/**
> 
> +=   Unit test of MtrrLib service GetVariableMtrrCount()
> 
> +
> 
> +  @param[in]  Context&n= bsp;   Ignored
> <= /span>
> +
> > +  @retval  UNIT_TEST_PASSED     =         The Unit test has completed and = the test
> 
> +=             &nb= sp;            =             &nb= sp;  case was successful.
>&= nbsp;
> +  @retval  UNIT_TEST_ERROR_TEST_FAILED = ; A test case assertion has failed.
> 
> +
>&nbs= p;
> +**/
> 
> +UNIT_TEST_STATUS
>&= nbsp;
> +EFIAPI
>&nb= sp;
> +UnitTestGetVariableMtrrCount (
> 
> +  IN UNIT_TEST_CONTEXT = Context
> 
> +=   )
> 
> += {
> 
> +  = UINT32           &nb= sp;        Result;
> 
> +  MTRR_LIB_SYSTEM_PARAMET= ER SystemParameter;
> 
> +  MTRR_LIB_TEST_CONTEXT     *LocalConte= xt;
> 
> +
&= gt; 
> +  LocalC= ontext =3D (MTRR_LIB_TEST_CONTEXT *) Context;
> 
> +
> 
> +  CopyMem (&SystemParameter, LocalCon= text->SystemParameter, sizeof (SystemParameter));
> 
> +  //
> 
> +  // If MTRR capability o= ff in CPUID leaf, then the count is always 0.
> 
> +  //
> 
> +  SystemParameter.MtrrSupported = = =3D FALSE;
> 
>= ; +  for (SystemParameter.VariableMtrrCount =3D 1; SystemParameter.Var= iableMtrrCount <=3D MTRR_NUMBER_OF_VARIABLE_MTRR; SystemParameter.Variab= leMtrrCount++) {
> > +    InitializeMtrrRegs (&SystemParameter);
&g= t; 
> +  &n= bsp; Result =3D GetVariableMtrrCount ();
> 
> +    UT_ASSERT_EQUAL (Result,= 0);
> 
> +&nbs= p; }
> 
> +
= > 
> +  //> 
> +  // T= ry all supported variable MTRR counts.
> 
> +  // If variable MTRR count is > MTRR= _NUMBER_OF_VARIABLE_MTRR, then an ASSERT()
> 
> +  // is generated.
> 
> +  //
> 
> +  SystemParameter.Mt= rrSupported =3D TRUE;
> 

> +  for (SystemParameter.VariableMtrrCount =3D 1; SystemPar= ameter.VariableMtrrCount <=3D MTRR_NUMBER_OF_VARIABLE_MTRR; SystemParame= ter.VariableMtrrCount++) {
> = ;
> +    InitializeMtrrRegs (&SystemParamet= er);
> 
> +&nbs= p;   Result =3D GetVariableMtrrCount ();
> 
> +    UT_ASSERT_EQUA= L (Result, SystemParameter.VariableMtrrCount);
> 
> +  }
> 
> +
> 
> +  //
> 
> +  // Expect ASSERT() if variable MTRR c= ount is > MTRR_NUMBER_OF_VARIABLE_MTRR
> 
> +  //
> 
> +  SystemParameter.VariableMtrrCount = = =3D MTRR_NUMBER_OF_VARIABLE_MTRR + 1;
> 
> +  InitializeMtrrRegs (&SystemParamet= er);
> 
> +&nbs= p; UT_EXPECT_ASSERT_FAILURE (GetVariableMtrrCount (), NULL);
> 
> +
> 
> +  SystemParameter.MtrrSupp= orted =3D TRUE;
> > +  SystemParameter.VariableMtrrCount =3D MAX_UINT8;
> 
> +  InitializeMtrr= Regs (&SystemParameter);
>&nb= sp;
> +  UT_EXPECT_ASSERT_FAILURE (GetVariableMtrrCount (= ), NULL);
> 
> = +
> 
> +  = return UNIT_TEST_PASSED;
> <= /span>
> +}
> <= br>> +
> 
> = +/**
> 
> +&nbs= p; Unit test of MtrrLib service GetFirmwareVariableMtrrCount()
> 

> +
> 
> +  @param[in]  Co= ntext    Ignored
>=  
> +
> 
> +  @retval  UNIT_TEST_PASSED    = ;         The Unit test has complet= ed and the test
> > +           &n= bsp;            = ;            &n= bsp;   case was successful.
> 
> +  @retval  UNIT_TEST_ERROR_TEST_FAIL= ED  A test case assertion has failed.
> 
> +
> 
> +**/
>&n= bsp;
> +UNIT_TEST_STATUS
> 
> +EFIAPI
> 
> +UnitTestGetFirmwareVariableMtrrCount (
> 

> +  IN UNIT_TES= T_CONTEXT  Context
> 
> +  )
> 
> +{
> > +  UINT32         =             &nb= sp;            =           Result;
> 

> +  UINT32 &n= bsp;            = ;            &n= bsp;            = ;     ReservedMtrrs;
> 
> +  MTRR_LIB_SYSTEM_PARAMETER  = ;            &n= bsp;          SystemParameter;=
> 
> +  M= TRR_LIB_GET_FIRMWARE_VARIABLE_MTRR_COUNT_CONTEXT *LocalContext;
> 

> +
> 
> +  LocalContext =3D (M= TRR_LIB_GET_FIRMWARE_VARIABLE_MTRR_COUNT_CONTEXT *) Context;
> 
> +
> 
> +  CopyMem (&SystemPara= meter, LocalContext->SystemParameter, sizeof (SystemParameter));
>=  
> +
> 
> +  InitializeMtrrReg= s (&SystemParameter);
> =
> +  //
> = ;
> +  // Positive test cases for VCNT =3D 10 and Reserve= d PCD in range 0..10
> 
> +  //
> 

> +  for (ReservedMtrrs =3D 0; ReservedMtrrs <=3D SystemP= arameter.VariableMtrrCount; ReservedMtrrs++) {
> 
> +    PatchPcdSet32 (Pcd= CpuNumberOfReservedVariableMtrrs, ReservedMtrrs);
> 
> +    Result =3D GetF= irmwareVariableMtrrCount ();
>&nb= sp;
> +    UT_ASSERT_EQUAL (Result, SystemParam= eter.VariableMtrrCount - ReservedMtrrs);
> 
> +  }
> 
> +
> 
> +  //
> 
> +  // Negative test cases when Reserved PCD is= larger than VCNT
> <= br>> +  //
> =
> +  for (ReservedMtrrs =3D SystemParameter.VariableMtrrCount += 1; ReservedMtrrs <=3D 255; ReservedMtrrs++) {
> 
> +    PatchPcdSet32 (= PcdCpuNumberOfReservedVariableMtrrs, ReservedMtrrs);
> 
> +    Result =3D G= etFirmwareVariableMtrrCount ();
>=  
> +    UT_ASSERT_EQUAL (Result, 0);
&= gt; 
> +  }
&= gt; 
> +
> 
> +  //
> 
> +  // Negative t= est cases when Reserved PCD is larger than VCNT
> 
> +  //
> 
> +  PatchPcdSet32 (PcdCpuNumberO= fReservedVariableMtrrs, MAX_UINT32);
> 
> +  Result =3D GetFirmwareVariableMtrrCount = ();
> 
> + = ; UT_ASSERT_EQUAL (Result, 0);
>&= nbsp;
> +
> 
> +  //
> 
> +  // Negative test case when MTRRs are not supported> 
> +  //> 
> +  Sys= temParameter.MtrrSupported =3D FALSE;
> 
> +  InitializeMtrrRegs (&SystemParamete= r);
> 
> + = ; PatchPcdSet32 (PcdCpuNumberOfReservedVariableMtrrs, 2);
> 
> +  Result =3D GetFirmw= areVariableMtrrCount ();
> <= /span>
> +  UT_ASSERT_EQUAL (Result, 0);
> 
> +
> 
> +  //
> 
> +  // Negative test case when Fixed= MTRRs are not supported
> <= /span>
> +  //
> =
> +  SystemParameter.MtrrSupported =3D TRUE;
> 

> +  SystemParamet= er.FixedMtrrSupported =3D FALSE;
> 
> +  InitializeMtrrRegs (&SystemParameter);> 
> +  Pat= chPcdSet32 (PcdCpuNumberOfReservedVariableMtrrs, 2);
> 
> +  Result =3D GetFirmwareVa= riableMtrrCount ();
> 

> +  UT_ASSERT_EQUAL (Result, 0);
> 
> +
> 
> +  //
> 
> +  // Expect ASSERT() if variable MTRR c= ount is > MTRR_NUMBER_OF_VARIABLE_MTRR
> 
> +  //
> 
> +  SystemParameter.FixedMtrrSupported= =3D TRUE;
> 
>= +  SystemParameter.VariableMtrrCount =3D MTRR_NUMBER_OF_VARIABLE_MTRR= + 1;
> 
> +&nb= sp; InitializeMtrrRegs (&SystemParameter);
> 
> +  UT_EXPECT_ASSERT_FAILURE (GetF= irmwareVariableMtrrCount (), NULL);
> 
> +
>&nbs= p;
> +  return UNIT_TEST_PASSED;
> 
> +}
> 
> +
> 
> +/**
>&= nbsp;
> +  Unit test of MtrrLib service MtrrGetMemoryAttr= ibute()
> 
> +<= br>> 
> +  @p= aram[in]  Context    Ignored
> 
> +
> 
> +  @retval  UNIT_TEST_PASSED =             The Unit= test has completed and the test
> 
> +        &nb= sp;            =             &nb= sp;      case was successful.
> 
> +  @retval  UNIT_= TEST_ERROR_TEST_FAILED  A test case assertion has failed.
> 
> +
> 
> +**/
> 
> +UNIT_TEST_STATUS
> 
> +EFIAPI
> 
> +UnitTestMtrrGetMemoryAttr= ibute (
> 
> +&= nbsp; IN UNIT_TEST_CONTEXT  Context
> 
> +  )
> 
> +{
> 
> +  return UNIT_TEST_PASSED;
> 
> +}
> 
> +
> 
> +/**
> 
> +  Unit test of MtrrLib service MtrrGetFix= edMtrr()
> 
> +=
> 
> +  @= param[in]  Context    Ignored
> 
> +
> 
> +  @retval  UNIT_TEST_PASSED = ;            The Uni= t test has completed and the test
> 
> +        &n= bsp;            = ;            &n= bsp;      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
> 
> +  )
> 
> +{
>&nbs= p;
> +  MTRR_FIXED_SETTINGS     =   *Result;
> > +  MTRR_FIXED_SETTINGS       Expec= tedFixedSettings;
> <= br>> +  MTRR_FIXED_SETTINGS       Fix= edSettings;
> 
>= ; +  UINTN          =            Index;
>=  
> +  UINTN&nbs= p;            &= nbsp;       MsrIndex;
> 
> +  UINTN   &n= bsp;            = ;     ByteIndex;
> 
> +  UINT64     &nbs= p;            &= nbsp; MsrValue;
> > +  MTRR_LIB_SYSTEM_PARAMETER SystemParameter;
> 
> +  MTRR_LIB_TEST_CONTE= XT     *LocalContext;
> 
> +
> 
> +  LocalContext =3D (MTRR_LIB_TEST_CONTEXT *) = Context;
> 
> +=
> 
> +  C= opyMem (&SystemParameter, LocalContext->SystemParameter, sizeof (Sys= temParameter));
> > +  InitializeMtrrRegs (&SystemParameter);
> 
> +  //
> 
> +  // Set random cach= e type to different ranges under 1MB and make sure
> 
> +  // the fixed MTRR settings= are expected.
> 
= > +  // Try 100 times.
>&= nbsp;
> +  //
>=  
> +  for (Index =3D 0; Index < 100; Index++) {<= br>> 
> + &nb= sp;  for (MsrIndex =3D 0; MsrIndex < ARRAY_SIZE (mFixedMtrrsIndex);= MsrIndex++) {
> 
= > +      MsrValue =3D 0;
> 
> +      = for (ByteIndex =3D 0; ByteIndex < sizeof (UINT64); ByteIndex++) {
>= ; 
> +  &nb= sp;     MsrValue =3D MsrValue | LShiftU64 (GenerateRand= omCacheType (), ByteIndex * 8);
>=  
> +      }
> 
> +    &n= bsp; ExpectedFixedSettings.Mtrr[MsrIndex] =3D MsrValue;
> 
> +    &n= bsp; AsmWriteMsr64 (mFixedMtrrsIndex[MsrIndex], MsrValue);
> 
> +    }
&= gt; 
> +
> 
> +    Re= sult =3D MtrrGetFixedMtrr (&FixedSettings);
> 
> +    UT_ASSERT_EQUAL (= Result, &FixedSettings);
>&nb= sp;
> +    UT_ASSERT_MEM_EQUAL (&FixedSetti= ngs, &ExpectedFixedSettings, sizeof (FixedSettings));
> 
> +  }
> 
> +
> 
> +  //
> 
> +  // Negative test case when= MTRRs are not supported
> <= /span>
> +  //
> =
> +  SystemParameter.MtrrSupported =3D FALSE;
> 

> +  InitializeMt= rrRegs (&SystemParameter);
>&= nbsp;
> +
> 
> +  ZeroMem (&FixedSettings, sizeof (FixedSettings));<= br>> 
> +  Ze= roMem (&ExpectedFixedSettings, sizeof (ExpectedFixedSettings));
>=  
> +  Result = =3D MtrrGetFixedMtrr (&FixedSettings);
> 
> +  UT_ASSERT_EQUAL (Result, &Fix= edSettings);
> 
&g= t; +  UT_ASSERT_MEM_EQUAL (&ExpectedFixedSettings, &FixedSetti= ngs, sizeof (ExpectedFixedSettings));
> 
> +
>&n= bsp;
> +  return UNIT_TEST_PASSED;
> 
> +}
> 
> +
> 
> +/**
> 
> +  Unit test of MtrrLib service MtrrGetAllMtrrs= ()
> 
> +
&g= t; 
> +  @param[= in]  Context    Ignored
> 
> +
> 
> +  @retval  UNIT_TEST_PASSED  = ;           The Unit test= has completed and the test
>&nbs= p;
> +         &n= bsp;            = ;            &n= bsp;     case was successful.
> 
> +  @retval  UNIT_TEST_ERR= OR_TEST_FAILED  A test case assertion has failed.
> 
> +
> 
> +**/
> 
> +UNIT_TEST_STATUS
> 
> +EFIAPI
> 
> +UnitTestMtrrGetAllMtrrs (
>=  
> +  IN UNIT_T= EST_CONTEXT      Context
> 
> +  )
> 
> +{
> 
> +  MTRR_SETTINGS   &nb= sp;         *Result;
> 
> +  MTRR_SETTINGS&nb= sp;            Mtrrs= ;
> 
> +  = MTRR_SETTINGS          &n= bsp;  ExpectedMtrrs;
> =
> +  MTRR_VARIABLE_SETTING     Varia= bleMtrr[MTRR_NUMBER_OF_VARIABLE_MTRR];
> 
> +  UINT32     &n= bsp;            = ;  Index;
> 
= > +  MTRR_LIB_SYSTEM_PARAMETER SystemParameter;
> 
> +  MTRR_LIB_TEST_CONTE= XT     *LocalContext;
> 
> +
> 
> +  LocalContext =3D (MTRR_LIB_TEST_CONTEXT *) = Context;
> 
> +=
> 
> +  C= opyMem (&SystemParameter, LocalContext->SystemParameter, sizeof (Sys= temParameter));
> > +  InitializeMtrrRegs (&SystemParameter);
> 
> +
> 
> +  for (Index =3D 0; Index <= ; SystemParameter.VariableMtrrCount; Index++) {
> 
> +    GenerateRandomMtr= rPair (SystemParameter.PhysicalAddressBits, GenerateRandomCacheType (), &am= p;VariableMtrr[Index], NULL);
>&n= bsp;
> +    AsmWriteMsr64 (MSR_IA32_MTRR_PHYSBA= SE0 + (Index << 1), VariableMtrr[Index].Base);
> 
> +    AsmWriteMsr6= 4 (MSR_IA32_MTRR_PHYSMASK0 + (Index << 1), VariableMtrr[Index].Mask);=
> 
> +  }=
> 
> +  R= esult =3D MtrrGetAllMtrrs (&Mtrrs);
> 
> +  UT_ASSERT_EQUAL (Result, &Mtrrs);=
> 
> +  U= T_ASSERT_MEM_EQUAL (Mtrrs.Variables.Mtrr, VariableMtrr, sizeof (MTRR_VARIAB= LE_SETTING) * SystemParameter.VariableMtrrCount);
> 
> +
> 
> +  //
> 
> +  // Negative test case when MTRRs a= re not supported
> > +  //
> <= br>> +  ZeroMem (&ExpectedMtrrs, sizeof (ExpectedMtrrs));
&g= t; 
> +  ZeroMem= (&Mtrrs, sizeof (Mtrrs));
>&= nbsp;
> +
> 
> +  SystemParameter.MtrrSupported =3D FALSE;
> 
> +  InitializeMtrrR= egs (&SystemParameter);
>&nbs= p;
> +  Result =3D MtrrGetAllMtrrs (&Mtrrs);
><= span class=3Dapple-converted-space> 

> +  UT_ASSERT_= EQUAL (Result, &Mtrrs);
>&nbs= p;
> +  UT_ASSERT_MEM_EQUAL (&ExpectedMtrrs, &Mtr= rs, sizeof (ExpectedMtrrs));
>&nb= sp;
> +
> 
> +  //
> 
> +  // Expect ASSERT() if variable MTRR count is > MTRR_= NUMBER_OF_VARIABLE_MTRR
> 
> +  //
> <= /span>
> +  SystemParameter.MtrrSupported =3D TRUE;
> 

> +  SystemParamete= r.VariableMtrrCount =3D MTRR_NUMBER_OF_VARIABLE_MTRR + 1;
> 
> +  InitializeMtrrRegs = (&SystemParameter);
> 
> +  UT_EXPECT_ASSERT_FAILURE (MtrrGetAllMtrrs (&Mtrrs= ), NULL);
> 
> = +
> 
> +  = return UNIT_TEST_PASSED;
> <= /span>
> +}
> <= br>> +
> 
> = +/**
> 
> +&nbs= p; Unit test of MtrrLib service MtrrSetAllMtrrs()
> 
> +
> 
> +  @param[in]  Context  = ;  Ignored
> > +
> 
> +&= nbsp; @retval  UNIT_TEST_PASSED      &nb= sp;      The Unit test has completed and the test<= br>> 
> + &nb= sp;            =             &nb= sp;            = case was successful.
> 
> +  @retval  UNIT_TEST_ERROR_TEST_FAILED  A test = case assertion has failed.
> = ;
> +
> =
> +**/
> 
&= gt; +UNIT_TEST_STATUS
> 
> +EFIAPI
> 

> +UnitTestMtrrSetAllMtrrs (
> 
> +  IN UNIT_TEST_CONTEXT  Context
&g= t; 
> +  )
&g= t; 
> +{
> 
> +  MTRR_SETTINGS&= nbsp;           &nbs= p;      *Result;
> 
> +  MTRR_SETTINGS   &nbs= p;            &= nbsp;  Mtrrs;
> =
> +  UINT32        &nbs= p;            &= nbsp;    Index;
>&= nbsp;
> +  MSR_IA32_MTRR_DEF_TYPE_REGISTER Default;
&g= t; 
> +  MTRR_LI= B_SYSTEM_PARAMETER       SystemParameter;
= > 
> +  MTRR_= LIB_TEST_CONTEXT          = ; *LocalContext;
> > +
> 
> +=   LocalContext =3D (MTRR_LIB_TEST_CONTEXT *) Context;
> 
> +
> 
> +  CopyMem (&SystemParame= ter, LocalContext->SystemParameter, sizeof (SystemParameter));
> 
> +  InitializeM= trrRegs (&SystemParameter);
>=  
> +
> 
> +  Default.Uint64 =3D 0;
> 
> +  Default.Bits.E =3D 1;
> 

> +  Default.Bits.= FE =3D 1;
> 
> = +  Default.Bits.Type =3D GenerateRandomCacheType ();
> 
> +
> 
> +  ZeroMem (&Mtrrs, sizeof= (Mtrrs));
> 
>= +  Mtrrs.MtrrDefType =3D Default.Uint64;
> 
> +  for (Index =3D 0; Index < S= ystemParameter.VariableMtrrCount; Index++) {
> 
> +    GenerateRandomMtrrPa= ir (SystemParameter.PhysicalAddressBits, GenerateRandomCacheType (), &M= trrs.Variables.Mtrr[Index], NULL);
> 
> +  }
> 
> +  Result =3D MtrrSetAllMtrrs (&Mtrrs);> 
> +  UT_= ASSERT_EQUAL (Result, &Mtrrs);
> 
> +
> = ;
> +  UT_ASSERT_EQUAL (AsmReadMsr64 (MSR_IA32_MTRR_DEF_T= YPE), Mtrrs.MtrrDefType);
> =
> +  for (Index =3D 0; Index < SystemParameter.Variab= leMtrrCount; Index++) {
> 
> +    UT_ASSERT_EQUAL (AsmReadMsr64 (MSR_IA32_M= TRR_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 MtrrGetM= emoryAttributeInVariableMtrr()
>&= nbsp;
> +
> 

> +  @param[in]  Context    Ignored
= > 
> +
> 
> +  @retval = UNIT_TEST_PASSED         &nbs= p;   The Unit test has completed and the test
> 
> +    &n= bsp;            = ;            &n= bsp;          case was success= ful.
> 
> +&nbs= p; @retval  UNIT_TEST_ERROR_TEST_FAILED  A test case assertion ha= s failed.
> 
> = +
> 
> +**/
= > 
> +UNIT_TEST_ST= ATUS
> 
> +EFIA= PI
> 
> +UnitTe= stMtrrGetMemoryAttributeInVariableMtrr (
> 
> +  IN UNIT_TEST_CONTEXT  Context> 
> +  )> 
> +{
><= span class=3Dapple-converted-space> 
> +  MTRR_LIB_T= EST_CONTEXT           *Lo= calContext;
> 
>= ; +  MTRR_LIB_SYSTEM_PARAMETER       Sys= temParameter;
> 
&= gt; +  UINT32         &nb= sp;            =     Result;
> = ;
> +  MTRR_VARIABLE_SETTING     = ;      VariableSetting[MTRR_NUMBER_OF_VARIABLE_MTR= R];
> 
> + = ; VARIABLE_MTRR          =          VariableMtrr[MTRR_NUMBER_O= F_VARIABLE_MTRR];
> <= br>> +  UINT64         = ;            &n= bsp;    ValidMtrrBitsMask;
> 
> +  UINT64     = ;            &n= bsp;        ValidMtrrAddressMask;
>= ; 
> +  UINT32&n= bsp;            = ;             I= ndex;
> 
> +&nb= sp; MSR_IA32_MTRR_PHYSBASE_REGISTER Base;
> 
> +  MSR_IA32_MTRR_PHYSMASK_REGISTER Mas= k;
> 
> +
&g= t; 
> +  LocalCo= ntext =3D (MTRR_LIB_TEST_CONTEXT *) Context;
> 
> +
> 
> +  CopyMem (&SystemParameter, LocalCont= ext->SystemParameter, sizeof (SystemParameter));
> 
> +
> 
> +  InitializeMtrrRegs (&SystemPa= rameter);
> 
> = +
> 
> +  = ValidMtrrBitsMask    =3D (1ull << SystemParameter.Phys= icalAddressBits) - 1;
> 
> +  ValidMtrrAddressMask =3D ValidMtrrBitsMask & 0xffff= fffffffff000ULL;
> > +
> 
> +=   for (Index =3D 0; Index < SystemParameter.VariableMtrrCount; Inde= x++) {
> 
> +&n= bsp;   GenerateRandomMtrrPair (SystemParameter.PhysicalAddressBit= s, GenerateRandomCacheType (), &VariableSetting[Index], NULL);
><= span class=3Dapple-converted-space> 

> +   = ; AsmWriteMsr64 (MSR_IA32_MTRR_PHYSBASE0 + (Index << 1), VariableSett= ing[Index].Base);
> <= br>> +    AsmWriteMsr64 (MSR_IA32_MTRR_PHYSMASK0 + (Index= << 1), VariableSetting[Index].Mask);
> 
> +  }
> 
> +  Result =3D MtrrGetMemoryAttribute= InVariableMtrr (ValidMtrrBitsMask, ValidMtrrAddressMask, VariableMtrr);
= > 
> +  UT_AS= SERT_EQUAL (Result, SystemParameter.VariableMtrrCount);
> 
> +
> 
> +  for (Index =3D 0; Index <= ; SystemParameter.VariableMtrrCount; Index++) {
> 
> +    Base.Uint64 =    =3D VariableMtrr[Index].BaseAddress;
> 
> +    Base.Bits.Type = = =3D (UINT32) VariableMtrr[Index].Type;
> 
> +    UT_ASSERT_EQUAL (Base.Uin= t64, VariableSetting[Index].Base);
> 
> +
> = ;
> +    Mask.Uint64    =3D ~(Va= riableMtrr[Index].Length - 1) & ValidMtrrBitsMask;
> 
> +    Mask.Bi= ts.V    =3D 1;
>&n= bsp;
> +    UT_ASSERT_EQUAL (Mask.Uint64, Varia= bleSetting[Index].Mask);
> <= /span>
> +  }
> <= /span>
> +
> > +  //
> <= br>> +  // Negative test case when MTRRs are not supported
><= span class=3Dapple-converted-space> 

> +  //
>=  
> +  SystemPar= ameter.MtrrSupported =3D FALSE;
>=  
> +  InitializeMtrrRegs (&SystemParameter);> 
> +  Resu= lt =3D MtrrGetMemoryAttributeInVariableMtrr (ValidMtrrBitsMask, ValidMtrrAd= dressMask, VariableMtrr);
> =
> +  UT_ASSERT_EQUAL (Result, 0);
> 
> +
> 
> +  //
> 
> +  // Expect ASSERT() if variable = MTRR count is > MTRR_NUMBER_OF_VARIABLE_MTRR
> 
> +  //
> 
> +  SystemParameter.MtrrSupporte= d =3D TRUE;
> 
>= ; +  SystemParameter.VariableMtrrCount =3D MTRR_NUMBER_OF_VARIABLE_MTR= R + 1;
> 
> +&n= bsp; InitializeMtrrRegs (&SystemParameter);
> 
> +  UT_EXPECT_ASSERT_FAILURE (Mtr= rGetMemoryAttributeInVariableMtrr (ValidMtrrBitsMask, ValidMtrrAddressMask,= VariableMtrr), NULL);
> 
> +
> 
= > +  return UNIT_TEST_PASSED;
> 
> +}
>&= nbsp;
> +
> 
> +/**
> <= br>> +  Unit test of MtrrLib service MtrrDebugPrintAllMtrrs()
&g= t; 
> +
> 
> +  @param[in] = ; Context    Ignored
> 
> +
>&nbs= p;
> +  @retval  UNIT_TEST_PASSED   &= nbsp;         The Unit test has com= pleted and the test
> 

> +          &nbs= p;            &= nbsp;           &nbs= p;    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;
> 
> +}
>&= nbsp;
> +
> 
> +/**
> <= br>> +  Unit test of MtrrLib service MtrrGetDefaultMemoryType().> 
> +
> 

> +  @param[in]&n= bsp; Context    Ignored
> 
> +
>&= nbsp;
> +  @retval  UNIT_TEST_PASSED  &nbs= p;          The Unit test has = completed and the test
> 
> +          &= nbsp;           &nbs= p;            &= nbsp;    case was successful.
> 
> +  @retval  UNIT_TEST_ERROR_TE= ST_FAILED  A test case assertion has failed.
> 
> +
> 
> +**/
> 
> +UNIT_TEST_STATUS
> 
> +EFIAPI
> 
> +UnitTestMtrrGetDefaultMemoryType (
>= ; 
> +  IN UNIT_= TEST_CONTEXT  Context
> = ;
> +  )
> = ;
> +{
> 

> +  MTRR_LIB_TEST_CONTEXT     *LocalConte= xt;
> 
> + = ; UINTN           &n= bsp;         Index;
> 
> +  MTRR_MEMORY_CACHE= _TYPE    Result;
>=  
> +  MTRR_LIB_SYSTEM_PARAMETER SystemParameter;> 
> +  MTRR= _MEMORY_CACHE_TYPE    CacheType[5];
> 
> +
> 
> +  CacheType[0] =3D CacheUncacheable;=
> 
> +  C= acheType[1] =3D CacheWriteCombining;
> 
> +  CacheType[2] =3D CacheWriteThrough;
&= gt; 
> +  CacheT= ype[3] =3D CacheWriteProtected;
>=  
> +  CacheType[4] =3D CacheWriteBack;
> 
> +
> 
> +  LocalContext =3D (M= TRR_LIB_TEST_CONTEXT *) Context;
> 
> +
> <= /span>
> +  CopyMem (&SystemParameter, LocalContext->Syst= emParameter, sizeof (SystemParameter));
> 
> +  //
> 
> +  // If MTRRs are supported, then alwa= ys return the cache type in the MSR
> 
> +  // MSR_IA32_MTRR_DEF_TYPE
> 
> +  //
> 
> +  for (Index =3D 0= ; Index < ARRAY_SIZE (CacheType); Index++) {
> 
> +    SystemParameter.D= efaultCacheType =3D CacheType[Index];
> 
> +    InitializeMtrrRegs (&Sy= stemParameter);
> > +    Result =3D MtrrGetDefaultMemoryType ();
> 

> +   = UT_ASSERT_EQUAL (Result, SystemParameter.DefaultCacheType);
> 
> +  }
> 
> +
> 
> +  //
> 
> +  // If MTRRs are not sup= ported, then always return CacheUncacheable
> 
> +  //
> 
> +  SystemParameter.MtrrSupported = =3D FALSE;
> 
>= ; +  InitializeMtrrRegs (&SystemParameter);
> 
> +  Result =3D MtrrGetDefaul= tMemoryType ();
> > +  UT_ASSERT_EQUAL (Result, CacheUncacheable);
> 
> +
> 
> +  SystemParameter.MtrrSupport= ed =3D TRUE;
> 
&g= t; +  SystemParameter.FixedMtrrSupported =3D FALSE;
> 
> +  InitializeMtrrRegs = (&SystemParameter);
> 
> +  Result =3D MtrrGetDefaultMemoryType ();
> 
> +  UT_ASSERT_EQUAL= (Result, CacheUncacheable);
>&nb= sp;
> +
> 
> +  SystemParameter.MtrrSupported =3D TRUE;
> 
> +  SystemParameter.Fi= xedMtrrSupported =3D TRUE;
> = ;
> +  SystemParameter.VariableMtrrCount =3D 0;
> 

> +  InitializeM= trrRegs (&SystemParameter);
>=  
> +  Result =3D MtrrGetDefaultMemoryType ();
&g= t; 
> +  UT_ASSE= RT_EQUAL (Result, CacheUncacheable);
> 
> +
>&nb= sp;
> +  return UNIT_TEST_PASSED;
> 
> +}
> 
> +
> 
> +/**
>=  
> +  Unit test of MtrrLib service MtrrSetMemoryAtt= ributeInMtrrSettings().
> 
> +
> > +  @param[in]  Context    Ignored
> 

> +
> 
> +  @retval  UNIT_= TEST_PASSED          &nbs= p;  The Unit test has completed and the test
> 
> +     &nbs= p;            &= nbsp;           &nbs= p;         case was successful.
= > 
> +  @retv= al  UNIT_TEST_ERROR_TEST_FAILED  A test case assertion has failed= .
> 
> +
>= ; 
> +**/
> 

> +UNIT_TEST_STATUS
= > 
> +EFIAPI
&g= t; 
> +UnitTestMtrrSe= tMemoryAttributeInMtrrSettings (
> 
> +  IN UNIT_TEST_CONTEXT  Context
> 
> +  )
> 
> +{
> 
> +  CONST MTRR_LIB_SYS= TEM_PARAMETER *SystemParameter;
>=  
> +  RETURN_STATUS     &n= bsp;            = ; Status;
> 
> = +  UINT32          &= nbsp;           &nbs= p;   UcCount;
> 
> +  UINT32        = ;            &n= bsp;     WtCount;
> 
> +  UINT32     &nb= sp;            =         WbCount;
> 
> +  UINT32   &= nbsp;           &nbs= p;          WpCount;
> 

> +  UINT32 = ;            &n= bsp;            WcCo= unt;
> 
> +
= > 
> +  UINTN=             &nb= sp;            =   MtrrIndex;
> <= br>> +  UINTN         =             &nb= sp;     Index;
> 
> +  MTRR_SETTINGS     = ;            &n= bsp; LocalMtrrs;
> > +
> 
> +=   MTRR_MEMORY_RANGE        &nb= sp;      RawMtrrRange[MTRR_NUMBER_OF_VARIABLE_MTRR= ];
> 
> + = MTRR_MEMORY_RANGE         &nb= sp;     ExpectedMemoryRanges[MTRR_NUMBER_OF_FIXED_MTRR = * sizeof (UINT64) + 2 * MTRR_NUMBER_OF_VARIABLE_MTRR + 1];
> 
> +  UINT32  =             &nb= sp;           ExpectedVar= iableMtrrUsage;
> > +  UINTN         &n= bsp;            = ;     ExpectedMemoryRangesCount;
> 
> +
> 
> +  MTRR_MEMORY_RANGE  &nb= sp;            Actua= lMemoryRanges[MTRR_NUMBER_OF_FIXED_MTRR * sizeof (UINT64) + 2 * MTRR_NUMBER= _OF_VARIABLE_MTRR + 1];
> 
> +  UINT32        = ;            &n= bsp;     ActualVariableMtrrUsage;
> 
> +  UINTN   =             &nb= sp;           ActualMemor= yRangesCount;
> 
&= gt; +
> 
> +&nb= sp; MTRR_SETTINGS         &nbs= p;         *Mtrrs[2];
> 
> +
> 
> +  SystemParameter =3D (MT= RR_LIB_SYSTEM_PARAMETER *) Context;
> 
> +  GenerateRandomMemoryTypeCombination (
= > 
> +  =   SystemParameter->VariableMtrrCount - PatchPcdGet32 (PcdCpuNumberO= fReservedVariableMtrrs),
> <= /span>
> +    &UcCount, &WtCount, &WbCount= , &WpCount, &WcCount
>&nb= sp;
> +    );
> 
> +  GenerateValidAndConfigurableMtrrPai= rs (
> 
> +&nbs= p;   SystemParameter->PhysicalAddressBits, RawMtrrRange,
&g= t; 
> +  &n= bsp; UcCount, WtCount, WbCount, WpCount, WcCount
> 
> +    );
> 
> +
> 
> +  ExpectedVariableMtrrUsa= ge =3D UcCount + WtCount + WbCount + WpCount + WcCount;
> 
> +  ExpectedMemoryRange= sCount =3D ARRAY_SIZE (ExpectedMemoryRanges);
> 
> +  GetEffectiveMemoryRanges (
&= gt; 
> +  &= nbsp; SystemParameter->DefaultCacheType,
> 
> +    SystemParameter->P= hysicalAddressBits,
> 

> +    RawMtrrRange, ExpectedVariableMtrrUsage,
&= gt; 
> +  &= nbsp; ExpectedMemoryRanges, &ExpectedMemoryRangesCount
> 
> +    );
= > 
> +
> 
> +  UT_LOG_INFO (= "--- Expected Memory Ranges [%d] ---\n", ExpectedMemoryRangesCoun= t);
> 
> + = ; DumpMemoryRanges (ExpectedMemoryRanges, ExpectedMemoryRangesCount);
&g= t; 
> +  //
&= gt; 
> +  // Def= ault cache type is always an INPUT
> 
> +  //
> 
> +  ZeroMem (&LocalMtrrs, sizeof (LocalMt= rrs));
> 
> +&n= bsp; LocalMtrrs.MtrrDefType =3D MtrrGetDefaultMemoryType ();
> 
> +  Mtrrs[0] &n= bsp;            = ; =3D &LocalMtrrs;
> 
> +  Mtrrs[1]       &nbs= p;       =3D NULL;
> 
> +
> 
> +  for (MtrrIndex =3D 0; MtrrIndex <= ARRAY_SIZE (Mtrrs); MtrrIndex++) {
> 
> +    for (Index =3D 0; Index < = ExpectedMemoryRangesCount; Index++) {
> 
> +      Status =3D Mtrr= SetMemoryAttributeInMtrrSettings (
> 
> +        &= nbsp;        Mtrrs[MtrrIndex],
> 

> +   =             &nb= sp; ExpectedMemoryRanges[Index].BaseAddress,
> 
> +      &nb= sp;          ExpectedMemoryRan= ges[Index].Length,
> =
> +           = ;      ExpectedMemoryRanges[Index].Type
> 
> +   &= nbsp;           &nbs= p; );
> 
> +&nb= sp;     UT_ASSERT_TRUE (Status =3D=3D RETURN_SUCCESS ||= Status =3D=3D RETURN_OUT_OF_RESOURCES || Status =3D=3D RETURN_BUFFER_TOO_S= MALL);
> 
> +&n= bsp;     if (Status =3D=3D RETURN_OUT_OF_RESOURCES || S= tatus =3D=3D RETURN_BUFFER_TOO_SMALL) {
> 
> +        r= eturn UNIT_TEST_SKIPPED;
> <= /span>
> +      }
> 
> +    }
> 
> +
> 
> +    if (Mtrrs[Mt= rrIndex] =3D=3D NULL) {
> 
> +      ZeroMem (&LocalMtrrs, siz= eof (LocalMtrrs));
> =
> +      MtrrGetAllMtrrs (&LocalMtrrs);=
> 
> + &n= bsp;  }
> 
&g= t; +    ActualMemoryRangesCount =3D ARRAY_SIZE (ActualMemory= Ranges);
> 
> +=     CollectTestResult (
> 
> +      SystemParamete= r->DefaultCacheType, SystemParameter->PhysicalAddressBits, SystemPara= meter->VariableMtrrCount,
>&nb= sp;
> +      &LocalMtrrs, ActualM= emoryRanges, &ActualMemoryRangesCount, &ActualVariableMtrrUsage
= > 
> +  =     );
> 

> +    UT_LOG_INFO ("--- Actual Memory Ranges= [%d] ---\n", ActualMemoryRangesCount);
> 
> +    DumpMemoryRanges (Ac= tualMemoryRanges, ActualMemoryRangesCount);
> 
> +    VerifyMemoryRanges (E= xpectedMemoryRanges, ExpectedMemoryRangesCount, ActualMemoryRanges, ActualM= emoryRangesCount);
> =
> +    UT_ASSERT_TRUE (ExpectedVariableMtrrUsage >= = =3D ActualVariableMtrrUsage);
>&= nbsp;
> +
> 
> +    ZeroMem (&LocalMtrrs, sizeof (LocalMtr= rs));
> 
> +&nb= sp; }
> 
> +> 
> +  retu= rn UNIT_TEST_PASSED;
> 

> +}
> 
&= gt; +
> 
> +> 
> +/**
>=  
> +  Prep rout= ine for UnitTestGetFirmwareVariableMtrrCount().
> 
> +
> 
> +  @param Context  Point to a UINT3= 2 data to save the PcdCpuNumberOfReservedVariableMtrrs.
> 
> +**/
> 
> +UNIT_TEST_STATUS
> 
> +EFIAPI
> 
> +SavePcdValue (
> 
> +  UNIT_TEST_CO= NTEXT  Context
> 

> +  )
> 
> +{
> 
&g= t; +  MTRR_LIB_GET_FIRMWARE_VARIABLE_MTRR_COUNT_CONTEXT  *LocalCo= ntext;
> 
> +> 
> +  Loc= alContext =3D (MTRR_LIB_GET_FIRMWARE_VARIABLE_MTRR_COUNT_CONTEXT *) Context= ;
> 
> +  = LocalContext->NumberOfReservedVariableMtrrs =3D PatchPcdGet32 (PcdCpuNum= berOfReservedVariableMtrrs);
>&nb= sp;
> +  return UNIT_TEST_PASSED;
> 
> +}
> 
> +
> 
> +/**
>=  
> +  Clean up routine for UnitTestGetFirmwareVaria= bleMtrrCount().
> > +
> 
> +&= nbsp; @param Context  Point to a UINT32 data to save the PcdCpuNumberO= fReservedVariableMtrrs.
> 
> +**/
> =
> +VOID
> 
= > +EFIAPI
> 
&g= t; +RestorePcdValue (
> 
> +  UNIT_TEST_CONTEXT  Context
> 
> +  )
> 
> +{
> 
> +  MTRR_LIB_GET_FIRMWARE_VARIABLE_M= TRR_COUNT_CONTEXT  *LocalContext;
> 
> +
>&= nbsp;
> +  LocalContext =3D (MTRR_LIB_GET_FIRMWARE_VARIAB= LE_MTRR_COUNT_CONTEXT *) Context;
> 
> +  PatchPcdSet32 (PcdCpuNumberOfReservedVariab= leMtrrs, LocalContext->NumberOfReservedVariableMtrrs);
> 
> +}
> 
> +
> 
> +/**
> 
> +  Initialize the unit test framework, sui= te, and unit tests for the
> = ;
> +  ResetSystemLib and run the ResetSystemLib unit tes= t.
> 
> +
&g= t; 
> +  @param = Iteration           =     Iteration of testing MtrrSetMemoryAttributeInMtrrSetting= s
> 
> + &= nbsp;           &nbs= p;            &= nbsp;      and MtrrSetMemoryAttributesInMtrrSettin= gs using random inputs.
> 
> +
> > +  @retval  EFI_SUCCESS      =      All test cases were dispatched.
> 
> +  @retval  EFI_O= UT_OF_RESOURCES  There are not enough resources available to
> 

> +   =             &nb= sp;            =      initialize the unit tests.
> 
> +**/
> 
> +STATIC
> 
> +EFI_STATUS
> 
> +EFIAPI
> 
> +UnitTestingEntry (
> 
> +  UINTN  &n= bsp;            = ;        Iteration
> 
> +  )
> 
> +{
> 
> +  EFI_STATUS   &n= bsp;            = ;            &n= bsp;           Status;> 
> +  UNIT= _TEST_FRAMEWORK_HANDLE         = ;            &n= bsp;  Framework;
> 
> +  UNIT_TEST_SUITE_HANDLE     &nb= sp;            =           MtrrApiTests;
>= ; 
> +  UINTN&nb= sp;            =             &nb= sp;            =        Index;
> 
> +  UINTN    &nbs= p;            &= nbsp;           &nbs= p;            &= nbsp;  SystemIndex;
> <= /span>
> +  MTRR_LIB_TEST_CONTEXT     &= nbsp;           &nbs= p;           Context;
= > 
> +  MTRR_= LIB_GET_FIRMWARE_VARIABLE_MTRR_COUNT_CONTEXT GetFirmwareVariableMtrrCountCo= ntext;
> 
> +> 
> +  Con= text.SystemParameter         &= nbsp;           &nbs= p;       =3D &mDefaultSystemParameter;> 
> +  GetF= irmwareVariableMtrrCountContext.SystemParameter =3D &mDefaultSystemPara= meter;
> 
> +&n= bsp; Framework =3D NULL;
> <= /span>
> +
> > +  DEBUG ((DEBUG_INFO, "%a v%a\n", UNIT_TEST_APP_NAME= , UNIT_TEST_APP_VERSION));
> = ;
> +
> =
> +  //
> 
> +  // Setup the test framework for running the tests.
>= ; 
> +  //
&g= t; 
> +  Status = = =3D InitUnitTestFramework (&Framework, UNIT_TEST_APP_NAME, gEfiCallerB= aseName, UNIT_TEST_APP_VERSION);
> 
> +  if (EFI_ERROR (Status)) {
> 
> +    DEBUG (= (DEBUG_ERROR, "Failed in InitUnitTestFramework. Status =3D %r\n",= Status));
> 
>= +    goto EXIT;
>=  
> +  }
>=  
> +
> 
> +  //
> <= /span>
> +  // --------------Suite-----------Description--------= ------Name----------Function--------Pre---Post-------------------Context---= --------
> 
> +=   //
> 
> = +
> 
> +  = //
> 
> + = // Populate the MtrrLib API Unit Test Suite.
> 
> +  //
> 
> +  Status =3D CreateUnitTestSuite= (&MtrrApiTests, Framework, "MtrrLib API Tests", "MtrrLi= b.MtrrLib", NULL, NULL);
>&n= bsp;
> +  if (EFI_ERROR (Status)) {
> 
> +    DEBUG ((DEB= UG_ERROR, "Failed in CreateUnitTestSuite for MtrrLib API Tests\n"= ));
> 
> + = ;   Status =3D EFI_OUT_OF_RESOURCES;
> 
> +    goto EXIT;
>=  
> +  }
>=  
> +  AddTestCa= se (MtrrApiTests, "Test IsMtrrSupported",    =             &nb= sp;     "MtrrSupported",   &nb= sp;            =         UnitTestIsMtrrSupported, &n= bsp;            = ;        NULL, NULL, &Context);
&= gt; 
> +  AddTes= tCase (MtrrApiTests, "Test GetVariableMtrrCount",  &nbs= p;            &= nbsp; "GetVariableMtrrCount",      =            UnitTestGetVar= iableMtrrCount,          =        NULL, NULL, &Context);
> 

> +  AddTestCase (= MtrrApiTests, "Test GetFirmwareVariableMtrrCount",  &nb= sp;      "GetFirmwareVariableMtrrCount",=          UnitTestGetFirmwareVariabl= eMtrrCount,         SavePcdValue, R= estorePcdValue, &GetFirmwareVariableMtrrCountContext);
> 
> +  AddTestCase (MtrrA= piTests, "Test MtrrGetMemoryAttribute",    &n= bsp;          "MtrrGetMem= oryAttribute",         &n= bsp;     UnitTestMtrrGetMemoryAttribute,  &nb= sp;            NULL,= NULL, &Context);
> 
> +  AddTestCase (MtrrApiTests, "Test MtrrGetFixedMtrr&= quot;,           &nb= sp;         "MtrrGetFixedMtrr&= quot;,           &nb= sp;         UnitTestMtrrGetFixedMtr= r,            &= nbsp;        NULL, NULL, &Context);<= br>> 
> +  Ad= dTestCase (MtrrApiTests, "Test MtrrGetAllMtrrs",   = ;            &n= bsp;      "MtrrGetAllMtrrs",  =             &nb= sp;       UnitTestMtrrGetAllMtrrs,  = ;            &n= bsp;       NULL, NULL, &Context);
>=  
> +  AddTestCa= se (MtrrApiTests, "Test MtrrSetAllMtrrs",    =             &nb= sp;     "MtrrSetAllMtrrs",   &= nbsp;           &nbs= p;      UnitTestMtrrSetAllMtrrs,   =             &nb= sp;      NULL, NULL, &Context);
> 
> +  AddTestCase (Mtr= rApiTests, "Test MtrrGetMemoryAttributeInVariableMtrr", "Mtr= rGetMemoryAttributeInVariableMtrr", UnitTestMtrrGetMemoryAttributeInVa= riableMtrr, NULL, NULL, &Context);
> 
> +  AddTestCase (MtrrApiTests, "Test = MtrrDebugPrintAllMtrrs",       &nbs= p;       "MtrrDebugPrintAllMtrrs",&= nbsp;           &nbs= p;  UnitTestMtrrDebugPrintAllMtrrs,      = ;         NULL, NULL, &Context)= ;
> 
> +  = AddTestCase (MtrrApiTests, "Test MtrrGetDefaultMemoryType", =             "Mt= rrGetDefaultMemoryType",       &nbs= p;     UnitTestMtrrGetDefaultMemoryType,  &nb= sp;          NULL, NULL, &= Context);
> 
> = +
> 
> +  = for (SystemIndex =3D 0; SystemIndex < ARRAY_SIZE (mSystemParameters); Sy= stemIndex++) {
> 
= > +    for (Index =3D 0; Index < Iteration; Index++) {=
> 
> + &n= bsp;    AddTestCase (MtrrApiTests, "Test InvalidMemoryL= ayouts",          &n= bsp;       "InvalidMemoryLayouts",&= nbsp;           &nbs= p;     UnitTestInvalidMemoryLayouts,   &= nbsp;           &nbs= p;  InitializeSystem, NULL, &mSystemParameters[SystemIndex]);
&= gt; 
> +  &= nbsp;   AddTestCase (MtrrApiTests, "Test MtrrSetMemoryAttrib= uteInMtrrSettings",  "MtrrSetMemoryAttributeInMtrrSettings&q= uot;,  UnitTestMtrrSetMemoryAttributeInMtrrSettings,  InitializeS= ystem, NULL, &mSystemParameters[SystemIndex]);
> 
> +      Ad= dTestCase (MtrrApiTests, "Test MtrrSetMemoryAttributesInMtrrSettings&q= uot;, "MtrrSetMemoryAttributesInMtrrSettings", UnitTestMtrrSetMem= oryAttributesInMtrrSettings, InitializeSystem, NULL, &mSystemParameters= [SystemIndex]);
> > +    }
>&nbs= p;
> +  }
>&nbs= p;
> +  //
>&nb= sp;
> +  // Execute the tests.
> 
> +  //
> 
> +  srand ((unsigned int) time = (NULL));
> 
> +=   Status =3D RunAllTestSuites (Framework);
> 
> +
> 
> +EXIT:
> 
> +  if (Framework !=3D NULL) {
> 
> +    Fre= eUnitTestFramework (Framework);
>=  
> +  }
>=  
> +
> 
> +  return Status;
> 
> +}
>&n= bsp;
> +
> 
> +/**
> > +  Standard POSIX C entry point for host based unit test execut= ion.
> 
> +
= > 
> +  @para= m Argc  Number of arguments.
> 
> +  @param Argv  Array of arguments.
&g= t; 
> +
> 
> +  @return Test ap= plication exit code.
> 
> +**/
> > +INT32
> 
&g= t; +main (
> 
>= +  INT32 Argc,
> 
> +  CHAR8 *Argv[]
> 
> +  )
> 
> +{
> =
> +  UINTN    Iteration;
> 
> +
> 
> +  //
> 
> +  // First parameter specif= ies the test iterations.
> <= /span>
> +  // Default is 10.
> 
> +  //
> 
> +  Iteration =3D 10;
> 
> +  if (Argc =3D=3D 2) = {
> 
> + &= nbsp;  Iteration =3D atoi (Argv[1]);
> 
> +  }
> 
> +  return UnitTestingEntry (Iteration)= ;
> 
> +}
&g= t; 
> diff --git a/Ue= fiCpuPkg/Library/MtrrLib/UnitTest/MtrrLibUnitTest.h b/UefiCpuPkg/Library/Mt= rrLib/UnitTest/MtrrLibUnitTest.h
> new file mode 100644
> index= 0000000000..9750523133
> --- /dev/null
> +++ b/UefiCpuPkg/Libr= ary/MtrrLib/UnitTest/MtrrLibUnitTest.h
> @@ -0,0 +1,182 @@
> +/= ** @file
> 
> +=
> 
> +  C= opyright (c) 2020, Intel Corporation. All rights reserved.<BR>
>= ; 
> +  SPDX-Lic= ense-Identifier: BSD-2-Clause-Patent
> 
> +
>&nb= sp;
> +**/
> 
> +
> > +#ifndef _MTRR_SUPPORT_H_
>=  
> +#define _MTRR_SUPPORT_H_
> 
> +
> 
> +#include <stdio.h>
> 
> +#include <stdlib.h><= br>> 
> +#include = <string.h>
> > +#include <stdarg.h>
> 
> +#include <stddef.h>
> 
> +#include <setjmp.h>
>=  
> +#include <cmo= cka.h>
> 
> = +#include <time.h>
> <= /span>
> +
> > +#include <Uefi.h>
>=  
> +#include <Library/BaseLib.h>
> 
> +#include <Library/BaseM= emoryLib.h>
> 
= > +#include <Library/DebugLib.h>
> 
> +#include <Library/UnitTestLib.h>
= > 
> +#include <= ;Library/MtrrLib.h>
> 
> +#include <Library/UnitTestHostBaseLib.h>
> 
> +
> 
> +#include <Register/Architect= uralMsr.h>
> 
&= gt; +#include <Register/Cpuid.h>
> 
> +#include <Register/Msr.h>
> 
> +
> 
> +#define UNIT_TEST_APP_NAME&nbs= p;       "MtrrLib Unit Tests"
&g= t; 
> +#define UNIT_T= EST_APP_VERSION     "1.0"
> 
> +
> 
> +#define SCRATCH_BUFFER_SIZE &= nbsp;     SIZE_16KB
> 
> +
>=  
> +typedef struct {
> 
> +  UINT8     &n= bsp;            Phys= icalAddressBits;
> > +  BOOLEAN         = ;       MtrrSupported;
> 
> +  BOOLEAN   = ;             F= ixedMtrrSupported;
> =
> +  MTRR_MEMORY_CACHE_TYPE DefaultCacheType;
> 
> +  UINT32  &= nbsp;           &nbs= p;  VariableMtrrCount;
>&nbs= p;
> +} MTRR_LIB_SYSTEM_PARAMETER;
> 
> +
> 
> +extern UINT32     &= nbsp;           &nbs= p;         mFixedMtrrsIndex[];
&= gt; 
> +
> 

> +/**
> 
> +  Initialize the MTRR= registers.
> 
>= ; +
> 
> + = ; @param SystemParameter System parameter that controls the MTRR registers = initialization.
> > +**/
> 
>= +UNIT_TEST_STATUS
> =
> +EFIAPI
> > +InitializeMtrrRegs (
>&nb= sp;
> +  IN MTRR_LIB_SYSTEM_PARAMETER  *SystemParame= ter
> 
> + = ; );
> 
> +
= > 
> +/**
><= span class=3Dapple-converted-space> 

> +  Initialize= the MTRR registers.
> 
> +
> 
&g= t; +  @param Context System parameter that controls the MTRR registers= initialization.
> > +**/
> 
>= ; +UNIT_TEST_STATUS
> 
> +EFIAPI
> <= br>> +InitializeSystem (
>&nbs= p;
> +  IN UNIT_TEST_CONTEXT     = ;   Context
> 
> +  );
> 
> +
> 
= > +/**
> 
> = +  Return a random memory cache type.
> 
> +**/
> 
> +MTRR_MEMORY_CACHE_TYPE
> 
> +GenerateRandomCacheType (
>= ; 
> +  VOID
= > 
> +  );> 
> +
> 

> +/**
> 
> +  Generate random M= TRRs.
> 
> +> 
> +  @par= am PhysicalAddressBits  Physical address bits.
> 
> +  @param RawMemoryRanges&nb= sp;     Return the randomly generated MTRRs.
> 

> +  @param UcCou= nt            &= nbsp; Count of Uncacheable MTRRs.
> 
> +  @param WtCount     = ;         Count of Write Through MT= RRs.
> 
> +&nbs= p; @param WbCount         &nbs= p;    Count of Write Back MTRRs.
> 
> +  @param WpCount  &nb= sp;           Count of Wr= ite Protected MTRRs.
> 
> +  @param WcCount       =        Count of Write Combining MTRRs.
>= ; 
> +**/
> 

> +VOID
> 
> +GenerateValidAndConfigur= ableMtrrPairs (
> > +  IN     UINT32    &nbs= p;            &= nbsp;  PhysicalAddressBits,
> 
> +  IN OUT MTRR_MEMORY_RANGE   &n= bsp;     *RawMemoryRanges,
> 
> +  IN     UIN= T32            =         UcCount,
> 
> +  IN    = ; UINT32           &= nbsp;        WtCount,
> 
> +  IN   = ;  UINT32          &= nbsp;         WbCount,
> 

> +  IN  =    UINT32         &n= bsp;          WpCount,
>=  
> +  IN &= nbsp;   UINT32        &nb= sp;           WcCount
= > 
> +  );> 
> +
> 

> +/**
> 
> +  Convert the MTRR = BASE/MASK array to memory ranges.
> 
> +
> =
> +  @param DefaultType     &nb= sp;    Default memory type.
> 
> +  @param PhysicalAddressBits  P= hysical address bits.
> 
> +  @param RawMemoryRanges      Ra= w memory ranges.
> > +  @param RawMemoryRangeCount  Count of raw memory ranges.=
> 
> +  @= param MemoryRanges         Memory r= anges.
> 
> +&n= bsp; @param MemoryRangeCount     Count of memory ranges= .
> 
> +**/
= > 
> +VOID
>=  
> +GetEffectiveMemo= ryRanges (
> 
>= +  IN MTRR_MEMORY_CACHE_TYPE DefaultType,
> 
> +  IN UINT32   &n= bsp;            = ; PhysicalAddressBits,
> 
> +  IN MTRR_MEMORY_RANGE      *Ra= wMemoryRanges,
> 
= > +  IN UINT32         = ;        RawMemoryRangeCount,
> 

> +  OUT MTRR_MEM= ORY_RANGE     *MemoryRanges,
> 
> +  OUT UINTN   &= nbsp;           &nbs= p; *MemoryRangeCount
> 
> +  );
> 
> +
> 
&= gt; +/**
> 
> +=   Generate random MTRR BASE/MASK for a specified type.
> 
> +
> 
> +  @param PhysicalAddressBit= s Physical address bits.
> <= /span>
> +  @param CacheType      =      Cache type.
> 
> +  @param MtrrPair    &= nbsp;       Return the random MTRR.
> 

> +  @param Mtrr= MemoryRange     Return the random memory range.
>=  
> +**/
> 

> +VOID
> 
> +GenerateRandomMtrrPair (<= br>> 
> +  IN=   UINT32          &n= bsp;      PhysicalAddressBits,
> 
> +  IN  MTRR_MEMOR= Y_CACHE_TYPE CacheType,
> 
> +  OUT MTRR_VARIABLE_SETTING  *MtrrPair,  = ;     OPTIONAL
> 
> +  OUT MTRR_MEMORY_RANGE   &nb= sp;  *MtrrMemoryRange OPTIONAL
> 
> +  );
> 
> +
>&nb= sp;
> +/**
> 
> +  Collect the test result.
> 
> +
> 
> +  @param DefaultType   &n= bsp;      Default memory type.
> 
> +  @param PhysicalAddr= essBits  Physical address bits.
> 
> +  @param VariableMtrrCount  &nbs= p; Count of variable MTRRs.
>&nbs= p;
> +  @param Mtrrs      &= nbsp;         MTRR settings to coll= ect from.
> 
> = +  @param Ranges         =       Return the memory ranges.
> 
> +  @param RangeCount&n= bsp;          Return the count= of memory ranges.
> =
> +  @param MtrrCount       =      Return the count of variable MTRRs being used.
= > 
> +**/
><= span class=3Dapple-converted-space> 

> +VOID
> 

> +CollectTestResult (> 
> +  IN&= nbsp;    MTRR_MEMORY_CACHE_TYPE DefaultType,
> 
> +  IN  &nb= sp;  UINT32          = ;       PhysicalAddressBits,
> 
> +  IN  &nbs= p;  UINT32          =        VariableMtrrCount,
> 
> +  IN   = ;  MTRR_SETTINGS         = *Mtrrs,
> 
> +=   OUT    MTRR_MEMORY_RANGE     = ; *Ranges,
> 
>= +  IN OUT UINTN         =          *RangeCount,
> 
> +  OUT  =   UINT32          &n= bsp;      *MtrrCount
> 
> +  );
> 
> +
> 
> +/**
> 
> +  Return a 64bit random number.
> 
> +
> 
> +  @param Start  Star= t of the random number range.
>&n= bsp;
> +  @param Limit  Limit of the random number r= ange.
> 
> +&nb= sp; @return 64bit random number
>=  
> +**/
> = ;
> +UINT64
> <= /span>
> +Random64 (
> = ;
> +  UINT64  Start,
> 
> +  UINT64  Limit
> 
> +  );
> 

> +
> 
> +/**
> 
> +  Return a 32bit random nu= mber.
> 
> +> 
> +  @par= am Start  Start of the random number range.
> 
> +  @param Limit  Limit of = the random number range.
> <= /span>
> +  @return 32bit random number
> 
> +**/
> 
> +UINT32
> 
> +Random32 (
> 
> +  UINT32  Start,
> 

> +  UINT32  = Limit
> 
> +&nb= sp; );
> 
> +#e= ndif
> 
> diff = --git a/UefiCpuPkg/Library/MtrrLib/UnitTest/MtrrLibUnitTestHost.inf b/UefiC= puPkg/Library/MtrrLib/UnitTest/MtrrLibUnitTestHost.inf
> new file mod= e 100644
> index 0000000000..447238dc81
> --- /dev/null
>= +++ b/UefiCpuPkg/Library/MtrrLib/UnitTest/MtrrLibUnitTestHost.inf
> = @@ -0,0 +1,39 @@
> +## @file
> 
> +# Unit tests of the MtrrLib instance of the MtrrL= ib class
> 
> += #
> 
> +# Copyr= ight (c) 2020, Intel Corporation. All rights reserved.<BR>
> 

> +# SPDX-License-Iden= tifier: BSD-2-Clause-Patent
>&nbs= p;
> +##
> 
> +
> 
&= gt; +[Defines]
> 
= > +  INF_VERSION        &nb= sp;           =3D 0x00010= 006
> 
> + = ; BASE_NAME          &nbs= p;           =3D MtrrLibU= nitTestHost
> 
>= ; +  FILE_GUID         &n= bsp;            =3D = A1542D84-B64D-4847-885E-0509084376AB
> 
> +  MODULE_TYPE     = ;            &n= bsp;  =3D HOST_APPLICATION
>=  
> +  VERSION_STRING     &= nbsp;           =3D 1.0> 
> +
> 

> +#
> 
> +# The following informati= on is for reference only and not required by the build tools.
> 
> +#
> 
> +#  VALID_ARCHITECTURE= S           =3D IA32 X64<= br>> 
> +#
>=  
> +
> 
> +[Sources]
> 
> +  MtrrLibUnitTest.= c
> 
> +  = MtrrLibUnitTest.h
> <= br>> +  Support.c
> =
> +
> <= br>> +[Packages]
> 
> +  MdePkg/MdePkg.dec
> 
> +  UefiCpuPkg/UefiCpuPkg.dec
> 
> +  UnitTestFramework= Pkg/UnitTestFrameworkPkg.dec
>&nb= sp;
> +
> 
> +[LibraryClasses]
>&nb= sp;
> +  BaseLib
> 
> +  BaseMemoryLib
> 
> +  DebugLib
> 
> +  MtrrLib
> 
> +  UnitTestLib
&g= t; 
> +
> 
> +[Pcd]
> 
> +  gUefiCpuPkgTokenSp= aceGuid.PcdCpuNumberOfReservedVariableMtrrs   ## SOMETIMES_CONSUM= ES
> 
> diff --= git a/UefiCpuPkg/Library/MtrrLib/UnitTest/Support.c b/UefiCpuPkg/Library/Mt= rrLib/UnitTest/Support.c
> new file mode 100644
> index 0000000= 000..a7eed45940
> --- /dev/null
> +++ b/UefiCpuPkg/Library/Mtrr= Lib/UnitTest/Support.c
> @@ -0,0 +1,923 @@
> +/** @file
>=  
> +  Unit test= s of the MtrrLib instance of the MtrrLib class
> 
> +
> 
> +  Copyright (c) 2018 - 2020, Intel Corpo= ration. All rights reserved.<BR>
> 
> +  SPDX-License-Identifier: BSD-2-Clause-= Patent
> 
> +> 
> +**/
>= ; 
> +
> 
> +#include "MtrrLibU= nitTest.h"
> > +
> 
> +M= TRR_MEMORY_CACHE_TYPE mMemoryCacheTypes[] =3D {
> 
> +  CacheUncacheable, CacheWriteC= ombining, CacheWriteThrough, CacheWriteProtected, CacheWriteBack
> 

> +  };
> 

> +
> 
> +UINT64   &n= bsp;            = ;           mFixedMtrrsVa= lue[MTRR_NUMBER_OF_FIXED_MTRR];
>=  
> +MSR_IA32_MTRR_PHYSBASE_REGISTER  mVariableMtrrs= PhysBase[MTRR_NUMBER_OF_VARIABLE_MTRR];
> 
> +MSR_IA32_MTRR_PHYSMASK_REGISTER  mVaria= bleMtrrsPhysMask[MTRR_NUMBER_OF_VARIABLE_MTRR];
> 
> +MSR_IA32_MTRR_DEF_TYPE_REGISTER = ; mDefTypeMsr;
> 
= > +MSR_IA32_MTRRCAP_REGISTER        m= MtrrCapMsr;
> 
>= ; +CPUID_VERSION_INFO_EDX        &n= bsp;  mCpuidVersionInfoEdx;
> 
> +CPUID_VIR_PHY_ADDRESS_SIZE_EAX   mCpuidVi= rPhyAddressSizeEax;
> 
> +
> 
>= ; +/**
> 
> +&n= bsp; 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 NUL= L, 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 on= ly available on IA-32 and x64.
>&= nbsp;
> +
> 
> +  @param  Index The 32-bit value to load into EAX p= rior to invoking the CPUID
> = ;
> +         &nb= sp;      instruction.
> 
> +  @param  Eax   T= he pointer to the 32-bit EAX value returned by the CPUID
> 
> +    &n= bsp;           instructio= n. This is an optional parameter that may be NULL.
> 
> +  @param  Ebx &nbs= p; The pointer to the 32-bit EBX value returned by the CPUID
> 
> +    = ;            instruc= tion. This is an optional parameter that may be NULL.
> 
> +  @param  Ecx &= nbsp; The pointer to the 32-bit ECX value returned by the CPUID
> 

> +   &n= bsp;            inst= ruction. This is an optional parameter that may be NULL.
> 
> +  @param  Edx&nb= sp;  The pointer to the 32-bit EDX value returned by the CPUID
>=  
> +  &nbs= p;             = instruction. This is an optional parameter that may be NULL.
> 
> +
> 
> +  @return Index.
> 

> +
> 
> +**/
> 
> +UINT32
> 
> +EFIAPI
> 
> +UnitTestMtrrLibAsmCpuid (
> 

> +  IN &nb= sp;    UINT32        = ;            Index,<= br>> 
> +  OU= T     UINT32       &= nbsp;            *Ea= x,  OPTIONAL
> <= br>> +  OUT     UINT32    &= nbsp;           &nbs= p;   *Ebx,  OPTIONAL
> 
> +  OUT     UINT32 &= nbsp;           &nbs= p;      *Ecx,  OPTIONAL
> 
> +  OUT   &n= bsp; UINT32          &nbs= p;         *Edx   OPTIONA= L
> 
> +  = )
> 
> +{
&g= t; 
> +  switch = (Index) {
> 
> = +  case CPUID_VERSION_INFO:
> 
> +    if (Edx !=3D NULL) {
> 

> +   &n= bsp;  *Edx =3D mCpuidVersionInfoEdx.Uint32;
> 
> +    }
> 
> +    retu= rn Index;
> 
> = +    break;
> = ;
> +  case CPUID_EXTENDED_FUNCTION:
> 
> +    if (Eax= !=3D NULL) {
> 
&= gt; +      *Eax =3D CPUID_VIR_PHY_ADDRESS_SIZE;> 
> +  = ;  }
> 
> = +    return Index;
> 
> +    break;
> 
> +  case CPUID_VIR_PHY_ADDRESS= _SIZE:
> 
> +&n= bsp;   if (Eax !=3D NULL) {
> 
> +      *Eax =3D mCpuid= VirPhyAddressSizeEax.Uint32;
>&nb= sp;
> +    }
> 
> +    return Index;
> 

> +    = break;
> 
> +&n= bsp; }
> 
> +> 
> +  //<= br>> 
> +  //= Should never fall through to here
> 
> +  //
> 
> +  ASSERT(FALSE);
> 
> +  return Index;
> 
> +}
> 
> +
> 
> +/**
> 
> +  Returns a 64-bit Machine Specific Re= gister(MSR).
> 
&g= t; +
> 
> +&nbs= p; Reads and returns the 64-bit MSR specified by Index. No parameter checki= ng is
> 
> +&nb= sp; performed on Index, and some Index values may cause CPU exceptions. The=
> 
> +  c= aller must either guarantee that Index is valid, or the caller must set up<= br>> 
> +  ex= ception handlers to catch the exceptions. This function is only available> 
> +  on = IA-32 and x64.
> 
= > +
> 
> +&n= bsp; @param  MsrIndex The 32-bit MSR index to read.
> 
> +
> 
> +  @return The value of the MS= R identified by MsrIndex.
> =
> +
> <= br>> +**/
> 
&g= t; +UINT64
> 
>= +EFIAPI
> 
> += UnitTestMtrrLibAsmReadMsr64(
>&nb= sp;
> +  IN UINT32  MsrIndex
> 
> +  )
> 
> +{
> 
> +  UINT32 Index;
> 
> +
> 
> +  for (Index =3D 0; Index <= ; ARRAY_SIZE (mFixedMtrrsValue); Index++) {
> 
> +    if (MsrIndex =3D=3D m= FixedMtrrsIndex[Index]) {
> =
> +      return mFixedMtrrsValue[Ind= ex];
> 
> +&nbs= p;   }
> > +  }
> > +
> 
> +=   if ((MsrIndex >=3D MSR_IA32_MTRR_PHYSBASE0) &&
> 

> +   &= nbsp;  (MsrIndex <=3D MSR_IA32_MTRR_PHYSMASK0 + (MTRR_NUMBER_OF_VAR= IABLE_MTRR << 1))) {
> = ;
> +    if (MsrIndex % 2 =3D=3D 0) {
> 

> +   =    Index =3D (MsrIndex - MSR_IA32_MTRR_PHYSBASE0) >> 1;
= > 
> +  =     return mVariableMtrrsPhysBase[Index].Uint64;
> 

> +    }= else {
> 
> +&= nbsp;     Index =3D (MsrIndex - MSR_IA32_MTRR_PHYSMASK0= ) >> 1;
> 
&= gt; +      return mVariableMtrrsPhysMask[Index].Ui= nt64;
> 
> +&nb= sp;   }
> <= br>> +  }
> <= br>> +
> 
> = +  if (MsrIndex =3D=3D MSR_IA32_MTRR_DEF_TYPE) {
> 
> +    return mDef= TypeMsr.Uint64;
> > +  }
> > +
> 
> +&= nbsp; if (MsrIndex =3D=3D MSR_IA32_MTRRCAP) {
> 
> +    return mMtrrCapMsr.= Uint64;
> 
> +&= nbsp; }
> 
> +<= br>> 
> +  //=
> 
> +  /= / Should never fall through to here
> 
> +  //
> 
> +  ASSERT(FALSE);
> 
> +  return 0;
> 
> +}
> 
> +
> 
> +/**
> 
> +  Writes a 64-bit value to a Machine Spec= ific Register(MSR), and returns the
> 
> +  value.
> 
> +
> 
> +  Writes the 64-bit value specified by Value t= o 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
> <= /span>
> +  must establish proper exception handlers. This funct= ion is only available on
> <= /span>
> +  IA-32 and x64.
> 
> +
>&n= bsp;
> +  @param  MsrIndex The 32-bit MSR index to w= rite.
> 
> +&nb= sp; @param  Value The 64-bit value to write to the MSR.
> 
> +
> 
> +  @return Value
> 

> +
> 
> +**/
> 
> +UINT64
> 
> +EFIAPI
> 
> +UnitTestMtrrLibAsmWriteMsr64(
&g= t; 
> +  IN = ;     UINT32       &= nbsp;            Msr= Index,
> 
> +&n= bsp; IN      UINT64     &= nbsp;           &nbs= p;  Value
> 
= > +  )
> 
= > +{
> 
> +&= nbsp; UINT32 Index;
> 
> +
> 
>= ; +  for (Index =3D 0; Index < ARRAY_SIZE (mFixedMtrrsValue); Index= ++) {
> 
> +&nb= sp;   if (MsrIndex =3D=3D mFixedMtrrsIndex[Index]) {
> 

> +   &nb= sp;  mFixedMtrrsValue[Index] =3D Value;
> 
> +      return V= alue;
> 
> +&nb= sp;   }
> <= br>> +  }
> <= br>> +
> 
> = +  if ((MsrIndex >=3D MSR_IA32_MTRR_PHYSBASE0) &&
> 

> +   =    (MsrIndex <=3D MSR_IA32_MTRR_PHYSMASK0 + (MTRR_NUMBER_OF_VA= RIABLE_MTRR << 1))) {
>&nbs= p;
> +    if (MsrIndex % 2 =3D=3D 0) {
><= span class=3Dapple-converted-space> 

> +   = ;   Index =3D (MsrIndex - MSR_IA32_MTRR_PHYSBASE0) >> 1;> 
> +  = ;    mVariableMtrrsPhysBase[Index].Uint64 =3D Value;
>=  
> +  &nbs= p;   return Value;
>&nb= sp;
> +    } else {
> 
> +      Index= =3D (MsrIndex - MSR_IA32_MTRR_PHYSMASK0) >> 1;
> 
> +     = mVariableMtrrsPhysMask[Index].Uint64 =3D Value;
> 
> +      retu= rn Value;
> 
> = +    }
> 
> +  }
> 
> +
> 
&= gt; +  if (MsrIndex =3D=3D MSR_IA32_MTRR_DEF_TYPE) {
> 
> +    mDefTyp= eMsr.Uint64 =3D Value;
> 
> +    return Value;
> 
> +  }
> 
> +
> 
> +  if (MsrIndex =3D=3D MSR_IA32_MTRRCAP) = {
> 
> + &= nbsp;  mMtrrCapMsr.Uint64 =3D Value;
> 
> +    return Value;
> 

> +  }
> 

> +
> 
> +  //
> 
> +  // Should never fa= ll through to here
> =
> +  //
> 
> +  ASSERT(FALSE);
> 
> +  return 0;
> 
> +}
> 
> +
> =
> +/**
> 
> +  Initialize the MTRR registers.
> 
> +
> 
> +  @param SystemParameter System param= eter that controls the MTRR registers initialization.
> 
> +**/
> 
> +UNIT_TEST_STATUS
> 
> +EFIAPI
> 
> +InitializeMtrrRegs (
&g= t; 
> +  IN MTRR= _LIB_SYSTEM_PARAMETER  *SystemParameter
> 
> +  )
> 
> +{
> 
> +  UINT32     &nb= sp;            =   Index;
> 
&= gt; +
> 
> +&nb= sp; SetMem (mFixedMtrrsValue, sizeof (mFixedMtrrsValue), SystemParameter-&g= t;DefaultCacheType);
> 
> +
> 
&g= t; +  for (Index =3D 0; Index < ARRAY_SIZE (mVariableMtrrsPhysBase)= ; Index++) {
> 
&g= t; +    mVariableMtrrsPhysBase[Index].Uint64  &nbs= p;      =3D 0;
> 
> +    mVariableMtrrsPhysBase[In= dex].Bits.Type      =3D SystemParameter->Defaul= tCacheType;
> 
>= ; +    mVariableMtrrsPhysBase[Index].Bits.Reserved1 =3D 0;> 
> +
> 

> +   = mVariableMtrrsPhysMask[Index].Uint64      &n= bsp;  =3D 0;
> <= br>> +    mVariableMtrrsPhysMask[Index].Bits.V  = ;       =3D 0;
> 
> +    mVariableMtrrsPhysMa= sk[Index].Bits.Reserved1 =3D 0;
>=  
> +  }
>=  
> +
> 
> +  mDefTypeMsr.Bits.E      = ;   =3D 1;
> 
> +  mDefTypeMsr.Bits.FE      &= nbsp; =3D 1;
> 
&g= t; +  mDefTypeMsr.Bits.Type      =3D SystemPa= rameter->DefaultCacheType;
>&n= bsp;
> +  mDefTypeMsr.Bits.Reserved1 =3D 0;
> 
> +  mDefTypeMsr.Bit= s.Reserved2 =3D 0;
> =
> +  mDefTypeMsr.Bits.Reserved3 =3D 0;
> 
> +
> 
> +  mMtrrCapMsr.Bits.SMRR  &= nbsp;   =3D 0;
> <= /span>
> +  mMtrrCapMsr.Bits.WC     &nb= sp;  =3D 0;
> > +  mMtrrCapMsr.Bits.VCNT      =3D Syst= emParameter->VariableMtrrCount;
> 
> +  mMtrrCapMsr.Bits.FIX   &nbs= p;   =3D SystemParameter->FixedMtrrSupported;
> 
> +  mMtrrCapMsr.Bits.R= eserved1 =3D 0;
> > +  mMtrrCapMsr.Bits.Reserved2 =3D 0;
> 
> +  mMtrrCapMsr.Bits.Reserved3 = =3D 0;
> 
> +<= br>> 
> +  mC= puidVersionInfoEdx.Bits.MTRR        = ;            &n= bsp; =3D SystemParameter->MtrrSupported;
> 
> +  mCpuidVirPhyAddressSizeEax.Bits.P= hysicalAddressBits =3D SystemParameter->PhysicalAddressBits;
> 

> +
> 
> +  //
> 
> +  // Hook BaseLib fu= nctions used by MtrrLib that require some emulation.
> 
> +  //
> 
> +  gUnitTestHostBaseLib.X8= 6->AsmCpuid      =3D UnitTestMtrrLibAsmCpuid;> 
> +  gUn= itTestHostBaseLib.X86->AsmReadMsr64  =3D UnitTestMtrrLibAsmReadMsr6= 4;
> 
> + = gUnitTestHostBaseLib.X86->AsmWriteMsr64 =3D UnitTestMtrrLibAsmWriteMsr6= 4;
> 
> +
&g= t; 
> +  return = UNIT_TEST_PASSED;
> <= br>> +}
> 
>= +
> 
> +/**> 
> +  Init= ialize the MTRR registers.
> = ;
> +
> =
> +  @param Context System parameter that controls the MTRR reg= isters initialization.
> 
> +**/
> <= br>> +UNIT_TEST_STATUS
> =
> +EFIAPI
> 
> +InitializeSystem (
> 
> +  IN UNIT_TEST_CONTEXT    = ;    Context
>&nbs= p;
> +  )
>&nbs= p;
> +{
> 
> +  return InitializeMtrrRegs ((MTRR_LIB_SYSTEM_PARAMETER *)= Context);
> 
>= +}
> 
> +
&= gt; 
> +/**
> 

> +  Collect the= test result.
> 
&= gt; +
> 
> +&nb= sp; @param DefaultType         = ; Default memory type.
> 
> +  @param PhysicalAddressBits  Physical address bits= .
> 
> +  = @param VariableMtrrCount    Count of variable MTRRs.
>=  
> +  @param Mt= rrs            =     MTRR settings to collect from.
> 
> +  @param Ranges  &n= bsp;            Retu= rn the memory ranges.
> 
> +  @param RangeCount      &n= bsp;    Return the count of memory ranges.
> 
> +  @param MtrrCount&nb= sp;           Return the = count of variable MTRRs being used.
> 
> +**/
>&= nbsp;
> +VOID
> = ;
> +CollectTestResult (
> 
> +  IN     MTRR_MEMORY_= CACHE_TYPE DefaultType,
> 
> +  IN     UINT32   &n= bsp;            = ; PhysicalAddressBits,
> 
> +  IN     UINT32   &nb= sp;            = VariableMtrrCount,
> 
> +  IN     MTRR_SETTINGS   = ;       *Mtrrs,
> 
> +  OUT    MTRR_MEMO= RY_RANGE      *Ranges,
> 
> +  IN OUT UINTN   = ;            &n= bsp;  *RangeCount,
> 
> +  OUT    UINT32    &= nbsp;            *Mt= rrCount
> 
> +&= nbsp; )
> 
> +{=
> 
> +  U= INTN            = ; Index;
> 
> +=   UINT64          &n= bsp; MtrrValidBitsMask;
> 
> +  UINT64        = ;    MtrrValidAddressMask;
> 
> +  MTRR_MEMORY_RANGE RawMemoryRanges[A= RRAY_SIZE (Mtrrs->Variables.Mtrr)];
> 
> +
>&= nbsp;
> +  ASSERT (Mtrrs !=3D NULL);
> 
> +  ASSERT (VariableMtr= rCount <=3D ARRAY_SIZE (Mtrrs->Variables.Mtrr));
> 
> +
> 
> +  MtrrValidBitsMask =3D (1ull= << PhysicalAddressBits) - 1;
> 
> +  MtrrValidAddressMask =3D MtrrValidBitsMas= k & ~0xFFFull;
> =
> +
> 
>= +  *MtrrCount =3D 0;
> = ;
> +  for (Index =3D 0; Index < VariableMtrrCount; In= dex++) {
> 
> +=     if (((MSR_IA32_MTRR_PHYSMASK_REGISTER *) &Mtrrs->= Variables.Mtrr[Index].Mask)->Bits.V =3D=3D 1) {
> 
> +      Ra= wMemoryRanges[*MtrrCount].BaseAddress =3D Mtrrs->Variables.Mtrr[Index].B= ase & MtrrValidAddressMask;
>=  
> +      RawMemoryRanges[*Mtrr= Count].Type        =3D
> 
> +    &n= bsp;   ((MSR_IA32_MTRR_PHYSBASE_REGISTER *) &Mtrrs->Variab= les.Mtrr[Index].Base)->Bits.Type;
> 
> +      RawMemoryRanges[= *MtrrCount].Length      =3D
> 
> +     &= nbsp;    ((~(Mtrrs->Variables.Mtrr[Index].Mask & Mtrr= ValidAddressMask)) & MtrrValidBitsMask) + 1;
> 
> +      (*Mt= rrCount)++;
> 
>= ; +    }
> 
> +  }
> 
> +
> > +  GetEffectiveMemoryRanges (DefaultType, PhysicalAddressBits, R= awMemoryRanges, *MtrrCount, Ranges, RangeCount);
> 
> +}
> 
> +
> 
> +/**
>&nb= sp;
> +  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
>&nbs= p;
> +**/
> 
> +UINT32
> 
> +Random32 (
> 
> +  UINT32  Start,
> 
> +  UINT32  Limit
> 
> +  )
> 
> +{
> 
> +  return (UINT32) (((double)= rand () / RAND_MAX) * (Limit - Start)) + Start;
> 
> +}
> 
> +
> 
> +/**
>&nb= sp;
> +  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
>&nbs= p;
> +**/
> 
> +UINT64
> 
> +Random64 (
> 
> +  UINT64  Start,
> 
> +  UINT64  Limit
> 
> +  )
> 
> +{
> 
> +  return (UINT64) (((double)= rand () / RAND_MAX) * (Limit - Start)) + Start;
> 
> +}
> 
> +
> 
> +/**
>&nb= sp;
> +  Generate random MTRR BASE/MASK for a specified t= ype.
> 
> +
= > 
> +  @para= m PhysicalAddressBits Physical address bits.
> 
> +  @param CacheType  &nbs= p;        Cache type.
> 
> +  @param MtrrPair&nbs= p;           Return the r= andom MTRR.
> 
>= ; +  @param MtrrMemoryRange     Return the random = memory range.
> 
&= gt; +**/
> 
> += VOID
> 
> +Gene= rateRandomMtrrPair (
> 
> +  IN  UINT32       = ;          PhysicalAddressBits= ,
> 
> +  = IN  MTRR_MEMORY_CACHE_TYPE CacheType,
> 
> +  OUT MTRR_VARIABLE_SETTING  *M= trrPair,       OPTIONAL
> 
> +  OUT MTRR_MEMORY_RANGE&n= bsp;     *MtrrMemoryRange OPTIONAL
> 
> +  )
> 
> +{
> 
> +  MSR_IA32_MTRR_PHYSBASE_REG= ISTER PhysBase;
> > +  MSR_IA32_MTRR_PHYSMASK_REGISTER PhysMask;
> 
> +  UINT32  &= nbsp;           &nbs= p;           SizeShift;> 
> +  UIN= T32            =             &nb= sp; BaseShift;
> 
= > +  UINT64         &n= bsp;            = ;    RandomBoundary;
> 
> +  UINT64      = ;            &n= bsp;       MaxPhysicalAddress;
> 
> +  UINT64 &nbs= p;            &= nbsp;           RangeSize= ;
> 
> +  = UINT64           &nb= sp;            =   RangeBase;
> <= br>> +  UINT64         = ;            &n= bsp;    PhysBasePhyMaskValidBitsMask;
> 
> +
> 
> +  MaxPhysicalAddress =3D 1ull <= < PhysicalAddressBits;
> =
> +  do {
>&nb= sp;
> +    SizeShift =3D Random32 (12, Physical= AddressBits - 1);
> <= br>> +    RangeSize =3D 1ull << SizeShift;
><= span class=3Dapple-converted-space> 

> +
> 
> +    BaseSh= ift =3D Random32 (SizeShift, PhysicalAddressBits - 1);
> 
> +    RandomB= oundary =3D Random64 (0, 1ull << (PhysicalAddressBits - BaseShift));<= br>> 
> + &nb= sp;  RangeBase =3D RandomBoundary << BaseShift;
> 
> +  } while (RangeBase= < SIZE_1MB || RangeBase > MaxPhysicalAddress - 1);
> 
> +
> 
> +  PhysBasePhyMaskValidBitsMas= k =3D (MaxPhysicalAddress - 1) & 0xfffffffffffff000ULL;
> 
> +
> 
> +  PhysBase.Uint64 &nbs= p;  =3D 0;
> > +  PhysBase.Bits.Type =3D CacheType;
> 
> +  PhysBase.Uint64   |= = =3D RangeBase & PhysBasePhyMaskValidBitsMask;
> 
> +  PhysMask.Uint64  = ;  =3D 0;
> 
= > +  PhysMask.Bits.V    =3D 1;
> 
> +  PhysMask.Uint64 &n= bsp; |=3D ((~RangeSize) + 1) & PhysBasePhyMaskValidBitsMask;
> 

> +
> 
> +  if (MtrrPair !=3D N= ULL) {
> 
> +&n= bsp;   MtrrPair->Base =3D PhysBase.Uint64;
> 
> +    MtrrPai= r->Mask =3D PhysMask.Uint64;
>=  
> +  }
>=  
> +
> 
> +  if (MtrrMemoryRange !=3D NULL) {
> 
> +    MtrrMem= oryRange->BaseAddress =3D RangeBase;
> 
> +    MtrrMemoryRange->Lengt= h      =3D RangeSize;
> 
> +    MtrrMemoryRange-&g= t;Type        =3D CacheType;
> 

> +  }
> 

> +}
> 
> +
> 
> +
> 
> +/**
> 
> +  Check whether the Range overlaps with an= y 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 (<= br>> 
> +  IN= MTRR_MEMORY_RANGE *Range,
> = ;
> +  IN MTRR_MEMORY_RANGE *Ranges,
> 
> +  IN UINTN  = ;           Count
>=  
> +  )
>=  
> +{
> 
> +  while (Count-- != = =3D 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
> <= /span>
> +    //
> 
> +    if ((Range->BaseAddress = <=3D Ranges[Count].BaseAddress && Ranges[Count].BaseAddress <= Range->BaseAddress + Range->Length)
> 
> +     || (Ranges[Count= ].BaseAddress <=3D Range->BaseAddress && Range->BaseAddres= s < Ranges[Count].BaseAddress + Ranges[Count].Length)) {
> 
> +    =   return TRUE;
> 
> +    }
>=  
> +  }
>=  
> +  return FALSE;
> 
> +}
> 
> +
>&nb= sp;
> +/**
> 
> +  Generate random MTRRs.
> 
> +
> 
> +  @param PhysicalAddressBits  Physica= l address bits.
> > +  @param RawMemoryRanges      Return t= he randomly generated MTRRs.
>&nb= sp;
> +  @param UcCount     &nbs= p;        Count of Uncacheable MTRRs.> 
> +  @par= am WtCount           = ;   Count of Write Through MTRRs.
> 
> +  @param WbCount   &= nbsp;          Count of Write = Back MTRRs.
> 
>= ; +  @param WpCount        &nb= sp;     Count of Write Protected MTRRs.
> 
> +  @param WcCount&nb= sp;            = Count of Write Combine MTRRs.
>&= nbsp;
> +**/
> =
> +VOID
> 
> +GenerateValidAndConfigurableMtrrPairs (
> 
> +  IN   &nbs= p; UINT32           =          PhysicalAddressBits,
&g= t; 
> +  IN OUT = MTRR_MEMORY_RANGE         *RawMemor= yRanges,
> 
> +=   IN     UINT32      = ;            &n= bsp; UcCount,
> 
&= gt; +  IN     UINT32     =             &nb= sp;  WtCount,
> =
> +  IN     UINT32    &= nbsp;           &nbs= p;   WbCount,
> 
> +  IN     UINT32   &n= bsp;            = ;    WpCount,
>&nb= sp;
> +  IN     UINT32  &nb= sp;            =      WcCount
> 
> +  )
> 
> +{
> =
> +  UINT32       &nb= sp;            =       Index;
> 
> +
>&n= bsp;
> +  //
>&= nbsp;
> +  // 1. Generate UC, WT, WB in order.
> 

> +  //
> 

> +  for (Index = = =3D 0; Index < UcCount; Index++) {
> 
> +    GenerateRandomMtrrPair (Ph= ysicalAddressBits, CacheUncacheable, NULL, &RawMemoryRanges[Index]);> 
> +  }> 
> +
> 

> +  for (Index = =3D UcCount; Index < UcCount + WtCount; Index++) {
> 
> +    Generat= eRandomMtrrPair (PhysicalAddressBits, CacheWriteThrough, NULL, &RawMemo= ryRanges[Index]);
> <= br>> +  }
> <= br>> +
> 
> = +  for (Index =3D UcCount + WtCount; Index < UcCount + WtCount + Wb= Count; Index++) {
> <= br>> +    GenerateRandomMtrrPair (PhysicalAddressBits, Ca= cheWriteBack, NULL, &RawMemoryRanges[Index]);
> 
> +  }
> 
> +
> 
> +  //
> 
> +  // 2. Generate WP MTRR and DO NOT = overlap with WT, WB.
> 
> +  //
> 
> +  for (Index =3D UcCount + WtCount + WbCount; Index < = UcCount + WtCount + WbCount + WpCount; Index++) {
> 
> +    GenerateRandomM= trrPair (PhysicalAddressBits, CacheWriteProtected, NULL, &RawMemoryRang= es[Index]);
> 
>= ; +    while (RangesOverlap (&RawMemoryRanges[Index], &a= mp;RawMemoryRanges[UcCount], WtCount + WbCount)) {
> 
> +      Ge= nerateRandomMtrrPair (PhysicalAddressBits, CacheWriteProtected, NULL, &= RawMemoryRanges[Index]);
> <= /span>
> +    }
> 
> +  }
> 
> +
>&nb= sp;
> +  //
>&n= bsp;
> +  // 3. Generate WC MTRR and DO NOT overlap with = WT, WB, WP.
> 
>= ; +  //
> 
&g= t; +  for (Index =3D UcCount + WtCount + WbCount + WpCount; Index <= UcCount + WtCount + WbCount + WpCount + WcCount; Index++) {
> 
> +    Gene= rateRandomMtrrPair (PhysicalAddressBits, CacheWriteCombining, NULL, &Ra= wMemoryRanges[Index]);
> 
> +    while (RangesOverlap (&RawMemoryRanges= [Index], &RawMemoryRanges[UcCount], WtCount + WbCount + WpCount)) {
= > 
> +  =     GenerateRandomMtrrPair (PhysicalAddressBits, CacheWriteC= ombining, NULL, &RawMemoryRanges[Index]);
> 
> +    }
> 
> +  }
> 
> +}
> 
> +
> 
> +/**
> 
> +  Return a random memory cache type.
&= gt; 
> +**/
> 

> +MTRR_MEMORY_CACHE_= TYPE
> 
> +Gene= rateRandomCacheType (
> 
> +  VOID
> <= /span>
> +  )
> <= /span>
> +{
> <= br>> +    return mMemoryCacheTypes[Random32 (0, ARRAY_SIZ= E (mMemoryCacheTypes) - 1)];
>&nb= sp;
> +}
> 
> +
> 
&= gt; +/**
> 
> +=   Compare function used by qsort().
> 
> +**/
> 
> +
>&nbs= p;
> +/**
> 
> +  Compare function used by qsort().
> 
> +
> 
> +  @param Left   Lef= t operand to compare.
> 
> +  @param Right  Right operand to compare.
> 

> +
> 
> +  @retval 0  Lef= t =3D=3D Right
> 
= > +  @retval -1 Left < Right
> 
> +  @retval 1  Left > Right
&g= t; 
> +**/
> 

> +INT32
> 
> +CompareFuncUint64 (> 
> +  CONS= T VOID * Left,
> 
= > +  CONST VOID * Right
>=  
> +  )
>=  
> +{
> <= /span>
> +    INT64 Delta;
> 
> +    Delta =3D (*(UINT= 64*)Left - *(UINT64*)Right);
>&nb= sp;
> +    if (Delta > 0) {
> 
> +    &= nbsp; return 1;
> > +    } else if (Delta =3D=3D 0) {
> 
> +    &n= bsp; return 0;
> 
= > +    } else {
> 
> +      return -1;
><= span class=3Dapple-converted-space> 

> +   = ; }
> 
> +}
= > 
> +
> 

> +/**
> 
> +  Determin the memor= y cache type for the Range.
>&nbs= p;
> +
> 
> +  @param DefaultType Default cache type.
> 
> +  @param Range &= nbsp;     The memory range to determin the cache type.<= br>> 
> +  @p= aram Ranges      The entire memory ranges.
>=  
> +  @param Ra= ngeCount  Count of the entire memory ranges.
> 
> +**/
> 
> +VOID
> 
> +DetermineMemoryCacheType (
> 
> +  IN  &nbs= p;  MTRR_MEMORY_CACHE_TYPE DefaultType,
> 
> +  IN OUT MTRR_MEMORY_RANGE &n= bsp;    *Range,
>&= nbsp;
> +  IN     MTRR_MEMORY_RANGE&n= bsp;     *Ranges,
> 
> +  IN     UINT32 =             &nb= sp;   RangeCount
> = ;
> +  )
> = ;
> +{
> 
> +  UINT32 Index;
>=  
> +  Range->Type =3D CacheInvalid;
> 

> +  for (Index =3D= 0; Index < RangeCount; Index++) {
> 
> +    if (RangesOverlap (Range, &= amp;Ranges[Index], 1)) {
> <= /span>
> +      if (Ranges[Index].Type < = Range->Type) {
> <= br>> +        Range->Type =3D Rang= es[Index].Type;
> > +      }
> 
> +    }
> 
> +  }
> 
> +
> 
> +  if (Range->Type =3D=3D CacheIn= valid) {
> 
> +=     Range->Type =3D DefaultType;
> 
> +  }
> 
> +}
> 
> +
> 
> +/**
>&= nbsp;
> +  Get the index of the element that does NOT equ= als to Array[Index].
> 
> +
> 
&g= t; +  @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.
>&n= bsp;
> +**/
> <= /span>
> +UINT32
> 
> +GetNextDifferentElementInSortedArray (
> 
> +  IN UINT32 Index,
>=  
> +  IN UINT64= *Array,
> 
> +=   IN UINT32 Count
> 
> +  )
> 
> +{
> > +  UINT64 CurrentElement;
> 
> +  CurrentElement =3D Array[Index];
>=  
> +  while (Cu= rrentElement =3D=3D Array[Index] && Index < Count) {
> 

> +    I= ndex++;
> 
> +&= nbsp; }
> 
> +&= nbsp; return Index;
> 
> +}
> 
&g= t; +
> 
> +/**<= br>> 
> +  Re= move the duplicates from the array.
> 
> +
>&nbs= p;
> +  @param Array  The array to operate on.
&g= t; 
> +  @param = Count  Count of the array.
>=  
> +**/
> = ;
> +VOID
> 
> +RemoveDuplicatesInSortedArray (
> 
> +  IN OUT UINT64 *Array,
> 

> +  IN OUT UINT= 32 *Count
> 
> = +  )
> 
> = +{
> 
> + = UINT32 Index;
> 
= > +  UINT32 NewCount;
>&n= bsp;
> +
> 
> +  Index    =3D 0;
> 
> +  NewCount =3D 0;
> 

> +  while (Index= < *Count) {
> > +    Array[NewCount] =3D Array[Index];
> 
> +    NewCo= unt++;
> 
> +&n= bsp;   Index =3D GetNextDifferentElementInSortedArray (Index, Arr= ay, *Count);
> 
&g= t; +  }
> 
&g= t; +  *Count =3D NewCount;
>=  
> +}
> <= /span>
> +
> > +/**
> 
>= ; +  Return TRUE when Address is in the Range.
> 
> +
> 
> +  @param Address The address to che= ck.
> 
> + = ; @param Range   The range to check.
> 
> +  @return TRUE when Address is i= n the Range.
> 
&g= t; +**/
> 
> +B= OOLEAN
> 
> +Ad= dressInRange (
> 
= > +  IN UINT64         = ;   Address,
> 
> +  IN MTRR_MEMORY_RANGE Range
> 
> +  )
> 
> +{
> 
> +    return (Address >=3D = Range.BaseAddress) && (Address <=3D Range.BaseAddress + Range.Le= ngth - 1);
> 
>= +}
> 
> +
&= gt; 
> +/**
> 

> +  Get the ove= rlap bit flag.
> 
= > +
> 
> +&n= bsp; @param RawMemoryRanges     Raw memory ranges.
&= gt; 
> +  @param= RawMemoryRangeCount Count of raw memory ranges.
> 
> +  @param Address  &n= bsp;          The address to c= heck.
> 
> +**/=
> 
> +UINT64> 
> +GetOverlap= BitFlag (
> 
> = +  IN MTRR_MEMORY_RANGE *RawMemoryRanges,
> 
> +  IN UINT32   &nb= sp;        RawMemoryRangeCount,
><= span class=3Dapple-converted-space> 

> +  IN UINT64&= nbsp;           Address> 
> +  )> 
> +{
><= span class=3Dapple-converted-space> 

> +  UINT64 Ove= rlapBitFlag;
> 
&g= t; +  UINT32 Index;
> <= /span>
> +  OverlapBitFlag =3D 0;
> 
> +  for (Index =3D 0; Index < Raw= MemoryRangeCount; Index++) {
>&nb= sp;
> +    if (AddressInRange (Address, RawMemo= ryRanges[Index])) {
> 
> +      OverlapBitFlag |=3D (1ull <<= ; Index);
> 
> = +    }
> 
> +  }
> 
> +
> 
&= gt; +  return OverlapBitFlag;
> 
> +}
>&nbs= p;
> +
> 
> +/**
> 
= > +  Return the relationship between flags.
> 
> +
> 
> +  @param Flag1 Flag 1
> 
> +  @param Flag2 Fl= ag 2
> 
> +
= > 
> +  @retv= al 0   Flag1 =3D=3D Flag2
> 
> +  @retval 1   Flag1 is a subset o= f Flag2
> 
> +&= nbsp; @retval 2   Flag2 is a subset of Flag1
> 
> +  @retval 3 &nbs= p; No subset relations between Flag1 and Flag2.
> 
> +**/
> 
> +UINT32
> 
> +CheckOverlapBitFlagsRelation (
> 

> +  IN UINT64 Flag= 1,
> 
> + = IN UINT64 Flag2
> > +  )
> > +{
> 
> = +    if (Flag1 =3D=3D Flag2) return 0;
> 
> +    if ((Flag1 = | Flag2) =3D=3D Flag2) return 1;
> 
> +    if ((Flag1 | Flag2) =3D=3D Flag1= ) return 2;
> 
>= ; +    return 3;
>=  
> +}
> <= /span>
> +
> > +/**
> 
>= ; +  Return TRUE when the Endpoint is in any of the Ranges.
> 

> +
> 
> +  @param Endpoint&nbs= p;   The endpoint to check.
> 
> +  @param Ranges    &n= bsp; The memory ranges.
> 
> +  @param RangeCount  Count of memory ranges.
&g= t; 
> +
> 
> +  @retval TRUE&nb= sp; Endpoint is in one of the range.
> 
> +  @retval FALSE Endpoint is not in any of = the ranges.
> 
>= ; +**/
> 
> +BO= OLEAN
> 
> +IsE= ndpointInRanges (
> <= br>> +  IN UINT64        &n= bsp;   Endpoint,
> = ;
> +  IN MTRR_MEMORY_RANGE *Ranges,
> 
> +  IN UINTN  = ;           RangeCount> 
> +  )> 
> +{
> 

> +   = UINT32 Index;
> 
= > +    for (Index =3D 0; Index < RangeCount; Index++) = {
> 
> + &= nbsp;    if (AddressInRange (Endpoint, Ranges[Index])) {
= > 
> +  =       return TRUE;
> 
> +      }
>=  
> +  &nbs= p; }
> 
> +&nbs= p;   return FALSE;
>&nb= sp;
> +}
> 
> +
> 
&= gt; +
> 
> +/**=
> 
> +  C= ompact adjacent ranges of the same type.
> 
> +
> 
> +  @param DefaultType    &n= bsp;            = ;   Default memory type.
> 
> +  @param PhysicalAddressBits  &nbs= p;         Physical address bits.> 
> +  @pa= ram EffectiveMtrrMemoryRanges      Memory ranges t= o compact.
> 
>= +  @param EffectiveMtrrMemoryRangesCount Return the new count of memo= ry ranges.
> 
>= +**/
> 
> +VOI= D
> 
> +Compact= AndExtendEffectiveMtrrMemoryRanges (
> 
> +  IN     MTRR_MEMORY_C= ACHE_TYPE DefaultType,
> 
> +  IN     UINT32   &nb= sp;            = PhysicalAddressBits,
> 
> +  IN OUT MTRR_MEMORY_RANGE      = **EffectiveMtrrMemoryRanges,
>&nb= sp;
> +  IN OUT UINTN      =             *Effecti= veMtrrMemoryRangesCount
> 
> +  )
> 
> +{
> > +  UINT64         =             &nb= sp;  MaxAddress;
> 
> +  UINTN        &n= bsp;            = ;    NewRangesCountAtMost;
> 
> +  MTRR_MEMORY_RANGE   =           *NewRanges;
><= span class=3Dapple-converted-space> 

> +  UINTN = ;            &n= bsp;           NewRangesC= ountActual;
> 
>= ; +  MTRR_MEMORY_RANGE        =      *CurrentRangeInNewRanges;
> 
> +  MTRR_MEMORY_CACHE_TYPE&nbs= p;       CurrentRangeTypeInOldRanges;
>=  
> +
> 
> +  MTRR_MEMORY_RANGE=              *O= ldRanges;
> 
> = +  MTRR_MEMORY_RANGE        &n= bsp;    OldLastRange;
> 
> +  UINTN      = ;            &n= bsp;      OldRangesIndex;
> 
> +
> 
> +  NewRangesCountActual =3D 0;
>= ; 
> +  NewRange= sCountAtMost =3D *EffectiveMtrrMemoryRangesCount + 2;   // At mos= t with 2 more range entries.
>&nb= sp;
> +  NewRanges      &nb= sp;     =3D (MTRR_MEMORY_RANGE *) calloc (NewRangesCoun= tAtMost, sizeof (MTRR_MEMORY_RANGE));
> 
> +  OldRanges     =        =3D *EffectiveMtrrMemoryRanges;
>= ; 
> +  if (OldR= anges[0].BaseAddress > 0) {
>&= nbsp;
> +    NewRanges[NewRangesCountActual].Ba= seAddress =3D 0;
> > +    NewRanges[NewRangesCountActual].Length &nbs= p;    =3D OldRanges[0].BaseAddress;
> 
> +    NewRanges[NewR= angesCountActual].Type        =3D Defaul= tType;
> 
> +&n= bsp;   NewRangesCountActual++;
> 
> +  }
> 
> +
> 
> +  OldRangesIndex =3D 0;
> 
> +  while (OldRangesIndex &l= t; *EffectiveMtrrMemoryRangesCount) {
> 
> +    CurrentRangeTypeInOldRanges= =3D OldRanges[OldRangesIndex].Type;
> 
> +    CurrentRangeInNewRanges =3D = NULL;
> 
> +&nb= sp;   if (NewRangesCountActual > 0)   // We need to = check CurrentNewRange first before generate a new NewRange.
> 
> +    {
= > 
> +  =     CurrentRangeInNewRanges =3D &NewRanges[NewRangesCoun= tActual - 1];
> 
&= gt; +    }
> =
> +    if (CurrentRangeInNewRanges !=3D NULL &= amp;& CurrentRangeInNewRanges->Type =3D=3D CurrentRangeTypeInOldRang= es) {
> 
> +&nb= sp;     CurrentRangeInNewRanges->Length +=3D OldRang= es[OldRangesIndex].Length;
> = ;
> +    } else {
> 
> +      NewRang= es[NewRangesCountActual].BaseAddress =3D OldRanges[OldRangesIndex].BaseAddr= ess;
> 
> +&nbs= p;     NewRanges[NewRangesCountActual].Length &nbs= p;   +=3D OldRanges[OldRangesIndex].Length;
> 
> +     = NewRanges[NewRangesCountActual].Type      &n= bsp; =3D CurrentRangeTypeInOldRanges;
> 
> +      while (OldRange= sIndex + 1 < *EffectiveMtrrMemoryRangesCount && OldRanges[OldRan= gesIndex + 1].Type =3D=3D CurrentRangeTypeInOldRanges)
> 
> +    &n= bsp; {
> 
> +&n= bsp;       OldRangesIndex++;
> 
> +    &= nbsp;   NewRanges[NewRangesCountActual].Length +=3D OldRanges[Old= RangesIndex].Length;
> 
> +      }
> 
> +      NewRange= sCountActual++;
> > +    }
>&nbs= p;
> +
> 
> +    OldRangesIndex++;
> 
> +  }
> 
> +
> 
> +  MaxAddress =3D (1ull << Physica= lAddressBits) - 1;
> =
> +  OldLastRange =3D OldRanges[(*EffectiveMtrrMemoryRangesCoun= t) - 1];
> 
> +=   CurrentRangeInNewRanges =3D &NewRanges[NewRangesCountActual - 1]= ;
> 
> +  = if (OldLastRange.BaseAddress + OldLastRange.Length - 1 < MaxAddress) {> 
> + &nbs= p;  if (CurrentRangeInNewRanges->Type =3D=3D DefaultType) {
>=  
> +  &nbs= p;   CurrentRangeInNewRanges->Length =3D MaxAddress - CurrentR= angeInNewRanges->BaseAddress + 1;
> 
> +    } else {
> 
> +    &n= bsp; NewRanges[NewRangesCountActual].BaseAddress =3D OldLastRange.BaseAddre= ss + OldLastRange.Length;
> =
> +      NewRanges[NewRangesCountAct= ual].Length =3D MaxAddress - NewRanges[NewRangesCountActual].BaseAddress + = 1;
> 
> + =      NewRanges[NewRangesCountActual].Type =3D DefaultTy= pe;
> 
> + = ;     NewRangesCountActual++;
> 
> +    }
> 
> +  }
> 
> +
> 
> +  free (*EffectiveMtrrMem= oryRanges);
> 
>= ; +  *EffectiveMtrrMemoryRanges =3D NewRanges;
> 
> +  *EffectiveMtrrMemoryRange= sCount =3D NewRangesCountActual;
> 
> +}
> =
> +
> <= br>> +/**
> 
&g= t; +  Collect all the endpoints in the raw memory ranges.
> 

> +
> 
> +  @param Endpoints&nb= sp;          Return the collec= ted endpoints.
> 
= > +  @param EndPointCount       Retur= n the count of endpoints.
> =
> +  @param RawMemoryRanges     Raw = memory ranges.
> 
= > +  @param RawMemoryRangeCount Count of raw memory ranges.
>=  
> +**/
> 

> +VOID
> 
> +CollectEndpoints (
>= ; 
> +  IN OUT U= INT64        *Endpoints,
> 
> +  IN OUT UINT32&nbs= p;       *EndPointCount,
> 
> +  IN MTRR_MEMORY_RANG= E *RawMemoryRanges,
> 
> +  IN UINT32        =     RawMemoryRangeCount
> 
> +  )
> 
> +{
>=  
> +  UINT32 Index;
> 
> +  UINT32 RawRangeIndex;
> 

> +
> 
> +  ASSERT ((RawMemoryR= angeCount << 1) =3D=3D *EndPointCount);
> 
> +
> 
> +  for (Index =3D 0; Index < *EndPointC= ount; Index +=3D 2) {
> 
> +    RawRangeIndex =3D Index >> 1;
>=  
> +  &nbs= p; Endpoints[Index] =3D RawMemoryRanges[RawRangeIndex].BaseAddress;
>=  
> +  &nbs= p; Endpoints[Index + 1] =3D RawMemoryRanges[RawRangeIndex].BaseAddress + Ra= wMemoryRanges[RawRangeIndex].Length - 1;
> 
> +  }
> 
> +
> 
> +  qsort (Endpoints, *EndPointCount, sizeof (UI= NT64), CompareFuncUint64);
> = ;
> +  RemoveDuplicatesInSortedArray (Endpoints, EndPoint= Count);
> 
> +}=
> 
> +
>=  
> +/**
> 

> +  Convert the MT= RR BASE/MASK array to memory ranges.
> 
> +
>&nb= sp;
> +  @param DefaultType     =      Default memory type.
> 
> +  @param PhysicalAddressBits = ; Physical address bits.
> <= /span>
> +  @param RawMemoryRanges     = Raw memory ranges.
> 
> +  @param RawMemoryRangeCount  Count of raw memory rang= es.
> 
> + = ; @param MemoryRanges         Memor= y ranges.
> 
> = +  @param MemoryRangeCount     Count of memory ran= ges.
> 
> +**/<= br>> 
> +VOID
&= gt; 
> +GetEffectiveM= emoryRanges (
> 
&= gt; +  IN MTRR_MEMORY_CACHE_TYPE DefaultType,
> 
> +  IN UINT32   = ;            &n= bsp; PhysicalAddressBits,
> =
> +  IN MTRR_MEMORY_RANGE      = *RawMemoryRanges,
> <= br>> +  IN UINT32        &n= bsp;        RawMemoryRangeCount,
>=  
> +  OUT MTRR_= MEMORY_RANGE     *MemoryRanges,
> 
> +  OUT UINTN  &nbs= p;            &= nbsp; *MemoryRangeCount
> 
> +  )
> 
> +{
> > +  UINTN         &= nbsp;       Index;
> 
> +  UINT32   &nbs= p;            AllEnd= PointsCount;
> 
&g= t; +  UINT64         &nbs= p;      *AllEndPointsInclusive;
> 
> +  UINT32  &= nbsp;           &nbs= p; AllRangePiecesCountMax;
> = ;
> +  MTRR_MEMORY_RANGE     *AllRang= ePieces;
> 
> +=   UINTN          &nb= sp;      AllRangePiecesCountActual;
> 
> +  UINT64 &nbs= p;            &= nbsp; OverlapBitFlag1;
> 
> +  UINT64        =         OverlapBitFlag2;
> 
> +  INT32  =             &nb= sp;  OverlapFlagRelation;
>&= nbsp;
> +
> 
> +  if (RawMemoryRangeCount =3D=3D 0) {
> 
> +    MemoryR= anges[0].BaseAddress =3D 0;
>&nbs= p;
> +    MemoryRanges[0].Length  &nb= sp;   =3D (1ull << PhysicalAddressBits);
> 
> +    MemoryR= anges[0].Type        =3D DefaultType;> 
> +  = ;  *MemoryRangeCount =3D 1;
> 
> +    return;
> 
> +  }
> 
> +
> 
> +  AllEndPointsCount   = ;      =3D RawMemoryRangeCount << 1;
>=  
> +  AllEndPoi= ntsInclusive     =3D calloc (AllEndPointsCount, sizeof = (UINT64));
> 
>= +  AllRangePiecesCountMax    =3D RawMemoryRangeCount *= 3 + 1;
> 
> +&= nbsp; AllRangePieces         &= nbsp;  =3D calloc (AllRangePiecesCountMax, sizeof (MTRR_MEMORY_RANGE))= ;
> 
> +  = CollectEndpoints (AllEndPointsInclusive, &AllEndPointsCount, RawMemoryR= anges, RawMemoryRangeCount);
>&nb= sp;
> +
> 
> +  for (Index =3D 0, AllRangePiecesCountActual =3D 0; Index= < AllEndPointsCount - 1; Index++) {
> 
> +    OverlapBitFlag1 =3D GetOv= erlapBitFlag (RawMemoryRanges, RawMemoryRangeCount, AllEndPointsInclusive[I= ndex]);
> 
> +&= nbsp;   OverlapBitFlag2 =3D GetOverlapBitFlag (RawMemoryRanges, R= awMemoryRangeCount, AllEndPointsInclusive[Index + 1]);
> 
> +    Overlap= FlagRelation =3D CheckOverlapBitFlagsRelation (OverlapBitFlag1, OverlapBitF= lag2);
> 
> +&n= bsp;   switch (OverlapFlagRelation) {
> 
> +      case = 0:   // [1, 2]
> <= /span>
> +        AllRangePieces[A= llRangePiecesCountActual].BaseAddress =3D AllEndPointsInclusive[Index];
= > 
> +  =       AllRangePieces[AllRangePiecesCountActual].Le= ngth      =3D AllEndPointsInclusive[Index + 1] - A= llEndPointsInclusive[Index] + 1;
> 
> +        AllRange= PiecesCountActual++;
> 
> +        break;
> 
> +   &nbs= p;  case 1:   // [1, 2)
> 
> +        Al= lRangePieces[AllRangePiecesCountActual].BaseAddress =3D AllEndPointsInclusi= ve[Index];
> 
>= +        AllRangePieces[AllRangePiecesC= ountActual].Length      =3D (AllEndPointsInclusive= [Index + 1] - 1) - AllEndPointsInclusive[Index] + 1;
> 
> +     &= nbsp;  AllRangePiecesCountActual++;
> 
> +        = break;
> 
> +&n= bsp;     case 2:   // (1, 2]
> 
> +    &= nbsp;   AllRangePieces[AllRangePiecesCountActual].BaseAddress =3D= AllEndPointsInclusive[Index] + 1;
> 
> +        AllRan= gePieces[AllRangePiecesCountActual].Length      = =3D AllEndPointsInclusive[Index + 1] - (AllEndPointsInclusive[Index] + 1) = + 1;
> 
> +&nbs= p;       AllRangePiecesCountActual++;
>=  
> +
> 
> +    =     if (!IsEndpointInRanges (AllEndPointsInclusive[Index], A= llRangePieces, AllRangePiecesCountActual)) {
> 
> +      &nb= sp;   AllRangePieces[AllRangePiecesCountActual].BaseAddress =3D A= llEndPointsInclusive[Index];
>&nb= sp;
> +          = AllRangePieces[AllRangePiecesCountActual].Length    &nb= sp; =3D 1;
> 
>= +          AllRangePiecesCoun= tActual++;
> 
>= +        }
> 
> +      &= nbsp; break;
> 
&g= t; +      case 3:   // (1, 2)
> 

> +   &= nbsp;    AllRangePieces[AllRangePiecesCountActual].BaseAddre= ss =3D AllEndPointsInclusive[Index] + 1;
> 
> +        = AllRangePieces[AllRangePiecesCountActual].Length    &nb= sp; =3D (AllEndPointsInclusive[Index + 1] - 1) - (AllEndPointsInclusive[Ind= ex] + 1) + 1;
> 
&= gt; +        if (AllRangePieces[AllRange= PiecesCountActual].Length =3D=3D 0)   // Only in case 3 can exist= s Length=3D0, we should skip such "segment".
> 
> +    &n= bsp;     break;
> 
> +        AllRa= ngePiecesCountActual++;
> 
> +        if (!IsEndpointIn= Ranges (AllEndPointsInclusive[Index], AllRangePieces, AllRangePiecesCountAc= tual)) {
> 
> +=           AllRangePieces[AllRa= ngePiecesCountActual].BaseAddress =3D AllEndPointsInclusive[Index];
>=  
> +  &nbs= p;       AllRangePieces[AllRangePiecesCountAc= tual].Length      =3D 1;
> 
> +     &nbs= p;    AllRangePiecesCountActual++;
> 
> +     &nbs= p;  }
> 
>= +        break;
> 
> +      d= efault:
> 
> +&= nbsp;       ASSERT (FALSE);
> 
> +    }
&g= t; 
> +  }
&g= t; 
> +
> 
> +  for (Index =3D = 0; Index < AllRangePiecesCountActual; Index++) {
> 
> +    DetermineMemo= ryCacheType (DefaultType, &AllRangePieces[Index], RawMemoryRanges, RawM= emoryRangeCount);
> <= br>> +  }
> <= br>> +
> 
> = +  CompactAndExtendEffectiveMtrrMemoryRanges (DefaultType, PhysicalAdd= ressBits, &AllRangePieces, &AllRangePiecesCountActual);
> 

> +  ASSERT (*Memo= ryRangeCount >=3D AllRangePiecesCountActual);
> 
> +  memcpy (MemoryRanges, AllRan= gePieces, AllRangePiecesCountActual * sizeof (MTRR_MEMORY_RANGE));
><= span class=3Dapple-converted-space> 

> +  *MemoryRan= geCount =3D AllRangePiecesCountActual;
> 
> +
>&= nbsp;
> +  free (AllEndPointsInclusive);
> 
> +  free (AllRangePiec= es);
> 
> +}> 
> diff --git a= /UefiCpuPkg/Test/UefiCpuPkgHostTest.dsc b/UefiCpuPkg/Test/UefiCpuPkgHostTes= t.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-bas= ed unit tests.
> 
= > +#
> 
> +#= Copyright (c) 2020, Intel Corporation. All rights reserved.<BR>
&= gt; 
> +# SPDX-Licens= e-Identifier: BSD-2-Clause-Patent
> 
> +#
> = ;
> +##
> 
> +
> 
&g= t; +[Defines]
> 
&= gt; +  PLATFORM_NAME        &n= bsp;  =3D UefiCpuPkgHostTest
> 
> +  PLATFORM_GUID     =       =3D E00B9599-5B74-4FF7-AB9F-8183FB13B2F9
= > 
> +  PLATF= ORM_VERSION        =3D 0.1
> 
> +  DSC_SPECIFICATI= ON       =3D 0x00010005
> 
> +  OUTPUT_DIRECTORY &= nbsp;      =3D Build/UefiCpuPkg/HostTest
> 

> +  SUPPORTED_A= RCHITECTURES =3D IA32|X64
> =
> +  BUILD_TARGETS      &n= bsp;    =3D NOOPT
> 
> +  SKUID_IDENTIFIER    &nbs= p;   =3D DEFAULT
> = ;
> +
> =
> +!include UnitTestFrameworkPkg/UnitTestFrameworkPkgHost.dsc.inc> 
> +
> 

> +[LibraryClasses]> 
> +  Mtrr= Lib|UefiCpuPkg/Library/MtrrLib/MtrrLib.inf
> 
> +
> 
> +[PcdsPatchableInModule]
> 
> +  gUefiCpuPkgTokenSpaceGuid.P= cdCpuNumberOfReservedVariableMtrrs|0
> 
> +
>&nb= sp;
> +[Components]
> 
> +  #
> 
> +  # Build HOST_APPLICATION that tests the Mtrr= Lib
> 
> + = ; #
> 
> + = ; UefiCpuPkg/Library/MtrrLib/UnitTest/MtrrLibUnitTestHost.inf
> 
> diff --git a/UefiCpuPkg= /UefiCpuPkg.ci.yaml b/UefiCpuPkg/UefiCpuPkg.ci.yaml
> index 99e460a8b= 0..4559b40105 100644
> --- a/UefiCpuPkg/UefiCpuPkg.ci.yaml
> ++= + b/UefiCpuPkg/UefiCpuPkg.ci.yaml
> @@ -8,6 +8,10 @@
> &nb= sp;     "CompilerPlugin": {
> 
>    &nbs= p;      "DscPath": "UefiCpuPkg.dsc&= quot;
> 
> = ;      },
> 
> +    ## options defined ci/Plugin/H= ostUnitTestCompilerPlugin
> =
> +    "HostUnitTestCompilerPlugin":= {
> 
> + =        "DscPath": "Test/UefiCp= uPkgHostTest.dsc"
> 
> +    },
> 
>       "CharEnc= odingCheck": {
> 
>           "= ;IgnoreFiles": []
> 
>       },
> 
> @@ -18,7 +22,9 @@
> &n= bsp;            = ; "UefiCpuPkg/UefiCpuPkg.dec"
> 
>       &nbs= p;   ],
> <= br>>           # For h= ost based unit tests
> 
> -        "AcceptableDepe= ndencies-HOST_APPLICATION":[],
> 
> +        "= ;AcceptableDependencies-HOST_APPLICATION":[
> 
> +      = ;      "UnitTestFrameworkPkg/UnitTestFramewor= kPkg.dec"
> 
= > +        ],
> 
>     &nbs= p;     # For UEFI shell based apps
> 
>    &nbs= p;      "AcceptableDependencies-UEFI_APPLICAT= ION":[],
> 
&= gt;           "Ignor= eInf": []
> 
= > @@ -30,6 +36,10 @@
>       &n= bsp;       "UefiCpuPkg/ResetVector/Vtf0/= Vtf0.inf"
> 
= >           ]
><= span class=3Dapple-converted-space> 

>   &= nbsp;   },
> 
> +    "HostUnitTestDscCompleteCheck": {<= br>> 
> + &nb= sp;      "IgnoreInf": [""],> 
> +  = ;      "DscPath": "Test/UefiCpuPkgH= ostTest.dsc"
> <= br>> +    },
>&= nbsp;
>       "GuidCheck&qu= ot;: {
> 
>&nbs= p;          "IgnoreGuidNa= me": ["SecCore", "ResetVector"], # Expected duplic= ation for gEfiFirmwareVolumeTopFileGuid
> 
>       &nbs= p;   "IgnoreGuidValue": [],
> 




 

 

<= /p>

------=_NextPart_000_0676_01D664E0.42A09380--