From nobody Mon Feb 9 04:59:36 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+64726+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+64726+1787277+3901457@groups.io ARC-Seal: i=1; a=rsa-sha256; t=1598593928; cv=none; d=zohomail.com; s=zohoarc; b=lpPgNw5Ulx68C11it7p/iZzNpK3xWnW3drruvpW3xQSzsudv3rV38+feiLCGZvUZwfmrukch2mTPzTWNBK9XcqawjLZopWPruC472+lfgcByWDfk/Cf2A2JAHxnuELDcBsAcEBc6ydDWp1ihFrEnrknMgml/QIMwJ79Vty+B2wA= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1598593928; 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=rlARunM8f1v1XRGCzPio53aiDDdWy1KVQuyKBGAc0XA=; b=LZBMRMpEye7p6iZsGJhnz1tkByphq4kB/KbAZd7dAov5zP7AeE0oaqaHKpuSThcMO7/33iLDE+ewBmft/KUr5aLUwzecuvasBxBvZ3C+NHSls20fMWBypl0MxKHIERBxgAgHL51SZeQAIlT7yrTbcxEmtQ+IKChEp8KYJO7wbcE= 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+64726+1787277+3901457@groups.io Received: from web01.groups.io (web01.groups.io [66.175.222.12]) by mx.zohomail.com with SMTPS id 1598593928055140.0991271313128; Thu, 27 Aug 2020 22:52:08 -0700 (PDT) Return-Path: X-Received: by 127.0.0.2 with SMTP id YWKKYY1788612x6i7IzDFSe1; Thu, 27 Aug 2020 22:52:07 -0700 X-Received: from mail-pj1-f51.google.com (mail-pj1-f51.google.com [209.85.216.51]) by mx.groups.io with SMTP id smtpd.web12.37097.1598593927052755127 for ; Thu, 27 Aug 2020 22:52:07 -0700 X-Received: by mail-pj1-f51.google.com with SMTP id mt12so32882pjb.4 for ; Thu, 27 Aug 2020 22:52:07 -0700 (PDT) X-Gm-Message-State: 3Vl64ZiCgJSROTUYqq5tBum6x1787277AA= X-Google-Smtp-Source: ABdhPJxZo3aQp9heRivMPvE2RLkF9qOyJf+gCzgGWZZsgHcTsFvkrboPtcq6qEq+zVg8cutq7Fnkog== X-Received: by 2002:a17:902:ab96:: with SMTP id f22mr53119plr.292.1598593925455; Thu, 27 Aug 2020 22:52:05 -0700 (PDT) X-Received: from localhost.localdomain (174-21-132-206.tukw.qwest.net. [174.21.132.206]) by smtp.gmail.com with ESMTPSA id fz19sm41802pjb.40.2020.08.27.22.52.03 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 27 Aug 2020 22:52:04 -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 v7 14/14] MdeModulePkg: Add a shell-based functional test for VariablePolicy Date: Thu, 27 Aug 2020 22:51:27 -0700 Message-Id: <20200828055127.1610-15-brbarkel@microsoft.com> In-Reply-To: <20200828055127.1610-1-brbarkel@microsoft.com> References: <20200828055127.1610-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=1598593927; bh=L/Er6D1NVkhT9RZw5NPEq5fu5MJJ2ozsog1vShvHADw=; h=Cc:Date:From:Reply-To:Subject:To; b=STCDByykRkt0Xpfmae73n2AvJEXa0ujnc8irbM1Ry0DOjhp1REqEf/DA4CxBm90Gd4J T9/2b3uMgznunYp8Jihd88xGix1LHDE5wFLEVMYz0O334jsE1V2aMXJ747T7aadHgNQU5 M+llwIzaddxt9yZwMx8mPm3y4n0pICbiwJ0= 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 | 2226 ++++++++++++++++++++ MdeModulePkg/MdeModulePkg.ci.yaml = | 4 +- MdeModulePkg/Test/ShellTest/VariablePolicyFuncTestApp/Readme.md = | 55 + MdeModulePkg/Test/ShellTest/VariablePolicyFuncTestApp/VariablePolicyFuncTe= stApp.inf | 47 + MdeModulePkg/Test/ShellTest/VariablePolicyFuncTestApp/VariablePolicyTestAu= thVar.h | 128 ++ 5 files changed, 2459 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..c2b28e4b642b --- /dev/null +++ b/MdeModulePkg/Test/ShellTest/VariablePolicyFuncTestApp/VariablePolicyF= uncTestApp.c @@ -0,0 +1,2226 @@ +/** @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 +#include + +#include "VariablePolicyTestAuthVar.h" + +// 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 } }; + +#define TEST_AUTH_VAR_NAME L"DummyAuthVar" +EFI_GUID mTestAuthNamespaceGuid =3D { 0xb6c5a2c6, 0x3ece, 0x4b9b, { 0x8c, = 0xc8, 0x96, 0xd8, 0xd9, 0xca, 0xd3, 0x4e } }; + +/** + 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 + +UNIT_TEST_STATUS +EFIAPI +VarPolicyEnabledPreReq ( + IN UNIT_TEST_CONTEXT Context + ) +{ + EFI_STATUS Status; + BOOLEAN State; + + UT_ASSERT_EQUAL(LocateVarPolicyPreReq(Context), UNIT_TEST_PASSED); + Status =3D mVarPol->IsVariablePolicyEnabled (&State); + UT_ASSERT_NOT_EFI_ERROR(Status); + UT_ASSERT_TRUE(State); + + return UNIT_TEST_PASSED; +} + +UNIT_TEST_STATUS +EFIAPI +VarPolicyDisabledPreReq ( + IN UNIT_TEST_CONTEXT Context + ) +{ + EFI_STATUS Status; + BOOLEAN State; + + UT_ASSERT_EQUAL(LocateVarPolicyPreReq(Context), UNIT_TEST_PASSED); + Status =3D mVarPol->IsVariablePolicyEnabled (&State); + UT_ASSERT_NOT_EFI_ERROR(Status); + UT_ASSERT_FALSE(State); + + return UNIT_TEST_PASSED; +} + +/** + Getting Started tests. +**/ +UNIT_TEST_STATUS +EFIAPI +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 +EFIAPI +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 + +/** + NOTE: Copied from SecureBootConfigImpl.c, then modified. + + Create a time based data payload by concatenating the EFI_VARIABLE_AUTHE= NTICATION_2 + descriptor with the input data. NO authentication is required in this fu= nction. + + @param[in, out] DataSize On input, the size of Data buffer in by= tes. + On output, the size of data returned in= Data + buffer in bytes. + @param[in, out] Data On input, Pointer to data buffer to be = wrapped or + pointer to NULL to wrap an empty payloa= d. + On output, Pointer to the new payload d= ate buffer allocated from pool, + it's caller's responsibility to free th= e memory when finish using it. + @param[in] Time [Optional] If provided, will be used as= the timestamp for the payload. + If NULL, a new timestamp will be genera= ted using GetTime(). + + @retval EFI_SUCCESS Create time based payload successfully. + @retval EFI_OUT_OF_RESOURCES There are not enough memory resources t= o create time based payload. + @retval EFI_INVALID_PARAMETER The parameter is invalid. + @retval Others Unexpected error happens. + +**/ +STATIC +EFI_STATUS +CreateEmptyTimeBasedPayload ( + IN OUT UINTN *DataSize, + IN OUT UINT8 **Data, + IN EFI_TIME *Time OPTIONAL + ) +{ + UINT8 *NewData; + UINT8 *Payload; + UINTN PayloadSize; + EFI_VARIABLE_AUTHENTICATION_2 *DescriptorData; + UINTN DescriptorSize; + EFI_TIME NewTime; + + if (Data =3D=3D NULL || DataSize =3D=3D NULL) { + DEBUG((DEBUG_ERROR, "CreateEmptyTimeBasedPayload(), invalid arg\n")); + return EFI_INVALID_PARAMETER; + } + + // + // In Setup mode or Custom mode, the variable does not need to be signed= but the + // parameters to the SetVariable() call still need to be prepared as aut= henticated + // variable. So we create EFI_VARIABLE_AUTHENTICATED_2 descriptor withou= t certificate + // data in it. + // + Payload =3D *Data; + PayloadSize =3D *DataSize; + + DescriptorSize =3D OFFSET_OF (EFI_VARIABLE_AUTHENTICATION_2, AuthInfo= ) + OFFSET_OF (WIN_CERTIFICATE_UEFI_GUID, CertData); + NewData =3D (UINT8*) AllocateZeroPool (DescriptorSize + PayloadSize); + if (NewData =3D=3D NULL) { + DEBUG((DEBUG_ERROR, "CreateEmptyTimeBasedPayload() Out of resources.\n= ")); + return EFI_OUT_OF_RESOURCES; + } + + if ((Payload !=3D NULL) && (PayloadSize !=3D 0)) { + CopyMem (NewData + DescriptorSize, Payload, PayloadSize); + } + + DescriptorData =3D (EFI_VARIABLE_AUTHENTICATION_2 *) (NewData); + + // + // Use or create the timestamp. + // + // If Time is NULL, create a new timestamp. + if (Time =3D=3D NULL) + { + NewTime.Year =3D 9999; + NewTime.Month =3D 12; + NewTime.Day =3D 31; + NewTime.Hour =3D 23; + NewTime.Minute =3D 59; + NewTime.Second =3D 59; + NewTime.Pad1 =3D 0; + NewTime.Nanosecond =3D 0; + NewTime.TimeZone =3D 0; + NewTime.Daylight =3D 0; + NewTime.Pad2 =3D 0; + Time =3D &NewTime; // Use the new timestamp. + } + CopyMem (&DescriptorData->TimeStamp, Time, sizeof (EFI_TIME)); + + DescriptorData->AuthInfo.Hdr.dwLength =3D OFFSET_OF (WIN_CERTIFI= CATE_UEFI_GUID, CertData); + DescriptorData->AuthInfo.Hdr.wRevision =3D 0x0200; + DescriptorData->AuthInfo.Hdr.wCertificateType =3D WIN_CERT_TYPE_EFI_GUID; + CopyGuid (&DescriptorData->AuthInfo.CertType, &gEfiCertPkcs7Guid); + + if (Payload !=3D NULL) { + FreePool(Payload); + } + + *DataSize =3D DescriptorSize + PayloadSize; + *Data =3D NewData; + return EFI_SUCCESS; +} + +/** + NoLock Policy tests. +**/ +UNIT_TEST_STATUS +EFIAPI +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 +EFIAPI +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 +EFIAPI +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 +EFIAPI +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 +EFIAPI +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 +EFIAPI +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 +EFIAPI +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 +EFIAPI +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 +EFIAPI +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 +EFIAPI +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 +EFIAPI +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 +EFIAPI +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 +EFIAPI +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 +EFIAPI +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 +EFIAPI +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 +EFIAPI +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 +EFIAPI +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 +EFIAPI +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 +EFIAPI +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 +EFIAPI +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 +EFIAPI +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 +EFIAPI +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 +EFIAPI +SaveStateAndReboot ( + VOID + ) +{ + EFI_STATUS Status; + + // + // Now, save all the data associated with this framework. + // TODO: Need to add to the UnitTestFrameworkPkg + Status =3D SaveFrameworkState( 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 + +STATIC +VOID +IgnoreContextAndReboot ( + IN UNIT_TEST_CONTEXT Context + ) +{ + // Just a wrapper for prototype reuse. + SaveStateAndReboot(); +} + +/** + Disable policy tests. +**/ +UNIT_TEST_STATUS +EFIAPI +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 + +// +// Pre-Disable Setup and Test for Authenticated Variables +// +UNIT_TEST_STATUS +TestAuthVarPart1 ( + IN UNIT_TEST_CONTEXT Context + ) +{ + EFI_STATUS Status; + UINT32 Data; + UINTN DataSize; + UINT8 *DeleteData; + + // First, we need to create our dummy Authenticated Variable. + Status =3D gRT->SetVariable(TEST_AUTH_VAR_NAME, + &mTestAuthNamespaceGuid, + (EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOT= SERVICE_ACCESS | + EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_T= IME_BASED_AUTHENTICATED_WRITE_ACCESS), + mTestAuthVarPayloadSize, + &mTestAuthVarPayload[0]); + UT_ASSERT_NOT_EFI_ERROR(Status); + + // Prove that we created it. + DataSize =3D sizeof(Data); + Status =3D gRT->GetVariable(TEST_AUTH_VAR_NAME, + &mTestAuthNamespaceGuid, + NULL, + &DataSize, + &Data); + UT_ASSERT_NOT_EFI_ERROR(Status); + UT_ASSERT_EQUAL(Data, 0xDEADBEEF); + + // Prove that we cannot delete it. + DeleteData =3D NULL; + DataSize =3D 0; + Status =3D CreateEmptyTimeBasedPayload(&DataSize, &DeleteData, NULL); + UT_ASSERT_NOT_EFI_ERROR(Status); + Status =3D gRT->SetVariable(TEST_AUTH_VAR_NAME, + &mTestAuthNamespaceGuid, + (EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOT= SERVICE_ACCESS | + EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_T= IME_BASED_AUTHENTICATED_WRITE_ACCESS), + DataSize, + (VOID*)DeleteData); + UT_ASSERT_STATUS_EQUAL(Status, EFI_SECURITY_VIOLATION); + FreePool(DeleteData); + + return UNIT_TEST_PASSED; +} + +// +// Post-Disable Test for Authenticated Variables +// +UNIT_TEST_STATUS +TestAuthVarPart2 ( + IN UNIT_TEST_CONTEXT Context + ) +{ + EFI_STATUS Status; + UINT32 Data; + UINTN DataSize; + UINT8 *DeleteData; + + // Prove that it exists. + DataSize =3D sizeof(Data); + Status =3D gRT->GetVariable(TEST_AUTH_VAR_NAME, + &mTestAuthNamespaceGuid, + NULL, + &DataSize, + &Data); + UT_ASSERT_NOT_EFI_ERROR(Status); + UT_ASSERT_EQUAL(Data, 0xDEADBEEF); + + // Prove that we can delete it. + DeleteData =3D NULL; + DataSize =3D 0; + Status =3D CreateEmptyTimeBasedPayload(&DataSize, &DeleteData, NULL); + UT_ASSERT_NOT_EFI_ERROR(Status); + Status =3D gRT->SetVariable(TEST_AUTH_VAR_NAME, + &mTestAuthNamespaceGuid, + (EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOT= SERVICE_ACCESS | + EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_T= IME_BASED_AUTHENTICATED_WRITE_ACCESS), + DataSize, + (VOID*)DeleteData); + UT_ASSERT_NOT_EFI_ERROR(Status); + FreePool(DeleteData); + + // Prove that we deleted it. + DataSize =3D sizeof(Data); + Status =3D gRT->GetVariable(TEST_AUTH_VAR_NAME, + &mTestAuthNamespaceGuid, + NULL, + &DataSize, + &Data); + UT_ASSERT_STATUS_EQUAL(Status, EFI_NOT_FOUND); + + return UNIT_TEST_PASSED; +} + +/** + Final Cleanup: delete some variables earlier test cases created. +**/ +STATIC +VOID +EFIAPI +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 +EFIAPI +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; + 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, IgnoreContextAndReboot, 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 AuthVar protection while Vari= ablePolicy is enabled", "Common.VP.DisablePolicyTests.TestAuthVar1", TestAu= thVarPart1, VarPolicyEnabledPreReq, NULL, NULL); + AddTestCase (DisablePolicyTestSuite, "Test disabling policy", "Common.VP= .DisablePolicyTests.DisablePolicyEngineTests", DisablePolicyEngineTests, Lo= cateVarPolicyPreReq, NULL, NULL); + AddTestCase (DisablePolicyTestSuite, "Test AuthVar protection while Vari= ablePolicy is disabled", "Common.VP.DisablePolicyTests.TestAuthVar2", TestA= uthVarPart2, VarPolicyDisabledPreReq, 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 20d53fc5a5fa..a1beee9f4aab 100644 --- a/MdeModulePkg/MdeModulePkg.ci.yaml +++ b/MdeModulePkg/MdeModulePkg.ci.yaml @@ -53,7 +53,9 @@ "UnitTestFrameworkPkg/UnitTestFrameworkPkg.dec" ], # For UEFI shell based apps - "AcceptableDependencies-UEFI_APPLICATION":[], + "AcceptableDependencies-UEFI_APPLICATION":[ + "UnitTestFrameworkPkg/UnitTestFrameworkPkg.dec" + ], "IgnoreInf": [] }, =20 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..bfbac406b504 --- /dev/null +++ b/MdeModulePkg/Test/ShellTest/VariablePolicyFuncTestApp/VariablePolicyF= uncTestApp.inf @@ -0,0 +1,47 @@ +## @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 + VariablePolicyTestAuthVar.h + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + UnitTestFrameworkPkg/UnitTestFrameworkPkg.dec + +[LibraryClasses] + UefiApplicationEntryPoint + BaseLib + BaseMemoryLib + UnitTestLib + UnitTestBootLib + PrintLib + UefiBootServicesTableLib + UefiRuntimeServicesTableLib + MemoryAllocationLib + VariablePolicyHelperLib + +[Guids] + gEfiCertPkcs7Guid + +[Protocols] + gEdkiiVariablePolicyProtocolGuid diff --git a/MdeModulePkg/Test/ShellTest/VariablePolicyFuncTestApp/Variable= PolicyTestAuthVar.h b/MdeModulePkg/Test/ShellTest/VariablePolicyFuncTestApp= /VariablePolicyTestAuthVar.h new file mode 100644 index 000000000000..c90310226827 --- /dev/null +++ b/MdeModulePkg/Test/ShellTest/VariablePolicyFuncTestApp/VariablePolicyT= estAuthVar.h @@ -0,0 +1,128 @@ +/** @file -- VarPolicyTestAuthVar.h +Payload to be used to create an Authenticated Variable for testing. + +Copyright (c) Microsoft Corporation. +SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef _VAR_POLICY_TEST_AUTH_VAR_H_ +#define _VAR_POLICY_TEST_AUTH_VAR_H_ + +UINT8 mTestAuthVarPayload[] =3D { + // EFI_VARIABLE_AUTHENTICATION_2 + // Timestamp + 0xE4, 0x07, 0x08, 0x15, 0x0D, 0x1E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, = 0x00, 0x00, 0x00, 0x00, + // AuthInfo (WIN_CERTIFICATE_UEFI_GUID) + // Hdr (WIN_CERTIFICATE) + // dwLength + 0x45, 0x05, 0x00, 0x00, + // wRevision + 0x00, 0x02, + // wCertificateType + // (WIN_CERT_TYPE_EFI_GUID) + 0xF1, 0x0E, + // CertType + // (gEfiCertPkcs7Guid) + 0x9D, 0xD2, 0xAF, 0x4A, 0xDF, 0x68, 0xEE, 0x49, 0x8A, 0xA9, 0x34, 0x7D, = 0x37, 0x56, 0x65, 0xA7, + // CertData (Packed SignedData Signature) + // Digest Buffer Was... + // Name (DummyAuthVar) + // 44 00 75 00 6D 00 6D 00 79 00 41 00 75 00 74 00 68 00 56 00 61= 00 72 00 + // Vendor Guid (mTestAuthNamespaceGuid) + // C6 A2 C5 B6 CE 3E 9B 4B 8C C8 96 D8 D9 CA D3 4E + // Attributes (NV + BS + RT, TimeAuth) + // 27 00 00 00 + // Timestamp + // E4 07 08 15 0D 1E 00 00 00 00 00 00 00 00 00 00 + // Data (0xDEADBEEF) + // EF BE AD DE + 0x30, 0x82, 0x05, 0x29, 0x02, 0x01, 0x01, 0x31, 0x0F, 0x30, 0x0D, 0x06, = 0x09, 0x60, 0x86, 0x48, + 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0x30, 0x0B, 0x06, 0x09, = 0x2A, 0x86, 0x48, 0x86, + 0xF7, 0x0D, 0x01, 0x07, 0x01, 0xA0, 0x82, 0x03, 0x82, 0x30, 0x82, 0x03, = 0x7E, 0x30, 0x82, 0x02, + 0x66, 0xA0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x10, 0x5A, 0xAE, 0x85, 0xA8, = 0x61, 0x6E, 0x80, 0xA3, + 0x4D, 0x11, 0x69, 0x06, 0xC3, 0xFE, 0x2D, 0x89, 0x30, 0x0D, 0x06, 0x09, = 0x2A, 0x86, 0x48, 0x86, + 0xF7, 0x0D, 0x01, 0x01, 0x0B, 0x05, 0x00, 0x30, 0x3F, 0x31, 0x3D, 0x30, = 0x3B, 0x06, 0x03, 0x55, + 0x04, 0x03, 0x1E, 0x34, 0x00, 0x50, 0x00, 0x41, 0x00, 0x4C, 0x00, 0x49, = 0x00, 0x4E, 0x00, 0x44, + 0x00, 0x52, 0x00, 0x4F, 0x00, 0x4D, 0x00, 0x45, 0x00, 0x5F, 0x00, 0x53, = 0x00, 0x65, 0x00, 0x6C, + 0x00, 0x66, 0x00, 0x68, 0x00, 0x6F, 0x00, 0x73, 0x00, 0x74, 0x00, 0x5F, = 0x00, 0x53, 0x00, 0x69, + 0x00, 0x67, 0x00, 0x6E, 0x00, 0x65, 0x00, 0x72, 0x30, 0x20, 0x17, 0x0D, = 0x30, 0x30, 0x30, 0x31, + 0x30, 0x31, 0x30, 0x37, 0x30, 0x30, 0x30, 0x30, 0x5A, 0x18, 0x0F, 0x32, = 0x39, 0x39, 0x39, 0x31, + 0x32, 0x33, 0x31, 0x30, 0x37, 0x30, 0x30, 0x30, 0x30, 0x5A, 0x30, 0x3F, = 0x31, 0x3D, 0x30, 0x3B, + 0x06, 0x03, 0x55, 0x04, 0x03, 0x1E, 0x34, 0x00, 0x50, 0x00, 0x41, 0x00, = 0x4C, 0x00, 0x49, 0x00, + 0x4E, 0x00, 0x44, 0x00, 0x52, 0x00, 0x4F, 0x00, 0x4D, 0x00, 0x45, 0x00, = 0x5F, 0x00, 0x53, 0x00, + 0x65, 0x00, 0x6C, 0x00, 0x66, 0x00, 0x68, 0x00, 0x6F, 0x00, 0x73, 0x00, = 0x74, 0x00, 0x5F, 0x00, + 0x53, 0x00, 0x69, 0x00, 0x67, 0x00, 0x6E, 0x00, 0x65, 0x00, 0x72, 0x30, = 0x82, 0x01, 0x22, 0x30, + 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x01, = 0x05, 0x00, 0x03, 0x82, + 0x01, 0x0F, 0x00, 0x30, 0x82, 0x01, 0x0A, 0x02, 0x82, 0x01, 0x01, 0x00, = 0xC9, 0xA2, 0x80, 0xE7, + 0x3A, 0x0B, 0x3E, 0xCF, 0xEE, 0x0E, 0x22, 0x65, 0xF5, 0x03, 0xD2, 0x6A, = 0x99, 0xBF, 0x5F, 0x48, + 0xF4, 0xC0, 0xD3, 0x19, 0xE7, 0x6B, 0x09, 0xFC, 0x0C, 0xB0, 0x3B, 0x69, = 0x3A, 0x07, 0x6F, 0x36, + 0x57, 0xF6, 0x63, 0xAF, 0x6B, 0x7B, 0x30, 0x55, 0xD5, 0xE9, 0xF4, 0xDE, = 0x89, 0xE3, 0x5F, 0xA1, + 0x71, 0x13, 0x3E, 0x84, 0x5D, 0x46, 0x9F, 0x78, 0xA9, 0x5B, 0xA5, 0x46, = 0x3B, 0x38, 0x4F, 0x00, + 0x06, 0x63, 0x0E, 0x7A, 0x0A, 0x93, 0xE7, 0x36, 0x87, 0xCC, 0x47, 0xBD, = 0xFB, 0x0A, 0x5D, 0x45, + 0x9C, 0xC4, 0x1B, 0xE6, 0x9E, 0xCB, 0xAB, 0xF9, 0x20, 0x11, 0xEF, 0x03, = 0xCA, 0x9F, 0xE9, 0x29, + 0x1A, 0x05, 0xF8, 0xB3, 0x46, 0xB0, 0x3D, 0xFD, 0x88, 0x7C, 0x82, 0x0E, = 0x3C, 0x6F, 0xEA, 0x5B, + 0xFF, 0xA8, 0xA4, 0xE0, 0x40, 0x2B, 0x25, 0xE8, 0x59, 0x46, 0xEE, 0xDB, = 0x4B, 0x5F, 0x02, 0xB3, + 0x21, 0x33, 0x47, 0x2E, 0xD5, 0x66, 0x79, 0xF3, 0x79, 0x93, 0x18, 0x75, = 0x94, 0x4A, 0x01, 0xCF, + 0x59, 0x86, 0xF4, 0x8B, 0x35, 0xBD, 0xA4, 0x58, 0xA4, 0x76, 0x89, 0x77, = 0x55, 0x55, 0xB1, 0xE4, + 0x00, 0x09, 0x78, 0xF3, 0x29, 0x5B, 0xC0, 0xED, 0xD6, 0x68, 0x7E, 0xDB, = 0xAA, 0x9F, 0x4E, 0xFE, + 0x67, 0x41, 0x4E, 0x6C, 0xC8, 0xDD, 0x52, 0xD6, 0xA5, 0x8A, 0x8A, 0x56, = 0x50, 0x51, 0x27, 0x29, + 0x2B, 0xD3, 0x1B, 0x4D, 0xCE, 0x93, 0x76, 0x8E, 0x55, 0x53, 0x55, 0x30, = 0x10, 0xF5, 0xF9, 0x6C, + 0xAE, 0xDA, 0xBA, 0xAC, 0x36, 0x79, 0x11, 0x02, 0xD0, 0x24, 0x07, 0xA6, = 0xD1, 0x56, 0xCB, 0xEC, + 0x81, 0x29, 0xA8, 0xC1, 0x2E, 0x9D, 0x9B, 0xF9, 0xE9, 0xF4, 0x55, 0x74, = 0xA0, 0x52, 0x87, 0x49, + 0x4F, 0xAC, 0x71, 0xFF, 0x30, 0x12, 0x24, 0xDD, 0x6D, 0x50, 0x5C, 0x7D, = 0x02, 0x03, 0x01, 0x00, + 0x01, 0xA3, 0x74, 0x30, 0x72, 0x30, 0x70, 0x06, 0x03, 0x55, 0x1D, 0x01, = 0x04, 0x69, 0x30, 0x67, + 0x80, 0x10, 0x0E, 0xB2, 0xFB, 0xDC, 0xD5, 0xAB, 0xCC, 0xB4, 0x3B, 0x46, = 0x1B, 0x60, 0x18, 0xFD, + 0xDE, 0x74, 0xA1, 0x41, 0x30, 0x3F, 0x31, 0x3D, 0x30, 0x3B, 0x06, 0x03, = 0x55, 0x04, 0x03, 0x1E, + 0x34, 0x00, 0x50, 0x00, 0x41, 0x00, 0x4C, 0x00, 0x49, 0x00, 0x4E, 0x00, = 0x44, 0x00, 0x52, 0x00, + 0x4F, 0x00, 0x4D, 0x00, 0x45, 0x00, 0x5F, 0x00, 0x53, 0x00, 0x65, 0x00, = 0x6C, 0x00, 0x66, 0x00, + 0x68, 0x00, 0x6F, 0x00, 0x73, 0x00, 0x74, 0x00, 0x5F, 0x00, 0x53, 0x00, = 0x69, 0x00, 0x67, 0x00, + 0x6E, 0x00, 0x65, 0x00, 0x72, 0x82, 0x10, 0x5A, 0xAE, 0x85, 0xA8, 0x61, = 0x6E, 0x80, 0xA3, 0x4D, + 0x11, 0x69, 0x06, 0xC3, 0xFE, 0x2D, 0x89, 0x30, 0x0D, 0x06, 0x09, 0x2A, = 0x86, 0x48, 0x86, 0xF7, + 0x0D, 0x01, 0x01, 0x0B, 0x05, 0x00, 0x03, 0x82, 0x01, 0x01, 0x00, 0xB5, = 0xA2, 0xD0, 0x1B, 0x70, + 0x24, 0xC2, 0xE8, 0x64, 0xCD, 0xF1, 0xE9, 0x97, 0x9E, 0xA7, 0xC1, 0x86, = 0x92, 0x06, 0x2F, 0x8F, + 0x33, 0x64, 0x0A, 0xB9, 0x2B, 0x77, 0xE2, 0x70, 0x82, 0xDE, 0x06, 0xD3, = 0x69, 0x8E, 0xB4, 0x69, + 0xF1, 0x6B, 0x59, 0x5E, 0x68, 0x5F, 0xB4, 0xFA, 0x30, 0xC3, 0xB6, 0xA1, = 0x72, 0x1A, 0xD4, 0x01, + 0xED, 0x69, 0x4A, 0x96, 0x0F, 0x1C, 0xC3, 0x6F, 0x80, 0x0B, 0xE5, 0xD4, = 0x46, 0xBE, 0x27, 0x9D, + 0xDE, 0x68, 0xB3, 0xA1, 0x93, 0xC3, 0x1A, 0x47, 0x20, 0x7A, 0x87, 0x80, = 0x13, 0x85, 0x1E, 0x46, + 0x01, 0x42, 0x6A, 0x68, 0x46, 0xE2, 0x77, 0x3D, 0x2E, 0x50, 0xA1, 0x96, = 0x23, 0x83, 0x03, 0xD1, + 0x57, 0xDD, 0xC6, 0x63, 0x59, 0xB7, 0x1A, 0x49, 0xA2, 0xC9, 0x44, 0x8D, = 0xC7, 0x81, 0x18, 0xE8, + 0x52, 0x3A, 0x74, 0x32, 0xD3, 0xE6, 0x6D, 0x54, 0x9F, 0xC9, 0x87, 0x1C, = 0xBC, 0x81, 0xEB, 0x6D, + 0x5D, 0x58, 0xF7, 0x91, 0x81, 0x5B, 0xB0, 0x86, 0xB4, 0x06, 0xE7, 0x19, = 0x44, 0xE9, 0x24, 0x28, + 0xF5, 0x42, 0x7A, 0x7A, 0x28, 0x94, 0x3E, 0x70, 0x61, 0x1B, 0x68, 0x8D, = 0xA9, 0x48, 0x3A, 0xFE, + 0x7D, 0xB5, 0x29, 0x10, 0xCE, 0xD6, 0xC1, 0xFF, 0x16, 0xDF, 0x90, 0x94, = 0x16, 0xC8, 0xFA, 0x9E, + 0x52, 0x49, 0xE5, 0xC3, 0xF5, 0x8C, 0x87, 0xC2, 0x93, 0x3D, 0x3D, 0x27, = 0x23, 0x37, 0xC3, 0xDA, + 0x55, 0x92, 0x12, 0xE9, 0x1F, 0xEB, 0x32, 0xB5, 0xD8, 0x30, 0xD6, 0xC0, = 0x23, 0x45, 0xBB, 0x06, + 0xBC, 0x11, 0xA6, 0xA3, 0x47, 0x82, 0x04, 0xCB, 0xAA, 0x98, 0xCA, 0xF9, = 0x00, 0x0E, 0xD3, 0xC3, + 0x09, 0xF6, 0x21, 0x4C, 0x90, 0xE0, 0x78, 0x08, 0xAE, 0x8F, 0xB1, 0x7D, = 0x62, 0x3F, 0x6A, 0x1E, + 0xD6, 0xF1, 0x8E, 0xEE, 0xFD, 0x49, 0x04, 0xDE, 0x14, 0x9C, 0x7B, 0x31, = 0x82, 0x01, 0x7E, 0x30, + 0x82, 0x01, 0x7A, 0x02, 0x01, 0x01, 0x30, 0x53, 0x30, 0x3F, 0x31, 0x3D, = 0x30, 0x3B, 0x06, 0x03, + 0x55, 0x04, 0x03, 0x1E, 0x34, 0x00, 0x50, 0x00, 0x41, 0x00, 0x4C, 0x00, = 0x49, 0x00, 0x4E, 0x00, + 0x44, 0x00, 0x52, 0x00, 0x4F, 0x00, 0x4D, 0x00, 0x45, 0x00, 0x5F, 0x00, = 0x53, 0x00, 0x65, 0x00, + 0x6C, 0x00, 0x66, 0x00, 0x68, 0x00, 0x6F, 0x00, 0x73, 0x00, 0x74, 0x00, = 0x5F, 0x00, 0x53, 0x00, + 0x69, 0x00, 0x67, 0x00, 0x6E, 0x00, 0x65, 0x00, 0x72, 0x02, 0x10, 0x5A, = 0xAE, 0x85, 0xA8, 0x61, + 0x6E, 0x80, 0xA3, 0x4D, 0x11, 0x69, 0x06, 0xC3, 0xFE, 0x2D, 0x89, 0x30, = 0x0D, 0x06, 0x09, 0x60, + 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0x30, 0x0D, = 0x06, 0x09, 0x2A, 0x86, + 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x01, 0x05, 0x00, 0x04, 0x82, 0x01, = 0x00, 0xA6, 0x06, 0xE7, + 0x46, 0x7E, 0xFB, 0x4A, 0xA7, 0x25, 0x2F, 0x52, 0x1D, 0xBC, 0x5C, 0x41, = 0x3B, 0xD3, 0x13, 0x50, + 0xCE, 0x5F, 0xE2, 0x4B, 0x31, 0xED, 0x28, 0x5E, 0xF5, 0x36, 0xBD, 0x1C, = 0x38, 0xA1, 0xB6, 0x45, + 0x7C, 0xFD, 0xAB, 0x7B, 0x0C, 0xBF, 0x06, 0x06, 0xBB, 0x95, 0x5E, 0x47, = 0x10, 0x7C, 0xD8, 0x10, + 0x76, 0x74, 0x81, 0x2D, 0x40, 0x3A, 0xD0, 0xF4, 0x15, 0x9D, 0xDF, 0x44, = 0x2B, 0xA4, 0xCD, 0xF7, + 0x44, 0x77, 0x9F, 0x35, 0x46, 0xD3, 0x30, 0x67, 0x44, 0x33, 0xF4, 0x7B, = 0xB6, 0xC0, 0xE4, 0xA2, + 0xAD, 0xDF, 0xAF, 0x56, 0x41, 0xA3, 0x0D, 0x76, 0x36, 0xB9, 0x7E, 0x29, = 0x49, 0x17, 0x43, 0xAF, + 0xB0, 0xA0, 0xC0, 0xF1, 0xE1, 0xE6, 0xCA, 0x62, 0x9F, 0x3E, 0x9D, 0x6C, = 0x63, 0x03, 0xF6, 0xDF, + 0x84, 0x32, 0xB1, 0x01, 0x0C, 0x12, 0x83, 0x52, 0x13, 0x2F, 0xAE, 0xBC, = 0x79, 0xB7, 0x75, 0xF6, + 0x10, 0x20, 0xFC, 0x7A, 0x13, 0x92, 0xF7, 0x87, 0x50, 0xF5, 0x9C, 0xD9, = 0xE4, 0xEA, 0x4C, 0x3D, + 0x31, 0xED, 0x7F, 0xA6, 0x6C, 0x58, 0xAD, 0x6C, 0x31, 0xAF, 0xC4, 0x64, = 0xAE, 0x11, 0xBF, 0x72, + 0xF5, 0xAA, 0x69, 0xB4, 0x76, 0xDB, 0x73, 0x8F, 0x8C, 0x3E, 0x23, 0x4A, = 0x2D, 0xB7, 0x65, 0x65, + 0x10, 0xA8, 0xC6, 0x52, 0x14, 0xE2, 0xC6, 0x2B, 0x07, 0xCE, 0x45, 0x58, = 0x6F, 0x92, 0x78, 0xAA, + 0xB5, 0xE9, 0x76, 0x39, 0x8A, 0x17, 0xE3, 0x0B, 0xA5, 0x12, 0x0F, 0x2A, = 0xC1, 0xCE, 0xC5, 0x4F, + 0xD8, 0xA7, 0xD1, 0x7C, 0x3F, 0xE3, 0x23, 0x9B, 0x53, 0x56, 0x18, 0x28, = 0x66, 0xC7, 0xB3, 0x04, + 0x38, 0xE3, 0x40, 0xCC, 0xB2, 0x18, 0xA8, 0xC7, 0x11, 0xE1, 0x67, 0xD8, = 0xBF, 0xBE, 0x8D, 0x2A, + 0x75, 0x00, 0x96, 0x8F, 0x7F, 0x80, 0xCF, 0xDB, 0xF0, 0x0D, 0xB5, 0x8D, = 0x73, + // Data + 0xEF, 0xBE, 0xAD, 0xDE +}; +UINTN mTestAuthVarPayloadSize =3D sizeof(mTestAuthVarPayload); + +#endif // _VAR_POLICY_TEST_AUTH_VAR_H_ --=20 2.28.0.windows.1 -=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 (#64726): https://edk2.groups.io/g/devel/message/64726 Mute This Topic: https://groups.io/mt/76468140/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-