From nobody Sun Feb 8 23:05:21 2026 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of groups.io designates 66.175.222.12 as permitted sender) client-ip=66.175.222.12; envelope-from=bounce+27952+60540+1787277+3901457@groups.io; helo=web01.groups.io; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of groups.io designates 66.175.222.12 as permitted sender) smtp.mailfrom=bounce+27952+60540+1787277+3901457@groups.io ARC-Seal: i=1; a=rsa-sha256; t=1591031812; cv=none; d=zohomail.com; s=zohoarc; b=bg4rMgHlQ6nrnRwaGzr01R82S7NUPuFzobaQ2J/OjHL3b/6qjibpFnYFpTPbkMtngF/J9sHm7ajf4Hmpq2GQyP8P6EwgmItGuXijyabcPS8akR8Nr1VM7xP1Y6iiGVW0joZXgqIqoULWUwEDFwU36hevuTQQeYJuSYUqq0H0Jto= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1591031812; h=Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:List-Id:List-Unsubscribe:MIME-Version:Message-ID:Reply-To:References:Sender:Subject:To; bh=cSSwGdEaOrekYHVdTUQOvvQo/Ya6ckdiS4F9DMvFM2c=; b=QTkZLZe56e14nnGaRXN61x4nFhmrdt4wPLaXWbsVxtz6nQlCEp/m34m8Ki/Qml5IQsFcJ2rU+LUHkvj3wXkKQ8ZONzftclHjWmDJBMvqOqhZIeH4bR/7TewNzM8MjI2ibiqgQpUYW9Ghy93THj07YVYSbgGPsCzgZO7Y7MZ9DFc= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of groups.io designates 66.175.222.12 as permitted sender) smtp.mailfrom=bounce+27952+60540+1787277+3901457@groups.io Received: from web01.groups.io (web01.groups.io [66.175.222.12]) by mx.zohomail.com with SMTPS id 1591031812383312.24722736244235; Mon, 1 Jun 2020 10:16:52 -0700 (PDT) Return-Path: X-Received: by 127.0.0.2 with SMTP id 8IIfYY1788612xcIxmm9NkTh; Mon, 01 Jun 2020 10:16:52 -0700 X-Received: from mail-pj1-f66.google.com (mail-pj1-f66.google.com [209.85.216.66]) by mx.groups.io with SMTP id smtpd.web12.41419.1591029219612133239 for ; Mon, 01 Jun 2020 09:33:39 -0700 X-Received: by mail-pj1-f66.google.com with SMTP id i12so53390pju.3 for ; Mon, 01 Jun 2020 09:33:39 -0700 (PDT) X-Gm-Message-State: hftST5Acea9ztdrD8gsirfXex1787277AA= X-Google-Smtp-Source: ABdhPJyut3BJEpgLr6frZingBeoonD2Rg+Qa09vsZlkYVBz4VFaND8Ru27ANX/r+5x/ep35C+b2ckQ== X-Received: by 2002:a17:90a:1b6c:: with SMTP id q99mr240873pjq.214.1591029218412; Mon, 01 Jun 2020 09:33:38 -0700 (PDT) X-Received: from localhost.localdomain ([71.212.144.72]) by smtp.gmail.com with ESMTPSA id np5sm91178pjb.43.2020.06.01.09.33.37 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 01 Jun 2020 09:33:37 -0700 (PDT) From: Bret Barkelew X-Google-Original-From: Bret Barkelew To: devel@edk2.groups.io Cc: Jian J Wang , Hao A Wu , Liming Gao Subject: [edk2-devel] [PATCH v4 14/14] MdeModulePkg: Add a shell-based functional test for VariablePolicy Date: Mon, 1 Jun 2020 09:33:10 -0700 Message-Id: <20200601163310.1718-15-brbarkel@microsoft.com> In-Reply-To: <20200601163310.1718-1-brbarkel@microsoft.com> References: <20200601163310.1718-1-brbarkel@microsoft.com> MIME-Version: 1.0 Precedence: Bulk List-Unsubscribe: Sender: devel@edk2.groups.io List-Id: Mailing-List: list devel@edk2.groups.io; contact devel+owner@edk2.groups.io Reply-To: devel@edk2.groups.io,bret@corthon.com Content-Transfer-Encoding: quoted-printable DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=groups.io; q=dns/txt; s=20140610; t=1591031812; bh=+A811TwZju9RFkrma7rmsyQOu2OaKBzOeKadDfMvJdk=; h=Cc:Date:From:Reply-To:Subject:To; b=OkAD4yUGrAk92mmEdwat+mj2UYI36dwy3WfumeL7WTLnoFWMYlTc/5IDKfJgHAOjUr3 MuTuJbfAcjsvzTvmYPIJVr7chPSSasaz8aSn2XDem1tx8qGGWI+tGuhkK71fG/X0OJHxJ ZrDw4eRJqUJjGgCDWpcjK3LCaHmhcI6pj2E= X-ZohoMail-DKIM: pass (identity @groups.io) Content-Type: text/plain; charset="utf-8" https://bugzilla.tianocore.org/show_bug.cgi?id=3D2522 To verify that VariablePolicy is correctly integrated on platforms, add a Shell-based functional test to confirm expected behavior. NOTE: This test assumes that VariablePolicy is built with PcdAllowVariablePolicyEnforcementDisable set to TRUE. Cc: Jian J Wang Cc: Hao A Wu Cc: Liming Gao Cc: Bret Barkelew Signed-off-by: Bret Barkelew --- MdeModulePkg/Test/ShellTest/VariablePolicyFuncTestApp/VariablePolicyFuncTe= stApp.c | 1950 ++++++++++++++++++++ MdeModulePkg/MdeModulePkg.ci.yaml = | 4 +- MdeModulePkg/MdeModulePkg.dsc = | 6 + MdeModulePkg/Test/ShellTest/VariablePolicyFuncTestApp/Readme.md = | 55 + MdeModulePkg/Test/ShellTest/VariablePolicyFuncTestApp/VariablePolicyFuncTe= stApp.inf | 42 + 5 files changed, 2056 insertions(+), 1 deletion(-) diff --git a/MdeModulePkg/Test/ShellTest/VariablePolicyFuncTestApp/Variable= PolicyFuncTestApp.c b/MdeModulePkg/Test/ShellTest/VariablePolicyFuncTestApp= /VariablePolicyFuncTestApp.c new file mode 100644 index 000000000000..cbf96f159240 --- /dev/null +++ b/MdeModulePkg/Test/ShellTest/VariablePolicyFuncTestApp/VariablePolicyF= uncTestApp.c @@ -0,0 +1,1950 @@ +/** @file +UEFI Shell based application for unit testing the Variable Policy Protocol. + +Copyright (c) Microsoft Corporation. +SPDX-License-Identifier: BSD-2-Clause-Patent +**/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// TODO: Need to add to the UnitTestFrameworkPkg +// #include + +#define UNIT_TEST_APP_NAME "Variable Policy Unit Test Application" +#define UNIT_TEST_APP_VERSION "0.1" + +// TODO: Need to add to the UnitTestFrameworkPkg +UNIT_TEST_FRAMEWORK_HANDLE +GetActiveFrameworkHandle ( + VOID + ); + +EDKII_VARIABLE_POLICY_PROTOCOL *mVarPol =3D NULL; + + +EFI_GUID mTestNamespaceGuid1 =3D { 0x3b389299, 0xabaf, 0x433b, { 0xa4, 0xa= 9, 0x23, 0xc8, 0x44, 0x02, 0xfc, 0xad } }; +EFI_GUID mTestNamespaceGuid2 =3D { 0x4c49a3aa, 0xbcb0, 0x544c, { 0xb5, 0xb= a, 0x34, 0xd9, 0x55, 0x13, 0x0d, 0xbe } }; +EFI_GUID mTestNamespaceGuid3 =3D { 0x5d5ab4bb, 0xcdc1, 0x655d, { 0xc6, 0xc= b, 0x45, 0xea, 0x66, 0x24, 0x1e, 0xcf } }; + +/** + Prerequisite for most test cases. +**/ +UNIT_TEST_STATUS +EFIAPI +LocateVarPolicyPreReq ( + IN UNIT_TEST_CONTEXT Context + ) +{ + EFI_STATUS Status; + + if (mVarPol =3D=3D NULL) { + Status =3D gBS->LocateProtocol (&gEdkiiVariablePolicyProtocolGuid, + NULL, + (VOID **) &mVarPol); + UT_ASSERT_NOT_EFI_ERROR (Status); + UT_ASSERT_NOT_NULL (mVarPol); + } + + return UNIT_TEST_PASSED; + +} // LocateVarPolicyPreReq + +/** + Getting Started tests. +**/ +UNIT_TEST_STATUS +CheckVpEnabled ( + IN UNIT_TEST_CONTEXT Context + ) +{ + EFI_STATUS Status; + BOOLEAN State; + + Status =3D mVarPol->IsVariablePolicyEnabled (&State); + + UT_ASSERT_NOT_EFI_ERROR (Status); + UT_ASSERT_EQUAL (State, TRUE); + + return UNIT_TEST_PASSED; +} // CheckVpEnabled + +UNIT_TEST_STATUS +CheckVpRevision ( + IN UNIT_TEST_CONTEXT Context + ) +{ + UT_ASSERT_NOT_EQUAL (mVarPol->Revision, 0); + UT_LOG_INFO ("VP Revision: 0x%x\n", mVarPol->Revision); + + return UNIT_TEST_PASSED; +} // CheckVpRevision + +/** + NoLock Policy tests. +**/ +UNIT_TEST_STATUS +TestMinSizeNoLock ( + IN UNIT_TEST_CONTEXT Context + ) +{ + EFI_STATUS Status; + UINT8 Value1; + UINT32 Value2; + UINT8 *Buffer; + + Status =3D RegisterBasicVariablePolicy (mVarPol, + &mTestNamespaceGuid1, + L"MinSizeNoLockVar", + 4, + VARIABLE_POLICY_NO_MAX_SIZE, + VARIABLE_POLICY_NO_MUST_ATTR, + VARIABLE_POLICY_NO_CANT_ATTR, + VARIABLE_POLICY_TYPE_NO_LOCK); + UT_ASSERT_NOT_EFI_ERROR (Status); + + // + // Try to write a var that is smaller than minsize + // + Value1 =3D 0x12; + Status =3D gRT->SetVariable (L"MinSizeNoLockVar", + &mTestNamespaceGuid1, + (EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BO= OTSERVICE_ACCESS), + sizeof (Value1), + &Value1); + UT_ASSERT_TRUE ((Status =3D=3D EFI_WRITE_PROTECTED) || (Status =3D=3D EF= I_INVALID_PARAMETER)); + + // + // Try to write a var of size that matches minsize + // + Value2 =3D 0xa1b2c3d4; + Status =3D gRT->SetVariable (L"MinSizeNoLockVar", + &mTestNamespaceGuid1, + (EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BO= OTSERVICE_ACCESS), + sizeof (Value2), + &Value2); + UT_ASSERT_NOT_EFI_ERROR (Status); + + // + // Should be able to delete the var + // + Status =3D gRT->SetVariable (L"MinSizeNoLockVar", + &mTestNamespaceGuid1, + 0, + 0, + NULL); + UT_ASSERT_NOT_EFI_ERROR (Status); + + // + // Try to write a var of size larger than minsize + // + Buffer =3D AllocateZeroPool (40); + UT_ASSERT_NOT_NULL (Buffer); + Status =3D gRT->SetVariable (L"MinSizeNoLockVar", + &mTestNamespaceGuid1, + (EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BO= OTSERVICE_ACCESS), + 40, + Buffer); + UT_ASSERT_NOT_EFI_ERROR (Status); + + // + // Delete the variable + // + Status =3D gRT->SetVariable (L"MinSizeNoLockVar", + &mTestNamespaceGuid1, + 0, + 0, + NULL); + UT_ASSERT_NOT_EFI_ERROR (Status); + + FreePool (Buffer); + + return UNIT_TEST_PASSED; +} // TestMinSizeNoLock + +UNIT_TEST_STATUS +TestMaxSizeNoLock ( + IN UNIT_TEST_CONTEXT Context + ) +{ + EFI_STATUS Status; + UINT8 Value1; + UINT32 Value2; + UINT8 *Buffer; + + Status =3D RegisterBasicVariablePolicy (mVarPol, + &mTestNamespaceGuid1, + L"MaxSizeNoLockVar", + VARIABLE_POLICY_NO_MIN_SIZE, + 4, + VARIABLE_POLICY_NO_MUST_ATTR, + VARIABLE_POLICY_NO_CANT_ATTR, + VARIABLE_POLICY_TYPE_NO_LOCK); + UT_ASSERT_NOT_EFI_ERROR (Status); + + // + // Try to write a var that is smaller than maxsize + // + Value1 =3D 0x34; + Status =3D gRT->SetVariable (L"MaxSizeNoLockVar", + &mTestNamespaceGuid1, + (EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BO= OTSERVICE_ACCESS), + sizeof (Value1), + &Value1); + UT_ASSERT_NOT_EFI_ERROR (Status); + + // + // Should be able to delete the var + // + Status =3D gRT->SetVariable (L"MaxSizeNoLockVar", + &mTestNamespaceGuid1, + 0, + 0, + NULL); + UT_ASSERT_NOT_EFI_ERROR (Status); + + // + // Try to write a var of size that matches maxsize + // + Value2 =3D 0xa1b2c3d4; + Status =3D gRT->SetVariable (L"MaxSizeNoLockVar", + &mTestNamespaceGuid1, + (EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BO= OTSERVICE_ACCESS), + sizeof (Value2), + &Value2); + UT_ASSERT_NOT_EFI_ERROR (Status); + + // + // Should be able to delete the var + // + Status =3D gRT->SetVariable (L"MaxSizeNoLockVar", + &mTestNamespaceGuid1, + 0, + 0, + NULL); + UT_ASSERT_NOT_EFI_ERROR (Status); + + // + // Try to write a var of size larger than maxsize + // + Buffer =3D AllocateZeroPool (40); + UT_ASSERT_NOT_NULL (Buffer); + Status =3D gRT->SetVariable (L"MaxSizeNoLockVar", + &mTestNamespaceGuid1, + (EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BO= OTSERVICE_ACCESS), + 40, + Buffer); + UT_ASSERT_TRUE ((Status =3D=3D EFI_WRITE_PROTECTED) || (Status =3D=3D EF= I_INVALID_PARAMETER)); + + FreePool (Buffer); + + return UNIT_TEST_PASSED; +} // TestMaxSizeNoLock + +UNIT_TEST_STATUS +TestMustHaveAttrNoLock ( + IN UNIT_TEST_CONTEXT Context + ) +{ + EFI_STATUS Status; + UINT8 Value; + + Status =3D RegisterBasicVariablePolicy (mVarPol, + &mTestNamespaceGuid1, + L"MustHaveAttrNoLockVar", + VARIABLE_POLICY_NO_MIN_SIZE, + VARIABLE_POLICY_NO_MAX_SIZE, + (EFI_VARIABLE_NON_VOLATILE | EFI_= VARIABLE_BOOTSERVICE_ACCESS), + VARIABLE_POLICY_NO_CANT_ATTR, + VARIABLE_POLICY_TYPE_NO_LOCK); + UT_ASSERT_NOT_EFI_ERROR (Status); + + // + // Try to write a var that doesn't have the must-have attributes + // + Value =3D 0x56; + Status =3D gRT->SetVariable (L"MustHaveAttrNoLockVar", + &mTestNamespaceGuid1, + EFI_VARIABLE_BOOTSERVICE_ACCESS, + sizeof (Value), + &Value); + UT_ASSERT_TRUE ((Status =3D=3D EFI_WRITE_PROTECTED) || (Status =3D=3D EF= I_INVALID_PARAMETER)); + + // + // Try to write a var that has exactly the required attributes + // + Status =3D gRT->SetVariable (L"MustHaveAttrNoLockVar", + &mTestNamespaceGuid1, + (EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BO= OTSERVICE_ACCESS), + sizeof (Value), + &Value); + UT_ASSERT_NOT_EFI_ERROR (Status); + + // + // Should be able to delete the var + // NOTE: some implementations of VP will require the musthave attributes= to be passed even when deleting + // + Status =3D gRT->SetVariable (L"MustHaveAttrNoLockVar", + &mTestNamespaceGuid1, + 0, + 0, + NULL); + UT_ASSERT_NOT_EFI_ERROR (Status); + + // + // Try to write a var that has the required attributes and one extra att= ribute + // + Status =3D gRT->SetVariable (L"MustHaveAttrNoLockVar", + &mTestNamespaceGuid1, + (EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BO= OTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS), + sizeof (Value), + &Value); + UT_ASSERT_NOT_EFI_ERROR (Status); + + // + // Should be able to delete the var + // NOTE: some implementations of VP will require the musthave attributes= to be passed even when deleting + // + Status =3D gRT->SetVariable (L"MustHaveAttrNoLockVar", + &mTestNamespaceGuid1, + 0, + 0, + NULL); + UT_ASSERT_NOT_EFI_ERROR (Status); + return UNIT_TEST_PASSED; +} // TestMustHaveAttrNoLock + +UNIT_TEST_STATUS +TestCantHaveAttrNoLock ( + IN UNIT_TEST_CONTEXT Context + ) +{ + EFI_STATUS Status; + UINT8 Value; + + Status =3D RegisterBasicVariablePolicy (mVarPol, + &mTestNamespaceGuid1, + L"CantHaveAttrNoLockVar", + VARIABLE_POLICY_NO_MIN_SIZE, + VARIABLE_POLICY_NO_MAX_SIZE, + VARIABLE_POLICY_NO_MUST_ATTR, + EFI_VARIABLE_NON_VOLATILE, + VARIABLE_POLICY_TYPE_NO_LOCK); + UT_ASSERT_NOT_EFI_ERROR (Status); + + // + // Try to write a var that has a can't have attr + // + Value =3D 0x78; + Status =3D gRT->SetVariable (L"CantHaveAttrNoLockVar", + &mTestNamespaceGuid1, + (EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIAB= LE_NON_VOLATILE), + sizeof (Value), + &Value); + UT_ASSERT_TRUE ((Status =3D=3D EFI_WRITE_PROTECTED) || (Status =3D=3D EF= I_INVALID_PARAMETER)); + + // + // Try to write a var that satisfies the can't have requirement + // + Status =3D gRT->SetVariable (L"CantHaveAttrNoLockVar", + &mTestNamespaceGuid1, + EFI_VARIABLE_BOOTSERVICE_ACCESS, + sizeof (Value), + &Value); + UT_ASSERT_NOT_EFI_ERROR (Status); + + // + // Should be able to delete the var + // + Status =3D gRT->SetVariable (L"CantHaveAttrNoLockVar", + &mTestNamespaceGuid1, + 0, + 0, + NULL); + UT_ASSERT_NOT_EFI_ERROR (Status); + + return UNIT_TEST_PASSED; +} // TestCantHaveAttrNoLock + +UNIT_TEST_STATUS +TestMaxSizeNamespaceNoLock ( + IN UNIT_TEST_CONTEXT Context + ) +{ + EFI_STATUS Status; + UINT8 Value1; + UINT32 Value2; + UINT8 *Buffer; + + // + // Register a namespace-wide policy limiting max size to 4 bytes + // + Status =3D RegisterBasicVariablePolicy (mVarPol, + &mTestNamespaceGuid2, + NULL, + VARIABLE_POLICY_NO_MIN_SIZE, + 4, + VARIABLE_POLICY_NO_MUST_ATTR, + VARIABLE_POLICY_NO_CANT_ATTR, + VARIABLE_POLICY_TYPE_NO_LOCK); + UT_ASSERT_NOT_EFI_ERROR (Status); + + // + // Try to write a var that is smaller than maxsize + // + Value1 =3D 0x34; + Status =3D gRT->SetVariable (L"MaxSizeNoLockVar", + &mTestNamespaceGuid2, + (EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BO= OTSERVICE_ACCESS), + sizeof (Value1), + &Value1); + UT_ASSERT_NOT_EFI_ERROR (Status); + + // + // Should be able to delete the var + // + Status =3D gRT->SetVariable (L"MaxSizeNoLockVar", + &mTestNamespaceGuid2, + 0, + 0, + NULL); + UT_ASSERT_NOT_EFI_ERROR (Status); + + // + // Try to write a var of size that matches maxsize + // + Value2 =3D 0xa1b2c3d4; + Status =3D gRT->SetVariable (L"MaxSizeNoLockVar", + &mTestNamespaceGuid2, + (EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BO= OTSERVICE_ACCESS), + sizeof (Value2), + &Value2); + UT_ASSERT_NOT_EFI_ERROR (Status); + + // + // Should be able to delete the var + // + Status =3D gRT->SetVariable (L"MaxSizeNoLockVar", + &mTestNamespaceGuid2, + 0, + 0, + NULL); + UT_ASSERT_NOT_EFI_ERROR (Status); + + // + // Try to write a var of size larger than maxsize + // + Buffer =3D AllocateZeroPool (40); + UT_ASSERT_NOT_NULL (Buffer); + Status =3D gRT->SetVariable (L"MaxSizeNoLockVar", + &mTestNamespaceGuid2, + (EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BO= OTSERVICE_ACCESS), + 40, + Buffer); + UT_ASSERT_TRUE ((Status =3D=3D EFI_WRITE_PROTECTED) || (Status =3D=3D EF= I_INVALID_PARAMETER)); + + FreePool (Buffer); + + return UNIT_TEST_PASSED; +} // TestMaxSizeNamespaceNoLock + +UNIT_TEST_STATUS +TestMustHaveAttrWildcardNoLock ( + IN UNIT_TEST_CONTEXT Context + ) +{ + EFI_STATUS Status; + UINT8 Value; + + Status =3D RegisterBasicVariablePolicy (mVarPol, + &mTestNamespaceGuid1, + L"MustHaveAttrWildcardNoLockVar###= #", + VARIABLE_POLICY_NO_MIN_SIZE, + VARIABLE_POLICY_NO_MAX_SIZE, + (EFI_VARIABLE_NON_VOLATILE | EFI_= VARIABLE_BOOTSERVICE_ACCESS), + VARIABLE_POLICY_NO_CANT_ATTR, + VARIABLE_POLICY_TYPE_NO_LOCK); + UT_ASSERT_NOT_EFI_ERROR (Status); + + // + // Try to write a var that doesn't have the must-have attributes + // + Value =3D 0x56; + Status =3D gRT->SetVariable (L"MustHaveAttrWildcardNoLockVar1573", + &mTestNamespaceGuid1, + EFI_VARIABLE_BOOTSERVICE_ACCESS, + sizeof (Value), + &Value); + UT_ASSERT_TRUE ((Status =3D=3D EFI_WRITE_PROTECTED) || (Status =3D=3D EF= I_INVALID_PARAMETER)); + + // + // Try to write a var that has exactly the required attributes + // + Status =3D gRT->SetVariable (L"MustHaveAttrWildcardNoLockVar1234", + &mTestNamespaceGuid1, + (EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BO= OTSERVICE_ACCESS), + sizeof (Value), + &Value); + UT_ASSERT_NOT_EFI_ERROR (Status); + + // + // Should be able to delete the var + // NOTE: some implementations of VP will require the musthave attributes= to be passed even when deleting + // + Status =3D gRT->SetVariable (L"MustHaveAttrWildcardNoLockVar1234", + &mTestNamespaceGuid1, + 0, + 0, + NULL); + UT_ASSERT_NOT_EFI_ERROR (Status); + + // + // Try to write a var that has the required attributes and one extra att= ribute + // + Status =3D gRT->SetVariable (L"MustHaveAttrWildcardNoLockVar5612", + &mTestNamespaceGuid1, + (EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BO= OTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS), + sizeof (Value), + &Value); + UT_ASSERT_NOT_EFI_ERROR (Status); + + // + // Should be able to delete the var + // NOTE: some implementations of VP will require the musthave attributes= to be passed even when deleting + // + Status =3D gRT->SetVariable (L"MustHaveAttrWildcardNoLockVar5612", + &mTestNamespaceGuid1, + 0, + 0, + NULL); + UT_ASSERT_NOT_EFI_ERROR (Status); + + return UNIT_TEST_PASSED; +} // TestMustHaveAttrWildcardNoLock + +UNIT_TEST_STATUS +TestPolicyprioritizationNoLock ( + IN UNIT_TEST_CONTEXT Context + ) +{ + EFI_STATUS Status; + UINT8 Value8; + UINT16 Value16; + UINT32 Value32; + UINT64 Value64; + + // + // Register a policy targeting the specific var + // + Status =3D RegisterBasicVariablePolicy (mVarPol, + &mTestNamespaceGuid3, + L"PolicyPriorityTestVar123", + 8, // min size of UINT64 + VARIABLE_POLICY_NO_MAX_SIZE, + VARIABLE_POLICY_NO_MUST_ATTR, + VARIABLE_POLICY_NO_CANT_ATTR, + VARIABLE_POLICY_TYPE_NO_LOCK); + UT_ASSERT_NOT_EFI_ERROR (Status); + + // + // Register a policy with wildcards in the name + // + Status =3D RegisterBasicVariablePolicy (mVarPol, + &mTestNamespaceGuid3, + L"PolicyPriorityTestVar###", + 4, // min size of UINT32 + VARIABLE_POLICY_NO_MAX_SIZE, + VARIABLE_POLICY_NO_MUST_ATTR, + VARIABLE_POLICY_NO_CANT_ATTR, + VARIABLE_POLICY_TYPE_NO_LOCK); + UT_ASSERT_NOT_EFI_ERROR (Status); + + // + // Register a policy with wildcards in the name + // + Status =3D RegisterBasicVariablePolicy (mVarPol, + &mTestNamespaceGuid3, + NULL, + 2, // min size of UINT16 + VARIABLE_POLICY_NO_MAX_SIZE, + VARIABLE_POLICY_NO_MUST_ATTR, + VARIABLE_POLICY_NO_CANT_ATTR, + VARIABLE_POLICY_TYPE_NO_LOCK); + UT_ASSERT_NOT_EFI_ERROR (Status); + + // + // The idea is that the most specific policy is applied: + // For varname "TestVar", the namespace-wide one should apply: UINT16 = minimum + // For varname "PolicyPriorityTestVar567" the wildcard policy should a= pply: UINT32 minimum + // For varname "PolicyPriorityTestVar123" the var-specific policy shou= ld apply: UINT64 minimum + // + + // + // Let's confirm the namespace-wide policy enforcement + // + Value8 =3D 0x78; + Status =3D gRT->SetVariable (L"TestVar", + &mTestNamespaceGuid3, + (EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIAB= LE_NON_VOLATILE), + sizeof (Value8), + &Value8); + UT_ASSERT_TRUE ((Status =3D=3D EFI_WRITE_PROTECTED) || (Status =3D=3D EF= I_INVALID_PARAMETER)); + + Value16 =3D 0x6543; + Status =3D gRT->SetVariable (L"TestVar", + &mTestNamespaceGuid3, + (EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIAB= LE_NON_VOLATILE), + sizeof (Value16), + &Value16); + UT_ASSERT_NOT_EFI_ERROR (Status); + + // + // Let's confirm the wildcard policy enforcement + // + Value16 =3D 0xabba; + Status =3D gRT->SetVariable (L"PolicyPriorityTestVar567", + &mTestNamespaceGuid3, + (EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIAB= LE_NON_VOLATILE), + sizeof (Value16), + &Value16); + UT_ASSERT_TRUE ((Status =3D=3D EFI_WRITE_PROTECTED) || (Status =3D=3D EF= I_INVALID_PARAMETER)); + + Value32 =3D 0xfedcba98; + Status =3D gRT->SetVariable (L"PolicyPriorityTestVar567", + &mTestNamespaceGuid3, + (EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIAB= LE_NON_VOLATILE), + sizeof (Value32), + &Value32); + UT_ASSERT_NOT_EFI_ERROR (Status); + + // + // Let's confirm the var-specific policy enforcement + // + Value32 =3D 0x8d3f627c; + Status =3D gRT->SetVariable (L"PolicyPriorityTestVar123", + &mTestNamespaceGuid3, + (EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIAB= LE_NON_VOLATILE), + sizeof (Value32), + &Value32); + UT_ASSERT_TRUE ((Status =3D=3D EFI_WRITE_PROTECTED) || (Status =3D=3D EF= I_INVALID_PARAMETER)); + + Value64 =3D 0xbebecdcdafaf6767; + Status =3D gRT->SetVariable (L"PolicyPriorityTestVar123", + &mTestNamespaceGuid3, + (EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIAB= LE_NON_VOLATILE), + sizeof (Value64), + &Value64); + UT_ASSERT_NOT_EFI_ERROR (Status); + + return UNIT_TEST_PASSED; +} // TestPolicyprioritizationNoLock + +/** + LockNow Policy tests. +**/ +UNIT_TEST_STATUS +TestExistingVarLockNow ( + IN UNIT_TEST_CONTEXT Context + ) +{ + EFI_STATUS Status; + UINT8 Value; + + // + // Write a var that we'll protect next + // + Value =3D 0x78; + Status =3D gRT->SetVariable (L"ExistingLockNowVar", + &mTestNamespaceGuid1, + (EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIAB= LE_NON_VOLATILE), + sizeof (Value), + &Value); + UT_ASSERT_NOT_EFI_ERROR (Status); + + // + // Register a LockNow policy targeting the var + // + Status =3D RegisterBasicVariablePolicy (mVarPol, + &mTestNamespaceGuid1, + L"ExistingLockNowVar", + VARIABLE_POLICY_NO_MIN_SIZE, + VARIABLE_POLICY_NO_MAX_SIZE, + VARIABLE_POLICY_NO_MUST_ATTR, + VARIABLE_POLICY_NO_CANT_ATTR, + VARIABLE_POLICY_TYPE_LOCK_NOW); + UT_ASSERT_NOT_EFI_ERROR (Status); + + // + // Attempt to modify the locked var + // + Value =3D 0xA5; + Status =3D gRT->SetVariable (L"ExistingLockNowVar", + &mTestNamespaceGuid1, + (EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIAB= LE_NON_VOLATILE), + sizeof (Value), + &Value); + UT_ASSERT_STATUS_EQUAL (Status, EFI_WRITE_PROTECTED); + + // + // Attempt to delete the locked var + // + Status =3D gRT->SetVariable (L"ExistingLockNowVar", + &mTestNamespaceGuid1, + 0, + 0, + NULL); + UT_ASSERT_STATUS_EQUAL (Status, EFI_WRITE_PROTECTED); + + // + // This variable is deleted in final cleanup. + // + + return UNIT_TEST_PASSED; +} // TestExistingVarLockNow + +UNIT_TEST_STATUS +TestNonexistentVarLockNow ( + IN UNIT_TEST_CONTEXT Context + ) +{ + EFI_STATUS Status; + UINT8 Value; + UINTN Size; + + // + // Make sure the variable we're about to create the policy for doesn't e= xist + // + Size =3D 0; + Status =3D gRT->GetVariable (L"NonexistentLockNowVar", + &mTestNamespaceGuid1, + NULL, + &Size, + NULL); + UT_ASSERT_STATUS_EQUAL (Status, EFI_NOT_FOUND); + + // + // Register a LockNow policy targeting the var + // + Status =3D RegisterBasicVariablePolicy (mVarPol, + &mTestNamespaceGuid1, + L"NonexistentLockNowVar", + VARIABLE_POLICY_NO_MIN_SIZE, + VARIABLE_POLICY_NO_MAX_SIZE, + VARIABLE_POLICY_NO_MUST_ATTR, + VARIABLE_POLICY_NO_CANT_ATTR, + VARIABLE_POLICY_TYPE_LOCK_NOW); + UT_ASSERT_NOT_EFI_ERROR (Status); + + // + // Attempt to create the locked var + // + Value =3D 0xA5; + Status =3D gRT->SetVariable (L"NonexistentLockNowVar", + &mTestNamespaceGuid1, + (EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIAB= LE_NON_VOLATILE), + sizeof (Value), + &Value); + UT_ASSERT_STATUS_EQUAL (Status, EFI_WRITE_PROTECTED); + + return UNIT_TEST_PASSED; +} // TestNonexistentVarLockNow + +/** + LockOnCreate Policy tests. +**/ +UNIT_TEST_STATUS +TestExistingVarLockOnCreate ( + IN UNIT_TEST_CONTEXT Context + ) +{ + EFI_STATUS Status; + UINT8 Value; + + // + // Write a var that we'll protect later + // + Value =3D 0x78; + Status =3D gRT->SetVariable (L"ExistingLockOnCreateVar", + &mTestNamespaceGuid1, + (EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIAB= LE_NON_VOLATILE), + sizeof (Value), + &Value); + UT_ASSERT_NOT_EFI_ERROR (Status); + + // + // Register a LockNow policy targeting the var + // + Status =3D RegisterBasicVariablePolicy (mVarPol, + &mTestNamespaceGuid1, + L"ExistingLockOnCreateVar", + VARIABLE_POLICY_NO_MIN_SIZE, + VARIABLE_POLICY_NO_MAX_SIZE, + VARIABLE_POLICY_NO_MUST_ATTR, + VARIABLE_POLICY_NO_CANT_ATTR, + VARIABLE_POLICY_TYPE_LOCK_ON_CREAT= E); + UT_ASSERT_NOT_EFI_ERROR (Status); + + // + // Attempt to modify the locked var + // + Value =3D 0xA5; + Status =3D gRT->SetVariable (L"ExistingLockOnCreateVar", + &mTestNamespaceGuid1, + (EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIAB= LE_NON_VOLATILE), + sizeof (Value), + &Value); + UT_ASSERT_STATUS_EQUAL (Status, EFI_WRITE_PROTECTED); + + // + // Attempt to delete the locked var + // + Status =3D gRT->SetVariable (L"ExistingLockOnCreateVar", + &mTestNamespaceGuid1, + 0, + 0, + NULL); + UT_ASSERT_STATUS_EQUAL (Status, EFI_WRITE_PROTECTED); + + // + // This variable is deleted in final cleanup. + // + + return UNIT_TEST_PASSED; +} // TestExistingVarLockOnCreate + +UNIT_TEST_STATUS +TestNonexistentVarLockOnCreate ( + IN UNIT_TEST_CONTEXT Context + ) +{ + EFI_STATUS Status; + UINT8 Value1; + UINT32 Value2; + UINTN Size; + + // + // Make sure the variable we're about to create the policy for doesn't e= xist + // + Size =3D 0; + Status =3D gRT->GetVariable (L"NonexistentLockOnCreateVar", + &mTestNamespaceGuid1, + NULL, + &Size, + NULL); + UT_ASSERT_STATUS_EQUAL (Status, EFI_NOT_FOUND); + + // + // Register a LockOnCreate policy targeting the var + // + Status =3D RegisterBasicVariablePolicy (mVarPol, + &mTestNamespaceGuid1, + L"NonexistentLockOnCreateVar", + 2, // min size of 2 bytes, UINT16+ + VARIABLE_POLICY_NO_MAX_SIZE, + EFI_VARIABLE_RUNTIME_ACCESS, // mu= st have RT attr + VARIABLE_POLICY_NO_CANT_ATTR, + VARIABLE_POLICY_TYPE_LOCK_ON_CREAT= E); + UT_ASSERT_NOT_EFI_ERROR (Status); + + // + // Attempt to create the var, but smaller than min size + // + Value1 =3D 0xA5; + Status =3D gRT->SetVariable (L"NonexistentLockOnCreateVar", + &mTestNamespaceGuid1, + (EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIAB= LE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE), + sizeof (Value1), + &Value1); + UT_ASSERT_TRUE ((Status =3D=3D EFI_WRITE_PROTECTED) || (Status =3D=3D EF= I_INVALID_PARAMETER)); + + // + // Now let's make sure attribute req is enforced + // + Value2 =3D 0x43218765; + Status =3D gRT->SetVariable (L"NonexistentLockOnCreateVar", + &mTestNamespaceGuid1, + (EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIAB= LE_NON_VOLATILE), + sizeof (Value2), + &Value2); + UT_ASSERT_TRUE ((Status =3D=3D EFI_WRITE_PROTECTED) || (Status =3D=3D EF= I_INVALID_PARAMETER)); + + // + // Now let's create a valid variable + // + Value2 =3D 0x43218765; + Status =3D gRT->SetVariable (L"NonexistentLockOnCreateVar", + &mTestNamespaceGuid1, + (EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIAB= LE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE), + sizeof (Value2), + &Value2); + UT_ASSERT_NOT_EFI_ERROR (Status); + + // + // Let's make sure we can't modify it + // + Value2 =3D 0xa5a5b6b6; + Status =3D gRT->SetVariable (L"NonexistentLockOnCreateVar", + &mTestNamespaceGuid1, + (EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIAB= LE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE), + sizeof (Value2), + &Value2); + UT_ASSERT_STATUS_EQUAL (Status, EFI_WRITE_PROTECTED); + + // + // Finally, let's make sure we can't delete it + // + Status =3D gRT->SetVariable (L"NonexistentLockOnCreateVar", + &mTestNamespaceGuid1, + 0, + 0, + NULL); + UT_ASSERT_STATUS_EQUAL (Status, EFI_WRITE_PROTECTED); + + // + // This variable is deleted in final cleanup. + // + + return UNIT_TEST_PASSED; +} // TestNonexistentVarLockOnCreate + +/** + LockOnVarState Policy tests. +**/ +UNIT_TEST_STATUS +TestLockOnVarStateBeforeCreate ( + IN UNIT_TEST_CONTEXT Context + ) +{ + EFI_STATUS Status; + UINTN Size; + UINT8 Value; + + // + // First of all, let's make sure the var we're trying to protect doesn't= exist + // + Size =3D 0; + Status =3D gRT->GetVariable (L"NonexistentLockOnVarStateVar", + &mTestNamespaceGuid1, + NULL, + &Size, + NULL); + UT_ASSERT_STATUS_EQUAL (Status, EFI_NOT_FOUND); + + // + // Good, now let's create a policy + // + Status =3D RegisterVarStateVariablePolicy (mVarPol, + &mTestNamespaceGuid1, + L"NonexistentLockOnVarStateVar", + VARIABLE_POLICY_NO_MIN_SIZE, + VARIABLE_POLICY_NO_MAX_SIZE, + VARIABLE_POLICY_NO_MUST_ATTR, + VARIABLE_POLICY_NO_CANT_ATTR, + &mTestNamespaceGuid1, + L"Trigger1", + 0x7E); + UT_ASSERT_NOT_EFI_ERROR (Status); + + // + // Now we write the trigger var + // + Value =3D 0x7E; + Status =3D gRT->SetVariable (L"Trigger1", + &mTestNamespaceGuid1, + (EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIAB= LE_NON_VOLATILE), + sizeof (Value), + &Value); + UT_ASSERT_NOT_EFI_ERROR (Status); + + // + // Ok, now we attempt to write a var protected by the trigger + // + Value =3D 0xFA; + Status =3D gRT->SetVariable (L"NonexistentLockOnVarStateVar", + &mTestNamespaceGuid1, + (EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIAB= LE_NON_VOLATILE), + sizeof (Value), + &Value); + UT_ASSERT_STATUS_EQUAL (Status, EFI_WRITE_PROTECTED); + + // + // Let's modify the trigger var and "untrigger" the policy + // + Value =3D 0x38; + Status =3D gRT->SetVariable (L"Trigger1", + &mTestNamespaceGuid1, + (EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIAB= LE_NON_VOLATILE), + sizeof (Value), + &Value); + UT_ASSERT_NOT_EFI_ERROR (Status); + + // + // Now we should be able to create the var targeted by the policy + // + Value =3D 0x23; + Status =3D gRT->SetVariable (L"NonexistentLockOnVarStateVar", + &mTestNamespaceGuid1, + (EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIAB= LE_NON_VOLATILE), + sizeof (Value), + &Value); + UT_ASSERT_NOT_EFI_ERROR (Status); + + // + // Cleanup: delete the trigger and the protected var + // + Status =3D gRT->SetVariable (L"Trigger1", + &mTestNamespaceGuid1, + 0, + 0, + NULL); + UT_ASSERT_NOT_EFI_ERROR (Status); + + Status =3D gRT->SetVariable (L"NonexistentLockOnVarStateVar", + &mTestNamespaceGuid1, + 0, + 0, + NULL); + UT_ASSERT_NOT_EFI_ERROR (Status); + + return UNIT_TEST_PASSED; +} // TestLockOnVarStateBeforeCreate + +UNIT_TEST_STATUS +TestLockOnVarStateAfterCreate ( + IN UNIT_TEST_CONTEXT Context + ) +{ + EFI_STATUS Status; + UINT8 Value; + + // + // Let's create a policy + // + Status =3D RegisterVarStateVariablePolicy (mVarPol, + &mTestNamespaceGuid1, + L"ExistingLockOnVarStateVar", + VARIABLE_POLICY_NO_MIN_SIZE, + VARIABLE_POLICY_NO_MAX_SIZE, + VARIABLE_POLICY_NO_MUST_ATTR, + VARIABLE_POLICY_NO_CANT_ATTR, + &mTestNamespaceGuid1, + L"Trigger2", + 0x5C); + UT_ASSERT_NOT_EFI_ERROR (Status); + + // + // Should be able to write targeted var since the policy isn't active ye= t. + // + Value =3D 0x17; + Status =3D gRT->SetVariable (L"ExistingLockOnVarStateVar", + &mTestNamespaceGuid1, + (EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIAB= LE_NON_VOLATILE), + sizeof (Value), + &Value); + UT_ASSERT_NOT_EFI_ERROR (Status); + + // + // Let's modify the var to make sure the policy isn't acting like a lock= -on-create one + // + Value =3D 0x30; + Status =3D gRT->SetVariable (L"ExistingLockOnVarStateVar", + &mTestNamespaceGuid1, + (EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIAB= LE_NON_VOLATILE), + sizeof (Value), + &Value); + UT_ASSERT_NOT_EFI_ERROR (Status); + + // + // Now we trigger the policy + // + Value =3D 0x5C; + Status =3D gRT->SetVariable (L"Trigger2", + &mTestNamespaceGuid1, + (EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIAB= LE_NON_VOLATILE), + sizeof (Value), + &Value); + UT_ASSERT_NOT_EFI_ERROR (Status); + + // + // Let's now verify the variable is protected + // + Value =3D 0xB9; + Status =3D gRT->SetVariable (L"ExistingLockOnVarStateVar", + &mTestNamespaceGuid1, + (EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIAB= LE_NON_VOLATILE), + sizeof (Value), + &Value); + UT_ASSERT_STATUS_EQUAL (Status, EFI_WRITE_PROTECTED); + + // + // Ok, to clean up, we need to remove the trigger var, so delete it, and= then delete the target var + // + Status =3D gRT->SetVariable (L"Trigger2", + &mTestNamespaceGuid1, + 0, + 0, + NULL); + UT_ASSERT_NOT_EFI_ERROR (Status); + + Status =3D gRT->SetVariable (L"ExistingLockOnVarStateVar", + &mTestNamespaceGuid1, + 0, + 0, + NULL); + UT_ASSERT_NOT_EFI_ERROR (Status); + + return UNIT_TEST_PASSED; +} // TestLockOnVarStateAfterCreate + +UNIT_TEST_STATUS +TestLockOnVarStateInvalidLargeTrigger ( + IN UNIT_TEST_CONTEXT Context + ) +{ + EFI_STATUS Status; + UINT16 Value; + + // + // First let's create a variable policy + // + Status =3D RegisterVarStateVariablePolicy (mVarPol, + &mTestNamespaceGuid1, + L"InvalidLargeTriggerLockOnVarS= tateVar", + VARIABLE_POLICY_NO_MIN_SIZE, + VARIABLE_POLICY_NO_MAX_SIZE, + VARIABLE_POLICY_NO_MUST_ATTR, + VARIABLE_POLICY_NO_CANT_ATTR, + &mTestNamespaceGuid1, + L"Trigger3", + 0x5C); + UT_ASSERT_NOT_EFI_ERROR (Status); + + // + // Now attempt to trigger the lock but with a variable larger than one b= yte + // + Value =3D 0x8085; + Status =3D gRT->SetVariable (L"Trigger3", + &mTestNamespaceGuid1, + (EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIAB= LE_NON_VOLATILE), + sizeof (Value), + &Value); + UT_ASSERT_NOT_EFI_ERROR (Status); + + // + // Should still be able to create the targeted var + // + Value =3D 0x1234; + Status =3D gRT->SetVariable (L"InvalidLargeTriggerLockOnVarStateVar", + &mTestNamespaceGuid1, + (EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIAB= LE_NON_VOLATILE), + sizeof (Value), + &Value); + UT_ASSERT_NOT_EFI_ERROR (Status); + + // + // Let's clean up by deleting the invalid trigger and the targeted var + // + Status =3D gRT->SetVariable (L"Trigger3", + &mTestNamespaceGuid1, + 0, + 0, + NULL); + UT_ASSERT_NOT_EFI_ERROR (Status); + + Status =3D gRT->SetVariable (L"InvalidLargeTriggerLockOnVarStateVar", + &mTestNamespaceGuid1, + 0, + 0, + NULL); + UT_ASSERT_NOT_EFI_ERROR (Status); + + return UNIT_TEST_PASSED; +} // TestLockOnVarStateInvalidLargeTrigger + +UNIT_TEST_STATUS +TestLockOnVarStateWrongValueTrigger ( + IN UNIT_TEST_CONTEXT Context + ) +{ + EFI_STATUS Status; + UINT8 Value; + + // + // First let's create a variable policy + // + Status =3D RegisterVarStateVariablePolicy (mVarPol, + &mTestNamespaceGuid1, + L"WrongValueTriggerLockOnVarSta= teVar", + VARIABLE_POLICY_NO_MIN_SIZE, + VARIABLE_POLICY_NO_MAX_SIZE, + VARIABLE_POLICY_NO_MUST_ATTR, + VARIABLE_POLICY_NO_CANT_ATTR, + &mTestNamespaceGuid1, + L"Trigger4", + 0xCA); + UT_ASSERT_NOT_EFI_ERROR (Status); + + // + // Now attempt to trigger the lock but with a wrong value + // + Value =3D 0x80; + Status =3D gRT->SetVariable (L"Trigger4", + &mTestNamespaceGuid1, + (EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIAB= LE_NON_VOLATILE), + sizeof (Value), + &Value); + UT_ASSERT_NOT_EFI_ERROR (Status); + + // + // Should still be able to create the targeted var + // + Value =3D 0x14; + Status =3D gRT->SetVariable (L"WrongValueTriggerLockOnVarStateVar", + &mTestNamespaceGuid1, + (EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIAB= LE_NON_VOLATILE), + sizeof (Value), + &Value); + UT_ASSERT_NOT_EFI_ERROR (Status); + + // + // Let's clean up by deleting the invalid trigger and the targeted var + // + Status =3D gRT->SetVariable (L"Trigger4", + &mTestNamespaceGuid1, + 0, + 0, + NULL); + UT_ASSERT_NOT_EFI_ERROR (Status); + + Status =3D gRT->SetVariable (L"WrongValueTriggerLockOnVarStateVar", + &mTestNamespaceGuid1, + 0, + 0, + NULL); + UT_ASSERT_NOT_EFI_ERROR (Status); + + return UNIT_TEST_PASSED; +} // TestLockOnVarStateWrongValueTrigger + +/** + Invalid policy tests. +**/ +UNIT_TEST_STATUS +TestInvalidAttributesPolicy ( + IN UNIT_TEST_CONTEXT Context + ) +{ + EFI_STATUS Status; + + // + // The only must/can't have attributes supported by VPE are NV, BS, and = RT. They are 1, 2, and 4, respectively. + // Let's try some bits higher than that? + // + + // + // Trying must have attribute 0x8 which is EFI_VARIABLE_HARDWARE_ERROR_R= ECORD + // + Status =3D RegisterBasicVariablePolicy (mVarPol, + &mTestNamespaceGuid1, + L"InvalidMustHaveAttributesPolicyV= ar1", + VARIABLE_POLICY_NO_MIN_SIZE, + VARIABLE_POLICY_NO_MAX_SIZE, + EFI_VARIABLE_HARDWARE_ERROR_RECORD, + VARIABLE_POLICY_NO_CANT_ATTR, + VARIABLE_POLICY_TYPE_NO_LOCK); + UT_LOG_INFO ("Setting must have attr to EFI_VARIABLE_HARDWARE_ERROR_RECO= RD returned %r\n", Status); + + // + // Let's try 0x10 - EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS, a deprecate= d attribute + // + Status =3D RegisterBasicVariablePolicy (mVarPol, + &mTestNamespaceGuid1, + L"InvalidMustHaveAttributesPolicyV= ar2", + VARIABLE_POLICY_NO_MIN_SIZE, + VARIABLE_POLICY_NO_MAX_SIZE, + EFI_VARIABLE_AUTHENTICATED_WRITE_A= CCESS, + VARIABLE_POLICY_NO_CANT_ATTR, + VARIABLE_POLICY_TYPE_NO_LOCK); + UT_LOG_INFO ("Setting must have attr to EFI_VARIABLE_AUTHENTICATED_WRITE= _ACCESS returned %r\n", Status); + + // + // Let's try 0x20 - EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS + // + Status =3D RegisterBasicVariablePolicy (mVarPol, + &mTestNamespaceGuid1, + L"InvalidMustHaveAttributesPolicyV= ar3", + VARIABLE_POLICY_NO_MIN_SIZE, + VARIABLE_POLICY_NO_MAX_SIZE, + EFI_VARIABLE_TIME_BASED_AUTHENTICA= TED_WRITE_ACCESS, + VARIABLE_POLICY_NO_CANT_ATTR, + VARIABLE_POLICY_TYPE_NO_LOCK); + UT_LOG_INFO ("Setting must have attr to EFI_VARIABLE_TIME_BASED_AUTHENTI= CATED_WRITE_ACCESS returned %r\n", Status); + + // + // Let's try something wild, like 0x4000 + // + Status =3D RegisterBasicVariablePolicy (mVarPol, + &mTestNamespaceGuid1, + L"InvalidMustHaveAttributesPolicyV= ar4", + VARIABLE_POLICY_NO_MIN_SIZE, + VARIABLE_POLICY_NO_MAX_SIZE, + 0x4000, + VARIABLE_POLICY_NO_CANT_ATTR, + VARIABLE_POLICY_TYPE_NO_LOCK); + UT_LOG_INFO ("Setting must have attr to 0x4000 returned %r\n", Status); + + // + // Now repeat the same tests, but for the can't-have param + // + Status =3D RegisterBasicVariablePolicy (mVarPol, + &mTestNamespaceGuid1, + L"InvalidCantHaveAttributesPolicyV= ar1", + VARIABLE_POLICY_NO_MIN_SIZE, + VARIABLE_POLICY_NO_MAX_SIZE, + VARIABLE_POLICY_NO_MUST_ATTR, + EFI_VARIABLE_HARDWARE_ERROR_RECORD, + VARIABLE_POLICY_TYPE_NO_LOCK); + UT_LOG_INFO ("Setting cant have attr to EFI_VARIABLE_HARDWARE_ERROR_RECO= RD returned %r\n", Status); + + Status =3D RegisterBasicVariablePolicy (mVarPol, + &mTestNamespaceGuid1, + L"InvalidCantHaveAttributesPolicyV= ar2", + VARIABLE_POLICY_NO_MIN_SIZE, + VARIABLE_POLICY_NO_MAX_SIZE, + VARIABLE_POLICY_NO_MUST_ATTR, + EFI_VARIABLE_AUTHENTICATED_WRITE_A= CCESS, + VARIABLE_POLICY_TYPE_NO_LOCK); + UT_LOG_INFO ("Setting cant have attr to EFI_VARIABLE_AUTHENTICATED_WRITE= _ACCESS returned %r\n", Status); + + Status =3D RegisterBasicVariablePolicy (mVarPol, + &mTestNamespaceGuid1, + L"InvalidCantHaveAttributesPolicyV= ar3", + VARIABLE_POLICY_NO_MIN_SIZE, + VARIABLE_POLICY_NO_MAX_SIZE, + VARIABLE_POLICY_NO_MUST_ATTR, + EFI_VARIABLE_TIME_BASED_AUTHENTICA= TED_WRITE_ACCESS, + VARIABLE_POLICY_TYPE_NO_LOCK); + UT_LOG_INFO ("Setting cant have attr to EFI_VARIABLE_TIME_BASED_AUTHENTI= CATED_WRITE_ACCESS returned %r\n", Status); + + Status =3D RegisterBasicVariablePolicy (mVarPol, + &mTestNamespaceGuid1, + L"InvalidCantHaveAttributesPolicyV= ar4", + VARIABLE_POLICY_NO_MIN_SIZE, + VARIABLE_POLICY_NO_MAX_SIZE, + VARIABLE_POLICY_NO_MUST_ATTR, + 0x4000, + VARIABLE_POLICY_TYPE_NO_LOCK); + UT_LOG_INFO ("Setting cant have attr to 0x4000 returned %r\n", Status); + + return UNIT_TEST_PASSED; +} // TestInvalidAttributesPolicy + +UNIT_TEST_STATUS +TestLargeMinSizePolicy ( + IN UNIT_TEST_CONTEXT Context + ) +{ + EFI_STATUS Status; + + // + // Let's set the min size to 2GB and see what happens + // + Status =3D RegisterBasicVariablePolicy (mVarPol, + &mTestNamespaceGuid1, + L"LargeMinSizeInvalidPolicyVar", + 0x80000000, + VARIABLE_POLICY_NO_MAX_SIZE, + VARIABLE_POLICY_NO_MUST_ATTR, + VARIABLE_POLICY_NO_CANT_ATTR, + VARIABLE_POLICY_TYPE_NO_LOCK); + + UT_LOG_INFO ("Setting min size to 0x80000000 returned %r\n", Status); + + return UNIT_TEST_PASSED; +} // TestLargeMinSizePolicy + +UNIT_TEST_STATUS +TestZeroMaxSizePolicy ( + IN UNIT_TEST_CONTEXT Context + ) +{ + EFI_STATUS Status; + + // + // Let's set the max size to 0 and see what happens + // + Status =3D RegisterBasicVariablePolicy (mVarPol, + &mTestNamespaceGuid1, + L"ZeroMinSizeInvalidPolicyVar", + VARIABLE_POLICY_NO_MIN_SIZE, + 0, + VARIABLE_POLICY_NO_MUST_ATTR, + VARIABLE_POLICY_NO_CANT_ATTR, + VARIABLE_POLICY_TYPE_NO_LOCK); + //UT_ASSERT_NOT_EQUAL (Status, EFI_SUCCESS); // this fails on QC. Real b= ug? Do we care? + UT_LOG_INFO ("Setting max size to 0 returned %r\n", Status); + + return UNIT_TEST_PASSED; +} // TestZeroMaxSizePolicy + +UNIT_TEST_STATUS +TestInvalidPolicyTypePolicy ( + IN UNIT_TEST_CONTEXT Context + ) +{ + EFI_STATUS Status; + + // + // Let's set policy type to an invalid value and see what happens + // Valid ones are: + // VARIABLE_POLICY_TYPE_NO_LOCK 0 + // VARIABLE_POLICY_TYPE_LOCK_NOW 1 + // VARIABLE_POLICY_TYPE_LOCK_ON_CREATE 2 + // VARIABLE_POLICY_TYPE_LOCK_ON_VAR_STATE 3 + // + Status =3D RegisterBasicVariablePolicy (mVarPol, + &mTestNamespaceGuid1, + L"InvalidPolicyTypePolicyVar", + VARIABLE_POLICY_NO_MIN_SIZE, + VARIABLE_POLICY_NO_MAX_SIZE, + VARIABLE_POLICY_NO_MUST_ATTR, + VARIABLE_POLICY_NO_CANT_ATTR, + 4); + UT_ASSERT_NOT_EQUAL (Status, EFI_SUCCESS); + + Status =3D RegisterBasicVariablePolicy (mVarPol, + &mTestNamespaceGuid1, + L"InvalidPolicyTypePolicyVar", + VARIABLE_POLICY_NO_MIN_SIZE, + VARIABLE_POLICY_NO_MAX_SIZE, + VARIABLE_POLICY_NO_MUST_ATTR, + VARIABLE_POLICY_NO_CANT_ATTR, + 147); + UT_ASSERT_NOT_EQUAL (Status, EFI_SUCCESS); + + return UNIT_TEST_PASSED; +} // TestInvalidPolicyTypePolicy + +/** + Test dumping policy. +**/ +UNIT_TEST_STATUS +TestDumpPolicy ( + IN UNIT_TEST_CONTEXT Context + ) +{ + EFI_STATUS Status; + UINT8* Buffer; + UINT32 Size; + + // + // First let's call DumpVariablePolicy with null buffer to get size + // + Size =3D 0; + Status =3D mVarPol->DumpVariablePolicy (NULL, &Size); + UT_ASSERT_STATUS_EQUAL (Status, EFI_BUFFER_TOO_SMALL); + + // + // Now we allocate the buffer for the dump + // + Buffer =3D NULL; + Buffer =3D AllocatePool (Size); + UT_ASSERT_NOT_NULL (Buffer); + + // + // Now we get the dump. In this test we will not analyze the dump. + // + Status =3D mVarPol->DumpVariablePolicy (Buffer, &Size); + UT_ASSERT_NOT_EFI_ERROR (Status); + + return UNIT_TEST_PASSED; +} // TestDumpPolicy + +/** + Test policy version. +**/ +UNIT_TEST_STATUS +TestPolicyVersion ( + IN UNIT_TEST_CONTEXT Context + ) +{ + EFI_STATUS Status; + VARIABLE_POLICY_ENTRY *NewEntry; + + // + // Create the new entry using a helper lib + // + NewEntry =3D NULL; + Status =3D CreateBasicVariablePolicy (&mTestNamespaceGuid1, + L"PolicyVersionTestNoLockVar", + VARIABLE_POLICY_NO_MIN_SIZE, + 4, // max size of 4 bytes + VARIABLE_POLICY_NO_MUST_ATTR, + VARIABLE_POLICY_NO_CANT_ATTR, + VARIABLE_POLICY_TYPE_NO_LOCK, + &NewEntry); + UT_ASSERT_NOT_EFI_ERROR (Status); + + NewEntry->Version =3D 0x1234; + Status =3D mVarPol->RegisterVariablePolicy (NewEntry); + UT_LOG_INFO ("Registering policy entry with an unknown version status: %= r\n", Status); + + FreePool (NewEntry); + + return UNIT_TEST_PASSED; +} // TestPolicyVersion + +/** + Lock Policy Tests. +**/ +UNIT_TEST_STATUS +LockPolicyEngineTests ( + IN UNIT_TEST_CONTEXT Context + ) +{ + EFI_STATUS Status; + UINT16 Value; + UINT64 Value64; + BOOLEAN State; + + // + // First let's register a policy that we'll test after VPE lock + // + Status =3D RegisterBasicVariablePolicy (mVarPol, + &mTestNamespaceGuid1, + L"BeforeVpeLockNoLockPolicyVar", + VARIABLE_POLICY_NO_MIN_SIZE, + 4, // max size of 4 bytes + VARIABLE_POLICY_NO_MUST_ATTR, + VARIABLE_POLICY_NO_CANT_ATTR, + VARIABLE_POLICY_TYPE_LOCK_ON_CREAT= E); + UT_ASSERT_NOT_EFI_ERROR (Status); + + // + // Now, lock VPE! + // + Status =3D mVarPol->LockVariablePolicy (); + UT_ASSERT_NOT_EFI_ERROR (Status); + + // + // See if we can lock it again? + // + Status =3D mVarPol->LockVariablePolicy (); + UT_LOG_INFO ("Locking VPE for second time returned %r\n", Status); + + // + // Let's confirm one of the policies from prior test suites is still enf= orced + // Attempt to delete a locked var + // + Status =3D gRT->SetVariable (L"ExistingLockNowVar", + &mTestNamespaceGuid1, + 0, + 0, + NULL); + UT_ASSERT_STATUS_EQUAL (Status, EFI_WRITE_PROTECTED); + + // + // We'll make sure the policy from earlier in this test case is actively= filtering out by size + // + Value64 =3D 0x3829fed212345678; + Status =3D gRT->SetVariable (L"BeforeVpeLockNoLockPolicyVar", + &mTestNamespaceGuid1, + (EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BO= OTSERVICE_ACCESS), + sizeof (Value64), + &Value64); + UT_ASSERT_TRUE ((Status =3D=3D EFI_WRITE_PROTECTED) || (Status =3D=3D EF= I_INVALID_PARAMETER)); + + // + // Let's create the variable from the policy now + // + Value =3D 0x323f; + Status =3D gRT->SetVariable (L"BeforeVpeLockNoLockPolicyVar", + &mTestNamespaceGuid1, + (EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BO= OTSERVICE_ACCESS), + sizeof (Value), + &Value); + UT_ASSERT_NOT_EFI_ERROR (Status); + + // + // Now confirm that the var is locked after creation + // + Value =3D 0x1212; + Status =3D gRT->SetVariable (L"BeforeVpeLockNoLockPolicyVar", + &mTestNamespaceGuid1, + (EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BO= OTSERVICE_ACCESS), + sizeof (Value), + &Value); + UT_ASSERT_STATUS_EQUAL (Status, EFI_WRITE_PROTECTED); + + // + // Let's attempt to register a new policy, it should fail + // + Status =3D RegisterBasicVariablePolicy (mVarPol, + &mTestNamespaceGuid1, + L"AfterVpeLockNowPolicyVar", + VARIABLE_POLICY_NO_MIN_SIZE, + VARIABLE_POLICY_NO_MAX_SIZE, + VARIABLE_POLICY_NO_MUST_ATTR, + VARIABLE_POLICY_NO_CANT_ATTR, + VARIABLE_POLICY_TYPE_LOCK_NOW); + UT_ASSERT_NOT_EQUAL (Status, EFI_SUCCESS); + + // + // Make sure VPE is enabled + // + Status =3D mVarPol->IsVariablePolicyEnabled (&State); + UT_ASSERT_NOT_EFI_ERROR (Status); + UT_ASSERT_EQUAL (State, TRUE); + + // + // Finally, make sure we can't disable VPE + // + Status =3D mVarPol->DisableVariablePolicy (); + UT_ASSERT_NOT_EQUAL (Status, EFI_SUCCESS); + + return UNIT_TEST_PASSED; +} // LockPolicyEngineTests + +/** + Save context and reboot after the lock policy test suite. +**/ +STATIC +VOID +SaveContextAndReboot ( + IN UNIT_TEST_CONTEXT Context + ) +{ + EFI_STATUS Status; + + // + // Now, save all the data associated with this framework. + // TODO: Need to add to the UnitTestFrameworkPkg + Status =3D SaveFrameworkState( GetActiveFrameworkHandle(), NULL, 0 ); + + // + // If we're all good, let's book... + if (!EFI_ERROR( Status )) + { + // + // Next, we want to update the BootNext variable to USB + // so that we have a fighting chance of coming back here. + // + // TODO: Need to add to the UnitTestFrameworkPkg + // SetBootNextDevice(); + + // + // Reset + DEBUG(( DEBUG_INFO, "%a - Rebooting! Launch this test again once boote= d.\n", __FUNCTION__ )); + gRT->ResetSystem( EfiResetCold, EFI_SUCCESS, 0, NULL ); + DEBUG(( DEBUG_ERROR, "%a - Unit test failed to quit! Framework can no = longer be used!\n", __FUNCTION__ )); + + // + // We REALLY shouldn't be here. + Status =3D EFI_ABORTED; + } + + return; +} // SaveContextAndReboot + +/** + Disable policy tests. +**/ +UNIT_TEST_STATUS +DisablePolicyEngineTests ( + IN UNIT_TEST_CONTEXT Context + ) +{ + EFI_STATUS Status; + BOOLEAN State; + UINT8 Value; + + // + // First, we disable the variable policy + // + Status =3D mVarPol->DisableVariablePolicy (); + UT_ASSERT_NOT_EFI_ERROR (Status); + + // + // Confirm it's disabled + // + Status =3D mVarPol->IsVariablePolicyEnabled (&State); + UT_ASSERT_NOT_EFI_ERROR (Status); + UT_ASSERT_EQUAL (State, FALSE); + + // + // Try locking it? + // + Status =3D mVarPol->LockVariablePolicy (); + UT_LOG_INFO ("Locking VP after disabling it status: %r\n", Status); + + // + // Try modifying the var from TestExistingVarLockNow + // + Value =3D 0xB5; + Status =3D gRT->SetVariable (L"ExistingLockNowVar", + &mTestNamespaceGuid1, + (EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIAB= LE_NON_VOLATILE), + sizeof (Value), + &Value); + UT_ASSERT_NOT_EFI_ERROR (Status); + + return UNIT_TEST_PASSED; +} // DisablePolicyEngineTests + +/** + Final Cleanup: delete some variables earlier test cases created. +**/ +STATIC +VOID +FinalCleanup ( + IN UNIT_TEST_CONTEXT Context + ) +{ + EFI_STATUS Status; + + Status =3D gRT->SetVariable (L"ExistingLockNowVar", + &mTestNamespaceGuid1, + 0, + 0, + NULL); + UT_LOG_INFO ("Delete ExistingLockNowVar status: %r\n", Status); + + Status =3D gRT->SetVariable (L"ExistingLockOnCreateVar", + &mTestNamespaceGuid1, + 0, + 0, + NULL); + UT_LOG_INFO ("Delete ExistingLockOnCreateVar status: %r\n", Status); + + Status =3D gRT->SetVariable (L"NonexistentLockOnCreateVar", + &mTestNamespaceGuid1, + 0, + 0, + NULL); + UT_LOG_INFO ("Delete NonexistentLockOnCreateVar status: %r\n", Status); + + Status =3D gRT->SetVariable (L"NonexistentLockNowVar", + &mTestNamespaceGuid1, + 0, + 0, + NULL); + UT_LOG_INFO ("Delete NonexistentLockNowVar status: %r\n", Status); + + Status =3D gRT->SetVariable (L"CantHaveAttrNoLockVar", + &mTestNamespaceGuid1, + 0, + 0, + NULL); + UT_LOG_INFO ("Delete CantHaveAttrNoLockVar status: %r\n", Status); + + Status =3D gRT->SetVariable (L"NonexistentLockOnVarStateVar", + &mTestNamespaceGuid1, + 0, + 0, + NULL); + UT_LOG_INFO ("Delete NonexistentLockOnVarStateVar status: %r\n", Status); + + Status =3D gRT->SetVariable (L"ExistingLockOnVarStateVar", + &mTestNamespaceGuid1, + 0, + 0, + NULL); + UT_LOG_INFO ("Delete ExistingLockOnVarStateVar status: %r\n", Status); +} // FinalCleanup + +/** + + Main fuction sets up the unit test environment. + +**/ +EFI_STATUS +UefiMain ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE* SystemTable) +{ + EFI_STATUS Status; + UNIT_TEST_FRAMEWORK_HANDLE Framework; + UNIT_TEST_SUITE_HANDLE GettingStartedTestSuite; + UNIT_TEST_SUITE_HANDLE NoLockPoliciesTestSuite; + UNIT_TEST_SUITE_HANDLE LockNowPoliciesTestSuite; + UNIT_TEST_SUITE_HANDLE LockOnCreatePoliciesTestSuite; + UNIT_TEST_SUITE_HANDLE LockOnVarStatePoliciesTestSuite; + UNIT_TEST_SUITE_HANDLE InvalidPoliciesTestSuite; + UNIT_TEST_SUITE_HANDLE DumpPolicyTestSuite; + UNIT_TEST_SUITE_HANDLE PolicyVersionTestSuite; + UNIT_TEST_SUITE_HANDLE LockPolicyTestSuite; + UNIT_TEST_SUITE_HANDLE DisablePolicyTestSuite; + + Framework =3D NULL; + GettingStartedTestSuite =3D NULL; + NoLockPoliciesTestSuite =3D NULL; + LockNowPoliciesTestSuite =3D NULL; + LockOnCreatePoliciesTestSuite =3D NULL; + LockOnVarStatePoliciesTestSuite =3D NULL; + InvalidPoliciesTestSuite =3D NULL; + DumpPolicyTestSuite =3D NULL; + PolicyVersionTestSuite =3D NULL; =20 + LockPolicyTestSuite =3D NULL; + DisablePolicyTestSuite =3D NULL; + + DEBUG ((DEBUG_INFO, "%a v%a\n", UNIT_TEST_APP_NAME, UNIT_TEST_APP_VERSIO= N)); + + // + // Start setting up the test framework for running the tests. + // + Status =3D InitUnitTestFramework (&Framework, UNIT_TEST_APP_NAME, gEfiCa= llerBaseName, UNIT_TEST_APP_VERSION); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "Failed in InitUnitTestFramework. Status =3D %r\n= ", Status)); + goto EXIT; + } + + // + // Test suite 1: Getting Started. Get VP protocol, check state, log revi= sion + // + Status =3D CreateUnitTestSuite (&GettingStartedTestSuite, Framework, "Ge= tting Started", "Common.VP.GettingStarted", NULL, NULL); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "Failed in CreateUnitTestSuite for the Getting St= arted Test Suite\n")); + Status =3D EFI_OUT_OF_RESOURCES; + goto EXIT; + } + AddTestCase (GettingStartedTestSuite, "Confirm VP is enabled", "Common.V= P.GettingStarted.CheckVpEnabled", CheckVpEnabled, LocateVarPolicyPreReq, NU= LL, NULL); + AddTestCase (GettingStartedTestSuite, "Check VP revision", "Common.VP.Ge= ttingStarted.CheckVpRevision", CheckVpRevision, LocateVarPolicyPreReq, NULL= , NULL); + + // + // Test suite 2: Test NoLock Policies + // + Status =3D CreateUnitTestSuite (&NoLockPoliciesTestSuite, Framework, "Ex= ercise NoLock Policies", "Common.VP.NoLockPolicies", NULL, NULL); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "Failed in CreateUnitTestSuite for the NoLock Pol= icies Test Suite\n")); + Status =3D EFI_OUT_OF_RESOURCES; + goto EXIT; + } + AddTestCase (NoLockPoliciesTestSuite, "Test Min Size enforcement in NoLo= ck policy", "Common.VP.NoLockPolicies.TestMinSizeNoLock", TestMinSizeNoLock= , LocateVarPolicyPreReq, NULL, NULL); + AddTestCase (NoLockPoliciesTestSuite, "Test Max Size enforcement in NoLo= ck policy", "Common.VP.NoLockPolicies.TestMaxSizeNoLock", TestMaxSizeNoLock= , LocateVarPolicyPreReq, NULL, NULL); + AddTestCase (NoLockPoliciesTestSuite, "Test Must Have Attribute enforcem= ent in NoLock policy", "Common.VP.NoLockPolicies.TestMustHaveAttrNoLock", T= estMustHaveAttrNoLock, LocateVarPolicyPreReq, NULL, NULL); + AddTestCase (NoLockPoliciesTestSuite, "Test Can't Have Attribute enforce= ment in NoLock policy", "Common.VP.NoLockPolicies.TestCantHaveAttrNoLock", = TestCantHaveAttrNoLock, LocateVarPolicyPreReq, NULL, NULL); + AddTestCase (NoLockPoliciesTestSuite, "Test Max Size enforcement in NoLo= ck policy for entire namespace", "Common.VP.NoLockPolicies.TestMaxSizeNames= paceNoLock", TestMaxSizeNamespaceNoLock, LocateVarPolicyPreReq, NULL, NULL); + AddTestCase (NoLockPoliciesTestSuite, "Test Must Have Attribute enforcem= ent in NoLock policy with wildcards", "Common.VP.NoLockPolicies.TestMustHav= eAttrWildcardNoLock", TestMustHaveAttrWildcardNoLock, LocateVarPolicyPreReq= , NULL, NULL); + AddTestCase (NoLockPoliciesTestSuite, "Test policy prioritization betwee= n namespace-wide, wildcard, and var-specific policies", "Common.VP.NoLockPo= licies.TestPolicyprioritizationNoLock", TestPolicyprioritizationNoLock, Loc= ateVarPolicyPreReq, NULL, NULL); + + // + // Test suite 3: Test LockNow policies + // + Status =3D CreateUnitTestSuite (&LockNowPoliciesTestSuite, Framework, "E= xercise LockNow Policies", "Common.VP.LockNowPolicies", NULL, NULL); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "Failed in CreateUnitTestSuite for the LockNow Po= licies Test Suite\n")); + Status =3D EFI_OUT_OF_RESOURCES; + goto EXIT; + } + AddTestCase (LockNowPoliciesTestSuite, "Test LockNow policy for a pre-ex= isting variable", "Common.VP.LockNowPolicies.TestExistingVarLockNow", TestE= xistingVarLockNow, LocateVarPolicyPreReq, NULL, NULL); + AddTestCase (LockNowPoliciesTestSuite, "Test LockNow policy for a nonexi= stent variable", "Common.VP.LockNowPolicies.TestNonexistentVarLockNow", Tes= tNonexistentVarLockNow, LocateVarPolicyPreReq, NULL, NULL); + + // + // Test suite 4: Test LockOnCreate policies + // + Status =3D CreateUnitTestSuite (&LockOnCreatePoliciesTestSuite, Framewor= k, "Exercise LockOnCreate Policies", "Common.VP.LockOnCreate", NULL, NULL); + if (EFI_ERROR (Status)) + { + DEBUG ((DEBUG_ERROR, "Failed in CreateUnitTestSuite for the LockOnCrea= te Policies Test Suite\n")); + Status =3D EFI_OUT_OF_RESOURCES; + goto EXIT; + } + AddTestCase (LockOnCreatePoliciesTestSuite, "Test LockOnCreate policy fo= r a pre-existing variable", "Common.VP.LockOnCreate.TestExistingVarLockOnCr= eate", TestExistingVarLockOnCreate, LocateVarPolicyPreReq, NULL, NULL); + AddTestCase (LockOnCreatePoliciesTestSuite, "Test LockOnCreate policy fo= r a nonexistent variable", "Common.VP.LockOnCreate.TestNonexistentVarLockOn= Create", TestNonexistentVarLockOnCreate, LocateVarPolicyPreReq, NULL, NULL); + + // + // Test suite 5: Test LockOnVarState policies + // + Status =3D CreateUnitTestSuite (&LockOnVarStatePoliciesTestSuite, Framew= ork, "Exercise LockOnVarState Policies", "Common.VP.LockOnVarState", NULL, = NULL); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "Failed in CreateUnitTestSuite for the LockOnVarS= tate Policies Test Suite\n")); + Status =3D EFI_OUT_OF_RESOURCES; + goto EXIT; + } + AddTestCase (LockOnVarStatePoliciesTestSuite, "Test LockOnVarState polic= y for a nonexistent variable", "Common.VP.LockOnVarState.TestLockOnVarState= BeforeCreate", TestLockOnVarStateBeforeCreate, LocateVarPolicyPreReq, NULL,= NULL); + AddTestCase (LockOnVarStatePoliciesTestSuite, "Test LockOnVarState polic= y for a pre-existing variable", "Common.VP.LockOnVarState.TestLockOnVarStat= eAfterCreate", TestLockOnVarStateAfterCreate, LocateVarPolicyPreReq, NULL, = NULL); + AddTestCase (LockOnVarStatePoliciesTestSuite, "Test LockOnVarState polic= y triggered by invalid-size variable", "Common.VP.LockOnVarState.TestLockOn= VarStateInvalidLargeTrigger", TestLockOnVarStateInvalidLargeTrigger, Locate= VarPolicyPreReq, NULL, NULL); + AddTestCase (LockOnVarStatePoliciesTestSuite, "Test LockOnVarState polic= y triggered by invalid-value variable", "Common.VP.LockOnVarState.TestLockO= nVarStateWrongValueTrigger", TestLockOnVarStateWrongValueTrigger, LocateVar= PolicyPreReq, NULL, NULL); + + // + // Test suite 6: Test registering invalid policies + // + Status =3D CreateUnitTestSuite (&InvalidPoliciesTestSuite, Framework, "A= ttempt registering invalid policies", "Common.VP.InvalidPolicies", NULL, NU= LL); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "Failed in CreateUnitTestSuite for the Invalid Po= licies Test Suite\n")); + Status =3D EFI_OUT_OF_RESOURCES; + goto EXIT; + } + AddTestCase (InvalidPoliciesTestSuite, "Test policy with invalid must-ha= ve attributes", "Common.VP.InvalidPolicies.TestInvalidAttributesPolicy", Te= stInvalidAttributesPolicy, LocateVarPolicyPreReq, NULL, NULL); + AddTestCase (InvalidPoliciesTestSuite, "Test policy with invalid attribu= tes", "Common.VP.InvalidPolicies.TestLargeMinSizePolicy", TestLargeMinSizeP= olicy, LocateVarPolicyPreReq, NULL, NULL); + AddTestCase (InvalidPoliciesTestSuite, "Test policy with invalid attribu= tes", "Common.VP.InvalidPolicies.TestZeroMaxSizePolicy", TestZeroMaxSizePol= icy, LocateVarPolicyPreReq, NULL, NULL); + AddTestCase (InvalidPoliciesTestSuite, "Test policy with invalid type", = "Common.VP.InvalidPolicies.TestInvalidPolicyTypePolicy", TestInvalidPolicyT= ypePolicy, LocateVarPolicyPreReq, NULL, NULL); + + // + // Test suite 7: Test dumping the policy + // + Status =3D CreateUnitTestSuite (&DumpPolicyTestSuite, Framework, "Attemp= t dumping policy", "Common.VP.DumpPolicy", NULL, NULL); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "Failed in CreateUnitTestSuite for the Dump Polic= y Test Suite\n")); + Status =3D EFI_OUT_OF_RESOURCES; + goto EXIT; + } + AddTestCase (DumpPolicyTestSuite, "Test dumping policy", "Common.VP.Dump= Policy.TestDumpPolicy", TestDumpPolicy, LocateVarPolicyPreReq, NULL, NULL); + + // + // Test suite 8: Test policy version + // + Status =3D CreateUnitTestSuite (&PolicyVersionTestSuite, Framework, "Use= non-zero policy version", "Common.VP.PolicyVersion", NULL, NULL); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "Failed in CreateUnitTestSuite for the Policy Ver= sion Test Suite\n")); + Status =3D EFI_OUT_OF_RESOURCES; + goto EXIT; + } + AddTestCase (PolicyVersionTestSuite, "Test policy version", "Common.VP.D= umpPolicy.TestPolicyVersion", TestPolicyVersion, LocateVarPolicyPreReq, NUL= L, NULL); + + // + // Test suite 9: Lock VPE and test implications + // + Status =3D CreateUnitTestSuite (&LockPolicyTestSuite, Framework, "Lock p= olicy, test it", "Common.VP.LockPolicyTests", NULL, NULL); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "Failed in CreateUnitTestSuite for the Lock Polic= y Test Suite\n")); + Status =3D EFI_OUT_OF_RESOURCES; + goto EXIT; + } + AddTestCase (LockPolicyTestSuite, "Test locking policy", "Common.VP.Lock= PolicyTests.LockPolicyEngineTests", LockPolicyEngineTests, LocateVarPolicyP= reReq, NULL, NULL); + AddTestCase (LockPolicyTestSuite, "Test locking policy", "Common.VP.Lock= PolicyTests.LockPolicyEngineTests", LockPolicyEngineTests, LocateVarPolicyP= reReq, SaveContextAndReboot, NULL); + + // + // Test suite 10: Disable var policy and confirm expected behavior + // + Status =3D CreateUnitTestSuite (&DisablePolicyTestSuite, Framework, "Dis= able policy, test it", "Common.VP.DisablePolicyTests", NULL, NULL); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "Failed in CreateUnitTestSuite for the Disable Po= licy Test Suite\n")); + Status =3D EFI_OUT_OF_RESOURCES; + goto EXIT; + } + AddTestCase (DisablePolicyTestSuite, "Confirm VP is enabled", "Common.VP= .DisablePolicyTests.CheckVpEnabled", CheckVpEnabled, LocateVarPolicyPreReq,= NULL, NULL); + AddTestCase (DisablePolicyTestSuite, "Test LockNow policy for a pre-exis= ting variable", "Common.VP.DisablePolicyTests.TestExistingVarLockNow", Test= ExistingVarLockNow, LocateVarPolicyPreReq, NULL, NULL); + AddTestCase (DisablePolicyTestSuite, "Test disabling policy", "Common.VP= .DisablePolicyTests.DisablePolicyEngineTests", DisablePolicyEngineTests, Lo= cateVarPolicyPreReq, FinalCleanup, NULL); + + // + // Execute the tests. + // + Status =3D RunAllTestSuites (Framework); + +EXIT: + if (Framework !=3D NULL) { + FreeUnitTestFramework (Framework); + } + + return Status; +} // UefiMain diff --git a/MdeModulePkg/MdeModulePkg.ci.yaml b/MdeModulePkg/MdeModulePkg.= ci.yaml index 1cfc1328390e..88a192d0e2a8 100644 --- a/MdeModulePkg/MdeModulePkg.ci.yaml +++ b/MdeModulePkg/MdeModulePkg.ci.yaml @@ -35,7 +35,9 @@ "UnitTestFrameworkPkg/UnitTestFrameworkPkg.dec" ], # For UEFI shell based apps - "AcceptableDependencies-UEFI_APPLICATION":[], + "AcceptableDependencies-UEFI_APPLICATION":[ + "UnitTestFrameworkPkg/UnitTestFrameworkPkg.dec" + ], "IgnoreInf": [] }, =20 diff --git a/MdeModulePkg/MdeModulePkg.dsc b/MdeModulePkg/MdeModulePkg.dsc index f0a75a3b337b..414a6c62dfdb 100644 --- a/MdeModulePkg/MdeModulePkg.dsc +++ b/MdeModulePkg/MdeModulePkg.dsc @@ -19,6 +19,8 @@ [Defines] BUILD_TARGETS =3D DEBUG|RELEASE|NOOPT SKUID_IDENTIFIER =3D DEFAULT =20 +!include UnitTestFrameworkPkg/UnitTestFrameworkPkgTarget.dsc.inc + [LibraryClasses] # # Entry point @@ -314,6 +316,10 @@ [Components] MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLib.inf MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLibRuntimeDxe.inf MdeModulePkg/Library/VarCheckPolicyLib/VarCheckPolicyLib.inf + MdeModulePkg/Test/ShellTest/VariablePolicyFuncTestApp/VariablePolicyFunc= TestApp.inf { + + UnitTestBootLib|UnitTestFrameworkPkg/Library/UnitTestBootLibNull/Uni= tTestBootLibNull.inf + } MdeModulePkg/Library/VarCheckLib/VarCheckLib.inf MdeModulePkg/Library/VarCheckHiiLib/VarCheckHiiLib.inf MdeModulePkg/Library/VarCheckPcdLib/VarCheckPcdLib.inf diff --git a/MdeModulePkg/Test/ShellTest/VariablePolicyFuncTestApp/Readme.m= d b/MdeModulePkg/Test/ShellTest/VariablePolicyFuncTestApp/Readme.md new file mode 100644 index 000000000000..804ad4173a5f --- /dev/null +++ b/MdeModulePkg/Test/ShellTest/VariablePolicyFuncTestApp/Readme.md @@ -0,0 +1,55 @@ +# variable Policy Unit Tests + +## 🔹 Copyright +Copyright (C) Microsoft Corporation. All rights reserved. +SPDX-License-Identifier: BSD-2-Clause-Patent + +## About This Test +This test verifies functionality of the Variable Policy Protocol by regist= ering various variable policies and exercising them, as well as tests locki= ng the policy, disabling it, and dumping the policy entries. + +Only policies that are created as a part of this test will be tested. +1. Try getting test context, if empty then get VP protocol, confirm that V= P is not disabled by calling IsVariablePolicyEnabled. Log VP revision. +2. "No lock" policies: + * check minsize enforcement + * check maxsize enforcement + * check musthave attr enforcement + * check canthave attr enforcement + * check one of the above with empty string policy i.e. name wildcard + * check another one of the above with a "#" containing policy string + * check policy prioritization by having a namespace-wide policy, a pol= icy with a # wildcard, and a one-var specific policy and testing which one = is enforced +3. "Lock now" policies (means if the var doesn't exist, it won't be create= d; if one exists, it can't be updated): + * test a policy for an already existing variable, verify we can't writ= e into that variable + * create a policy for a non-existing variable and attempt to register = such var +4. "Lock on create" policies (means the var can still be created, but no u= pdates later, existing vars can't be updated): + * create a var, lock it with LockOnCreate, attempt to update its conte= nts + * create LockOnCreate VP, attempt to create var with invalid size, the= n invalid attr, then create valid var, attempt to update its contents +5. "Lock on var state" policies (means the var protected by this policy ca= n't be created or updated once the trigger is set) + * create VP, trigger lock with a valid var, attempt to create a locked= var, then modify the trigger var, create locked var + * create VP, create targeted var, modify it, trigger lock, attempt to = modify var + * create VP, trigger lock with invalid (larger than one byte) var, see= if VPE allows creation of the locked var (it should allow) + * create VP, set locking var with wrong value, see if VPE allows creat= ion of the locked var (should allow) +6. Attempt registering invalid policy entries + * invalid required and banned attributes + * large min size - let's say 2GB + * max size equal to 0 + * invalid policy type +7. Exercise dumping policy. No need to check the validity of the dump blob. +8. Test registering a policy with a random version. +9. Lock VPE, make sure old policies are enforced, new ones can't be regist= ered. + * Register a LockOnCreate policy + * Lock VPE + * Test locking it again. + * Verify one of the prior policies is enforced + * Make sure we can create variables even if those are protected by Loc= kOnCreate policy, after locking the VPE + * Attempt to register new policies + * Make sure can't disable VPE + * Cleanup: save context and reboot +10. Disable variable policy and try some things + * Locate Variable Policy Protocol + * Make sure VP is enabled + * Register a policy + * Disable VPE + * Call IsVariablePolicyEnabled to confirm it's disabled. + * Make sure can't lock policy + * Make sure the policy from a is no longer enforced + * Final cleanup: delete vars that were created in some earlier test su= ites diff --git a/MdeModulePkg/Test/ShellTest/VariablePolicyFuncTestApp/Variable= PolicyFuncTestApp.inf b/MdeModulePkg/Test/ShellTest/VariablePolicyFuncTestA= pp/VariablePolicyFuncTestApp.inf new file mode 100644 index 000000000000..9ad277a547c2 --- /dev/null +++ b/MdeModulePkg/Test/ShellTest/VariablePolicyFuncTestApp/VariablePolicyF= uncTestApp.inf @@ -0,0 +1,42 @@ +## @file +# Uefi Shell based Application that unit tests the Variable Policy Protocol +# +# Copyright (c) Microsoft Corporation. +# SPDX-License-Identifier: BSD-2-Clause-Patent +## + +[Defines] + INF_VERSION =3D 0x00010005 + BASE_NAME =3D VariablePolicyFuncTestApp + FILE_GUID =3D B653C4C3-3FCC-4B6C-8051-5F692AEAECBA + MODULE_TYPE =3D UEFI_APPLICATION + VERSION_STRING =3D 1.0 + ENTRY_POINT =3D UefiMain + +# +# The following information is for reference only and not required by the = build tools. +# +# VALID_ARCHITECTURES =3D X64 AARCH64 +# + +[Sources] + VariablePolicyFuncTestApp.c + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + UnitTestFrameworkPkg/UnitTestFrameworkPkg.dec + +[LibraryClasses] + UefiApplicationEntryPoint + BaseLib + UnitTestLib + UnitTestBootLib + PrintLib + UefiBootServicesTableLib + UefiRuntimeServicesTableLib + MemoryAllocationLib + VariablePolicyHelperLib + +[Protocols] + gEdkiiVariablePolicyProtocolGuid --=20 2.26.2.windows.1.8.g01c50adf56.20200515075929 -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#60540): https://edk2.groups.io/g/devel/message/60540 Mute This Topic: https://groups.io/mt/74609742/1787277 Group Owner: devel+owner@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [importer@patchew.org] -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-