From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from ma1-aaemail-dr-lapp02.apple.com (ma1-aaemail-dr-lapp02.apple.com [17.171.2.68]) by mx.groups.io with SMTP id smtpd.web11.19556.1595962746211724238 for ; Tue, 28 Jul 2020 11:59:08 -0700 Authentication-Results: mx.groups.io; dkim=pass header.i=@apple.com header.s=20180706 header.b=KbO/HSEU; spf=pass (domain: apple.com, ip: 17.171.2.68, mailfrom: afish@apple.com) Received: from pps.filterd (ma1-aaemail-dr-lapp02.apple.com [127.0.0.1]) by ma1-aaemail-dr-lapp02.apple.com (8.16.0.42/8.16.0.42) with SMTP id 06SIvfV2036275; Tue, 28 Jul 2020 11:59:04 -0700 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=apple.com; h=from : message-id : content-type : mime-version : subject : date : in-reply-to : cc : to : references; s=20180706; bh=vLO5qfX3mIq8WzYqiv7i8X9btTUi7eaJhlp8LJA5h9E=; b=KbO/HSEUK8JDo0akCRhl3EiPfzBw/7I5xFHEQl7d9t0sdCNYwzGKaASS4iW6rHdToSFi cRZ070Aqe7deoCF98h0bX66b1h2PBJ3HrWYLD+3NhTjP+2a4bW1zauZ+sm3m8d40HEp3 Cm8s6eUd/mSSgBgPjKzCMIG3wlsYpZLTOOmpsI/RoyiBTk7H4hQQq7aPqgOA/yb+sEZd UPPB3RNBk8o/UQD8JkRypVld/ZpsOIgs52M5CVaCWH10zKNBnkZF9i1elLml26UY1X9E piAlRIePGqB6OIfYnINO7189iFmN8sJPi2K2utNnmvbFbAH/NsoG+vWYei4LTDzxa4yR uA== Received: from rn-mailsvcp-mta-lapp04.rno.apple.com (rn-mailsvcp-mta-lapp04.rno.apple.com [10.225.203.152]) by ma1-aaemail-dr-lapp02.apple.com with ESMTP id 32ghdses6f-6 (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128 verify=NO); Tue, 28 Jul 2020 11:59:04 -0700 Received: from rn-mailsvcp-mmp-lapp01.rno.apple.com (rn-mailsvcp-mmp-lapp01.rno.apple.com [17.179.253.14]) by rn-mailsvcp-mta-lapp04.rno.apple.com (Oracle Communications Messaging Server 8.1.0.5.20200312 64bit (built Mar 12 2020)) with ESMTPS id <0QE700AIU0QFJIL0@rn-mailsvcp-mta-lapp04.rno.apple.com>; Tue, 28 Jul 2020 11:59:03 -0700 (PDT) Received: from process_milters-daemon.rn-mailsvcp-mmp-lapp01.rno.apple.com by rn-mailsvcp-mmp-lapp01.rno.apple.com (Oracle Communications Messaging Server 8.1.0.5.20200312 64bit (built Mar 12 2020)) id <0QE700Y000IPNY00@rn-mailsvcp-mmp-lapp01.rno.apple.com>; Tue, 28 Jul 2020 11:59:03 -0700 (PDT) X-Va-A: X-Va-T-CD: 678bf7de5df0d9ff994f556fd1b44182 X-Va-E-CD: f8701eb65c486e38e93d7dee001e3ed3 X-Va-R-CD: 00086717f1212c03f74c76706f07f981 X-Va-CD: 0 X-Va-ID: 75a73731-5040-4386-95fe-939553c9fc87 X-V-A: X-V-T-CD: 678bf7de5df0d9ff994f556fd1b44182 X-V-E-CD: f8701eb65c486e38e93d7dee001e3ed3 X-V-R-CD: 00086717f1212c03f74c76706f07f981 X-V-CD: 0 X-V-ID: 9b81ca3c-a78e-44fb-89d2-a36ab4659887 X-Proofpoint-Virus-Version: vendor=fsecure engine=2.50.10434:6.0.235,18.0.687 definitions=2020-07-28_15:2020-07-28,2020-07-28 signatures=0 Received: from [17.235.54.163] (unknown [17.235.54.163]) by rn-mailsvcp-mmp-lapp01.rno.apple.com (Oracle Communications Messaging Server 8.1.0.5.20200312 64bit (built Mar 12 2020)) with ESMTPSA id <0QE70025O0QCYR00@rn-mailsvcp-mmp-lapp01.rno.apple.com>; Tue, 28 Jul 2020 11:59:03 -0700 (PDT) From: "Andrew Fish" Message-id: MIME-version: 1.0 (Mac OS X Mail 13.4 \(3608.80.23.2.2\)) Subject: Re: [EXTERNAL] [edk2-devel] [PATCH v4] UefiCpuPkg/MtrrLib/UnitTest: Add host based unit test Date: Tue, 28 Jul 2020 11:59:00 -0700 In-reply-to: Cc: "tim.lewis@insyde.com" , "spbrogan@outlook.com" , "Ni, Ray" , Mike Kinney , Ming Shao , "Dong, Eric" , Laszlo Ersek , Sean Brogan , "Yao, Jiewen" To: devel@edk2.groups.io, bret.barkelew@microsoft.com References: <04ae01d66502$67338d20$359aa760$@insyde.com> X-Mailer: Apple Mail (2.3608.80.23.2.2) X-Proofpoint-Virus-Version: vendor=fsecure engine=2.50.10434:6.0.235,18.0.687 definitions=2020-07-28_15:2020-07-28,2020-07-28 signatures=0 Content-type: multipart/alternative; boundary="Apple-Mail=_11383A57-0AF5-436A-87D8-D0FDA9BCE6B2" --Apple-Mail=_11383A57-0AF5-436A-87D8-D0FDA9BCE6B2 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset=utf-8 > 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 exp= oses problem sets? > Bret, >>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. > > 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. > 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 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 Thanks, Andrew Fish > Thanks! > > - Bret > > From: tim.lewis@insyde.com > Sent: Tuesday, July 28, 2020 10:13 AM > To: devel@edk2.groups.io ; spbrogan@outlook= .com ; Ni, Ray > Cc: Kinney, Michael D ; 'Ming Shao' <= mailto:ming.shao@intel.com>; Dong, Eric ; 'Lasz= lo Ersek' ; Sean Brogan ; Bret Barkelew ; Yao, Jiewen = > Subject: [EXTERNAL] RE: [edk2-devel] [PATCH v4] UefiCpuPkg/MtrrLib/UnitT= est: Add host based unit test > > Sean -- >=20 > What I have 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 that value. Using a static seed might actually be the default for C= I runs, but stand-alone runs could use a random value.=20 >=20 > Just a thought. >=20 > Tim >=20 > -----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= > Cc: Michael D Kinney >; Ming Shao >= ; Eric Dong >; Laszlo Erse= k >; Sean Brogan >; Bret Barkelew >; Jiewen Yao > > Subject: Re: [edk2-devel] [PATCH v4] UefiCpuPkg/MtrrLib/UnitTest: Add ho= st based unit test >=20 > Ray, >=20 > 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. >=20 > 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. >=20 > 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. >=20 > 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. >=20 > Thoughts? >=20 > Thanks > Sean >=20 >=20 >=20 >=20 > 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/MtrrLibUnitTe= st.c > > create mode 100644 UefiCpuPkg/Library/MtrrLib/UnitTest/MtrrLibUnitTe= st.h > > create mode 100644 UefiCpuPkg/Library/MtrrLib/UnitTest/MtrrLibUnitTe= stHost.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/U= efiCpuPkg/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() te= st. > >=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= return 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, ActualR= anges[Index].BaseAddress); > >=20 > > + UT_ASSERT_EQUAL (ExpectedMemoryRanges[Index].Length, ActualRanges= [Index].Length); > >=20 > > + UT_ASSERT_EQUAL (ExpectedMemoryRanges[Index].Type, ActualRanges[I= ndex].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].B= aseAddress, 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 a= nd the test > >=20 > > + case was successful. > >=20 > > + @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has fai= led. > >=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_VARIABL= E_MTRR]; > >=20 > > + MTRR_MEMORY_RANGE ExpectedMemoryRanges[MTRR_NUMBER_OF= _FIXED_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_F= IXED_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 (PcdCpuNumberO= fReservedVariableMtrrs), > >=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, Wc= Count > >=20 > > + ); > >=20 > > + UT_LOG_INFO ("--- Expected Memory Ranges [%d] ---\n", ExpectedMemor= yRangesCount); > >=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[MtrrInd= ex], 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->PhysicalAdd= ressBits, SystemParameter->VariableMtrrCount, > >=20 > > + &LocalMtrrs, ActualMemoryRanges, &ActualMemoryRangesCount, &Act= ualVariableMtrrUsage > >=20 > > + ); > >=20 > > + > >=20 > > + UT_LOG_INFO ("--- Actual Memory Ranges [%d] ---\n", ActualMemoryR= angesCount); > >=20 > > + DumpMemoryRanges (ActualMemoryRanges, ActualMemoryRangesCount); > >=20 > > + VerifyMemoryRanges (ExpectedMemoryRanges, ExpectedMemoryRangesCou= nt, ActualMemoryRanges, ActualMemoryRangesCount); > >=20 > > + UT_ASSERT_TRUE (ExpectedVariableMtrrUsage >=3D ActualVariableMtrr= Usage); > >=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].= Type > >=20 > > + ); > >=20 > > + UT_ASSERT_TRUE (RETURN_ERROR (Status)); > >=20 > > + } > >=20 > > + > >=20 > > + ScratchSize =3D 0; > >=20 > > + Status =3D MtrrSetMemoryAttributesInMtrrSettings (NULL, NULL, &Scra= tchSize, 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 a= nd the test > >=20 > > + case was successful. > >=20 > > + @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has fai= led. > >=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 (S= ystemParameter)); > >=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 MT= RRs. > >=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 a= nd the test > >=20 > > + case was successful. > >=20 > > + @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has fai= led. > >=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 (S= ystemParameter)); > >=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.Varia= bleMtrrCount <=3D MTRR_NUMBER_OF_VARIABLE_MTRR; SystemParameter.VariableMtr= rCount++) { > >=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 a= n ASSERT() > >=20 > > + // is generated. > >=20 > > + // > >=20 > > + SystemParameter.MtrrSupported =3D TRUE; > >=20 > > + for (SystemParameter.VariableMtrrCount =3D 1; SystemParameter.Varia= bleMtrrCount <=3D MTRR_NUMBER_OF_VARIABLE_MTRR; SystemParameter.VariableMtr= rCount++) { > >=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_VARIA= BLE_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 a= nd the test > >=20 > > + case was successful. > >=20 > > + @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has fai= led. > >=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 (S= ystemParameter)); > >=20 > > + > >=20 > > + InitializeMtrrRegs (&SystemParameter); > >=20 > > + // > >=20 > > + // Positive test cases for VCNT =3D 10 and Reserved PCD in range 0.= .10 > >=20 > > + // > >=20 > > + for (ReservedMtrrs =3D 0; ReservedMtrrs <=3D SystemParameter.Variab= leMtrrCount; ReservedMtrrs++) { > >=20 > > + PatchPcdSet32 (PcdCpuNumberOfReservedVariableMtrrs, ReservedMtrrs= ); > >=20 > > + Result =3D GetFirmwareVariableMtrrCount (); > >=20 > > + UT_ASSERT_EQUAL (Result, SystemParameter.VariableMtrrCount - Rese= rvedMtrrs); > >=20 > > + } > >=20 > > + > >=20 > > + // > >=20 > > + // Negative test cases when Reserved PCD is larger than VCNT > >=20 > > + // > >=20 > > + for (ReservedMtrrs =3D SystemParameter.VariableMtrrCount + 1; Reser= vedMtrrs <=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_VARIA= BLE_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 a= nd the test > >=20 > > + case was successful. > >=20 > > + @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has fai= led. > >=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 a= nd the test > >=20 > > + case was successful. > >=20 > > + @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has fai= led. > >=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 (S= ystemParameter)); > >=20 > > + InitializeMtrrRegs (&SystemParameter); > >=20 > > + // > >=20 > > + // Set random cache type to different ranges under 1MB and make sur= e > >=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); Ms= rIndex++) { > >=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, size= of (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 a= nd the test > >=20 > > + case was successful. > >=20 > > + @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has fai= led. > >=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 (S= ystemParameter)); > >=20 > > + InitializeMtrrRegs (&SystemParameter); > >=20 > > + > >=20 > > + for (Index =3D 0; Index < SystemParameter.VariableMtrrCount; Index+= +) { > >=20 > > + GenerateRandomMtrrPair (SystemParameter.PhysicalAddressBits, Gene= rateRandomCacheType (), &VariableMtrr[Index], NULL); > >=20 > > + AsmWriteMsr64 (MSR_IA32_MTRR_PHYSBASE0 + (Index << 1), VariableMt= rr[Index].Base); > >=20 > > + AsmWriteMsr64 (MSR_IA32_MTRR_PHYSMASK0 + (Index << 1), VariableMt= rr[Index].Mask); > >=20 > > + } > >=20 > > + Result =3D MtrrGetAllMtrrs (&Mtrrs); > >=20 > > + UT_ASSERT_EQUAL (Result, &Mtrrs); > >=20 > > + UT_ASSERT_MEM_EQUAL (Mtrrs.Variables.Mtrr, VariableMtrr, sizeof (MT= RR_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_VARIA= BLE_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 a= nd the test > >=20 > > + case was successful. > >=20 > > + @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has fai= led. > >=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 (S= ystemParameter)); > >=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, Gene= rateRandomCacheType (), &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.MtrrD= efType); > >=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 a= nd the test > >=20 > > + case was successful. > >=20 > > + @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has fai= led. > >=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_VARI= ABLE_MTRR]; > >=20 > > + VARIABLE_MTRR VariableMtrr[MTRR_NUMBER_OF_VARIABL= E_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 (S= ystemParameter)); > >=20 > > + > >=20 > > + InitializeMtrrRegs (&SystemParameter); > >=20 > > + > >=20 > > + ValidMtrrBitsMask =3D (1ull << SystemParameter.PhysicalAddressBi= ts) - 1; > >=20 > > + ValidMtrrAddressMask =3D ValidMtrrBitsMask & 0xfffffffffffff000ULL; > >=20 > > + > >=20 > > + for (Index =3D 0; Index < SystemParameter.VariableMtrrCount; Index+= +) { > >=20 > > + GenerateRandomMtrrPair (SystemParameter.PhysicalAddressBits, Gene= rateRandomCacheType (), &VariableSetting[Index], NULL); > >=20 > > + AsmWriteMsr64 (MSR_IA32_MTRR_PHYSBASE0 + (Index << 1), VariableSe= tting[Index].Base); > >=20 > > + AsmWriteMsr64 (MSR_IA32_MTRR_PHYSMASK0 + (Index << 1), VariableSe= tting[Index].Mask); > >=20 > > + } > >=20 > > + Result =3D MtrrGetMemoryAttributeInVariableMtrr (ValidMtrrBitsMask,= ValidMtrrAddressMask, 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) & ValidMtrrB= itsMask; > >=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,= ValidMtrrAddressMask, VariableMtrr); > >=20 > > + UT_ASSERT_EQUAL (Result, 0); > >=20 > > + > >=20 > > + // > >=20 > > + // Expect ASSERT() if variable MTRR count is > MTRR_NUMBER_OF_VARIA= BLE_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 (Val= idMtrrBitsMask, 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 a= nd the test > >=20 > > + case was successful. > >=20 > > + @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has fai= led. > >=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 a= nd the test > >=20 > > + case was successful. > >=20 > > + @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has fai= led. > >=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 (S= ystemParameter)); > >=20 > > + // > >=20 > > + // If MTRRs are supported, then always return the cache type in the= MSR > >=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 a= nd the test > >=20 > > + case was successful. > >=20 > > + @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has fai= led. > >=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_VARIABL= E_MTRR]; > >=20 > > + MTRR_MEMORY_RANGE ExpectedMemoryRanges[MTRR_NUMBER_OF= _FIXED_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_F= IXED_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 (PcdCpuNumberO= fReservedVariableMtrrs), > >=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", ExpectedMemor= yRangesCount); > >=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 R= ETURN_OUT_OF_RESOURCES || Status =3D=3D RETURN_BUFFER_TOO_SMALL); > >=20 > > + if (Status =3D=3D RETURN_OUT_OF_RESOURCES || Status =3D=3D RETU= RN_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->PhysicalAdd= ressBits, SystemParameter->VariableMtrrCount, > >=20 > > + &LocalMtrrs, ActualMemoryRanges, &ActualMemoryRangesCount, &Act= ualVariableMtrrUsage > >=20 > > + ); > >=20 > > + UT_LOG_INFO ("--- Actual Memory Ranges [%d] ---\n", ActualMemoryR= angesCount); > >=20 > > + DumpMemoryRanges (ActualMemoryRanges, ActualMemoryRangesCount); > >=20 > > + VerifyMemoryRanges (ExpectedMemoryRanges, ExpectedMemoryRangesCou= nt, ActualMemoryRanges, ActualMemoryRangesCount); > >=20 > > + UT_ASSERT_TRUE (ExpectedVariableMtrrUsage >=3D ActualVariableMtrr= Usage); > >=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 PcdCpuNumberOfRe= servedVariableMtrrs. > >=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 (PcdC= puNumberOfReservedVariableMtrrs); > >=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 PcdCpuNumberOfRe= servedVariableMtrrs. > >=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->N= umberOfReservedVariableMtrrs); > >=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 MtrrSetMemoryAt= tributeInMtrrSettings > >=20 > > + and MtrrSetMemoryAttributesInMtrrSet= tings using random inputs. > >=20 > > + > >=20 > > + @retval EFI_SUCCESS All test cases were dispatched. > >=20 > > + @retval EFI_OUT_OF_RESOURCES There are not enough resources avail= able 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 GetFirmwareVariab= leMtrrCountContext; > >=20 > > + > >=20 > > + Context.SystemParameter =3D &mDefaultSy= stemParameter; > >=20 > > + GetFirmwareVariableMtrrCountContext.SystemParameter =3D &mDefaultSy= stemParameter; > >=20 > > + Framework =3D NULL; > >=20 > > + > >=20 > > + DEBUG ((DEBUG_INFO, "%a v%a\n", UNIT_TEST_APP_NAME, UNIT_TEST_APP_V= ERSION)); > >=20 > > + > >=20 > > + // > >=20 > > + // Setup the test framework for running the tests. > >=20 > > + // > >=20 > > + Status =3D InitUnitTestFramework (&Framework, UNIT_TEST_APP_NAME, g= EfiCallerBaseName, 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 = API Tests", "MtrrLib.MtrrLib", NULL, NULL); > >=20 > > + if (EFI_ERROR (Status)) { > >=20 > > + DEBUG ((DEBUG_ERROR, "Failed in CreateUnitTestSuite for MtrrLib A= PI 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", UnitTestGetFirmwareVariableMtr= rCount, SavePcdValue, RestorePcdValue, &GetFirmwareVariableMtrrCoun= tContext); > >=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 MtrrGetMemoryAttributeInVariableMt= rr", "MtrrGetMemoryAttributeInVariableMtrr", UnitTestMtrrGetMemoryAttribute= InVariableMtrr, NULL, NULL, &Context); > >=20 > > + AddTestCase (MtrrApiTests, "Test MtrrDebugPrintAllMtrrs", = "MtrrDebugPrintAllMtrrs", UnitTestMtrrDebugPrintAllMtrrs= , NULL, NULL, &Context); > >=20 > > + AddTestCase (MtrrApiTests, "Test MtrrGetDefaultMemoryType", = "MtrrGetDefaultMemoryType", UnitTestMtrrGetDefaultMemoryTy= pe, 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", UnitTestInvalidMemoryLay= outs, InitializeSystem, NULL, &mSystemParameters[SystemInd= ex]); > >=20 > > + AddTestCase (MtrrApiTests, "Test MtrrSetMemoryAttributeInMtrrSe= ttings", "MtrrSetMemoryAttributeInMtrrSettings", UnitTestMtrrSetMemoryAtt= ributeInMtrrSettings, InitializeSystem, NULL, &mSystemParameters[SystemInd= ex]); > >=20 > > + AddTestCase (MtrrApiTests, "Test MtrrSetMemoryAttributesInMtrrS= ettings", "MtrrSetMemoryAttributesInMtrrSettings", UnitTestMtrrSetMemoryAtt= ributesInMtrrSettings, InitializeSystem, NULL, &mSystemParameters[SystemInd= ex]); > >=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/U= efiCpuPkg/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 regi= sters 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 in= itialization. > >=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 bein= g 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.i= nf 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-05090843= 76AB > >=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= the 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 ## = SOMETIMES_CONSUMES > >=20 > > diff --git a/UefiCpuPkg/Library/MtrrLib/UnitTest/Support.c b/UefiCpuPk= g/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.<= BR> > >=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, CacheWrit= eProtected, CacheWriteBack > >=20 > > + }; > >=20 > > + > >=20 > > +UINT64 mFixedMtrrsValue[MTRR_NUMBER_OF_FIXE= D_MTRR]; > >=20 > > +MSR_IA32_MTRR_PHYSBASE_REGISTER mVariableMtrrsPhysBase[MTRR_NUMBER_O= F_VARIABLE_MTRR]; > >=20 > > +MSR_IA32_MTRR_PHYSMASK_REGISTER mVariableMtrrsPhysMask[MTRR_NUMBER_O= F_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 i= n Eax. > >=20 > > + If Ebx is not NULL, then the value of EBX after CPUID is returned i= n Ebx. > >=20 > > + If Ecx is not NULL, then the value of ECX after CPUID is returned i= n Ecx. > >=20 > > + If Edx is not NULL, then the value of EDX after CPUID is returned i= n 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 t= he CPUID > >=20 > > + instruction. > >=20 > > + @param Eax The pointer to the 32-bit EAX value returned by the C= PUID > >=20 > > + instruction. This is an optional parameter that may b= e NULL. > >=20 > > + @param Ebx The pointer to the 32-bit EBX value returned by the C= PUID > >=20 > > + instruction. This is an optional parameter that may b= e NULL. > >=20 > > + @param Ecx The pointer to the 32-bit ECX value returned by the C= PUID > >=20 > > + instruction. This is an optional parameter that may b= e NULL. > >=20 > > + @param Edx The pointer to the 32-bit EDX value returned by the C= PUID > >=20 > > + instruction. This is an optional parameter that may b= e 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 c= hecking is > >=20 > > + performed on Index, and some Index values may cause CPU exceptions.= The > >=20 > > + caller must either guarantee that Index is valid, or the caller mus= t set up > >=20 > > + exception handlers to catch the exceptions. This function is only a= vailable > >=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_VARIAB= LE_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 retu= rns the > >=20 > > + value. > >=20 > > + > >=20 > > + Writes the 64-bit value specified by Value to the MSR specified by = Index. 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 except= ions. The > >=20 > > + caller must either guarantee that Index and Value are valid, or the= caller > >=20 > > + must establish proper exception handlers. This function is only ava= ilable 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_VARIAB= LE_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 regi= sters 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), SystemParamete= r->DefaultCacheType); > >=20 > > + > >=20 > > + for (Index =3D 0; Index < ARRAY_SIZE (mVariableMtrrsPhysBase); Inde= x++) { > >=20 > > + mVariableMtrrsPhysBase[Index].Uint64 =3D 0; > >=20 > > + mVariableMtrrsPhysBase[Index].Bits.Type =3D SystemParameter-= >DefaultCacheType; > >=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 SystemParam= eter->MtrrSupported; > >=20 > > + mCpuidVirPhyAddressSizeEax.Bits.PhysicalAddressBits =3D SystemParam= eter->PhysicalAddressBits; > >=20 > > + > >=20 > > + // > >=20 > > + // Hook BaseLib functions used by MtrrLib that require some emulati= on. > >=20 > > + // > >=20 > > + gUnitTestHostBaseLib.X86->AsmCpuid =3D UnitTestMtrrLibAsmCpuid= ; > >=20 > > + gUnitTestHostBaseLib.X86->AsmReadMsr64 =3D UnitTestMtrrLibAsmReadM= sr64; > >=20 > > + gUnitTestHostBaseLib.X86->AsmWriteMsr64 =3D UnitTestMtrrLibAsmWrite= Msr64; > >=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 in= itialization. > >=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 bein= g 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[I= ndex].Mask)->Bits.V =3D=3D 1) { > >=20 > > + RawMemoryRanges[*MtrrCount].BaseAddress =3D Mtrrs->Variables.Mt= rr[Index].Base & MtrrValidAddressMask; > >=20 > > + RawMemoryRanges[*MtrrCount].Type =3D > >=20 > > + ((MSR_IA32_MTRR_PHYSBASE_REGISTER *) &Mtrrs->Variables.Mtrr[I= ndex].Base)->Bits.Type; > >=20 > > + RawMemoryRanges[*MtrrCount].Length =3D > >=20 > > + ((~(Mtrrs->Variables.Mtrr[Index].Mask & MtrrValidAddressMas= k)) & MtrrValidBitsMask) + 1; > >=20 > > + (*MtrrCount)++; > >=20 > > + } > >=20 > > + } > >=20 > > + > >=20 > > + GetEffectiveMemoryRanges (DefaultType, PhysicalAddressBits, RawMemo= ryRanges, *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)) += Start; > >=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)) += Start; > >=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 - Ba= seShift)); > >=20 > > + RangeBase =3D RandomBoundary << BaseShift; > >=20 > > + } while (RangeBase < SIZE_1MB || RangeBase > MaxPhysicalAddress - 1= ); > >=20 > > + > >=20 > > + PhysBasePhyMaskValidBitsMask =3D (MaxPhysicalAddress - 1) & 0xfffff= ffffffff000ULL; > >=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) & PhysBasePhyMaskValidBit= sMask; > >=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[= Count].BaseAddress < Range->BaseAddress + Range->Length) > >=20 > > + || (Ranges[Count].BaseAddress <=3D Range->BaseAddress && Range->= BaseAddress < 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, NU= LL, &RawMemoryRanges[Index]); > >=20 > > + } > >=20 > > + > >=20 > > + for (Index =3D UcCount; Index < UcCount + WtCount; Index++) { > >=20 > > + GenerateRandomMtrrPair (PhysicalAddressBits, CacheWriteThrough, N= ULL, &RawMemoryRanges[Index]); > >=20 > > + } > >=20 > > + > >=20 > > + for (Index =3D UcCount + WtCount; Index < UcCount + WtCount + WbCou= nt; 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 + WtCou= nt + WbCount + WpCount; Index++) { > >=20 > > + GenerateRandomMtrrPair (PhysicalAddressBits, CacheWriteProtected,= NULL, &RawMemoryRanges[Index]); > >=20 > > + while (RangesOverlap (&RawMemoryRanges[Index], &RawMemoryRanges[U= cCount], WtCount + WbCount)) { > >=20 > > + GenerateRandomMtrrPair (PhysicalAddressBits, CacheWriteProtecte= d, 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 < UcCou= nt + WtCount + WbCount + WpCount + WcCount; Index++) { > >=20 > > + GenerateRandomMtrrPair (PhysicalAddressBits, CacheWriteCombining,= NULL, &RawMemoryRanges[Index]); > >=20 > > + while (RangesOverlap (&RawMemoryRanges[Index], &RawMemoryRanges[U= cCount], WtCount + WbCount + WpCount)) { > >=20 > > + GenerateRandomMtrrPair (PhysicalAddressBits, CacheWriteCombinin= g, 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 (mMemoryCacheTyp= es) - 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, *Co= unt); > >=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.Ba= seAddress + 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 memor= y 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 (NewRangesCou= ntAtMost, 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].Base= Address; > >=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 CurrentNewRan= ge first before generate a new NewRange. > >=20 > > + { > >=20 > > + CurrentRangeInNewRanges =3D &NewRanges[NewRangesCountActual - 1= ]; > >=20 > > + } > >=20 > > + if (CurrentRangeInNewRanges !=3D NULL && CurrentRangeInNewRanges-= >Type =3D=3D CurrentRangeTypeInOldRanges) { > >=20 > > + CurrentRangeInNewRanges->Length +=3D OldRanges[OldRangesIndex].= Length; > >=20 > > + } else { > >=20 > > + NewRanges[NewRangesCountActual].BaseAddress =3D OldRanges[OldRa= ngesIndex].BaseAddress; > >=20 > > + NewRanges[NewRangesCountActual].Length +=3D OldRanges[OldRa= ngesIndex].Length; > >=20 > > + NewRanges[NewRangesCountActual].Type =3D CurrentRangeTyp= eInOldRanges; > >=20 > > + while (OldRangesIndex + 1 < *EffectiveMtrrMemoryRangesCount && = OldRanges[OldRangesIndex + 1].Type =3D=3D CurrentRangeTypeInOldRanges) > >=20 > > + { > >=20 > > + OldRangesIndex++; > >=20 > > + NewRanges[NewRangesCountActual].Length +=3D OldRanges[OldRang= esIndex].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 - CurrentRangeIn= NewRanges->BaseAddress + 1; > >=20 > > + } else { > >=20 > > + NewRanges[NewRangesCountActual].BaseAddress =3D OldLastRange.Ba= seAddress + OldLastRange.Length; > >=20 > > + NewRanges[NewRangesCountActual].Length =3D MaxAddress - NewRang= es[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].BaseAddre= ss + RawMemoryRanges[RawRangeIndex].Length - 1; > >=20 > > + } > >=20 > > + > >=20 > > + qsort (Endpoints, *EndPointCount, sizeof (UINT64), CompareFuncUint6= 4); > >=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 (UI= NT64)); > >=20 > > + AllRangePiecesCountMax =3D RawMemoryRangeCount * 3 + 1; > >=20 > > + AllRangePieces =3D calloc (AllRangePiecesCountMax, sizeo= f (MTRR_MEMORY_RANGE)); > >=20 > > + CollectEndpoints (AllEndPointsInclusive, &AllEndPointsCount, RawMem= oryRanges, RawMemoryRangeCount); > >=20 > > + > >=20 > > + for (Index =3D 0, AllRangePiecesCountActual =3D 0; Index < AllEndPo= intsCount - 1; Index++) { > >=20 > > + OverlapBitFlag1 =3D GetOverlapBitFlag (RawMemoryRanges, RawMemory= RangeCount, AllEndPointsInclusive[Index]); > >=20 > > + OverlapBitFlag2 =3D GetOverlapBitFlag (RawMemoryRanges, RawMemory= RangeCount, AllEndPointsInclusive[Index + 1]); > >=20 > > + OverlapFlagRelation =3D CheckOverlapBitFlagsRelation (OverlapBitF= lag1, OverlapBitFlag2); > >=20 > > + switch (OverlapFlagRelation) { > >=20 > > + case 0: // [1, 2] > >=20 > > + AllRangePieces[AllRangePiecesCountActual].BaseAddress =3D All= EndPointsInclusive[Index]; > >=20 > > + AllRangePieces[AllRangePiecesCountActual].Length =3D All= EndPointsInclusive[Index + 1] - AllEndPointsInclusive[Index] + 1; > >=20 > > + AllRangePiecesCountActual++; > >=20 > > + break; > >=20 > > + case 1: // [1, 2) > >=20 > > + AllRangePieces[AllRangePiecesCountActual].BaseAddress =3D All= EndPointsInclusive[Index]; > >=20 > > + AllRangePieces[AllRangePiecesCountActual].Length =3D (Al= lEndPointsInclusive[Index + 1] - 1) - AllEndPointsInclusive[Index] + 1; > >=20 > > + AllRangePiecesCountActual++; > >=20 > > + break; > >=20 > > + case 2: // (1, 2] > >=20 > > + AllRangePieces[AllRangePiecesCountActual].BaseAddress =3D All= EndPointsInclusive[Index] + 1; > >=20 > > + AllRangePieces[AllRangePiecesCountActual].Length =3D All= EndPointsInclusive[Index + 1] - (AllEndPointsInclusive[Index] + 1) + 1; > >=20 > > + AllRangePiecesCountActual++; > >=20 > > + > >=20 > > + if (!IsEndpointInRanges (AllEndPointsInclusive[Index], AllRan= gePieces, AllRangePiecesCountActual)) { > >=20 > > + AllRangePieces[AllRangePiecesCountActual].BaseAddress =3D A= llEndPointsInclusive[Index]; > >=20 > > + AllRangePieces[AllRangePiecesCountActual].Length =3D 1= ; > >=20 > > + AllRangePiecesCountActual++; > >=20 > > + } > >=20 > > + break; > >=20 > > + case 3: // (1, 2) > >=20 > > + AllRangePieces[AllRangePiecesCountActual].BaseAddress =3D All= EndPointsInclusive[Index] + 1; > >=20 > > + AllRangePieces[AllRangePiecesCountActual].Length =3D (Al= lEndPointsInclusive[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], AllRan= gePieces, AllRangePiecesCountActual)) { > >=20 > > + AllRangePieces[AllRangePiecesCountActual].BaseAddress =3D A= llEndPointsInclusive[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], Ra= wMemoryRanges, RawMemoryRangeCount); > >=20 > > + } > >=20 > > + > >=20 > > + CompactAndExtendEffectiveMtrrMemoryRanges (DefaultType, PhysicalAdd= ressBits, &AllRangePieces, &AllRangePiecesCountActual); > >=20 > > + ASSERT (*MemoryRangeCount >=3D AllRangePiecesCountActual); > >=20 > > + memcpy (MemoryRanges, AllRangePieces, AllRangePiecesCountActual * s= izeof (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/= UefiCpuPkgHostTest.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.= yaml > > 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 dup= lication for gEfiFirmwareVolumeTopFileGuid > >=20 > > "IgnoreGuidValue": [], > >=20 >=20 >=20 >=20 >=20 > >=20 --Apple-Mail=_11383A57-0AF5-436A-87D8-D0FDA9BCE6B2 Content-Transfer-Encoding: quoted-printable Content-Type: text/html; charset=utf-8

On Jul 28, 2020, at 10:53 A= M, Bret Barkelew via groups.io = <b= ret.barkelew=3Dmicrosoft.com@groups.io> wrote:

In this strategy, th= e seed would function like a meta =E2=80=9Ccase=E2=80=9D? We could add extr= a =E2=80=9Ccases=E2=80=9D as isolated testing exposes problem sets?
 

Bret,

From a quick skim of the test it looks like it always generates = random data? Not sure if I missed something. 

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 for th= e existing structured test cases.
&= nbsp;

Th= e fixed seed is an interesting idea, but I=E2=80=99m not sure that is reall= y portable. What if the CI is running on Windows and the developer is debug= ging on macOS or Linux? Seems like you could get different results. So I th= ink that is a plus for there being more of a structured set of tests as you= advocate. 

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

Thanks,<= /div>

Andrew Fish

Thanks!
 
- Bret
 
From: tim.lewis@insyde.com
Sent: Tues= day, July 28, 2020 10:13 AM
To: devel@edk= 2.groups.io; spbrogan@outlook.com; Ni, Ray
Cc: Kinney, Michael D; 'Ming Shao'; Dong, = Eric; 'Laszlo Ersek'; Sean Brogan; Bret Barkelew= ; Yao, Jiewen
Subject: [EXTERNAL] RE: [edk2-devel] [PATCH = v4] UefiCpuPkg/MtrrLib/UnitTest: Add host based unit test
 

S= ean --

What I have 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 that value. Using a static seed mi= ght actually be the default for CI runs, but stand-alone runs could use a r= andom value. 

Just a thought.

Tim

-----Original Message-----
From: deve= l@edk2.groups.io <= devel@edk2.groups.io> On Behalf Of SeanSent: 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>; Mi= ng Shao <ming.shao@intel.com>; Eric Don= g <eric.dong@intel.com>; Laszlo Ersek &= lt;lersek@redhat.com>; Sean Brogan <sean.brogan@microsoft.com>; Bret Barkelew= <Bret.Barkelew@microsoft.com>;= Jiewen Yao <jiewen.yao@intel.com>
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. 
= Generating random test cases means that the test cases on any given run 
could find a = bug in this code without this code changing.   I think this 
type of testing= (fuzz testing like) is great but I think we might want 
to consider this a different = test type and treat it differently.

For unit t= esting 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 n= eeded to get full code coverage then&= nbsp;
developing those would be great.
<= br class=3D"">Another point is once we start tracking code coverage your ra= ndom test 
= generation will lead to different results which will make it hard to 
track the metric= s reliably.

Finally, if edk2 community wants t= o support fuzz testing (which i think=  
is good) we should add details about how to add= fuzz testing to edk2 and 
  how to exclude it from PR/CI test runs.

Thoughts?

Thanks
Sean




On 7/28/2020 1:43 AM, Ni, Ray wrote:
> Add host bas= ed unit tests for the MtrrLib services.
> The BaseLib serv= ices AsmCpuid(), AsmReadMsr64(), and
> AsmWriteMsr64() are= hooked and provide simple emulation
> of the CPUID leafs = and MSRs required by the MtrrLib to
> run as a host based = unit test.
> 
> Test cases are developed for each of the API.
> 
> For the most important APIs MtrrSetMemoryAttributesInMtrrSettin= gs()
> and MtrrSetMemoryAttributeInMtrrSettings(), random = inputs are
> generated and fed to the APIs to make sure th= e implementation is
> good. The test application accepts a= n optional parameter which
> specifies how many iterations= of feeding random inputs to the two
> APIs. The overall n= umber of test cases increases when the iteration
> increas= es. Default iteration is 10 when no parameter is specified.
&= gt; 
> S= igned-off-by: Ray Ni <ray.ni@intel.com>> Signed-off-by: Michael D Kinney <michael.d.kinney@intel.com>
> Signed-off= -by: Ming Shao <ming.shao@intel.com>> Cc: Michael D Kinney <= michael.d.kinney@intel.com>
> Cc: Eric Dong <eric.dong@intel.com>
> Cc: L= aszlo Ersek <lersek@redhat.com>
> Cc: Ming Shao <ming.shao@intel.c= om>
> Cc: Sean Brogan <sean.brogan@microsoft.com>
> Cc: Bret Barkel= ew <Bret.Barkelew@microsoft.com>= ;
> Cc: Jiewen Yao <jiewen.y= ao@intel.com>
> ---
>   = .../MtrrLib/UnitTest/MtrrLibUnitTest.c      &= nbsp; | 1139 +++++++++++++++++
>   .../MtrrLib/U= nitTest/MtrrLibUnitTest.h        | = 182 +++
>   .../MtrrLib/UnitTest/MtrrLibUnitTes= tHost.inf  |   39 +
>   UefiCpuPk= g/Library/MtrrLib/UnitTest/Support.c |  923 +++++++++++++
>   UefiCpuPkg/Test/UefiCpuPkgHostTest.dsc   =      |   31 +
>   = UefiCpuPkg/UefiCpuPkg.ci.yaml       &nbs= p;         |   12 +-
>   6 files changed, 2325 insertions(+), 1 deletion(= -)
>   create mode 100644 UefiCpuPkg/Library/Mtr= rLib/UnitTest/MtrrLibUnitTest.c
>   create mode = 100644 UefiCpuPkg/Library/MtrrLib/UnitTest/MtrrLibUnitTest.h
= >   create mode 100644 UefiCpuPkg/Library/MtrrLib/UnitTest/Mtr= rLibUnitTestHost.inf
>   create mode 100644 Uefi= CpuPkg/Library/MtrrLib/UnitTest/Support.c
>   cr= eate mode 100644 UefiCpuPkg/Test/UefiCpuPkgHostTest.dsc
><= span class=3D"Apple-converted-space"> 

> diff = --git a/UefiCpuPkg/Library/MtrrLib/UnitTest/MtrrLibUnitTest.c b/UefiCpuPkg/= 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
> 
> +  Unit tests of the MtrrLib instance of the = MtrrLib class
> = ;
> +
> 
> +  Copyright (c) 2020, Int= el Corporation. All rights reserved.<BR>
> 
> +  SPDX-L= icense-Identifier: BSD-2-Clause-Patent
> 
> +
> 

> +**/> 
> +
>&nbs= p;
> +#include "MtrrLibUnitTest.h"
&g= t; 
> +<= br class=3D"">> 
> +STATIC CONST MTRR_LIB_SYSTEM_PARAMETER mDefaultSystemParamet= er =3D {
> 
> +  42, TRUE, TRUE, CacheUncacheable, 12
> 
> +};
> 
> +
> 
> +STATIC MTRR_LIB_SYSTEM_PARAMETER = mSystemParameters[] =3D {
> 
> +  { 38, TRUE, TRUE, CacheUnca= cheable,    12 },
> 
> +  { 38, TRUE, TRUE, Ca= cheWriteBack,      12 },
> 
> +  { 3= 8, TRUE, TRUE, CacheWriteThrough,   12 },
> 

> +  {= 38, TRUE, TRUE, CacheWriteProtected, 12 },
> 
> +  { 38, = TRUE, TRUE, CacheWriteCombining, 12 },
> 
> +
> 

> + = ; { 42, TRUE, TRUE, CacheUncacheable,    12 },
> 
>= +  { 42, TRUE, TRUE, CacheWriteBack,      12= },
> > +  { 42, TRUE, TRUE, CacheWriteThrough,   = 12 },
> =
> +  { 42, TRUE, TRUE, CacheWriteProtected, 12 },> 
> +  { 42, TRUE, TRUE, CacheWriteCombining, 12 },
> 
> +
> 
> +  { 48, TRUE, TRUE, CacheUncacheable, &nb= sp;  12 },
>&nb= sp;
> +  { 48, TRUE, TRUE, CacheWriteBack,&nbs= p;     12 },
> 
> +  { 48, TRUE, TRUE, Ca= cheWriteThrough,   12 },
> 
> +  { 48, TRUE, TRUE, = CacheWriteProtected, 12 },
> 
> +  { 48, TRUE, TRUE, CacheWri= teCombining, 12 },
>=  
> +};
> 
> +
> 

> +UINT32&= nbsp;           &nbs= p;       mFixedMtrrsIndex[] =3D {
> 
&g= t; +  MSR_IA32_MTRR_FIX64K_00000,
> 
> +  MSR_IA32_MTRR_= FIX16K_80000,
> = ;
> +  MSR_IA32_MTRR_FIX16K_A0000,
> 
&g= t; +  MSR_IA32_MTRR_FIX4K_C0000,
> 
> +  MSR_IA32_MTRR_F= IX4K_C8000,
> <= /span>
> +  MSR_IA32_MTRR_FIX4K_D0000,
= > 
> = +  MSR_IA32_MTRR_FIX4K_D8000,
> 
> +  MSR_IA32_MTRR_FIX4= K_E0000,
> 
> +  MSR_IA32_MTRR_FIX4K_E8000,
>= ; 
> +&n= bsp; MSR_IA32_MTRR_FIX4K_F0000,
> 
> +  MSR_IA32_MTRR_FIX4K_F= 8000
> <= br class=3D"">> +};
> 
> +STATIC_ASSERT (
> 

> + = (ARRAY_SIZE (mFixedMtrrsIndex) =3D=3D MTRR_NUMBER_OF_FIXED_MTRR),
> 
> +  "gFixedMtrrIndex does NOT contain all the fixed MTRRs!"
> 
> +  );
> 
> +
> 
> +//
>=  
> +// = Context structure to be used for most of the test cases.
>=  
> +//<= br class=3D"">> 
> +typedef struct {
> 
> +  CONST MTRR_LIB_SYSTEM= _PARAMETER *SystemParameter;
> 
> +} MTRR_LIB_TEST_CONTEXT;
> 
> +
> 
> +//
> 
> +// Context structure to be used = for GetFirmwareVariableMtrrCount() test.
> 
> +//
&g= t; 
> +t= ypedef struct {
>&nb= sp;
> +  UINT32     &= nbsp;           &nbs= p;        NumberOfReservedVariableMtrrs;=
> 
> +  CONST MTRR_LIB_SYSTEM_PARAMETER *SystemParameter;> 
> +} MTRR_LIB_GET_FIRMWARE_VARIABLE_MTRR_COUNT_CONTEXT;
> 
> +
> 
> +STATIC CHAR8 *mCacheDescription[] =3D { "UC", "WC",= "N/A", "N/A", "WT", "WP", "WB" };
> 
> +
> 
> +/**
> 
> +  Compare the actual memory ranges against expected memor= y ranges and return PASS when they match.
> 
> +
>= ; 
> +&n= bsp; @param ExpectedMemoryRanges     Expected memory ra= nges.
> =
> +  @param ExpectedMemoryRangeCount Count of expect= ed memory ranges.
>&= nbsp;
> +  @param ActualRanges  &nbs= p;          Actual memory rang= es.
> > +  @param ActualRangeCount    &n= bsp;    Count of actual memory ranges.
> 

> +
> 
> +  @retval UNIT_TEST_PASSED  Test passed.
> 
&g= t; +  @retval others        &n= bsp;   Test failed.
> 
> +**/
> 
> +UNIT_TEST_S= TATUS
> =
> +VerifyMemoryRanges (
> 
> +  IN MTRR_MEM= ORY_RANGE  *ExpectedMemoryRanges,
> 
> +  IN UINTN =              Ex= pectedMemoryRangeCount,
> 
> +  IN MTRR_MEMORY_RANGE  *A= ctualRanges,
> =
> +  IN UINTN     &n= bsp;        ActualRangeCount
> 
&g= t; +  )
> =
> +{
> 
> +  UINTN  Index;
> 
> +  UT_ASSERT_EQUAL (ExpectedMemoryRangeCount, ActualRangeC= ount);
> 
> +  for (Index =3D 0; Index < ExpectedMemoryRan= geCount; Index++) {
> 
> +    UT_ASSERT_EQUAL (Expe= ctedMemoryRanges[Index].BaseAddress, ActualRanges[Index].BaseAddress);
> 
> +    UT_ASSERT_EQUAL (ExpectedMemoryRanges[Index= ].Length, ActualRanges[Index].Length);
> 
> +    UT= _ASSERT_EQUAL (ExpectedMemoryRanges[Index].Type, ActualRanges[Index].Type);=
> 
> +  }
> 
> +
> 
> +  return UNIT_= TEST_PASSED;
> =
> +}
> 
> +
> 
> +/**
> 
> +  Dump the memory ranges.
> 
> +
> 

> + = ; @param Ranges       Memory ranges to dump.<= br class=3D"">> 
> +  @param RangeCount   Count of memory ranges.=
> 
> +**/
> 
> +VOID
> 
> +DumpMemoryRanges (> 
> +  MTRR_MEMORY_RANGE    *Ranges,
> 
> +  UINTN         &= nbsp;      RangeCount
> 
> +  )
> 
> +{
>&nbs= p;
> +  UINTN     Index;> 
> +  for (Index =3D 0; Index < RangeCount; Index++) {> 
> +    UT_LOG_INFO ("\t{ 0x%016llx, 0x%016llx, %a = },\n", Ranges[Index].BaseAddress, Ranges[Index].Length, mCacheDescription[R= anges[Index].Type]);
> 
> +  }
> 
> +}
> 
&g= t; +
> <= br class=3D"">> +/**
> 
> +**/
> 
> +
&g= t; 
> +/= **
> > +  Generate random count of MTRRs for each cache type= .
> 
> +
>&= nbsp;
> +  @param TotalCount Total MTRR count.=
> 
> +  @param UcCount    Return count of Unc= acheable type.
>&nbs= p;
> +  @param WtCount    Retur= n count of Write Through type.
> 
> +  @param WbCount &n= bsp;  Return count of Write Back type.
> 
> +  @param= WpCount    Return count of Write Protected type.
> 
> +  @param WcCount    Return count of Write Combi= ning type.
> 
> +**/
> 
> +VOID
> 
> +GenerateRa= ndomMemoryTypeCombination (
> 
> +  IN  UINT32 TotalCoun= t,
> > +  OUT UINT32 *UcCount,
> 
> +  OUT UI= NT32 *WtCount,
>&nbs= p;
> +  OUT UINT32 *WbCount,
>= ; 
> +&n= bsp; OUT UINT32 *WpCount,
> 
> +  OUT UINT32 *WcCount
> 
> +  )
>&n= bsp;
> +{
> 
> +  UINTN  Index;<= br class=3D"">> 
> +  UINT32 TotalMtrrCount;
> 
> +  UINT32= *CountPerType[5];
>=  
> +
> 
> +  CountPerType[0] = =3D UcCount;
> = ;
> +  CountPerType[1] =3D WtCount;
> 
> +  CountPerType[2] =3D WbCount;
> 
> +  CountP= erType[3] =3D WpCount;
> 
> +  CountPerType[4] =3D WcCount;> 
> +
>&nbs= p;
> +  //
> 
> +  // Initialize= the count of each cache type to 0.
> 
> +  //
= > 
> = +  for (Index =3D 0; Index < ARRAY_SIZE (CountPerType); Index++) {<= br class=3D"">> 
> +    *(CountPerType[Index]) =3D 0;
> 
&g= t; +  }
> =
> +
> 
> +  //
> 

> + = // Pick a random count of MTRRs
> 
> +  //
>= ; 
> +&n= bsp; TotalMtrrCount =3D Random32 (1, TotalCount);
> 
> +  for= (Index =3D 0; Index < TotalMtrrCount; Index++) {
> 

> + &= nbsp;  //
>&nbs= p;
> +    // For each of them, pick = a random cache type.
> 
> +    //
>= ; 
> +&n= bsp;   (*(CountPerType[Random32 (0, ARRAY_SIZE (CountPerType) - 1= )]))++;
> 

> +  }
> 
> +}
> 
> +
> 
> +/**
> <= /span>
> +  Unit test of MtrrLib service MtrrSetMemor= yAttribute()
> =
> +
> 
> +  @param[in]  Context=     Ignored
> 
> +
> 
> +  @retval&nb= sp; UNIT_TEST_PASSED         &= nbsp;   The Unit test has completed and the test
&g= t; 
> +&= nbsp;           &nbs= p;            &= nbsp;           &nbs= p;  case was successful.
> 
> +  @retval  UNIT_TEST= _ERROR_TEST_FAILED  A test case assertion has failed.
&g= t; 
> +<= br class=3D"">> 
> +**/
>=  
> +UNIT_TEST_STATUS
> 
> +EFIAPI> 
> +UnitTestMtrrSetMemoryAttributesInMtrrSettings (
= > 
> = +  IN UNIT_TEST_CONTEXT  Context
> 
> +  )
> 
> +{
> 
> +  CONST MTRR_LIB_SYSTEM_PARAMETER *SystemPara= meter;
> 
> +  RETURN_STATUS     &nb= sp;            = Status;
> 
> +  UINT32      &n= bsp;            = ;       UcCount;
> 
> +  UINT32=             &nb= sp;            = WtCount;
> 
> +  UINT32      &= nbsp;           &nbs= p;       WbCount;
> 
> +  UINT3= 2            &n= bsp;            = ; WpCount;
> 
> +  UINT32      =             &nb= sp;       WcCount;
> 
> +
> 
> +  UINT32         =             &nb= sp;    MtrrIndex;
> 
> +  UINT8  &nb= sp;            =             *Scratch= ;
> 
> +  UINTN       &nbs= p;            &= nbsp;      ScratchSize;
> 
> +  MTRR= _SETTINGS           =         LocalMtrrs;
> 

> +
> 
> +  MTRR_MEMORY_RANGE      &n= bsp;        RawMtrrRange[MTRR_NUMBER_OF_= VARIABLE_MTRR];
>&nb= sp;
> +  MTRR_MEMORY_RANGE   &n= bsp;           ExpectedMe= moryRanges[MTRR_NUMBER_OF_FIXED_MTRR * sizeof (UINT64) + 2 * MTRR_NUMBER_OF= _VARIABLE_MTRR + 1];
> 
> +  UINT32    &n= bsp;            = ;         ExpectedVariableMtrrUsage= ;
> 
> +  UINTN       &nbs= p;            &= nbsp;      ExpectedMemoryRangesCount;
> 
>= ; +
> > +  MTRR_MEMORY_RANGE     &n= bsp;         ActualMemoryRanges[MTR= R_NUMBER_OF_FIXED_MTRR   * sizeof (UINT64) + 2 * MTRR_NUMBER_OF_V= ARIABLE_MTRR + 1];
>=  
> +  UINT32    &nbs= p;            &= nbsp;        ActualVariableMtrrUsage;> 
> +  UINTN        &n= bsp;            = ;      ActualMemoryRangesCount;
>=  
> +> 
> +  MTRR_SETTINGS       =       *Mtrrs[2];
> 
> +
>= ; 
> +&n= bsp; SystemParameter =3D (MTRR_LIB_SYSTEM_PARAMETER *) Context;
> 
&g= t; +  GenerateRandomMemoryTypeCombination (
> 
> +  = ;  SystemParameter->VariableMtrrCount - PatchPcdGet32 (PcdCpuNumber= OfReservedVariableMtrrs),
> 
> +    &UcCount, &= amp;WtCount, &WbCount, &WpCount, &WcCount
> 

> + =    );
>&nb= sp;
> +  GenerateValidAndConfigurableMtrrPairs= (
> > +    SystemParameter->PhysicalAddressBit= s, RawMtrrRange,
>&n= bsp;
> +    UcCount, WtCount, WbCoun= t, WpCount, WcCount
> 
> +    );
>=  
> +> 
> +  ExpectedVariableMtrrUsage =3D UcCount + WtCount + WbCou= nt + WpCount + WcCount;
> 
> +  ExpectedMemoryRangesCount =3D= ARRAY_SIZE (ExpectedMemoryRanges);
> 
> +  GetEffectiveMemor= yRanges (
> 
> +    SystemParameter->DefaultCach= eType,
> 
> +    SystemParameter->PhysicalAddres= sBits,
> 
> +    RawMtrrRange, ExpectedVariableMtrr= Usage,
> 
> +    ExpectedMemoryRanges, &Expecte= dMemoryRangesCount
>=  
> +    );
><= span class=3D"Apple-converted-space"> 

> +
> 
> +  UT_LOG_INFO (
> 
> +    "Total = MTRR [%d]: UC=3D%d, WT=3D%d, WB=3D%d, WP=3D%d, WC=3D%d\n",
&g= t; 
> +&= nbsp;   ExpectedVariableMtrrUsage, UcCount, WtCount, WbCount, WpC= ount, WcCount
> = ;
> +    );
> 
> +  UT= _LOG_INFO ("--- Expected Memory Ranges [%d] ---\n", ExpectedMemoryRangesCou= nt);
> <= br class=3D"">> +  DumpMemoryRanges (ExpectedMemoryRanges, Expected= MemoryRangesCount);
> 
> +
> 
> +  //
= > 
> = +  // Default cache type is always an INPUT
> 
> +  //> 
> +  ZeroMem (&LocalMtrrs, sizeof (LocalMtrrs));
> 
> +  LocalMtrrs.MtrrDefType =3D MtrrGetDefaultMemoryType ();
> 
> +  ScratchSize       &n= bsp;    =3D SCRATCH_BUFFER_SIZE;
> 
> +  Mtrrs= [0]            =    =3D &LocalMtrrs;
> 
> +  Mtrrs[1]  = ;             = =3D NULL;
> 
> +
> 
> +  for (MtrrIndex =3D 0; Mtrr= Index < ARRAY_SIZE (Mtrrs); MtrrIndex++) {
> 
> +  &= nbsp; Scratch =3D calloc (ScratchSize, sizeof (UINT8));
><= span class=3D"Apple-converted-space"> 

> +&nbs= p;   Status =3D MtrrSetMemoryAttributesInMtrrSettings (Mtrrs[Mtrr= Index], Scratch, &ScratchSize, ExpectedMemoryRanges, ExpectedMemoryRang= esCount);
> 
> +    if (Status =3D=3D RETURN_BUFFER= _TOO_SMALL) {
> = ;
> +      Scratch =3D rea= lloc (Scratch, ScratchSize);
> 
> +      = Status =3D MtrrSetMemoryAttributesInMtrrSettings (Mtrrs[MtrrIndex], Scratch= , &ScratchSize, ExpectedMemoryRanges, ExpectedMemoryRangesCount);
> 
> +    }
> 
> +    UT_ASSE= RT_STATUS_EQUAL (Status, RETURN_SUCCESS);
> 
> +
>= ; 
> +&n= bsp;   if (Mtrrs[MtrrIndex] =3D=3D NULL) {
> 

> + &= nbsp;    ZeroMem (&LocalMtrrs, sizeof (LocalMtrrs));
> 
> +      MtrrGetAllMtrrs (&LocalMtrr= s);
> > +    }
> 
> +    A= ctualMemoryRangesCount =3D ARRAY_SIZE (ActualMemoryRanges);
&= gt; 
> +=     CollectTestResult (
> 
> +   &nb= sp;  SystemParameter->DefaultCacheType, SystemParameter->Physica= lAddressBits, SystemParameter->VariableMtrrCount,
> 

> + &= nbsp;    &LocalMtrrs, ActualMemoryRanges, &ActualMem= oryRangesCount, &ActualVariableMtrrUsage
> 
> +  &= nbsp;   );
> 
> +
> 
> +    UT_L= OG_INFO ("--- Actual Memory Ranges [%d] ---\n", ActualMemoryRangesCount);> 
> +    DumpMemoryRanges (ActualMemoryRanges, Actu= alMemoryRangesCount);
> 
> +    VerifyMemoryRanges = (ExpectedMemoryRanges, ExpectedMemoryRangesCount, ActualMemoryRanges, Actua= lMemoryRangesCount);
> 
> +    UT_ASSERT_TRUE (Expe= ctedVariableMtrrUsage >=3D ActualVariableMtrrUsage);
><= span class=3D"Apple-converted-space"> 

> +
> 
> +    ZeroMem (&LocalMtrrs, sizeof (LocalMtrr= s));
> <= br class=3D"">> +  }
> 
> +
> 
> +  free (= Scratch);
> 
> +
> 
> +  return UNIT_TEST_PASSED;> 
> +}
>&nbs= p;
> +
> 
> +/**
> 
> +  Tes= t routine to check whether invalid base/size can be rejected.
> 
>= +
> > +  @param Context   Pointer to MTRR_LIB_SYS= TEM_PARAMETER.
>&nbs= p;
> +
> 
> +  @return Test status.> 
> +**/
>&= nbsp;
> +UNIT_TEST_STATUS
> 
> +EFIAPI
> 
> +UnitTestInvalidMemoryLayouts (
> 
> +  IN UNI= T_TEST_CONTEXT          Contex= t
> 
> +  )
> 
> +{
> 
> +  CONST MTRR= _LIB_SYSTEM_PARAMETER *SystemParameter;
> 
> +  MTRR_MEMORY_R= ANGE            = ;   Ranges[MTRR_NUMBER_OF_VARIABLE_MTRR * 2 + 1];
&= gt; 
> +=   UINTN          &nb= sp;            =     RangeCount;
> 
> +  UINT64  &nbs= p;            &= nbsp;          MaxAddress;
> 
> +  UINT32        &= nbsp;           &nbs= p;     Index;
> 
> +  UINT64  &= nbsp;           &nbs= p;           BaseAddress;=
> 
> +  UINT64       &nbs= p;            &= nbsp;     Length;
> 
> +  RETURN_STATUS&n= bsp;            = ;      Status;
> 
> +  UINTN &n= bsp;            = ;             S= cratchSize;
> <= /span>
> +
> 
> +  SystemParameter =3D (MTRR= _LIB_SYSTEM_PARAMETER *) Context;
> 
> +
> 
> +  Ran= geCount =3D Random32 (1, ARRAY_SIZE (Ranges));
> 
> +  MaxAdd= ress =3D 1ull << SystemParameter->PhysicalAddressBits;
> 
&g= t; +
> <= br class=3D"">> +  for (Index =3D 0; Index < RangeCount; Index++= ) {
> > +    do {
> 
> +   = ;   BaseAddress =3D Random64 (0, MaxAddress);
><= span class=3D"Apple-converted-space"> 

> +&nbs= p;     Length      =3D Random6= 4 (1, MaxAddress - BaseAddress);
> 
> +    } while = (((BaseAddress & 0xFFF) =3D=3D 0) || ((Length & 0xFFF) =3D=3D 0));<= br class=3D"">> 
> +
>&nb= sp;
> +    Ranges[Index].BaseAddress= =3D BaseAddress;
>&= nbsp;
> +    Ranges[Index].Length&nb= sp;     =3D Length;
> 
> +    R= anges[Index].Type        =3D GenerateRan= domCacheType ();
>&n= bsp;
> +
> 
> +    Status = =3D MtrrSetMemoryAttribute (
> 
> +     = Ranges[Index].BaseAddress, Ranges[Index].Length, Ranges[Index].Type
> 
> +      );
> 
> +   = ; UT_ASSERT_TRUE (RETURN_ERROR (Status));
> 
> +  }
> 
> +
> 
> +  ScratchSize =3D 0;
> 
> +  Sta= tus =3D MtrrSetMemoryAttributesInMtrrSettings (NULL, NULL, &ScratchSize= , Ranges, RangeCount);
> 
> +  UT_ASSERT_TRUE (RETURN_ERROR (= Status));
> 
> +
> 
> +  return UNIT_TEST_PASSED;> 
> +}
>&nbs= p;
> +
> 
> +/**
> 
> +  Uni= t test of MtrrLib service IsMtrrSupported()
> 
> +
> 
>= ; +  @param[in]  Context    Ignored
= > 
> = +
> 
> +  @retval  UNIT_TEST_PASSED   &nb= sp;         The Unit test has compl= eted and the test
>&= nbsp;
> +       =             &nb= sp;            =         case was successful.
> 
&g= t; +  @retval  UNIT_TEST_ERROR_TEST_FAILED  A test case asse= rtion has failed.
>&= nbsp;
> +
> 
> +**/
> 

> +UNIT_TE= ST_STATUS
> 
> +EFIAPI
> 
> +UnitTestIsMtrrSupported (> 
> +  IN UNIT_TEST_CONTEXT  Context
> 

> + = ; )
> > +{
> 
> +  MTRR_LIB_SYSTEM_PARAMETER  = SystemParameter;
>&n= bsp;
> +  MTRR_LIB_TEST_CONTEXT  &nb= sp;   *LocalContext;
> 
> +
> 
> +  LocalC= ontext =3D (MTRR_LIB_TEST_CONTEXT *) Context;
> 
> +
> 
>= ; +  CopyMem (&SystemParameter, LocalContext->SystemParameter, = sizeof (SystemParameter));
> 
> +  //
> 

> +  /= / MTRR capability off in CPUID leaf.
> 
> +  //
> 
>= +  SystemParameter.MtrrSupported =3D FALSE;
> 
> +  Ini= tializeMtrrRegs (&SystemParameter);
> 
> +  UT_ASSERT_FAL= SE (IsMtrrSupported ());
> 
> +
> 
> +  //
> 
> +  // MTRR capability on in CPUID leaf, but no variable or fixe= d MTRRs.
> 
> +  //
> 
> +  SystemParameter.Mtr= rSupported =3D TRUE;
> 
> +  SystemParameter.VariableMtrrCoun= t =3D 0;
> 
> +  SystemParameter.FixedMtrrSupported =3D FALSE= ;
> 
> +  InitializeMtrrRegs (&SystemParameter);
> 
> +  UT_ASSERT_FALSE (IsMtrrSupported ());
> 

> +
> 
> +  //
>=  
> +  // MTRR capability on in CPUID lea= f, but no variable MTRRs.
> 
> +  //
> 
> +  Sy= stemParameter.MtrrSupported =3D TRUE;
> 
> +  SystemParameter= .VariableMtrrCount =3D 0;
> 
> +  SystemParameter.FixedMtrrSu= pported =3D TRUE;
>&= nbsp;
> +  InitializeMtrrRegs (&SystemPara= meter);
> 
> +  UT_ASSERT_FALSE (IsMtrrSupported ());
> 
> +
> 
> +  //
> 
> +  // MTRR capability = on in CPUID leaf, but no fixed MTRRs.
> 
> +  //
> 
>= ; +  SystemParameter.MtrrSupported =3D TRUE;
> 
> +  Sys= temParameter.VariableMtrrCount =3D 7;
> 
> +  SystemParameter= .FixedMtrrSupported =3D FALSE;
> 
> +  InitializeMtrrRegs (&a= mp;SystemParameter);
> 
> +  UT_ASSERT_FALSE (IsMtrrSupported= ());
> =
> +
> 
> +  //
> 
> +  // MTR= R capability on in CPUID leaf with both variable and fixed MTRRs.
> 
> +  //
>&= nbsp;
> +  SystemParameter.MtrrSupported =3D T= RUE;
> <= br class=3D"">> +  SystemParameter.VariableMtrrCount =3D 7;
> 
> +  SystemParameter.FixedMtrrSupported =3D TRUE;
&= gt; 
> +=   InitializeMtrrRegs (&SystemParameter);
> 
> +  UT_= ASSERT_TRUE (IsMtrrSupported ());
> 
> +
> 
> +  ret= urn UNIT_TEST_PASSED;
> 
> +}
> 
> +
> 

> +/**> 
> +  Unit test of MtrrLib service GetVariableMtrrCount()> 
> +
> = ;
> +  @param[in]  Context  &nb= sp; Ignored
> <= /span>
> +
> 
> +  @retval  UNIT_TEST_P= ASSED           &nbs= p; The Unit test has completed and the test
> 
> +  &= nbsp;           &nbs= p;            &= nbsp;            cas= e was successful.
>&= nbsp;
> +  @retval  UNIT_TEST_ERROR_TEST_= FAILED  A test case assertion has failed.
> 
> +
> 
>= ; +**/
> 
> +UNIT_TEST_STATUS
> 
> +EFIAPI
= > 
> = +UnitTestGetVariableMtrrCount (
> 
> +  IN UNIT_TEST_CONTEXT&= nbsp; Context
> = ;
> +  )
> 
> +{
> 

> + = ; UINT32           &= nbsp;        Result;
><= span class=3D"Apple-converted-space"> 

> +&nbs= p; MTRR_LIB_SYSTEM_PARAMETER SystemParameter;
> 
> +  MTRR_L= IB_TEST_CONTEXT     *LocalContext;
> 

> +
> 
> +  LocalContext =3D (MTRR_LIB_TEST_CONTEXT *) Context;
> 
> +
> = ;
> +  CopyMem (&SystemParameter, LocalCon= text->SystemParameter, sizeof (SystemParameter));
> 

> +  = //
> > +  // If MTRR capability off in CPUID leaf, then the = count is always 0.
>=  
> +  //
> 
> +  System= Parameter.MtrrSupported =3D FALSE;
> 
> +  for (SystemParamet= er.VariableMtrrCount =3D 1; SystemParameter.VariableMtrrCount <=3D MTRR_= NUMBER_OF_VARIABLE_MTRR; SystemParameter.VariableMtrrCount++) {
> 
&g= t; +    InitializeMtrrRegs (&SystemParameter);
> 
> +    Result =3D GetVariableMtrrCount ();
> 
>= ; +    UT_ASSERT_EQUAL (Result, 0);
> 
> +  }<= br class=3D"">> 
> +
>&nb= sp;
> +  //
> 
> +  // Try all s= upported variable MTRR counts.
> 
> +  // If variable MTRR co= unt is > MTRR_NUMBER_OF_VARIABLE_MTRR, then an ASSERT()
&g= t; 
> +&= nbsp; // is generated.
> 
> +  //
> 
> +  Syste= mParameter.MtrrSupported =3D TRUE;
> 
> +  for (SystemParamet= er.VariableMtrrCount =3D 1; SystemParameter.VariableMtrrCount <=3D MTRR_= NUMBER_OF_VARIABLE_MTRR; SystemParameter.VariableMtrrCount++) {
> 
&g= t; +    InitializeMtrrRegs (&SystemParameter);
> 
> +    Result =3D GetVariableMtrrCount ();
> 
>= ; +    UT_ASSERT_EQUAL (Result, SystemParameter.VariableMtrr= Count);
> 
> +  }
> 
> +
> 
> +  //> 
> +  // Expect ASSERT() if variable MTRR count is > MTRR_= NUMBER_OF_VARIABLE_MTRR
> 
> +  //
> 
> +  Syst= emParameter.VariableMtrrCount =3D MTRR_NUMBER_OF_VARIABLE_MTRR + 1;
> 
> +  InitializeMtrrRegs (&SystemParameter);
>= ; 
> +&n= bsp; UT_EXPECT_ASSERT_FAILURE (GetVariableMtrrCount (), NULL);
> 
>= ; +
> > +  SystemParameter.MtrrSupported =3D TRUE;
> 
> +  SystemParameter.VariableMtrrCount =3D MAX_UINT8;
> 
&g= t; +  InitializeMtrrRegs (&SystemParameter);
> 

> + = UT_EXPECT_ASSERT_FAILURE (GetVariableMtrrCount (), NULL);
&g= t; 
> +<= br class=3D"">> 
> +  return UNIT_TEST_PASSED;
> 
> +}
> 
&g= t; +
> <= br class=3D"">> +/**
> 
> +  Unit test of MtrrLib service = GetFirmwareVariableMtrrCount()
> 
> +
> 
> +  @param= [in]  Context    Ignored
> 
> +
> 
>= ; +  @retval  UNIT_TEST_PASSED      = ;       The Unit test has completed and the t= est
> > +         &n= bsp;            = ;            &n= bsp;     case was successful.
> 
> +  @re= tval  UNIT_TEST_ERROR_TEST_FAILED  A test case assertion has fail= ed.
> > +
> 
> +**/
> 
> +UNIT_TEST_STATUS
> 
> +EFIAPI
> 
> +UnitTestGetFirmwareVariableMtrrCount (> 
> +  IN UNIT_TEST_CONTEXT  Context
><= span class=3D"Apple-converted-space"> 

> +&nbs= p; )
> <= br class=3D"">> +{
> 
> +  UINT32    &= nbsp;           &nbs= p;            &= nbsp;           &nbs= p;  Result;
>&n= bsp;
> +  UINT32     =             &nb= sp;            =             &nb= sp; ReservedMtrrs;
>=  
> +  MTRR_LIB_SYSTEM_PARAMETER &nb= sp;            =            SystemParamete= r;
> > +  MTRR_LIB_GET_FIRMWARE_VARIABLE_MTRR_COUNT_CONTEXT = *LocalContext;
>&nbs= p;
> +
> 
> +  LocalContext =3D (MTRR= _LIB_GET_FIRMWARE_VARIABLE_MTRR_COUNT_CONTEXT *) Context;
>= ; 
> +> 
> +  CopyMem (&SystemParameter, LocalContext->System= Parameter, sizeof (SystemParameter));
> 
> +
> 

> + = InitializeMtrrRegs (&SystemParameter);
> 
> +  //
> 
> +  // Positive test cases for VCNT =3D 10 and Reserved PCD= in range 0..10
>&nb= sp;
> +  //
> 
> +  for (Reserve= dMtrrs =3D 0; ReservedMtrrs <=3D SystemParameter.VariableMtrrCount; Rese= rvedMtrrs++) {
>&nbs= p;
> +    PatchPcdSet32 (PcdCpuNumbe= rOfReservedVariableMtrrs, ReservedMtrrs);
> 
> +   = Result =3D GetFirmwareVariableMtrrCount ();
> 
> +  &= nbsp; UT_ASSERT_EQUAL (Result, SystemParameter.VariableMtrrCount - Reserved= Mtrrs);
> 
> +  }
> 
> +
> 
> +  //> 
> +  // Negative test cases when Reserved PCD is larger than= VCNT
> =
> +  //
> 
> +  for (ReservedMtrrs =3D= SystemParameter.VariableMtrrCount + 1; ReservedMtrrs <=3D 255; Reserved= Mtrrs++) {
> 
> +    PatchPcdSet32 (PcdCpuNumberOfR= eservedVariableMtrrs, ReservedMtrrs);
> 
> +    Res= ult =3D GetFirmwareVariableMtrrCount ();
> 
> +    = UT_ASSERT_EQUAL (Result, 0);
> 
> +  }
> 

> +
> 
> +  //
>=  
> +  // Negative test cases when Reserv= ed PCD is larger than VCNT
> 
> +  //
> 

> +  P= atchPcdSet32 (PcdCpuNumberOfReservedVariableMtrrs, MAX_UINT32);
> 
&g= t; +  Result =3D GetFirmwareVariableMtrrCount ();
> 

> + = ; UT_ASSERT_EQUAL (Result, 0);
> 
> +
> 
> +  //
> 
> +  // Negative test case when MTRRs are not supported
> 
> +  //
> 
> +  SystemParameter.MtrrSupported = = =3D FALSE;
> <= /span>
> +  InitializeMtrrRegs (&SystemParameter)= ;
> 
> +  PatchPcdSet32 (PcdCpuNumberOfReservedVariableMtrrs,= 2);
> <= br class=3D"">> +  Result =3D GetFirmwareVariableMtrrCount ();
> 
> +  UT_ASSERT_EQUAL (Result, 0);
> 
> +
> 
> +  //
>&= nbsp;
> +  // Negative test case when Fixed MT= RRs are not supported
> 
> +  //
> 
> +  System= Parameter.MtrrSupported =3D TRUE;
> 
> +  SystemParameter.Fix= edMtrrSupported =3D FALSE;
> 
> +  InitializeMtrrRegs (&S= ystemParameter);
>&n= bsp;
> +  PatchPcdSet32 (PcdCpuNumberOfReserve= dVariableMtrrs, 2);
> 
> +  Result =3D GetFirmwareVariableMtr= rCount ();
> 
> +  UT_ASSERT_EQUAL (Result, 0);
> 
>= +
> > +  //
> 
> +  // Expect ASSERT() if var= iable MTRR count is > MTRR_NUMBER_OF_VARIABLE_MTRR
> 

> + = //
> > +  SystemParameter.FixedMtrrSupported =3D TRUE;
> 
> +  SystemParameter.VariableMtrrCount =3D MTRR_NUMBER_OF_VA= RIABLE_MTRR + 1;
>&n= bsp;
> +  InitializeMtrrRegs (&SystemParam= eter);
> 
> +  UT_EXPECT_ASSERT_FAILURE (GetFirmwareVariableM= trrCount (), NULL);
> 
> +
> 
> +  return UNIT_TEST_= PASSED;
> 
> +}
> 
> +
> 
> +/**
&= gt; 
> +=   Unit test of MtrrLib service MtrrGetMemoryAttribute()
= > 
> = +
> 
> +  @param[in]  Context    Ignored<= br class=3D"">> 
> +
>&nb= sp;
> +  @retval  UNIT_TEST_PASSED &= nbsp;           The Unit = test has completed and the test
> 
> +    &nbs= p;            &= nbsp;           &nbs= p;          case was successfu= l.
> > +  @retval  UNIT_TEST_ERROR_TEST_FAILED  A = test case assertion has failed.
> 
> +
> 
> +**/
> 
> +UNIT_TEST_STATUS
> 
> +EFIAPI
> 
> +UnitTestMtrrG= etMemoryAttribute (
> 
> +  IN UNIT_TEST_CONTEXT  Contex= t
> 
> +  )
> 
> +{
> 
> +  return UNI= T_TEST_PASSED;
>&nbs= p;
> +}
> 
> +
> 
> +/**
> 
> +  Unit test of MtrrLib service MtrrGetFixedMtrr()
> 
>= ; +
> > +  @param[in]  Context    Ignore= d
> 
> +
>&= nbsp;
> +  @retval  UNIT_TEST_PASSED = ;            The Uni= t test has completed and the test
> 
> +    &n= bsp;            = ;            &n= bsp;          case was success= ful.
> <= br class=3D"">> +  @retval  UNIT_TEST_ERROR_TEST_FAILED  = A test case assertion has failed.
> 
> +
> 
> +**/
> 
> +UNIT_TEST_STATUS
> 
> +EFIAPI
> 
> +UnitTestMtrr= GetFixedMtrr (
>&nbs= p;
> +  IN UNIT_TEST_CONTEXT  Context
> 
> +  )
> 
> +{
> 
> +  MTRR_FIXED_SET= TINGS       *Result;
> 
> +  MT= RR_FIXED_SETTINGS       ExpectedFixedSettings= ;
> 
> +  MTRR_FIXED_SETTINGS     &n= bsp; FixedSettings;
> 
> +  UINTN    &nbs= p;            &= nbsp;   Index;
> 
> +  UINTN    = ;            &n= bsp;    MsrIndex;
> 
> +  UINTN  &nb= sp;            =       ByteIndex;
> 
> +  UINT64 = ;            &n= bsp;      MsrValue;
> 
> +  MTRR_L= IB_SYSTEM_PARAMETER SystemParameter;
> 
> +  MTRR_LIB_TEST_CO= NTEXT     *LocalContext;
> 
> +
> 
>= ; +  LocalContext =3D (MTRR_LIB_TEST_CONTEXT *) Context;
> 
>= +
> > +  CopyMem (&SystemParameter, LocalContext->Sy= stemParameter, sizeof (SystemParameter));
> 
> +  InitializeM= trrRegs (&SystemParameter);
> 
> +  //
>=  
> +&nb= sp; // Set random cache type to different ranges under 1MB and make sure> 
> +  // the fixed MTRR settings are expected.
= > 
> = +  // Try 100 times.
> 
> +  //
> 
> +  fo= r (Index =3D 0; Index < 100; Index++) {
> 
> +   = ; for (MsrIndex =3D 0; MsrIndex < ARRAY_SIZE (mFixedMtrrsIndex); MsrInde= x++) {
> 
> +      MsrValue =3D 0;
> 
> +      for (ByteIndex =3D 0; ByteIndex <= ; sizeof (UINT64); ByteIndex++) {
> 
> +    &n= bsp;   MsrValue =3D MsrValue | LShiftU64 (GenerateRandomCacheType= (), ByteIndex * 8);
> 
> +      }
> 
> +      ExpectedFixedSettings.Mtrr[MsrIndex= ] =3D MsrValue;
>&nb= sp;
> +      AsmWriteMsr64= (mFixedMtrrsIndex[MsrIndex], MsrValue);
> 
> +    = }
> 
> +
>&= nbsp;
> +    Result =3D MtrrGetFixed= Mtrr (&FixedSettings);
> 
> +    UT_ASSERT_EQUA= L (Result, &FixedSettings);
> 
> +    UT_ASSERT= _MEM_EQUAL (&FixedSettings, &ExpectedFixedSettings, sizeof (FixedSe= ttings));
> 
> +  }
> 
> +
> 
> +  //<= br class=3D"">> 
> +  // Negative test case when MTRRs are not supported> 
> +  //
> 
> +  SystemParameter.MtrrSupported = = =3D FALSE;
> <= /span>
> +  InitializeMtrrRegs (&SystemParameter)= ;
> 
> +
>&= nbsp;
> +  ZeroMem (&FixedSettings, sizeof= (FixedSettings));
>=  
> +  ZeroMem (&ExpectedFixedSetting= s, sizeof (ExpectedFixedSettings));
> 
> +  Result =3D MtrrGe= tFixedMtrr (&FixedSettings);
> 
> +  UT_ASSERT_EQUAL (Res= ult, &FixedSettings);
> 
> +  UT_ASSERT_MEM_EQUAL (&E= xpectedFixedSettings, &FixedSettings, sizeof (ExpectedFixedSettings));<= br class=3D"">> 
> +
>&nb= sp;
> +  return UNIT_TEST_PASSED;
> 
>= ; +}
> <= br class=3D"">> +
> 
> +/**
> 
> +  Unit test of = MtrrLib service MtrrGetAllMtrrs()
> 
> +
> 
> +  @pa= ram[in]  Context    Ignored
> 
> +
> 
&g= t; +  @retval  UNIT_TEST_PASSED     &nbs= p;       The Unit test has completed and the = test
> <= br class=3D"">> +         &= nbsp;           &nbs= p;            &= nbsp;     case was successful.
> 
> +  @r= etval  UNIT_TEST_ERROR_TEST_FAILED  A test case assertion has fai= led.
> <= br class=3D"">> +
> 
> +**/
> 
> +UNIT_TEST_STATUS
> 
> +EFIAPI
> 
> +UnitTestMtrrGetAllMtrrs (
= > 
> = +  IN UNIT_TEST_CONTEXT      Context
> 
> +  )
>&n= bsp;
> +{
> 
> +  MTRR_SETTINGS =             *Result;=
> 
> +  MTRR_SETTINGS      &nb= sp;      Mtrrs;
> 
> +  MTRR_SETTING= S             E= xpectedMtrrs;
> = ;
> +  MTRR_VARIABLE_SETTING   =   VariableMtrr[MTRR_NUMBER_OF_VARIABLE_MTRR];
> 
> +  UI= NT32            = ;        Index;
> 
> +  MT= RR_LIB_SYSTEM_PARAMETER SystemParameter;
> 
> +  MTRR_LIB_TES= T_CONTEXT     *LocalContext;
> 
> +
> 
> +  LocalContext =3D (MTRR_LIB_TEST_CONTEXT *) Context;
> 
> +
> 
> +  CopyMem (&SystemParameter, LocalContext-= >SystemParameter, sizeof (SystemParameter));
> 
> +  Initi= alizeMtrrRegs (&SystemParameter);
> 
> +
> 

> + = for (Index =3D 0; Index < SystemParameter.VariableMtrrCount; Index++) {=
> 
> +    GenerateRandomMtrrPair (SystemParameter.= PhysicalAddressBits, GenerateRandomCacheType (), &VariableMtrr[Index], = NULL);
> 
> +    AsmWriteMsr64 (MSR_IA32_MTRR_PHYSB= ASE0 + (Index << 1), VariableMtrr[Index].Base);
> 

> + =    AsmWriteMsr64 (MSR_IA32_MTRR_PHYSMASK0 + (Index << 1), V= ariableMtrr[Index].Mask);
> 
> +  }
> 
> +  Res= ult =3D MtrrGetAllMtrrs (&Mtrrs);
> 
> +  UT_ASSERT_EQUAL= (Result, &Mtrrs);
> 
> +  UT_ASSERT_MEM_EQUAL (Mtrrs.Var= iables.Mtrr, VariableMtrr, sizeof (MTRR_VARIABLE_SETTING) * SystemParameter= .VariableMtrrCount);
> 
> +
> 
> +  //
> 
>= +  // Negative test case when MTRRs are not supported
&= gt; 
> +=   //
> 
> +  ZeroMem (&ExpectedMtrrs, sizeof (Expect= edMtrrs));
> 
> +  ZeroMem (&Mtrrs, sizeof (Mtrrs));
> 
> +
> = ;
> +  SystemParameter.MtrrSupported =3D FALSE= ;
> 
> +  InitializeMtrrRegs (&SystemParameter);
> 
> +  Result =3D MtrrGetAllMtrrs (&Mtrrs);
><= span class=3D"Apple-converted-space"> 

> +&nbs= p; UT_ASSERT_EQUAL (Result, &Mtrrs);
> 
> +  UT_ASSERT_ME= M_EQUAL (&ExpectedMtrrs, &Mtrrs, sizeof (ExpectedMtrrs));
> 
> +
> 
> +  //
> 
> +  // Expect ASSERT() = if variable MTRR count is > MTRR_NUMBER_OF_VARIABLE_MTRR
&= gt; 
> +=   //
> 
> +  SystemParameter.MtrrSupported =3D TRUE;
> 
> +  SystemParameter.VariableMtrrCount =3D MTRR_NUMBER_OF_VA= RIABLE_MTRR + 1;
>&n= bsp;
> +  InitializeMtrrRegs (&SystemParam= eter);
> 
> +  UT_EXPECT_ASSERT_FAILURE (MtrrGetAllMtrrs (&am= p;Mtrrs), NULL);
>&n= bsp;
> +
> 
> +  return UNIT_TEST_PAS= SED;
> <= br class=3D"">> +}
> 
> +
> 
> +/**
>=  
> +&nb= sp; Unit test of MtrrLib service MtrrSetAllMtrrs()
> 
> +
> 
> +  @param[in]  Context    Ignored
> 
> +
> 
> +  @retval  UNIT_TEST_PASSED  &n= bsp;          The Unit test ha= s completed and the test
> 
> +      = ;            &n= bsp;            = ;         case was successful.
> 
> +  @retval  UNIT_TEST_ERROR_TEST_FAILED  A test = case assertion has failed.
> 
> +
> 
> +**/
> 
>= +UNIT_TEST_STATUS
>=  
> +EFIAPI
> 
> +UnitTestMtrrSetAllM= trrs (
> 
> +  IN UNIT_TEST_CONTEXT  Context
> 
&g= t; +  )
> =
> +{
> 
> +  MTRR_SETTINGS &nbs= p;            &= nbsp;    *Result;
> 
> +  MTRR_SETTINGS &= nbsp;           &nbs= p;     Mtrrs;
> 
> +  UINT32  &= nbsp;           &nbs= p;           Index;
> 
> +  MSR_IA32_MTRR_DEF_TYPE_REGISTER Default;
= > 
> = +  MTRR_LIB_SYSTEM_PARAMETER       Syste= mParameter;
> <= /span>
> +  MTRR_LIB_TEST_CONTEXT   &n= bsp;       *LocalContext;
><= span class=3D"Apple-converted-space"> 

> +
> 
> +  LocalContext =3D (MTRR_LIB_TEST_CONTEXT *) Context;
> 
> +
> = ;
> +  CopyMem (&SystemParameter, LocalCon= text->SystemParameter, sizeof (SystemParameter));
> 

> +  = InitializeMtrrRegs (&SystemParameter);
> 
> +
&g= t; 
> +&= nbsp; Default.Uint64 =3D 0;
> 
> +  Default.Bits.E =3D 1;
> 
> +  Default.Bits.FE =3D 1;
> 
> +  Default.Bi= ts.Type =3D GenerateRandomCacheType ();
> 
> +
><= span class=3D"Apple-converted-space"> 

> +&nbs= p; ZeroMem (&Mtrrs, sizeof (Mtrrs));
> 
> +  Mtrrs.MtrrDe= fType =3D Default.Uint64;
> 
> +  for (Index =3D 0; Index <= ; SystemParameter.VariableMtrrCount; Index++) {
> 
> +  =   GenerateRandomMtrrPair (SystemParameter.PhysicalAddressBits, Generat= eRandomCacheType (), &Mtrrs.Variables.Mtrr[Index], NULL);
> 
>= +  }
> 
> +  Result =3D MtrrSetAllMtrrs (&Mtrrs);> 
> +  UT_ASSERT_EQUAL (Result, &Mtrrs);
&g= t; 
> +<= br class=3D"">> 
> +  UT_ASSERT_EQUAL (AsmReadMsr64 (MSR_IA32_MTRR_DEF_TYPE= ), Mtrrs.MtrrDefType);
> 
> +  for (Index =3D 0; Index < S= ystemParameter.VariableMtrrCount; Index++) {
> 
> +  &= nbsp; UT_ASSERT_EQUAL (AsmReadMsr64 (MSR_IA32_MTRR_PHYSBASE0 + (Index <&= lt; 1)), Mtrrs.Variables.Mtrr[Index].Base);
> 
> +  &= nbsp; UT_ASSERT_EQUAL (AsmReadMsr64 (MSR_IA32_MTRR_PHYSMASK0 + (Index <&= lt; 1)), Mtrrs.Variables.Mtrr[Index].Mask);
> 
> +  }
> 
> +
> = ;
> +  return UNIT_TEST_PASSED;
= > 
> = +}
> > +
>=  
> +/**
> 
> +  Unit test of Mt= rrLib service MtrrGetMemoryAttributeInVariableMtrr()
> 

> +
> 
> +  @param[in]  Context    Ignored
> 
> +
> 
> +  @retval  UNIT_TEST_PASSED  &n= bsp;          The Unit test ha= s completed and the test
> 
> +      = ;            &n= bsp;            = ;         case was successful.
> 
> +  @retval  UNIT_TEST_ERROR_TEST_FAILED  A test = case assertion has failed.
> 
> +
> 
> +**/
> 
>= +UNIT_TEST_STATUS
>=  
> +EFIAPI
> 
> +UnitTestMtrrGetMemo= ryAttributeInVariableMtrr (
> 
> +  IN UNIT_TEST_CONTEXT = ; Context
> 
> +  )
> 
> +{
> 
> +  MT= RR_LIB_TEST_CONTEXT         &n= bsp; *LocalContext;
> 
> +  MTRR_LIB_SYSTEM_PARAMETER &n= bsp;     SystemParameter;
> 
> +  UINT32=             &nb= sp;            = Result;
> 
> +  MTRR_VARIABLE_SETTING    = ;       VariableSetting[MTRR_NUMBER_OF_VARIAB= LE_MTRR];
> 
> +  VARIABLE_MTRR     =             &nb= sp; VariableMtrr[MTRR_NUMBER_OF_VARIABLE_MTRR];
> 
> +  UINT6= 4            &n= bsp;            = ; ValidMtrrBitsMask;
> 
> +  UINT64    &n= bsp;            = ;         ValidMtrrAddressMask;
> 
> +  UINT32        &= nbsp;           &nbs= p;     Index;
> 
> +  MSR_IA32_MTRR_PHYSB= ASE_REGISTER Base;
>=  
> +  MSR_IA32_MTRR_PHYSMASK_REGISTER Ma= sk;
> > +
> 
> +  LocalContext =3D (MTRR_LIB_TEST_C= ONTEXT *) Context;
>=  
> +
> 
> +  CopyMem (&Syst= emParameter, LocalContext->SystemParameter, sizeof (SystemParameter));> 
> +
>&nbs= p;
> +  InitializeMtrrRegs (&SystemParamet= er);
> <= br class=3D"">> +
> 
> +  ValidMtrrBitsMask  &nb= sp; =3D (1ull << SystemParameter.PhysicalAddressBits) - 1;
> 
> +  ValidMtrrAddressMask =3D ValidMtrrBitsMask & 0xfffffffff= ffff000ULL;
> <= /span>
> +
> 
> +  for (Index =3D 0; Index &= lt; SystemParameter.VariableMtrrCount; Index++) {
> 
> + &nbs= p;  GenerateRandomMtrrPair (SystemParameter.PhysicalAddressBits, Gener= ateRandomCacheType (), &VariableSetting[Index], NULL);
&g= t; 
> +&= nbsp;   AsmWriteMsr64 (MSR_IA32_MTRR_PHYSBASE0 + (Index << = 1), VariableSetting[Index].Base);
> 
> +    AsmWrit= eMsr64 (MSR_IA32_MTRR_PHYSMASK0 + (Index << 1), VariableSetting[Index= ].Mask);
> 
> +  }
> 
> +  Result =3D MtrrGetMe= moryAttributeInVariableMtrr (ValidMtrrBitsMask, ValidMtrrAddressMask, Varia= bleMtrr);
> 
> +  UT_ASSERT_EQUAL (Result, SystemParameter.Va= riableMtrrCount);
>&= nbsp;
> +
> 
> +  for (Index =3D 0; I= ndex < SystemParameter.VariableMtrrCount; Index++) {
><= span class=3D"Apple-converted-space"> 

> +&nbs= p;   Base.Uint64    =3D VariableMtrr[Index].BaseAd= dress;
> 
> +    Base.Bits.Type =3D (UINT32) Variab= leMtrr[Index].Type;
> 
> +    UT_ASSERT_EQUAL (Base= .Uint64, VariableSetting[Index].Base);
> 
> +
> 

> + = ;   Mask.Uint64    =3D ~(VariableMtrr[Index].Lengt= h - 1) & ValidMtrrBitsMask;
> 
> +    Mask.Bits= .V    =3D 1;
> 
> +    UT_ASSERT_EQU= AL (Mask.Uint64, VariableSetting[Index].Mask);
> 
> +  }
> 
> +
> = ;
> +  //
> 
> +  // Negative te= st case when MTRRs are not supported
> 
> +  //
> 
>= +  SystemParameter.MtrrSupported =3D FALSE;
> 
> +  Ini= tializeMtrrRegs (&SystemParameter);
> 
> +  Result =3D Mt= rrGetMemoryAttributeInVariableMtrr (ValidMtrrBitsMask, ValidMtrrAddressMask= , VariableMtrr);
>&n= bsp;
> +  UT_ASSERT_EQUAL (Result, 0);
> 
> +
> 
> +  //
> 
> +  // Expect ASSERT() = if variable MTRR count is > MTRR_NUMBER_OF_VARIABLE_MTRR
&= gt; 
> +=   //
> 
> +  SystemParameter.MtrrSupported =3D TRUE;
> 
> +  SystemParameter.VariableMtrrCount =3D MTRR_NUMBER_OF_VA= RIABLE_MTRR + 1;
>&n= bsp;
> +  InitializeMtrrRegs (&SystemParam= eter);
> 
> +  UT_EXPECT_ASSERT_FAILURE (MtrrGetMemoryAttribu= teInVariableMtrr (ValidMtrrBitsMask, ValidMtrrAddressMask, VariableMtrr), N= ULL);
> =
> +
> 
> +  return UNIT_TEST_PASSED;
> 
> +}
> 
> +
> 
> +/**
> 
> +  Unit t= est of MtrrLib service MtrrDebugPrintAllMtrrs()
> 
> +
> 
&g= t; +  @param[in]  Context    Ignored
> 
>= +
> > +  @retval  UNIT_TEST_PASSED   &n= bsp;         The Unit test has comp= leted and the test
>=  
> +       = ;            &n= bsp;            = ;        case was successful.
> 
> +  @retval  UNIT_TEST_ERROR_TEST_FAILED  A test case = assertion has failed.
> 
> +
> 
> +**/
>=  
> +UNI= T_TEST_STATUS
> = ;
> +EFIAPI
> 
> +UnitTestMtrrDebugPrintAl= lMtrrs (
> 
> +  IN UNIT_TEST_CONTEXT  Context
> 
> +  )
>&n= bsp;
> +{
> 
> +  return UNIT_TEST_PA= SSED;
> =
> +}
> 
> +
> 
> +/**
>= ; 
> +&n= bsp; Unit test of MtrrLib service MtrrGetDefaultMemoryType().
> 
>= +
> > +  @param[in]  Context    Ignored=
> 
> +
>&n= bsp;
> +  @retval  UNIT_TEST_PASSED =             The Unit= test has completed and the test
> 
> +    &nb= sp;            =             &nb= sp;          case was successf= ul.
> > +  @retval  UNIT_TEST_ERROR_TEST_FAILED  A= test case assertion has failed.
> 
> +
> 
> +**/
> 
> +UNIT_TEST_STATUS
> 
> +EFIAPI
> 
> +UnitTestMtrrG= etDefaultMemoryType (
> 
> +  IN UNIT_TEST_CONTEXT  Cont= ext
> > +  )
> 
> +{
> 
> +  MTRR_L= IB_TEST_CONTEXT     *LocalContext;
> 

> + = ; UINTN           &n= bsp;         Index;
&= gt; 
> +=   MTRR_MEMORY_CACHE_TYPE    Result;
><= span class=3D"Apple-converted-space"> 

> +&nbs= p; MTRR_LIB_SYSTEM_PARAMETER SystemParameter;
> 
> +  MTRR_M= EMORY_CACHE_TYPE    CacheType[5];
> 
> +
> 
> +  CacheType[0] =3D CacheUncacheable;
> 
> +  Cac= heType[1] =3D CacheWriteCombining;
> 
> +  CacheType[2] =3D C= acheWriteThrough;
>&= nbsp;
> +  CacheType[3] =3D CacheWriteProtecte= d;
> > +  CacheType[4] =3D CacheWriteBack;
>= ; 
> +> 
> +  LocalContext =3D (MTRR_LIB_TEST_CONTEXT *) Context;> 
> +
> = ;
> +  CopyMem (&SystemParameter, LocalCon= text->SystemParameter, sizeof (SystemParameter));
> 

> +  = //
> > +  // If MTRRs are supported, then always return the = cache type in the MSR
> 
> +  // MSR_IA32_MTRR_DEF_TYPE
> 
> +  //
> 
> +  for (Index =3D 0; Index < A= RRAY_SIZE (CacheType); Index++) {
> 
> +    SystemP= arameter.DefaultCacheType =3D CacheType[Index];
> 
> +  =   InitializeMtrrRegs (&SystemParameter);
> 
> + &nbs= p;  Result =3D MtrrGetDefaultMemoryType ();
> 
> +  = ;  UT_ASSERT_EQUAL (Result, SystemParameter.DefaultCacheType);
> 
> +  }
>&n= bsp;
> +
> 
> +  //
>= ; 
> +&n= bsp; // If MTRRs are not supported, then always return CacheUncacheable
> 
> +  //
> 
> +  SystemParameter.MtrrSupported = = =3D FALSE;
> <= /span>
> +  InitializeMtrrRegs (&SystemParameter)= ;
> 
> +  Result =3D MtrrGetDefaultMemoryType ();
> 
&g= t; +  UT_ASSERT_EQUAL (Result, CacheUncacheable);
> 

> +
> 
> +  SystemParameter.MtrrSupported =3D TRUE;
&= gt; 
> +=   SystemParameter.FixedMtrrSupported =3D FALSE;
> 

> +  = InitializeMtrrRegs (&SystemParameter);
> 
> +  Result =3D= MtrrGetDefaultMemoryType ();
> 
> +  UT_ASSERT_EQUAL (Result= , CacheUncacheable);
> 
> +
> 
> +  SystemParameter.= MtrrSupported =3D TRUE;
> 
> +  SystemParameter.FixedMtrrSupp= orted =3D TRUE;
>&nb= sp;
> +  SystemParameter.VariableMtrrCount =3D= 0;
> > +  InitializeMtrrRegs (&SystemParameter);
> 
> +  Result =3D MtrrGetDefaultMemoryType ();
><= span class=3D"Apple-converted-space"> 

> +&nbs= p; UT_ASSERT_EQUAL (Result, CacheUncacheable);
> 
> +
> 
>= ; +  return UNIT_TEST_PASSED;
> 
> +}
> 

> +
> 
> +/**
> <= /span>
> +  Unit test of MtrrLib service MtrrSetMemor= yAttributeInMtrrSettings().
> 
> +
> 
> +  @param= [in]  Context    Ignored
> 
> +
> 
>= ; +  @retval  UNIT_TEST_PASSED      = ;       The Unit test has completed and the t= est
> > +         &n= bsp;            = ;            &n= bsp;     case was successful.
> 
> +  @re= tval  UNIT_TEST_ERROR_TEST_FAILED  A test case assertion has fail= ed.
> > +
> 
> +**/
> 
> +UNIT_TEST_STATUS
> 
> +EFIAPI
> 
> +UnitTestMtrrSetMemoryAttributeInMtrrSett= ings (
> 
> +  IN UNIT_TEST_CONTEXT  Context
> 
&g= t; +  )
> =
> +{
> 
> +  CONST MTRR_LIB_SYSTEM_P= ARAMETER *SystemParameter;
> 
> +  RETURN_STATUS  &= nbsp;           &nbs= p;    Status;
> 
> +  UINT32   =             &nb= sp;          UcCount;
> 
> +  UINT32         =             &nb= sp;    WtCount;
> 
> +  UINT32  &nbs= p;            &= nbsp;          WbCount;
> 
> +  UINT32         = ;            &n= bsp;    WpCount;
> 
> +  UINT32  &nb= sp;            =            WcCount;
> 
> +
> = ;
> +  UINTN     &nbs= p;            &= nbsp;        MtrrIndex;
&g= t; 
> +&= nbsp; UINTN          &nbs= p;            &= nbsp;   Index;
> 
> +  MTRR_SETTINGS  &nb= sp;            =     LocalMtrrs;
> 
> +
> 
> +  MTRR_M= EMORY_RANGE          &nbs= p;    RawMtrrRange[MTRR_NUMBER_OF_VARIABLE_MTRR];
> 
> +  MTRR_MEMORY_RANGE       &= nbsp;       ExpectedMemoryRanges[MTRR_NUMBER_= OF_FIXED_MTRR * sizeof (UINT64) + 2 * MTRR_NUMBER_OF_VARIABLE_MTRR + 1];> 
> +  UINT32        &= nbsp;           &nbs= p;     ExpectedVariableMtrrUsage;
> 

> + = UINTN           &nb= sp;            =    ExpectedMemoryRangesCount;
> 
> +
><= span class=3D"Apple-converted-space"> 

> +&nbs= p; MTRR_MEMORY_RANGE         &= nbsp;     ActualMemoryRanges[MTRR_NUMBER_OF_FIXED_MTRR = * sizeof (UINT64) + 2 * MTRR_NUMBER_OF_VARIABLE_MTRR + 1];
&g= t; 
> +&= nbsp; UINT32          &nb= sp;            =    ActualVariableMtrrUsage;
> 
> +  UINTN &nbs= p;            &= nbsp;            Act= ualMemoryRangesCount;
> 
> +
> 
> +  MTRR_SETTINGS&n= bsp;            = ;      *Mtrrs[2];
> 
> +
&g= t; 
> +&= nbsp; SystemParameter =3D (MTRR_LIB_SYSTEM_PARAMETER *) Context;
> 
> +  GenerateRandomMemoryTypeCombination (
> 

> + &= nbsp;  SystemParameter->VariableMtrrCount - PatchPcdGet32 (PcdCpuNu= mberOfReservedVariableMtrrs),
> 
> +    &UcCoun= t, &WtCount, &WbCount, &WpCount, &WcCount
>= ; 
> +&n= bsp;   );
> 
> +  GenerateValidAndConfigurableMtrrP= airs (
> 
> +    SystemParameter->PhysicalAddres= sBits, RawMtrrRange,
> 
> +    UcCount, WtCount, Wb= Count, WpCount, WcCount
> 
> +    );
= > 
> = +
> 
> +  ExpectedVariableMtrrUsage =3D UcCount + WtCount + W= bCount + WpCount + WcCount;
> 
> +  ExpectedMemoryRangesCount= =3D ARRAY_SIZE (ExpectedMemoryRanges);
> 
> +  GetEffectiveM= emoryRanges (
> = ;
> +    SystemParameter->Default= CacheType,
> 
> +    SystemParameter->PhysicalAd= dressBits,
> 
> +    RawMtrrRange, ExpectedVariable= MtrrUsage,
> 
> +    ExpectedMemoryRanges, &Exp= ectedMemoryRangesCount
> 
> +    );
&= gt; 
> +=
> 
> +  UT_LOG_INFO ("--- Expected Memory Ranges [%d] ---\n"= , ExpectedMemoryRangesCount);
> 
> +  DumpMemoryRanges (Expec= tedMemoryRanges, ExpectedMemoryRangesCount);
> 
> +  //
> 
> +  // Default cache type is always an INPUT
= > 
> = +  //
> 
> +  ZeroMem (&LocalMtrrs, sizeof (LocalMtr= rs));
> =
> +  LocalMtrrs.MtrrDefType =3D MtrrGetDefaultMemory= Type ();
> 
> +  Mtrrs[0]      =          =3D &LocalMtrrs;
> 
> +  Mtrrs[1]        = ;       =3D NULL;
> 
> +
> 
&g= t; +  for (MtrrIndex =3D 0; MtrrIndex < ARRAY_SIZE (Mtrrs); MtrrInd= ex++) {
> 
> +    for (Index =3D 0; Index < Expe= ctedMemoryRangesCount; Index++) {
> 
> +    &n= bsp; Status =3D MtrrSetMemoryAttributeInMtrrSettings (
> 

> + = ;            &n= bsp;   Mtrrs[MtrrIndex],
> 
> +    &= nbsp;            Exp= ectedMemoryRanges[Index].BaseAddress,
> 
> +   &nbs= p;             = ExpectedMemoryRanges[Index].Length,
> 
> +    =              Ex= pectedMemoryRanges[Index].Type
> 
> +     = ;            );
> 
> +      UT_ASSERT_TRUE (Status =3D=3D R= ETURN_SUCCESS || Status =3D=3D RETURN_OUT_OF_RESOURCES || Status =3D=3D RET= URN_BUFFER_TOO_SMALL);
> 
> +      if (St= atus =3D=3D RETURN_OUT_OF_RESOURCES || Status =3D=3D RETURN_BUFFER_TOO_SMAL= L) {
> <= br class=3D"">> +        return UNIT_= TEST_SKIPPED;
> = ;
> +      }
> 
>= +    }
> 
> +
> 
> +    if= (Mtrrs[MtrrIndex] =3D=3D NULL) {
> 
> +    &n= bsp; ZeroMem (&LocalMtrrs, sizeof (LocalMtrrs));
> 

> + &= nbsp;    MtrrGetAllMtrrs (&LocalMtrrs);
&g= t; 
> +&= nbsp;   }
> 
> +    ActualMemoryRangesCou= nt =3D ARRAY_SIZE (ActualMemoryRanges);
> 
> +    C= ollectTestResult (
>=  
> +      SystemPara= meter->DefaultCacheType, SystemParameter->PhysicalAddressBits, System= Parameter->VariableMtrrCount,
> 
> +    &nb= sp; &LocalMtrrs, ActualMemoryRanges, &ActualMemoryRangesCount, &= ;ActualVariableMtrrUsage
> 
> +      );> 
> +    UT_LOG_INFO ("--- Actual Memory Ranges [%d= ] ---\n", ActualMemoryRangesCount);
> 
> +    DumpM= emoryRanges (ActualMemoryRanges, ActualMemoryRangesCount);
&g= t; 
> +&= nbsp;   VerifyMemoryRanges (ExpectedMemoryRanges, ExpectedMemoryR= angesCount, ActualMemoryRanges, ActualMemoryRangesCount);
>= ; 
> +&n= bsp;   UT_ASSERT_TRUE (ExpectedVariableMtrrUsage >=3D ActualVa= riableMtrrUsage);
>&= nbsp;
> +
> 
> +    ZeroMem= (&LocalMtrrs, sizeof (LocalMtrrs));
> 
> +  }
> 
> +
> 
> +  return UNIT_TEST_PASSED;
><= span class=3D"Apple-converted-space"> 

> +}> 
> +
> = ;
> +
> 
> +/**
> 
> +  Prep= routine for UnitTestGetFirmwareVariableMtrrCount().
> 

> +
> 
> +  @param Context  Point to a UINT32 data to save the Pcd= CpuNumberOfReservedVariableMtrrs.
> 
> +**/
> 

> +UNIT_TE= ST_STATUS
> 
> +EFIAPI
> 
> +SavePcdValue (
> 
>= +  UNIT_TEST_CONTEXT  Context
> 
> +  )
> 
> +{
> 
> +  MTRR_LIB_GET_FIRMWARE_VARIABLE_MTRR_COUNT_C= ONTEXT  *LocalContext;
> 
> +
> 
> +  LocalC= ontext =3D (MTRR_LIB_GET_FIRMWARE_VARIABLE_MTRR_COUNT_CONTEXT *) Context;> 
> +  LocalContext->NumberOfReservedVariableMtrrs =3D Pat= chPcdGet32 (PcdCpuNumberOfReservedVariableMtrrs);
> 
> +  ret= urn UNIT_TEST_PASSED;
> 
> +}
> 
> +
> 

> +/**> 
> +  Clean up routine for UnitTestGetFirmwareVariableMtrrCo= unt().
> 
> +
> 
> +  @param Context  Point to = a UINT32 data to save the PcdCpuNumberOfReservedVariableMtrrs.
> 
>= ; +**/
> 
> +VOID
> 
> +EFIAPI
> 
> +RestorePcdV= alue (
> 
> +  UNIT_TEST_CONTEXT  Context
= > 
> = +  )
> 
> +{
> 
> +  MTRR_LIB_GET_FIRMWARE_VARI= ABLE_MTRR_COUNT_CONTEXT  *LocalContext;
> 
> +
> 
>= ; +  LocalContext =3D (MTRR_LIB_GET_FIRMWARE_VARIABLE_MTRR_COUNT_CONTE= XT *) Context;
>&nbs= p;
> +  PatchPcdSet32 (PcdCpuNumberOfReservedV= ariableMtrrs, LocalContext->NumberOfReservedVariableMtrrs);
> 
>= ; +}
> <= br class=3D"">> +
> 
> +/**
> 
> +  Initialize th= e unit test framework, suite, and unit tests for the
> 

> +  = ResetSystemLib and run the ResetSystemLib unit test.
> 

> +
> 
> +  @param Iteration       &= nbsp;       Iteration of testing MtrrSetMemor= yAttributeInMtrrSettings
> 
> +      = ;            &n= bsp;            = ;  and MtrrSetMemoryAttributesInMtrrSettings using random inputs.
> 
> +
> = ;
> +  @retval  EFI_SUCCESS  &n= bsp;        All test cases were dispatch= ed.
> > +  @retval  EFI_OUT_OF_RESOURCES  There ar= e not enough resources available to
> 
> +    =             &nb= sp;            =     initialize the unit tests.
> 
> +**/
> 
> +STATIC
>&nbs= p;
> +EFI_STATUS
> 
> +EFIAPI
> 
>= ; +UnitTestingEntry (
> 
> +  UINTN    &n= bsp;            = ;      Iteration
> 
> +  )
> 
> +{
> 
> +  EFI_STATUS     &nb= sp;            =             &nb= sp;         Status;
&= gt; 
> +=   UNIT_TEST_FRAMEWORK_HANDLE       =             &nb= sp;    Framework;
> 
> +  UNIT_TEST_SUITE_HAND= LE            &= nbsp;           &nbs= p;   MtrrApiTests;
> 
> +  UINTN   &= nbsp;           &nbs= p;            &= nbsp;           &nbs= p;    Index;
> 
> +  UINTN   &n= bsp;            = ;            &n= bsp;            = ;    SystemIndex;
> 
> +  MTRR_LIB_TEST_CONTEX= T            &n= bsp;            = ;    Context;
> 
> +  MTRR_LIB_GET_FIRMWARE_VA= RIABLE_MTRR_COUNT_CONTEXT GetFirmwareVariableMtrrCountContext;
> 
>= ; +
> > +  Context.SystemParameter    &n= bsp;            = ;            =3D &am= p;mDefaultSystemParameter;
> 
> +  GetFirmwareVariableMtrrCou= ntContext.SystemParameter =3D &mDefaultSystemParameter;
&= gt; 
> +=   Framework =3D NULL;
> 
> +
> 
> +  DEBUG ((DE= BUG_INFO, "%a v%a\n", UNIT_TEST_APP_NAME, UNIT_TEST_APP_VERSION));
> 
> +
> 
> +  //
> 
> +  // Setup the test f= ramework for running the tests.
> 
> +  //
>=  
> +&nb= sp; Status =3D InitUnitTestFramework (&Framework, UNIT_TEST_APP_NAME, g= EfiCallerBaseName, UNIT_TEST_APP_VERSION);
> 
> +  if (EFI_ER= ROR (Status)) {
>&nb= sp;
> +    DEBUG ((DEBUG_ERROR, "Fai= led in InitUnitTestFramework. Status =3D %r\n", Status));
>= ; 
> +&n= bsp;   goto EXIT;
> 
> +  }
> 

> +
> 
> +  //
>&= nbsp;
> +  // --------------Suite-----------De= scription--------------Name----------Function--------Pre---Post------------= -------Context-----------
> 
> +  //
> 
> +
> 
> +  //
>&= nbsp;
> +  // Populate the MtrrLib API Unit Te= st Suite.
> 
> +  //
> 
> +  Status =3D CreateU= nitTestSuite (&MtrrApiTests, Framework, "MtrrLib API Tests", "MtrrLib.M= trrLib", NULL, NULL);
> 
> +  if (EFI_ERROR (Status)) {
> 
> +    DEBUG ((DEBUG_ERROR, "Failed in CreateUnitT= estSuite for MtrrLib API Tests\n"));
> 
> +    Stat= us =3D EFI_OUT_OF_RESOURCES;
> 
> +    goto EXIT;> 
> +  }
> 
> +  AddTestCase (MtrrApiTests, "Te= st IsMtrrSupported",         &= nbsp;            "Mt= rrSupported",          &n= bsp;            = ; UnitTestIsMtrrSupported,        &= nbsp;           &nbs= p; NULL, NULL, &Context);
> 
> +  AddTestCase (MtrrApiTes= ts, "Test GetVariableMtrrCount",       &= nbsp;         "GetVariableMtrrCount= ",            &= nbsp;    UnitTestGetVariableMtrrCount,   &nbs= p;             = NULL, NULL, &Context);
> 
> +  AddTestCase (MtrrApiTests,= "Test GetFirmwareVariableMtrrCount",      &n= bsp;  "GetFirmwareVariableMtrrCount",     &nb= sp;   UnitTestGetFirmwareVariableMtrrCount,   &nbs= p;     SavePcdValue, RestorePcdValue, &GetFirmwareV= ariableMtrrCountContext);
> 
> +  AddTestCase (MtrrApiTests, = "Test MtrrGetMemoryAttribute",       &nb= sp;       "MtrrGetMemoryAttribute", &nbs= p;             = UnitTestMtrrGetMemoryAttribute,       &n= bsp;       NULL, NULL, &Context);
> 
> +  AddTestCase (MtrrApiTests, "Test MtrrGetFixedMtrr", &nb= sp;            =        "MtrrGetFixedMtrr",   &= nbsp;           &nbs= p;     UnitTestMtrrGetFixedMtrr,    = ;            &n= bsp;    NULL, NULL, &Context);
> 
> +  Add= TestCase (MtrrApiTests, "Test MtrrGetAllMtrrs",    &nbs= p;            &= nbsp;    "MtrrGetAllMtrrs",     &nb= sp;            =     UnitTestMtrrGetAllMtrrs,     &n= bsp;            = ;    NULL, NULL, &Context);
> 
> +  AddTes= tCase (MtrrApiTests, "Test MtrrSetAllMtrrs",     &= nbsp;           &nbs= p;    "MtrrSetAllMtrrs",      =             &nb= sp;   UnitTestMtrrSetAllMtrrs,      = ;            &n= bsp;   NULL, NULL, &Context);
> 
> +  AddTes= tCase (MtrrApiTests, "Test MtrrGetMemoryAttributeInVariableMtrr", "MtrrGetM= emoryAttributeInVariableMtrr", UnitTestMtrrGetMemoryAttributeInVariableMtrr= , NULL, NULL, &Context);
> 
> +  AddTestCase (MtrrApiTest= s, "Test MtrrDebugPrintAllMtrrs",       =         "MtrrDebugPrintAllMtrrs", &= nbsp;           &nbs= p; UnitTestMtrrDebugPrintAllMtrrs,       = ;        NULL, NULL, &Context);
> 
> +  AddTestCase (MtrrApiTests, "Test MtrrGetDefaultMemoryTy= pe",            = ; "MtrrGetDefaultMemoryType",       &nbs= p;     UnitTestMtrrGetDefaultMemoryType,  &nb= sp;          NULL, NULL, &= Context);
> 
> +
> 
> +  for (SystemIndex =3D 0; Sys= temIndex < ARRAY_SIZE (mSystemParameters); SystemIndex++) {
> 
>= ; +    for (Index =3D 0; Index < Iteration; Index++) {> 
> +      AddTestCase (MtrrApiTests, "Tes= t InvalidMemoryLayouts",        &nb= sp;         "InvalidMemoryLayouts",=             &nb= sp;     UnitTestInvalidMemoryLayouts,   =             &nb= sp;  InitializeSystem, NULL, &mSystemParameters[SystemIndex]);
> 
> +      AddTestCase (MtrrApiTests, "Tes= t MtrrSetMemoryAttributeInMtrrSettings",  "MtrrSetMemoryAttributeInMtr= rSettings",  UnitTestMtrrSetMemoryAttributeInMtrrSettings,  Initi= alizeSystem, NULL, &mSystemParameters[SystemIndex]);
>=  
> +&nb= sp;     AddTestCase (MtrrApiTests, "Test MtrrSetMemoryA= ttributesInMtrrSettings", "MtrrSetMemoryAttributesInMtrrSettings", UnitTest= MtrrSetMemoryAttributesInMtrrSettings, InitializeSystem, NULL, &mSystem= Parameters[SystemIndex]);
> 
> +    }
> 
>= +  }
> 
> +  //
> 
> +  // Execute the te= sts.
> <= br class=3D"">> +  //
> 
> +  srand ((unsigned int) t= ime (NULL));
> =
> +  Status =3D RunAllTestSuites (Framework);=
> 
> +
>&n= bsp;
> +EXIT:
> 
> +  if (Framework != = =3D NULL) {
> =
> +    FreeUnitTestFramework (Frame= work);
> 
> +  }
> 
> +
> 
> +  return= Status;
> 
> +}
> 
> +
> 
> +/**
= > 
> = +  Standard POSIX C entry point for host based unit test execution.> 
> +
> = ;
> +  @param Argc  Number of arguments.<= br class=3D"">> 
> +  @param Argv  Array of arguments.
&= gt; 
> +=
> 
> +  @return Test application exit code.
&g= t; 
> +*= */
> > +INT32
> 
> +main (
> 
> +  INT32 = Argc,
> =
> +  CHAR8 *Argv[]
> 
> +  )
> 
> +{
> 
> +  UINTN    Iteration;
> 
> +
> 
> +  //
> 
> +  // First parameter = specifies the test iterations.
> 
> +  // Default is 10.
> 
> +  //
> 
> +  Iteration =3D 10;
> 
>= ; +  if (Argc =3D=3D 2) {
> 
> +    Iteration = = =3D atoi (Argv[1]);
> 
> +  }
> 
> +  return= UnitTestingEntry (Iteration);
> 
> +}
> 
> diff --git a/= UefiCpuPkg/Library/MtrrLib/UnitTest/MtrrLibUnitTest.h b/UefiCpuPkg/Library/= MtrrLib/UnitTest/MtrrLibUnitTest.h
> new file mode 100644<= br class=3D"">> index 0000000000..9750523133
> --- /dev= /null
> +++ b/UefiCpuPkg/Library/MtrrLib/UnitTest/MtrrLibU= nitTest.h
> @@ -0,0 +1,182 @@
> +/** @fil= e
> 
> +
>&= nbsp;
> +  Copyright (c) 2020, Intel Corporati= on. All rights reserved.<BR>
> 
> +  SPDX-License-Ident= ifier: BSD-2-Clause-Patent
> 
> +
> 
> +**/
> 
>= +
> > +#ifndef _MTRR_SUPPORT_H_
> 
> +#define _MTRR_SUP= PORT_H_
> 
> +
> 
> +#include <stdio.h>
> 
&g= t; +#include <stdlib.h>
> 
> +#include <string.h>
> 
> +#include <stdarg.h>
> 
> +#include <stddef.h= >
> <= br class=3D"">> +#include <setjmp.h>
> 
> +#include <= cmocka.h>
> =
> +#include <time.h>
> 

> +
> 
> +#include <Uefi.h>
> 
> +#include <Library/BaseLib= .h>
> 
> +#include <Library/BaseMemoryLib.h>
> 
>= ; +#include <Library/DebugLib.h>
> 
> +#include <Library/= UnitTestLib.h>
>&= nbsp;
> +#include <Library/MtrrLib.h>
> 
> +#include <Library/UnitTestHostBaseLib.h>
> 

> +
> 
> +#include <Register/ArchitecturalMsr.h>
>= ; 
> +#i= nclude <Register/Cpuid.h>
> 
> +#include <Register/Msr.h&= gt;
> > +
> 
> +#define UNIT_TEST_APP_NAME  &n= bsp;     "MtrrLib Unit Tests"
> 
> +#define UN= IT_TEST_APP_VERSION     "1.0"
> 
> +
> 
> +#define SCRATCH_BUFFER_SIZE       SIZ= E_16KB
> 
> +
> 
> +typedef struct {
> 

> + = ; UINT8           &n= bsp;      PhysicalAddressBits;
><= span class=3D"Apple-converted-space"> 

> +&nbs= p; BOOLEAN           = ;     MtrrSupported;
> 
> +  BOOLEAN = ;            &n= bsp;  FixedMtrrSupported;
> 
> +  MTRR_MEMORY_CACHE_TYPE= DefaultCacheType;
>=  
> +  UINT32    &nbs= p;            Variab= leMtrrCount;
> =
> +} MTRR_LIB_SYSTEM_PARAMETER;
>=  
> +> 
> +extern UINT32        &= nbsp;           &nbs= p;      mFixedMtrrsIndex[];
> 

> +
> 
> +/**
> =
> +  Initialize the MTRR registers.
> 
> +
> 
> +  @param SystemParameter System parameter that= controls the MTRR registers initialization.
> 
> +**/
> 
> +UNIT_TEST_STATUS
> 
> +EFIAPI
> 
> +InitializeMtr= rRegs (
> 
> +  IN MTRR_LIB_SYSTEM_PARAMETER  *SystemPar= ameter
> 
> +  );
> 
> +
> 
> +/**
> 
> +  Initialize the MTRR registers.
> 
> +
> 
>= ; +  @param Context System parameter that controls the MTRR registers = initialization.
>&nb= sp;
> +**/
> 
> +UNIT_TEST_STATUS
> 
> +EFIAPI
>&nbs= p;
> +InitializeSystem (
> 
> +  IN U= NIT_TEST_CONTEXT        Context
> 
> +  );
>&= nbsp;
> +
> 
> +/**
> 

> +  = Return a random memory cache type.
> 
> +**/
> 

> +MTRR_M= EMORY_CACHE_TYPE
>&n= bsp;
> +GenerateRandomCacheType (
>= ; 
> +&n= bsp; VOID
> 
> +  );
> 
> +
> 
> +/**
> 
> +  Generate random MTRRs.
> 
> +
&g= t; 
> +&= nbsp; @param PhysicalAddressBits  Physical address bits.
> 
>= +  @param RawMemoryRanges      Return the ra= ndomly generated MTRRs.
> 
> +  @param UcCount  &nb= sp;           Count of Un= cacheable MTRRs.
>&n= bsp;
> +  @param WtCount   &nbs= p;          Count of Write Thr= ough MTRRs.
> <= /span>
> +  @param WbCount    &nb= sp;         Count of Write Back MTR= Rs.
> > +  @param WpCount      = ;        Count of Write Protected MTRRs.=
> 
> +  @param WcCount      &n= bsp;       Count of Write Combining MTRRs.> 
> +**/
>&n= bsp;
> +VOID
> 
> +GenerateValidAndConfigu= rableMtrrPairs (
>&n= bsp;
> +  IN     UINT32&nb= sp;            =        PhysicalAddressBits,
>= ; 
> +&n= bsp; IN OUT MTRR_MEMORY_RANGE       &nbs= p; *RawMemoryRanges,
> 
> +  IN     UINT3= 2            &n= bsp;       UcCount,
> 
> +  IN&= nbsp;    UINT32       &nb= sp;            WtCou= nt,
> > +  IN     UINT32  &nbs= p;            &= nbsp;    WbCount,
> 
> +  IN   =   UINT32          &n= bsp;         WpCount,
> 
>= +  IN     UINT32     &nb= sp;            =   WcCount
>&nbs= p;
> +  );
> 
> +
><= span class=3D"Apple-converted-space"> 

> +/**<= br class=3D"">> 
> +  Convert the MTRR BASE/MASK array to memory ranges.> 
> +
> = ;
> +  @param DefaultType   &nb= sp;      Default memory type.
> 

> + = ; @param PhysicalAddressBits  Physical address bits.
>= ; 
> +&n= bsp; @param RawMemoryRanges      Raw memory ranges= .
> 
> +  @param RawMemoryRangeCount  Count of raw memor= y ranges.
> 
> +  @param MemoryRanges    =      Memory ranges.
> 
> +  @param Memory= RangeCount     Count of memory ranges.
&g= t; 
> +*= */
> > +VOID
> 
> +GetEffectiveMemoryRanges (
> 
> +  IN MTRR_MEMORY_CACHE_TYPE DefaultType,
> 

> + = IN UINT32           = ;      PhysicalAddressBits,
> 

> +  = IN MTRR_MEMORY_RANGE      *RawMemoryRanges,
> 
> +  IN UINT32        &n= bsp;        RawMemoryRangeCount,
> 
> +  OUT MTRR_MEMORY_RANGE     *MemoryRanges,=
> 
> +  OUT UINTN       &= nbsp;         *MemoryRangeCount
> 
> +  );
> 
> +
> 
> +/**
>= ; 
> +&n= bsp; Generate random MTRR BASE/MASK for a specified type.
>= ; 
> +> 
> +  @param PhysicalAddressBits Physical address bits.
> 
> +  @param CacheType      &nb= sp;    Cache type.
> 
> +  @param MtrrPair&nbs= p;           Return the r= andom MTRR.
> <= /span>
> +  @param MtrrMemoryRange   &= nbsp; Return the random memory range.
> 
> +**/
>=  
> +VOI= D
> 
> +GenerateRandomMtrrPair (
> 
> +  IN  UI= NT32            = ;     PhysicalAddressBits,
> 
> +  IN&nbs= p; MTRR_MEMORY_CACHE_TYPE CacheType,
> 
> +  OUT MTRR_VARIABL= E_SETTING  *MtrrPair,       OPTIONAL
> 
> +  OUT MTRR_MEMORY_RANGE      *Mt= rrMemoryRange OPTIONAL
> 
> +  );
> 
> +
> 
&g= t; +/**
> 
> +  Collect the test result.
> 

> +
> 
> +  @param DefaultType      &= nbsp;   Default memory type.
> 
> +  @param Physica= lAddressBits  Physical address bits.
> 
> +  @param Vari= ableMtrrCount    Count of variable MTRRs.
>=  
> +&nb= sp; @param Mtrrs          = ;      MTRR settings to collect from.
> 
>= ; +  @param Ranges        &nbs= p;      Return the memory ranges.
&g= t; 
> +&= nbsp; @param RangeCount        &nbs= p;  Return the count of memory ranges.
> 
> +  @param= MtrrCount           = ; Return the count of variable MTRRs being used.
> 
> +**/
> 
> +VOID
> =
> +CollectTestResult (
> 
> +  IN&nb= sp;    MTRR_MEMORY_CACHE_TYPE DefaultType,
>= ; 
> +&n= bsp; IN     UINT32      &= nbsp;          PhysicalAddress= Bits,
> =
> +  IN     UINT32  &n= bsp;            = ;  VariableMtrrCount,
> 
> +  IN    = MTRR_SETTINGS          *Mtrrs= ,
> 
> +  OUT    MTRR_MEMORY_RANGE  =     *Ranges,
> 
> +  IN OUT UINTN  &= nbsp;           &nbs= p;   *RangeCount,
> 
> +  OUT    UIN= T32            =      *MtrrCount
> 
> +  );
= > 
> = +
> 
> +/**
> 
> +  Return a 64bit random number.> 
> +
> = ;
> +  @param Start  Start of the random = number range.
> = ;
> +  @param Limit  Limit of the random = number range.
> = ;
> +  @return 64bit random number
> 
&g= t; +**/
> 
> +UINT64
> 
> +Random64 (
><= span class=3D"Apple-converted-space"> 

> +&nbs= p; UINT64  Start,
> 
> +  UINT64  Limit
> 
&g= t; +  );
> = ;
> +
> 
> +/**
> 
> +  Retu= rn a 32bit random number.
> 
> +
> 
> +  @param Star= t  Start of the random number range.
> 
> +  @param Limi= t  Limit of the random number range.
> 
> +  @return 32b= it random number
>&n= bsp;
> +**/
> 
> +UINT32
>= ; 
> +Ra= ndom32 (
> 
> +  UINT32  Start,
> 
> +  UI= NT32  Limit
>&n= bsp;
> +  );
> 
> +#endif
> 
&g= t; 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/Libra= ry/MtrrLib/UnitTest/MtrrLibUnitTestHost.inf
> @@ -0,0 +1,3= 9 @@
> +## @file
> 
> +# Unit tests of the MtrrLi= b instance of the MtrrLib class
> 
> +#
> 
> +# Copyright= (c) 2020, Intel Corporation. All rights reserved.<BR>
= > 
> = +# SPDX-License-Identifier: BSD-2-Clause-Patent
> 
> +##
> 
> +
> 
> +[Defines]
> 
> +  INF_VERSION &n= bsp;            = ;      =3D 0x00010006
> 
> +  BASE_N= AME            =           =3D MtrrLibUnitTestH= ost
> > +  FILE_GUID      &nbs= p;            &= nbsp;  =3D A1542D84-B64D-4847-885E-0509084376AB
> 

> +  = MODULE_TYPE          &nbs= p;         =3D HOST_APPLICATION
> 
> +  VERSION_STRING       = ;          =3D 1.0
> 
&g= t; +
> <= br class=3D"">> +#
> 
> +# The following information is for ref= erence only and not required by the build tools.
> 
> +#
> 
> +#  VALID_ARCHITECTURES      &nbs= p;    =3D IA32 X64
> 
> +#
> 
> +
> 
> +[Sources]
>&= nbsp;
> +  MtrrLibUnitTest.c
>= ; 
> +&n= bsp; MtrrLibUnitTest.h
> 
> +  Support.c
> 

> +
> 
> +[Packages]
> 
> +  MdePkg/MdePkg.dec
> 
&g= t; +  UefiCpuPkg/UefiCpuPkg.dec
> 
> +  UnitTestFramewor= kPkg/UnitTestFrameworkPkg.dec
> 
> +
> 
> +[LibraryClass= es]
> > +  BaseLib
> 
> +  BaseMemoryLib
> 
> +  DebugLib
> 
> +  MtrrLib
&g= t; 
> +&= nbsp; UnitTestLib
>&= nbsp;
> +
> 
> +[Pcd]
> 

> + = ; gUefiCpuPkgTokenSpaceGuid.PcdCpuNumberOfReservedVariableMtrrs  = ## SOMETIMES_CONSUMES
> 
> diff --git a/UefiCpuPkg/Library/MtrrLi= b/UnitTest/Support.c b/UefiCpuPkg/Library/MtrrLib/UnitTest/Support.c
> new file mode 100644
> index 0000000000..a7ee= d45940
> --- /dev/null
> +++ b/UefiCpuPkg= /Library/MtrrLib/UnitTest/Support.c
> @@ -0,0 +1,923 @@> +/** @file
> 
> +  Unit tests of the MtrrLib= instance of the MtrrLib class
> 
> +
> 
> +  Copyri= ght (c) 2018 - 2020, Intel Corporation. All rights reserved.<BR>
> 
> +  SPDX-License-Identifier: BSD-2-Clause-Patent
> 
> +
> 
> +**/
> 
> +
> 
> +#include "Mtr= rLibUnitTest.h"
>&nb= sp;
> +
> 
> +MTRR_MEMORY_CACHE_TYPE mMemo= ryCacheTypes[] =3D {
> 
> +  CacheUncacheable, CacheWriteComb= ining, CacheWriteThrough, CacheWriteProtected, CacheWriteBack
> 
>= +  };
> <= /span>
> +
> 
> +UINT64    &n= bsp;            = ;          mFixedMtrrsValue[MT= RR_NUMBER_OF_FIXED_MTRR];
> 
> +MSR_IA32_MTRR_PHYSBASE_REGISTER&nb= sp; mVariableMtrrsPhysBase[MTRR_NUMBER_OF_VARIABLE_MTRR];
>= ; 
> +MS= R_IA32_MTRR_PHYSMASK_REGISTER  mVariableMtrrsPhysMask[MTRR_NUMBER_OF_V= ARIABLE_MTRR];
>&nbs= p;
> +MSR_IA32_MTRR_DEF_TYPE_REGISTER  mDefTyp= eMsr;
> =
> +MSR_IA32_MTRRCAP_REGISTER     = ;   mMtrrCapMsr;
> 
> +CPUID_VERSION_INFO_EDX  = ;         mCpuidVersionInfoEdx;
> 
> +CPUID_VIR_PHY_ADDRESS_SIZE_EAX   mCpuidVirPhyAddress= SizeEax;
> 
> +
> 
> +/**
> 
> +  Retrie= ves CPUID information.
> 
> +
> 
> +  Executes the C= PUID instruction with EAX set to the value specified by Index.
> 
>= ; +  This function always returns Index.
> 
> +  If Eax= is not NULL, then the value of EAX after CPUID is returned in Eax.
> 
> +  If Ebx is not NULL, then the value of EBX after CPUID is ret= urned in Ebx.
> = ;
> +  If Ecx is not NULL, then the value of E= CX after CPUID is returned in Ecx.
> 
> +  If Edx is not NULL= , then the value of EDX after CPUID is returned in Edx.
><= span class=3D"Apple-converted-space"> 

> +&nbs= p; This function is only available on IA-32 and x64.
> 

> +
> 
> +  @param  Index The 32-bit value to load into EAX prior = to invoking the CPUID
> 
> +      &n= bsp;         instruction.
> 
> +  @param  Eax   The pointer to the 32-bit EAX v= alue returned by the CPUID
> 
> +     &nb= sp;          instruction. This= is an optional parameter that may be NULL.
> 
> +  @param=   Ebx   The pointer to the 32-bit EBX value returned by the = CPUID
> =
> +         =        instruction. This is an optional param= eter that may be NULL.
> 
> +  @param  Ecx   T= he pointer to the 32-bit ECX value returned by the CPUID
>=  
> +&nb= sp;            =    instruction. This is an optional parameter that may be NULL.> 
> +  @param  Edx   The pointer to the 32-bit= EDX value returned by the CPUID
> 
> +    &nb= sp;           instruction= . This is an optional parameter that may be NULL.
> 
> +
> 
> +  @return Index.
> 
> +
> 
> +**/
> 
> +UINT32
>&nbs= p;
> +EFIAPI
> 
> +UnitTestMtrrLibAsmCpuid= (
> > +  IN      UINT32  = ;            &n= bsp;     Index,
> 
> +  OUT  &n= bsp;  UINT32         &nbs= p;          *Eax,  OPTION= AL
> > +  OUT     UINT32  &nbs= p;            &= nbsp;    *Ebx,  OPTIONAL
> 
> +  OUT&nb= sp;    UINT32        = ;            *Ecx,&n= bsp; OPTIONAL
> = ;
> +  OUT     UINT32 = ;            &n= bsp;      *Edx   OPTIONAL
= > 
> = +  )
> 
> +{
> 
> +  switch (Index) {
> 
> +  case CPUID_VERSION_INFO:
> 
> +    i= f (Edx !=3D NULL) {
> 
> +      *Edx =3D = mCpuidVersionInfoEdx.Uint32;
> 
> +    }
> 
> +    return Index;
> 
> +    = break;
> 
> +  case CPUID_EXTENDED_FUNCTION:
&g= t; 
> +&= nbsp;   if (Eax !=3D NULL) {
> 
> +   &nb= sp;  *Eax =3D CPUID_VIR_PHY_ADDRESS_SIZE;
> 
> +  &= nbsp; }
> 
> +    return Index;
><= span class=3D"Apple-converted-space"> 

> +&nbs= p;   break;
> 
> +  case CPUID_VIR_PHY_ADDRESS_SIZE= :
> 
> +    if (Eax !=3D NULL) {
>=  
> +&nb= sp;     *Eax =3D mCpuidVirPhyAddressSizeEax.Uint32;
> 
> +    }
> 
> +    return = Index;
> 
> +    break;
> 
> +  }
> 
> +
> = ;
> +  //
> 
> +  // Should neve= r fall through to here
> 
> +  //
> 
> +  ASSER= T(FALSE);
> 
> +  return Index;
> 
> +}
> 
&g= t; +
> <= br class=3D"">> +/**
> 
> +  Returns a 64-bit Machine Spec= ific Register(MSR).
> 
> +
> 
> +  Reads and returns= the 64-bit MSR specified by Index. No parameter checking is
= > 
> = +  performed on Index, and some Index values may cause CPU exceptions.= The
> <= br class=3D"">> +  caller must either guarantee that Index is valid= , or the caller must set up
> 
> +  exception handlers to cat= ch the exceptions. This function is only available
> 
> +  on= IA-32 and x64.
>&nb= sp;
> +
> 
> +  @param  MsrIndex= The 32-bit MSR index to read.
> 
> +
> 
> +  @retur= n The value of the MSR identified by MsrIndex.
> 
> +
> 
>= ; +**/
> 
> +UINT64
> 
> +EFIAPI
> 
> +UnitTestM= trrLibAsmReadMsr64(
> 
> +  IN UINT32  MsrIndex
> 
> +  )
>&n= bsp;
> +{
> 
> +  UINT32 Index;
> 
> +
> = ;
> +  for (Index =3D 0; Index < ARRAY_SIZE= (mFixedMtrrsValue); Index++) {
> 
> +    if (MsrIn= dex =3D=3D mFixedMtrrsIndex[Index]) {
> 
> +   &nbs= p;  return mFixedMtrrsValue[Index];
> 
> +    = }
> 
> +  }
> 
> +
> 
> +  if ((MsrInd= ex >=3D MSR_IA32_MTRR_PHYSBASE0) &&
> 
> +  &= nbsp;   (MsrIndex <=3D MSR_IA32_MTRR_PHYSMASK0 + (MTRR_NUMBER_= OF_VARIABLE_MTRR << 1))) {
> 
> +    if (MsrI= ndex % 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;
> 
> +      return mVariableMtrrsPhysMask[I= ndex].Uint64;
> = ;
> +    }
> 
> +  }> 
> +
>&nbs= p;
> +  if (MsrIndex =3D=3D MSR_IA32_MTRR_DEF_= TYPE) {
> 
> +    return mDefTypeMsr.Uint64;
> 
> +  }
>&= nbsp;
> +
> 
> +  if (MsrIndex =3D=3D= MSR_IA32_MTRRCAP) {
> 
> +    return mMtrrCapMsr.U= int64;
> 
> +  }
> 
> +
> 
> +  //
> 
> +  // Should never fall through to here
>=  
> +&nb= sp; //
> 
> +  ASSERT(FALSE);
> 
> +  return= 0;
> > +}
> 
> +
> 
> +/**
><= span class=3D"Apple-converted-space"> 

> +&nbs= p; Writes a 64-bit value to a Machine Specific Register(MSR), and returns t= he
> > +  value.
> 
> +
> 
> +  Write= s the 64-bit value specified by Value to the MSR specified by Index. The> 
> +  64-bit value written to the MSR is returned. No paramet= er checking is
>&nbs= p;
> +  performed on Index or Value, and some = of these may cause CPU exceptions. The
> 
> +  caller must ei= ther guarantee that Index and Value are valid, or the caller
= > 
> = +  must establish proper exception handlers. This function is only ava= ilable on
> 
> +  IA-32 and x64.
> 
> +
> 
>= ; +  @param  MsrIndex The 32-bit MSR index to write.
> 
>= ; +  @param  Value The 64-bit value to write to the MSR.
> 
> +
> 
> +  @return Value
> 
> +
> 
>= ; +**/
> 
> +UINT64
> 
> +EFIAPI
> 
> +UnitTestM= trrLibAsmWriteMsr64(
> 
> +  IN     = UINT32           &n= bsp;        MsrIndex,
>=  
> +&nb= sp; IN      UINT64     &n= bsp;            = ;  Value
> = ;
> +  )
> 
> +{
> 

> + = ; UINT32 Index;
>&nb= sp;
> +
> 
> +  for (Index =3D 0; Ind= ex < ARRAY_SIZE (mFixedMtrrsValue); Index++) {
> 
> + &nbs= p;  if (MsrIndex =3D=3D mFixedMtrrsIndex[Index]) {
><= span class=3D"Apple-converted-space"> 

> +&nbs= p;     mFixedMtrrsValue[Index] =3D Value;
> 
>= +      return Value;
> 
> +  &= nbsp; }
> 
> +  }
> 
> +
> 
> +  if ((= MsrIndex >=3D MSR_IA32_MTRR_PHYSBASE0) &&
> 

> + &= nbsp;    (MsrIndex <=3D MSR_IA32_MTRR_PHYSMASK0 + (MTRR_N= UMBER_OF_VARIABLE_MTRR << 1))) {
> 
> +    if= (MsrIndex % 2 =3D=3D 0) {
> 
> +      In= dex =3D (MsrIndex - MSR_IA32_MTRR_PHYSBASE0) >> 1;
>=  
> +&nb= sp;     mVariableMtrrsPhysBase[Index].Uint64 =3D Value;=
> 
> +      return Value;
= > 
> = +    } else {
> 
> +      = Index =3D (MsrIndex - MSR_IA32_MTRR_PHYSMASK0) >> 1;
&g= t; 
> +&= nbsp;     mVariableMtrrsPhysMask[Index].Uint64 =3D Valu= e;
> > +      return Value;
> 
>= ; +    }
> 
> +  }
> 
> +
> 
&g= t; +  if (MsrIndex =3D=3D MSR_IA32_MTRR_DEF_TYPE) {
>=  
> +&nb= sp;   mDefTypeMsr.Uint64 =3D Value;
> 
> +  &= nbsp; return Value;
> 
> +  }
> 
> +
> 
>= ; +  if (MsrIndex =3D=3D MSR_IA32_MTRRCAP) {
> 
> + &nbs= p;  mMtrrCapMsr.Uint64 =3D Value;
> 
> +    re= turn Value;
> <= /span>
> +  }
> 
> +
> 

> +  /= /
> 
> +  // Should never fall through to here
= > 
> = +  //
> 
> +  ASSERT(FALSE);
> 
> +  retur= n 0;
> <= br class=3D"">> +}
> 
> +
> 
> +/**
>=  
> +&nb= sp; Initialize the MTRR registers.
> 
> +
> 
> +  @p= aram SystemParameter System parameter that controls the MTRR registers init= ialization.
> <= /span>
> +**/
> 
> +UNIT_TEST_STATUS
> 
>= ; +EFIAPI
> 
> +InitializeMtrrRegs (
> 
> +  IN MTR= R_LIB_SYSTEM_PARAMETER  *SystemParameter
> 
> +  )
> 
> +{
>&nbs= p;
> +  UINT32     &n= bsp;            = ;  Index;
>&nbs= p;
> +
> 
> +  SetMem (mFixedMtrrsVal= ue, sizeof (mFixedMtrrsValue), SystemParameter->DefaultCacheType);
> 
> +
> = ;
> +  for (Index =3D 0; Index < ARRAY_SIZE= (mVariableMtrrsPhysBase); Index++) {
> 
> +    mVa= riableMtrrsPhysBase[Index].Uint64       =   =3D 0;
> = ;
> +    mVariableMtrrsPhysBase[Inde= x].Bits.Type      =3D SystemParameter->DefaultC= acheType;
> 
> +    mVariableMtrrsPhysBase[Index].B= its.Reserved1 =3D 0;
> 
> +
> 
> +    mVar= iableMtrrsPhysMask[Index].Uint64       &= nbsp; =3D 0;
> =
> +    mVariableMtrrsPhysMask[Index= ].Bits.V         =3D 0;
> 
&g= t; +    mVariableMtrrsPhysMask[Index].Bits.Reserved1 =3D 0;<= br class=3D"">> 
> +  }
> 
> +
> 
> +  mDefTypeMsr.B= its.E         =3D 1;
= > 
> = +  mDefTypeMsr.Bits.FE        =3D 1= ;
> 
> +  mDefTypeMsr.Bits.Type     = =3D SystemParameter->DefaultCacheType;
> 
> +  mDefTypeMs= r.Bits.Reserved1 =3D 0;
> 
> +  mDefTypeMsr.Bits.Reserved2 = =3D 0;
> 
> +  mDefTypeMsr.Bits.Reserved3 =3D 0;
> 
&g= t; +
> <= br class=3D"">> +  mMtrrCapMsr.Bits.SMRR    &nb= sp; =3D 0;
> 
> +  mMtrrCapMsr.Bits.WC    = ;    =3D 0;
> 
> +  mMtrrCapMsr.Bits.VCNT = ;     =3D SystemParameter->VariableMtrrCount;
> 
> +  mMtrrCapMsr.Bits.FIX       = =3D SystemParameter->FixedMtrrSupported;
> 
> +  mMtrrC= apMsr.Bits.Reserved1 =3D 0;
> 
> +  mMtrrCapMsr.Bits.Reserved= 2 =3D 0;
> 
> +  mMtrrCapMsr.Bits.Reserved3 =3D 0;
> 
> +
> 
> +  mCpuidVersionInfoEdx.Bits.MTRR  &n= bsp;            = ;       =3D SystemParameter->MtrrSupported= ;
> 
> +  mCpuidVirPhyAddressSizeEax.Bits.PhysicalAddressBits= =3D SystemParameter->PhysicalAddressBits;
> 
> +
> 
>= ; +  //
> =
> +  // Hook BaseLib functions used by MtrrLi= b that require some emulation.
> 
> +  //
><= span class=3D"Apple-converted-space"> 

> +&nbs= p; gUnitTestHostBaseLib.X86->AsmCpuid      =3D = UnitTestMtrrLibAsmCpuid;
> 
> +  gUnitTestHostBaseLib.X86->= ;AsmReadMsr64  =3D UnitTestMtrrLibAsmReadMsr64;
> 

> +  = gUnitTestHostBaseLib.X86->AsmWriteMsr64 =3D UnitTestMtrrLibAsmWriteMsr64= ;
> 
> +
>&= nbsp;
> +  return UNIT_TEST_PASSED;
> 
> +}
> 
> +
> 
> +/**
> 
> +  Initia= lize the MTRR registers.
> 
> +
> 
> +  @param Conte= xt System parameter that controls the MTRR registers initialization.
> 
> +**/
> =
> +UNIT_TEST_STATUS
> 
> +EFIAPI
> 
> +InitializeSystem (
> 
> +  IN UNIT_TEST_CONTEXT = ;       Context
> 
> +  )
> 
> +{
>&nbs= p;
> +  return InitializeMtrrRegs ((MTRR_LIB_S= YSTEM_PARAMETER *) Context);
> 
> +}
> 
> +
> 
>= ; +/**
> 
> +  Collect the test result.
> 

> +
> 
> +  @param DefaultType      &= nbsp;   Default memory type.
> 
> +  @param Physica= lAddressBits  Physical address bits.
> 
> +  @param Vari= ableMtrrCount    Count of variable MTRRs.
>=  
> +&nb= sp; @param Mtrrs          = ;      MTRR settings to collect from.
> 
>= ; +  @param Ranges        &nbs= p;      Return the memory ranges.
&g= t; 
> +&= nbsp; @param RangeCount        &nbs= p;  Return the count of memory ranges.
> 
> +  @param= MtrrCount           = ; Return the count of variable MTRRs being used.
> 
> +**/
> 
> +VOID
> =
> +CollectTestResult (
> 
> +  IN&nb= sp;    MTRR_MEMORY_CACHE_TYPE DefaultType,
>= ; 
> +&n= bsp; IN     UINT32      &= nbsp;          PhysicalAddress= Bits,
> =
> +  IN     UINT32  &n= bsp;            = ;  VariableMtrrCount,
> 
> +  IN    = MTRR_SETTINGS          *Mtrrs= ,
> 
> +  OUT    MTRR_MEMORY_RANGE  =     *Ranges,
> 
> +  IN OUT UINTN  &= nbsp;           &nbs= p;   *RangeCount,
> 
> +  OUT    UIN= T32            =      *MtrrCount
> 
> +  )
&= gt; 
> += {
> 
> +  UINTN       &nbs= p;     Index;
> 
> +  UINT64  &= nbsp;         MtrrValidBitsMask;> 
> +  UINT64        &= nbsp;   MtrrValidAddressMask;
> 
> +  MTRR_MEMORY_R= ANGE RawMemoryRanges[ARRAY_SIZE (Mtrrs->Variables.Mtrr)];
= > 
> = +
> 
> +  ASSERT (Mtrrs !=3D NULL);
> 
> +  ASS= ERT (VariableMtrrCount <=3D ARRAY_SIZE (Mtrrs->Variables.Mtrr));
> 
> +
> = ;
> +  MtrrValidBitsMask =3D (1ull << Ph= ysicalAddressBits) - 1;
> 
> +  MtrrValidAddressMask =3D Mtrr= ValidBitsMask & ~0xFFFull;
> 
> +
> 
> +  *MtrrC= ount =3D 0;
> <= /span>
> +  for (Index =3D 0; Index < VariableMtrr= Count; Index++) {
>&= nbsp;
> +    if (((MSR_IA32_MTRR_PHY= SMASK_REGISTER *) &Mtrrs->Variables.Mtrr[Index].Mask)->Bits.V =3D= = =3D 1) {
> 
> +      RawMemoryRanges[*Mt= rrCount].BaseAddress =3D Mtrrs->Variables.Mtrr[Index].Base & MtrrVal= idAddressMask;
>&nbs= p;
> +      RawMemoryRange= s[*MtrrCount].Type        =3D
> 
> +        ((MSR_IA32_MTRR_PHYSBASE= _REGISTER *) &Mtrrs->Variables.Mtrr[Index].Base)->Bits.Type;
> 
> +      RawMemoryRanges[*MtrrCount].Len= gth      =3D
> 
> +   &nbs= p;      ((~(Mtrrs->Variables.Mtrr[Index].Mask &= amp; MtrrValidAddressMask)) & MtrrValidBitsMask) + 1;
>= ; 
> +&n= bsp;     (*MtrrCount)++;
> 
> +  &= nbsp; }
> 
> +  }
> 
> +
> 
> +  GetEf= fectiveMemoryRanges (DefaultType, PhysicalAddressBits, RawMemoryRanges, *Mt= rrCount, Ranges, RangeCount);
> 
> +}
> 
> +
> 
>= ; +/**
> 
> +  Return a 32bit random number.
&g= t; 
> +<= br class=3D"">> 
> +  @param Start  Start of the random number range.<= br class=3D"">> 
> +  @param Limit  Limit of the random number range.<= br class=3D"">> 
> +  @return 32bit random number
> 
> +**/
> 
> +UINT32
>&nb= sp;
> +Random32 (
> 
> +  UINT32 = ; Start,
> 
> +  UINT32  Limit
> 
> +  )> 
> +{
>&nb= sp;
> +  return (UINT32) (((double) rand () / = RAND_MAX) * (Limit - Start)) + Start;
> 
> +}
> 

> +
> 
> +/**
>&n= bsp;
> +  Return a 64bit random number.
> 
> +
> 
> +  @param Start  Start of the random numb= er range.
> 
> +  @param Limit  Limit of the random numb= er range.
> 
> +  @return 64bit random number
&= gt; 
> += **/
> > +UINT64
> 
> +Random64 (
> 

> +  U= INT64  Start,
>=  
> +  UINT64  Limit
&= gt; 
> +=   )
> 
> +{
> 
> +  return (UINT64) (((double) = rand () / RAND_MAX) * (Limit - Start)) + Start;
> 
> +}
> 
> +
> 
> +/**
> 
> +  Generate random MTRR BASE= /MASK for a specified type.
> 
> +
> 
> +  @param= PhysicalAddressBits Physical address bits.
> 
> +  @param= CacheType           Cach= e type.
> 
> +  @param MtrrPair     =        Return the random MTRR.
= > 
> = +  @param MtrrMemoryRange     Return the random me= mory range.
> <= /span>
> +**/
> 
> +VOID
> 
> +GenerateR= andomMtrrPair (
>&nb= sp;
> +  IN  UINT32   &nbs= p;             = PhysicalAddressBits,
> 
> +  IN  MTRR_MEMORY_CACHE_TYPE = CacheType,
> 
> +  OUT MTRR_VARIABLE_SETTING  *MtrrPair,=        OPTIONAL
> 
> +  OUT MT= RR_MEMORY_RANGE      *MtrrMemoryRange OPTIONAL
> 
> +  )
> 
> +{
> 
> +  MSR_IA32_MTRR_= PHYSBASE_REGISTER PhysBase;
> 
> +  MSR_IA32_MTRR_PHYSMASK_RE= GISTER PhysMask;
>&n= bsp;
> +  UINT32     =             &nb= sp;        SizeShift;
>=  
> +&nb= sp; UINT32           = ;            &n= bsp;  BaseShift;
> 
> +  UINT64    &= nbsp;           &nbs= p;         RandomBoundary;
> 
> +  UINT64         =             &nb= sp;    MaxPhysicalAddress;
> 
> +  UINT64 = ;            &n= bsp;            Rang= eSize;
> 
> +  UINT64      &nbs= p;            &= nbsp;      RangeBase;
> 
> +  UINT64=             &nb= sp;            = PhysBasePhyMaskValidBitsMask;
> 
> +
> 
> +  MaxPhy= sicalAddress =3D 1ull << PhysicalAddressBits;
> 

> +  d= o {
> > +    SizeShift =3D Random32 (12, PhysicalA= ddressBits - 1);
>&n= bsp;
> +    RangeSize =3D 1ull <&= lt; SizeShift;
>&nbs= p;
> +
> 
> +    BaseShift = = =3D Random32 (SizeShift, PhysicalAddressBits - 1);
> 

> + &n= bsp;  RandomBoundary =3D Random64 (0, 1ull << (PhysicalAddressBi= ts - BaseShift));
>&= nbsp;
> +    RangeBase =3D RandomBou= ndary << BaseShift;
> 
> +  } while (RangeBase < SIZ= E_1MB || RangeBase > MaxPhysicalAddress - 1);
> 
> +
> 
> +  PhysBasePhyMaskValidBitsMask =3D (MaxPhysicalAddress - 1) &a= mp; 0xfffffffffffff000ULL;
> 
> +
> 
> +  PhysBase.U= int64    =3D 0;
> 
> +  PhysBase.Bits.Type =3D= CacheType;
> <= /span>
> +  PhysBase.Uint64   |=3D RangeBas= e & PhysBasePhyMaskValidBitsMask;
> 
> +  PhysMask.Uint64=     =3D 0;
> 
> +  PhysMask.Bits.V  =   =3D 1;
> = ;
> +  PhysMask.Uint64   |=3D ((~Ran= geSize) + 1) & PhysBasePhyMaskValidBitsMask;
> 
> +
> 
> +  if (MtrrPair !=3D NULL) {
> 
> +    = MtrrPair->Base =3D PhysBase.Uint64;
> 
> +    Mt= rrPair->Mask =3D PhysMask.Uint64;
> 
> +  }
= > 
> = +
> 
> +  if (MtrrMemoryRange !=3D NULL) {
>=  
> +&nb= sp;   MtrrMemoryRange->BaseAddress =3D RangeBase;
> 
>= ; +    MtrrMemoryRange->Length    &nb= sp; =3D RangeSize;
>=  
> +    MtrrMemoryRange->Ty= pe        =3D CacheType;
&= gt; 
> +=   }
> 
> +}
> 
> +
> 
> +
>= ; 
> +/*= *
> 
> +  Check whether the Range overlaps with any one in Ra= nges.
> =
> +
> 
> +  @param Range  The memory r= ange to check.
>&nbs= p;
> +  @param Ranges The memory ranges.
> 
> +  @param Count  Count of memory ranges.
> 
>= ; +
> > +  @return TRUE when overlap exists.
&= gt; 
> += **/
> > +BOOLEAN
> 
> +RangesOverlap (
>= ; 
> +&n= bsp; IN MTRR_MEMORY_RANGE *Range,
> 
> +  IN MTRR_MEMORY_RANG= E *Ranges,
> 
> +  IN UINTN     &nbs= p;       Count
> 
> +  )
> 
> +{
>&nbs= p;
> +  while (Count-- !=3D 0) {
> 
>= +    //
> 
> +    // Two ranges ove= rlap when:
> 
> +    // 1. range#2.base is in the m= iddle of range#1
>&n= bsp;
> +    // 2. range#1.base is in= the middle of range#2
> 
> +    //
&= gt; 
> +=     if ((Range->BaseAddress <=3D Ranges[Count].BaseAdd= ress && Ranges[Count].BaseAddress < Range->BaseAddress + Rang= e->Length)
> = ;
> +     || (Ranges[Count].Bas= eAddress <=3D Range->BaseAddress && Range->BaseAddress <= ; Ranges[Count].BaseAddress + Ranges[Count].Length)) {
> 

> + = ;     return TRUE;
> 
> +    }<= br class=3D"">> 
> +  }
> 
> +  return FALSE;
&= gt; 
> += }
> 
> +
>&= nbsp;
> +/**
> 
> +  Generate random = MTRRs.
> 
> +
> 
> +  @param PhysicalAddressBits&nbs= p; Physical address bits.
> 
> +  @param RawMemoryRanges = ;     Return the randomly generated MTRRs.
> 
>= ; +  @param UcCount        &nb= sp;     Count of Uncacheable MTRRs.
><= span class=3D"Apple-converted-space"> 

> +&nbs= p; @param WtCount         &nbs= p;    Count of Write Through MTRRs.
> 
> +  @p= aram WbCount          &nb= sp;   Count of Write Back MTRRs.
> 
> +  @param WpC= ount            = ;  Count of Write Protected MTRRs.
> 
> +  @param WcCoun= t            &n= bsp; Count of Write Combine MTRRs.
> 
> +**/
> 

> +VOID> 
> +GenerateValidAndConfigurableMtrrPairs (
> 

> + = IN     UINT32       = ;             P= hysicalAddressBits,
> 
> +  IN OUT MTRR_MEMORY_RANGE &nb= sp;       *RawMemoryRanges,
>= ; 
> +&n= bsp; IN     UINT32      &= nbsp;           &nbs= p; UcCount,
> <= /span>
> +  IN     UINT32 &n= bsp;            = ;      WtCount,
> 
> +  IN &nbs= p;   UINT32         =            WbCount,
> 
> +  IN     UINT32   &nbs= p;            &= nbsp;   WpCount,
> 
> +  IN    = UINT32           &n= bsp;        WcCount
> 

> + = ; )
> > +{
> 
> +  UINT32    &n= bsp;            = ;         Index;
>=  
> +> 
> +  //
> 
> +  // 1. Generate UC, WT, WB in o= rder.
> =
> +  //
> 
> +  for (Index =3D 0; Inde= x < UcCount; Index++) {
> 
> +    GenerateRandom= MtrrPair (PhysicalAddressBits, CacheUncacheable, NULL, &RawMemoryRanges= [Index]);
> 
> +  }
> 
> +
> 
> +  for= (Index =3D UcCount; Index < UcCount + WtCount; Index++) {
> 
>= +    GenerateRandomMtrrPair (PhysicalAddressBits, CacheWrit= eThrough, NULL, &RawMemoryRanges[Index]);
> 
> +  }
> 
> +
> = ;
> +  for (Index =3D UcCount + WtCount; Index= < UcCount + WtCount + WbCount; Index++) {
> 
> +  &= nbsp; GenerateRandomMtrrPair (PhysicalAddressBits, CacheWriteBack, NULL, &a= mp;RawMemoryRanges[Index]);
> 
> +  }
> 

> +
> 
> +  //
>&= nbsp;
> +  // 2. Generate WP MTRR and DO NOT o= verlap with WT, WB.
> 
> +  //
> 
> +  for (I= ndex =3D UcCount + WtCount + WbCount; Index < UcCount + WtCount + WbCoun= t + WpCount; Index++) {
> 
> +    GenerateRandomMtr= rPair (PhysicalAddressBits, CacheWriteProtected, NULL, &RawMemoryRanges= [Index]);
> 
> +    while (RangesOverlap (&RawM= emoryRanges[Index], &RawMemoryRanges[UcCount], WtCount + WbCount)) {> 
> +      GenerateRandomMtrrPair (Physica= lAddressBits, CacheWriteProtected, NULL, &RawMemoryRanges[Index]);
> 
> +    }
> 
> +  }
>= ; 
> +> 
> +  //
> 
> +  // 3. Generate WC MTRR and DO= NOT overlap with WT, WB, WP.
> 
> +  //
> 

> + = ; for (Index =3D UcCount + WtCount + WbCount + WpCount; Index < UcCount = + WtCount + WbCount + WpCount + WcCount; Index++) {
> 

> + &n= bsp;  GenerateRandomMtrrPair (PhysicalAddressBits, CacheWriteCombining= , NULL, &RawMemoryRanges[Index]);
> 
> +    whi= le (RangesOverlap (&RawMemoryRanges[Index], &RawMemoryRanges[UcCoun= t], WtCount + WbCount + WpCount)) {
> 
> +    =   GenerateRandomMtrrPair (PhysicalAddressBits, CacheWriteCombining, NU= LL, &RawMemoryRanges[Index]);
> 
> +    }
> 
> +  }
> 
> +}
> 
> +
> 

> +/**> 
> +  Return a random memory cache type.
><= span class=3D"Apple-converted-space"> 

> +**/<= br class=3D"">> 
> +MTRR_MEMORY_CACHE_TYPE
> 
> +GenerateRandomCacheTyp= e (
> > +  VOID
> 
> +  )
> 

> +{
> 
> +    return mMemoryCacheTypes[Random32 (0, ARRAY= _SIZE (mMemoryCacheTypes) - 1)];
> 
> +}
> 
> +
> 
> +/**
> <= /span>
> +  Compare function used by qsort().
> 
> +**/
> <= /span>
> +
> 
> +/**
> 
> +  Compar= e function used by qsort().
> 
> +
> 
> +  @param= Left   Left operand to compare.
> 
> +  @param Rig= ht  Right operand to compare.
> 
> +
> 
> +  @r= etval 0  Left =3D=3D Right
> 
> +  @retval -1 Left < = Right
> =
> +  @retval 1  Left > Right
&= gt; 
> += **/
> > +INT32
> 
> +CompareFuncUint64 (
&= gt; 
> +=   CONST VOID * Left,
> 
> +  CONST VOID * Right
> 
> +  )
>&n= bsp;
> +{
> 
> +    INT64 D= elta;
> =
> +    Delta =3D (*(UINT64*)Left - *(UINT6= 4*)Right);
> 
> +    if (Delta > 0) {
> 
> +      return 1;
> 
> +  = ;  } else if (Delta =3D=3D 0) {
> 
> +    = ;  return 0;
>&= nbsp;
> +    } else {
= > 
> = +      return -1;
> 
> +   = ; }
> > +}
> 
> +
> 
> +/**
><= span class=3D"Apple-converted-space"> 

> +&nbs= p; Determin the memory cache type for the Range.
> 
> +
> 
> +  @param DefaultType Default cache type.
> 

> + = @param Range       The memory range to deter= min the cache type.
> 
> +  @param Ranges   &n= bsp;  The entire memory ranges.
> 
> +  @param RangeCoun= t  Count of the entire memory ranges.
> 
> +**/
> 
>= +VOID
> 
> +DetermineMemoryCacheType (
> 
> +  IN&n= bsp;    MTRR_MEMORY_CACHE_TYPE DefaultType,
&g= t; 
> +&= nbsp; IN OUT MTRR_MEMORY_RANGE      *Range,
> 
> +  IN     MTRR_MEMORY_RANGE  &nb= sp;   *Ranges,
> 
> +  IN     U= INT32           &nbs= p;     RangeCount
> 
> +  )
> 
>= +{
> > +  UINT32 Index;
> 
> +  Range->Typ= e =3D CacheInvalid;
> 
> +  for (Index =3D 0; Index < Rang= eCount; Index++) {
>=  
> +    if (RangesOverlap (Ran= ge, &Ranges[Index], 1)) {
> 
> +     = if (Ranges[Index].Type < Range->Type) {
> 
> +  &= nbsp;     Range->Type =3D Ranges[Index].Type;
> 
> +      }
> 
> +   = }
> > +  }
> 
> +
> 
> +  if (Range-= >Type =3D=3D CacheInvalid) {
> 
> +    Range->= ;Type =3D DefaultType;
> 
> +  }
> 
> +}
> 
&g= t; +
> <= br class=3D"">> +/**
> 
> +  Get the index of the element = that does NOT equals to Array[Index].
> 
> +
> 

> + = @param Index   Current element.
> 
> +  @param Arr= ay   Array to scan.
> 
> +  @param Count  = ; Count of the array.
> 
> +
> 
> +  @return Next el= ement that doesn't equal to current one.
> 
> +**/
&= gt; 
> += UINT32
> 
> +GetNextDifferentElementInSortedArray (
= > 
> = +  IN UINT32 Index,
> 
> +  IN UINT64 *Array,
> 
> +  IN UINT32 Count
> 
> +  )
> 

> +{
> 
> +  UINT64 CurrentElement;
> 
> +  CurrentEle= ment =3D Array[Index];
> 
> +  while (CurrentElement =3D=3D A= rray[Index] && Index < Count) {
> 
> +   = ; Index++;
> 
> +  }
> 
> +  return Index;
> 
> +}
>&nbs= p;
> +
> 
> +/**
> 
> +  Rem= ove the duplicates from the array.
> 
> +
> 
> +  @p= aram Array  The array to operate on.
> 
> +  @param Coun= t  Count of the array.
> 
> +**/
> 
> +VOID
> 
> +RemoveDuplicatesInSortedArray (
> 
> +  IN OUT UINT64= *Array,
> 
> +  IN OUT UINT32 *Count
> 

> +  )=
> 
> +{
>&= nbsp;
> +  UINT32 Index;
> 

> + = UINT32 NewCount;
>&= nbsp;
> +
> 
> +  Index  &n= bsp; =3D 0;
> <= /span>
> +  NewCount =3D 0;
> 
> +  whi= le (Index < *Count) {
> 
> +    Array[NewCount] = = =3D Array[Index];
>=  
> +    NewCount++;
> 
> +    Index =3D GetNextDifferentElementInSortedArray (= Index, Array, *Count);
> 
> +  }
> 
> +  *Count= =3D NewCount;
>&nbs= p;
> +}
> 
> +
> 
> +/**
> 
> +  Return TRUE when Address is in the Range.
>=  
> +> 
> +  @param Address The address to check.
>=  
> +&nb= sp; @param Range   The range to check.
> 
> +  @ret= urn TRUE when Address is in the Range.
> 
> +**/
>= ; 
> +BO= OLEAN
> =
> +AddressInRange (
> 
> +  IN UINT64 =            Address,
> 
> +  IN MTRR_MEMORY_RANGE Range
> 
> +  )
> 
> +{
>&nbs= p;
> +    return (Address >=3D Ra= nge.BaseAddress) && (Address <=3D Range.BaseAddress + Range.Leng= th - 1);
> 
> +}
> 
> +
> 
> +/**
= > 
> = +  Get the overlap bit flag.
> 
> +
> 
> +  @pa= ram RawMemoryRanges     Raw memory ranges.
> 
>= ; +  @param RawMemoryRangeCount Count of raw memory ranges.
> 
> +  @param Address       &nbs= p;     The address to check.
> 
> +**/
> 
> +UINT64
>&nbs= p;
> +GetOverlapBitFlag (
> 
> +  IN = MTRR_MEMORY_RANGE *RawMemoryRanges,
> 
> +  IN UINT32 &n= bsp;          RawMemoryRangeCo= unt,
> <= br class=3D"">> +  IN UINT64      &nb= sp;     Address
> 
> +  )
&= gt; 
> += {
> 
> +  UINT64 OverlapBitFlag;
> 
> +  UINT32= Index;
> 
> +  OverlapBitFlag =3D 0;
> 

> +  f= or (Index =3D 0; Index < RawMemoryRangeCount; Index++) {
&= gt; 
> +=     if (AddressInRange (Address, RawMemoryRanges[Index])) {<= br class=3D"">> 
> +      OverlapBitFlag |=3D (1ull <= ;< Index);
> = ;
> +    }
> 
> +  }> 
> +
>&nbs= p;
> +  return OverlapBitFlag;
&= gt; 
> += }
> 
> +
>&= nbsp;
> +/**
> 
> +  Return the relat= ionship between flags.
> 
> +
> 
> +  @param Flag1 F= lag 1
> =
> +  @param Flag2 Flag 2
> 
> +
> 
&g= t; +  @retval 0   Flag1 =3D=3D Flag2
> 

> +  @= retval 1   Flag1 is a subset of Flag2
> 
> +  @retv= al 2   Flag2 is a subset of Flag1
> 
> +  @retva= l 3   No subset relations between Flag1 and Flag2.
= > 
> = +**/
> <= br class=3D"">> +UINT32
> 
> +CheckOverlapBitFlagsRelation (> 
> +  IN UINT64 Flag1,
> 
> +  IN UINT64 Flag2<= br class=3D"">> 
> +  )
> 
> +{
> 
> +    = if (Flag1 =3D=3D Flag2) return 0;
> 
> +    if ((Fl= ag1 | Flag2) =3D=3D Flag2) return 1;
> 
> +    if (= (Flag1 | Flag2) =3D=3D Flag1) return 2;
> 
> +    r= eturn 3;
> 
> +}
> 
> +
> 
> +/**
= > 
> = +  Return TRUE when the Endpoint is in any of the Ranges.
> 
>= ; +
> > +  @param Endpoint    The endpoint to= check.
> 
> +  @param Ranges      T= he memory ranges.
>&= nbsp;
> +  @param RangeCount  Count of me= mory ranges.
> =
> +
> 
> +  @retval TRUE  Endpo= int is in one of the range.
> 
> +  @retval FALSE Endpoint is= not in any of the ranges.
> 
> +**/
> 
> +BOOLEAN
> 
> +IsEndpointInRanges (
> 
> +  IN UINT64 &nbs= p;          Endpoint,
> 
> +  IN MTRR_MEMORY_RANGE *Ranges,
> 
> +  IN UIN= TN             = RangeCount
> 
> +  )
> 
> +{
> 

> + &n= bsp;  UINT32 Index;
> 
> +    for (Index =3D 0= ; Index < RangeCount; Index++) {
> 
> +    =   if (AddressInRange (Endpoint, Ranges[Index])) {
> 

> + = ;       return TRUE;
> 
> + &nb= sp;    }
> 
> +    }
&= gt; 
> +=     return FALSE;
> 
> +}
> 
> +
> 
> +
> 
> +/**
> 
> +  Compact adjacent ranges o= f the same type.
>&n= bsp;
> +
> 
> +  @param DefaultType&n= bsp;            = ;       Default memory type.
&g= t; 
> +&= nbsp; @param PhysicalAddressBits       &= nbsp;    Physical address bits.
> 
> +  @param= EffectiveMtrrMemoryRanges      Memory ranges to c= ompact.
> 
> +  @param EffectiveMtrrMemoryRangesCount Return = the new count of memory ranges.
> 
> +**/
> 
> +VOID
> 
> +CompactAndExtendEffectiveMtrrMemoryRanges (
>=  
> +&nb= sp; IN     MTRR_MEMORY_CACHE_TYPE DefaultType,
> 
> +  IN     UINT32    &nb= sp;            Physi= calAddressBits,
>&nb= sp;
> +  IN OUT MTRR_MEMORY_RANGE  &= nbsp;   **EffectiveMtrrMemoryRanges,
> 
> +  IN OUT= UINTN           &nb= sp;      *EffectiveMtrrMemoryRangesCount
> 
> +  )
>&n= bsp;
> +{
> 
> +  UINT64  &= nbsp;           &nbs= p;         MaxAddress;
> 
>= ; +  UINTN          =             &nb= sp;  NewRangesCountAtMost;
> 
> +  MTRR_MEMORY_RANGE&nbs= p;            *NewRa= nges;
> =
> +  UINTN       =             &nb= sp;     NewRangesCountActual;
> 
> +  MTR= R_MEMORY_RANGE          &= nbsp;  *CurrentRangeInNewRanges;
> 
> +  MTRR_MEMORY_CAC= HE_TYPE        CurrentRangeTypeInOldRang= es;
> > +
> 
> +  MTRR_MEMORY_RANGE  &nbs= p;          *OldRanges;
> 
> +  MTRR_MEMORY_RANGE       =       OldLastRange;
> 
> +  UINTN&= nbsp;           &nbs= p;            OldRan= gesIndex;
> 
> +
> 
> +  NewRangesCountActual =3D 0;=
> 
> +  NewRangesCountAtMost =3D *EffectiveMtrrMemoryRangesC= ount + 2;   // At most with 2 more range entries.
&= gt; 
> +=   NewRanges          = ;  =3D (MTRR_MEMORY_RANGE *) calloc (NewRangesCountAtMost, sizeof (MTR= R_MEMORY_RANGE));
>&= nbsp;
> +  OldRanges    &n= bsp;       =3D *EffectiveMtrrMemoryRanges;> 
> +  if (OldRanges[0].BaseAddress > 0) {
&g= t; 
> +&= nbsp;   NewRanges[NewRangesCountActual].BaseAddress =3D 0;
> 
> +    NewRanges[NewRangesCountActual].Length &nb= sp;    =3D OldRanges[0].BaseAddress;
> 

> + &n= bsp;  NewRanges[NewRangesCountActual].Type    &nbs= p;   =3D DefaultType;
> 
> +    NewRanges= CountActual++;
>&nbs= p;
> +  }
> 
> +
> 

> + = ; OldRangesIndex =3D 0;
> 
> +  while (OldRangesIndex < *E= ffectiveMtrrMemoryRangesCount) {
> 
> +    CurrentR= angeTypeInOldRanges =3D OldRanges[OldRangesIndex].Type;
><= span class=3D"Apple-converted-space"> 

> +&nbs= p;   CurrentRangeInNewRanges =3D NULL;
> 
> +  = ;  if (NewRangesCountActual > 0)   // We need to check Cu= rrentNewRange first before generate a new NewRange.
> 

> + &n= bsp;  {
> =
> +      CurrentRangeInNe= wRanges =3D &NewRanges[NewRangesCountActual - 1];
> 

> + =    }
>&nbs= p;
> +    if (CurrentRangeInNewRange= s !=3D NULL && CurrentRangeInNewRanges->Type =3D=3D CurrentRange= TypeInOldRanges) {
>=  
> +      CurrentRan= geInNewRanges->Length +=3D OldRanges[OldRangesIndex].Length;
> 
&g= t; +    } else {
> 
> +    &nbs= p; NewRanges[NewRangesCountActual].BaseAddress =3D OldRanges[OldRangesIndex= ].BaseAddress;
>&nbs= p;
> +      NewRanges[NewR= angesCountActual].Length     +=3D OldRanges[OldRangesIn= dex].Length;
> =
> +      NewRanges[NewRan= gesCountActual].Type        =3D CurrentR= angeTypeInOldRanges;
> 
> +      while (O= ldRangesIndex + 1 < *EffectiveMtrrMemoryRangesCount && OldRanges= [OldRangesIndex + 1].Type =3D=3D CurrentRangeTypeInOldRanges)
> 
>= +      {
> 
> +    &= nbsp;   OldRangesIndex++;
> 
> +    =     NewRanges[NewRangesCountActual].Length +=3D OldRanges[Ol= dRangesIndex].Length;
> 
> +      }
> 
> +      NewRangesCountActual++;
> 
> +    }
> 
> +
> 
> +  &= nbsp; OldRangesIndex++;
> 
> +  }
> 
> +
> 
&g= t; +  MaxAddress =3D (1ull << PhysicalAddressBits) - 1;
> 
> +  OldLastRange =3D OldRanges[(*EffectiveMtrrMemoryRangesCount)= - 1];
> 
> +  CurrentRangeInNewRanges =3D &NewRanges[New= RangesCountActual - 1];
> 
> +  if (OldLastRange.BaseAddress = + OldLastRange.Length - 1 < MaxAddress) {
> 
> +  &= nbsp; if (CurrentRangeInNewRanges->Type =3D=3D DefaultType) {
> 
> +      CurrentRangeInNewRanges->Length = =3D MaxAddress - CurrentRangeInNewRanges->BaseAddress + 1;
> 
>= ; +    } else {
> 
> +     = ; NewRanges[NewRangesCountActual].BaseAddress =3D OldLastRange.BaseAddress = + OldLastRange.Length;
> 
> +      NewRan= ges[NewRangesCountActual].Length =3D MaxAddress - NewRanges[NewRangesCountA= ctual].BaseAddress + 1;
> 
> +      NewRa= nges[NewRangesCountActual].Type =3D DefaultType;
> 
> +  = ;    NewRangesCountActual++;
> 
> +  &= nbsp; }
> 
> +  }
> 
> +
> 
> +  free = (*EffectiveMtrrMemoryRanges);
> 
> +  *EffectiveMtrrMemoryRan= ges =3D NewRanges;
>=  
> +  *EffectiveMtrrMemoryRangesCount = =3D NewRangesCountActual;
> 
> +}
> 
> +
> 
>= ; +/**
> 
> +  Collect all the endpoints in the raw memory ra= nges.
> =
> +
> 
> +  @param Endpoints  &nb= sp;        Return the collected endpoint= s.
> > +  @param EndPointCount     =   Return the count of endpoints.
> 
> +  @param RawMemor= yRanges     Raw memory ranges.
> 
> +  @p= aram RawMemoryRangeCount Count of raw memory ranges.
> 

> +**/
> 
> +VOID
>&= nbsp;
> +CollectEndpoints (
> 

> +  I= N OUT UINT64        *Endpoints,
> 
> +  IN OUT UINT32        *End= PointCount,
> <= /span>
> +  IN MTRR_MEMORY_RANGE *RawMemoryRanges,> 
> +  IN UINT32       &nbs= p;    RawMemoryRangeCount
> 
> +  )
> 
> +{
> 
> +  UINT32 Index;
> 
> +  UINT32= RawRangeIndex;
>&nb= sp;
> +
> 
> +  ASSERT ((RawMemoryRan= geCount << 1) =3D=3D *EndPointCount);
> 
> +
> 
>= ; +  for (Index =3D 0; Index < *EndPointCount; Index +=3D 2) {
> 
> +    RawRangeIndex =3D Index >> 1;
> 
> +    Endpoints[Index] =3D RawMemoryRanges[RawRangeInd= ex].BaseAddress;
>&n= bsp;
> +    Endpoints[Index + 1] =3D= RawMemoryRanges[RawRangeIndex].BaseAddress + RawMemoryRanges[RawRangeIndex= ].Length - 1;
> = ;
> +  }
> 
> +
> 

> + = qsort (Endpoints, *EndPointCount, sizeof (UINT64), CompareFuncUint64);
> 
> +  RemoveDuplicatesInSortedArray (Endpoints, EndPointCount= );
> > +}
> 
> +
> 
> +/**
> 

> + = ; Convert the MTRR BASE/MASK array to memory ranges.
> 

> +
> 
> +  @param DefaultType       = ;   Default memory type.
> 
> +  @param PhysicalAdd= ressBits  Physical address bits.
> 
> +  @param RawMemor= yRanges      Raw memory ranges.
>=  
> +&nb= sp; @param RawMemoryRangeCount  Count of raw memory ranges.
> 
> +  @param MemoryRanges       = ;  Memory ranges.
> 
> +  @param MemoryRangeCount &= nbsp;   Count of memory ranges.
> 
> +**/
= > 
> = +VOID
> =
> +GetEffectiveMemoryRanges (
> 
> +  IN MT= RR_MEMORY_CACHE_TYPE DefaultType,
> 
> +  IN UINT32 &nbs= p;            &= nbsp;  PhysicalAddressBits,
> 
> +  IN MTRR_MEMORY_RANGE=       *RawMemoryRanges,
> 
> +  IN U= INT32           &nbs= p;     RawMemoryRangeCount,
> 
> +  OUT M= TRR_MEMORY_RANGE     *MemoryRanges,
><= span class=3D"Apple-converted-space"> 

> +&nbs= p; OUT UINTN          &nb= sp;      *MemoryRangeCount
> 

> +  )=
> 
> +{
>&= nbsp;
> +  UINTN     =             Index;> 
> +  UINT32        =         AllEndPointsCount;
> 
>= +  UINT64          =       *AllEndPointsInclusive;
> 

> + = ; UINT32           &= nbsp;    AllRangePiecesCountMax;
> 
> +  MTRR_= MEMORY_RANGE     *AllRangePieces;
> 

> + = UINTN           &nb= sp;     AllRangePiecesCountActual;
> 

> + = ; UINT64           &= nbsp;    OverlapBitFlag1;
> 
> +  UINT64 =             &nb= sp;  OverlapBitFlag2;
> 
> +  INT32   &nb= sp;            = OverlapFlagRelation;
> 
> +
> 
> +  if (RawMemoryRa= ngeCount =3D=3D 0) {
> 
> +    MemoryRanges[0].Base= Address =3D 0;
>&nbs= p;
> +    MemoryRanges[0].Length&nbs= p;     =3D (1ull << PhysicalAddressBits);
> 
> +    MemoryRanges[0].Type    &nbs= p;   =3D DefaultType;
> 
> +    *MemoryRa= ngeCount =3D 1;
>&nb= sp;
> +    return;
>= ; 
> +&n= bsp; }
> 
> +
> 
> +  AllEndPointsCount  &= nbsp;      =3D RawMemoryRangeCount << 1;
> 
> +  AllEndPointsInclusive     =3D callo= c (AllEndPointsCount, sizeof (UINT64));
> 
> +  AllRangePiece= sCountMax    =3D RawMemoryRangeCount * 3 + 1;
= > 
> = +  AllRangePieces         = ;   =3D calloc (AllRangePiecesCountMax, sizeof (MTRR_MEMORY_RANGE= ));
> > +  CollectEndpoints (AllEndPointsInclusive, &All= EndPointsCount, RawMemoryRanges, RawMemoryRangeCount);
> 

> +
> 
> +  for (Index =3D 0, AllRangePiecesCountActual =3D 0; Inde= x < AllEndPointsCount - 1; Index++) {
> 
> +    = OverlapBitFlag1 =3D GetOverlapBitFlag (RawMemoryRanges, RawMemoryRangeCount= , AllEndPointsInclusive[Index]);
> 
> +    OverlapB= itFlag2 =3D GetOverlapBitFlag (RawMemoryRanges, RawMemoryRangeCount, AllEnd= PointsInclusive[Index + 1]);
> 
> +    OverlapFlagR= elation =3D CheckOverlapBitFlagsRelation (OverlapBitFlag1, OverlapBitFlag2)= ;
> 
> +    switch (OverlapFlagRelation) {
> 
> +      case 0:   // [1, 2]
> 
> +        AllRangePieces[AllRange= PiecesCountActual].BaseAddress =3D AllEndPointsInclusive[Index];
> 
> +        AllRangePieces[AllRangeP= iecesCountActual].Length      =3D AllEndPointsIncl= usive[Index + 1] - AllEndPointsInclusive[Index] + 1;
> 

> + &= nbsp;      AllRangePiecesCountActual++;
> 
> +        break;
>= ; 
> +&n= bsp;     case 1:   // [1, 2)
&g= t; 
> +&= nbsp;       AllRangePieces[AllRangePiecesCoun= tActual].BaseAddress =3D AllEndPointsInclusive[Index];
> 

> + = ;       AllRangePieces[AllRangePiecesCountAct= ual].Length      =3D (AllEndPointsInclusive[Index = + 1] - 1) - AllEndPointsInclusive[Index] + 1;
> 
> +  &= nbsp;     AllRangePiecesCountActual++;
&g= t; 
> +&= nbsp;       break;
> 
> +  = ;    case 2:   // (1, 2]
> 
> + &nbs= p;      AllRangePieces[AllRangePiecesCountActual].= BaseAddress =3D AllEndPointsInclusive[Index] + 1;
> 
> + &nbs= p;      AllRangePieces[AllRangePiecesCountActual].= Length      =3D AllEndPointsInclusive[Index + 1] -= (AllEndPointsInclusive[Index] + 1) + 1;
> 
> +   &= nbsp;    AllRangePiecesCountActual++;
> 

> +
> 
> +        if (!IsEndpointInRanges= (AllEndPointsInclusive[Index], AllRangePieces, AllRangePiecesCountActual))= {
> > +          Al= lRangePieces[AllRangePiecesCountActual].BaseAddress =3D AllEndPointsInclusi= ve[Index];
> 
> +        &= nbsp; AllRangePieces[AllRangePiecesCountActual].Length   &nb= sp;  =3D 1;
>&n= bsp;
> +       &= nbsp;  AllRangePiecesCountActual++;
> 
> +   &= nbsp;    }
> 
> +     &nbs= p;  break;
>&nb= sp;
> +      case 3: =   // (1, 2)
>&n= bsp;
> +        = AllRangePieces[AllRangePiecesCountActual].BaseAddress =3D AllEndPointsInclu= sive[Index] + 1;
>&n= bsp;
> +        = AllRangePieces[AllRangePiecesCountActual].Length    &nb= sp; =3D (AllEndPointsInclusive[Index + 1] - 1) - (AllEndPointsInclusive[Ind= ex] + 1) + 1;
> = ;
> +        if = (AllRangePieces[AllRangePiecesCountActual].Length =3D=3D 0)   // = Only in case 3 can exists Length=3D0, we should skip such "segment".
> 
> +          break;
> 
> +        AllRangePiecesCount= Actual++;
> 
> +        if (!Is= EndpointInRanges (AllEndPointsInclusive[Index], AllRangePieces, AllRangePie= cesCountActual)) {
>=  
> +       = ;   AllRangePieces[AllRangePiecesCountActual].BaseAddress =3D All= EndPointsInclusive[Index];
> 
> +     &nb= sp;    AllRangePieces[AllRangePiecesCountActual].Length = ;     =3D 1;
> 
> +    &nb= sp;     AllRangePiecesCountActual++;
>=  
> +&nb= sp;       }
> 
> +   =      break;
> 
> +    &nbs= p; default:
> <= /span>
> +        ASSER= T (FALSE);
> 
> +    }
> 
> +  }
> 
> +
> = ;
> +  for (Index =3D 0; Index < AllRangePi= ecesCountActual; Index++) {
> 
> +    DetermineMemo= ryCacheType (DefaultType, &AllRangePieces[Index], RawMemoryRanges, RawM= emoryRangeCount);
>&= nbsp;
> +  }
> 
> +
>= ; 
> +&n= bsp; CompactAndExtendEffectiveMtrrMemoryRanges (DefaultType, PhysicalAddres= sBits, &AllRangePieces, &AllRangePiecesCountActual);
= > 
> = +  ASSERT (*MemoryRangeCount >=3D AllRangePiecesCountActual);
> 
> +  memcpy (MemoryRanges, AllRangePieces, AllRangePiecesCou= ntActual * sizeof (MTRR_MEMORY_RANGE));
> 
> +  *MemoryRangeC= ount =3D AllRangePiecesCountActual;
> 
> +
> 

> +  f= ree (AllEndPointsInclusive);
> 
> +  free (AllRangePieces);> 
> +}
>&nb= sp;
> diff --git a/UefiCpuPkg/Test/UefiCpuPkgHostTe= st.dsc b/UefiCpuPkg/Test/UefiCpuPkgHostTest.dsc
> new file= mode 100644
> index 0000000000..8a5c456830
= > --- /dev/null
> +++ b/UefiCpuPkg/Test/UefiCpuPkgHostT= est.dsc
> @@ -0,0 +1,31 @@
> +## @file> 
> +# UefiCpuPkg DSC file used to build host-based unit tests.
> 
> +#
>&nbs= p;
> +# Copyright (c) 2020, Intel Corporation. All = rights reserved.<BR>
> 
> +# SPDX-License-Identifier: BSD-2-= Clause-Patent
> = ;
> +#
> 
> +##
> 
> +
> 
> +[Defines]
>&= nbsp;
> +  PLATFORM_NAME   &nbs= p;       =3D UefiCpuPkgHostTest
> 
>= +  PLATFORM_GUID         = ;  =3D E00B9599-5B74-4FF7-AB9F-8183FB13B2F9
> 
> +  PLAT= FORM_VERSION        =3D 0.1
> 
>= ; +  DSC_SPECIFICATION       =3D 0x00010= 005
> > +  OUTPUT_DIRECTORY     &nb= sp;  =3D Build/UefiCpuPkg/HostTest
> 
> +  SUPPORTED_ARC= HITECTURES =3D IA32|X64
> 
> +  BUILD_TARGETS  &nbs= p;        =3D NOOPT
> 

> + = ; SKUID_IDENTIFIER        =3D DEFAULT> 
> +
> = ;
> +!include UnitTestFrameworkPkg/UnitTestFramewor= kPkgHost.dsc.inc
>&n= bsp;
> +
> 
> +[LibraryClasses]
> 
> +  MtrrLib|UefiCpuPkg/Library/MtrrLib/MtrrLib.inf
> 
>= +
> > +[PcdsPatchableInModule]
> 
> +  gUefiCpuPkg= TokenSpaceGuid.PcdCpuNumberOfReservedVariableMtrrs|0
> 

> +
> 
> +[Components]
> 
> +  #
> 
> +  # Buil= d HOST_APPLICATION that tests the MtrrLib
> 
> +  #
> 
> +  UefiCpuPkg/Library/MtrrLib/UnitTest/MtrrLibUnitTestHost.inf<= br class=3D"">> 
> diff --git a/UefiCpuPkg/UefiCpuPkg.ci.yaml b/UefiCpuPkg/UefiC= puPkg.ci.yaml
> index 99e460a8b0..4559b40105 100644
> --- a/UefiCpuPkg/UefiCpuPkg.ci.yaml
> +++ b/U= efiCpuPkg/UefiCpuPkg.ci.yaml
> @@ -8,6 +8,10 @@
>       "CompilerPlugin": {
> 
>           "DscPath= ": "UefiCpuPkg.dsc"
> 
>       },> 
> +    ## options defined ci/Plugin/HostUnitTestCo= mpilerPlugin
> =
> +    "HostUnitTestCompilerPlugin"= : {
> > +        "DscPath": "T= est/UefiCpuPkgHostTest.dsc"
> 
> +    },
> 
>       "CharEncodingCheck": {
> 
>           "IgnoreF= iles": []
> 
>       },
> 
>= ; @@ -18,7 +22,9 @@
>      &= nbsp;        "UefiCpuPkg/UefiCpuPkg.dec"=
> 
>           = ],
> >          = ; # For host based unit tests
> 
> -     =    "AcceptableDependencies-HOST_APPLICATION":[],
&g= t; 
> +&= nbsp;       "AcceptableDependencies-HOST_APPL= ICATION":[
> 
> +        &= nbsp;   "UnitTestFrameworkPkg/UnitTestFrameworkPkg.dec"
> 
> +        ],
> 

> &n= bsp;         # For UEFI shell based= apps
> =
>         &n= bsp; "AcceptableDependencies-UEFI_APPLICATION":[],
> 
>  = ;         "IgnoreInf": []
> 
> @@ -30,6 +36,10 @@
>     &= nbsp;         "UefiCpuPkg/ResetVect= or/Vtf0/Vtf0.inf"
>&= nbsp;
>       &n= bsp;   ]
>=  
>       },
> 
> +    "HostUnitTestDscCompleteCheck": {
> 
> +        "IgnoreInf": [""],
> 
> +        "DscPath": "Test/Ue= fiCpuPkgHostTest.dsc"
> 
> +    },
&g= t; 
>&nb= sp;      "GuidCheck": {
> 
>  &= nbsp;        "IgnoreGuidName": ["SecCore= ", "ResetVector"], # Expected duplication for gEfiFirmwareVolumeTopFileGuid=
> 
>           = "IgnoreGuidValue": [],
> 



 

--Apple-Mail=_11383A57-0AF5-436A-87D8-D0FDA9BCE6B2--