From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mga14.intel.com (mga14.intel.com [192.55.52.115]) by mx.groups.io with SMTP id smtpd.web10.6867.1595918210208678598 for ; Mon, 27 Jul 2020 23:36:50 -0700 Authentication-Results: mx.groups.io; dkim=pass header.i=@intel.onmicrosoft.com header.s=selector2-intel-onmicrosoft-com header.b=Vqey62gF; spf=pass (domain: intel.com, ip: 192.55.52.115, mailfrom: eric.dong@intel.com) IronPort-SDR: 5WPDfSOYX1netII8t6nc/pm0MMGOeR+rs9pqpfEimpcBsdKp60rjwlQjr0AcVRDMdHwzyh2IcJ RAsWr3lCnbEA== X-IronPort-AV: E=McAfee;i="6000,8403,9695"; a="150331408" X-IronPort-AV: E=Sophos;i="5.75,405,1589266800"; d="scan'208,217";a="150331408" X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from fmsmga007.fm.intel.com ([10.253.24.52]) by fmsmga103.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 27 Jul 2020 23:36:49 -0700 IronPort-SDR: /XUN7YJDtriemnYOocIDc2WYoHVxKyky6bmPn1Iyi52PpwmRh8HgqzVPNhjfC/gyv01BvtKpjv FTryfXVUhXcA== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.75,405,1589266800"; d="scan'208,217";a="272220689" Received: from orsmsx103.amr.corp.intel.com ([10.22.225.130]) by fmsmga007.fm.intel.com with ESMTP; 27 Jul 2020 23:36:48 -0700 Received: from orsmsx151.amr.corp.intel.com (10.22.226.38) by ORSMSX103.amr.corp.intel.com (10.22.225.130) with Microsoft SMTP Server (TLS) id 14.3.439.0; Mon, 27 Jul 2020 23:36:47 -0700 Received: from ORSEDG002.ED.cps.intel.com (10.7.248.5) by ORSMSX151.amr.corp.intel.com (10.22.226.38) with Microsoft SMTP Server (TLS) id 14.3.439.0; Mon, 27 Jul 2020 23:36:47 -0700 Received: from NAM04-SN1-obe.outbound.protection.outlook.com (104.47.44.53) by edgegateway.intel.com (134.134.137.101) with Microsoft SMTP Server (TLS) id 14.3.439.0; Mon, 27 Jul 2020 23:36:47 -0700 ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=n5TbYhdaH54acQOtrfDRehcqZ98lup9sKg6B2QNuMvmCCjZVo05xNpp6YbBlsxyM33zvkCoEUgbp3IpwxSDPXnHosgOvB6Lszv3saiNvTL1l4hMT3xmFnpBW2S6WBjA2E+vD/2DpoTd70vCN+ZZtsow2izPA26I0JOEfpNSh9a5VeeEZMUS+oqhR05pYuzz4DlB5JdN8WlAmghGn/COKzKYs6w3Fhs9ybKSpY45C4NTpfvwo2gLcwFE9aEEy5v86gcDMOlvMM3/PKJ6Ws5aQtwCpqO7Gu+2KhxqfJbfBs++OTwLPCiVzHgQ6QZN4rayaSVaFe/zDpy//+pxeYkiDFA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector9901; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=hOo/ixmlA/V9YqrSpE8PaDkA+opj3/lyD1t4iY53EOo=; b=bRKcyI8xR6lkL83Iz9YNln5xz46JyYfg2tvRt+sgpq7A3NTcjQS2xw4poc1GYX7TkcjoCrFwrot4NxNvyUVgQ76mnmzPyDlLV94wZYwpLvksQpQeVKuGGmH3HHD7O03IEH6RN1F99QBxVH+hz7bGWjFVM+wfp4cfV+B90yiOr3KSIklEgnEKd0nDM/dwCGbYqkXxlbcoz07NJr7cXgBSMArMnrKuTsX88R9KtUZq8vrjL4GKT9AqH88uGZEzj6DxHw/r0Hf3PxImv04Yal4jsCA60sUYZNYJ0MfxN/e3EcssWlULz8teoHqKx2fM5HNlKzRxr6AlrjKUTwaqTS6ltg== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass smtp.mailfrom=intel.com; dmarc=pass action=none header.from=intel.com; dkim=pass header.d=intel.com; arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=intel.onmicrosoft.com; s=selector2-intel-onmicrosoft-com; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=hOo/ixmlA/V9YqrSpE8PaDkA+opj3/lyD1t4iY53EOo=; b=Vqey62gFPbTk3EBmCQNulzifmljwOgYCgSnZNBpUrhMTfxZhhS6AFwQ9W5KxnCQqQt3Ae0zPQQ618hTxy3bCIuZw3xSl9JegYTbMY88ry7UHZJNPLoUCCvbcOebbCx3ossCmTJ956gEHCQKjcc57pu+BrnoItgSYS06va//4+M8= Received: from DM6PR11MB3274.namprd11.prod.outlook.com (2603:10b6:5:b::26) by DM6PR11MB2922.namprd11.prod.outlook.com (2603:10b6:5:63::15) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.3216.21; Tue, 28 Jul 2020 06:36:42 +0000 Received: from DM6PR11MB3274.namprd11.prod.outlook.com ([fe80::7173:fdb:cfda:5820]) by DM6PR11MB3274.namprd11.prod.outlook.com ([fe80::7173:fdb:cfda:5820%6]) with mapi id 15.20.3216.033; Tue, 28 Jul 2020 06:36:42 +0000 From: "Dong, Eric" To: "Ni, Ray" , "devel@edk2.groups.io" CC: "Kinney, Michael D" , "Shao, Ming" , Laszlo Ersek , Sean Brogan , Bret Barkelew , "Yao, Jiewen" Subject: Re: [edk2-devel] [PATCH v3] UefiCpuPkg/MtrrLib/UnitTest: Add host based unit test Thread-Topic: [edk2-devel] [PATCH v3] UefiCpuPkg/MtrrLib/UnitTest: Add host based unit test Thread-Index: AQHWZIcvCN+cC4kWs0OKOtxYKHGteqkcRvmggABCxCA= Date: Tue, 28 Jul 2020 06:36:41 +0000 Message-ID: References: <1625C9C070741AB7.9177@groups.io> <734D49CCEBEEF84792F5B80ED585239D5C62D380@SHSMSX104.ccr.corp.intel.com> In-Reply-To: <734D49CCEBEEF84792F5B80ED585239D5C62D380@SHSMSX104.ccr.corp.intel.com> Accept-Language: en-US X-MS-Has-Attach: X-MS-TNEF-Correlator: authentication-results: intel.com; dkim=none (message not signed) header.d=none;intel.com; dmarc=none action=none header.from=intel.com; x-originating-ip: [192.102.204.45] x-ms-publictraffictype: Email x-ms-office365-filtering-correlation-id: ffb77213-ee4a-4d67-88b7-08d832c09700 x-ms-traffictypediagnostic: DM6PR11MB2922: x-ld-processed: 46c98d88-e344-4ed4-8496-4ed7712e255d,ExtAddr x-ms-exchange-transport-forked: True x-microsoft-antispam-prvs: x-ms-oob-tlc-oobclassifiers: OLM:9508; x-ms-exchange-senderadcheck: 1 x-microsoft-antispam: BCL:0; x-microsoft-antispam-message-info: DhBQIg0Kuabl7Qkdh142uGXdDdfAasSp7qxmDTGsnsUraBPZOvKmy1GT0QhhziJnsm3xInBX7Now+/Pfn28ptbau+OMVgtwkLKsfY1lENbCktsY5U1ZQmhE+8s5EvzwcDfuNeBdP61F64X3RU2ICWCc05xaoRNdM2ouM7xx+f+mj6MDhW7Ic7bXMvnZkC8plAT0MyKUctm2NaPbBbOwjtm+bjF1JtuANepvMaE3ovN7WZzqYIEkzEI8RAOb2B97bO9pgdSs1ZAoctIioe6XaZ2TcGHpgVl9x0MYQwxKxlVrGrwhEpQGhfvLRjXAwxYD9iOG+DgAeJAYN22KDxF3yealuxRF/pNyxECKDEakT+MP185MSFr+2z3clv3a1bOjlqYfYLBuHlwbs2JtcEQOXrUhtc3qVyFnfo94j3PmVqgPQBpx2+dVNCwUofcg/fofB x-forefront-antispam-report: CIP:255.255.255.255;CTRY:;LANG:en;SCL:1;SRV:;IPV:NLI;SFV:NSPM;H:DM6PR11MB3274.namprd11.prod.outlook.com;PTR:;CAT:NONE;SFTY:;SFS:(4636009)(366004)(346002)(396003)(376002)(136003)(39860400002)(83380400001)(66946007)(66476007)(66556008)(64756008)(66446008)(2906002)(186003)(30864003)(26005)(52536014)(76116006)(33656002)(86362001)(53546011)(45080400002)(6506007)(110136005)(4326008)(5660300002)(8936002)(478600001)(71200400001)(54906003)(9686003)(316002)(107886003)(8676002)(966005)(55016002)(7696005)(579004)(559001)(569008);DIR:OUT;SFP:1102; x-ms-exchange-antispam-messagedata: q40YaQsAvJ0vdZkwl2Ua3cWSajSPx19EEQsX/LQpE/hXTVFJdVN4eB3BUBgn+vLiMHmmGYSNRu4Yu2O7eswcnKKiYFiN6ysunSazdpG6kJ11dmi9zHKON+ugQid6j3O/6DOji/dowxDMtpC2zW2t0yy0q4KLu45IK0r6th+whHvHWoLbJQzmteDC565MGSQqT9UcvEvOWm5FxWeRx/RTwSuaciQznYGC2PQTKrvmLR5/GfjGktTNvgwBxLn2WNufhdpzYct/dBzs3k/BQ+rMQB2Xr6EAvW2dePtWHwWI4fIV4Y95i055Vn/BWArrUAXrQY6Oe9lvTD5JoSOKgW+RUYSgZwJuexU/t9S/HDvyGAP5kyRRIg+Tf2g0FMEcvQzUzd8FVaKd/ADb7XvfduX+Il47fUv91L/dCGjGNzSo30qq1jALevj0nLdO58GlO1QmLkYIJ2x//OMZqwYfkgqVUBNPSRhL5znf6KAaZXxoEGRWhztdh/cRSENSRiOze7Qi MIME-Version: 1.0 X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-AuthSource: DM6PR11MB3274.namprd11.prod.outlook.com X-MS-Exchange-CrossTenant-Network-Message-Id: ffb77213-ee4a-4d67-88b7-08d832c09700 X-MS-Exchange-CrossTenant-originalarrivaltime: 28 Jul 2020 06:36:41.9650 (UTC) X-MS-Exchange-CrossTenant-fromentityheader: Hosted X-MS-Exchange-CrossTenant-id: 46c98d88-e344-4ed4-8496-4ed7712e255d X-MS-Exchange-CrossTenant-mailboxtype: HOSTED X-MS-Exchange-CrossTenant-userprincipalname: s1HLZ4BUUfRC8/yTyf2fFq4s9UWEyLS1MiD1nAkJcWoUyKwDIiJcjgd6YVWUUvp+ZTNZVgQI18em0Ge0IxUuww== X-MS-Exchange-Transport-CrossTenantHeadersStamped: DM6PR11MB2922 Return-Path: eric.dong@intel.com X-OriginatorOrg: intel.com Content-Language: en-US Content-Type: multipart/alternative; boundary="_000_DM6PR11MB327419476918AE28D7FAAE99FE730DM6PR11MB3274namp_" --_000_DM6PR11MB327419476918AE28D7FAAE99FE730DM6PR11MB3274namp_ Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: quoted-printable Reviewed-by: Eric Dong From: Ni, Ray Sent: Tuesday, July 28, 2020 10:41 AM To: devel@edk2.groups.io; Ni, Ray Cc: Kinney, Michael D ; Shao, Ming ; Dong, Eric ; Laszlo Ersek ; Sean Brogan ; Bret Barkelew ; Yao, Jiewen Subject: RE: [edk2-devel] [PATCH v3] UefiCpuPkg/MtrrLib/UnitTest: Add host = based unit test Mike, Eric, Laszlo, Sorry I just found that the v2 patch cannot pass the CI test because the ya= ml file is not updated to allow some modules depend on UnitTestFrameworkPkg= . So, this v3 patch doesn't change the other files but only yaml files compar= ing to v2. I cannot separate the yaml change to a separate patch because that will sti= ll break the CI. But, please just review the yaml part. I guarantee that no changes were mad= e to non-yaml files. I also added the unit test build/run to CI build step, following what MdePk= g/MdeModulePkg did. Thanks, Ray > -----Original Message----- > From: devel@edk2.groups.io > On Behalf Of Ni, Ray > Sent: Tuesday, July 28, 2020 10:30 AM > To: devel@edk2.groups.io > Cc: Kinney, Michael D >; Shao, Ming >;= Dong, Eric > >; Laszlo Ersek >; Sean Brogan >; Bret Barkelew > >; Yao, J= iewen > > Subject: [edk2-devel] [PATCH v3] UefiCpuPkg/MtrrLib/UnitTest: Add host ba= sed unit test > > Add host based unit tests for the MtrrLib services. > The BaseLib services AsmCpuid(), AsmReadMsr64(), and > AsmWriteMsr64() are hooked and provide simple emulation > of the CPUID leafs and MSRs required by the MtrrLib to > run as a host based unit test. > > Test cases are developed for each of the API. > > For the most important APIs MtrrSetMemoryAttributesInMtrrSettings() > and MtrrSetMemoryAttributeInMtrrSettings(), random inputs are > generated and fed to the APIs to make sure the implementation is > good. The test application accepts an optional parameter which > specifies how many iterations of feeding random inputs to the two > APIs. The overall number of test cases increases when the iteration > increases. Default iteration is 10 when no parameter is specified. > > Signed-off-by: Ray Ni > > 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 | 1140 +++++++++++++++++ > .../MtrrLib/UnitTest/MtrrLibUnitTest.h | 171 +++ > .../MtrrLib/UnitTest/MtrrLibUnitTestHost.inf | 39 + > UefiCpuPkg/Library/MtrrLib/UnitTest/Support.c | 913 +++++++++++++ > UefiCpuPkg/Test/UefiCpuPkgHostTest.dsc | 31 + > UefiCpuPkg/UefiCpuPkg.ci.yaml | 12 +- > 6 files changed, 2305 insertions(+), 1 deletion(-) > create mode 100644 UefiCpuPkg/Library/MtrrLib/UnitTest/MtrrLibUnitTest.c > create mode 100644 UefiCpuPkg/Library/MtrrLib/UnitTest/MtrrLibUnitTest.h > create mode 100644 UefiCpuPkg/Library/MtrrLib/UnitTest/MtrrLibUnitTestHo= st.inf > create mode 100644 UefiCpuPkg/Library/MtrrLib/UnitTest/Support.c > create mode 100644 UefiCpuPkg/Test/UefiCpuPkgHostTest.dsc > > diff --git a/UefiCpuPkg/Library/MtrrLib/UnitTest/MtrrLibUnitTest.c > b/UefiCpuPkg/Library/MtrrLib/UnitTest/MtrrLibUnitTest.c > new file mode 100644 > index 0000000000..2eac41fc74 > --- /dev/null > +++ b/UefiCpuPkg/Library/MtrrLib/UnitTest/MtrrLibUnitTest.c > @@ -0,0 +1,1140 @@ > +/** @file > > + Unit tests of the MtrrLib instance of the MtrrLib class > > + > > + Copyright (c) 2020, Intel Corporation. All rights reserved.
> > + SPDX-License-Identifier: BSD-2-Clause-Patent > > + > > +**/ > > + > > +#include "MtrrLibUnitTest.h" > > + > > +STATIC CONST MTRR_LIB_SYSTEM_PARAMETER mDefaultSystemParameter =3D { > > + 42, TRUE, TRUE, CacheUncacheable, 12 > > +}; > > + > > +STATIC MTRR_LIB_SYSTEM_PARAMETER mSystemParameters[] =3D { > > + { 38, TRUE, TRUE, CacheUncacheable, 12 }, > > + { 38, TRUE, TRUE, CacheWriteBack, 12 }, > > + { 38, TRUE, TRUE, CacheWriteThrough, 12 }, > > + { 38, TRUE, TRUE, CacheWriteProtected, 12 }, > > + { 38, TRUE, TRUE, CacheWriteCombining, 12 }, > > + > > + { 42, TRUE, TRUE, CacheUncacheable, 12 }, > > + { 42, TRUE, TRUE, CacheWriteBack, 12 }, > > + { 42, TRUE, TRUE, CacheWriteThrough, 12 }, > > + { 42, TRUE, TRUE, CacheWriteProtected, 12 }, > > + { 42, TRUE, TRUE, CacheWriteCombining, 12 }, > > + > > + { 48, TRUE, TRUE, CacheUncacheable, 12 }, > > + { 48, TRUE, TRUE, CacheWriteBack, 12 }, > > + { 48, TRUE, TRUE, CacheWriteThrough, 12 }, > > + { 48, TRUE, TRUE, CacheWriteProtected, 12 }, > > + { 48, TRUE, TRUE, CacheWriteCombining, 12 }, > > +}; > > + > > +UINT32 mFixedMtrrsIndex[] =3D { > > + MSR_IA32_MTRR_FIX64K_00000, > > + MSR_IA32_MTRR_FIX16K_80000, > > + MSR_IA32_MTRR_FIX16K_A0000, > > + MSR_IA32_MTRR_FIX4K_C0000, > > + MSR_IA32_MTRR_FIX4K_C8000, > > + MSR_IA32_MTRR_FIX4K_D0000, > > + MSR_IA32_MTRR_FIX4K_D8000, > > + MSR_IA32_MTRR_FIX4K_E0000, > > + MSR_IA32_MTRR_FIX4K_E8000, > > + MSR_IA32_MTRR_FIX4K_F0000, > > + MSR_IA32_MTRR_FIX4K_F8000 > > +}; > > +STATIC_ASSERT ( > > + (ARRAY_SIZE (mFixedMtrrsIndex) =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. > > +// > > +typedef struct { > > + CONST MTRR_LIB_SYSTEM_PARAMETER *SystemParameter; > > +} MTRR_LIB_TEST_CONTEXT; > > + > > +// > > +// Context structure to be used for GetFirmwareVariableMtrrCount() test. > > +// > > +typedef struct { > > + UINT32 NumberOfReservedVariableMtrrs; > > + CONST MTRR_LIB_SYSTEM_PARAMETER *SystemParameter; > > +} MTRR_LIB_GET_FIRMWARE_VARIABLE_MTRR_COUNT_CONTEXT; > > + > > +STATIC CHAR8 *mCacheDescription[] =3D { "UC", "WC", "N/A", "N/A", "WT", = "WP", "WB" }; > > + > > +/** > > + Compare the actual memory ranges against expected memory ranges and re= turn PASS when they match. > > + > > + @param ExpectedMemoryRanges Expected memory ranges. > > + @param ExpectedMemoryRangeCount Count of expected memory ranges. > > + @param ActualRanges Actual memory ranges. > > + @param ActualRangeCount Count of actual memory ranges. > > + > > + @retval UNIT_TEST_PASSED Test passed. > > + @retval others Test failed. > > +**/ > > +UNIT_TEST_STATUS > > +VerifyMemoryRanges ( > > + IN MTRR_MEMORY_RANGE *ExpectedMemoryRanges, > > + IN UINTN ExpectedMemoryRangeCount, > > + IN MTRR_MEMORY_RANGE *ActualRanges, > > + IN UINTN ActualRangeCount > > + ) > > +{ > > + UINTN Index; > > + UT_ASSERT_EQUAL (ExpectedMemoryRangeCount, ActualRangeCount); > > + for (Index =3D 0; Index < ExpectedMemoryRangeCount; Index++) { > > + UT_ASSERT_EQUAL (ExpectedMemoryRanges[Index].BaseAddress, ActualRang= es[Index].BaseAddress); > > + UT_ASSERT_EQUAL (ExpectedMemoryRanges[Index].Length, ActualRanges[In= dex].Length); > > + UT_ASSERT_EQUAL (ExpectedMemoryRanges[Index].Type, ActualRanges[Inde= x].Type); > > + } > > + > > + return UNIT_TEST_PASSED; > > +} > > + > > +/** > > + Dump the memory ranges. > > + > > + @param Ranges Memory ranges to dump. > > + @param RangeCount Count of memory ranges. > > +**/ > > +VOID > > +DumpMemoryRanges ( > > + MTRR_MEMORY_RANGE *Ranges, > > + UINTN RangeCount > > + ) > > +{ > > + UINTN Index; > > + for (Index =3D 0; Index < RangeCount; Index++) { > > + UT_LOG_INFO ("\t{ 0x%016llx, 0x%016llx, %a },\n", Ranges[Index].Base= Address, Ranges[Index].Length, > mCacheDescription[Ranges[Index].Type]); > > + } > > +} > > + > > +/** > > +**/ > > + > > +/** > > + Generate random count of MTRRs for each cache type. > > + > > + @param TotalCount Total MTRR count. > > + @param UcCount Return count of Uncacheable type. > > + @param WtCount Return count of Write Through type. > > + @param WbCount Return count of Write Back type. > > + @param WpCount Return count of Write Protected type. > > + @param WcCount Return count of Write Combining type. > > +**/ > > +VOID > > +GenerateRandomMemoryTypeCombination ( > > + IN UINT32 TotalCount, > > + OUT UINT32 *UcCount, > > + OUT UINT32 *WtCount, > > + OUT UINT32 *WbCount, > > + OUT UINT32 *WpCount, > > + OUT UINT32 *WcCount > > + ) > > +{ > > + UINTN Index; > > + UINT32 TotalMtrrCount; > > + UINT32 *CountPerType[5]; > > + > > + CountPerType[0] =3D UcCount; > > + CountPerType[1] =3D WtCount; > > + CountPerType[2] =3D WbCount; > > + CountPerType[3] =3D WpCount; > > + CountPerType[4] =3D WcCount; > > + > > + // > > + // Initialize the count of each cache type to 0. > > + // > > + for (Index =3D 0; Index < ARRAY_SIZE (CountPerType); Index++) { > > + *(CountPerType[Index]) =3D 0; > > + } > > + > > + // > > + // Pick a random count of MTRRs > > + // > > + TotalMtrrCount =3D Random32 (1, TotalCount); > > + for (Index =3D 0; Index < TotalMtrrCount; Index++) { > > + // > > + // For each of them, pick a random cache type. > > + // > > + (*(CountPerType[Random32 (0, ARRAY_SIZE (CountPerType) - 1)]))++; > > + } > > +} > > + > > +/** > > + Unit test of MtrrLib service MtrrSetMemoryAttribute() > > + > > + @param[in] Context Ignored > > + > > + @retval UNIT_TEST_PASSED The Unit test has completed and = the test > > + case was successful. > > + @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has failed= . > > + > > +**/ > > +UNIT_TEST_STATUS > > +EFIAPI > > +UnitTestMtrrSetMemoryAttributesInMtrrSettings ( > > + IN UNIT_TEST_CONTEXT Context > > + ) > > +{ > > + CONST MTRR_LIB_SYSTEM_PARAMETER *SystemParameter; > > + RETURN_STATUS Status; > > + UINT32 UcCount; > > + UINT32 WtCount; > > + UINT32 WbCount; > > + UINT32 WpCount; > > + UINT32 WcCount; > > + > > + UINT32 MtrrIndex; > > + UINT8 *Scratch; > > + UINTN ScratchSize; > > + MTRR_SETTINGS LocalMtrrs; > > + > > + MTRR_MEMORY_RANGE RawMtrrRange[MTRR_NUMBER_OF_VARIABLE_M= TRR]; > > + MTRR_MEMORY_RANGE ExpectedMemoryRanges[MTRR_NUMBER_OF_FI= XED_MTRR * sizeof (UINT64) + 2 * > MTRR_NUMBER_OF_VARIABLE_MTRR + 1]; > > + UINT32 ExpectedVariableMtrrUsage; > > + UINTN ExpectedMemoryRangesCount; > > + > > + MTRR_MEMORY_RANGE ActualMemoryRanges[MTRR_NUMBER_OF_FIXE= D_MTRR * sizeof (UINT64) + 2 * > MTRR_NUMBER_OF_VARIABLE_MTRR + 1]; > > + UINT32 ActualVariableMtrrUsage; > > + UINTN ActualMemoryRangesCount; > > + > > + MTRR_SETTINGS *Mtrrs[2]; > > + > > + SystemParameter =3D (MTRR_LIB_SYSTEM_PARAMETER *) Context; > > + GenerateRandomMemoryTypeCombination ( > > + SystemParameter->VariableMtrrCount - PatchPcdGet32 (PcdCpuNumberOfRe= servedVariableMtrrs), > > + &UcCount, &WtCount, &WbCount, &WpCount, &WcCount > > + ); > > + GenerateValidAndConfigurableMtrrPairs ( > > + SystemParameter->PhysicalAddressBits, RawMtrrRange, > > + UcCount, WtCount, WbCount, WpCount, WcCount > > + ); > > + > > + ExpectedVariableMtrrUsage =3D UcCount + WtCount + WbCount + WpCount + = WcCount; > > + ExpectedMemoryRangesCount =3D ARRAY_SIZE (ExpectedMemoryRanges); > > + GetEffectiveMemoryRanges ( > > + SystemParameter->DefaultCacheType, > > + SystemParameter->PhysicalAddressBits, > > + RawMtrrRange, ExpectedVariableMtrrUsage, > > + ExpectedMemoryRanges, &ExpectedMemoryRangesCount > > + ); > > + > > + UT_LOG_INFO ( > > + "Total MTRR [%d]: UC=3D%d, WT=3D%d, WB=3D%d, WP=3D%d, WC=3D%d\n", > > + ExpectedVariableMtrrUsage, UcCount, WtCount, WbCount, WpCount, WcCou= nt > > + ); > > + UT_LOG_INFO ("--- Expected Memory Ranges [%d] ---\n", ExpectedMemoryRa= ngesCount); > > + DumpMemoryRanges (ExpectedMemoryRanges, ExpectedMemoryRangesCount); > > + > > + // > > + // Default cache type is always an INPUT > > + // > > + ZeroMem (&LocalMtrrs, sizeof (LocalMtrrs)); > > + LocalMtrrs.MtrrDefType =3D MtrrGetDefaultMemoryType (); > > + ScratchSize =3D SCRATCH_BUFFER_SIZE; > > + Mtrrs[0] =3D &LocalMtrrs; > > + Mtrrs[1] =3D NULL; > > + > > + for (MtrrIndex =3D 0; MtrrIndex < ARRAY_SIZE (Mtrrs); MtrrIndex++) { > > + Scratch =3D calloc (ScratchSize, sizeof (UINT8)); > > + Status =3D MtrrSetMemoryAttributesInMtrrSettings (Mtrrs[MtrrIndex], = Scratch, &ScratchSize, ExpectedMemoryRanges, > ExpectedMemoryRangesCount); > > + if (Status =3D=3D RETURN_BUFFER_TOO_SMALL) { > > + Scratch =3D realloc (Scratch, ScratchSize); > > + Status =3D MtrrSetMemoryAttributesInMtrrSettings (Mtrrs[MtrrIndex]= , Scratch, &ScratchSize, ExpectedMemoryRanges, > ExpectedMemoryRangesCount); > > + } > > + UT_ASSERT_STATUS_EQUAL (Status, RETURN_SUCCESS); > > + > > + if (Mtrrs[MtrrIndex] =3D=3D NULL) { > > + ZeroMem (&LocalMtrrs, sizeof (LocalMtrrs)); > > + MtrrGetAllMtrrs (&LocalMtrrs); > > + } > > + ActualMemoryRangesCount =3D ARRAY_SIZE (ActualMemoryRanges); > > + CollectTestResult ( > > + SystemParameter->DefaultCacheType, SystemParameter->PhysicalAddres= sBits, SystemParameter->VariableMtrrCount, > > + &LocalMtrrs, ActualMemoryRanges, &ActualMemoryRangesCount, &Actual= VariableMtrrUsage > > + ); > > + > > + UT_LOG_INFO ("--- Actual Memory Ranges [%d] ---\n", ActualMemoryRang= esCount); > > + DumpMemoryRanges (ActualMemoryRanges, ActualMemoryRangesCount); > > + VerifyMemoryRanges (ExpectedMemoryRanges, ExpectedMemoryRangesCount,= ActualMemoryRanges, > ActualMemoryRangesCount); > > + UT_ASSERT_TRUE (ExpectedVariableMtrrUsage >=3D ActualVariableMtrrUsa= ge); > > + > > + ZeroMem (&LocalMtrrs, sizeof (LocalMtrrs)); > > + } > > + > > + free (Scratch); > > + > > + return UNIT_TEST_PASSED; > > +} > > + > > +/** > > + Test routine to check whether invalid base/size can be rejected. > > + > > + @param Context Pointer to MTRR_LIB_SYSTEM_PARAMETER. > > + > > + @return Test status. > > +**/ > > +UNIT_TEST_STATUS > > +EFIAPI > > +UnitTestInvalidMemoryLayouts ( > > + IN UNIT_TEST_CONTEXT Context > > + ) > > +{ > > + CONST MTRR_LIB_SYSTEM_PARAMETER *SystemParameter; > > + MTRR_MEMORY_RANGE Ranges[MTRR_NUMBER_OF_VARIABLE_MTRR * = 2 + 1]; > > + UINTN RangeCount; > > + UINT64 MaxAddress; > > + UINT32 Index; > > + UINT64 BaseAddress; > > + UINT64 Length; > > + RETURN_STATUS Status; > > + UINTN ScratchSize; > > + > > + SystemParameter =3D (MTRR_LIB_SYSTEM_PARAMETER *) Context; > > + > > + RangeCount =3D Random32 (1, ARRAY_SIZE (Ranges)); > > + MaxAddress =3D 1ull << SystemParameter->PhysicalAddressBits; > > + > > + for (Index =3D 0; Index < RangeCount; Index++) { > > + do { > > + BaseAddress =3D Random64 (0, MaxAddress); > > + Length =3D Random64 (1, MaxAddress - BaseAddress); > > + } while (((BaseAddress & 0xFFF) =3D=3D 0) || ((Length & 0xFFF) =3D= =3D 0)); > > + > > + Ranges[Index].BaseAddress =3D BaseAddress; > > + Ranges[Index].Length =3D Length; > > + Ranges[Index].Type =3D GenerateRandomCacheType (); > > + > > + Status =3D MtrrSetMemoryAttribute ( > > + Ranges[Index].BaseAddress, Ranges[Index].Length, Ranges[Index].Typ= e > > + ); > > + UT_ASSERT_TRUE (RETURN_ERROR (Status)); > > + } > > + > > + ScratchSize =3D 0; > > + Status =3D MtrrSetMemoryAttributesInMtrrSettings (NULL, NULL, &Scratch= Size, Ranges, RangeCount); > > + UT_ASSERT_TRUE (RETURN_ERROR (Status)); > > + > > + return UNIT_TEST_PASSED; > > +} > > + > > +/** > > + Unit test of MtrrLib service IsMtrrSupported() > > + > > + @param[in] Context Ignored > > + > > + @retval UNIT_TEST_PASSED The Unit test has completed and = the test > > + case was successful. > > + @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has failed= . > > + > > +**/ > > +UNIT_TEST_STATUS > > +EFIAPI > > +UnitTestIsMtrrSupported ( > > + IN UNIT_TEST_CONTEXT Context > > + ) > > +{ > > + MTRR_LIB_SYSTEM_PARAMETER SystemParameter; > > + MTRR_LIB_TEST_CONTEXT *LocalContext; > > + > > + LocalContext =3D (MTRR_LIB_TEST_CONTEXT *) Context; > > + > > + CopyMem (&SystemParameter, LocalContext->SystemParameter, sizeof (Syst= emParameter)); > > + // > > + // MTRR capability off in CPUID leaf. > > + // > > + SystemParameter.MtrrSupported =3D FALSE; > > + InitializeMtrrRegs (&SystemParameter); > > + UT_ASSERT_FALSE (IsMtrrSupported ()); > > + > > + // > > + // MTRR capability on in CPUID leaf, but no variable or fixed MTRRs. > > + // > > + SystemParameter.MtrrSupported =3D TRUE; > > + SystemParameter.VariableMtrrCount =3D 0; > > + SystemParameter.FixedMtrrSupported =3D FALSE; > > + InitializeMtrrRegs (&SystemParameter); > > + UT_ASSERT_FALSE (IsMtrrSupported ()); > > + > > + // > > + // MTRR capability on in CPUID leaf, but no variable MTRRs. > > + // > > + SystemParameter.MtrrSupported =3D TRUE; > > + SystemParameter.VariableMtrrCount =3D 0; > > + SystemParameter.FixedMtrrSupported =3D TRUE; > > + InitializeMtrrRegs (&SystemParameter); > > + UT_ASSERT_FALSE (IsMtrrSupported ()); > > + > > + // > > + // MTRR capability on in CPUID leaf, but no fixed MTRRs. > > + // > > + SystemParameter.MtrrSupported =3D TRUE; > > + SystemParameter.VariableMtrrCount =3D 7; > > + SystemParameter.FixedMtrrSupported =3D FALSE; > > + InitializeMtrrRegs (&SystemParameter); > > + UT_ASSERT_FALSE (IsMtrrSupported ()); > > + > > + // > > + // MTRR capability on in CPUID leaf with both variable and fixed MTRRs= . > > + // > > + SystemParameter.MtrrSupported =3D TRUE; > > + SystemParameter.VariableMtrrCount =3D 7; > > + SystemParameter.FixedMtrrSupported =3D TRUE; > > + InitializeMtrrRegs (&SystemParameter); > > + UT_ASSERT_TRUE (IsMtrrSupported ()); > > + > > + return UNIT_TEST_PASSED; > > +} > > + > > +/** > > + Unit test of MtrrLib service GetVariableMtrrCount() > > + > > + @param[in] Context Ignored > > + > > + @retval UNIT_TEST_PASSED The Unit test has completed and = the test > > + case was successful. > > + @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has failed= . > > + > > +**/ > > +UNIT_TEST_STATUS > > +EFIAPI > > +UnitTestGetVariableMtrrCount ( > > + IN UNIT_TEST_CONTEXT Context > > + ) > > +{ > > + UINT32 Result; > > + MTRR_LIB_SYSTEM_PARAMETER SystemParameter; > > + MTRR_LIB_TEST_CONTEXT *LocalContext; > > + > > + LocalContext =3D (MTRR_LIB_TEST_CONTEXT *) Context; > > + > > + CopyMem (&SystemParameter, LocalContext->SystemParameter, sizeof (Syst= emParameter)); > > + // > > + // If MTRR capability off in CPUID leaf, then the count is always 0. > > + // > > + SystemParameter.MtrrSupported =3D FALSE; > > + for (SystemParameter.VariableMtrrCount =3D 1; SystemParameter.Variable= MtrrCount <=3D > MTRR_NUMBER_OF_VARIABLE_MTRR; SystemParameter.VariableMtrrCount++) { > > + InitializeMtrrRegs (&SystemParameter); > > + Result =3D GetVariableMtrrCount (); > > + UT_ASSERT_EQUAL (Result, 0); > > + } > > + > > + // > > + // Try all supported variable MTRR counts. > > + // If variable MTRR count is > MTRR_NUMBER_OF_VARIABLE_MTRR, then an A= SSERT() > > + // is generated. > > + // > > + SystemParameter.MtrrSupported =3D TRUE; > > + for (SystemParameter.VariableMtrrCount =3D 1; SystemParameter.Variable= MtrrCount <=3D > MTRR_NUMBER_OF_VARIABLE_MTRR; SystemParameter.VariableMtrrCount++) { > > + InitializeMtrrRegs (&SystemParameter); > > + Result =3D GetVariableMtrrCount (); > > + UT_ASSERT_EQUAL (Result, SystemParameter.VariableMtrrCount); > > + } > > + > > + // > > + // Expect ASSERT() if variable MTRR count is > MTRR_NUMBER_OF_VARIABLE= _MTRR > > + // > > + SystemParameter.VariableMtrrCount =3D MTRR_NUMBER_OF_VARIABLE_MTRR + 1= ; > > + InitializeMtrrRegs (&SystemParameter); > > + UT_EXPECT_ASSERT_FAILURE (GetVariableMtrrCount (), NULL); > > + > > + SystemParameter.MtrrSupported =3D TRUE; > > + SystemParameter.VariableMtrrCount =3D MAX_UINT8; > > + InitializeMtrrRegs (&SystemParameter); > > + UT_EXPECT_ASSERT_FAILURE (GetVariableMtrrCount (), NULL); > > + > > + return UNIT_TEST_PASSED; > > +} > > + > > +/** > > + Unit test of MtrrLib service GetFirmwareVariableMtrrCount() > > + > > + @param[in] Context Ignored > > + > > + @retval UNIT_TEST_PASSED The Unit test has completed and = the test > > + case was successful. > > + @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has failed= . > > + > > +**/ > > +UNIT_TEST_STATUS > > +EFIAPI > > +UnitTestGetFirmwareVariableMtrrCount ( > > + IN UNIT_TEST_CONTEXT Context > > + ) > > +{ > > + UINT32 Result; > > + UINT32 ReservedMtrrs; > > + MTRR_LIB_SYSTEM_PARAMETER SystemParameter; > > + MTRR_LIB_GET_FIRMWARE_VARIABLE_MTRR_COUNT_CONTEXT *LocalContext; > > + > > + LocalContext =3D (MTRR_LIB_GET_FIRMWARE_VARIABLE_MTRR_COUNT_CONTEXT *)= Context; > > + > > + CopyMem (&SystemParameter, LocalContext->SystemParameter, sizeof (Syst= emParameter)); > > + > > + InitializeMtrrRegs (&SystemParameter); > > + // > > + // Positive test cases for VCNT =3D 10 and Reserved PCD in range 0..10 > > + // > > + for (ReservedMtrrs =3D 0; ReservedMtrrs <=3D SystemParameter.VariableM= trrCount; ReservedMtrrs++) { > > + PatchPcdSet32 (PcdCpuNumberOfReservedVariableMtrrs, ReservedMtrrs); > > + Result =3D GetFirmwareVariableMtrrCount (); > > + UT_ASSERT_EQUAL (Result, SystemParameter.VariableMtrrCount - Reserve= dMtrrs); > > + } > > + > > + // > > + // Negative test cases when Reserved PCD is larger than VCNT > > + // > > + for (ReservedMtrrs =3D SystemParameter.VariableMtrrCount + 1; Reserved= Mtrrs <=3D 255; ReservedMtrrs++) { > > + PatchPcdSet32 (PcdCpuNumberOfReservedVariableMtrrs, ReservedMtrrs); > > + Result =3D GetFirmwareVariableMtrrCount (); > > + UT_ASSERT_EQUAL (Result, 0); > > + } > > + > > + // > > + // Negative test cases when Reserved PCD is larger than VCNT > > + // > > + PatchPcdSet32 (PcdCpuNumberOfReservedVariableMtrrs, MAX_UINT32); > > + Result =3D GetFirmwareVariableMtrrCount (); > > + UT_ASSERT_EQUAL (Result, 0); > > + > > + // > > + // Negative test case when MTRRs are not supported > > + // > > + SystemParameter.MtrrSupported =3D FALSE; > > + InitializeMtrrRegs (&SystemParameter); > > + PatchPcdSet32 (PcdCpuNumberOfReservedVariableMtrrs, 2); > > + Result =3D GetFirmwareVariableMtrrCount (); > > + UT_ASSERT_EQUAL (Result, 0); > > + > > + // > > + // Negative test case when Fixed MTRRs are not supported > > + // > > + SystemParameter.MtrrSupported =3D TRUE; > > + SystemParameter.FixedMtrrSupported =3D FALSE; > > + InitializeMtrrRegs (&SystemParameter); > > + PatchPcdSet32 (PcdCpuNumberOfReservedVariableMtrrs, 2); > > + Result =3D GetFirmwareVariableMtrrCount (); > > + UT_ASSERT_EQUAL (Result, 0); > > + > > + // > > + // Expect ASSERT() if variable MTRR count is > MTRR_NUMBER_OF_VARIABLE= _MTRR > > + // > > + SystemParameter.FixedMtrrSupported =3D TRUE; > > + SystemParameter.VariableMtrrCount =3D MTRR_NUMBER_OF_VARIABLE_MTRR + 1= ; > > + InitializeMtrrRegs (&SystemParameter); > > + UT_EXPECT_ASSERT_FAILURE (GetFirmwareVariableMtrrCount (), NULL); > > + > > + return UNIT_TEST_PASSED; > > +} > > + > > +/** > > + Unit test of MtrrLib service MtrrGetMemoryAttribute() > > + > > + @param[in] Context Ignored > > + > > + @retval UNIT_TEST_PASSED The Unit test has completed and = the test > > + case was successful. > > + @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has failed= . > > + > > +**/ > > +UNIT_TEST_STATUS > > +EFIAPI > > +UnitTestMtrrGetMemoryAttribute ( > > + IN UNIT_TEST_CONTEXT Context > > + ) > > +{ > > + return UNIT_TEST_PASSED; > > +} > > + > > +/** > > + Unit test of MtrrLib service MtrrGetFixedMtrr() > > + > > + @param[in] Context Ignored > > + > > + @retval UNIT_TEST_PASSED The Unit test has completed and = the test > > + case was successful. > > + @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has failed= . > > + > > +**/ > > +UNIT_TEST_STATUS > > +EFIAPI > > +UnitTestMtrrGetFixedMtrr ( > > + IN UNIT_TEST_CONTEXT Context > > + ) > > +{ > > + MTRR_FIXED_SETTINGS *Result; > > + MTRR_FIXED_SETTINGS ExpectedFixedSettings; > > + MTRR_FIXED_SETTINGS FixedSettings; > > + UINTN Index; > > + UINTN MsrIndex; > > + UINTN ByteIndex; > > + UINT64 MsrValue; > > + MTRR_LIB_SYSTEM_PARAMETER SystemParameter; > > + MTRR_LIB_TEST_CONTEXT *LocalContext; > > + > > + LocalContext =3D (MTRR_LIB_TEST_CONTEXT *) Context; > > + > > + CopyMem (&SystemParameter, LocalContext->SystemParameter, sizeof (Syst= emParameter)); > > + InitializeMtrrRegs (&SystemParameter); > > + // > > + // Set random cache type to different ranges under 1MB and make sure > > + // the fixed MTRR settings are expected. > > + // Try 100 times. > > + // > > + for (Index =3D 0; Index < 100; Index++) { > > + for (MsrIndex =3D 0; MsrIndex < ARRAY_SIZE (mFixedMtrrsIndex); MsrIn= dex++) { > > + MsrValue =3D 0; > > + for (ByteIndex =3D 0; ByteIndex < sizeof (UINT64); ByteIndex++) { > > + MsrValue =3D MsrValue | LShiftU64 (GenerateRandomCacheType (), B= yteIndex * 8); > > + } > > + ExpectedFixedSettings.Mtrr[MsrIndex] =3D MsrValue; > > + AsmWriteMsr64 (mFixedMtrrsIndex[MsrIndex], MsrValue); > > + } > > + > > + Result =3D MtrrGetFixedMtrr (&FixedSettings); > > + UT_ASSERT_EQUAL (Result, &FixedSettings); > > + UT_ASSERT_MEM_EQUAL (&FixedSettings, &ExpectedFixedSettings, sizeof = (FixedSettings)); > > + } > > + > > + // > > + // Negative test case when MTRRs are not supported > > + // > > + SystemParameter.MtrrSupported =3D FALSE; > > + InitializeMtrrRegs (&SystemParameter); > > + > > + ZeroMem (&FixedSettings, sizeof (FixedSettings)); > > + ZeroMem (&ExpectedFixedSettings, sizeof (ExpectedFixedSettings)); > > + Result =3D MtrrGetFixedMtrr (&FixedSettings); > > + UT_ASSERT_EQUAL (Result, &FixedSettings); > > + UT_ASSERT_MEM_EQUAL (&ExpectedFixedSettings, &FixedSettings, sizeof (E= xpectedFixedSettings)); > > + > > + return UNIT_TEST_PASSED; > > +} > > + > > +/** > > + Unit test of MtrrLib service MtrrGetAllMtrrs() > > + > > + @param[in] Context Ignored > > + > > + @retval UNIT_TEST_PASSED The Unit test has completed and = the test > > + case was successful. > > + @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has failed= . > > + > > +**/ > > +UNIT_TEST_STATUS > > +EFIAPI > > +UnitTestMtrrGetAllMtrrs ( > > + IN UNIT_TEST_CONTEXT Context > > + ) > > +{ > > + MTRR_SETTINGS *Result; > > + MTRR_SETTINGS Mtrrs; > > + MTRR_SETTINGS ExpectedMtrrs; > > + MTRR_VARIABLE_SETTING VariableMtrr[MTRR_NUMBER_OF_VARIABLE_MTRR]; > > + UINT32 Index; > > + MTRR_LIB_SYSTEM_PARAMETER SystemParameter; > > + MTRR_LIB_TEST_CONTEXT *LocalContext; > > + > > + LocalContext =3D (MTRR_LIB_TEST_CONTEXT *) Context; > > + > > + CopyMem (&SystemParameter, LocalContext->SystemParameter, sizeof (Syst= emParameter)); > > + InitializeMtrrRegs (&SystemParameter); > > + > > + for (Index =3D 0; Index < SystemParameter.VariableMtrrCount; Index++) = { > > + GenerateRandomMtrrPair (SystemParameter.PhysicalAddressBits, Generat= eRandomCacheType (), &VariableMtrr[Index], > NULL); > > + AsmWriteMsr64 (MSR_IA32_MTRR_PHYSBASE0 + (Index << 1), VariableMtrr[= Index].Base); > > + AsmWriteMsr64 (MSR_IA32_MTRR_PHYSMASK0 + (Index << 1), VariableMtrr[= Index].Mask); > > + } > > + Result =3D MtrrGetAllMtrrs (&Mtrrs); > > + UT_ASSERT_EQUAL (Result, &Mtrrs); > > + UT_ASSERT_MEM_EQUAL (Mtrrs.Variables.Mtrr, VariableMtrr, sizeof (MTRR_= VARIABLE_SETTING) * > SystemParameter.VariableMtrrCount); > > + > > + // > > + // Negative test case when MTRRs are not supported > > + // > > + ZeroMem (&ExpectedMtrrs, sizeof (ExpectedMtrrs)); > > + ZeroMem (&Mtrrs, sizeof (Mtrrs)); > > + > > + SystemParameter.MtrrSupported =3D FALSE; > > + InitializeMtrrRegs (&SystemParameter); > > + Result =3D MtrrGetAllMtrrs (&Mtrrs); > > + UT_ASSERT_EQUAL (Result, &Mtrrs); > > + UT_ASSERT_MEM_EQUAL (&ExpectedMtrrs, &Mtrrs, sizeof (ExpectedMtrrs)); > > + > > + // > > + // Expect ASSERT() if variable MTRR count is > MTRR_NUMBER_OF_VARIABLE= _MTRR > > + // > > + SystemParameter.MtrrSupported =3D TRUE; > > + SystemParameter.VariableMtrrCount =3D MTRR_NUMBER_OF_VARIABLE_MTRR + 1= ; > > + InitializeMtrrRegs (&SystemParameter); > > + UT_EXPECT_ASSERT_FAILURE (MtrrGetAllMtrrs (&Mtrrs), NULL); > > + > > + return UNIT_TEST_PASSED; > > +} > > + > > +/** > > + Unit test of MtrrLib service MtrrSetAllMtrrs() > > + > > + @param[in] Context Ignored > > + > > + @retval UNIT_TEST_PASSED The Unit test has completed and = the test > > + case was successful. > > + @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has failed= . > > + > > +**/ > > +UNIT_TEST_STATUS > > +EFIAPI > > +UnitTestMtrrSetAllMtrrs ( > > + IN UNIT_TEST_CONTEXT Context > > + ) > > +{ > > + MTRR_SETTINGS *Result; > > + MTRR_SETTINGS Mtrrs; > > + UINT32 Index; > > + MSR_IA32_MTRR_DEF_TYPE_REGISTER Default; > > + MTRR_LIB_SYSTEM_PARAMETER SystemParameter; > > + MTRR_LIB_TEST_CONTEXT *LocalContext; > > + > > + LocalContext =3D (MTRR_LIB_TEST_CONTEXT *) Context; > > + > > + CopyMem (&SystemParameter, LocalContext->SystemParameter, sizeof (Syst= emParameter)); > > + InitializeMtrrRegs (&SystemParameter); > > + > > + Default.Uint64 =3D 0; > > + Default.Bits.E =3D 1; > > + Default.Bits.FE =3D 1; > > + Default.Bits.Type =3D GenerateRandomCacheType (); > > + > > + ZeroMem (&Mtrrs, sizeof (Mtrrs)); > > + Mtrrs.MtrrDefType =3D Default.Uint64; > > + for (Index =3D 0; Index < SystemParameter.VariableMtrrCount; Index++) = { > > + GenerateRandomMtrrPair (SystemParameter.PhysicalAddressBits, Generat= eRandomCacheType (), > &Mtrrs.Variables.Mtrr[Index], NULL); > > + } > > + Result =3D MtrrSetAllMtrrs (&Mtrrs); > > + UT_ASSERT_EQUAL (Result, &Mtrrs); > > + > > + UT_ASSERT_EQUAL (AsmReadMsr64 (MSR_IA32_MTRR_DEF_TYPE), Mtrrs.MtrrDefT= ype); > > + for (Index =3D 0; Index < SystemParameter.VariableMtrrCount; Index++) = { > > + UT_ASSERT_EQUAL (AsmReadMsr64 (MSR_IA32_MTRR_PHYSBASE0 + (Index << 1= )), Mtrrs.Variables.Mtrr[Index].Base); > > + UT_ASSERT_EQUAL (AsmReadMsr64 (MSR_IA32_MTRR_PHYSMASK0 + (Index << 1= )), Mtrrs.Variables.Mtrr[Index].Mask); > > + } > > + > > + return UNIT_TEST_PASSED; > > +} > > + > > +/** > > + Unit test of MtrrLib service MtrrGetMemoryAttributeInVariableMtrr() > > + > > + @param[in] Context Ignored > > + > > + @retval UNIT_TEST_PASSED The Unit test has completed and = the test > > + case was successful. > > + @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has failed= . > > + > > +**/ > > +UNIT_TEST_STATUS > > +EFIAPI > > +UnitTestMtrrGetMemoryAttributeInVariableMtrr ( > > + IN UNIT_TEST_CONTEXT Context > > + ) > > +{ > > + MTRR_LIB_TEST_CONTEXT *LocalContext; > > + MTRR_LIB_SYSTEM_PARAMETER SystemParameter; > > + UINT32 Result; > > + MTRR_VARIABLE_SETTING VariableSetting[MTRR_NUMBER_OF_VARIABL= E_MTRR]; > > + VARIABLE_MTRR VariableMtrr[MTRR_NUMBER_OF_VARIABLE_M= TRR]; > > + UINT64 ValidMtrrBitsMask; > > + UINT64 ValidMtrrAddressMask; > > + UINT32 Index; > > + MSR_IA32_MTRR_PHYSBASE_REGISTER Base; > > + MSR_IA32_MTRR_PHYSMASK_REGISTER Mask; > > + > > + LocalContext =3D (MTRR_LIB_TEST_CONTEXT *) Context; > > + > > + CopyMem (&SystemParameter, LocalContext->SystemParameter, sizeof (Syst= emParameter)); > > + > > + InitializeMtrrRegs (&SystemParameter); > > + > > + ValidMtrrBitsMask =3D (1ull << SystemParameter.PhysicalAddressBits)= - 1; > > + ValidMtrrAddressMask =3D ValidMtrrBitsMask & 0xfffffffffffff000ULL; > > + > > + for (Index =3D 0; Index < SystemParameter.VariableMtrrCount; Index++) = { > > + GenerateRandomMtrrPair (SystemParameter.PhysicalAddressBits, Generat= eRandomCacheType (), > &VariableSetting[Index], NULL); > > + AsmWriteMsr64 (MSR_IA32_MTRR_PHYSBASE0 + (Index << 1), VariableSetti= ng[Index].Base); > > + AsmWriteMsr64 (MSR_IA32_MTRR_PHYSMASK0 + (Index << 1), VariableSetti= ng[Index].Mask); > > + } > > + Result =3D MtrrGetMemoryAttributeInVariableMtrr (ValidMtrrBitsMask, Va= lidMtrrAddressMask, VariableMtrr); > > + UT_ASSERT_EQUAL (Result, SystemParameter.VariableMtrrCount); > > + > > + for (Index =3D 0; Index < SystemParameter.VariableMtrrCount; Index++) = { > > + Base.Uint64 =3D VariableMtrr[Index].BaseAddress; > > + Base.Bits.Type =3D (UINT32) VariableMtrr[Index].Type; > > + UT_ASSERT_EQUAL (Base.Uint64, VariableSetting[Index].Base); > > + > > + Mask.Uint64 =3D ~(VariableMtrr[Index].Length - 1) & ValidMtrrBits= Mask; > > + Mask.Bits.V =3D 1; > > + UT_ASSERT_EQUAL (Mask.Uint64, VariableSetting[Index].Mask); > > + } > > + > > + // > > + // Negative test case when MTRRs are not supported > > + // > > + SystemParameter.MtrrSupported =3D FALSE; > > + InitializeMtrrRegs (&SystemParameter); > > + Result =3D MtrrGetMemoryAttributeInVariableMtrr (ValidMtrrBitsMask, Va= lidMtrrAddressMask, VariableMtrr); > > + UT_ASSERT_EQUAL (Result, 0); > > + > > + // > > + // Expect ASSERT() if variable MTRR count is > MTRR_NUMBER_OF_VARIABLE= _MTRR > > + // > > + SystemParameter.MtrrSupported =3D TRUE; > > + SystemParameter.VariableMtrrCount =3D MTRR_NUMBER_OF_VARIABLE_MTRR + 1= ; > > + InitializeMtrrRegs (&SystemParameter); > > + UT_EXPECT_ASSERT_FAILURE (MtrrGetMemoryAttributeInVariableMtrr (ValidM= trrBitsMask, ValidMtrrAddressMask, > VariableMtrr), NULL); > > + > > + return UNIT_TEST_PASSED; > > +} > > + > > +/** > > + Unit test of MtrrLib service MtrrDebugPrintAllMtrrs() > > + > > + @param[in] Context Ignored > > + > > + @retval UNIT_TEST_PASSED The Unit test has completed and = the test > > + case was successful. > > + @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has failed= . > > + > > +**/ > > +UNIT_TEST_STATUS > > +EFIAPI > > +UnitTestMtrrDebugPrintAllMtrrs ( > > + IN UNIT_TEST_CONTEXT Context > > + ) > > +{ > > + return UNIT_TEST_PASSED; > > +} > > + > > +/** > > + Unit test of MtrrLib service MtrrGetDefaultMemoryType(). > > + > > + @param[in] Context Ignored > > + > > + @retval UNIT_TEST_PASSED The Unit test has completed and = the test > > + case was successful. > > + @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has failed= . > > + > > +**/ > > +UNIT_TEST_STATUS > > +EFIAPI > > +UnitTestMtrrGetDefaultMemoryType ( > > + IN UNIT_TEST_CONTEXT Context > > + ) > > +{ > > + MTRR_LIB_TEST_CONTEXT *LocalContext; > > + UINTN Index; > > + MTRR_MEMORY_CACHE_TYPE Result; > > + MTRR_LIB_SYSTEM_PARAMETER SystemParameter; > > + MTRR_MEMORY_CACHE_TYPE CacheType[5]; > > + > > + CacheType[0] =3D CacheUncacheable; > > + CacheType[1] =3D CacheWriteCombining; > > + CacheType[2] =3D CacheWriteThrough; > > + CacheType[3] =3D CacheWriteProtected; > > + CacheType[4] =3D CacheWriteBack; > > + > > + LocalContext =3D (MTRR_LIB_TEST_CONTEXT *) Context; > > + > > + CopyMem (&SystemParameter, LocalContext->SystemParameter, sizeof (Syst= emParameter)); > > + // > > + // If MTRRs are supported, then always return the cache type in the MS= R > > + // MSR_IA32_MTRR_DEF_TYPE > > + // > > + for (Index =3D 0; Index < ARRAY_SIZE (CacheType); Index++) { > > + SystemParameter.DefaultCacheType =3D CacheType[Index]; > > + InitializeMtrrRegs (&SystemParameter); > > + Result =3D MtrrGetDefaultMemoryType (); > > + UT_ASSERT_EQUAL (Result, SystemParameter.DefaultCacheType); > > + } > > + > > + // > > + // If MTRRs are not supported, then always return CacheUncacheable > > + // > > + SystemParameter.MtrrSupported =3D FALSE; > > + InitializeMtrrRegs (&SystemParameter); > > + Result =3D MtrrGetDefaultMemoryType (); > > + UT_ASSERT_EQUAL (Result, CacheUncacheable); > > + > > + SystemParameter.MtrrSupported =3D TRUE; > > + SystemParameter.FixedMtrrSupported =3D FALSE; > > + InitializeMtrrRegs (&SystemParameter); > > + Result =3D MtrrGetDefaultMemoryType (); > > + UT_ASSERT_EQUAL (Result, CacheUncacheable); > > + > > + SystemParameter.MtrrSupported =3D TRUE; > > + SystemParameter.FixedMtrrSupported =3D TRUE; > > + SystemParameter.VariableMtrrCount =3D 0; > > + InitializeMtrrRegs (&SystemParameter); > > + Result =3D MtrrGetDefaultMemoryType (); > > + UT_ASSERT_EQUAL (Result, CacheUncacheable); > > + > > + return UNIT_TEST_PASSED; > > +} > > + > > +/** > > + Unit test of MtrrLib service MtrrSetMemoryAttributeInMtrrSettings(). > > + > > + @param[in] Context Ignored > > + > > + @retval UNIT_TEST_PASSED The Unit test has completed and = the test > > + case was successful. > > + @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has failed= . > > + > > +**/ > > +UNIT_TEST_STATUS > > +EFIAPI > > +UnitTestMtrrSetMemoryAttributeInMtrrSettings ( > > + IN UNIT_TEST_CONTEXT Context > > + ) > > +{ > > + CONST MTRR_LIB_SYSTEM_PARAMETER *SystemParameter; > > + RETURN_STATUS Status; > > + UINT32 UcCount; > > + UINT32 WtCount; > > + UINT32 WbCount; > > + UINT32 WpCount; > > + UINT32 WcCount; > > + > > + UINTN MtrrIndex; > > + UINTN Index; > > + MTRR_SETTINGS LocalMtrrs; > > + > > + MTRR_MEMORY_RANGE RawMtrrRange[MTRR_NUMBER_OF_VARIABLE_M= TRR]; > > + MTRR_MEMORY_RANGE ExpectedMemoryRanges[MTRR_NUMBER_OF_FI= XED_MTRR * sizeof (UINT64) + 2 * > MTRR_NUMBER_OF_VARIABLE_MTRR + 1]; > > + UINT32 ExpectedVariableMtrrUsage; > > + UINTN ExpectedMemoryRangesCount; > > + > > + MTRR_MEMORY_RANGE ActualMemoryRanges[MTRR_NUMBER_OF_FIXE= D_MTRR * sizeof (UINT64) + 2 * > MTRR_NUMBER_OF_VARIABLE_MTRR + 1]; > > + UINT32 ActualVariableMtrrUsage; > > + UINTN ActualMemoryRangesCount; > > + > > + MTRR_SETTINGS *Mtrrs[2]; > > + > > + SystemParameter =3D (MTRR_LIB_SYSTEM_PARAMETER *) Context; > > + GenerateRandomMemoryTypeCombination ( > > + SystemParameter->VariableMtrrCount - PatchPcdGet32 (PcdCpuNumberOfRe= servedVariableMtrrs), > > + &UcCount, &WtCount, &WbCount, &WpCount, &WcCount > > + ); > > + GenerateValidAndConfigurableMtrrPairs ( > > + SystemParameter->PhysicalAddressBits, RawMtrrRange, > > + UcCount, WtCount, WbCount, WpCount, WcCount > > + ); > > + > > + ExpectedVariableMtrrUsage =3D UcCount + WtCount + WbCount + WpCount + = WcCount; > > + ExpectedMemoryRangesCount =3D ARRAY_SIZE (ExpectedMemoryRanges); > > + GetEffectiveMemoryRanges ( > > + SystemParameter->DefaultCacheType, > > + SystemParameter->PhysicalAddressBits, > > + RawMtrrRange, ExpectedVariableMtrrUsage, > > + ExpectedMemoryRanges, &ExpectedMemoryRangesCount > > + ); > > + > > + UT_LOG_INFO ("--- Expected Memory Ranges [%d] ---\n", ExpectedMemoryRa= ngesCount); > > + DumpMemoryRanges (ExpectedMemoryRanges, ExpectedMemoryRangesCount); > > + // > > + // Default cache type is always an INPUT > > + // > > + ZeroMem (&LocalMtrrs, sizeof (LocalMtrrs)); > > + LocalMtrrs.MtrrDefType =3D MtrrGetDefaultMemoryType (); > > + Mtrrs[0] =3D &LocalMtrrs; > > + Mtrrs[1] =3D NULL; > > + > > + for (MtrrIndex =3D 0; MtrrIndex < ARRAY_SIZE (Mtrrs); MtrrIndex++) { > > + for (Index =3D 0; Index < ExpectedMemoryRangesCount; Index++) { > > + Status =3D MtrrSetMemoryAttributeInMtrrSettings ( > > + Mtrrs[MtrrIndex], > > + ExpectedMemoryRanges[Index].BaseAddress, > > + ExpectedMemoryRanges[Index].Length, > > + ExpectedMemoryRanges[Index].Type > > + ); > > + UT_ASSERT_TRUE (Status =3D=3D RETURN_SUCCESS || Status =3D=3D RETU= RN_OUT_OF_RESOURCES || Status =3D=3D > RETURN_BUFFER_TOO_SMALL); > > + if (Status =3D=3D RETURN_OUT_OF_RESOURCES || Status =3D=3D RETURN_= BUFFER_TOO_SMALL) { > > + return UNIT_TEST_SKIPPED; > > + } > > + } > > + > > + if (Mtrrs[MtrrIndex] =3D=3D NULL) { > > + ZeroMem (&LocalMtrrs, sizeof (LocalMtrrs)); > > + MtrrGetAllMtrrs (&LocalMtrrs); > > + } > > + ActualMemoryRangesCount =3D ARRAY_SIZE (ActualMemoryRanges); > > + CollectTestResult ( > > + SystemParameter->DefaultCacheType, SystemParameter->PhysicalAddres= sBits, SystemParameter->VariableMtrrCount, > > + &LocalMtrrs, ActualMemoryRanges, &ActualMemoryRangesCount, &Actual= VariableMtrrUsage > > + ); > > + UT_LOG_INFO ("--- Actual Memory Ranges [%d] ---\n", ActualMemoryRang= esCount); > > + DumpMemoryRanges (ActualMemoryRanges, ActualMemoryRangesCount); > > + VerifyMemoryRanges (ExpectedMemoryRanges, ExpectedMemoryRangesCount,= ActualMemoryRanges, > ActualMemoryRangesCount); > > + UT_ASSERT_TRUE (ExpectedVariableMtrrUsage >=3D ActualVariableMtrrUsa= ge); > > + > > + ZeroMem (&LocalMtrrs, sizeof (LocalMtrrs)); > > + } > > + > > + return UNIT_TEST_PASSED; > > +} > > + > > + > > +/** > > + Prep routine for UnitTestGetFirmwareVariableMtrrCount(). > > + > > + @param Context Point to a UINT32 data to save the PcdCpuNumberOfReser= vedVariableMtrrs. > > +**/ > > +UNIT_TEST_STATUS > > +EFIAPI > > +SavePcdValue ( > > + UNIT_TEST_CONTEXT Context > > + ) > > +{ > > + MTRR_LIB_GET_FIRMWARE_VARIABLE_MTRR_COUNT_CONTEXT *LocalContext; > > + > > + LocalContext =3D (MTRR_LIB_GET_FIRMWARE_VARIABLE_MTRR_COUNT_CONTEXT *)= Context; > > + LocalContext->NumberOfReservedVariableMtrrs =3D PatchPcdGet32 (PcdCpuN= umberOfReservedVariableMtrrs); > > + return UNIT_TEST_PASSED; > > +} > > + > > +/** > > + Clean up routine for UnitTestGetFirmwareVariableMtrrCount(). > > + > > + @param Context Point to a UINT32 data to save the PcdCpuNumberOfReser= vedVariableMtrrs. > > +**/ > > +UNIT_TEST_STATUS > > +EFIAPI > > +RestorePcdValue ( > > + UNIT_TEST_CONTEXT Context > > + ) > > +{ > > + MTRR_LIB_GET_FIRMWARE_VARIABLE_MTRR_COUNT_CONTEXT *LocalContext; > > + > > + LocalContext =3D (MTRR_LIB_GET_FIRMWARE_VARIABLE_MTRR_COUNT_CONTEXT *)= Context; > > + PatchPcdSet32 (PcdCpuNumberOfReservedVariableMtrrs, LocalContext->Numb= erOfReservedVariableMtrrs); > > + return UNIT_TEST_PASSED; > > +} > > + > > +/** > > + Initialize the unit test framework, suite, and unit tests for the > > + ResetSystemLib and run the ResetSystemLib unit test. > > + > > + @param Iteration Iteration of testing MtrrSetMemoryAttri= buteInMtrrSettings > > + and MtrrSetMemoryAttributesInMtrrSettin= gs using random inputs. > > + > > + @retval EFI_SUCCESS All test cases were dispatched. > > + @retval EFI_OUT_OF_RESOURCES There are not enough resources availabl= e to > > + initialize the unit tests. > > +**/ > > +STATIC > > +EFI_STATUS > > +EFIAPI > > +UnitTestingEntry ( > > + UINTN Iteration > > + ) > > +{ > > + EFI_STATUS Status; > > + UNIT_TEST_FRAMEWORK_HANDLE Framework; > > + UNIT_TEST_SUITE_HANDLE MtrrApiTests; > > + UINTN Index; > > + UINTN SystemIndex; > > + MTRR_LIB_TEST_CONTEXT Context; > > + MTRR_LIB_GET_FIRMWARE_VARIABLE_MTRR_COUNT_CONTEXT GetFirmwareVariableM= trrCountContext; > > + > > + Context.SystemParameter =3D &mDefaultSyste= mParameter; > > + GetFirmwareVariableMtrrCountContext.SystemParameter =3D &mDefaultSyste= mParameter; > > + Framework =3D NULL; > > + > > + DEBUG ((DEBUG_INFO, "%a v%a\n", UNIT_TEST_APP_NAME, UNIT_TEST_APP_VERS= ION)); > > + > > + // > > + // Setup the test framework for running the tests. > > + // > > + Status =3D InitUnitTestFramework (&Framework, UNIT_TEST_APP_NAME, gEfi= CallerBaseName, UNIT_TEST_APP_VERSION); > > + if (EFI_ERROR (Status)) { > > + DEBUG ((DEBUG_ERROR, "Failed in InitUnitTestFramework. Status =3D %r= \n", Status)); > > + goto EXIT; > > + } > > + > > + // > > + // --------------Suite-----------Description--------------Name--------= --Function--------Pre---Post-------------------Context----------- > > + // > > + > > + // > > + // Populate the MtrrLib API Unit Test Suite. > > + // > > + Status =3D CreateUnitTestSuite (&MtrrApiTests, Framework, "MtrrLib API= Tests", "MtrrLib.MtrrLib", NULL, NULL); > > + if (EFI_ERROR (Status)) { > > + DEBUG ((DEBUG_ERROR, "Failed in CreateUnitTestSuite for MtrrLib API = Tests\n")); > > + Status =3D EFI_OUT_OF_RESOURCES; > > + goto EXIT; > > + } > > + AddTestCase (MtrrApiTests, "Test IsMtrrSupported", = "MtrrSupported", > UnitTestIsMtrrSupported, NULL, NULL, &Context); > > + AddTestCase (MtrrApiTests, "Test GetVariableMtrrCount", = "GetVariableMtrrCount", > UnitTestGetVariableMtrrCount, NULL, NULL, &Context); > > + AddTestCase (MtrrApiTests, "Test GetFirmwareVariableMtrrCount", = "GetFirmwareVariableMtrrCount", > UnitTestGetFirmwareVariableMtrrCount, SavePcdValue, RestorePcdVal= ue, &GetFirmwareVariableMtrrCountContext); > > + AddTestCase (MtrrApiTests, "Test MtrrGetMemoryAttribute", = "MtrrGetMemoryAttribute", > UnitTestMtrrGetMemoryAttribute, NULL, NULL, &Context); > > + AddTestCase (MtrrApiTests, "Test MtrrGetFixedMtrr", = "MtrrGetFixedMtrr", > UnitTestMtrrGetFixedMtrr, NULL, NULL, &Context); > > + AddTestCase (MtrrApiTests, "Test MtrrGetAllMtrrs", = "MtrrGetAllMtrrs", > UnitTestMtrrGetAllMtrrs, NULL, NULL, &Context); > > + AddTestCase (MtrrApiTests, "Test MtrrSetAllMtrrs", = "MtrrSetAllMtrrs", UnitTestMtrrSetAllMtrrs, > NULL, NULL, &Context); > > + AddTestCase (MtrrApiTests, "Test MtrrGetMemoryAttributeInVariableMtrr"= , "MtrrGetMemoryAttributeInVariableMtrr", > UnitTestMtrrGetMemoryAttributeInVariableMtrr, NULL, NULL, &Context); > > + AddTestCase (MtrrApiTests, "Test MtrrDebugPrintAllMtrrs", = "MtrrDebugPrintAllMtrrs", > UnitTestMtrrDebugPrintAllMtrrs, NULL, NULL, &Context); > > + AddTestCase (MtrrApiTests, "Test MtrrGetDefaultMemoryType", = "MtrrGetDefaultMemoryType", > UnitTestMtrrGetDefaultMemoryType, NULL, NULL, &Context); > > + > > + for (SystemIndex =3D 0; SystemIndex < ARRAY_SIZE (mSystemParameters); = SystemIndex++) { > > + for (Index =3D 0; Index < Iteration; Index++) { > > + AddTestCase (MtrrApiTests, "Test InvalidMemoryLayouts", = "InvalidMemoryLayouts", > UnitTestInvalidMemoryLayouts, InitializeMtrrRegs, NULL, = &mSystemParameters[SystemIndex]); > > + AddTestCase (MtrrApiTests, "Test MtrrSetMemoryAttributeInMtrrSetti= ngs", "MtrrSetMemoryAttributeInMtrrSettings", > UnitTestMtrrSetMemoryAttributeInMtrrSettings, InitializeMtrrRegs, NULL, = &mSystemParameters[SystemIndex]); > > + AddTestCase (MtrrApiTests, "Test MtrrSetMemoryAttributesInMtrrSett= ings", > "MtrrSetMemoryAttributesInMtrrSettings", UnitTestMtrrSetMemoryAttributesI= nMtrrSettings, InitializeMtrrRegs, NULL, > &mSystemParameters[SystemIndex]); > > + } > > + } > > + // > > + // Execute the tests. > > + // > > + srand ((unsigned int) time (NULL)); > > + Status =3D RunAllTestSuites (Framework); > > + > > +EXIT: > > + if (Framework !=3D NULL) { > > + FreeUnitTestFramework (Framework); > > + } > > + > > + return Status; > > +} > > + > > +/** > > + Standard POSIX C entry point for host based unit test execution. > > + > > + @param Argc Number of arguments. > > + @param Argv Array of arguments. > > + > > + @return Test application exit code. > > +**/ > > +INT32 > > +main ( > > + INT32 Argc, > > + CHAR8 *Argv[] > > + ) > > +{ > > + UINTN Iteration; > > + > > + // > > + // First parameter specifies the test iterations. > > + // Default is 10. > > + // > > + Iteration =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 > index 0000000000..25d4269589 > --- /dev/null > +++ b/UefiCpuPkg/Library/MtrrLib/UnitTest/MtrrLibUnitTest.h > @@ -0,0 +1,171 @@ > +/** @file > > + > > + Copyright (c) 2020, Intel Corporation. All rights reserved.
> > + SPDX-License-Identifier: BSD-2-Clause-Patent > > + > > +**/ > > + > > +#ifndef _MTRR_SUPPORT_H_ > > +#define _MTRR_SUPPORT_H_ > > + > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > + > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > + > > +#include > > +#include > > +#include > > + > > +#define UNIT_TEST_APP_NAME "MtrrLib Unit Tests" > > +#define UNIT_TEST_APP_VERSION "1.0" > > + > > +#define SCRATCH_BUFFER_SIZE SIZE_16KB > > + > > +typedef struct { > > + UINT8 PhysicalAddressBits; > > + BOOLEAN MtrrSupported; > > + BOOLEAN FixedMtrrSupported; > > + MTRR_MEMORY_CACHE_TYPE DefaultCacheType; > > + UINT32 VariableMtrrCount; > > +} MTRR_LIB_SYSTEM_PARAMETER; > > + > > +extern UINT32 mFixedMtrrsIndex[]; > > + > > +/** > > + Initialize the MTRR registers. > > + > > + @param SystemParameter System parameter that controls the MTRR registe= rs initialization. > > +**/ > > +UNIT_TEST_STATUS > > +EFIAPI > > +InitializeMtrrRegs ( > > + IN MTRR_LIB_SYSTEM_PARAMETER *SystemParameter > > + ); > > + > > +/** > > + Return a random memory cache type. > > +**/ > > +MTRR_MEMORY_CACHE_TYPE > > +GenerateRandomCacheType ( > > + VOID > > + ); > > + > > +/** > > + Generate random MTRRs. > > + > > + @param PhysicalAddressBits Physical address bits. > > + @param RawMemoryRanges Return the randomly generated MTRRs. > > + @param UcCount Count of Uncacheable MTRRs. > > + @param WtCount Count of Write Through MTRRs. > > + @param WbCount Count of Write Back MTRRs. > > + @param WpCount Count of Write Protected MTRRs. > > + @param WcCount Count of Write Combining MTRRs. > > +**/ > > +VOID > > +GenerateValidAndConfigurableMtrrPairs ( > > + IN UINT32 PhysicalAddressBits, > > + IN OUT MTRR_MEMORY_RANGE *RawMemoryRanges, > > + IN UINT32 UcCount, > > + IN UINT32 WtCount, > > + IN UINT32 WbCount, > > + IN UINT32 WpCount, > > + IN UINT32 WcCount > > + ); > > + > > +/** > > + Convert the MTRR BASE/MASK array to memory ranges. > > + > > + @param DefaultType Default memory type. > > + @param PhysicalAddressBits Physical address bits. > > + @param RawMemoryRanges Raw memory ranges. > > + @param RawMemoryRangeCount Count of raw memory ranges. > > + @param MemoryRanges Memory ranges. > > + @param MemoryRangeCount Count of memory ranges. > > +**/ > > +VOID > > +GetEffectiveMemoryRanges ( > > + IN MTRR_MEMORY_CACHE_TYPE DefaultType, > > + IN UINT32 PhysicalAddressBits, > > + IN MTRR_MEMORY_RANGE *RawMemoryRanges, > > + IN UINT32 RawMemoryRangeCount, > > + OUT MTRR_MEMORY_RANGE *MemoryRanges, > > + OUT UINTN *MemoryRangeCount > > + ); > > + > > +/** > > + Generate random MTRR BASE/MASK for a specified type. > > + > > + @param PhysicalAddressBits Physical address bits. > > + @param CacheType Cache type. > > + @param MtrrPair Return the random MTRR. > > + @param MtrrMemoryRange Return the random memory range. > > +**/ > > +VOID > > +GenerateRandomMtrrPair ( > > + IN UINT32 PhysicalAddressBits, > > + IN MTRR_MEMORY_CACHE_TYPE CacheType, > > + OUT MTRR_VARIABLE_SETTING *MtrrPair, OPTIONAL > > + OUT MTRR_MEMORY_RANGE *MtrrMemoryRange OPTIONAL > > + ); > > + > > +/** > > + Collect the test result. > > + > > + @param DefaultType Default memory type. > > + @param PhysicalAddressBits Physical address bits. > > + @param VariableMtrrCount Count of variable MTRRs. > > + @param Mtrrs MTRR settings to collect from. > > + @param Ranges Return the memory ranges. > > + @param RangeCount Return the count of memory ranges. > > + @param MtrrCount Return the count of variable MTRRs being u= sed. > > +**/ > > +VOID > > +CollectTestResult ( > > + IN MTRR_MEMORY_CACHE_TYPE DefaultType, > > + IN UINT32 PhysicalAddressBits, > > + IN UINT32 VariableMtrrCount, > > + IN MTRR_SETTINGS *Mtrrs, > > + OUT MTRR_MEMORY_RANGE *Ranges, > > + IN OUT UINTN *RangeCount, > > + OUT UINT32 *MtrrCount > > + ); > > + > > +/** > > + Return a 64bit random number. > > + > > + @param Start Start of the random number range. > > + @param Limit Limit of the random number range. > > + @return 64bit random number > > +**/ > > +UINT64 > > +Random64 ( > > + UINT64 Start, > > + UINT64 Limit > > + ); > > + > > +/** > > + Return a 32bit random number. > > + > > + @param Start Start of the random number range. > > + @param Limit Limit of the random number range. > > + @return 32bit random number > > +**/ > > +UINT32 > > +Random32 ( > > + UINT32 Start, > > + UINT32 Limit > > + ); > > +#endif > > diff --git a/UefiCpuPkg/Library/MtrrLib/UnitTest/MtrrLibUnitTestHost.inf > b/UefiCpuPkg/Library/MtrrLib/UnitTest/MtrrLibUnitTestHost.inf > new file mode 100644 > index 0000000000..447238dc81 > --- /dev/null > +++ b/UefiCpuPkg/Library/MtrrLib/UnitTest/MtrrLibUnitTestHost.inf > @@ -0,0 +1,39 @@ > +## @file > > +# Unit tests of the MtrrLib instance of the MtrrLib class > > +# > > +# Copyright (c) 2020, Intel Corporation. All rights reserved.
> > +# SPDX-License-Identifier: BSD-2-Clause-Patent > > +## > > + > > +[Defines] > > + INF_VERSION =3D 0x00010006 > > + BASE_NAME =3D MtrrLibUnitTestHost > > + FILE_GUID =3D A1542D84-B64D-4847-885E-0509084376A= B > > + MODULE_TYPE =3D HOST_APPLICATION > > + VERSION_STRING =3D 1.0 > > + > > +# > > +# The following information is for reference only and not required by th= e build tools. > > +# > > +# VALID_ARCHITECTURES =3D IA32 X64 > > +# > > + > > +[Sources] > > + MtrrLibUnitTest.c > > + MtrrLibUnitTest.h > > + Support.c > > + > > +[Packages] > > + MdePkg/MdePkg.dec > > + UefiCpuPkg/UefiCpuPkg.dec > > + UnitTestFrameworkPkg/UnitTestFrameworkPkg.dec > > + > > +[LibraryClasses] > > + BaseLib > > + BaseMemoryLib > > + DebugLib > > + MtrrLib > > + UnitTestLib > > + > > +[Pcd] > > + gUefiCpuPkgTokenSpaceGuid.PcdCpuNumberOfReservedVariableMtrrs ## SOM= ETIMES_CONSUMES > > diff --git a/UefiCpuPkg/Library/MtrrLib/UnitTest/Support.c b/UefiCpuPkg/L= ibrary/MtrrLib/UnitTest/Support.c > new file mode 100644 > index 0000000000..9fe4b0278e > --- /dev/null > +++ b/UefiCpuPkg/Library/MtrrLib/UnitTest/Support.c > @@ -0,0 +1,913 @@ > +/** @file > > + Unit tests of the MtrrLib instance of the MtrrLib class > > + > > + Copyright (c) 2018 - 2020, Intel Corporation. All rights reserved.
> > + SPDX-License-Identifier: BSD-2-Clause-Patent > > + > > +**/ > > + > > +#include "MtrrLibUnitTest.h" > > + > > +MTRR_MEMORY_CACHE_TYPE mMemoryCacheTypes[] =3D { > > + CacheUncacheable, CacheWriteCombining, CacheWriteThrough, CacheWritePr= otected, CacheWriteBack > > + }; > > + > > +UINT64 mFixedMtrrsValue[MTRR_NUMBER_OF_FIXED_M= TRR]; > > +MSR_IA32_MTRR_PHYSBASE_REGISTER mVariableMtrrsPhysBase[MTRR_NUMBER_OF_V= ARIABLE_MTRR]; > > +MSR_IA32_MTRR_PHYSMASK_REGISTER mVariableMtrrsPhysMask[MTRR_NUMBER_OF_V= ARIABLE_MTRR]; > > +MSR_IA32_MTRR_DEF_TYPE_REGISTER mDefTypeMsr; > > +MSR_IA32_MTRRCAP_REGISTER mMtrrCapMsr; > > +CPUID_VERSION_INFO_EDX mCpuidVersionInfoEdx; > > +CPUID_VIR_PHY_ADDRESS_SIZE_EAX mCpuidVirPhyAddressSizeEax; > > + > > +/** > > + Retrieves CPUID information. > > + > > + Executes the CPUID instruction with EAX set to the value specified by = Index. > > + This function always returns Index. > > + If Eax is not NULL, then the value of EAX after CPUID is returned in E= ax. > > + If Ebx is not NULL, then the value of EBX after CPUID is returned in E= bx. > > + If Ecx is not NULL, then the value of ECX after CPUID is returned in E= cx. > > + If Edx is not NULL, then the value of EDX after CPUID is returned in E= dx. > > + This function is only available on IA-32 and x64. > > + > > + @param Index The 32-bit value to load into EAX prior to invoking the = CPUID > > + instruction. > > + @param Eax The pointer to the 32-bit EAX value returned by the CPUI= D > > + instruction. This is an optional parameter that may be N= ULL. > > + @param Ebx The pointer to the 32-bit EBX value returned by the CPUI= D > > + instruction. This is an optional parameter that may be N= ULL. > > + @param Ecx The pointer to the 32-bit ECX value returned by the CPUI= D > > + instruction. This is an optional parameter that may be N= ULL. > > + @param Edx The pointer to the 32-bit EDX value returned by the CPUI= D > > + instruction. This is an optional parameter that may be N= ULL. > > + > > + @return Index. > > + > > +**/ > > +UINT32 > > +EFIAPI > > +UnitTestMtrrLibAsmCpuid ( > > + IN UINT32 Index, > > + OUT UINT32 *Eax, OPTIONAL > > + OUT UINT32 *Ebx, OPTIONAL > > + OUT UINT32 *Ecx, OPTIONAL > > + OUT UINT32 *Edx OPTIONAL > > + ) > > +{ > > + switch (Index) { > > + case CPUID_VERSION_INFO: > > + if (Edx !=3D NULL) { > > + *Edx =3D mCpuidVersionInfoEdx.Uint32; > > + } > > + return Index; > > + break; > > + case CPUID_EXTENDED_FUNCTION: > > + if (Eax !=3D NULL) { > > + *Eax =3D CPUID_VIR_PHY_ADDRESS_SIZE; > > + } > > + return Index; > > + break; > > + case CPUID_VIR_PHY_ADDRESS_SIZE: > > + if (Eax !=3D NULL) { > > + *Eax =3D mCpuidVirPhyAddressSizeEax.Uint32; > > + } > > + return Index; > > + break; > > + } > > + > > + // > > + // Should never fall through to here > > + // > > + ASSERT(FALSE); > > + return Index; > > +} > > + > > +/** > > + Returns a 64-bit Machine Specific Register(MSR). > > + > > + Reads and returns the 64-bit MSR specified by Index. No parameter chec= king is > > + performed on Index, and some Index values may cause CPU exceptions. Th= e > > + caller must either guarantee that Index is valid, or the caller must s= et up > > + exception handlers to catch the exceptions. This function is only avai= lable > > + on IA-32 and x64. > > + > > + @param MsrIndex The 32-bit MSR index to read. > > + > > + @return The value of the MSR identified by MsrIndex. > > + > > +**/ > > +UINT64 > > +EFIAPI > > +UnitTestMtrrLibAsmReadMsr64( > > + IN UINT32 MsrIndex > > + ) > > +{ > > + UINT32 Index; > > + > > + for (Index =3D 0; Index < ARRAY_SIZE (mFixedMtrrsValue); Index++) { > > + if (MsrIndex =3D=3D mFixedMtrrsIndex[Index]) { > > + return mFixedMtrrsValue[Index]; > > + } > > + } > > + > > + if ((MsrIndex >=3D MSR_IA32_MTRR_PHYSBASE0) && > > + (MsrIndex <=3D MSR_IA32_MTRR_PHYSMASK0 + (MTRR_NUMBER_OF_VARIABLE_= MTRR << 1))) { > > + if (MsrIndex % 2 =3D=3D 0) { > > + Index =3D (MsrIndex - MSR_IA32_MTRR_PHYSBASE0) >> 1; > > + return mVariableMtrrsPhysBase[Index].Uint64; > > + } else { > > + Index =3D (MsrIndex - MSR_IA32_MTRR_PHYSMASK0) >> 1; > > + return mVariableMtrrsPhysMask[Index].Uint64; > > + } > > + } > > + > > + if (MsrIndex =3D=3D MSR_IA32_MTRR_DEF_TYPE) { > > + return mDefTypeMsr.Uint64; > > + } > > + > > + if (MsrIndex =3D=3D MSR_IA32_MTRRCAP) { > > + return mMtrrCapMsr.Uint64; > > + } > > + > > + // > > + // Should never fall through to here > > + // > > + ASSERT(FALSE); > > + return 0; > > +} > > + > > +/** > > + Writes a 64-bit value to a Machine Specific Register(MSR), and returns= the > > + value. > > + > > + Writes the 64-bit value specified by Value to the MSR specified by Ind= ex. The > > + 64-bit value written to the MSR is returned. No parameter checking is > > + performed on Index or Value, and some of these may cause CPU exception= s. The > > + caller must either guarantee that Index and Value are valid, or the ca= ller > > + must establish proper exception handlers. This function is only availa= ble on > > + IA-32 and x64. > > + > > + @param MsrIndex The 32-bit MSR index to write. > > + @param Value The 64-bit value to write to the MSR. > > + > > + @return Value > > + > > +**/ > > +UINT64 > > +EFIAPI > > +UnitTestMtrrLibAsmWriteMsr64( > > + IN UINT32 MsrIndex, > > + IN UINT64 Value > > + ) > > +{ > > + UINT32 Index; > > + > > + for (Index =3D 0; Index < ARRAY_SIZE (mFixedMtrrsValue); Index++) { > > + if (MsrIndex =3D=3D mFixedMtrrsIndex[Index]) { > > + mFixedMtrrsValue[Index] =3D Value; > > + return Value; > > + } > > + } > > + > > + if ((MsrIndex >=3D MSR_IA32_MTRR_PHYSBASE0) && > > + (MsrIndex <=3D MSR_IA32_MTRR_PHYSMASK0 + (MTRR_NUMBER_OF_VARIABLE_= MTRR << 1))) { > > + if (MsrIndex % 2 =3D=3D 0) { > > + Index =3D (MsrIndex - MSR_IA32_MTRR_PHYSBASE0) >> 1; > > + mVariableMtrrsPhysBase[Index].Uint64 =3D Value; > > + return Value; > > + } else { > > + Index =3D (MsrIndex - MSR_IA32_MTRR_PHYSMASK0) >> 1; > > + mVariableMtrrsPhysMask[Index].Uint64 =3D Value; > > + return Value; > > + } > > + } > > + > > + if (MsrIndex =3D=3D MSR_IA32_MTRR_DEF_TYPE) { > > + mDefTypeMsr.Uint64 =3D Value; > > + return Value; > > + } > > + > > + if (MsrIndex =3D=3D MSR_IA32_MTRRCAP) { > > + mMtrrCapMsr.Uint64 =3D Value; > > + return Value; > > + } > > + > > + // > > + // Should never fall through to here > > + // > > + ASSERT(FALSE); > > + return 0; > > +} > > + > > +/** > > + Initialize MTRR registers. > > +**/ > > + > > +/** > > + Initialize the MTRR registers. > > + > > + @param SystemParameter System parameter that controls the MTRR registe= rs initialization. > > +**/ > > +UNIT_TEST_STATUS > > +EFIAPI > > +InitializeMtrrRegs ( > > + IN MTRR_LIB_SYSTEM_PARAMETER *SystemParameter > > + ) > > +{ > > + UINT32 Index; > > + > > + SetMem (mFixedMtrrsValue, sizeof (mFixedMtrrsValue), SystemParameter->= DefaultCacheType); > > + > > + for (Index =3D 0; Index < ARRAY_SIZE (mVariableMtrrsPhysBase); Index++= ) { > > + mVariableMtrrsPhysBase[Index].Uint64 =3D 0; > > + mVariableMtrrsPhysBase[Index].Bits.Type =3D SystemParameter->De= faultCacheType; > > + mVariableMtrrsPhysBase[Index].Bits.Reserved1 =3D 0; > > + > > + mVariableMtrrsPhysMask[Index].Uint64 =3D 0; > > + mVariableMtrrsPhysMask[Index].Bits.V =3D 0; > > + mVariableMtrrsPhysMask[Index].Bits.Reserved1 =3D 0; > > + } > > + > > + mDefTypeMsr.Bits.E =3D 1; > > + mDefTypeMsr.Bits.FE =3D 1; > > + mDefTypeMsr.Bits.Type =3D SystemParameter->DefaultCacheType; > > + mDefTypeMsr.Bits.Reserved1 =3D 0; > > + mDefTypeMsr.Bits.Reserved2 =3D 0; > > + mDefTypeMsr.Bits.Reserved3 =3D 0; > > + > > + mMtrrCapMsr.Bits.SMRR =3D 0; > > + mMtrrCapMsr.Bits.WC =3D 0; > > + mMtrrCapMsr.Bits.VCNT =3D SystemParameter->VariableMtrrCount; > > + mMtrrCapMsr.Bits.FIX =3D SystemParameter->FixedMtrrSupported; > > + mMtrrCapMsr.Bits.Reserved1 =3D 0; > > + mMtrrCapMsr.Bits.Reserved2 =3D 0; > > + mMtrrCapMsr.Bits.Reserved3 =3D 0; > > + > > + mCpuidVersionInfoEdx.Bits.MTRR =3D SystemParamete= r->MtrrSupported; > > + mCpuidVirPhyAddressSizeEax.Bits.PhysicalAddressBits =3D SystemParamete= r->PhysicalAddressBits; > > + > > + // > > + // Hook BaseLib functions used by MtrrLib that require some emulation. > > + // > > + gUnitTestHostBaseLib.X86->AsmCpuid =3D UnitTestMtrrLibAsmCpuid; > > + gUnitTestHostBaseLib.X86->AsmReadMsr64 =3D UnitTestMtrrLibAsmReadMsr6= 4; > > + gUnitTestHostBaseLib.X86->AsmWriteMsr64 =3D UnitTestMtrrLibAsmWriteMsr= 64; > > + > > + return UNIT_TEST_PASSED; > > +} > > + > > +/** > > + Collect the test result. > > + > > + @param DefaultType Default memory type. > > + @param PhysicalAddressBits Physical address bits. > > + @param VariableMtrrCount Count of variable MTRRs. > > + @param Mtrrs MTRR settings to collect from. > > + @param Ranges Return the memory ranges. > > + @param RangeCount Return the count of memory ranges. > > + @param MtrrCount Return the count of variable MTRRs being u= sed. > > +**/ > > +VOID > > +CollectTestResult ( > > + IN MTRR_MEMORY_CACHE_TYPE DefaultType, > > + IN UINT32 PhysicalAddressBits, > > + IN UINT32 VariableMtrrCount, > > + IN MTRR_SETTINGS *Mtrrs, > > + OUT MTRR_MEMORY_RANGE *Ranges, > > + IN OUT UINTN *RangeCount, > > + OUT UINT32 *MtrrCount > > + ) > > +{ > > + UINTN Index; > > + UINT64 MtrrValidBitsMask; > > + UINT64 MtrrValidAddressMask; > > + MTRR_MEMORY_RANGE RawMemoryRanges[ARRAY_SIZE (Mtrrs->Variables.Mtrr)]; > > + > > + ASSERT (Mtrrs !=3D NULL); > > + ASSERT (VariableMtrrCount <=3D ARRAY_SIZE (Mtrrs->Variables.Mtrr)); > > + > > + MtrrValidBitsMask =3D (1ull << PhysicalAddressBits) - 1; > > + MtrrValidAddressMask =3D MtrrValidBitsMask & ~0xFFFull; > > + > > + *MtrrCount =3D 0; > > + for (Index =3D 0; Index < VariableMtrrCount; Index++) { > > + if (((MSR_IA32_MTRR_PHYSMASK_REGISTER *) &Mtrrs->Variables.Mtrr[Inde= x].Mask)->Bits.V =3D=3D 1) { > > + RawMemoryRanges[*MtrrCount].BaseAddress =3D Mtrrs->Variables.Mtrr[= Index].Base & MtrrValidAddressMask; > > + RawMemoryRanges[*MtrrCount].Type =3D > > + ((MSR_IA32_MTRR_PHYSBASE_REGISTER *) &Mtrrs->Variables.Mtrr[Inde= x].Base)->Bits.Type; > > + RawMemoryRanges[*MtrrCount].Length =3D > > + ((~(Mtrrs->Variables.Mtrr[Index].Mask & MtrrValidAddressMask))= & MtrrValidBitsMask) + 1; > > + (*MtrrCount)++; > > + } > > + } > > + > > + GetEffectiveMemoryRanges (DefaultType, PhysicalAddressBits, RawMemoryR= anges, *MtrrCount, Ranges, RangeCount); > > +} > > + > > +/** > > + Return a 32bit random number. > > + > > + @param Start Start of the random number range. > > + @param Limit Limit of the random number range. > > + @return 32bit random number > > +**/ > > +UINT32 > > +Random32 ( > > + UINT32 Start, > > + UINT32 Limit > > + ) > > +{ > > + return (UINT32) (((double) rand () / RAND_MAX) * (Limit - Start)) + St= art; > > +} > > + > > +/** > > + Return a 64bit random number. > > + > > + @param Start Start of the random number range. > > + @param Limit Limit of the random number range. > > + @return 64bit random number > > +**/ > > +UINT64 > > +Random64 ( > > + UINT64 Start, > > + UINT64 Limit > > + ) > > +{ > > + return (UINT64) (((double) rand () / RAND_MAX) * (Limit - Start)) + St= art; > > +} > > + > > +/** > > + Generate random MTRR BASE/MASK for a specified type. > > + > > + @param PhysicalAddressBits Physical address bits. > > + @param CacheType Cache type. > > + @param MtrrPair Return the random MTRR. > > + @param MtrrMemoryRange Return the random memory range. > > +**/ > > +VOID > > +GenerateRandomMtrrPair ( > > + IN UINT32 PhysicalAddressBits, > > + IN MTRR_MEMORY_CACHE_TYPE CacheType, > > + OUT MTRR_VARIABLE_SETTING *MtrrPair, OPTIONAL > > + OUT MTRR_MEMORY_RANGE *MtrrMemoryRange OPTIONAL > > + ) > > +{ > > + MSR_IA32_MTRR_PHYSBASE_REGISTER PhysBase; > > + MSR_IA32_MTRR_PHYSMASK_REGISTER PhysMask; > > + UINT32 SizeShift; > > + UINT32 BaseShift; > > + UINT64 RandomBoundary; > > + UINT64 MaxPhysicalAddress; > > + UINT64 RangeSize; > > + UINT64 RangeBase; > > + UINT64 PhysBasePhyMaskValidBitsMask; > > + > > + MaxPhysicalAddress =3D 1ull << PhysicalAddressBits; > > + do { > > + SizeShift =3D Random32 (12, PhysicalAddressBits - 1); > > + RangeSize =3D 1ull << SizeShift; > > + > > + BaseShift =3D Random32 (SizeShift, PhysicalAddressBits - 1); > > + RandomBoundary =3D Random64 (0, 1ull << (PhysicalAddressBits - BaseS= hift)); > > + RangeBase =3D RandomBoundary << BaseShift; > > + } while (RangeBase < SIZE_1MB || RangeBase > MaxPhysicalAddress - 1); > > + > > + PhysBasePhyMaskValidBitsMask =3D (MaxPhysicalAddress - 1) & 0xffffffff= fffff000ULL; > > + > > + PhysBase.Uint64 =3D 0; > > + PhysBase.Bits.Type =3D CacheType; > > + PhysBase.Uint64 |=3D RangeBase & PhysBasePhyMaskValidBitsMask; > > + PhysMask.Uint64 =3D 0; > > + PhysMask.Bits.V =3D 1; > > + PhysMask.Uint64 |=3D ((~RangeSize) + 1) & PhysBasePhyMaskValidBitsMa= sk; > > + > > + if (MtrrPair !=3D NULL) { > > + MtrrPair->Base =3D PhysBase.Uint64; > > + MtrrPair->Mask =3D PhysMask.Uint64; > > + } > > + > > + if (MtrrMemoryRange !=3D NULL) { > > + MtrrMemoryRange->BaseAddress =3D RangeBase; > > + MtrrMemoryRange->Length =3D RangeSize; > > + MtrrMemoryRange->Type =3D CacheType; > > + } > > +} > > + > > + > > +/** > > + Check whether the Range overlaps with any one in Ranges. > > + > > + @param Range The memory range to check. > > + @param Ranges The memory ranges. > > + @param Count Count of memory ranges. > > + > > + @return TRUE when overlap exists. > > +**/ > > +BOOLEAN > > +RangesOverlap ( > > + IN MTRR_MEMORY_RANGE *Range, > > + IN MTRR_MEMORY_RANGE *Ranges, > > + IN UINTN Count > > + ) > > +{ > > + while (Count-- !=3D 0) { > > + // > > + // Two ranges overlap when: > > + // 1. range#2.base is in the middle of range#1 > > + // 2. range#1.base is in the middle of range#2 > > + // > > + if ((Range->BaseAddress <=3D Ranges[Count].BaseAddress && Ranges[Cou= nt].BaseAddress < Range->BaseAddress + > Range->Length) > > + || (Ranges[Count].BaseAddress <=3D Range->BaseAddress && Range->Bas= eAddress < Ranges[Count].BaseAddress + > Ranges[Count].Length)) { > > + return TRUE; > > + } > > + } > > + return FALSE; > > +} > > + > > +/** > > + Generate random MTRRs. > > + > > + @param PhysicalAddressBits Physical address bits. > > + @param RawMemoryRanges Return the randomly generated MTRRs. > > + @param UcCount Count of Uncacheable MTRRs. > > + @param WtCount Count of Write Through MTRRs. > > + @param WbCount Count of Write Back MTRRs. > > + @param WpCount Count of Write Protected MTRRs. > > + @param WcCount Count of Write Combine MTRRs. > > +**/ > > +VOID > > +GenerateValidAndConfigurableMtrrPairs ( > > + IN UINT32 PhysicalAddressBits, > > + IN OUT MTRR_MEMORY_RANGE *RawMemoryRanges, > > + IN UINT32 UcCount, > > + IN UINT32 WtCount, > > + IN UINT32 WbCount, > > + IN UINT32 WpCount, > > + IN UINT32 WcCount > > + ) > > +{ > > + UINT32 Index; > > + > > + // > > + // 1. Generate UC, WT, WB in order. > > + // > > + for (Index =3D 0; Index < UcCount; Index++) { > > + GenerateRandomMtrrPair (PhysicalAddressBits, CacheUncacheable, NULL,= &RawMemoryRanges[Index]); > > + } > > + > > + for (Index =3D UcCount; Index < UcCount + WtCount; Index++) { > > + GenerateRandomMtrrPair (PhysicalAddressBits, CacheWriteThrough, NULL= , &RawMemoryRanges[Index]); > > + } > > + > > + for (Index =3D UcCount + WtCount; Index < UcCount + WtCount + WbCount;= Index++) { > > + GenerateRandomMtrrPair (PhysicalAddressBits, CacheWriteBack, NULL, &= RawMemoryRanges[Index]); > > + } > > + > > + // > > + // 2. Generate WP MTRR and DO NOT overlap with WT, WB. > > + // > > + for (Index =3D UcCount + WtCount + WbCount; Index < UcCount + WtCount = + WbCount + WpCount; Index++) { > > + GenerateRandomMtrrPair (PhysicalAddressBits, CacheWriteProtected, NU= LL, &RawMemoryRanges[Index]); > > + while (RangesOverlap (&RawMemoryRanges[Index], &RawMemoryRanges[UcCo= unt], WtCount + WbCount)) { > > + GenerateRandomMtrrPair (PhysicalAddressBits, 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++) { > > + GenerateRandomMtrrPair (PhysicalAddressBits, CacheWriteCombining, NU= LL, &RawMemoryRanges[Index]); > > + while (RangesOverlap (&RawMemoryRanges[Index], &RawMemoryRanges[UcCo= unt], WtCount + WbCount + WpCount)) > { > > + GenerateRandomMtrrPair (PhysicalAddressBits, CacheWriteCombining, = NULL, &RawMemoryRanges[Index]); > > + } > > + } > > +} > > + > > +/** > > + Return a random memory cache type. > > +**/ > > +MTRR_MEMORY_CACHE_TYPE > > +GenerateRandomCacheType ( > > + VOID > > + ) > > +{ > > + return mMemoryCacheTypes[Random32 (0, ARRAY_SIZE (mMemoryCacheTypes)= - 1)]; > > +} > > + > > +/** > > + Compare function used by qsort(). > > +**/ > > + > > +/** > > + Compare function used by qsort(). > > + > > + @param Left Left operand to compare. > > + @param Right Right operand to compare. > > + > > + @retval 0 Left =3D=3D Right > > + @retval -1 Left < Right > > + @retval 1 Left > Right > > +**/ > > +INT32 > > +CompareFuncUint64 ( > > + CONST VOID * Left, > > + CONST VOID * Right > > + ) > > +{ > > + INT64 Delta; > > + Delta =3D (*(UINT64*)Left - *(UINT64*)Right); > > + if (Delta > 0) { > > + return 1; > > + } else if (Delta =3D=3D 0) { > > + return 0; > > + } else { > > + return -1; > > + } > > +} > > + > > +/** > > + Determin the memory cache type for the Range. > > + > > + @param DefaultType Default cache type. > > + @param Range The memory range to determin the cache type. > > + @param Ranges The entire memory ranges. > > + @param RangeCount Count of the entire memory ranges. > > +**/ > > +VOID > > +DetermineMemoryCacheType ( > > + IN MTRR_MEMORY_CACHE_TYPE DefaultType, > > + IN OUT MTRR_MEMORY_RANGE *Range, > > + IN MTRR_MEMORY_RANGE *Ranges, > > + IN UINT32 RangeCount > > + ) > > +{ > > + UINT32 Index; > > + Range->Type =3D CacheInvalid; > > + for (Index =3D 0; Index < RangeCount; Index++) { > > + if (RangesOverlap (Range, &Ranges[Index], 1)) { > > + if (Ranges[Index].Type < Range->Type) { > > + Range->Type =3D Ranges[Index].Type; > > + } > > + } > > + } > > + > > + if (Range->Type =3D=3D CacheInvalid) { > > + Range->Type =3D DefaultType; > > + } > > +} > > + > > +/** > > + Get the index of the element that does NOT equals to Array[Index]. > > + > > + @param Index Current element. > > + @param Array Array to scan. > > + @param Count Count of the array. > > + > > + @return Next element that doesn't equal to current one. > > +**/ > > +UINT32 > > +GetNextDifferentElementInSortedArray ( > > + IN UINT32 Index, > > + IN UINT64 *Array, > > + IN UINT32 Count > > + ) > > +{ > > + UINT64 CurrentElement; > > + CurrentElement =3D Array[Index]; > > + while (CurrentElement =3D=3D Array[Index] && Index < Count) { > > + Index++; > > + } > > + return Index; > > +} > > + > > +/** > > + Remove the duplicates from the array. > > + > > + @param Array The array to operate on. > > + @param Count Count of the array. > > +**/ > > +VOID > > +RemoveDuplicatesInSortedArray ( > > + IN OUT UINT64 *Array, > > + IN OUT UINT32 *Count > > + ) > > +{ > > + UINT32 Index; > > + UINT32 NewCount; > > + > > + Index =3D 0; > > + NewCount =3D 0; > > + while (Index < *Count) { > > + Array[NewCount] =3D Array[Index]; > > + NewCount++; > > + Index =3D GetNextDifferentElementInSortedArray (Index, Array, *Count= ); > > + } > > + *Count =3D NewCount; > > +} > > + > > +/** > > + Return TRUE when Address is in the Range. > > + > > + @param Address The address to check. > > + @param Range The range to check. > > + @return TRUE when Address is in the Range. > > +**/ > > +BOOLEAN > > +AddressInRange ( > > + IN UINT64 Address, > > + IN MTRR_MEMORY_RANGE Range > > + ) > > +{ > > + return (Address >=3D Range.BaseAddress) && (Address <=3D Range.BaseA= ddress + Range.Length - 1); > > +} > > + > > +/** > > + Get the overlap bit flag. > > + > > + @param RawMemoryRanges Raw memory ranges. > > + @param RawMemoryRangeCount Count of raw memory ranges. > > + @param Address The address to check. > > +**/ > > +UINT64 > > +GetOverlapBitFlag ( > > + IN MTRR_MEMORY_RANGE *RawMemoryRanges, > > + IN UINT32 RawMemoryRangeCount, > > + IN UINT64 Address > > + ) > > +{ > > + UINT64 OverlapBitFlag; > > + UINT32 Index; > > + OverlapBitFlag =3D 0; > > + for (Index =3D 0; Index < RawMemoryRangeCount; Index++) { > > + if (AddressInRange (Address, RawMemoryRanges[Index])) { > > + OverlapBitFlag |=3D (1ull << Index); > > + } > > + } > > + > > + return OverlapBitFlag; > > +} > > + > > +/** > > + Return the relationship between flags. > > + > > + @param Flag1 Flag 1 > > + @param Flag2 Flag 2 > > + > > + @retval 0 Flag1 =3D=3D Flag2 > > + @retval 1 Flag1 is a subset of Flag2 > > + @retval 2 Flag2 is a subset of Flag1 > > + @retval 3 No subset relations between Flag1 and Flag2. > > +**/ > > +UINT32 > > +CheckOverlapBitFlagsRelation ( > > + IN UINT64 Flag1, > > + IN UINT64 Flag2 > > + ) > > +{ > > + if (Flag1 =3D=3D Flag2) return 0; > > + if ((Flag1 | Flag2) =3D=3D Flag2) return 1; > > + if ((Flag1 | Flag2) =3D=3D Flag1) return 2; > > + return 3; > > +} > > + > > +/** > > + Return TRUE when the Endpoint is in any of the Ranges. > > + > > + @param Endpoint The endpoint to check. > > + @param Ranges The memory ranges. > > + @param RangeCount Count of memory ranges. > > + > > + @retval TRUE Endpoint is in one of the range. > > + @retval FALSE Endpoint is not in any of the ranges. > > +**/ > > +BOOLEAN > > +IsEndpointInRanges ( > > + IN UINT64 Endpoint, > > + IN MTRR_MEMORY_RANGE *Ranges, > > + IN UINTN RangeCount > > + ) > > +{ > > + UINT32 Index; > > + for (Index =3D 0; Index < RangeCount; Index++) { > > + if (AddressInRange (Endpoint, Ranges[Index])) { > > + return TRUE; > > + } > > + } > > + return FALSE; > > +} > > + > > + > > +/** > > + Compact adjacent ranges of the same type. > > + > > + @param DefaultType Default memory type. > > + @param PhysicalAddressBits Physical address bits. > > + @param EffectiveMtrrMemoryRanges Memory ranges to compact. > > + @param EffectiveMtrrMemoryRangesCount Return the new count of memory r= anges. > > +**/ > > +VOID > > +CompactAndExtendEffectiveMtrrMemoryRanges ( > > + IN MTRR_MEMORY_CACHE_TYPE DefaultType, > > + IN UINT32 PhysicalAddressBits, > > + IN OUT MTRR_MEMORY_RANGE **EffectiveMtrrMemoryRanges, > > + IN OUT UINTN *EffectiveMtrrMemoryRangesCount > > + ) > > +{ > > + UINT64 MaxAddress; > > + UINTN NewRangesCountAtMost; > > + MTRR_MEMORY_RANGE *NewRanges; > > + UINTN NewRangesCountActual; > > + MTRR_MEMORY_RANGE *CurrentRangeInNewRanges; > > + MTRR_MEMORY_CACHE_TYPE CurrentRangeTypeInOldRanges; > > + > > + MTRR_MEMORY_RANGE *OldRanges; > > + MTRR_MEMORY_RANGE OldLastRange; > > + UINTN OldRangesIndex; > > + > > + NewRangesCountActual =3D 0; > > + NewRangesCountAtMost =3D *EffectiveMtrrMemoryRangesCount + 2; // At = most with 2 more range entries. > > + NewRanges =3D (MTRR_MEMORY_RANGE *) calloc (NewRangesCountA= tMost, sizeof (MTRR_MEMORY_RANGE)); > > + OldRanges =3D *EffectiveMtrrMemoryRanges; > > + if (OldRanges[0].BaseAddress > 0) { > > + NewRanges[NewRangesCountActual].BaseAddress =3D 0; > > + NewRanges[NewRangesCountActual].Length =3D OldRanges[0].BaseAdd= ress; > > + NewRanges[NewRangesCountActual].Type =3D DefaultType; > > + NewRangesCountActual++; > > + } > > + > > + OldRangesIndex =3D 0; > > + while (OldRangesIndex < *EffectiveMtrrMemoryRangesCount) { > > + CurrentRangeTypeInOldRanges =3D OldRanges[OldRangesIndex].Type; > > + CurrentRangeInNewRanges =3D NULL; > > + if (NewRangesCountActual > 0) // We need to check CurrentNewRange = first before generate a new NewRange. > > + { > > + CurrentRangeInNewRanges =3D &NewRanges[NewRangesCountActual - 1]; > > + } > > + if (CurrentRangeInNewRanges !=3D NULL && CurrentRangeInNewRanges->Ty= pe =3D=3D CurrentRangeTypeInOldRanges) { > > + CurrentRangeInNewRanges->Length +=3D OldRanges[OldRangesIndex].Len= gth; > > + } else { > > + NewRanges[NewRangesCountActual].BaseAddress =3D OldRanges[OldRange= sIndex].BaseAddress; > > + NewRanges[NewRangesCountActual].Length +=3D OldRanges[OldRange= sIndex].Length; > > + NewRanges[NewRangesCountActual].Type =3D CurrentRangeTypeIn= OldRanges; > > + while (OldRangesIndex + 1 < *EffectiveMtrrMemoryRangesCount && Old= Ranges[OldRangesIndex + 1].Type =3D=3D > CurrentRangeTypeInOldRanges) > > + { > > + OldRangesIndex++; > > + NewRanges[NewRangesCountActual].Length +=3D OldRanges[OldRangesI= ndex].Length; > > + } > > + NewRangesCountActual++; > > + } > > + > > + OldRangesIndex++; > > + } > > + > > + MaxAddress =3D (1ull << PhysicalAddressBits) - 1; > > + OldLastRange =3D OldRanges[(*EffectiveMtrrMemoryRangesCount) - 1]; > > + CurrentRangeInNewRanges =3D &NewRanges[NewRangesCountActual - 1]; > > + if (OldLastRange.BaseAddress + OldLastRange.Length - 1 < MaxAddress) { > > + if (CurrentRangeInNewRanges->Type =3D=3D DefaultType) { > > + CurrentRangeInNewRanges->Length =3D MaxAddress - CurrentRangeInNew= Ranges->BaseAddress + 1; > > + } else { > > + NewRanges[NewRangesCountActual].BaseAddress =3D OldLastRange.BaseA= ddress + OldLastRange.Length; > > + NewRanges[NewRangesCountActual].Length =3D MaxAddress - NewRanges[= NewRangesCountActual].BaseAddress + 1; > > + NewRanges[NewRangesCountActual].Type =3D DefaultType; > > + NewRangesCountActual++; > > + } > > + } > > + > > + free (*EffectiveMtrrMemoryRanges); > > + *EffectiveMtrrMemoryRanges =3D NewRanges; > > + *EffectiveMtrrMemoryRangesCount =3D NewRangesCountActual; > > +} > > + > > +/** > > + Collect all the endpoints in the raw memory ranges. > > + > > + @param Endpoints Return the collected endpoints. > > + @param EndPointCount Return the count of endpoints. > > + @param RawMemoryRanges Raw memory ranges. > > + @param RawMemoryRangeCount Count of raw memory ranges. > > +**/ > > +VOID > > +CollectEndpoints ( > > + IN OUT UINT64 *Endpoints, > > + IN OUT UINT32 *EndPointCount, > > + IN MTRR_MEMORY_RANGE *RawMemoryRanges, > > + IN UINT32 RawMemoryRangeCount > > + ) > > +{ > > + UINT32 Index; > > + UINT32 RawRangeIndex; > > + > > + ASSERT ((RawMemoryRangeCount << 1) =3D=3D *EndPointCount); > > + > > + for (Index =3D 0; Index < *EndPointCount; Index +=3D 2) { > > + RawRangeIndex =3D Index >> 1; > > + Endpoints[Index] =3D RawMemoryRanges[RawRangeIndex].BaseAddress; > > + 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 PhysicalAddressBits Physical address bits. > > + @param RawMemoryRanges Raw memory ranges. > > + @param RawMemoryRangeCount Count of raw memory ranges. > > + @param MemoryRanges Memory ranges. > > + @param MemoryRangeCount Count of memory ranges. > > +**/ > > +VOID > > +GetEffectiveMemoryRanges ( > > + IN MTRR_MEMORY_CACHE_TYPE DefaultType, > > + IN UINT32 PhysicalAddressBits, > > + IN MTRR_MEMORY_RANGE *RawMemoryRanges, > > + IN UINT32 RawMemoryRangeCount, > > + OUT MTRR_MEMORY_RANGE *MemoryRanges, > > + OUT UINTN *MemoryRangeCount > > + ) > > +{ > > + UINTN Index; > > + UINT32 AllEndPointsCount; > > + UINT64 *AllEndPointsInclusive; > > + UINT32 AllRangePiecesCountMax; > > + MTRR_MEMORY_RANGE *AllRangePieces; > > + UINTN AllRangePiecesCountActual; > > + UINT64 OverlapBitFlag1; > > + UINT64 OverlapBitFlag2; > > + INT32 OverlapFlagRelation; > > + > > + if (RawMemoryRangeCount =3D=3D 0) { > > + MemoryRanges[0].BaseAddress =3D 0; > > + MemoryRanges[0].Length =3D (1ull << PhysicalAddressBits); > > + MemoryRanges[0].Type =3D DefaultType; > > + *MemoryRangeCount =3D 1; > > + return; > > + } > > + > > + AllEndPointsCount =3D RawMemoryRangeCount << 1; > > + AllEndPointsInclusive =3D calloc (AllEndPointsCount, sizeof (UINT6= 4)); > > + AllRangePiecesCountMax =3D RawMemoryRangeCount * 3 + 1; > > + AllRangePieces =3D calloc (AllRangePiecesCountMax, sizeof (= MTRR_MEMORY_RANGE)); > > + CollectEndpoints (AllEndPointsInclusive, &AllEndPointsCount, RawMemory= Ranges, RawMemoryRangeCount); > > + > > + for (Index =3D 0, AllRangePiecesCountActual =3D 0; Index < AllEndPoint= sCount - 1; Index++) { > > + OverlapBitFlag1 =3D GetOverlapBitFlag (RawMemoryRanges, RawMemoryRan= geCount, AllEndPointsInclusive[Index]); > > + OverlapBitFlag2 =3D GetOverlapBitFlag (RawMemoryRanges, RawMemoryRan= geCount, AllEndPointsInclusive[Index + 1]); > > + OverlapFlagRelation =3D CheckOverlapBitFlagsRelation (OverlapBitFlag= 1, OverlapBitFlag2); > > + switch (OverlapFlagRelation) { > > + case 0: // [1, 2] > > + AllRangePieces[AllRangePiecesCountActual].BaseAddress =3D AllEnd= PointsInclusive[Index]; > > + AllRangePieces[AllRangePiecesCountActual].Length =3D AllEnd= PointsInclusive[Index + 1] - > AllEndPointsInclusive[Index] + 1; > > + AllRangePiecesCountActual++; > > + break; > > + case 1: // [1, 2) > > + AllRangePieces[AllRangePiecesCountActual].BaseAddress =3D AllEnd= PointsInclusive[Index]; > > + AllRangePieces[AllRangePiecesCountActual].Length =3D (AllEn= dPointsInclusive[Index + 1] - 1) - > AllEndPointsInclusive[Index] + 1; > > + AllRangePiecesCountActual++; > > + break; > > + case 2: // (1, 2] > > + AllRangePieces[AllRangePiecesCountActual].BaseAddress =3D AllEnd= PointsInclusive[Index] + 1; > > + AllRangePieces[AllRangePiecesCountActual].Length =3D AllEnd= PointsInclusive[Index + 1] - > (AllEndPointsInclusive[Index] + 1) + 1; > > + AllRangePiecesCountActual++; > > + > > + if (!IsEndpointInRanges (AllEndPointsInclusive[Index], AllRangeP= ieces, AllRangePiecesCountActual)) { > > + AllRangePieces[AllRangePiecesCountActual].BaseAddress =3D AllE= ndPointsInclusive[Index]; > > + AllRangePieces[AllRangePiecesCountActual].Length =3D 1; > > + AllRangePiecesCountActual++; > > + } > > + break; > > + case 3: // (1, 2) > > + AllRangePieces[AllRangePiecesCountActual].BaseAddress =3D AllEnd= PointsInclusive[Index] + 1; > > + AllRangePieces[AllRangePiecesCountActual].Length =3D (AllEn= dPointsInclusive[Index + 1] - 1) - > (AllEndPointsInclusive[Index] + 1) + 1; > > + if (AllRangePieces[AllRangePiecesCountActual].Length =3D=3D 0) = // Only in case 3 can exists Length=3D0, we should skip > such "segment". > > + break; > > + AllRangePiecesCountActual++; > > + if (!IsEndpointInRanges (AllEndPointsInclusive[Index], AllRangeP= ieces, AllRangePiecesCountActual)) { > > + AllRangePieces[AllRangePiecesCountActual].BaseAddress =3D AllE= ndPointsInclusive[Index]; > > + AllRangePieces[AllRangePiecesCountActual].Length =3D 1; > > + AllRangePiecesCountActual++; > > + } > > + break; > > + default: > > + ASSERT (FALSE); > > + } > > + } > > + > > + for (Index =3D 0; Index < AllRangePiecesCountActual; Index++) { > > + DetermineMemoryCacheType (DefaultType, &AllRangePieces[Index], RawMe= moryRanges, RawMemoryRangeCount); > > + } > > + > > + CompactAndExtendEffectiveMtrrMemoryRanges (DefaultType, PhysicalAddres= sBits, &AllRangePieces, > &AllRangePiecesCountActual); > > + ASSERT (*MemoryRangeCount >=3D AllRangePiecesCountActual); > > + memcpy (MemoryRanges, AllRangePieces, AllRangePiecesCountActual * size= of (MTRR_MEMORY_RANGE)); > > + *MemoryRangeCount =3D AllRangePiecesCountActual; > > + > > + free (AllEndPointsInclusive); > > + free (AllRangePieces); > > +} > > diff --git a/UefiCpuPkg/Test/UefiCpuPkgHostTest.dsc b/UefiCpuPkg/Test/Uef= iCpuPkgHostTest.dsc > new file mode 100644 > index 0000000000..8a5c456830 > --- /dev/null > +++ b/UefiCpuPkg/Test/UefiCpuPkgHostTest.dsc > @@ -0,0 +1,31 @@ > +## @file > > +# UefiCpuPkg DSC file used to build host-based unit tests. > > +# > > +# Copyright (c) 2020, Intel Corporation. All rights reserved.
> > +# SPDX-License-Identifier: BSD-2-Clause-Patent > > +# > > +## > > + > > +[Defines] > > + PLATFORM_NAME =3D UefiCpuPkgHostTest > > + PLATFORM_GUID =3D E00B9599-5B74-4FF7-AB9F-8183FB13B2F9 > > + PLATFORM_VERSION =3D 0.1 > > + DSC_SPECIFICATION =3D 0x00010005 > > + OUTPUT_DIRECTORY =3D Build/UefiCpuPkg/HostTest > > + SUPPORTED_ARCHITECTURES =3D IA32|X64 > > + BUILD_TARGETS =3D NOOPT > > + SKUID_IDENTIFIER =3D DEFAULT > > + > > +!include UnitTestFrameworkPkg/UnitTestFrameworkPkgHost.dsc.inc > > + > > +[LibraryClasses] > > + MtrrLib|UefiCpuPkg/Library/MtrrLib/MtrrLib.inf > > + > > +[PcdsPatchableInModule] > > + gUefiCpuPkgTokenSpaceGuid.PcdCpuNumberOfReservedVariableMtrrs|0 > > + > > +[Components] > > + # > > + # Build HOST_APPLICATION that tests the MtrrLib > > + # > > + UefiCpuPkg/Library/MtrrLib/UnitTest/MtrrLibUnitTestHost.inf > > diff --git a/UefiCpuPkg/UefiCpuPkg.ci.yaml b/UefiCpuPkg/UefiCpuPkg.ci.yam= l > index 99e460a8b0..4559b40105 100644 > --- a/UefiCpuPkg/UefiCpuPkg.ci.yaml > +++ b/UefiCpuPkg/UefiCpuPkg.ci.yaml > @@ -8,6 +8,10 @@ > "CompilerPlugin": { > > "DscPath": "UefiCpuPkg.dsc" > > }, > > + ## options defined ci/Plugin/HostUnitTestCompilerPlugin > > + "HostUnitTestCompilerPlugin": { > > + "DscPath": "Test/UefiCpuPkgHostTest.dsc" > > + }, > > "CharEncodingCheck": { > > "IgnoreFiles": [] > > }, > > @@ -18,7 +22,9 @@ > "UefiCpuPkg/UefiCpuPkg.dec" > > ], > > # For host based unit tests > > - "AcceptableDependencies-HOST_APPLICATION":[], > > + "AcceptableDependencies-HOST_APPLICATION":[ > > + "UnitTestFrameworkPkg/UnitTestFrameworkPkg.dec" > > + ], > > # For UEFI shell based apps > > "AcceptableDependencies-UEFI_APPLICATION":[], > > "IgnoreInf": [] > > @@ -30,6 +36,10 @@ > "UefiCpuPkg/ResetVector/Vtf0/Vtf0.inf" > > ] > > }, > > + "HostUnitTestDscCompleteCheck": { > > + "IgnoreInf": [""], > > + "DscPath": "Test/UefiCpuPkgHostTest.dsc" > > + }, > > "GuidCheck": { > > "IgnoreGuidName": ["SecCore", "ResetVector"], # Expected duplica= tion for gEfiFirmwareVolumeTopFileGuid > > "IgnoreGuidValue": [], > > -- > 2.27.0.windows.1 > > > -=3D-=3D-=3D-=3D-=3D-=3D > Groups.io Links: You receive all messages sent to this group. > > View/Reply Online (#63380): https://edk2.groups.io/g/devel/message/63380 > Mute This Topic: https://groups.io/mt/75837117/1712937 > Group Owner: devel+owner@edk2.groups.io > Unsubscribe: https://edk2.groups.io/g/devel/unsub [ray.ni@intel.com] > -=3D-=3D-=3D-=3D-=3D-=3D --_000_DM6PR11MB327419476918AE28D7FAAE99FE730DM6PR11MB3274namp_ Content-Type: text/html; charset="us-ascii" Content-Transfer-Encoding: quoted-printable

Reviewed-by: Eric Dong <eric.dong@intel.com>

 

From: Ni, Ray <ray.ni@intel.com>
Sent: Tuesday, July 28, 2020 10:41 AM
To: devel@edk2.groups.io; Ni, Ray <ray.ni@intel.com>
Cc: Kinney, Michael D <michael.d.kinney@intel.com>; Shao, Ming= <ming.shao@intel.com>; Dong, Eric <eric.dong@intel.com>; Laszl= o Ersek <lersek@redhat.com>; Sean Brogan <sean.brogan@microsoft.co= m>; Bret Barkelew <Bret.Barkelew@microsoft.com>; Yao, Jiewen <jiewen.yao@intel.com>
Subject: RE: [edk2-devel] [PATCH v3] UefiCpuPkg/MtrrLib/UnitTest: Ad= d host based unit test

 

Mike, Eric, Laszlo,
Sorry I just found that&nbs= p;the v2 patch cannot pass the CI test&n= bsp;because the yaml file is not updated = ;to allow some modules depend on UnitTestFram= eworkPkg.

So, this v3 patch doesn't&n= bsp;change the other files but only yaml = ;files comparing to v2.
I cannot separate the yaml&= nbsp;change to a separate patch because that&= nbsp;will still break the CI.
But, please just review the=  yaml part. I guarantee that no changes&= nbsp;were made to non-yaml files.

I also added the unit = test build/run to CI build step, following&nb= sp;what MdePkg/MdeModulePkg did.


Thanks,
Ray

> -----Original Message-----
> From: devel@edk2.groups.io <devel@edk2.groups.io> On Behalf Of = ;Ni, Ray
> Sent: Tuesday, July 2= 8, 2020 10:30 AM
> To: devel@edk2.groups.io
> Cc: Kinney, Michael D=  <michael.d.kinney@in= tel.com>; Shao, Ming <ming.shao@intel.com>; Dong, Eric
> <eric.dong@intel.com>; Laszlo Ersek <lersek@redhat.com>; Sean Bro= gan <sean.brogan@micro= soft.com>; Bret Barkelew
> <Bret.Barkelew@microsoft.com>; Yao, Jiewen&n= bsp;<jiewen.yao@intel.com>= ;
> Subject: [edk2-devel] [PAT= CH v3] UefiCpuPkg/MtrrLib/UnitTest: Add host based=  unit test

> Add host based unit&n= bsp;tests for the MtrrLib services.
> The BaseLib services = AsmCpuid(), AsmReadMsr64(), and
> AsmWriteMsr64() are hooked=  and provide simple emulation
> of the CPUID leafs&nb= sp;and MSRs required by the MtrrLib to=
> run as a host ba= sed unit test.

> Test cases are develo= ped for each of the API.

> For the most importan= t APIs MtrrSetMemoryAttributesInMtrrSettings()
> and MtrrSetMemoryAttributeInMtr= rSettings(), random inputs are
> generated and fed to&= nbsp;the APIs to make sure the implementation=  is
> good. The test applic= ation accepts an optional parameter which > specifies how many it= erations of feeding random inputs to the = ;two
> APIs. The overall num= ber of test cases increases when the ite= ration
> increases. Default iterati= on is 10 when no parameter is specified.=

> Signed-off-by: Ray Ni = ;<ray.ni@intel.com> > Signed-off-by: Michael D&n= bsp;Kinney <michael.d= .kinney@intel.com>
> Signed-off-by: Ming Shao&n= bsp;<ming.shao@intel.com><= /span>
> Cc: Michael D Kinney&= nbsp;<michael.d.kinney@int= el.com>
> Cc: Eric Dong <eric.dong@intel.com>
> Cc: Laszlo Ersek <= lersek@redhat.com>
> Cc: Ming Shao <ming.shao@intel.com>
> Cc: Sean Brogan <<= a href=3D"mailto:sean.brogan@microsoft.com">sean.brogan@microsoft.com&g= t;
> Cc: Bret Barkelew <= ;Bret.Barkelew@microsoft.com= >
> Cc: Jiewen Yao <jiewen.yao@intel.com> > ---
>  .../MtrrLib/UnitTest/MtrrLibUn= itTest.c        | 1140 ++= +++++++++++++++
>  .../MtrrLib/UnitTest/MtrrLibUn= itTest.h        |  171&nb= sp;+++
>  .../MtrrLib/UnitTest/MtrrLibUn= itTestHost.inf  |   39 +
>  UefiCpuPkg/Library/MtrrLib/Uni= tTest/Support.c |  913 +++++++++++++
>  UefiCpuPkg/Test/UefiCpuPkgHost= Test.dsc        |   = 31 +
>  UefiCpuPkg/UefiCpuPkg.ci.yaml&= nbsp;           &nbs= p;    |   12 +-
>  6 files changed,&nbs= p;2305 insertions(+), 1 deletion(-)
>  create mode 100644&n= bsp;UefiCpuPkg/Library/MtrrLib/UnitTest/MtrrLibUnitTest.c
>  create mode 100644&n= bsp;UefiCpuPkg/Library/MtrrLib/UnitTest/MtrrLibUnitTest.h
>  create mode 100644&n= bsp;UefiCpuPkg/Library/MtrrLib/UnitTest/MtrrLibUnitTestHost.inf
>  create mode 100644&n= bsp;UefiCpuPkg/Library/MtrrLib/UnitTest/Support.c
>  create mode 100644&n= bsp;UefiCpuPkg/Test/UefiCpuPkgHostTest.dsc

> diff --git a/UefiCpuPkg/Li= brary/MtrrLib/UnitTest/MtrrLibUnitTest.c
> b/UefiCpuPkg/Library/MtrrLib/UnitTes= t/MtrrLibUnitTest.c
> new file mode 100644<= /span>
> index 0000000000..2eac41fc74
> --- /dev/null
> +++ b/UefiCpuPkg/Library/MtrrLi= b/UnitTest/MtrrLibUnitTest.c
> @@ -0,0 +1,1140 @@
> +/** @file

> +  Unit tests of=  the MtrrLib instance of the MtrrLib cla= ss

> +

> +  Copyright (c) = ;2020, Intel Corporation. All rights reserved.<= BR>

> +  SPDX-License-Identifier= : BSD-2-Clause-Patent

> +

> +**/

> +

> +#include "MtrrLibUnitTest= .h"

> +

> +STATIC CONST MTRR_LIB_SYS= TEM_PARAMETER mDefaultSystemParameter =3D {

> +  42, TRUE, TRU= E, CacheUncacheable, 12

> +};

> +

> +STATIC MTRR_LIB_SYSTEM_PARAMET= ER mSystemParameters[] =3D {

> +  { 38, TRUE,&n= bsp;TRUE, CacheUncacheable,    12 },
> +  { 38, TRUE,&n= bsp;TRUE, CacheWriteBack,      12 }= ,

> +  { 38, TRUE,&n= bsp;TRUE, CacheWriteThrough,   12 },

> +  { 38, TRUE,&n= bsp;TRUE, CacheWriteProtected, 12 },

> +  { 38, TRUE,&n= bsp;TRUE, CacheWriteCombining, 12 },

> +

> +  { 42, TRUE,&n= bsp;TRUE, CacheUncacheable,    12 },
> +  { 42, TRUE,&n= bsp;TRUE, CacheWriteBack,      12 }= ,

> +  { 42, TRUE,&n= bsp;TRUE, CacheWriteThrough,   12 },

> +  { 42, TRUE,&n= bsp;TRUE, CacheWriteProtected, 12 },

> +  { 42, TRUE,&n= bsp;TRUE, CacheWriteCombining, 12 },

> +

> +  { 48, TRUE,&n= bsp;TRUE, CacheUncacheable,    12 },
> +  { 48, TRUE,&n= bsp;TRUE, CacheWriteBack,      12 }= ,

> +  { 48, TRUE,&n= bsp;TRUE, CacheWriteThrough,   12 },

> +  { 48, TRUE,&n= bsp;TRUE, CacheWriteProtected, 12 },

> +  { 48, TRUE,&n= bsp;TRUE, CacheWriteCombining, 12 },

> +};

> +

> +UINT32     = ;            &n= bsp;  mFixedMtrrsIndex[] =3D {

> +  MSR_IA32_MTRR_FIX64K_00= 000,

> +  MSR_IA32_MTRR_FIX16K_80= 000,

> +  MSR_IA32_MTRR_FIX16K_A0= 000,

> +  MSR_IA32_MTRR_FIX4K_C00= 00,

> +  MSR_IA32_MTRR_FIX4K_C80= 00,

> +  MSR_IA32_MTRR_FIX4K_D00= 00,

> +  MSR_IA32_MTRR_FIX4K_D80= 00,

> +  MSR_IA32_MTRR_FIX4K_E00= 00,

> +  MSR_IA32_MTRR_FIX4K_E80= 00,

> +  MSR_IA32_MTRR_FIX4K_F00= 00,

> +  MSR_IA32_MTRR_FIX4K_F80= 00

> +};

> +STATIC_ASSERT (

> +  (ARRAY_SIZE (mFixe= dMtrrsIndex) =3D=3D MTRR_NUMBER_OF_FIXED_MTRR),

> +  "gFixedMtrrIndex&n= bsp;does NOT contain all the fixed MTRRs!&quo= t;

> +  );

> +

> +//

> +// Context structure = ;to be used for most of the test ca= ses.

> +//

> +typedef struct {
> +  CONST MTRR_LIB_SYS= TEM_PARAMETER *SystemParameter;

> +} MTRR_LIB_TEST_CONTEXT;

> +

> +//

> +// Context structure = ;to be used for GetFirmwareVariableMtrrCount() tes= t.

> +//

> +typedef struct {
> +  UINT32   = ;            &n= bsp;          NumberOfRes= ervedVariableMtrrs;

> +  CONST MTRR_LIB_SYS= TEM_PARAMETER *SystemParameter;

> +} MTRR_LIB_GET_FIRMWARE_VARIAB= LE_MTRR_COUNT_CONTEXT;

> +

> +STATIC CHAR8 *mCacheDescr= iption[] =3D { "UC", "WC", &qu= ot;N/A", "N/A", "WT", "WP"= ;, "WB" };

> +

> +/**

> +  Compare the a= ctual memory ranges against expected memory r= anges and return PASS when they match.=

> +

> +  @param ExpectedMem= oryRanges     Expected memory ranges.

> +  @param ExpectedMem= oryRangeCount Count of expected memory ranges.

> +  @param ActualRange= s            &n= bsp;Actual memory ranges.

> +  @param ActualRange= Count         Count of&nb= sp;actual memory ranges.

> +

> +  @retval UNIT_TEST_= PASSED  Test passed.

> +  @retval others&nbs= p;           Test&nb= sp;failed.

> +**/

> +UNIT_TEST_STATUS

> +VerifyMemoryRanges (
> +  IN MTRR_MEMORY_RAN= GE  *ExpectedMemoryRanges,

> +  IN UINTN &nbs= p;            E= xpectedMemoryRangeCount,

> +  IN MTRR_MEMORY_RAN= GE  *ActualRanges,

> +  IN UINTN &nbs= p;            A= ctualRangeCount

> +  )

> +{

> +  UINTN  Index;=

> +  UT_ASSERT_EQUAL (E= xpectedMemoryRangeCount, ActualRangeCount);

> +  for (Index = =3D 0; Index < ExpectedMemoryRangeCount; Index+= +) {

> +    UT_ASSERT_E= QUAL (ExpectedMemoryRanges[Index].BaseAddress, ActualRanges[Index= ].BaseAddress);

> +    UT_ASSERT_E= QUAL (ExpectedMemoryRanges[Index].Length, ActualRanges[Index].Len= gth);

> +    UT_ASSERT_E= QUAL (ExpectedMemoryRanges[Index].Type, ActualRanges[Index].Type)= ;

> +  }

> +

> +  return UNIT_TEST_P= ASSED;

> +}

> +

> +/**

> +  Dump the memo= ry ranges.

> +

> +  @param Ranges = ;      Memory ranges to dump.<= /span>

> +  @param RangeCount&= nbsp;  Count of memory ranges.

> +**/

> +VOID

> +DumpMemoryRanges (

> +  MTRR_MEMORY_RANGE =    *Ranges,

> +  UINTN   =             &nb= sp;RangeCount

> +  )

> +{

> +  UINTN   =   Index;

> +  for (Index = =3D 0; Index < RangeCount; Index++) {

> +    UT_LOG_INFO=  ("\t{ 0x%016llx, 0x%016llx, %a },\n",&n= bsp;Ranges[Index].BaseAddress, Ranges[Index].Length,
> mCacheDescription[Ranges[Index].Type= ]);

> +  }

> +}

> +

> +/**

> +**/

> +

> +/**

> +  Generate random&nb= sp;count of MTRRs for each cache type.=

> +

> +  @param TotalCount&= nbsp;Total MTRR count.

> +  @param UcCount&nbs= p;   Return count of Uncacheable type.

> +  @param WtCount&nbs= p;   Return count of Write Through = type.

> +  @param WbCount&nbs= p;   Return count of Write Back typ= e.

> +  @param WpCount&nbs= p;   Return count of Write Protected&nbs= p;type.

> +  @param WcCount&nbs= p;   Return count of Write Combining&nbs= p;type.

> +**/

> +VOID

> +GenerateRandomMemoryTypeCombination=  (

> +  IN  UINT32&nb= sp;TotalCount,

> +  OUT UINT32 *U= cCount,

> +  OUT UINT32 *W= tCount,

> +  OUT UINT32 *W= bCount,

> +  OUT UINT32 *W= pCount,

> +  OUT UINT32 *W= cCount

> +  )

> +{

> +  UINTN  Index;=

> +  UINT32 TotalMtrrCo= unt;

> +  UINT32 *CountPerTy= pe[5];

> +

> +  CountPerType[0] = =3D UcCount;

> +  CountPerType[1] = =3D WtCount;

> +  CountPerType[2] = =3D WbCount;

> +  CountPerType[3] = =3D WpCount;

> +  CountPerType[4] = =3D WcCount;

> +

> +  //

> +  // Initialize = ;the count of each cache type to 0.

> +  //

> +  for (Index = =3D 0; Index < ARRAY_SIZE (CountPerType); = Index++) {

> +    *(CountPerT= ype[Index]) =3D 0;

> +  }

> +

> +  //

> +  // Pick a&nbs= p;random count of MTRRs

> +  //

> +  TotalMtrrCount =3D=  Random32 (1, TotalCount);

> +  for (Index = =3D 0; Index < TotalMtrrCount; Index++) {<= /span>

> +    //
> +    // For=  each of them, pick a random cache = type.

> +    //
> +    (*(CountPer= Type[Random32 (0, ARRAY_SIZE (CountPerType) - 1)])= )++;

> +  }

> +}

> +

> +/**

> +  Unit test of&= nbsp;MtrrLib service MtrrSetMemoryAttribute()

> +

> +  @param[in]  C= ontext    Ignored

> +

> +  @retval  UNIT= _TEST_PASSED          &nb= sp;  The Unit test has completed and&nbs= p;the test

> +      = ;            &n= bsp;            = ;         case was s= uccessful.

> +  @retval  UNIT= _TEST_ERROR_TEST_FAILED  A test case assertion&nbs= p;has failed.

> +

> +**/

> +UNIT_TEST_STATUS

> +EFIAPI

> +UnitTestMtrrSetMemoryAttributesInMt= rrSettings (

> +  IN UNIT_TEST_CONTE= XT  Context

> +  )

> +{

> +  CONST MTRR_LIB_SYS= TEM_PARAMETER *SystemParameter;

> +  RETURN_STATUS &nbs= p;            &= nbsp;    Status;

> +  UINT32   = ;            &n= bsp;          UcCount;

> +  UINT32   = ;            &n= bsp;          WtCount;

> +  UINT32   = ;            &n= bsp;          WbCount;

> +  UINT32   = ;            &n= bsp;          WpCount;

> +  UINT32   = ;            &n= bsp;          WcCount;

> +

> +  UINT32   = ;            &n= bsp;          MtrrIndex;<= /span>

> +  UINT8   =             &nb= sp;           *Scrat= ch;

> +  UINTN   =             &nb= sp;           Scratc= hSize;

> +  MTRR_SETTINGS &nbs= p;            &= nbsp;    LocalMtrrs;

> +

> +  MTRR_MEMORY_RANGE =             &nb= sp; RawMtrrRange[MTRR_NUMBER_OF_VARIABLE_MTRR];

> +  MTRR_MEMORY_RANGE =             &nb= sp; ExpectedMemoryRanges[MTRR_NUMBER_OF_FIXED_MTRR * sizeof&= nbsp;(UINT64) + 2 *
> MTRR_NUMBER_OF_VARIABLE_MTRR +&= nbsp;1];

> +  UINT32   = ;            &n= bsp;          ExpectedVar= iableMtrrUsage;

> +  UINTN   =             &nb= sp;           Expect= edMemoryRangesCount;

> +

> +  MTRR_MEMORY_RANGE =             &nb= sp; ActualMemoryRanges[MTRR_NUMBER_OF_FIXED_MTRR   *&nb= sp;sizeof (UINT64) + 2 *
> MTRR_NUMBER_OF_VARIABLE_MTRR +&= nbsp;1];

> +  UINT32   = ;            &n= bsp;          ActualVaria= bleMtrrUsage;

> +  UINTN   =             &nb= sp;           Actual= MemoryRangesCount;

> +

> +  MTRR_SETTINGS &nbs= p;           *Mtrrs[= 2];

> +

> +  SystemParameter = =3D (MTRR_LIB_SYSTEM_PARAMETER *) Context;

> +  GenerateRandomMemoryTyp= eCombination (

> +    SystemParam= eter->VariableMtrrCount - PatchPcdGet32 (PcdCpuNumberOfRe= servedVariableMtrrs),

> +    &UcCoun= t, &WtCount, &WbCount, &WpCount, &WcCou= nt

> +    );
> +  GenerateValidAndConfigu= rableMtrrPairs (

> +    SystemParam= eter->PhysicalAddressBits, RawMtrrRange,

> +    UcCount,&nb= sp;WtCount, WbCount, WpCount, WcCount

> +    );
> +

> +  ExpectedVariableMtrrUsa= ge =3D UcCount + WtCount + WbCount +&nbs= p;WpCount + WcCount;

> +  ExpectedMemoryRangesCou= nt =3D ARRAY_SIZE (ExpectedMemoryRanges);

> +  GetEffectiveMemoryRange= s (

> +    SystemParam= eter->DefaultCacheType,

> +    SystemParam= eter->PhysicalAddressBits,

> +    RawMtrrRang= e, ExpectedVariableMtrrUsage,

> +    ExpectedMem= oryRanges, &ExpectedMemoryRangesCount

> +    );
> +

> +  UT_LOG_INFO (

> +    "Total=  MTRR [%d]: UC=3D%d, WT=3D%d, WB=3D%d, WP=3D%= d, WC=3D%d\n",

> +    ExpectedVar= iableMtrrUsage, UcCount, WtCount, WbCount, WpCount,&nbs= p;WcCount

> +    );
> +  UT_LOG_INFO ("= ;--- Expected Memory Ranges [%d] ---\n", = ;ExpectedMemoryRangesCount);

> +  DumpMemoryRanges (= ExpectedMemoryRanges, ExpectedMemoryRangesCount);

> +

> +  //

> +  // Default ca= che type is always an INPUT

> +  //

> +  ZeroMem (&Loca= lMtrrs, sizeof (LocalMtrrs));

> +  LocalMtrrs.MtrrDefType&= nbsp;=3D MtrrGetDefaultMemoryType ();

> +  ScratchSize  =           =3D SCRATC= H_BUFFER_SIZE;

> +  Mtrrs[0]  &nb= sp;            = =3D &LocalMtrrs;

> +  Mtrrs[1]  &nb= sp;            = =3D NULL;

> +

> +  for (MtrrIndex&nbs= p;=3D 0; MtrrIndex < ARRAY_SIZE (Mtrrs); M= trrIndex++) {

> +    Scratch&nbs= p;=3D calloc (ScratchSize, sizeof (UINT8));

> +    Status = ;=3D MtrrSetMemoryAttributesInMtrrSettings (Mtrrs[MtrrIndex],&nbs= p;Scratch, &ScratchSize, ExpectedMemoryRanges,
> ExpectedMemoryRangesCount);
> +    if (St= atus =3D=3D RETURN_BUFFER_TOO_SMALL) {

> +      = ;Scratch =3D realloc (Scratch, ScratchSize);

> +      = ;Status =3D MtrrSetMemoryAttributesInMtrrSettings (Mtrrs[Mtr= rIndex], Scratch, &ScratchSize, ExpectedMemoryRanges,
> ExpectedMemoryRangesCount);
> +    }
> +    UT_ASSERT_S= TATUS_EQUAL (Status, RETURN_SUCCESS);

> +

> +    if (Mt= rrs[MtrrIndex] =3D=3D NULL) {

> +      = ;ZeroMem (&LocalMtrrs, sizeof (LocalMtrrs));

> +      = ;MtrrGetAllMtrrs (&LocalMtrrs);

> +    }
> +    ActualMemor= yRangesCount =3D ARRAY_SIZE (ActualMemoryRanges);

> +    CollectTest= Result (

> +      = ;SystemParameter->DefaultCacheType, SystemParameter->PhysicalAdd= ressBits, SystemParameter->VariableMtrrCount,

> +      = ;&LocalMtrrs, ActualMemoryRanges, &ActualMemoryRangesCoun= t, &ActualVariableMtrrUsage

> +      = ;);

> +

> +    UT_LOG_INFO=  ("--- Actual Memory Ranges [%d] ---\n&q= uot;, ActualMemoryRangesCount);

> +    DumpMemoryR= anges (ActualMemoryRanges, ActualMemoryRangesCount);

> +    VerifyMemor= yRanges (ExpectedMemoryRanges, ExpectedMemoryRangesCount, Ac= tualMemoryRanges,
> ActualMemoryRangesCount);

> +    UT_ASSERT_T= RUE (ExpectedVariableMtrrUsage >=3D ActualVariableMtrrUsa= ge);

> +

> +    ZeroMem&nbs= p;(&LocalMtrrs, sizeof (LocalMtrrs));

> +  }

> +

> +  free (Scratch);

> +

> +  return UNIT_TEST_P= ASSED;

> +}

> +

> +/**

> +  Test routine = to check whether invalid base/size can be&nbs= p;rejected.

> +

> +  @param Context&nbs= p;  Pointer to MTRR_LIB_SYSTEM_PARAMETER.

> +

> +  @return Test = status.

> +**/

> +UNIT_TEST_STATUS

> +EFIAPI

> +UnitTestInvalidMemoryLayouts (=

> +  IN UNIT_TEST_CONTE= XT          Context

> +  )

> +{

> +  CONST MTRR_LIB_SYS= TEM_PARAMETER *SystemParameter;

> +  MTRR_MEMORY_RANGE =             &nb= sp; Ranges[MTRR_NUMBER_OF_VARIABLE_MTRR * 2 + 1];<= /span>

> +  UINTN   =             &nb= sp;           RangeC= ount;

> +  UINT64   = ;            &n= bsp;          MaxAddress;=

> +  UINT32   = ;            &n= bsp;          Index;

> +  UINT64   = ;            &n= bsp;          BaseAddress= ;

> +  UINT64   = ;            &n= bsp;          Length;

> +  RETURN_STATUS &nbs= p;            &= nbsp;    Status;

> +  UINTN   =             &nb= sp;           Scratc= hSize;

> +

> +  SystemParameter = =3D (MTRR_LIB_SYSTEM_PARAMETER *) Context;

> +

> +  RangeCount =3D&nbs= p;Random32 (1, ARRAY_SIZE (Ranges));

> +  MaxAddress =3D&nbs= p;1ull << SystemParameter->PhysicalAddressBits;
> +

> +  for (Index = =3D 0; Index < RangeCount; Index++) {

> +    do {

> +      = ;BaseAddress =3D Random64 (0, MaxAddress);

> +      = ;Length      =3D Random64 (1, = MaxAddress - BaseAddress);

> +    } whil= e (((BaseAddress & 0xFFF) =3D=3D 0) ||&nb= sp;((Length & 0xFFF) =3D=3D 0));

> +

> +    Ranges[Inde= x].BaseAddress =3D BaseAddress;

> +    Ranges[Inde= x].Length      =3D Length;

> +    Ranges[Inde= x].Type        =3D GenerateRan= domCacheType ();

> +

> +    Status = ;=3D MtrrSetMemoryAttribute (

> +      = ;Ranges[Index].BaseAddress, Ranges[Index].Length, Ranges[Index].T= ype

> +      = ;);

> +    UT_ASSERT_T= RUE (RETURN_ERROR (Status));

> +  }

> +

> +  ScratchSize =3D&nb= sp;0;

> +  Status =3D Mt= rrSetMemoryAttributesInMtrrSettings (NULL, NULL, &Scratc= hSize, Ranges, RangeCount);

> +  UT_ASSERT_TRUE (RE= TURN_ERROR (Status));

> +

> +  return UNIT_TEST_P= ASSED;

> +}

> +

> +/**

> +  Unit test of&= nbsp;MtrrLib service IsMtrrSupported()

> +

> +  @param[in]  C= ontext    Ignored

> +

> +  @retval  UNIT= _TEST_PASSED          &nb= sp;  The Unit test has completed and&nbs= p;the test

> +      = ;            &n= bsp;            = ;         case was s= uccessful.

> +  @retval  UNIT= _TEST_ERROR_TEST_FAILED  A test case assertion&nbs= p;has failed.

> +

> +**/

> +UNIT_TEST_STATUS

> +EFIAPI

> +UnitTestIsMtrrSupported (

> +  IN UNIT_TEST_CONTE= XT  Context

> +  )

> +{

> +  MTRR_LIB_SYSTEM_PARAMET= ER  SystemParameter;

> +  MTRR_LIB_TEST_CONTEXT&n= bsp;     *LocalContext;

> +

> +  LocalContext =3D&n= bsp;(MTRR_LIB_TEST_CONTEXT *) Context;

> +

> +  CopyMem (&Syst= emParameter, LocalContext->SystemParameter, sizeof (Syste= mParameter));

> +  //

> +  // MTRR capab= ility off in CPUID leaf.

> +  //

> +  SystemParameter.MtrrSup= ported =3D FALSE;

> +  InitializeMtrrRegs = ;(&SystemParameter);

> +  UT_ASSERT_FALSE (I= sMtrrSupported ());

> +

> +  //

> +  // MTRR capab= ility on in CPUID leaf, but no variable&= nbsp;or fixed MTRRs.

> +  //

> +  SystemParameter.MtrrSup= ported =3D TRUE;

> +  SystemParameter.Variabl= eMtrrCount =3D 0;

> +  SystemParameter.FixedMt= rrSupported =3D FALSE;

> +  InitializeMtrrRegs = ;(&SystemParameter);

> +  UT_ASSERT_FALSE (I= sMtrrSupported ());

> +

> +  //

> +  // MTRR capab= ility on in CPUID leaf, but no variable&= nbsp;MTRRs.

> +  //

> +  SystemParameter.MtrrSup= ported =3D TRUE;

> +  SystemParameter.Variabl= eMtrrCount =3D 0;

> +  SystemParameter.FixedMt= rrSupported =3D TRUE;

> +  InitializeMtrrRegs = ;(&SystemParameter);

> +  UT_ASSERT_FALSE (I= sMtrrSupported ());

> +

> +  //

> +  // MTRR capab= ility on in CPUID leaf, but no fixed&nbs= p;MTRRs.

> +  //

> +  SystemParameter.MtrrSup= ported =3D TRUE;

> +  SystemParameter.Variabl= eMtrrCount =3D 7;

> +  SystemParameter.FixedMt= rrSupported =3D FALSE;

> +  InitializeMtrrRegs = ;(&SystemParameter);

> +  UT_ASSERT_FALSE (I= sMtrrSupported ());

> +

> +  //

> +  // MTRR capab= ility on in CPUID leaf with both variabl= e and fixed MTRRs.

> +  //

> +  SystemParameter.MtrrSup= ported =3D TRUE;

> +  SystemParameter.Variabl= eMtrrCount =3D 7;

> +  SystemParameter.FixedMt= rrSupported =3D TRUE;

> +  InitializeMtrrRegs = ;(&SystemParameter);

> +  UT_ASSERT_TRUE (Is= MtrrSupported ());

> +

> +  return UNIT_TEST_P= ASSED;

> +}

> +

> +/**

> +  Unit test of&= nbsp;MtrrLib service GetVariableMtrrCount()

> +

> +  @param[in]  C= ontext    Ignored

> +

> +  @retval  UNIT= _TEST_PASSED          &nb= sp;  The Unit test has completed and&nbs= p;the test

> +      = ;            &n= bsp;            = ;         case was s= uccessful.

> +  @retval  UNIT= _TEST_ERROR_TEST_FAILED  A test case assertion&nbs= p;has failed.

> +

> +**/

> +UNIT_TEST_STATUS

> +EFIAPI

> +UnitTestGetVariableMtrrCount (=

> +  IN UNIT_TEST_CONTE= XT  Context

> +  )

> +{

> +  UINT32   = ;            &n= bsp;    Result;

> +  MTRR_LIB_SYSTEM_PARAMET= ER SystemParameter;

> +  MTRR_LIB_TEST_CONTEXT&n= bsp;    *LocalContext;

> +

> +  LocalContext =3D&n= bsp;(MTRR_LIB_TEST_CONTEXT *) Context;

> +

> +  CopyMem (&Syst= emParameter, LocalContext->SystemParameter, sizeof (Syste= mParameter));

> +  //

> +  // If MTRR&nb= sp;capability off in CPUID leaf, then the&nbs= p;count is always 0.

> +  //

> +  SystemParameter.MtrrSup= ported =3D FALSE;

> +  for (SystemParamet= er.VariableMtrrCount =3D 1; SystemParameter.VariableMtrrCoun= t <=3D
> MTRR_NUMBER_OF_VARIABLE_MTRR; S= ystemParameter.VariableMtrrCount++) {

> +    InitializeM= trrRegs (&SystemParameter);

> +    Result = ;=3D GetVariableMtrrCount ();

> +    UT_ASSERT_E= QUAL (Result, 0);

> +  }

> +

> +  //

> +  // Try all&nb= sp;supported variable MTRR counts.

> +  // If variabl= e MTRR count is > MTRR_NUMBER_OF_VARIABLE_MTRR,=  then an ASSERT()

> +  // is generat= ed.

> +  //

> +  SystemParameter.MtrrSup= ported =3D TRUE;

> +  for (SystemParamet= er.VariableMtrrCount =3D 1; SystemParameter.VariableMtrrCoun= t <=3D
> MTRR_NUMBER_OF_VARIABLE_MTRR; S= ystemParameter.VariableMtrrCount++) {

> +    InitializeM= trrRegs (&SystemParameter);

> +    Result = ;=3D GetVariableMtrrCount ();

> +    UT_ASSERT_E= QUAL (Result, SystemParameter.VariableMtrrCount);

> +  }

> +

> +  //

> +  // Expect ASS= ERT() if variable MTRR count is > MTR= R_NUMBER_OF_VARIABLE_MTRR

> +  //

> +  SystemParameter.Variabl= eMtrrCount =3D MTRR_NUMBER_OF_VARIABLE_MTRR + 1;=

> +  InitializeMtrrRegs = ;(&SystemParameter);

> +  UT_EXPECT_ASSERT_FAILUR= E (GetVariableMtrrCount (), NULL);

> +

> +  SystemParameter.MtrrSup= ported =3D TRUE;

> +  SystemParameter.Variabl= eMtrrCount =3D MAX_UINT8;

> +  InitializeMtrrRegs = ;(&SystemParameter);

> +  UT_EXPECT_ASSERT_FAILUR= E (GetVariableMtrrCount (), NULL);

> +

> +  return UNIT_TEST_P= ASSED;

> +}

> +

> +/**

> +  Unit test of&= nbsp;MtrrLib service GetFirmwareVariableMtrrCount()

> +

> +  @param[in]  C= ontext    Ignored

> +

> +  @retval  UNIT= _TEST_PASSED          &nb= sp;  The Unit test has completed and&nbs= p;the test

> +      = ;            &n= bsp;            = ;         case was s= uccessful.

> +  @retval  UNIT= _TEST_ERROR_TEST_FAILED  A test case assertion&nbs= p;has failed.

> +

> +**/

> +UNIT_TEST_STATUS

> +EFIAPI

> +UnitTestGetFirmwareVariableMtrrCoun= t (

> +  IN UNIT_TEST_CONTE= XT  Context

> +  )

> +{

> +  UINT32   = ;            &n= bsp;            = ;            &n= bsp;   Result;

> +  UINT32   = ;            &n= bsp;            = ;            &n= bsp;   ReservedMtrrs;

> +  MTRR_LIB_SYSTEM_PARAMET= ER            &= nbsp;           &nbs= p;SystemParameter;

> +  MTRR_LIB_GET_FIRMWARE_V= ARIABLE_MTRR_COUNT_CONTEXT *LocalContext;

> +

> +  LocalContext =3D&n= bsp;(MTRR_LIB_GET_FIRMWARE_VARIABLE_MTRR_COUNT_CONTEXT *) Context= ;

> +

> +  CopyMem (&Syst= emParameter, LocalContext->SystemParameter, sizeof (Syste= mParameter));

> +

> +  InitializeMtrrRegs = ;(&SystemParameter);

> +  //

> +  // Positive t= est cases for VCNT =3D 10 and Reserved&n= bsp;PCD in range 0..10

> +  //

> +  for (ReservedMtrrs=  =3D 0; ReservedMtrrs <=3D SystemParameter.Vari= ableMtrrCount; ReservedMtrrs++) {

> +    PatchPcdSet= 32 (PcdCpuNumberOfReservedVariableMtrrs, ReservedMtrrs);
> +    Result = ;=3D GetFirmwareVariableMtrrCount ();

> +    UT_ASSERT_E= QUAL (Result, SystemParameter.VariableMtrrCount - Reser= vedMtrrs);

> +  }

> +

> +  //

> +  // Negative t= est cases when Reserved PCD is larger th= an VCNT

> +  //

> +  for (ReservedMtrrs=  =3D SystemParameter.VariableMtrrCount + 1; Reserv= edMtrrs <=3D 255; ReservedMtrrs++) {

> +    PatchPcdSet= 32 (PcdCpuNumberOfReservedVariableMtrrs, ReservedMtrrs);
> +    Result = ;=3D GetFirmwareVariableMtrrCount ();

> +    UT_ASSERT_E= QUAL (Result, 0);

> +  }

> +

> +  //

> +  // Negative t= est cases when Reserved PCD is larger th= an VCNT

> +  //

> +  PatchPcdSet32 (Pcd= CpuNumberOfReservedVariableMtrrs, MAX_UINT32);

> +  Result =3D Ge= tFirmwareVariableMtrrCount ();

> +  UT_ASSERT_EQUAL (R= esult, 0);

> +

> +  //

> +  // Negative t= est case when MTRRs are not supported<= br>
> +  //

> +  SystemParameter.MtrrSup= ported =3D FALSE;

> +  InitializeMtrrRegs = ;(&SystemParameter);

> +  PatchPcdSet32 (Pcd= CpuNumberOfReservedVariableMtrrs, 2);

> +  Result =3D Ge= tFirmwareVariableMtrrCount ();

> +  UT_ASSERT_EQUAL (R= esult, 0);

> +

> +  //

> +  // Negative t= est case when Fixed MTRRs are not suppor= ted

> +  //

> +  SystemParameter.MtrrSup= ported =3D TRUE;

> +  SystemParameter.FixedMt= rrSupported =3D FALSE;

> +  InitializeMtrrRegs = ;(&SystemParameter);

> +  PatchPcdSet32 (Pcd= CpuNumberOfReservedVariableMtrrs, 2);

> +  Result =3D Ge= tFirmwareVariableMtrrCount ();

> +  UT_ASSERT_EQUAL (R= esult, 0);

> +

> +  //

> +  // Expect ASS= ERT() if variable MTRR count is > MTR= R_NUMBER_OF_VARIABLE_MTRR

> +  //

> +  SystemParameter.FixedMt= rrSupported =3D TRUE;

> +  SystemParameter.Variabl= eMtrrCount =3D MTRR_NUMBER_OF_VARIABLE_MTRR + 1;=

> +  InitializeMtrrRegs = ;(&SystemParameter);

> +  UT_EXPECT_ASSERT_FAILUR= E (GetFirmwareVariableMtrrCount (), NULL);

> +

> +  return UNIT_TEST_P= ASSED;

> +}

> +

> +/**

> +  Unit test of&= nbsp;MtrrLib service MtrrGetMemoryAttribute()

> +

> +  @param[in]  C= ontext    Ignored

> +

> +  @retval  UNIT= _TEST_PASSED          &nb= sp;  The Unit test has completed and&nbs= p;the test

> +      = ;            &n= bsp;            = ;         case was s= uccessful.

> +  @retval  UNIT= _TEST_ERROR_TEST_FAILED  A test case assertion&nbs= p;has failed.

> +

> +**/

> +UNIT_TEST_STATUS

> +EFIAPI

> +UnitTestMtrrGetMemoryAttribute = ;(

> +  IN UNIT_TEST_CONTE= XT  Context

> +  )

> +{

> +  return UNIT_TEST_P= ASSED;

> +}

> +

> +/**

> +  Unit test of&= nbsp;MtrrLib service MtrrGetFixedMtrr()

> +

> +  @param[in]  C= ontext    Ignored

> +

> +  @retval  UNIT= _TEST_PASSED          &nb= sp;  The Unit test has completed and&nbs= p;the test

> +      = ;            &n= bsp;            = ;         case was s= uccessful.

> +  @retval  UNIT= _TEST_ERROR_TEST_FAILED  A test case assertion&nbs= p;has failed.

> +

> +**/

> +UNIT_TEST_STATUS

> +EFIAPI

> +UnitTestMtrrGetFixedMtrr (

> +  IN UNIT_TEST_CONTE= XT  Context

> +  )

> +{

> +  MTRR_FIXED_SETTINGS&nbs= p;      *Result;

> +  MTRR_FIXED_SETTINGS&nbs= p;      ExpectedFixedSettings;

> +  MTRR_FIXED_SETTINGS&nbs= p;      FixedSettings;

> +  UINTN   =             &nb= sp;     Index;

> +  UINTN   =             &nb= sp;     MsrIndex;

> +  UINTN   =             &nb= sp;     ByteIndex;

> +  UINT64   = ;            &n= bsp;    MsrValue;

> +  MTRR_LIB_SYSTEM_PARAMET= ER SystemParameter;

> +  MTRR_LIB_TEST_CONTEXT&n= bsp;    *LocalContext;

> +

> +  LocalContext =3D&n= bsp;(MTRR_LIB_TEST_CONTEXT *) Context;

> +

> +  CopyMem (&Syst= emParameter, LocalContext->SystemParameter, sizeof (Syste= mParameter));

> +  InitializeMtrrRegs = ;(&SystemParameter);

> +  //

> +  // Set random=  cache type to different ranges under 1M= B and make sure

> +  // the fixed&= nbsp;MTRR settings are expected.

> +  // Try 100&nb= sp;times.

> +  //

> +  for (Index = =3D 0; Index < 100; Index++) {

> +    for (M= srIndex =3D 0; MsrIndex < ARRAY_SIZE (mFix= edMtrrsIndex); MsrIndex++) {

> +      = ;MsrValue =3D 0;

> +      = ;for (ByteIndex =3D 0; ByteIndex < sizeof&= nbsp;(UINT64); ByteIndex++) {

> +      = ;  MsrValue =3D MsrValue | LShiftU64 (Ge= nerateRandomCacheType (), ByteIndex * 8);

> +      = ;}

> +      = ;ExpectedFixedSettings.Mtrr[MsrIndex] =3D MsrValue;

> +      = ;AsmWriteMsr64 (mFixedMtrrsIndex[MsrIndex], MsrValue);

> +    }
> +

> +    Result = ;=3D MtrrGetFixedMtrr (&FixedSettings);

> +    UT_ASSERT_E= QUAL (Result, &FixedSettings);

> +    UT_ASSERT_M= EM_EQUAL (&FixedSettings, &ExpectedFixedSettings, si= zeof (FixedSettings));

> +  }

> +

> +  //

> +  // Negative t= est case when MTRRs are not supported<= br>
> +  //

> +  SystemParameter.MtrrSup= ported =3D FALSE;

> +  InitializeMtrrRegs = ;(&SystemParameter);

> +

> +  ZeroMem (&Fixe= dSettings, sizeof (FixedSettings));

> +  ZeroMem (&Expe= ctedFixedSettings, sizeof (ExpectedFixedSettings));

> +  Result =3D Mt= rrGetFixedMtrr (&FixedSettings);

> +  UT_ASSERT_EQUAL (R= esult, &FixedSettings);

> +  UT_ASSERT_MEM_EQUAL&nbs= p;(&ExpectedFixedSettings, &FixedSettings, sizeof (E= xpectedFixedSettings));

> +

> +  return UNIT_TEST_P= ASSED;

> +}

> +

> +/**

> +  Unit test of&= nbsp;MtrrLib service MtrrGetAllMtrrs()

> +

> +  @param[in]  C= ontext    Ignored

> +

> +  @retval  UNIT= _TEST_PASSED          &nb= sp;  The Unit test has completed and&nbs= p;the test

> +      = ;            &n= bsp;            = ;         case was s= uccessful.

> +  @retval  UNIT= _TEST_ERROR_TEST_FAILED  A test case assertion&nbs= p;has failed.

> +

> +**/

> +UNIT_TEST_STATUS

> +EFIAPI

> +UnitTestMtrrGetAllMtrrs (

> +  IN UNIT_TEST_CONTE= XT      Context

> +  )

> +{

> +  MTRR_SETTINGS &nbs= p;           *Result= ;

> +  MTRR_SETTINGS &nbs= p;           Mtrrs;<= /span>

> +  MTRR_SETTINGS &nbs= p;           Expecte= dMtrrs;

> +  MTRR_VARIABLE_SETTING&n= bsp;    VariableMtrr[MTRR_NUMBER_OF_VARIABLE_MTRR];

> +  UINT32   = ;            &n= bsp;    Index;

> +  MTRR_LIB_SYSTEM_PARAMET= ER SystemParameter;

> +  MTRR_LIB_TEST_CONTEXT&n= bsp;    *LocalContext;

> +

> +  LocalContext =3D&n= bsp;(MTRR_LIB_TEST_CONTEXT *) Context;

> +

> +  CopyMem (&Syst= emParameter, LocalContext->SystemParameter, sizeof (Syste= mParameter));

> +  InitializeMtrrRegs = ;(&SystemParameter);

> +

> +  for (Index = =3D 0; Index < SystemParameter.VariableMtrrCount;&nb= sp;Index++) {

> +    GenerateRan= domMtrrPair (SystemParameter.PhysicalAddressBits, GenerateRandomC= acheType (), &VariableMtrr[Index],
> NULL);

> +    AsmWriteMsr= 64 (MSR_IA32_MTRR_PHYSBASE0 + (Index << 1),&= nbsp;VariableMtrr[Index].Base);

> +    AsmWriteMsr= 64 (MSR_IA32_MTRR_PHYSMASK0 + (Index << 1),&= nbsp;VariableMtrr[Index].Mask);

> +  }

> +  Result =3D Mt= rrGetAllMtrrs (&Mtrrs);

> +  UT_ASSERT_EQUAL (R= esult, &Mtrrs);

> +  UT_ASSERT_MEM_EQUAL&nbs= p;(Mtrrs.Variables.Mtrr, VariableMtrr, sizeof (MTRR_VARIABLE= _SETTING) *
> SystemParameter.VariableMtrrCount);<= /span>

> +

> +  //

> +  // Negative t= est case when MTRRs are not supported<= br>
> +  //

> +  ZeroMem (&Expe= ctedMtrrs, sizeof (ExpectedMtrrs));

> +  ZeroMem (&Mtrr= s, sizeof (Mtrrs));

> +

> +  SystemParameter.MtrrSup= ported =3D FALSE;

> +  InitializeMtrrRegs = ;(&SystemParameter);

> +  Result =3D Mt= rrGetAllMtrrs (&Mtrrs);

> +  UT_ASSERT_EQUAL (R= esult, &Mtrrs);

> +  UT_ASSERT_MEM_EQUAL&nbs= p;(&ExpectedMtrrs, &Mtrrs, sizeof (ExpectedMtrrs));<= /span>

> +

> +  //

> +  // Expect ASS= ERT() if variable MTRR count is > MTR= R_NUMBER_OF_VARIABLE_MTRR

> +  //

> +  SystemParameter.MtrrSup= ported =3D TRUE;

> +  SystemParameter.Variabl= eMtrrCount =3D MTRR_NUMBER_OF_VARIABLE_MTRR + 1;=

> +  InitializeMtrrRegs = ;(&SystemParameter);

> +  UT_EXPECT_ASSERT_FAILUR= E (MtrrGetAllMtrrs (&Mtrrs), NULL);

> +

> +  return UNIT_TEST_P= ASSED;

> +}

> +

> +/**

> +  Unit test of&= nbsp;MtrrLib service MtrrSetAllMtrrs()

> +

> +  @param[in]  C= ontext    Ignored

> +

> +  @retval  UNIT= _TEST_PASSED          &nb= sp;  The Unit test has completed and&nbs= p;the test

> +      = ;            &n= bsp;            = ;         case was s= uccessful.

> +  @retval  UNIT= _TEST_ERROR_TEST_FAILED  A test case assertion&nbs= p;has failed.

> +

> +**/

> +UNIT_TEST_STATUS

> +EFIAPI

> +UnitTestMtrrSetAllMtrrs (

> +  IN UNIT_TEST_CONTE= XT  Context

> +  )

> +{

> +  MTRR_SETTINGS &nbs= p;            &= nbsp;    *Result;

> +  MTRR_SETTINGS &nbs= p;            &= nbsp;    Mtrrs;

> +  UINT32   = ;            &n= bsp;          Index;

> +  MSR_IA32_MTRR_DEF_TYPE_= REGISTER Default;

> +  MTRR_LIB_SYSTEM_PARAMET= ER       SystemParameter;

> +  MTRR_LIB_TEST_CONTEXT&n= bsp;          *LocalConte= xt;

> +

> +  LocalContext =3D&n= bsp;(MTRR_LIB_TEST_CONTEXT *) Context;

> +

> +  CopyMem (&Syst= emParameter, LocalContext->SystemParameter, sizeof (Syste= mParameter));

> +  InitializeMtrrRegs = ;(&SystemParameter);

> +

> +  Default.Uint64 =3D=  0;

> +  Default.Bits.E =3D=  1;

> +  Default.Bits.FE = =3D 1;

> +  Default.Bits.Type = =3D GenerateRandomCacheType ();

> +

> +  ZeroMem (&Mtrr= s, sizeof (Mtrrs));

> +  Mtrrs.MtrrDefType = =3D Default.Uint64;

> +  for (Index = =3D 0; Index < SystemParameter.VariableMtrrCount;&nb= sp;Index++) {

> +    GenerateRan= domMtrrPair (SystemParameter.PhysicalAddressBits, GenerateRandomC= acheType (),
> &Mtrrs.Variables.Mtrr[Index],&nb= sp;NULL);

> +  }

> +  Result =3D Mt= rrSetAllMtrrs (&Mtrrs);

> +  UT_ASSERT_EQUAL (R= esult, &Mtrrs);

> +

> +  UT_ASSERT_EQUAL (A= smReadMsr64 (MSR_IA32_MTRR_DEF_TYPE), Mtrrs.MtrrDefType);<= br>
> +  for (Index = =3D 0; Index < SystemParameter.VariableMtrrCount;&nb= sp;Index++) {

> +    UT_ASSERT_E= QUAL (AsmReadMsr64 (MSR_IA32_MTRR_PHYSBASE0 + (Index&nb= sp;<< 1)), Mtrrs.Variables.Mtrr[Index].Base);

> +    UT_ASSERT_E= QUAL (AsmReadMsr64 (MSR_IA32_MTRR_PHYSMASK0 + (Index&nb= sp;<< 1)), Mtrrs.Variables.Mtrr[Index].Mask);

> +  }

> +

> +  return UNIT_TEST_P= ASSED;

> +}

> +

> +/**

> +  Unit test of&= nbsp;MtrrLib service MtrrGetMemoryAttributeInVariableMtrr()

> +

> +  @param[in]  C= ontext    Ignored

> +

> +  @retval  UNIT= _TEST_PASSED          &nb= sp;  The Unit test has completed and&nbs= p;the test

> +      = ;            &n= bsp;            = ;         case was s= uccessful.

> +  @retval  UNIT= _TEST_ERROR_TEST_FAILED  A test case assertion&nbs= p;has failed.

> +

> +**/

> +UNIT_TEST_STATUS

> +EFIAPI

> +UnitTestMtrrGetMemoryAttributeInVar= iableMtrr (

> +  IN UNIT_TEST_CONTE= XT  Context

> +  )

> +{

> +  MTRR_LIB_TEST_CONTEXT&n= bsp;          *LocalConte= xt;

> +  MTRR_LIB_SYSTEM_PARAMET= ER       SystemParameter;

> +  UINT32   = ;            &n= bsp;          Result;

> +  MTRR_VARIABLE_SETTING&n= bsp;          VariableSet= ting[MTRR_NUMBER_OF_VARIABLE_MTRR];

> +  VARIABLE_MTRR &nbs= p;            &= nbsp;    VariableMtrr[MTRR_NUMBER_OF_VARIABLE_MTRR];

> +  UINT64   = ;            &n= bsp;          ValidMtrrBi= tsMask;

> +  UINT64   = ;            &n= bsp;          ValidMtrrAd= dressMask;

> +  UINT32   = ;            &n= bsp;          Index;

> +  MSR_IA32_MTRR_PHYSBASE_= REGISTER Base;

> +  MSR_IA32_MTRR_PHYSMASK_= REGISTER Mask;

> +

> +  LocalContext =3D&n= bsp;(MTRR_LIB_TEST_CONTEXT *) Context;

> +

> +  CopyMem (&Syst= emParameter, LocalContext->SystemParameter, sizeof (Syste= mParameter));

> +

> +  InitializeMtrrRegs = ;(&SystemParameter);

> +

> +  ValidMtrrBitsMask =    =3D (1ull << SystemParameter.Physica= lAddressBits) - 1;

> +  ValidMtrrAddressMask&nb= sp;=3D ValidMtrrBitsMask & 0xfffffffffffff000ULL;=

> +

> +  for (Index = =3D 0; Index < SystemParameter.VariableMtrrCount;&nb= sp;Index++) {

> +    GenerateRan= domMtrrPair (SystemParameter.PhysicalAddressBits, GenerateRandomC= acheType (),
> &VariableSetting[Index], NU= LL);

> +    AsmWriteMsr= 64 (MSR_IA32_MTRR_PHYSBASE0 + (Index << 1),&= nbsp;VariableSetting[Index].Base);

> +    AsmWriteMsr= 64 (MSR_IA32_MTRR_PHYSMASK0 + (Index << 1),&= nbsp;VariableSetting[Index].Mask);

> +  }

> +  Result =3D Mt= rrGetMemoryAttributeInVariableMtrr (ValidMtrrBitsMask, ValidMtrrA= ddressMask, VariableMtrr);

> +  UT_ASSERT_EQUAL (R= esult, SystemParameter.VariableMtrrCount);

> +

> +  for (Index = =3D 0; Index < SystemParameter.VariableMtrrCount;&nb= sp;Index++) {

> +    Base.Uint64=     =3D VariableMtrr[Index].BaseAddress;
> +    Base.Bits.T= ype =3D (UINT32) VariableMtrr[Index].Type;

> +    UT_ASSERT_E= QUAL (Base.Uint64, VariableSetting[Index].Base);

> +

> +    Mask.Uint64=     =3D ~(VariableMtrr[Index].Length - 1= ) & ValidMtrrBitsMask;

> +    Mask.Bits.V=     =3D 1;

> +    UT_ASSERT_E= QUAL (Mask.Uint64, VariableSetting[Index].Mask);

> +  }

> +

> +  //

> +  // Negative t= est case when MTRRs are not supported<= br>
> +  //

> +  SystemParameter.MtrrSup= ported =3D FALSE;

> +  InitializeMtrrRegs = ;(&SystemParameter);

> +  Result =3D Mt= rrGetMemoryAttributeInVariableMtrr (ValidMtrrBitsMask, ValidMtrrA= ddressMask, VariableMtrr);

> +  UT_ASSERT_EQUAL (R= esult, 0);

> +

> +  //

> +  // Expect ASS= ERT() if variable MTRR count is > MTR= R_NUMBER_OF_VARIABLE_MTRR

> +  //

> +  SystemParameter.MtrrSup= ported =3D TRUE;

> +  SystemParameter.Variabl= eMtrrCount =3D MTRR_NUMBER_OF_VARIABLE_MTRR + 1;=

> +  InitializeMtrrRegs = ;(&SystemParameter);

> +  UT_EXPECT_ASSERT_FAILUR= E (MtrrGetMemoryAttributeInVariableMtrr (ValidMtrrBitsMask, = ValidMtrrAddressMask,
> VariableMtrr), NULL);
> +

> +  return UNIT_TEST_P= ASSED;

> +}

> +

> +/**

> +  Unit test of&= nbsp;MtrrLib service MtrrDebugPrintAllMtrrs()

> +

> +  @param[in]  C= ontext    Ignored

> +

> +  @retval  UNIT= _TEST_PASSED          &nb= sp;  The Unit test has completed and&nbs= p;the test

> +      = ;            &n= bsp;            = ;         case was s= uccessful.

> +  @retval  UNIT= _TEST_ERROR_TEST_FAILED  A test case assertion&nbs= p;has failed.

> +

> +**/

> +UNIT_TEST_STATUS

> +EFIAPI

> +UnitTestMtrrDebugPrintAllMtrrs = ;(

> +  IN UNIT_TEST_CONTE= XT  Context

> +  )

> +{

> +  return UNIT_TEST_P= ASSED;

> +}

> +

> +/**

> +  Unit test of&= nbsp;MtrrLib service MtrrGetDefaultMemoryType().

> +

> +  @param[in]  C= ontext    Ignored

> +

> +  @retval  UNIT= _TEST_PASSED          &nb= sp;  The Unit test has completed and&nbs= p;the test

> +      = ;            &n= bsp;            = ;         case was s= uccessful.

> +  @retval  UNIT= _TEST_ERROR_TEST_FAILED  A test case assertion&nbs= p;has failed.

> +

> +**/

> +UNIT_TEST_STATUS

> +EFIAPI

> +UnitTestMtrrGetDefaultMemoryType&nb= sp;(

> +  IN UNIT_TEST_CONTE= XT  Context

> +  )

> +{

> +  MTRR_LIB_TEST_CONTEXT&n= bsp;    *LocalContext;

> +  UINTN   =             &nb= sp;     Index;

> +  MTRR_MEMORY_CACHE_TYPE&= nbsp;   Result;

> +  MTRR_LIB_SYSTEM_PARAMET= ER SystemParameter;

> +  MTRR_MEMORY_CACHE_TYPE&= nbsp;   CacheType[5];

> +

> +  CacheType[0] =3D&n= bsp;CacheUncacheable;

> +  CacheType[1] =3D&n= bsp;CacheWriteCombining;

> +  CacheType[2] =3D&n= bsp;CacheWriteThrough;

> +  CacheType[3] =3D&n= bsp;CacheWriteProtected;

> +  CacheType[4] =3D&n= bsp;CacheWriteBack;

> +

> +  LocalContext =3D&n= bsp;(MTRR_LIB_TEST_CONTEXT *) Context;

> +

> +  CopyMem (&Syst= emParameter, LocalContext->SystemParameter, sizeof (Syste= mParameter));

> +  //

> +  // If MTRRs&n= bsp;are supported, then always return the cac= he type in the MSR

> +  // MSR_IA32_MTRR_D= EF_TYPE

> +  //

> +  for (Index = =3D 0; Index < ARRAY_SIZE (CacheType); Ind= ex++) {

> +    SystemParam= eter.DefaultCacheType =3D CacheType[Index];

> +    InitializeM= trrRegs (&SystemParameter);

> +    Result = ;=3D MtrrGetDefaultMemoryType ();

> +    UT_ASSERT_E= QUAL (Result, SystemParameter.DefaultCacheType);

> +  }

> +

> +  //

> +  // If MTRRs&n= bsp;are not supported, then always return Cac= heUncacheable

> +  //

> +  SystemParameter.MtrrSup= ported =3D FALSE;

> +  InitializeMtrrRegs = ;(&SystemParameter);

> +  Result =3D Mt= rrGetDefaultMemoryType ();

> +  UT_ASSERT_EQUAL (R= esult, CacheUncacheable);

> +

> +  SystemParameter.MtrrSup= ported =3D TRUE;

> +  SystemParameter.FixedMt= rrSupported =3D FALSE;

> +  InitializeMtrrRegs = ;(&SystemParameter);

> +  Result =3D Mt= rrGetDefaultMemoryType ();

> +  UT_ASSERT_EQUAL (R= esult, CacheUncacheable);

> +

> +  SystemParameter.MtrrSup= ported =3D TRUE;

> +  SystemParameter.FixedMt= rrSupported =3D TRUE;

> +  SystemParameter.Variabl= eMtrrCount =3D 0;

> +  InitializeMtrrRegs = ;(&SystemParameter);

> +  Result =3D Mt= rrGetDefaultMemoryType ();

> +  UT_ASSERT_EQUAL (R= esult, CacheUncacheable);

> +

> +  return UNIT_TEST_P= ASSED;

> +}

> +

> +/**

> +  Unit test of&= nbsp;MtrrLib service MtrrSetMemoryAttributeInMtrrSettings().

> +

> +  @param[in]  C= ontext    Ignored

> +

> +  @retval  UNIT= _TEST_PASSED          &nb= sp;  The Unit test has completed and&nbs= p;the test

> +      = ;            &n= bsp;            = ;         case was s= uccessful.

> +  @retval  UNIT= _TEST_ERROR_TEST_FAILED  A test case assertion&nbs= p;has failed.

> +

> +**/

> +UNIT_TEST_STATUS

> +EFIAPI

> +UnitTestMtrrSetMemoryAttributeInMtr= rSettings (

> +  IN UNIT_TEST_CONTE= XT  Context

> +  )

> +{

> +  CONST MTRR_LIB_SYS= TEM_PARAMETER *SystemParameter;

> +  RETURN_STATUS &nbs= p;            &= nbsp;    Status;

> +  UINT32   = ;            &n= bsp;          UcCount;

> +  UINT32   = ;            &n= bsp;          WtCount;

> +  UINT32   = ;            &n= bsp;          WbCount;

> +  UINT32   = ;            &n= bsp;          WpCount;

> +  UINT32   = ;            &n= bsp;          WcCount;

> +

> +  UINTN   =             &nb= sp;           MtrrIn= dex;

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

> +  MTRR_SETTINGS &nbs= p;            &= nbsp;    LocalMtrrs;

> +

> +  MTRR_MEMORY_RANGE =             &nb= sp; RawMtrrRange[MTRR_NUMBER_OF_VARIABLE_MTRR];

> +  MTRR_MEMORY_RANGE =             &nb= sp; ExpectedMemoryRanges[MTRR_NUMBER_OF_FIXED_MTRR * sizeof&= nbsp;(UINT64) + 2 *
> MTRR_NUMBER_OF_VARIABLE_MTRR +&= nbsp;1];

> +  UINT32   = ;            &n= bsp;          ExpectedVar= iableMtrrUsage;

> +  UINTN   =             &nb= sp;           Expect= edMemoryRangesCount;

> +

> +  MTRR_MEMORY_RANGE =             &nb= sp; ActualMemoryRanges[MTRR_NUMBER_OF_FIXED_MTRR * sizeof&nb= sp;(UINT64) + 2 *
> MTRR_NUMBER_OF_VARIABLE_MTRR +&= nbsp;1];

> +  UINT32   = ;            &n= bsp;          ActualVaria= bleMtrrUsage;

> +  UINTN   =             &nb= sp;           Actual= MemoryRangesCount;

> +

> +  MTRR_SETTINGS &nbs= p;            &= nbsp;    *Mtrrs[2];

> +

> +  SystemParameter = =3D (MTRR_LIB_SYSTEM_PARAMETER *) Context;

> +  GenerateRandomMemoryTyp= eCombination (

> +    SystemParam= eter->VariableMtrrCount - PatchPcdGet32 (PcdCpuNumberOfRe= servedVariableMtrrs),

> +    &UcCoun= t, &WtCount, &WbCount, &WpCount, &WcCou= nt

> +    );
> +  GenerateValidAndConfigu= rableMtrrPairs (

> +    SystemParam= eter->PhysicalAddressBits, RawMtrrRange,

> +    UcCount,&nb= sp;WtCount, WbCount, WpCount, WcCount

> +    );
> +

> +  ExpectedVariableMtrrUsa= ge =3D UcCount + WtCount + WbCount +&nbs= p;WpCount + WcCount;

> +  ExpectedMemoryRangesCou= nt =3D ARRAY_SIZE (ExpectedMemoryRanges);

> +  GetEffectiveMemoryRange= s (

> +    SystemParam= eter->DefaultCacheType,

> +    SystemParam= eter->PhysicalAddressBits,

> +    RawMtrrRang= e, ExpectedVariableMtrrUsage,

> +    ExpectedMem= oryRanges, &ExpectedMemoryRangesCount

> +    );
> +

> +  UT_LOG_INFO ("= ;--- Expected Memory Ranges [%d] ---\n", = ;ExpectedMemoryRangesCount);

> +  DumpMemoryRanges (= ExpectedMemoryRanges, ExpectedMemoryRangesCount);

> +  //

> +  // Default ca= che type is always an INPUT

> +  //

> +  ZeroMem (&Loca= lMtrrs, sizeof (LocalMtrrs));

> +  LocalMtrrs.MtrrDefType&= nbsp;=3D MtrrGetDefaultMemoryType ();

> +  Mtrrs[0]  &nb= sp;            = =3D &LocalMtrrs;

> +  Mtrrs[1]  &nb= sp;            = =3D NULL;

> +

> +  for (MtrrIndex&nbs= p;=3D 0; MtrrIndex < ARRAY_SIZE (Mtrrs); M= trrIndex++) {

> +    for (I= ndex =3D 0; Index < ExpectedMemoryRangesCount;&= nbsp;Index++) {

> +      = ;Status =3D MtrrSetMemoryAttributeInMtrrSettings (
> +      = ;           Mtrrs[Mt= rrIndex],

> +      = ;           Expected= MemoryRanges[Index].BaseAddress,

> +      = ;           Expected= MemoryRanges[Index].Length,

> +      = ;           Expected= MemoryRanges[Index].Type

> +      = ;           );

> +      = ;UT_ASSERT_TRUE (Status =3D=3D RETURN_SUCCESS || S= tatus =3D=3D RETURN_OUT_OF_RESOURCES || Status =3D= =3D
> RETURN_BUFFER_TOO_SMALL);

> +      = ;if (Status =3D=3D RETURN_OUT_OF_RESOURCES || Stat= us =3D=3D RETURN_BUFFER_TOO_SMALL) {

> +      = ;  return UNIT_TEST_SKIPPED;

> +      = ;}

> +    }
> +

> +    if (Mt= rrs[MtrrIndex] =3D=3D NULL) {

> +      = ;ZeroMem (&LocalMtrrs, sizeof (LocalMtrrs));

> +      = ;MtrrGetAllMtrrs (&LocalMtrrs);

> +    }
> +    ActualMemor= yRangesCount =3D ARRAY_SIZE (ActualMemoryRanges);

> +    CollectTest= Result (

> +      = ;SystemParameter->DefaultCacheType, SystemParameter->PhysicalAdd= ressBits, SystemParameter->VariableMtrrCount,

> +      = ;&LocalMtrrs, ActualMemoryRanges, &ActualMemoryRangesCoun= t, &ActualVariableMtrrUsage

> +      = ;);

> +    UT_LOG_INFO=  ("--- Actual Memory Ranges [%d] ---\n&q= uot;, ActualMemoryRangesCount);

> +    DumpMemoryR= anges (ActualMemoryRanges, ActualMemoryRangesCount);

> +    VerifyMemor= yRanges (ExpectedMemoryRanges, ExpectedMemoryRangesCount, Ac= tualMemoryRanges,
> ActualMemoryRangesCount);

> +    UT_ASSERT_T= RUE (ExpectedVariableMtrrUsage >=3D ActualVariableMtrrUsa= ge);

> +

> +    ZeroMem&nbs= p;(&LocalMtrrs, sizeof (LocalMtrrs));

> +  }

> +

> +  return UNIT_TEST_P= ASSED;

> +}

> +

> +

> +/**

> +  Prep routine = for UnitTestGetFirmwareVariableMtrrCount().

> +

> +  @param Context&nbs= p; Point to a UINT32 data to save t= he PcdCpuNumberOfReservedVariableMtrrs.

> +**/

> +UNIT_TEST_STATUS

> +EFIAPI

> +SavePcdValue (

> +  UNIT_TEST_CONTEXT =  Context

> +  )

> +{

> +  MTRR_LIB_GET_FIRMWARE_V= ARIABLE_MTRR_COUNT_CONTEXT  *LocalContext;

> +

> +  LocalContext =3D&n= bsp;(MTRR_LIB_GET_FIRMWARE_VARIABLE_MTRR_COUNT_CONTEXT *) Context= ;

> +  LocalContext->Number= OfReservedVariableMtrrs =3D PatchPcdGet32 (PcdCpuNumberOfRes= ervedVariableMtrrs);

> +  return UNIT_TEST_P= ASSED;

> +}

> +

> +/**

> +  Clean up rout= ine for UnitTestGetFirmwareVariableMtrrCount().

> +

> +  @param Context&nbs= p; Point to a UINT32 data to save t= he PcdCpuNumberOfReservedVariableMtrrs.

> +**/

> +UNIT_TEST_STATUS

> +EFIAPI

> +RestorePcdValue (

> +  UNIT_TEST_CONTEXT =  Context

> +  )

> +{

> +  MTRR_LIB_GET_FIRMWARE_V= ARIABLE_MTRR_COUNT_CONTEXT  *LocalContext;

> +

> +  LocalContext =3D&n= bsp;(MTRR_LIB_GET_FIRMWARE_VARIABLE_MTRR_COUNT_CONTEXT *) Context= ;

> +  PatchPcdSet32 (Pcd= CpuNumberOfReservedVariableMtrrs, LocalContext->NumberOfReservedVar= iableMtrrs);

> +  return UNIT_TEST_P= ASSED;

> +}

> +

> +/**

> +  Initialize the&nbs= p;unit test framework, suite, and unit tests&= nbsp;for the

> +  ResetSystemLib and=  run the ResetSystemLib unit test.

> +

> +  @param Iteration&n= bsp;            = ;  Iteration of testing MtrrSetMemoryAttributeInMt= rrSettings

> +      = ;            &n= bsp;            = ;  and MtrrSetMemoryAttributesInMtrrSettings using = ;random inputs.

> +

> +  @retval  EFI_= SUCCESS           Al= l test cases were dispatched.

> +  @retval  EFI_= OUT_OF_RESOURCES  There are not enough resour= ces available to

> +      = ;            &n= bsp;            = ;  initialize the unit tests.

> +**/

> +STATIC

> +EFI_STATUS

> +EFIAPI

> +UnitTestingEntry (

> +  UINTN   =             &nb= sp;       Iteration

> +  )

> +{

> +  EFI_STATUS  &= nbsp;           &nbs= p;            &= nbsp;           &nbs= p;Status;

> +  UNIT_TEST_FRAMEWORK_HAN= DLE            =             Fra= mework;

> +  UNIT_TEST_SUITE_HANDLE&= nbsp;           &nbs= p;            &= nbsp;  MtrrApiTests;

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

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

> +  MTRR_LIB_TEST_CONTEXT&n= bsp;            = ;            &n= bsp;   Context;

> +  MTRR_LIB_GET_FIRMWARE_V= ARIABLE_MTRR_COUNT_CONTEXT GetFirmwareVariableMtrrCountContext;=

> +

> +  Context.SystemParameter=             &nb= sp;            =     =3D &mDefaultSystemParameter;

> +  GetFirmwareVariableMtrr= CountContext.SystemParameter =3D &mDefaultSystemParameter;

> +  Framework =3D = ;NULL;

> +

> +  DEBUG ((DEBUG_INFO= , "%a v%a\n", UNIT_TEST_APP_NAME, UNIT_TEST_A= PP_VERSION));

> +

> +  //

> +  // Setup the&= nbsp;test framework for running the tests.<= br>
> +  //

> +  Status =3D In= itUnitTestFramework (&Framework, UNIT_TEST_APP_NAME, gEf= iCallerBaseName, UNIT_TEST_APP_VERSION);

> +  if (EFI_ERROR = ;(Status)) {

> +    DEBUG = ((DEBUG_ERROR, "Failed in InitUnitTestFramework. S= tatus =3D %r\n", Status));

> +    goto E= XIT;

> +  }

> +

> +  //

> +  // --------------S= uite-----------Description--------------Name----------Function--------Pre--= -Post-------------------Context-----------

> +  //

> +

> +  //

> +  // Populate t= he MtrrLib API Unit Test Suite.

> +  //

> +  Status =3D Cr= eateUnitTestSuite (&MtrrApiTests, Framework, "MtrrL= ib API Tests", "MtrrLib.MtrrLib", NULL,&= nbsp;NULL);

> +  if (EFI_ERROR = ;(Status)) {

> +    DEBUG = ((DEBUG_ERROR, "Failed in CreateUnitTestSuite for&= nbsp;MtrrLib API Tests\n"));

> +    Status = ;=3D EFI_OUT_OF_RESOURCES;

> +    goto E= XIT;

> +  }

> +  AddTestCase (MtrrA= piTests, "Test IsMtrrSupported",    = ;            &n= bsp;     "MtrrSupported",
> UnitTestIsMtrrSupported,  =             &nb= sp;       NULL, NULL, &Con= text);

> +  AddTestCase (MtrrA= piTests, "Test GetVariableMtrrCount",   =             &nb= sp; "GetVariableMtrrCount",
> UnitTestGetVariableMtrrCount, &= nbsp;           &nbs= p;   NULL, NULL, &Context);

> +  AddTestCase (MtrrA= piTests, "Test GetFirmwareVariableMtrrCount", &nbs= p;       "GetFirmwareVariableMtrrCo= unt",
> UnitTestGetFirmwareVariableMtrrCount= ,         SavePcdValue, R= estorePcdValue, &GetFirmwareVariableMtrrCountContext);

> +  AddTestCase (MtrrA= piTests, "Test MtrrGetMemoryAttribute",  &nbs= p;            &= quot;MtrrGetMemoryAttribute",
> UnitTestMtrrGetMemoryAttribute, = ;            &n= bsp; NULL, NULL, &Context);

> +  AddTestCase (MtrrA= piTests, "Test MtrrGetFixedMtrr",   &nbs= p;            &= nbsp;    "MtrrGetFixedMtrr",
> UnitTestMtrrGetFixedMtrr,  = ;            &n= bsp;      NULL, NULL, &Context)= ;

> +  AddTestCase (MtrrA= piTests, "Test MtrrGetAllMtrrs",    = ;            &n= bsp;     "MtrrGetAllMtrrs",
> UnitTestMtrrGetAllMtrrs,  =             &nb= sp;       NULL, NULL, &Con= text);

> +  AddTestCase (MtrrA= piTests, "Test MtrrSetAllMtrrs",    = ;            &n= bsp;     "MtrrSetAllMtrrs",  &= nbsp;           &nbs= p;       UnitTestMtrrSetAllMtrrs,=
> NULL, NULL, &Context);=

> +  AddTestCase (MtrrA= piTests, "Test MtrrGetMemoryAttributeInVariableMtrr",&n= bsp;"MtrrGetMemoryAttributeInVariableMtrr",
> UnitTestMtrrGetMemoryAttributeInVari= ableMtrr, NULL, NULL, &Context);

> +  AddTestCase (MtrrA= piTests, "Test MtrrDebugPrintAllMtrrs",  &nbs= p;            &= quot;MtrrDebugPrintAllMtrrs",
> UnitTestMtrrDebugPrintAllMtrrs, = ;            &n= bsp; NULL, NULL, &Context);

> +  AddTestCase (MtrrA= piTests, "Test MtrrGetDefaultMemoryType",  &n= bsp;          "MtrrG= etDefaultMemoryType",
> UnitTestMtrrGetDefaultMemoryType,&nb= sp;            = NULL, NULL, &Context);

> +

> +  for (SystemIndex&n= bsp;=3D 0; SystemIndex < ARRAY_SIZE (mSystemPar= ameters); SystemIndex++) {

> +    for (I= ndex =3D 0; Index < Iteration; Index++)&nb= sp;{

> +      = ;AddTestCase (MtrrApiTests, "Test InvalidMemoryLayouts&= quot;,           &nb= sp;      "InvalidMemoryLayouts",
> UnitTestInvalidMemoryLayouts, &= nbsp;           &nbs= p;    InitializeMtrrRegs, NULL, &mSystemP= arameters[SystemIndex]);

> +      = ;AddTestCase (MtrrApiTests, "Test MtrrSetMemoryAttribut= eInMtrrSettings",  "MtrrSetMemoryAttributeInMtrrSetting= s",
> UnitTestMtrrSetMemoryAttributeInMtrr= Settings,  InitializeMtrrRegs, NULL, &mSystemParame= ters[SystemIndex]);

> +      = ;AddTestCase (MtrrApiTests, "Test MtrrSetMemoryAttribut= esInMtrrSettings",
> "MtrrSetMemoryAttributesInMtrrS= ettings", UnitTestMtrrSetMemoryAttributesInMtrrSettings, Ini= tializeMtrrRegs, NULL,
> &mSystemParameters[SystemIndex])= ;

> +    }
> +  }

> +  //

> +  // Execute th= e tests.

> +  //

> +  srand ((unsigned&n= bsp;int) time (NULL));

> +  Status =3D Ru= nAllTestSuites (Framework);

> +

> +EXIT:

> +  if (Framework = ;!=3D NULL) {

> +    FreeUnitTes= tFramework (Framework);

> +  }

> +

> +  return Status;

> +}

> +

> +/**

> +  Standard POSIX&nbs= p;C entry point for host based unit test=  execution.

> +

> +  @param Argc &= nbsp;Number of arguments.

> +  @param Argv &= nbsp;Array of arguments.

> +

> +  @return Test = application exit code.

> +**/

> +INT32

> +main (

> +  INT32 Argc,=

> +  CHAR8 *Argv[]

> +  )

> +{

> +  UINTN   =  Iteration;

> +

> +  //

> +  // First para= meter specifies the test iterations.

> +  // Default is=  10.

> +  //

> +  Iteration =3D = ;10;

> +  if (Argc =3D= =3D 2) {

> +    Iteration&n= bsp;=3D atoi (Argv[1]);

> +  }

> +  return UnitTesting= Entry (Iteration);

> +}

> diff --git a/UefiCpuPkg/Li= brary/MtrrLib/UnitTest/MtrrLibUnitTest.h
> b/UefiCpuPkg/Library/MtrrLib/UnitTes= t/MtrrLibUnitTest.h
> new file mode 100644<= /span>
> index 0000000000..25d4269589
> --- /dev/null
> +++ b/UefiCpuPkg/Library/MtrrLi= b/UnitTest/MtrrLibUnitTest.h
> @@ -0,0 +1,171 @@
> +/** @file

> +

> +  Copyright (c) = ;2020, Intel Corporation. All rights reserved.<= BR>

> +  SPDX-License-Identifier= : BSD-2-Clause-Patent

> +

> +**/

> +

> +#ifndef _MTRR_SUPPORT_H_

> +#define _MTRR_SUPPORT_H_

> +

> +#include <stdio.h>

> +#include <stdlib.h>

> +#include <string.h>

> +#include <stdarg.h>

> +#include <stddef.h>

> +#include <setjmp.h>

> +#include <cmocka.h>

> +#include <time.h>=

> +

> +#include <Uefi.h>=

> +#include <Library/BaseLib.h= >

> +#include <Library/BaseMemor= yLib.h>

> +#include <Library/DebugLib.= h>

> +#include <Library/UnitTestL= ib.h>

> +#include <Library/MtrrLib.h= >

> +#include <Library/UnitTestH= ostBaseLib.h>

> +

> +#include <Register/Architec= turalMsr.h>

> +#include <Register/Cpuid.h&= gt;

> +#include <Register/Msr.h>= ;

> +

> +#define UNIT_TEST_APP_NAME&nbs= p;       "MtrrLib Unit Te= sts"

> +#define UNIT_TEST_APP_VERSION&= nbsp;    "1.0"

> +

> +#define SCRATCH_BUFFER_SIZE&nb= sp;      SIZE_16KB

> +

> +typedef struct {
> +  UINT8   =             &nb= sp;  PhysicalAddressBits;

> +  BOOLEAN  &nbs= p;            &= nbsp;MtrrSupported;

> +  BOOLEAN  &nbs= p;            &= nbsp;FixedMtrrSupported;

> +  MTRR_MEMORY_CACHE_TYPE&= nbsp;DefaultCacheType;

> +  UINT32   = ;            &n= bsp; VariableMtrrCount;

> +} MTRR_LIB_SYSTEM_PARAMETER;

> +

> +extern UINT32   = ;            &n= bsp;           mFixe= dMtrrsIndex[];

> +

> +/**

> +  Initialize the&nbs= p;MTRR registers.

> +

> +  @param SystemParam= eter System parameter that controls the MTRR&= nbsp;registers initialization.

> +**/

> +UNIT_TEST_STATUS

> +EFIAPI

> +InitializeMtrrRegs (
> +  IN MTRR_LIB_SYSTEM= _PARAMETER  *SystemParameter

> +  );

> +

> +/**

> +  Return a rand= om memory cache type.

> +**/

> +MTRR_MEMORY_CACHE_TYPE

> +GenerateRandomCacheType (

> +  VOID

> +  );

> +

> +/**

> +  Generate random&nb= sp;MTRRs.

> +

> +  @param PhysicalAdd= ressBits  Physical address bits.

> +  @param RawMemoryRa= nges      Return the randomly = generated MTRRs.

> +  @param UcCount&nbs= p;            &= nbsp;Count of Uncacheable MTRRs.

> +  @param WtCount&nbs= p;            &= nbsp;Count of Write Through MTRRs.

> +  @param WbCount&nbs= p;            &= nbsp;Count of Write Back MTRRs.

> +  @param WpCount&nbs= p;            &= nbsp;Count of Write Protected MTRRs.

> +  @param WcCount&nbs= p;            &= nbsp;Count of Write Combining MTRRs.

> +**/

> +VOID

> +GenerateValidAndConfigurableMtrrPai= rs (

> +  IN   &nb= sp; UINT32          =           PhysicalAddress= Bits,

> +  IN OUT MTRR_M= EMORY_RANGE         *RawMemory= Ranges,

> +  IN   &nb= sp; UINT32          =           UcCount,=

> +  IN   &nb= sp; UINT32          =           WtCount,=

> +  IN   &nb= sp; UINT32          =           WbCount,=

> +  IN   &nb= sp; UINT32          =           WpCount,=

> +  IN   &nb= sp; UINT32          =           WcCount<= br>
> +  );

> +

> +/**

> +  Convert the M= TRR BASE/MASK array to memory ranges.

> +

> +  @param DefaultType=           Default me= mory type.

> +  @param PhysicalAdd= ressBits  Physical address bits.

> +  @param RawMemoryRa= nges      Raw memory ranges.=

> +  @param RawMemoryRa= ngeCount  Count of raw memory ranges.<= br>
> +  @param MemoryRange= s         Memory ranges.<= /span>

> +  @param MemoryRange= Count     Count of memory ranges.

> +**/

> +VOID

> +GetEffectiveMemoryRanges (

> +  IN MTRR_MEMORY_CAC= HE_TYPE DefaultType,

> +  IN UINT32 &nb= sp;            =    PhysicalAddressBits,

> +  IN MTRR_MEMORY_RAN= GE      *RawMemoryRanges,

> +  IN UINT32 &nb= sp;            =    RawMemoryRangeCount,

> +  OUT MTRR_MEMORY_RA= NGE     *MemoryRanges,

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

> +  );

> +

> +/**

> +  Generate random&nb= sp;MTRR BASE/MASK for a specified type.

> +

> +  @param PhysicalAdd= ressBits Physical address bits.

> +  @param CacheType&n= bsp;          Cache = type.

> +  @param MtrrPair&nb= sp;           Return=  the random MTRR.

> +  @param MtrrMemoryR= ange     Return the random memory&n= bsp;range.

> +**/

> +VOID

> +GenerateRandomMtrrPair (

> +  IN  UINT32&nb= sp;            =     PhysicalAddressBits,

> +  IN  MTRR_MEMO= RY_CACHE_TYPE CacheType,

> +  OUT MTRR_VARIABLE_= SETTING  *MtrrPair,       OPTI= ONAL

> +  OUT MTRR_MEMORY_RA= NGE      *MtrrMemoryRange OPTIONAL

> +  );

> +

> +/**

> +  Collect the t= est result.

> +

> +  @param DefaultType=           Default me= mory type.

> +  @param PhysicalAdd= ressBits  Physical address bits.

> +  @param VariableMtr= rCount    Count of variable MTRRs.

> +  @param Mtrrs =             &nb= sp;  MTRR settings to collect from.
> +  @param Ranges = ;            &n= bsp; Return the memory ranges.

> +  @param RangeCount&= nbsp;          Return&nbs= p;the count of memory ranges.

> +  @param MtrrCount&n= bsp;           Retur= n the count of variable MTRRs being used= .

> +**/

> +VOID

> +CollectTestResult (

> +  IN   &nb= sp; MTRR_MEMORY_CACHE_TYPE DefaultType,

> +  IN   &nb= sp; UINT32          =        PhysicalAddressBits,

> +  IN   &nb= sp; UINT32          =        VariableMtrrCount,

> +  IN   &nb= sp; MTRR_SETTINGS         = ; *Mtrrs,

> +  OUT   &n= bsp;MTRR_MEMORY_RANGE      *Ranges,
> +  IN OUT UINTN&= nbsp;           &nbs= p;     *RangeCount,

> +  OUT   &n= bsp;UINT32           = ;      *MtrrCount

> +  );

> +

> +/**

> +  Return a 64bi= t random number.

> +

> +  @param Start =  Start of the random number range.

> +  @param Limit =  Limit of the random number range.

> +  @return 64bit = ;random number

> +**/

> +UINT64

> +Random64 (

> +  UINT64  Start= ,

> +  UINT64  Limit=

> +  );

> +

> +/**

> +  Return a 32bi= t random number.

> +

> +  @param Start =  Start of the random number range.

> +  @param Limit =  Limit of the random number range.

> +  @return 32bit = ;random number

> +**/

> +UINT32

> +Random32 (

> +  UINT32  Start= ,

> +  UINT32  Limit=

> +  );

> +#endif

> diff --git a/UefiCpuPkg/Li= brary/MtrrLib/UnitTest/MtrrLibUnitTestHost.inf
> b/UefiCpuPkg/Library/MtrrLib/UnitTes= t/MtrrLibUnitTestHost.inf
> new file mode 100644<= /span>
> index 0000000000..447238dc81
> --- /dev/null
> +++ b/UefiCpuPkg/Library/MtrrLi= b/UnitTest/MtrrLibUnitTestHost.inf
> @@ -0,0 +1,39 @@
> +## @file

> +# Unit tests of = ;the MtrrLib instance of the MtrrLib class

> +#

> +# Copyright (c) 2020= , Intel Corporation. All rights reserved.<BR>= ;

> +# SPDX-License-Identifier:&nbs= p;BSD-2-Clause-Patent

> +##

> +

> +[Defines]

> +  INF_VERSION  =             &nb= sp;     =3D 0x00010006

> +  BASE_NAME  &n= bsp;            = ;       =3D MtrrLibUnitTestHost

> +  FILE_GUID  &n= bsp;            = ;       =3D A1542D84-B64D-4847-885E= -0509084376AB

> +  MODULE_TYPE  =             &nb= sp;     =3D HOST_APPLICATION

> +  VERSION_STRING &nb= sp;            =    =3D 1.0

> +

> +#

> +# The following info= rmation is for reference only and not re= quired by the build tools.

> +#

> +#  VALID_ARCHITECTURES&nb= sp;          =3D IA3= 2 X64

> +#

> +

> +[Sources]

> +  MtrrLibUnitTest.c

> +  MtrrLibUnitTest.h

> +  Support.c

> +

> +[Packages]

> +  MdePkg/MdePkg.dec

> +  UefiCpuPkg/UefiCpuPkg.d= ec

> +  UnitTestFrameworkPkg/Un= itTestFrameworkPkg.dec

> +

> +[LibraryClasses]

> +  BaseLib

> +  BaseMemoryLib
> +  DebugLib

> +  MtrrLib

> +  UnitTestLib

> +

> +[Pcd]

> +  gUefiCpuPkgTokenSpaceGu= id.PcdCpuNumberOfReservedVariableMtrrs   ## SOMETIMES_C= ONSUMES

> diff --git a/UefiCpuPkg/Li= brary/MtrrLib/UnitTest/Support.c b/UefiCpuPkg/Library/MtrrLib/UnitTest= /Support.c
> new file mode 100644<= /span>
> index 0000000000..9fe4b0278e
> --- /dev/null
> +++ b/UefiCpuPkg/Library/MtrrLi= b/UnitTest/Support.c
> @@ -0,0 +1,913 @@
> +/** @file

> +  Unit tests of=  the MtrrLib instance of the MtrrLib cla= ss

> +

> +  Copyright (c) = ;2018 - 2020, Intel Corporation. All rights&n= bsp;reserved.<BR>

> +  SPDX-License-Identifier= : BSD-2-Clause-Patent

> +

> +**/

> +

> +#include "MtrrLibUnitTest= .h"

> +

> +MTRR_MEMORY_CACHE_TYPE mMemory= CacheTypes[] =3D {

> +  CacheUncacheable, = CacheWriteCombining, CacheWriteThrough, CacheWriteProtected, = ;CacheWriteBack

> +  };

> +

> +UINT64     = ;            &n= bsp;         mFixedMtrrsValue[= MTRR_NUMBER_OF_FIXED_MTRR];

> +MSR_IA32_MTRR_PHYSBASE_REGISTER&nbs= p; mVariableMtrrsPhysBase[MTRR_NUMBER_OF_VARIABLE_MTRR];

> +MSR_IA32_MTRR_PHYSMASK_REGISTER&nbs= p; mVariableMtrrsPhysMask[MTRR_NUMBER_OF_VARIABLE_MTRR];

> +MSR_IA32_MTRR_DEF_TYPE_REGISTER&nbs= p; mDefTypeMsr;

> +MSR_IA32_MTRRCAP_REGISTER &nbs= p;      mMtrrCapMsr;

> +CPUID_VERSION_INFO_EDX  &= nbsp;        mCpuidVersionInfoEdx;<= /span>

> +CPUID_VIR_PHY_ADDRESS_SIZE_EAX = ;  mCpuidVirPhyAddressSizeEax;

> +

> +/**

> +  Retrieves CPUID&nb= sp;information.

> +

> +  Executes the = CPUID instruction with EAX set to the va= lue specified by Index.

> +  This function = ;always returns Index.

> +  If Eax is&nbs= p;not NULL, then the value of EAX after&= nbsp;CPUID is returned in Eax.

> +  If Ebx is&nbs= p;not NULL, then the value of EBX after&= nbsp;CPUID is returned in Ebx.

> +  If Ecx is&nbs= p;not NULL, then the value of ECX after&= nbsp;CPUID is returned in Ecx.

> +  If Edx is&nbs= p;not NULL, then the value of EDX after&= nbsp;CPUID is returned in Edx.

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

> +  @param  Index=  The 32-bit value to load into EAX = prior to invoking the CPUID

> +      = ;          instruction.

> +  @param  Eax&n= bsp;  The pointer to the 32-bit EAX = ;value returned by the CPUID

> +      = ;          instruction.&n= bsp;This is an optional parameter that may&nb= sp;be NULL.

> +  @param  Ebx&n= bsp;  The pointer to the 32-bit EBX = ;value returned by the CPUID

> +      = ;          instruction.&n= bsp;This is an optional parameter that may&nb= sp;be NULL.

> +  @param  Ecx&n= bsp;  The pointer to the 32-bit ECX = ;value returned by the CPUID

> +      = ;          instruction.&n= bsp;This is an optional parameter that may&nb= sp;be NULL.

> +  @param  Edx&n= bsp;  The pointer to the 32-bit EDX = ;value returned by the CPUID

> +      = ;          instruction.&n= bsp;This is an optional parameter that may&nb= sp;be NULL.

> +

> +  @return Index.

> +

> +**/

> +UINT32

> +EFIAPI

> +UnitTestMtrrLibAsmCpuid (

> +  IN   &nb= sp;  UINT32         =            Index,

> +  OUT   &n= bsp; UINT32          = ;          *Eax, &nb= sp;OPTIONAL

> +  OUT   &n= bsp; UINT32          = ;          *Ebx, &nb= sp;OPTIONAL

> +  OUT   &n= bsp; UINT32          = ;          *Ecx, &nb= sp;OPTIONAL

> +  OUT   &n= bsp; UINT32          = ;          *Edx &nbs= p; OPTIONAL

> +  )

> +{

> +  switch (Index)&nbs= p;{

> +  case CPUID_VERSION= _INFO:

> +    if (Ed= x !=3D NULL) {

> +      = ;*Edx =3D mCpuidVersionInfoEdx.Uint32;

> +    }
> +    return = ;Index;

> +    break;

> +  case CPUID_EXTENDE= D_FUNCTION:

> +    if (Ea= x !=3D NULL) {

> +      = ;*Eax =3D CPUID_VIR_PHY_ADDRESS_SIZE;

> +    }
> +    return = ;Index;

> +    break;

> +  case CPUID_VIR_PHY= _ADDRESS_SIZE:

> +    if (Ea= x !=3D NULL) {

> +      = ;*Eax =3D mCpuidVirPhyAddressSizeEax.Uint32;

> +    }
> +    return = ;Index;

> +    break;

> +  }

> +

> +  //

> +  // Should nev= er fall through to here

> +  //

> +  ASSERT(FALSE);
> +  return Index;

> +}

> +

> +/**

> +  Returns a 64-= bit Machine Specific Register(MSR).

> +

> +  Reads and ret= urns the 64-bit MSR specified by Index. = No parameter checking is

> +  performed on = Index, and some Index values may cause C= PU exceptions. The

> +  caller must e= ither guarantee that Index is valid, or = the caller must set up

> +  exception handlers=  to catch the exceptions. This function = is only available

> +  on IA-32 and&= nbsp;x64.

> +

> +  @param  MsrIn= dex The 32-bit MSR index to read.

> +

> +  @return The v= alue of the MSR identified by MsrIndex.

> +

> +**/

> +UINT64

> +EFIAPI

> +UnitTestMtrrLibAsmReadMsr64(=

> +  IN UINT32 &nb= sp;MsrIndex

> +  )

> +{

> +  UINT32 Index;

> +

> +  for (Index = =3D 0; Index < ARRAY_SIZE (mFixedMtrrsValue);&n= bsp;Index++) {

> +    if (Ms= rIndex =3D=3D mFixedMtrrsIndex[Index]) {

> +      = ;return mFixedMtrrsValue[Index];

> +    }
> +  }

> +

> +  if ((MsrIndex = ;>=3D MSR_IA32_MTRR_PHYSBASE0) &&

> +      = ;(MsrIndex <=3D MSR_IA32_MTRR_PHYSMASK0 + (MTRR_NUMB= ER_OF_VARIABLE_MTRR << 1))) {

> +    if (Ms= rIndex % 2 =3D=3D 0) {

> +      = ;Index =3D (MsrIndex - MSR_IA32_MTRR_PHYSBASE0) &g= t;> 1;

> +      = ;return mVariableMtrrsPhysBase[Index].Uint64;

> +    } else=  {

> +      = ;Index =3D (MsrIndex - MSR_IA32_MTRR_PHYSMASK0) &g= t;> 1;

> +      = ;return mVariableMtrrsPhysMask[Index].Uint64;

> +    }
> +  }

> +

> +  if (MsrIndex = =3D=3D MSR_IA32_MTRR_DEF_TYPE) {

> +    return = ;mDefTypeMsr.Uint64;

> +  }

> +

> +  if (MsrIndex = =3D=3D MSR_IA32_MTRRCAP) {

> +    return = ;mMtrrCapMsr.Uint64;

> +  }

> +

> +  //

> +  // Should nev= er fall through to here

> +  //

> +  ASSERT(FALSE);
> +  return 0;
> +}

> +

> +/**

> +  Writes a 64-b= it value to a Machine Specific Register(MSR),=  and returns the

> +  value.

> +

> +  Writes the 64= -bit value specified by Value to the MSR=  specified by Index. The

> +  64-bit value = written to the MSR is returned. No param= eter checking is

> +  performed on = Index or Value, and some of these may&nb= sp;cause CPU exceptions. The

> +  caller must e= ither guarantee that Index and Value are = ;valid, or the caller

> +  must establish&nbs= p;proper exception handlers. This function is = ;only available on

> +  IA-32 and x64= .

> +

> +  @param  MsrIn= dex The 32-bit MSR index to write.

> +  @param  Value=  The 64-bit value to write to the M= SR.

> +

> +  @return Value

> +

> +**/

> +UINT64

> +EFIAPI

> +UnitTestMtrrLibAsmWriteMsr64(

> +  IN   &nb= sp;  UINT32         =            MsrIndex,=

> +  IN   &nb= sp;  UINT64         =            Value

> +  )

> +{

> +  UINT32 Index;

> +

> +  for (Index = =3D 0; Index < ARRAY_SIZE (mFixedMtrrsValue);&n= bsp;Index++) {

> +    if (Ms= rIndex =3D=3D mFixedMtrrsIndex[Index]) {

> +      = ;mFixedMtrrsValue[Index] =3D Value;

> +      = ;return Value;

> +    }
> +  }

> +

> +  if ((MsrIndex = ;>=3D MSR_IA32_MTRR_PHYSBASE0) &&

> +      = ;(MsrIndex <=3D MSR_IA32_MTRR_PHYSMASK0 + (MTRR_NUMB= ER_OF_VARIABLE_MTRR << 1))) {

> +    if (Ms= rIndex % 2 =3D=3D 0) {

> +      = ;Index =3D (MsrIndex - MSR_IA32_MTRR_PHYSBASE0) &g= t;> 1;

> +      = ;mVariableMtrrsPhysBase[Index].Uint64 =3D Value;

> +      = ;return Value;

> +    } else=  {

> +      = ;Index =3D (MsrIndex - MSR_IA32_MTRR_PHYSMASK0) &g= t;> 1;

> +      = ;mVariableMtrrsPhysMask[Index].Uint64 =3D Value;

> +      = ;return Value;

> +    }
> +  }

> +

> +  if (MsrIndex = =3D=3D MSR_IA32_MTRR_DEF_TYPE) {

> +    mDefTypeMsr= .Uint64 =3D Value;

> +    return = ;Value;

> +  }

> +

> +  if (MsrIndex = =3D=3D MSR_IA32_MTRRCAP) {

> +    mMtrrCapMsr= .Uint64 =3D Value;

> +    return = ;Value;

> +  }

> +

> +  //

> +  // Should nev= er fall through to here

> +  //

> +  ASSERT(FALSE);
> +  return 0;
> +}

> +

> +/**

> +  Initialize MTRR&nb= sp;registers.

> +**/

> +

> +/**

> +  Initialize the&nbs= p;MTRR registers.

> +

> +  @param SystemParam= eter System parameter that controls the MTRR&= nbsp;registers initialization.

> +**/

> +UNIT_TEST_STATUS

> +EFIAPI

> +InitializeMtrrRegs (
> +  IN MTRR_LIB_SYSTEM= _PARAMETER  *SystemParameter

> +  )

> +{

> +  UINT32   = ;            &n= bsp;    Index;

> +

> +  SetMem (mFixedMtrr= sValue, sizeof (mFixedMtrrsValue), SystemParameter->Defau= ltCacheType);

> +

> +  for (Index = =3D 0; Index < ARRAY_SIZE (mVariableMtrrsPhysBa= se); Index++) {

> +    mVariableMt= rrsPhysBase[Index].Uint64        &n= bsp;=3D 0;

> +    mVariableMt= rrsPhysBase[Index].Bits.Type      =3D Sy= stemParameter->DefaultCacheType;

> +    mVariableMt= rrsPhysBase[Index].Bits.Reserved1 =3D 0;

> +

> +    mVariableMt= rrsPhysMask[Index].Uint64        &n= bsp;=3D 0;

> +    mVariableMt= rrsPhysMask[Index].Bits.V        &n= bsp;=3D 0;

> +    mVariableMt= rrsPhysMask[Index].Bits.Reserved1 =3D 0;

> +  }

> +

> +  mDefTypeMsr.Bits.E = ;        =3D 1;

> +  mDefTypeMsr.Bits.FE&nbs= p;       =3D 1;

> +  mDefTypeMsr.Bits.Type&n= bsp;     =3D SystemParameter->DefaultCache= Type;

> +  mDefTypeMsr.Bits.Reserv= ed1 =3D 0;

> +  mDefTypeMsr.Bits.Reserv= ed2 =3D 0;

> +  mDefTypeMsr.Bits.Reserv= ed3 =3D 0;

> +

> +  mMtrrCapMsr.Bits.SMRR&n= bsp;     =3D 0;

> +  mMtrrCapMsr.Bits.WC&nbs= p;       =3D 0;

> +  mMtrrCapMsr.Bits.VCNT&n= bsp;     =3D SystemParameter->VariableMtrr= Count;

> +  mMtrrCapMsr.Bits.FIX&nb= sp;      =3D SystemParameter->FixedMt= rrSupported;

> +  mMtrrCapMsr.Bits.Reserv= ed1 =3D 0;

> +  mMtrrCapMsr.Bits.Reserv= ed2 =3D 0;

> +  mMtrrCapMsr.Bits.Reserv= ed3 =3D 0;

> +

> +  mCpuidVersionInfoEdx.Bi= ts.MTRR           &n= bsp;          =3D Sy= stemParameter->MtrrSupported;

> +  mCpuidVirPhyAddressSize= Eax.Bits.PhysicalAddressBits =3D SystemParameter->PhysicalAddr= essBits;

> +

> +  //

> +  // Hook BaseL= ib functions used by MtrrLib that require&nbs= p;some emulation.

> +  //

> +  gUnitTestHostBaseLib.X8= 6->AsmCpuid      =3D UnitTestMtrrLibA= smCpuid;

> +  gUnitTestHostBaseLib.X8= 6->AsmReadMsr64  =3D UnitTestMtrrLibAsmReadMsr64;<= br>
> +  gUnitTestHostBaseLib.X8= 6->AsmWriteMsr64 =3D UnitTestMtrrLibAsmWriteMsr64;

> +

> +  return UNIT_TEST_P= ASSED;

> +}

> +

> +/**

> +  Collect the t= est result.

> +

> +  @param DefaultType=           Default me= mory type.

> +  @param PhysicalAdd= ressBits  Physical address bits.

> +  @param VariableMtr= rCount    Count of variable MTRRs.

> +  @param Mtrrs =             &nb= sp;  MTRR settings to collect from.
> +  @param Ranges = ;            &n= bsp; Return the memory ranges.

> +  @param RangeCount&= nbsp;          Return&nbs= p;the count of memory ranges.

> +  @param MtrrCount&n= bsp;           Retur= n the count of variable MTRRs being used= .

> +**/

> +VOID

> +CollectTestResult (

> +  IN   &nb= sp; MTRR_MEMORY_CACHE_TYPE DefaultType,

> +  IN   &nb= sp; UINT32          =        PhysicalAddressBits,

> +  IN   &nb= sp; UINT32          =        VariableMtrrCount,

> +  IN   &nb= sp; MTRR_SETTINGS         = ; *Mtrrs,

> +  OUT   &n= bsp;MTRR_MEMORY_RANGE      *Ranges,
> +  IN OUT UINTN&= nbsp;           &nbs= p;     *RangeCount,

> +  OUT   &n= bsp;UINT32           = ;      *MtrrCount

> +  )

> +{

> +  UINTN   =           Index;
> +  UINT64   = ;         MtrrValidBitsMask;

> +  UINT64   = ;         MtrrValidAddressMask= ;

> +  MTRR_MEMORY_RANGE = RawMemoryRanges[ARRAY_SIZE (Mtrrs->Variables.Mtrr)];

> +

> +  ASSERT (Mtrrs = ;!=3D NULL);

> +  ASSERT (VariableMt= rrCount <=3D ARRAY_SIZE (Mtrrs->Variables.Mtrr));

> +

> +  MtrrValidBitsMask = =3D (1ull << PhysicalAddressBits) - 1;

> +  MtrrValidAddressMask&nb= sp;=3D MtrrValidBitsMask & ~0xFFFull;

> +

> +  *MtrrCount =3D&nbs= p;0;

> +  for (Index = =3D 0; Index < VariableMtrrCount; Index++) = ;{

> +    if (((= MSR_IA32_MTRR_PHYSMASK_REGISTER *) &Mtrrs->Variables.Mtrr[= Index].Mask)->Bits.V =3D=3D 1) {

> +      = ;RawMemoryRanges[*MtrrCount].BaseAddress =3D Mtrrs->Variables.= Mtrr[Index].Base & MtrrValidAddressMask;

> +      = ;RawMemoryRanges[*MtrrCount].Type       =  =3D

> +      = ;  ((MSR_IA32_MTRR_PHYSBASE_REGISTER *) &Mtrrs->= Variables.Mtrr[Index].Base)->Bits.Type;

> +      = ;RawMemoryRanges[*MtrrCount].Length      =3D<= /span>

> +      = ;    ((~(Mtrrs->Variables.Mtrr[Index].Mask &= ; MtrrValidAddressMask)) & MtrrValidBitsMask) +&nbs= p;1;

> +      = ;(*MtrrCount)++;

> +    }
> +  }

> +

> +  GetEffectiveMemoryRange= s (DefaultType, PhysicalAddressBits, RawMemoryRanges, *= MtrrCount, Ranges, RangeCount);

> +}

> +

> +/**

> +  Return a 32bi= t random number.

> +

> +  @param Start =  Start of the random number range.

> +  @param Limit =  Limit of the random number range.

> +  @return 32bit = ;random number

> +**/

> +UINT32

> +Random32 (

> +  UINT32  Start= ,

> +  UINT32  Limit=

> +  )

> +{

> +  return (UINT32)&nb= sp;(((double) rand () / RAND_MAX) * (Limit&nb= sp;- Start)) + Start;

> +}

> +

> +/**

> +  Return a 64bi= t random number.

> +

> +  @param Start =  Start of the random number range.

> +  @param Limit =  Limit of the random number range.

> +  @return 64bit = ;random number

> +**/

> +UINT64

> +Random64 (

> +  UINT64  Start= ,

> +  UINT64  Limit=

> +  )

> +{

> +  return (UINT64)&nb= sp;(((double) rand () / RAND_MAX) * (Limit&nb= sp;- Start)) + Start;

> +}

> +

> +/**

> +  Generate random&nb= sp;MTRR BASE/MASK for a specified type.

> +

> +  @param PhysicalAdd= ressBits Physical address bits.

> +  @param CacheType&n= bsp;          Cache = type.

> +  @param MtrrPair&nb= sp;           Return=  the random MTRR.

> +  @param MtrrMemoryR= ange     Return the random memory&n= bsp;range.

> +**/

> +VOID

> +GenerateRandomMtrrPair (

> +  IN  UINT32&nb= sp;            =     PhysicalAddressBits,

> +  IN  MTRR_MEMO= RY_CACHE_TYPE CacheType,

> +  OUT MTRR_VARIABLE_= SETTING  *MtrrPair,       OPTI= ONAL

> +  OUT MTRR_MEMORY_RA= NGE      *MtrrMemoryRange OPTIONAL

> +  )

> +{

> +  MSR_IA32_MTRR_PHYSBASE_= REGISTER PhysBase;

> +  MSR_IA32_MTRR_PHYSMASK_= REGISTER PhysMask;

> +  UINT32   = ;            &n= bsp;          SizeShift;<= /span>

> +  UINT32   = ;            &n= bsp;          BaseShift;<= /span>

> +  UINT64   = ;            &n= bsp;          RandomBound= ary;

> +  UINT64   = ;            &n= bsp;          MaxPhysical= Address;

> +  UINT64   = ;            &n= bsp;          RangeSize;<= /span>

> +  UINT64   = ;            &n= bsp;          RangeBase;<= /span>

> +  UINT64   = ;            &n= bsp;          PhysBasePhy= MaskValidBitsMask;

> +

> +  MaxPhysicalAddress = ;=3D 1ull << PhysicalAddressBits;

> +  do {

> +    SizeShift&n= bsp;=3D Random32 (12, PhysicalAddressBits - 1);

> +    RangeSize&n= bsp;=3D 1ull << SizeShift;

> +

> +    BaseShift&n= bsp;=3D Random32 (SizeShift, PhysicalAddressBits - = ;1);

> +    RandomBound= ary =3D Random64 (0, 1ull << (PhysicalA= ddressBits - BaseShift));

> +    RangeBase&n= bsp;=3D RandomBoundary << BaseShift;

> +  } while (Rang= eBase < SIZE_1MB || RangeBase > MaxPhys= icalAddress - 1);

> +

> +  PhysBasePhyMaskValidBit= sMask =3D (MaxPhysicalAddress - 1) & 0xff= fffffffffff000ULL;

> +

> +  PhysBase.Uint64 &n= bsp;  =3D 0;

> +  PhysBase.Bits.Type = ;=3D CacheType;

> +  PhysBase.Uint64 &n= bsp; |=3D RangeBase & PhysBasePhyMaskValidBitsMask;=

> +  PhysMask.Uint64 &n= bsp;  =3D 0;

> +  PhysMask.Bits.V &n= bsp;  =3D 1;

> +  PhysMask.Uint64 &n= bsp; |=3D ((~RangeSize) + 1) & PhysBasePh= yMaskValidBitsMask;

> +

> +  if (MtrrPair = !=3D NULL) {

> +    MtrrPair-&g= t;Base =3D PhysBase.Uint64;

> +    MtrrPair-&g= t;Mask =3D PhysMask.Uint64;

> +  }

> +

> +  if (MtrrMemoryRang= e !=3D NULL) {

> +    MtrrMemoryR= ange->BaseAddress =3D RangeBase;

> +    MtrrMemoryR= ange->Length      =3D RangeSize;

> +    MtrrMemoryR= ange->Type        =3D Cache= Type;

> +  }

> +}

> +

> +

> +/**

> +  Check whether = ;the Range overlaps with any one in Rang= es.

> +

> +  @param Range =  The memory range to check.

> +  @param Ranges = ;The memory ranges.

> +  @param Count =  Count of memory ranges.

> +

> +  @return TRUE = when overlap exists.

> +**/

> +BOOLEAN

> +RangesOverlap (

> +  IN MTRR_MEMORY_RAN= GE *Range,

> +  IN MTRR_MEMORY_RAN= GE *Ranges,

> +  IN UINTN &nbs= p;           Count

> +  )

> +{

> +  while (Count--&nbs= p;!=3D 0) {

> +    //
> +    // Two=  ranges overlap when:

> +    // 1.&= nbsp;range#2.base is in the middle of range#1=

> +    // 2.&= nbsp;range#1.base is in the middle of range#2=

> +    //
> +    if ((R= ange->BaseAddress <=3D Ranges[Count].BaseAddress &= & Ranges[Count].BaseAddress < Range->BaseAddress&n= bsp;+
> Range->Length)

> +     ||&nb= sp;(Ranges[Count].BaseAddress <=3D Range->BaseAddress = && Range->BaseAddress < Ranges[Count].BaseAddr= ess +
> Ranges[Count].Length)) {=

> +      = ;return TRUE;

> +    }
> +  }

> +  return FALSE;

> +}

> +

> +/**

> +  Generate random&nb= sp;MTRRs.

> +

> +  @param PhysicalAdd= ressBits  Physical address bits.

> +  @param RawMemoryRa= nges      Return the randomly = generated MTRRs.

> +  @param UcCount&nbs= p;            &= nbsp;Count of Uncacheable MTRRs.

> +  @param WtCount&nbs= p;            &= nbsp;Count of Write Through MTRRs.

> +  @param WbCount&nbs= p;            &= nbsp;Count of Write Back MTRRs.

> +  @param WpCount&nbs= p;            &= nbsp;Count of Write Protected MTRRs.

> +  @param WcCount&nbs= p;            &= nbsp;Count of Write Combine MTRRs.

> +**/

> +VOID

> +GenerateValidAndConfigurableMtrrPai= rs (

> +  IN   &nb= sp; UINT32          =           PhysicalAddress= Bits,

> +  IN OUT MTRR_M= EMORY_RANGE         *RawMemory= Ranges,

> +  IN   &nb= sp; UINT32          =           UcCount,=

> +  IN   &nb= sp; UINT32          =           WtCount,=

> +  IN   &nb= sp; UINT32          =           WbCount,=

> +  IN   &nb= sp; UINT32          =           WpCount,=

> +  IN   &nb= sp; UINT32          =           WcCount<= br>
> +  )

> +{

> +  UINT32   = ;            &n= bsp;          Index;

> +

> +  //

> +  // 1. Generat= e UC, WT, WB in order.

> +  //

> +  for (Index = =3D 0; Index < UcCount; Index++) {<= br>
> +    GenerateRan= domMtrrPair (PhysicalAddressBits, CacheUncacheable, NULL,&nb= sp;&RawMemoryRanges[Index]);

> +  }

> +

> +  for (Index = =3D UcCount; Index < UcCount + WtCount;&nb= sp;Index++) {

> +    GenerateRan= domMtrrPair (PhysicalAddressBits, CacheWriteThrough, NULL,&n= bsp;&RawMemoryRanges[Index]);

> +  }

> +

> +  for (Index = =3D UcCount + WtCount; Index < UcCount&nbs= p;+ WtCount + WbCount; Index++) {

> +    GenerateRan= domMtrrPair (PhysicalAddressBits, CacheWriteBack, NULL, = ;&RawMemoryRanges[Index]);

> +  }

> +

> +  //

> +  // 2. Generat= e WP MTRR and DO NOT overlap with W= T, WB.

> +  //

> +  for (Index = =3D UcCount + WtCount + WbCount; Index &= lt; UcCount + WtCount + WbCount + WpCoun= t; Index++) {

> +    GenerateRan= domMtrrPair (PhysicalAddressBits, CacheWriteProtected, NULL,=  &RawMemoryRanges[Index]);

> +    while = (RangesOverlap (&RawMemoryRanges[Index], &RawMemoryRanges= [UcCount], WtCount + WbCount)) {

> +      = ;GenerateRandomMtrrPair (PhysicalAddressBits, CacheWriteProtected= , NULL, &RawMemoryRanges[Index]);

> +    }
> +  }

> +

> +  //

> +  // 3. Generat= e WC MTRR and DO NOT overlap with W= T, WB, WP.

> +  //

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

> +    GenerateRan= domMtrrPair (PhysicalAddressBits, CacheWriteCombining, NULL,=  &RawMemoryRanges[Index]);

> +    while = (RangesOverlap (&RawMemoryRanges[Index], &RawMemoryRanges= [UcCount], WtCount + WbCount + WpCount)) > {

> +      = ;GenerateRandomMtrrPair (PhysicalAddressBits, CacheWriteCombining= , NULL, &RawMemoryRanges[Index]);

> +    }
> +  }

> +}

> +

> +/**

> +  Return a rand= om memory cache type.

> +**/

> +MTRR_MEMORY_CACHE_TYPE

> +GenerateRandomCacheType (

> +  VOID

> +  )

> +{

> +    return = ;mMemoryCacheTypes[Random32 (0, ARRAY_SIZE (mMemoryCacheType= s) - 1)];

> +}

> +

> +/**

> +  Compare function&n= bsp;used by qsort().

> +**/

> +

> +/**

> +  Compare function&n= bsp;used by qsort().

> +

> +  @param Left &= nbsp; Left operand to compare.

> +  @param Right =  Right operand to compare.

> +

> +  @retval 0 &nb= sp;Left =3D=3D Right

> +  @retval -1 Le= ft < Right

> +  @retval 1 &nb= sp;Left > Right

> +**/

> +INT32

> +CompareFuncUint64 (

> +  CONST VOID *&= nbsp;Left,

> +  CONST VOID *&= nbsp;Right

> +  )

> +{

> +    INT64 = Delta;

> +    Delta = =3D (*(UINT64*)Left - *(UINT64*)Right);

> +    if (De= lta > 0) {

> +      = ;return 1;

> +    } else=  if (Delta =3D=3D 0) {

> +      = ;return 0;

> +    } else=  {

> +      = ;return -1;

> +    }
> +}

> +

> +/**

> +  Determin the = memory cache type for the Range.

> +

> +  @param DefaultType=  Default cache type.

> +  @param Range =       The memory range to = ;determin the cache type.

> +  @param Ranges = ;     The entire memory ranges.

> +  @param RangeCount&= nbsp; Count of the entire memory ranges.

> +**/

> +VOID

> +DetermineMemoryCacheType (

> +  IN   &nb= sp; MTRR_MEMORY_CACHE_TYPE DefaultType,

> +  IN OUT MTRR_M= EMORY_RANGE      *Range,

> +  IN   &nb= sp; MTRR_MEMORY_RANGE      *Ranges,

> +  IN   &nb= sp; UINT32          =        RangeCount

> +  )

> +{

> +  UINT32 Index;

> +  Range->Type =3D=  CacheInvalid;

> +  for (Index = =3D 0; Index < RangeCount; Index++) {

> +    if (Ra= ngesOverlap (Range, &Ranges[Index], 1)) {
> +      = ;if (Ranges[Index].Type < Range->Type) {
> +      = ;  Range->Type =3D Ranges[Index].Type;

> +      = ;}

> +    }
> +  }

> +

> +  if (Range->Type=  =3D=3D CacheInvalid) {

> +    Range->T= ype =3D DefaultType;

> +  }

> +}

> +

> +/**

> +  Get the index=  of the element that does NOT equals&nbs= p;to Array[Index].

> +

> +  @param Index =   Current element.

> +  @param Array =   Array to scan.

> +  @param Count =   Count of the array.

> +

> +  @return Next = element that doesn't equal to current one.

> +**/

> +UINT32

> +GetNextDifferentElementInSortedArra= y (

> +  IN UINT32 Ind= ex,

> +  IN UINT64 *Ar= ray,

> +  IN UINT32 Cou= nt

> +  )

> +{

> +  UINT64 CurrentElem= ent;

> +  CurrentElement =3D=  Array[Index];

> +  while (CurrentElem= ent =3D=3D Array[Index] && Index < = ;Count) {

> +    Index++;

> +  }

> +  return Index;

> +}

> +

> +/**

> +  Remove the du= plicates from the array.

> +

> +  @param Array =  The array to operate on.

> +  @param Count =  Count of the array.

> +**/

> +VOID

> +RemoveDuplicatesInSortedArray = (

> +  IN OUT UINT64=  *Array,

> +  IN OUT UINT32=  *Count

> +  )

> +{

> +  UINT32 Index;

> +  UINT32 NewCount;

> +

> +  Index   =  =3D 0;

> +  NewCount =3D = 0;

> +  while (Index = < *Count) {

> +    Array[NewCo= unt] =3D Array[Index];

> +    NewCount++;=

> +    Index = =3D GetNextDifferentElementInSortedArray (Index, Array, = ;*Count);

> +  }

> +  *Count =3D Ne= wCount;

> +}

> +

> +/**

> +  Return TRUE w= hen Address is in the Range.

> +

> +  @param Address&nbs= p;The address to check.

> +  @param Range =   The range to check.

> +  @return TRUE = when Address is in the Range.

> +**/

> +BOOLEAN

> +AddressInRange (

> +  IN UINT64 &nb= sp;          Address,

> +  IN MTRR_MEMORY_RAN= GE Range

> +  )

> +{

> +    return = ;(Address >=3D Range.BaseAddress) && (Addres= s <=3D Range.BaseAddress + Range.Length - = 1);

> +}

> +

> +/**

> +  Get the overl= ap bit flag.

> +

> +  @param RawMemoryRa= nges     Raw memory ranges.

> +  @param RawMemoryRa= ngeCount Count of raw memory ranges.

> +  @param Address&nbs= p;            T= he address to check.

> +**/

> +UINT64

> +GetOverlapBitFlag (

> +  IN MTRR_MEMORY_RAN= GE *RawMemoryRanges,

> +  IN UINT32 &nb= sp;          RawMemoryRan= geCount,

> +  IN UINT64 &nb= sp;          Address

> +  )

> +{

> +  UINT64 OverlapBitF= lag;

> +  UINT32 Index;

> +  OverlapBitFlag =3D=  0;

> +  for (Index = =3D 0; Index < RawMemoryRangeCount; Index++)&nb= sp;{

> +    if (Ad= dressInRange (Address, RawMemoryRanges[Index])) {

> +      = ;OverlapBitFlag |=3D (1ull << Index);

> +    }
> +  }

> +

> +  return OverlapBitF= lag;

> +}

> +

> +/**

> +  Return the re= lationship between flags.

> +

> +  @param Flag1 = Flag 1

> +  @param Flag2 = Flag 2

> +

> +  @retval 0 &nb= sp; Flag1 =3D=3D Flag2

> +  @retval 1 &nb= sp; Flag1 is a subset of Flag2

> +  @retval 2 &nb= sp; Flag2 is a subset of Flag1

> +  @retval 3 &nb= sp; No subset relations between Flag1 and&nbs= p;Flag2.

> +**/

> +UINT32

> +CheckOverlapBitFlagsRelation (=

> +  IN UINT64 Fla= g1,

> +  IN UINT64 Fla= g2

> +  )

> +{

> +    if (Fl= ag1 =3D=3D Flag2) return 0;

> +    if ((F= lag1 | Flag2) =3D=3D Flag2) return 1;<= br>
> +    if ((F= lag1 | Flag2) =3D=3D Flag1) return 2;<= br>
> +    return = ;3;

> +}

> +

> +/**

> +  Return TRUE w= hen the Endpoint is in any of the R= anges.

> +

> +  @param Endpoint&nb= sp;   The endpoint to check.

> +  @param Ranges = ;     The memory ranges.

> +  @param RangeCount&= nbsp; Count of memory ranges.

> +

> +  @retval TRUE =  Endpoint is in one of the range.=

> +  @retval FALSE = ;Endpoint is not in any of the ranges.

> +**/

> +BOOLEAN

> +IsEndpointInRanges (
> +  IN UINT64 &nb= sp;          Endpoint,

> +  IN MTRR_MEMORY_RAN= GE *Ranges,

> +  IN UINTN &nbs= p;           RangeCo= unt

> +  )

> +{

> +    UINT32 = ;Index;

> +    for (I= ndex =3D 0; Index < RangeCount; Index++)&n= bsp;{

> +      = ;if (AddressInRange (Endpoint, Ranges[Index])) {=

> +      = ;  return TRUE;

> +      = ;}

> +    }
> +    return = ;FALSE;

> +}

> +

> +

> +/**

> +  Compact adjacent&n= bsp;ranges of the same type.

> +

> +  @param DefaultType=             &nb= sp;       Default memory type.=

> +  @param PhysicalAdd= ressBits           &= nbsp;Physical address bits.

> +  @param EffectiveMt= rrMemoryRanges      Memory ranges t= o compact.

> +  @param EffectiveMt= rrMemoryRangesCount Return the new count of m= emory ranges.

> +**/

> +VOID

> +CompactAndExtendEffectiveMtrrMemory= Ranges (

> +  IN   &nb= sp; MTRR_MEMORY_CACHE_TYPE DefaultType,

> +  IN   &nb= sp; UINT32          =        PhysicalAddressBits,

> +  IN OUT MTRR_M= EMORY_RANGE      **EffectiveMtrrMemoryRanges,=

> +  IN OUT UINTN&= nbsp;           &nbs= p;     *EffectiveMtrrMemoryRangesCount

> +  )

> +{

> +  UINT64   = ;            &n= bsp;        MaxAddress;

> +  UINTN   =             &nb= sp;         NewRangesCountAtMo= st;

> +  MTRR_MEMORY_RANGE =             *Ne= wRanges;

> +  UINTN   =             &nb= sp;         NewRangesCountActu= al;

> +  MTRR_MEMORY_RANGE =             *Cu= rrentRangeInNewRanges;

> +  MTRR_MEMORY_CACHE_TYPE&= nbsp;       CurrentRangeTypeInOldRanges;=

> +

> +  MTRR_MEMORY_RANGE =             *Ol= dRanges;

> +  MTRR_MEMORY_RANGE =             Old= LastRange;

> +  UINTN   =             &nb= sp;         OldRangesIndex;

> +

> +  NewRangesCountActual&nb= sp;=3D 0;

> +  NewRangesCountAtMost&nb= sp;=3D *EffectiveMtrrMemoryRangesCount + 2;   = ;// At most with 2 more range entries.

> +  NewRanges  &n= bsp;         =3D (MTRR_ME= MORY_RANGE *) calloc (NewRangesCountAtMost, sizeof = ;(MTRR_MEMORY_RANGE));

> +  OldRanges  &n= bsp;         =3D *Effecti= veMtrrMemoryRanges;

> +  if (OldRanges[0].B= aseAddress > 0) {

> +    NewRanges[N= ewRangesCountActual].BaseAddress =3D 0;

> +    NewRanges[N= ewRangesCountActual].Length      =3D Old= Ranges[0].BaseAddress;

> +    NewRanges[N= ewRangesCountActual].Type        = =3D DefaultType;

> +    NewRangesCo= untActual++;

> +  }

> +

> +  OldRangesIndex =3D=  0;

> +  while (OldRangesIn= dex < *EffectiveMtrrMemoryRangesCount) {

> +    CurrentRang= eTypeInOldRanges =3D OldRanges[OldRangesIndex].Type;

> +    CurrentRang= eInNewRanges =3D NULL;

> +    if (Ne= wRangesCountActual > 0)   // We need&= nbsp;to check CurrentNewRange first before generat= e a new NewRange.

> +    {
> +      = ;CurrentRangeInNewRanges =3D &NewRanges[NewRangesCountActual&= nbsp;- 1];

> +    }
> +    if (Cu= rrentRangeInNewRanges !=3D NULL && CurrentRange= InNewRanges->Type =3D=3D CurrentRangeTypeInOldRanges) {

> +      = ;CurrentRangeInNewRanges->Length +=3D OldRanges[OldRangesIndex= ].Length;

> +    } else=  {

> +      = ;NewRanges[NewRangesCountActual].BaseAddress =3D OldRanges[OldRan= gesIndex].BaseAddress;

> +      = ;NewRanges[NewRangesCountActual].Length     +=3D&n= bsp;OldRanges[OldRangesIndex].Length;

> +      = ;NewRanges[NewRangesCountActual].Type      &n= bsp; =3D CurrentRangeTypeInOldRanges;

> +      = ;while (OldRangesIndex + 1 < *EffectiveMtrrMemo= ryRangesCount && OldRanges[OldRangesIndex + 1].= Type =3D=3D
> CurrentRangeTypeInOldRanges)<= br>
> +      = ;{

> +      = ;  OldRangesIndex++;

> +      = ;  NewRanges[NewRangesCountActual].Length +=3D OldRange= s[OldRangesIndex].Length;

> +      = ;}

> +      = ;NewRangesCountActual++;

> +    }
> +

> +    OldRangesIn= dex++;

> +  }

> +

> +  MaxAddress =3D&nbs= p;(1ull << PhysicalAddressBits) - 1;

> +  OldLastRange =3D&n= bsp;OldRanges[(*EffectiveMtrrMemoryRangesCount) - 1];

> +  CurrentRangeInNewRanges=  =3D &NewRanges[NewRangesCountActual - 1];
> +  if (OldLastRange.B= aseAddress + OldLastRange.Length - 1 < Max= Address) {

> +    if (Cu= rrentRangeInNewRanges->Type =3D=3D DefaultType) {<= br>
> +      = ;CurrentRangeInNewRanges->Length =3D MaxAddress - Cu= rrentRangeInNewRanges->BaseAddress + 1;

> +    } else=  {

> +      = ;NewRanges[NewRangesCountActual].BaseAddress =3D OldLastRange.Bas= eAddress + OldLastRange.Length;

> +      = ;NewRanges[NewRangesCountActual].Length =3D MaxAddress -&nbs= p;NewRanges[NewRangesCountActual].BaseAddress + 1;

> +      = ;NewRanges[NewRangesCountActual].Type =3D DefaultType;

> +      = ;NewRangesCountActual++;

> +    }
> +  }

> +

> +  free (*EffectiveMt= rrMemoryRanges);

> +  *EffectiveMtrrMemoryRan= ges =3D NewRanges;

> +  *EffectiveMtrrMemoryRan= gesCount =3D NewRangesCountActual;

> +}

> +

> +/**

> +  Collect all t= he endpoints in the raw memory ranges.=

> +

> +  @param Endpoints&n= bsp;          Return = ;the collected endpoints.

> +  @param EndPointCou= nt       Return the count = ;of endpoints.

> +  @param RawMemoryRa= nges     Raw memory ranges.

> +  @param RawMemoryRa= ngeCount Count of raw memory ranges.

> +**/

> +VOID

> +CollectEndpoints (

> +  IN OUT UINT64=         *Endpoints,

> +  IN OUT UINT32=         *EndPointCount,

> +  IN MTRR_MEMORY_RAN= GE *RawMemoryRanges,

> +  IN UINT32 &nb= sp;          RawMemoryRan= geCount

> +  )

> +{

> +  UINT32 Index;

> +  UINT32 RawRangeInd= ex;

> +

> +  ASSERT ((RawMemory= RangeCount << 1) =3D=3D *EndPointCount);
> +

> +  for (Index = =3D 0; Index < *EndPointCount; Index +=3D&= nbsp;2) {

> +    RawRangeInd= ex =3D Index >> 1;

> +    Endpoints[I= ndex] =3D RawMemoryRanges[RawRangeIndex].BaseAddress;

> +    Endpoints[I= ndex + 1] =3D RawMemoryRanges[RawRangeIndex].BaseAddres= s + RawMemoryRanges[RawRangeIndex].Length
> - 1;

> +  }

> +

> +  qsort (Endpoints,&= nbsp;*EndPointCount, sizeof (UINT64), CompareFuncUint64);

> +  RemoveDuplicatesInSorte= dArray (Endpoints, EndPointCount);

> +}

> +

> +/**

> +  Convert the M= TRR BASE/MASK array to memory ranges.

> +

> +  @param DefaultType=           Default me= mory type.

> +  @param PhysicalAdd= ressBits  Physical address bits.

> +  @param RawMemoryRa= nges      Raw memory ranges.=

> +  @param RawMemoryRa= ngeCount  Count of raw memory ranges.<= br>
> +  @param MemoryRange= s         Memory ranges.<= /span>

> +  @param MemoryRange= Count     Count of memory ranges.

> +**/

> +VOID

> +GetEffectiveMemoryRanges (

> +  IN MTRR_MEMORY_CAC= HE_TYPE DefaultType,

> +  IN UINT32 &nb= sp;            =    PhysicalAddressBits,

> +  IN MTRR_MEMORY_RAN= GE      *RawMemoryRanges,

> +  IN UINT32 &nb= sp;            =    RawMemoryRangeCount,

> +  OUT MTRR_MEMORY_RA= NGE     *MemoryRanges,

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

> +  )

> +{

> +  UINTN   =             &nb= sp; Index;

> +  UINT32   = ;            &n= bsp;AllEndPointsCount;

> +  UINT64   = ;            &n= bsp;*AllEndPointsInclusive;

> +  UINT32   = ;            &n= bsp;AllRangePiecesCountMax;

> +  MTRR_MEMORY_RANGE =     *AllRangePieces;

> +  UINTN   =             &nb= sp; AllRangePiecesCountActual;

> +  UINT64   = ;            &n= bsp;OverlapBitFlag1;

> +  UINT64   = ;            &n= bsp;OverlapBitFlag2;

> +  INT32   =             &nb= sp; OverlapFlagRelation;

> +

> +  if (RawMemoryRange= Count =3D=3D 0) {

> +    MemoryRange= s[0].BaseAddress =3D 0;

> +    MemoryRange= s[0].Length      =3D (1ull <<=  PhysicalAddressBits);

> +    MemoryRange= s[0].Type        =3D DefaultTy= pe;

> +    *MemoryRang= eCount =3D 1;

> +    return;

> +  }

> +

> +  AllEndPointsCount =         =3D RawMemoryRangeCoun= t << 1;

> +  AllEndPointsInclusive&n= bsp;    =3D calloc (AllEndPointsCount, s= izeof (UINT64));

> +  AllRangePiecesCountMax&= nbsp;   =3D RawMemoryRangeCount * 3 +&nb= sp;1;

> +  AllRangePieces &nb= sp;          =3D cal= loc (AllRangePiecesCountMax, sizeof (MTRR_MEMORY_RANGE));

> +  CollectEndpoints (= AllEndPointsInclusive, &AllEndPointsCount, RawMemoryRanges,&n= bsp;RawMemoryRangeCount);

> +

> +  for (Index = =3D 0, AllRangePiecesCountActual =3D 0; Index = ;< AllEndPointsCount - 1; Index++) {

> +    OverlapBitF= lag1 =3D GetOverlapBitFlag (RawMemoryRanges, RawMemoryR= angeCount, AllEndPointsInclusive[Index]);

> +    OverlapBitF= lag2 =3D GetOverlapBitFlag (RawMemoryRanges, RawMemoryR= angeCount, AllEndPointsInclusive[Index + 1]);

> +    OverlapFlag= Relation =3D CheckOverlapBitFlagsRelation (OverlapBitFlag1,&= nbsp;OverlapBitFlag2);

> +    switch = ;(OverlapFlagRelation) {

> +      = ;case 0:   // [1, 2]

> +      = ;  AllRangePieces[AllRangePiecesCountActual].BaseAddress =3D=  AllEndPointsInclusive[Index];

> +      = ;  AllRangePieces[AllRangePiecesCountActual].Length  &n= bsp;   =3D AllEndPointsInclusive[Index + 1]&n= bsp;-
> AllEndPointsInclusive[Index] +&= nbsp;1;

> +      = ;  AllRangePiecesCountActual++;

> +      = ;  break;

> +      = ;case 1:   // [1, 2)

> +      = ;  AllRangePieces[AllRangePiecesCountActual].BaseAddress =3D=  AllEndPointsInclusive[Index];

> +      = ;  AllRangePieces[AllRangePiecesCountActual].Length  &n= bsp;   =3D (AllEndPointsInclusive[Index + 1]&= nbsp;- 1) -
> AllEndPointsInclusive[Index] +&= nbsp;1;

> +      = ;  AllRangePiecesCountActual++;

> +      = ;  break;

> +      = ;case 2:   // (1, 2]

> +      = ;  AllRangePieces[AllRangePiecesCountActual].BaseAddress =3D=  AllEndPointsInclusive[Index] + 1;

> +      = ;  AllRangePieces[AllRangePiecesCountActual].Length  &n= bsp;   =3D AllEndPointsInclusive[Index + 1]&n= bsp;-
> (AllEndPointsInclusive[Index] +=  1) + 1;

> +      = ;  AllRangePiecesCountActual++;

> +

> +      = ;  if (!IsEndpointInRanges (AllEndPointsInclusive[Index= ], AllRangePieces, AllRangePiecesCountActual)) {

> +      = ;    AllRangePieces[AllRangePiecesCountActual].BaseAddr= ess =3D AllEndPointsInclusive[Index];

> +      = ;    AllRangePieces[AllRangePiecesCountActual].Length&n= bsp;     =3D 1;

> +      = ;    AllRangePiecesCountActual++;

> +      = ;  }

> +      = ;  break;

> +      = ;case 3:   // (1, 2)

> +      = ;  AllRangePieces[AllRangePiecesCountActual].BaseAddress =3D=  AllEndPointsInclusive[Index] + 1;

> +      = ;  AllRangePieces[AllRangePiecesCountActual].Length  &n= bsp;   =3D (AllEndPointsInclusive[Index + 1]&= nbsp;- 1) -
> (AllEndPointsInclusive[Index] +=  1) + 1;

> +      = ;  if (AllRangePieces[AllRangePiecesCountActual].Length = ;=3D=3D 0)   // Only in case 3 = ;can exists Length=3D0, we should skip
> such "segment".

> +      = ;    break;

> +      = ;  AllRangePiecesCountActual++;

> +      = ;  if (!IsEndpointInRanges (AllEndPointsInclusive[Index= ], AllRangePieces, AllRangePiecesCountActual)) {

> +      = ;    AllRangePieces[AllRangePiecesCountActual].BaseAddr= ess =3D AllEndPointsInclusive[Index];

> +      = ;    AllRangePieces[AllRangePiecesCountActual].Length&n= bsp;     =3D 1;

> +      = ;    AllRangePiecesCountActual++;

> +      = ;  }

> +      = ;  break;

> +      = ;default:

> +      = ;  ASSERT (FALSE);

> +    }
> +  }

> +

> +  for (Index = =3D 0; Index < AllRangePiecesCountActual; Index= ++) {

> +    DetermineMe= moryCacheType (DefaultType, &AllRangePieces[Index], RawM= emoryRanges, RawMemoryRangeCount);

> +  }

> +

> +  CompactAndExtendEffecti= veMtrrMemoryRanges (DefaultType, PhysicalAddressBits, &A= llRangePieces,
> &AllRangePiecesCountActual);

> +  ASSERT (*MemoryRan= geCount >=3D AllRangePiecesCountActual);

> +  memcpy (MemoryRang= es, AllRangePieces, AllRangePiecesCountActual * sizeof&= nbsp;(MTRR_MEMORY_RANGE));

> +  *MemoryRangeCount = =3D AllRangePiecesCountActual;

> +

> +  free (AllEndPoints= Inclusive);

> +  free (AllRangePiec= es);

> +}

> diff --git a/UefiCpuPkg/Te= st/UefiCpuPkgHostTest.dsc b/UefiCpuPkg/Test/UefiCpuPkgHostTest.dsc
> new file mode 100644<= /span>
> index 0000000000..8a5c456830
> --- /dev/null
> +++ b/UefiCpuPkg/Test/UefiCpuPk= gHostTest.dsc
> @@ -0,0 +1,31 @@
> +## @file

> +# UefiCpuPkg DSC fil= e used to build host-based unit tests.=

> +#

> +# Copyright (c) 2020= , Intel Corporation. All rights reserved.<BR>= ;

> +# SPDX-License-Identifier:&nbs= p;BSD-2-Clause-Patent

> +#

> +##

> +

> +[Defines]

> +  PLATFORM_NAME &nbs= p;         =3D UefiCpuPkg= HostTest

> +  PLATFORM_GUID &nbs= p;         =3D E00B9599-5= B74-4FF7-AB9F-8183FB13B2F9

> +  PLATFORM_VERSION &= nbsp;      =3D 0.1

> +  DSC_SPECIFICATION =       =3D 0x00010005

> +  OUTPUT_DIRECTORY &= nbsp;      =3D Build/UefiCpuPkg/HostTest=

> +  SUPPORTED_ARCHITECTURES=  =3D IA32|X64

> +  BUILD_TARGETS &nbs= p;         =3D NOOPT

> +  SKUID_IDENTIFIER &= nbsp;      =3D DEFAULT

> +

> +!include UnitTestFrameworkPkg/= UnitTestFrameworkPkgHost.dsc.inc

> +

> +[LibraryClasses]

> +  MtrrLib|UefiCpuPkg/Libr= ary/MtrrLib/MtrrLib.inf

> +

> +[PcdsPatchableInModule]

> +  gUefiCpuPkgTokenSpaceGu= id.PcdCpuNumberOfReservedVariableMtrrs|0

> +

> +[Components]

> +  #

> +  # Build HOST_= APPLICATION that tests the MtrrLib

> +  #

> +  UefiCpuPkg/Library/Mtrr= Lib/UnitTest/MtrrLibUnitTestHost.inf

> diff --git a/UefiCpuPkg/Ue= fiCpuPkg.ci.yaml b/UefiCpuPkg/UefiCpuPkg.ci.yaml
> index 99e460a8b0..4559b40105&nb= sp;100644
> --- a/UefiCpuPkg/UefiCpuPkg.ci.= yaml
> +++ b/UefiCpuPkg/UefiCpuPkg.ci.= yaml
> @@ -8,6 +8,10 @@
>      "= CompilerPlugin": {

>       =    "DscPath": "UefiCpuPkg.dsc"

>      },

> +    ## opt= ions defined ci/Plugin/HostUnitTestCompilerPlugin

> +    "HostU= nitTestCompilerPlugin": {

> +      = ;  "DscPath": "Test/UefiCpuPkgHostTest.dsc&qu= ot;

> +    },
>      "= CharEncodingCheck": {

>       =    "IgnoreFiles": []

>      },

> @@ -18,7 +22,9 @@
>       =        "UefiCpuPkg/UefiCpuPkg.dec&q= uot;

>       =    ],

>       =    # For host based unit tests

> -      = ;  "AcceptableDependencies-HOST_APPLICATION":[],=

> +      = ;  "AcceptableDependencies-HOST_APPLICATION":[
> +      = ;      "UnitTestFrameworkPkg/UnitTestFra= meworkPkg.dec"

> +      = ;  ],

>       =    # For UEFI shell based apps

>       =    "AcceptableDependencies-UEFI_APPLICATION":[],

>       =    "IgnoreInf": []

> @@ -30,6 +36,10 @@
>       =        "UefiCpuPkg/ResetVector/Vtf0= /Vtf0.inf"

>       =    ]

>      },

> +    "HostU= nitTestDscCompleteCheck": {

> +      = ;  "IgnoreInf": [""],

> +      = ;  "DscPath": "Test/UefiCpuPkgHostTest.dsc&qu= ot;

> +    },
>      "= GuidCheck": {

>       =    "IgnoreGuidName": ["SecCore",&nb= sp;"ResetVector"], # Expected duplication for=  gEfiFirmwareVolumeTopFileGuid

>       =    "IgnoreGuidValue": [],

> --
> 2.27.0.windows.1


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

> View/Reply Online (#63380)= : https://edk2.groups.io/g/devel/message/63380
> Mute This Topic: http= s://groups.io/mt/75837117/1712937
> Group Owner: devel+owner@e= dk2.groups.io
> Unsubscribe: https://edk2.group= s.io/g/devel/unsub  [ray.ni@intel.com]
> -=3D-=3D-=3D-=3D-=3D-=3D=

--_000_DM6PR11MB327419476918AE28D7FAAE99FE730DM6PR11MB3274namp_--