From: Michael Kubacki <michael.kuba...@microsoft.com> Introduces two new APIs to EDKII_VARIABLE_POLICY_PROTOCOL: 1. GetVariablePolicyInfo() 2. GetLockOnVariableStateVariablePolicyInfo()
These allow a caller to retrieve policy information associated with a UEFI variable given the variable name and vendor GUID. GetVariablePolicyInfo() - Returns the variable policy applied to the UEFI variable. If the variable policy is applied toward an individual UEFI variable, that name can optionally be returned. GetLockOnVariableStateVariablePolicyInfo() - Returns the Lock on Variable State policy applied to the UEFI variable. If the Lock on Variable State policy is applied to a specific variable name, that name can optionally be returned. These functions can be useful for a variety of purposes such as auditing, testing, and functional flows. Also fixed some variable name typos in code touched by the changes. Cc: Dandan Bi <dandan...@intel.com> Cc: Hao A Wu <hao.a...@intel.com> Cc: Jian J Wang <jian.j.w...@intel.com> Cc: Liming Gao <gaolim...@byosoft.com.cn> Signed-off-by: Michael Kubacki <michael.kuba...@microsoft.com> --- MdeModulePkg/Library/VarCheckPolicyLib/VarCheckPolicyLib.c | 174 ++++++++-- MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLib.c | 304 +++++++++++++++++ MdeModulePkg/Universal/Variable/RuntimeDxe/VariableDxe.c | 4 +- MdeModulePkg/Universal/Variable/RuntimeDxe/VariablePolicySmmDxe.c | 346 +++++++++++++++++++- MdeModulePkg/Include/Guid/VarCheckPolicyMmi.h | 39 ++- MdeModulePkg/Include/Library/VariablePolicyLib.h | 107 ++++++ MdeModulePkg/Include/Protocol/VariablePolicy.h | 133 +++++++- MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLib.inf | 1 + 8 files changed, 1062 insertions(+), 46 deletions(-) diff --git a/MdeModulePkg/Library/VarCheckPolicyLib/VarCheckPolicyLib.c b/MdeModulePkg/Library/VarCheckPolicyLib/VarCheckPolicyLib.c index 5de46133bb26..1448af85555a 100644 --- a/MdeModulePkg/Library/VarCheckPolicyLib/VarCheckPolicyLib.c +++ b/MdeModulePkg/Library/VarCheckPolicyLib/VarCheckPolicyLib.c @@ -76,14 +76,20 @@ VarCheckPolicyLibMmiHandler ( VOID *InternalCommBuffer; EFI_STATUS Status; EFI_STATUS SubCommandStatus; - VAR_CHECK_POLICY_COMM_HEADER *PolicyCommmHeader; - VAR_CHECK_POLICY_COMM_HEADER *InternalPolicyCommmHeader; + VAR_CHECK_POLICY_COMM_HEADER *PolicyCommHeader; + VAR_CHECK_POLICY_COMM_HEADER *InternalPolicyCommHeader; VAR_CHECK_POLICY_COMM_IS_ENABLED_PARAMS *IsEnabledParams; VAR_CHECK_POLICY_COMM_DUMP_PARAMS *DumpParamsIn; VAR_CHECK_POLICY_COMM_DUMP_PARAMS *DumpParamsOut; + VAR_CHECK_POLICY_COMM_GET_INFO_PARAMS *GetInfoParamsInternal; + VAR_CHECK_POLICY_COMM_GET_INFO_PARAMS *GetInfoParamsExternal; + CHAR16 *InternalCopyOfOutputVariableName; + CHAR16 *ExternalCopyOfOutputVariableName; UINT8 *DumpInputBuffer; UINT8 *DumpOutputBuffer; + UINTN AllowedOutputVariableNameSize; UINTN DumpTotalPages; + UINTN LocalSize; VARIABLE_POLICY_ENTRY *PolicyEntry; UINTN ExpectedSize; UINT32 TempSize; @@ -122,21 +128,21 @@ VarCheckPolicyLibMmiHandler ( // InternalCommBuffer = &mSecurityEvalBuffer[0]; CopyMem (InternalCommBuffer, CommBuffer, InternalCommBufferSize); - PolicyCommmHeader = CommBuffer; - InternalPolicyCommmHeader = InternalCommBuffer; + PolicyCommHeader = CommBuffer; + InternalPolicyCommHeader = InternalCommBuffer; // Check the revision and the signature of the comm header. - if ((InternalPolicyCommmHeader->Signature != VAR_CHECK_POLICY_COMM_SIG) || - (InternalPolicyCommmHeader->Revision != VAR_CHECK_POLICY_COMM_REVISION)) + if ((InternalPolicyCommHeader->Signature != VAR_CHECK_POLICY_COMM_SIG) || + (InternalPolicyCommHeader->Revision != VAR_CHECK_POLICY_COMM_REVISION)) { DEBUG ((DEBUG_INFO, "%a - Signature or revision are incorrect!\n", __func__)); // We have verified the buffer is not null and have enough size to hold Result field. - PolicyCommmHeader->Result = EFI_INVALID_PARAMETER; + PolicyCommHeader->Result = EFI_INVALID_PARAMETER; return EFI_SUCCESS; } // If we're in the middle of a paginated dump and any other command is sent, // pagination cache must be cleared. - if ((mPaginationCache != NULL) && (InternalPolicyCommmHeader->Command != mCurrentPaginationCommand)) { + if ((mPaginationCache != NULL) && (InternalPolicyCommHeader->Command != mCurrentPaginationCommand)) { FreePool (mPaginationCache); mPaginationCache = NULL; mPaginationCacheSize = 0; @@ -146,10 +152,10 @@ VarCheckPolicyLibMmiHandler ( // // Now we can process the command as it was sent. // - PolicyCommmHeader->Result = EFI_ABORTED; // Set a default return for incomplete commands. - switch (InternalPolicyCommmHeader->Command) { + PolicyCommHeader->Result = EFI_ABORTED; // Set a default return for incomplete commands. + switch (InternalPolicyCommHeader->Command) { case VAR_CHECK_POLICY_COMMAND_DISABLE: - PolicyCommmHeader->Result = DisableVariablePolicy (); + PolicyCommHeader->Result = DisableVariablePolicy (); break; case VAR_CHECK_POLICY_COMMAND_IS_ENABLED: @@ -158,14 +164,14 @@ VarCheckPolicyLibMmiHandler ( ExpectedSize += sizeof (VAR_CHECK_POLICY_COMM_IS_ENABLED_PARAMS); if (InternalCommBufferSize < ExpectedSize) { DEBUG ((DEBUG_INFO, "%a - Bad comm buffer size! %d < %d\n", __func__, InternalCommBufferSize, ExpectedSize)); - PolicyCommmHeader->Result = EFI_INVALID_PARAMETER; + PolicyCommHeader->Result = EFI_INVALID_PARAMETER; break; } // Now that we know we've got a valid size, we can fill in the rest of the data. - IsEnabledParams = (VAR_CHECK_POLICY_COMM_IS_ENABLED_PARAMS *)((UINT8 *)CommBuffer + sizeof (VAR_CHECK_POLICY_COMM_HEADER)); - IsEnabledParams->State = IsVariablePolicyEnabled (); - PolicyCommmHeader->Result = EFI_SUCCESS; + IsEnabledParams = (VAR_CHECK_POLICY_COMM_IS_ENABLED_PARAMS *)((UINT8 *)CommBuffer + sizeof (VAR_CHECK_POLICY_COMM_HEADER)); + IsEnabledParams->State = IsVariablePolicyEnabled (); + PolicyCommHeader->Result = EFI_SUCCESS; break; case VAR_CHECK_POLICY_COMMAND_REGISTER: @@ -174,7 +180,7 @@ VarCheckPolicyLibMmiHandler ( ExpectedSize += sizeof (VARIABLE_POLICY_ENTRY); if (InternalCommBufferSize < ExpectedSize) { DEBUG ((DEBUG_INFO, "%a - Bad comm buffer size! %d < %d\n", __func__, InternalCommBufferSize, ExpectedSize)); - PolicyCommmHeader->Result = EFI_INVALID_PARAMETER; + PolicyCommHeader->Result = EFI_INVALID_PARAMETER; break; } @@ -187,11 +193,11 @@ VarCheckPolicyLibMmiHandler ( (InternalCommBufferSize < ExpectedSize)) { DEBUG ((DEBUG_INFO, "%a - Bad policy entry contents!\n", __func__)); - PolicyCommmHeader->Result = EFI_INVALID_PARAMETER; + PolicyCommHeader->Result = EFI_INVALID_PARAMETER; break; } - PolicyCommmHeader->Result = RegisterVariablePolicy (PolicyEntry); + PolicyCommHeader->Result = RegisterVariablePolicy (PolicyEntry); break; case VAR_CHECK_POLICY_COMMAND_DUMP: @@ -200,13 +206,13 @@ VarCheckPolicyLibMmiHandler ( ExpectedSize += sizeof (VAR_CHECK_POLICY_COMM_DUMP_PARAMS) + VAR_CHECK_POLICY_MM_DUMP_BUFFER_SIZE; if (InternalCommBufferSize < ExpectedSize) { DEBUG ((DEBUG_INFO, "%a - Bad comm buffer size! %d < %d\n", __func__, InternalCommBufferSize, ExpectedSize)); - PolicyCommmHeader->Result = EFI_INVALID_PARAMETER; + PolicyCommHeader->Result = EFI_INVALID_PARAMETER; break; } // Now that we know we've got a valid size, we can fill in the rest of the data. - DumpParamsIn = (VAR_CHECK_POLICY_COMM_DUMP_PARAMS *)(InternalPolicyCommmHeader + 1); - DumpParamsOut = (VAR_CHECK_POLICY_COMM_DUMP_PARAMS *)(PolicyCommmHeader + 1); + DumpParamsIn = (VAR_CHECK_POLICY_COMM_DUMP_PARAMS *)(InternalPolicyCommHeader + 1); + DumpParamsOut = (VAR_CHECK_POLICY_COMM_DUMP_PARAMS *)(PolicyCommHeader + 1); // If we're requesting the first page, initialize the cache and get the sizes. if (DumpParamsIn->PageRequested == 0) { @@ -289,17 +295,131 @@ VarCheckPolicyLibMmiHandler ( } // There's currently no use for this, but it shouldn't be hard to implement. - PolicyCommmHeader->Result = SubCommandStatus; + PolicyCommHeader->Result = SubCommandStatus; break; case VAR_CHECK_POLICY_COMMAND_LOCK: - PolicyCommmHeader->Result = LockVariablePolicy (); + PolicyCommHeader->Result = LockVariablePolicy (); + break; + + case VAR_CHECK_POLICY_COMMAND_GET_INFO: + case VAR_CHECK_POLICY_COMMAND_GET_LOCK_VAR_STATE_INFO: + ExpectedSize += VAR_CHECK_POLICY_COMM_GET_INFO_PARAMS_END + VAR_CHECK_POLICY_MM_GET_INFO_BUFFER_SIZE; + + if (InternalCommBufferSize < ExpectedSize) { + PolicyCommHeader->Result = EFI_INVALID_PARAMETER; + break; + } + + GetInfoParamsInternal = (VAR_CHECK_POLICY_COMM_GET_INFO_PARAMS *)(InternalPolicyCommHeader + 1); + GetInfoParamsExternal = (VAR_CHECK_POLICY_COMM_GET_INFO_PARAMS *)(PolicyCommHeader + 1); + + SubCommandStatus = SafeUintnSub ( + VAR_CHECK_POLICY_MM_GET_INFO_BUFFER_SIZE, + GetInfoParamsInternal->InputVariableNameSize, + &AllowedOutputVariableNameSize + ); + if (EFI_ERROR (SubCommandStatus)) { + PolicyCommHeader->Result = EFI_INVALID_PARAMETER; + break; + } + + if (GetInfoParamsInternal->OutputVariableNameSize > 0) { + SubCommandStatus = SafeUintnAdd ( + ((UINTN)GetInfoParamsInternal + VAR_CHECK_POLICY_COMM_GET_INFO_PARAMS_END), + (UINTN)GetInfoParamsInternal->InputVariableNameSize, + (UINTN *)&InternalCopyOfOutputVariableName + ); + if (EFI_ERROR (SubCommandStatus)) { + PolicyCommHeader->Result = EFI_INVALID_PARAMETER; + break; + } + } else { + InternalCopyOfOutputVariableName = NULL; + } + + ZeroMem (&GetInfoParamsInternal->OutputPolicyEntry, sizeof (GetInfoParamsInternal->OutputPolicyEntry)); + ZeroMem (&GetInfoParamsExternal->OutputPolicyEntry, sizeof (GetInfoParamsExternal->OutputPolicyEntry)); + + LocalSize = (UINTN)GetInfoParamsInternal->OutputVariableNameSize; + + if (InternalPolicyCommHeader->Command == VAR_CHECK_POLICY_COMMAND_GET_INFO) { + SubCommandStatus = GetVariablePolicyInfo ( + GetInfoParamsInternal->InputVariableName, + &GetInfoParamsInternal->InputVendorGuid, + &LocalSize, + &GetInfoParamsInternal->OutputPolicyEntry.VariablePolicy, + InternalCopyOfOutputVariableName + ); + } else if (InternalPolicyCommHeader->Command == VAR_CHECK_POLICY_COMMAND_GET_LOCK_VAR_STATE_INFO) { + SubCommandStatus = GetLockOnVariableStateVariablePolicyInfo ( + GetInfoParamsInternal->InputVariableName, + &GetInfoParamsInternal->InputVendorGuid, + &LocalSize, + &GetInfoParamsInternal->OutputPolicyEntry.LockOnVarStatePolicy, + InternalCopyOfOutputVariableName + ); + } else { + PolicyCommHeader->Result = EFI_INVALID_PARAMETER; + break; + } + + if (EFI_ERROR (SubCommandStatus) && (SubCommandStatus != EFI_BUFFER_TOO_SMALL)) { + PolicyCommHeader->Result = SubCommandStatus; + break; + } + + if (EFI_ERROR (SafeUintnToUint32 (LocalSize, &GetInfoParamsInternal->OutputVariableNameSize))) { + PolicyCommHeader->Result = EFI_BAD_BUFFER_SIZE; + break; + } + + ASSERT (sizeof (GetInfoParamsInternal->OutputPolicyEntry) == sizeof (GetInfoParamsExternal->OutputPolicyEntry)); + CopyMem ( + &GetInfoParamsExternal->OutputPolicyEntry, + &GetInfoParamsInternal->OutputPolicyEntry, + sizeof (GetInfoParamsExternal->OutputPolicyEntry) + ); + + GetInfoParamsExternal->OutputVariableNameSize = GetInfoParamsInternal->OutputVariableNameSize; + if (SubCommandStatus == EFI_BUFFER_TOO_SMALL) { + PolicyCommHeader->Result = EFI_BUFFER_TOO_SMALL; + break; + } + + SubCommandStatus = SafeUintnAdd ( + ((UINTN)GetInfoParamsExternal + VAR_CHECK_POLICY_COMM_GET_INFO_PARAMS_END), + (UINTN)GetInfoParamsInternal->InputVariableNameSize, + (UINTN *)&ExternalCopyOfOutputVariableName + ); + if (EFI_ERROR (SubCommandStatus)) { + PolicyCommHeader->Result = EFI_BAD_BUFFER_SIZE; + break; + } + + if (GetInfoParamsInternal->OutputVariableNameSize > 0) { + SubCommandStatus = StrnCpyS ( + ExternalCopyOfOutputVariableName, + AllowedOutputVariableNameSize, + InternalCopyOfOutputVariableName, + (UINTN)GetInfoParamsInternal->OutputVariableNameSize + ); + ASSERT_EFI_ERROR (SubCommandStatus); + } else { + // The comm buffer should always have the space for the variable policy output + // variable name. Fill it with NULL chars if a variable name is not present so + // it has a consistent value in the case of variable name absence. + SetMem (ExternalCopyOfOutputVariableName, AllowedOutputVariableNameSize, CHAR_NULL); + } + + PolicyCommHeader->Result = SubCommandStatus; + break; default: // Mark unknown requested command as EFI_UNSUPPORTED. - DEBUG ((DEBUG_INFO, "%a - Invalid command requested! %d\n", __func__, PolicyCommmHeader->Command)); - PolicyCommmHeader->Result = EFI_UNSUPPORTED; + DEBUG ((DEBUG_INFO, "%a - Invalid command requested! %d\n", __func__, PolicyCommHeader->Command)); + PolicyCommHeader->Result = EFI_UNSUPPORTED; break; } @@ -307,8 +427,8 @@ VarCheckPolicyLibMmiHandler ( DEBUG_VERBOSE, "%a - Command %d returning %r.\n", __func__, - PolicyCommmHeader->Command, - PolicyCommmHeader->Result + PolicyCommHeader->Command, + PolicyCommHeader->Result )); return Status; diff --git a/MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLib.c b/MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLib.c index 214f76ab9626..768662829dbf 100644 --- a/MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLib.c +++ b/MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLib.c @@ -8,6 +8,7 @@ SPDX-License-Identifier: BSD-2-Clause-Patent #include <Uefi.h> +#include <Library/BaseLib.h> #include <Library/SafeIntLib.h> #include <Library/MemoryAllocationLib.h> #include <Library/BaseMemoryLib.h> @@ -684,6 +685,309 @@ DumpVariablePolicy ( return EFI_SUCCESS; } +/** + This function will return variable policy information for a UEFI variable with a + registered variable policy. + + @param[in] VariableName The name of the variable to use for the policy search. + @param[in] VendorGuid The vendor GUID of the variable to use for the policy search. + @param[in,out] VariablePolicyVariableNameBufferSize On input, the size, in bytes, of the VariablePolicyVariableName + buffer. + + On output, the size, in bytes, needed to store the variable + policy variable name. + + If testing for the VariablePolicyVariableName buffer size + needed, set this value to zero so EFI_BUFFER_TOO_SMALL is + guaranteed to be returned if the variable policy variable name + is found. + @param[out] VariablePolicy Pointer to a buffer where the policy entry will be written + if found. + @param[out] VariablePolicyVariableName Pointer to a buffer where the variable name used for the + variable policy will be written if a variable name is + registered. + + If the variable policy is not associated with a variable name + (e.g. applied to variable vendor namespace) and this parameter + is given, this parameter will not be modified and + VariablePolicyVariableNameBufferSize will be set to zero to + indicate a name was not present. + + If the pointer given is not NULL, + VariablePolicyVariableNameBufferSize must be non-NULL. + + @retval EFI_SUCCESS A variable policy entry was found and returned successfully. + @retval EFI_BAD_BUFFER_SIZE An internal buffer size caused a calculation error. + @retval EFI_BUFFER_TOO_SMALL The VariablePolicyVariableName buffer value is too small for the size needed. + The buffer should now point to the size needed. + @retval EFI_NOT_READY Variable policy has not yet been initialized. + @retval EFI_INVALID_PARAMETER A required pointer argument passed is NULL. This will be returned if + VariablePolicyVariableName is non-NULL and VariablePolicyVariableNameBufferSize + is NULL. + @retval EFI_NOT_FOUND A variable policy was not found for the given UEFI variable name and vendor GUID. + +**/ +EFI_STATUS +EFIAPI +GetVariablePolicyInfo ( + IN CONST CHAR16 *VariableName, + IN CONST EFI_GUID *VendorGuid, + IN OUT UINTN *VariablePolicyVariableNameBufferSize OPTIONAL, + OUT VARIABLE_POLICY_ENTRY *VariablePolicy, + OUT CHAR16 *VariablePolicyVariableName OPTIONAL + ) +{ + EFI_STATUS Status; + UINT8 MatchPriority; + UINTN LocalVariablePolicyVariableNameBufferSize; + UINTN RequiredVariablePolicyVariableNameBufferSize; + VARIABLE_POLICY_ENTRY *MatchPolicy; + + Status = EFI_SUCCESS; + + if (!IsVariablePolicyLibInitialized ()) { + return EFI_NOT_READY; + } + + if ((VariableName == NULL) || (VendorGuid == NULL) || (VariablePolicy == NULL)) { + return EFI_INVALID_PARAMETER; + } + + MatchPolicy = GetBestPolicyMatch ( + VariableName, + VendorGuid, + &MatchPriority + ); + if (MatchPolicy != NULL) { + CopyMem (VariablePolicy, MatchPolicy, sizeof (*VariablePolicy)); + + if (VariablePolicyVariableNameBufferSize == NULL) { + if (VariablePolicyVariableName != NULL) { + return EFI_INVALID_PARAMETER; + } + + return Status; + } + + if (MatchPolicy->Size != MatchPolicy->OffsetToName) { + if (MatchPolicy->Size < MatchPolicy->OffsetToName) { + ASSERT (MatchPolicy->Size > MatchPolicy->OffsetToName); + return EFI_BAD_BUFFER_SIZE; + } + + RequiredVariablePolicyVariableNameBufferSize = (UINTN)(MatchPolicy->Size - MatchPolicy->OffsetToName); + ASSERT (RequiredVariablePolicyVariableNameBufferSize > 0); + + if (*VariablePolicyVariableNameBufferSize < RequiredVariablePolicyVariableNameBufferSize) { + // Let the caller get the size needed to hold the policy variable name + *VariablePolicyVariableNameBufferSize = RequiredVariablePolicyVariableNameBufferSize; + return EFI_BUFFER_TOO_SMALL; + } + + if (VariablePolicyVariableName == NULL) { + // If the policy variable name size given is valid, then a valid policy variable name buffer should be provided + *VariablePolicyVariableNameBufferSize = RequiredVariablePolicyVariableNameBufferSize; + return EFI_INVALID_PARAMETER; + } + + LocalVariablePolicyVariableNameBufferSize = *VariablePolicyVariableNameBufferSize; + + // Actual string size should match expected string size + if ( + ((StrnLenS (GET_POLICY_NAME (MatchPolicy), RequiredVariablePolicyVariableNameBufferSize) + 1) * sizeof (CHAR16)) + != RequiredVariablePolicyVariableNameBufferSize) + { + ASSERT_EFI_ERROR (EFI_BAD_BUFFER_SIZE); + return EFI_BAD_BUFFER_SIZE; + } + + *VariablePolicyVariableNameBufferSize = RequiredVariablePolicyVariableNameBufferSize; + + Status = StrnCpyS ( + VariablePolicyVariableName, + LocalVariablePolicyVariableNameBufferSize / sizeof (CHAR16), + GET_POLICY_NAME (MatchPolicy), + RequiredVariablePolicyVariableNameBufferSize / sizeof (CHAR16) + ); + ASSERT_EFI_ERROR (Status); + } else { + // A variable policy variable name is not present. Return values according to interface. + *VariablePolicyVariableNameBufferSize = 0; + } + + return Status; + } + + return EFI_NOT_FOUND; +} + +/** + This function will return the Lock on Variable State policy information for the policy + associated with the given UEFI variable. + + @param[in] VariableName The name of the variable to use for the policy search. + @param[in] VendorGuid The vendor GUID of the variable to use for the policy + search. + @param[in,out] VariableLockPolicyVariableNameBufferSize On input, the size, in bytes, of the + VariableLockPolicyVariableName buffer. + + On output, the size, in bytes, needed to store the variable + policy variable name. + + If testing for the VariableLockPolicyVariableName buffer + size needed, set this value to zero so EFI_BUFFER_TOO_SMALL + is guaranteed to be returned if the variable policy variable + name is found. + @param[out] VariablePolicy Pointer to a buffer where the policy entry will be written + if found. + @param[out] VariableLockPolicyVariableName Pointer to a buffer where the variable name used for the + variable lock on variable state policy will be written if + a variable name is registered. + + If the lock on variable policy is not associated with a + variable name (e.g. applied to variable vendor namespace) + and this parameter is given, this parameter will not be + modified and VariableLockPolicyVariableNameBufferSize will + be set to zero to indicate a name was not present. + + If the pointer given is not NULL, + VariableLockPolicyVariableNameBufferSize must be non-NULL. + + @retval EFI_SUCCESS A Lock on Variable State variable policy entry was found and returned + successfully. + @retval EFI_BAD_BUFFER_SIZE An internal buffer size caused a calculation error. + @retval EFI_BUFFER_TOO_SMALL The VariableLockPolicyVariableName buffer is too small for the size needed. + The buffer should now point to the size needed. + @retval EFI_NOT_READY Variable policy has not yet been initialized. + @retval EFI_INVALID_PARAMETER A required pointer argument passed is NULL. This will be returned if + VariableLockPolicyVariableName is non-NULL and + VariableLockPolicyVariableNameBufferSize is NULL. + @retval EFI_NOT_FOUND A Lock on Variable State variable policy was not found for the given UEFI + variable name and vendor GUID. + +**/ +EFI_STATUS +EFIAPI +GetLockOnVariableStateVariablePolicyInfo ( + IN CONST CHAR16 *VariableName, + IN CONST EFI_GUID *VendorGuid, + IN OUT UINTN *VariableLockPolicyVariableNameBufferSize OPTIONAL, + OUT VARIABLE_LOCK_ON_VAR_STATE_POLICY *VariablePolicy, + OUT CHAR16 *VariableLockPolicyVariableName OPTIONAL + ) +{ + EFI_STATUS Status; + UINT8 MatchPriority; + UINTN RequiredVariablePolicyVariableNameBufferSize; + UINTN RequiredVariableLockPolicyVariableNameBufferSize; + UINTN LocalVariablePolicyLockVariableNameBufferSize; + UINTN LockOnVarStatePolicyEndOffset; + CHAR16 *LocalVariableLockPolicyVariableName; + VARIABLE_LOCK_ON_VAR_STATE_POLICY *LocalLockOnVarStatePolicy; + VARIABLE_POLICY_ENTRY *MatchPolicy; + + Status = EFI_SUCCESS; + + if (!IsVariablePolicyLibInitialized ()) { + return EFI_NOT_READY; + } + + if ((VariableName == NULL) || (VendorGuid == NULL) || (VariablePolicy == NULL)) { + return EFI_INVALID_PARAMETER; + } + + MatchPolicy = GetBestPolicyMatch ( + VariableName, + VendorGuid, + &MatchPriority + ); + if (MatchPolicy != NULL) { + if (MatchPolicy->LockPolicyType != VARIABLE_POLICY_TYPE_LOCK_ON_VAR_STATE) { + return EFI_NOT_FOUND; + } + + Status = SafeUintnAdd ( + sizeof (VARIABLE_POLICY_ENTRY), + sizeof (VARIABLE_LOCK_ON_VAR_STATE_POLICY), + &LockOnVarStatePolicyEndOffset + ); + if (EFI_ERROR (Status) || (LockOnVarStatePolicyEndOffset > (UINTN)MatchPolicy->Size)) { + return EFI_BAD_BUFFER_SIZE; + } + + LocalLockOnVarStatePolicy = (VARIABLE_LOCK_ON_VAR_STATE_POLICY *)(MatchPolicy + 1); + CopyMem (VariablePolicy, LocalLockOnVarStatePolicy, sizeof (*LocalLockOnVarStatePolicy)); + + if ((VariableLockPolicyVariableNameBufferSize == NULL)) { + if (VariableLockPolicyVariableName != NULL) { + return EFI_INVALID_PARAMETER; + } + + return Status; + } + + // The name offset should be less than or equal to the total policy size. + if (MatchPolicy->Size < MatchPolicy->OffsetToName) { + return EFI_BAD_BUFFER_SIZE; + } + + RequiredVariablePolicyVariableNameBufferSize = (UINTN)(MatchPolicy->Size - MatchPolicy->OffsetToName); + RequiredVariableLockPolicyVariableNameBufferSize = MatchPolicy->Size - + (LockOnVarStatePolicyEndOffset + RequiredVariablePolicyVariableNameBufferSize); + + LocalVariablePolicyLockVariableNameBufferSize = *VariableLockPolicyVariableNameBufferSize; + *VariableLockPolicyVariableNameBufferSize = RequiredVariableLockPolicyVariableNameBufferSize; + + if (LocalVariablePolicyLockVariableNameBufferSize < RequiredVariableLockPolicyVariableNameBufferSize) { + // Let the caller get the size needed to hold the policy variable name + return EFI_BUFFER_TOO_SMALL; + } + + if (VariableLockPolicyVariableName == NULL) { + // If the policy variable name size given is valid, then a valid policy variable name buffer should be provided + return EFI_INVALID_PARAMETER; + } + + if (RequiredVariableLockPolicyVariableNameBufferSize == 0) { + return Status; + } + + LocalVariableLockPolicyVariableName = (CHAR16 *)((UINT8 *)LocalLockOnVarStatePolicy + sizeof (*LocalLockOnVarStatePolicy)); + *VariableLockPolicyVariableNameBufferSize = RequiredVariableLockPolicyVariableNameBufferSize; + + // Actual string size should match expected string size (if a variable name is present) + if ( + (RequiredVariablePolicyVariableNameBufferSize > 0) && + (((StrnLenS (GET_POLICY_NAME (MatchPolicy), RequiredVariablePolicyVariableNameBufferSize) + 1) * sizeof (CHAR16)) != + RequiredVariablePolicyVariableNameBufferSize)) + { + ASSERT_EFI_ERROR (EFI_BAD_BUFFER_SIZE); + return EFI_BAD_BUFFER_SIZE; + } + + // Actual string size should match expected string size (if here, variable lock variable name is present) + if ( + ((StrnLenS (LocalVariableLockPolicyVariableName, RequiredVariableLockPolicyVariableNameBufferSize) + 1) * sizeof (CHAR16)) != + RequiredVariableLockPolicyVariableNameBufferSize) + { + ASSERT_EFI_ERROR (EFI_BAD_BUFFER_SIZE); + return EFI_BAD_BUFFER_SIZE; + } + + Status = StrnCpyS ( + VariableLockPolicyVariableName, + LocalVariablePolicyLockVariableNameBufferSize / sizeof (CHAR16), + LocalVariableLockPolicyVariableName, + RequiredVariableLockPolicyVariableNameBufferSize / sizeof (CHAR16) + ); + ASSERT_EFI_ERROR (Status); + + return Status; + } + + return EFI_NOT_FOUND; +} + /** This API function returns whether or not the policy engine is currently being enforced. diff --git a/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableDxe.c b/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableDxe.c index d5c409c914d1..c4ccdfd20f74 100644 --- a/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableDxe.c +++ b/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableDxe.c @@ -33,7 +33,9 @@ EDKII_VARIABLE_POLICY_PROTOCOL mVariablePolicyProtocol = { ProtocolIsVariablePolicyEnabled, RegisterVariablePolicy, DumpVariablePolicy, - LockVariablePolicy + LockVariablePolicy, + GetVariablePolicyInfo, + GetLockOnVariableStateVariablePolicyInfo }; EDKII_VAR_CHECK_PROTOCOL mVarCheck = { VarCheckRegisterSetVariableCheckHandler, diff --git a/MdeModulePkg/Universal/Variable/RuntimeDxe/VariablePolicySmmDxe.c b/MdeModulePkg/Universal/Variable/RuntimeDxe/VariablePolicySmmDxe.c index 6151a2ba0b18..0dd72dde27ce 100644 --- a/MdeModulePkg/Universal/Variable/RuntimeDxe/VariablePolicySmmDxe.c +++ b/MdeModulePkg/Universal/Variable/RuntimeDxe/VariablePolicySmmDxe.c @@ -410,6 +410,338 @@ ProtocolLockVariablePolicy ( return (EFI_ERROR (Status)) ? Status : PolicyHeader->Result; } +/** + Internal implementation to retrieve variable information for a given UEFI variable that is shared + between different policy types. + + Currently, the two policy structure types supported (and all that is defined) are VARIABLE_POLICY_ENTRY + and VARIABLE_LOCK_ON_VAR_STATE_POLICY. + + @param[in] Command The command value to use in the communicate call. + @param[in] VariableName The name of the variable to use for the policy search. + @param[in] VendorGuid The vendor GUID of the variable to use for the policy search. + @param[in,out] VariablePolicyVariableNameBufferSize On input, the size, in bytes, of the VariablePolicyVariableName + buffer. + + On output, the size, in bytes, needed to store the variable + policy variable name. + + If testing for the VariablePolicyVariableName buffer size + needed, set this value to zero so EFI_BUFFER_TOO_SMALL is + guaranteed to be returned if the variable policy variable name + is found. + @param[out] VariablePolicy Pointer to a buffer where the policy entry will be written + if found. + @param[out] VariablePolicyVariableName Pointer to a buffer where the variable name used for the + variable policy will be written if a variable name is + registered. + + If the variable policy is not associated with a variable name + (e.g. applied to variable vendor namespace) and this parameter + is given, this parameter will not be modified and + VariablePolicyVariableNameBufferSize will be set to zero to + indicate a name was not present. + + If the pointer given is not NULL, + VariablePolicyVariableNameBufferSize must be non-NULL. + + @retval EFI_SUCCESS A variable policy entry was found and returned successfully. + @retval EFI_BAD_BUFFER_SIZE An internal buffer size caused a calculation error. + @retval EFI_BUFFER_TOO_SMALL The VariablePolicyVariableName buffer value is too small for the size needed. + The buffer should now point to the size needed. + @retval EFI_NOT_READY Variable policy has not yet been initialized. + @retval EFI_INVALID_PARAMETER A required pointer argument passed is NULL. This will be returned if + VariablePolicyVariableName is non-NULL and VariablePolicyVariableNameBufferSize + is NULL. It can also be returned if the Command value provided is invalid. + @retval EFI_NOT_FOUND A variable policy was not found for the given UEFI variable name and vendor GUID. + + +**/ +STATIC +EFI_STATUS +InternalProtocolGetVariablePolicyInfo ( + IN UINT32 Command, + IN CONST CHAR16 *VariableName, + IN CONST EFI_GUID *VendorGuid, + IN OUT UINTN *VariablePolicyVariableNameBufferSize, OPTIONAL + OUT VOID *VariablePolicy, + OUT CHAR16 *VariablePolicyVariableName OPTIONAL + ) +{ + EFI_STATUS Status; + CHAR16 *OutputVariableName; + EFI_MM_COMMUNICATE_HEADER *CommHeader; + VAR_CHECK_POLICY_COMM_HEADER *PolicyHeader; + VAR_CHECK_POLICY_COMM_GET_INFO_PARAMS *CommandParams; + UINTN AllowedOutputVariableNameSize; + UINTN BufferSize; + UINTN VariableNameSize; + + if ((VariableName == NULL) || (VendorGuid == NULL) || (VariablePolicy == NULL)) { + return EFI_INVALID_PARAMETER; + } + + switch (Command) { + case VAR_CHECK_POLICY_COMMAND_GET_INFO: + case VAR_CHECK_POLICY_COMMAND_GET_LOCK_VAR_STATE_INFO: + break; + default: + return EFI_INVALID_PARAMETER; + } + + AcquireLockOnlyAtBootTime (&mMmCommunicationLock); + + VariableNameSize = StrnSizeS ( + VariableName, + (VAR_CHECK_POLICY_MM_GET_INFO_BUFFER_SIZE - VAR_CHECK_POLICY_COMM_GET_INFO_PARAMS_END) + ); + if (VariableNameSize >= (VAR_CHECK_POLICY_MM_GET_INFO_BUFFER_SIZE - VAR_CHECK_POLICY_COMM_GET_INFO_PARAMS_END)) { + Status = EFI_INVALID_PARAMETER; + goto Done; + } + + if ((VariablePolicyVariableName != NULL) && (VariablePolicyVariableNameBufferSize == NULL)) { + return EFI_INVALID_PARAMETER; + goto Done; + } + + BufferSize = mMmCommunicationBufferSize; + CommHeader = mMmCommunicationBuffer; + + Status = SafeUintnSub ( + VAR_CHECK_POLICY_MM_GET_INFO_BUFFER_SIZE, + VariableNameSize, + &AllowedOutputVariableNameSize + ); + if (EFI_ERROR (Status)) { + Status = EFI_INVALID_PARAMETER; + goto Done; + } + + if (VariablePolicyVariableNameBufferSize != NULL) { + AllowedOutputVariableNameSize = MIN (AllowedOutputVariableNameSize, *VariablePolicyVariableNameBufferSize); + } else { + AllowedOutputVariableNameSize = 0; + } + + PolicyHeader = (VAR_CHECK_POLICY_COMM_HEADER *)&CommHeader->Data; + CommandParams = (VAR_CHECK_POLICY_COMM_GET_INFO_PARAMS *)(PolicyHeader + 1); + + CopyGuid (&CommHeader->HeaderGuid, &gVarCheckPolicyLibMmiHandlerGuid); + CommHeader->MessageLength = BufferSize - OFFSET_OF (EFI_MM_COMMUNICATE_HEADER, Data); + PolicyHeader->Signature = VAR_CHECK_POLICY_COMM_SIG; + PolicyHeader->Revision = VAR_CHECK_POLICY_COMM_REVISION; + PolicyHeader->Command = Command; + + ZeroMem ((VOID *)&CommandParams->OutputPolicyEntry, sizeof (CommandParams->OutputPolicyEntry)); + CopyGuid (&CommandParams->InputVendorGuid, VendorGuid); + Status = SafeUintnToUint32 (VariableNameSize, &CommandParams->InputVariableNameSize); + if (EFI_ERROR (Status)) { + Status = EFI_INVALID_PARAMETER; + goto Done; + } + + Status = SafeUintnToUint32 (AllowedOutputVariableNameSize, &CommandParams->OutputVariableNameSize); + if (EFI_ERROR (Status)) { + Status = EFI_INVALID_PARAMETER; + goto Done; + } + + if (AllowedOutputVariableNameSize > 0) { + Status = StrnCpyS ( + CommandParams->InputVariableName, + AllowedOutputVariableNameSize / sizeof (CHAR16), + VariableName, + (UINTN)CommandParams->InputVariableNameSize / sizeof (CHAR16) + ); + ASSERT_EFI_ERROR (Status); + } + + Status = InternalMmCommunicate (CommHeader, &BufferSize); + if (Status == EFI_SUCCESS) { + CopyMem ( + VariablePolicy, + (VOID *)&CommandParams->OutputPolicyEntry, + (Command == VAR_CHECK_POLICY_COMMAND_GET_INFO) ? + sizeof (CommandParams->OutputPolicyEntry.VariablePolicy) : + sizeof (CommandParams->OutputPolicyEntry.LockOnVarStatePolicy) + ); + + if (VariablePolicyVariableNameBufferSize == NULL) { + if (VariablePolicyVariableName != NULL) { + Status = EFI_INVALID_PARAMETER; + } + + goto Done; + } + + if (PolicyHeader->Result == EFI_BUFFER_TOO_SMALL) { + *VariablePolicyVariableNameBufferSize = (UINTN)CommandParams->OutputVariableNameSize; + goto Done; + } + + if (PolicyHeader->Result == EFI_SUCCESS) { + if (CommandParams->OutputVariableNameSize > 0) { + Status = SafeUintnAdd ( + ((UINTN)CommandParams + VAR_CHECK_POLICY_COMM_GET_INFO_PARAMS_END), + (UINTN)CommandParams->InputVariableNameSize, + (UINTN *)&OutputVariableName + ); + if (EFI_ERROR (Status)) { + Status = EFI_BAD_BUFFER_SIZE; + goto Done; + } + + Status = StrnCpyS ( + VariablePolicyVariableName, + *VariablePolicyVariableNameBufferSize / sizeof (CHAR16), + OutputVariableName, + (UINTN)CommandParams->OutputVariableNameSize + ); + ASSERT_EFI_ERROR (Status); + *VariablePolicyVariableNameBufferSize = (UINTN)CommandParams->OutputVariableNameSize; + } else { + // A variable policy variable name is not present. Return values according to interface. + *VariablePolicyVariableNameBufferSize = 0; + } + } + } + +Done: + ReleaseLockOnlyAtBootTime (&mMmCommunicationLock); + + return (EFI_ERROR (Status)) ? Status : PolicyHeader->Result; +} + +/** + This function will return variable policy information for a UEFI variable with a + registered variable policy. + + @param[in] VariableName The name of the variable to use for the policy search. + @param[in] VendorGuid The vendor GUID of the variable to use for the policy search. + @param[in,out] VariablePolicyVariableNameBufferSize On input, the size, in bytes, of the VariablePolicyVariableName + buffer. + + On output, the size, in bytes, needed to store the variable + policy variable name. + + If testing for the VariablePolicyVariableName buffer size + needed, set this value to zero so EFI_BUFFER_TOO_SMALL is + guaranteed to be returned if the variable policy variable name + is found. + @param[out] VariablePolicy Pointer to a buffer where the policy entry will be written + if found. + @param[out] VariablePolicyVariableName Pointer to a buffer where the variable name used for the + variable policy will be written if a variable name is + registered. + + If the variable policy is not associated with a variable name + (e.g. applied to variable vendor namespace) and this parameter + is given, this parameter will not be modified and + VariablePolicyVariableNameBufferSize will be set to zero to + indicate a name was not present. + + If the pointer given is not NULL, + VariablePolicyVariableNameBufferSize must be non-NULL. + + @retval EFI_SUCCESS A variable policy entry was found and returned successfully. + @retval EFI_BAD_BUFFER_SIZE An internal buffer size caused a calculation error. + @retval EFI_BUFFER_TOO_SMALL The VariablePolicyVariableName buffer value is too small for the size needed. + The buffer should now point to the size needed. + @retval EFI_NOT_READY Variable policy has not yet been initialized. + @retval EFI_INVALID_PARAMETER A required pointer argument passed is NULL. This will be returned if + VariablePolicyVariableName is non-NULL and VariablePolicyVariableNameBufferSize + is NULL. + @retval EFI_NOT_FOUND A variable policy was not found for the given UEFI variable name and vendor GUID. + +**/ +STATIC +EFI_STATUS +EFIAPI +ProtocolGetVariablePolicyInfo ( + IN CONST CHAR16 *VariableName, + IN CONST EFI_GUID *VendorGuid, + IN OUT UINTN *VariablePolicyVariableNameBufferSize, OPTIONAL + OUT VARIABLE_POLICY_ENTRY *VariablePolicy, + OUT CHAR16 *VariablePolicyVariableName OPTIONAL + ) +{ + return InternalProtocolGetVariablePolicyInfo ( + VAR_CHECK_POLICY_COMMAND_GET_INFO, + VariableName, + VendorGuid, + VariablePolicyVariableNameBufferSize, + VariablePolicy, + VariablePolicyVariableName + ); +} + +/** + This function will return the Lock on Variable State policy information for the policy + associated with the given UEFI variable. + + @param[in] VariableName The name of the variable to use for the policy search. + @param[in] VendorGuid The vendor GUID of the variable to use for the policy + search. + @param[in,out] VariableLockPolicyVariableNameBufferSize On input, the size, in bytes, of the + VariableLockPolicyVariableName buffer. + + On output, the size, in bytes, needed to store the variable + policy variable name. + + If testing for the VariableLockPolicyVariableName buffer + P size needed, set this value to zero so EFI_BUFFER_TOO_SMALL + is guaranteed to be returned if the variable policy variable + name is found. + @param[out] VariablePolicy Pointer to a buffer where the policy entry will be written + if found. + @param[out] VariableLockPolicyVariableName Pointer to a buffer where the variable name used for the + variable lock on variable state policy will be written if + a variable name is registered. + + If the lock on variable policy is not associated with a + variable name (e.g. applied to variable vendor namespace) + and this parameter is given, this parameter will not be + modified and VariableLockPolicyVariableNameBufferSize will + be set to zero to indicate a name was not present. + + If the pointer given is not NULL, + VariableLockPolicyVariableNameBufferSize must be non-NULL. + + @retval EFI_SUCCESS A Lock on Variable State variable policy entry was found and returned + successfully. + @retval EFI_BAD_BUFFER_SIZE An internal buffer size caused a calculation error. + @retval EFI_BUFFER_TOO_SMALL The VariableLockPolicyVariableName buffer is too small for the size needed. + The buffer should now point to the size needed. + @retval EFI_NOT_READY Variable policy has not yet been initialized. + @retval EFI_INVALID_PARAMETER A required pointer argument passed is NULL. This will be returned if + VariableLockPolicyVariableName is non-NULL and + VariableLockPolicyVariableNameBufferSize is NULL. + @retval EFI_NOT_FOUND A Lock on Variable State variable policy was not found for the given UEFI + variable name and vendor GUID. + +**/ +STATIC +EFI_STATUS +EFIAPI +ProtocolGetLockOnVariableStateVariablePolicyInfo ( + IN CONST CHAR16 *VariableName, + IN CONST EFI_GUID *VendorGuid, + IN OUT UINTN *VariableLockPolicyVariableNameBufferSize, OPTIONAL + OUT VARIABLE_LOCK_ON_VAR_STATE_POLICY *VariablePolicy, + OUT CHAR16 *VariableLockPolicyVariableName OPTIONAL + ) +{ + return InternalProtocolGetVariablePolicyInfo ( + VAR_CHECK_POLICY_COMMAND_GET_LOCK_VAR_STATE_INFO, + VariableName, + VendorGuid, + VariableLockPolicyVariableNameBufferSize, + VariablePolicy, + VariableLockPolicyVariableName + ); +} + /** This helper function locates the shared comm buffer and assigns it to input pointers. @@ -514,12 +846,14 @@ VariablePolicySmmDxeMain ( } // Configure the VariablePolicy protocol structure. - mVariablePolicyProtocol.Revision = EDKII_VARIABLE_POLICY_PROTOCOL_REVISION; - mVariablePolicyProtocol.DisableVariablePolicy = ProtocolDisableVariablePolicy; - mVariablePolicyProtocol.IsVariablePolicyEnabled = ProtocolIsVariablePolicyEnabled; - mVariablePolicyProtocol.RegisterVariablePolicy = ProtocolRegisterVariablePolicy; - mVariablePolicyProtocol.DumpVariablePolicy = ProtocolDumpVariablePolicy; - mVariablePolicyProtocol.LockVariablePolicy = ProtocolLockVariablePolicy; + mVariablePolicyProtocol.Revision = EDKII_VARIABLE_POLICY_PROTOCOL_REVISION; + mVariablePolicyProtocol.DisableVariablePolicy = ProtocolDisableVariablePolicy; + mVariablePolicyProtocol.IsVariablePolicyEnabled = ProtocolIsVariablePolicyEnabled; + mVariablePolicyProtocol.RegisterVariablePolicy = ProtocolRegisterVariablePolicy; + mVariablePolicyProtocol.DumpVariablePolicy = ProtocolDumpVariablePolicy; + mVariablePolicyProtocol.LockVariablePolicy = ProtocolLockVariablePolicy; + mVariablePolicyProtocol.GetVariablePolicyInfo = ProtocolGetVariablePolicyInfo; + mVariablePolicyProtocol.GetLockOnVariableStateVariablePolicyInfo = ProtocolGetLockOnVariableStateVariablePolicyInfo; // Register all the protocols and return the status. Status = gBS->InstallMultipleProtocolInterfaces ( diff --git a/MdeModulePkg/Include/Guid/VarCheckPolicyMmi.h b/MdeModulePkg/Include/Guid/VarCheckPolicyMmi.h index ff3d4a1fd68a..a692fa40c946 100644 --- a/MdeModulePkg/Include/Guid/VarCheckPolicyMmi.h +++ b/MdeModulePkg/Include/Guid/VarCheckPolicyMmi.h @@ -32,23 +32,52 @@ typedef struct _VAR_CHECK_POLICY_COMM_DUMP_PARAMS { BOOLEAN HasMore; } VAR_CHECK_POLICY_COMM_DUMP_PARAMS; +typedef union { + VARIABLE_POLICY_ENTRY VariablePolicy; + VARIABLE_LOCK_ON_VAR_STATE_POLICY LockOnVarStatePolicy; +} VAR_CHECK_POLICY_OUTPUT_POLICY_ENTRY; + +typedef struct _VAR_CHECK_POLICY_COMM_GET_INFO_PARAMS { + EFI_GUID InputVendorGuid; + UINT32 InputVariableNameSize; + UINT32 OutputVariableNameSize; + VAR_CHECK_POLICY_OUTPUT_POLICY_ENTRY OutputPolicyEntry; + CHAR16 InputVariableName[1]; +} VAR_CHECK_POLICY_COMM_GET_INFO_PARAMS; + #pragma pack(pop) +#define VAR_CHECK_POLICY_COMM_GET_INFO_PARAMS_END \ + (OFFSET_OF(VAR_CHECK_POLICY_COMM_GET_INFO_PARAMS, InputVariableName)) + // Make sure that we will hold at least the headers. #define VAR_CHECK_POLICY_MM_COMM_BUFFER_SIZE MAX((OFFSET_OF(EFI_MM_COMMUNICATE_HEADER, Data) + sizeof (VAR_CHECK_POLICY_COMM_HEADER) + EFI_PAGES_TO_SIZE(1)), EFI_PAGES_TO_SIZE(4)) #define VAR_CHECK_POLICY_MM_DUMP_BUFFER_SIZE (VAR_CHECK_POLICY_MM_COMM_BUFFER_SIZE - \ (OFFSET_OF(EFI_MM_COMMUNICATE_HEADER, Data) + \ sizeof(VAR_CHECK_POLICY_COMM_HEADER) + \ sizeof(VAR_CHECK_POLICY_COMM_DUMP_PARAMS))) + +#define VAR_CHECK_POLICY_MM_GET_INFO_BUFFER_SIZE (VAR_CHECK_POLICY_MM_COMM_BUFFER_SIZE - \ + (OFFSET_OF(EFI_MM_COMMUNICATE_HEADER, Data) + \ + sizeof(VAR_CHECK_POLICY_COMM_HEADER) + \ + OFFSET_OF(VAR_CHECK_POLICY_COMM_GET_INFO_PARAMS, InputVariableName))) + STATIC_ASSERT ( VAR_CHECK_POLICY_MM_DUMP_BUFFER_SIZE < VAR_CHECK_POLICY_MM_COMM_BUFFER_SIZE, "an integer underflow may have occurred calculating VAR_CHECK_POLICY_MM_DUMP_BUFFER_SIZE" ); -#define VAR_CHECK_POLICY_COMMAND_DISABLE 0x0001 -#define VAR_CHECK_POLICY_COMMAND_IS_ENABLED 0x0002 -#define VAR_CHECK_POLICY_COMMAND_REGISTER 0x0003 -#define VAR_CHECK_POLICY_COMMAND_DUMP 0x0004 -#define VAR_CHECK_POLICY_COMMAND_LOCK 0x0005 +STATIC_ASSERT ( + VAR_CHECK_POLICY_MM_GET_INFO_BUFFER_SIZE < VAR_CHECK_POLICY_MM_COMM_BUFFER_SIZE, + "an integer underflow may have occurred calculating VAR_CHECK_POLICY_MM_GET_INFO_BUFFER_SIZE" + ); + +#define VAR_CHECK_POLICY_COMMAND_DISABLE 0x0001 +#define VAR_CHECK_POLICY_COMMAND_IS_ENABLED 0x0002 +#define VAR_CHECK_POLICY_COMMAND_REGISTER 0x0003 +#define VAR_CHECK_POLICY_COMMAND_DUMP 0x0004 +#define VAR_CHECK_POLICY_COMMAND_LOCK 0x0005 +#define VAR_CHECK_POLICY_COMMAND_GET_INFO 0x0006 +#define VAR_CHECK_POLICY_COMMAND_GET_LOCK_VAR_STATE_INFO 0x0007 #endif // _VAR_CHECK_POLICY_MMI_COMMON_H_ diff --git a/MdeModulePkg/Include/Library/VariablePolicyLib.h b/MdeModulePkg/Include/Library/VariablePolicyLib.h index 63c49fbca1ed..bc4e26b2d434 100644 --- a/MdeModulePkg/Include/Library/VariablePolicyLib.h +++ b/MdeModulePkg/Include/Library/VariablePolicyLib.h @@ -102,6 +102,113 @@ DumpVariablePolicy ( IN OUT UINT32 *Size ); +/** + This function will return variable policy information for a UEFI variable with a + registered variable policy. + + @param[in] VariableName The name of the variable to use for the policy search. + @param[in] VendorGuid The vendor GUID of the variable to use for the policy search. + @param[in,out] VariablePolicyVariableNameBufferSize On input, the size, in bytes, of the VariablePolicyVariableName + buffer. + + On output, the size, in bytes, needed to store the variable + policy variable name. + + If testing for the VariablePolicyVariableName buffer size + needed, set this value to zero so EFI_BUFFER_TOO_SMALL is + guaranteed to be returned if the variable policy variable name + is found. + @param[out] VariablePolicy Pointer to a buffer where the policy entry will be written + if found. + @param[out] VariablePolicyVariableName Pointer to a buffer where the variable name used for the + variable policy will be written if a variable name is + registered. + + If the variable policy is not associated with a variable name + (e.g. applied to variable vendor namespace) and this parameter + is given, this parameter will not be modified and + VariablePolicyVariableNameBufferSize will be set to zero to + indicate a name was not present. + + If the pointer given is not NULL, + VariablePolicyVariableNameBufferSize must be non-NULL. + + @retval EFI_SUCCESS A variable policy entry was found and returned successfully. + @retval EFI_BAD_BUFFER_SIZE An internal buffer size caused a calculation error. + @retval EFI_BUFFER_TOO_SMALL The VariablePolicyVariableName buffer value is too small for the size needed. + The buffer should now point to the size needed. + @retval EFI_NOT_READY Variable policy has not yet been initialized. + @retval EFI_INVALID_PARAMETER A required pointer argument passed is NULL. This will be returned if + VariablePolicyVariableName is non-NULL and VariablePolicyVariableNameBufferSize + is NULL. + @retval EFI_NOT_FOUND A variable policy was not found for the given UEFI variable name and vendor GUID. + +**/ +EFI_STATUS +EFIAPI +GetVariablePolicyInfo ( + IN CONST CHAR16 *VariableName, + IN CONST EFI_GUID *VendorGuid, + IN OUT UINTN *VariablePolicyVariableNameBufferSize OPTIONAL, + OUT VARIABLE_POLICY_ENTRY *VariablePolicy, + OUT CHAR16 *VariablePolicyVariableName OPTIONAL + ); + +/** + This function will return the Lock on Variable State policy information for the policy + associated with the given UEFI variable. + + @param[in] VariableName The name of the variable to use for the policy search. + @param[in] VendorGuid The vendor GUID of the variable to use for the policy + search. + @param[in,out] VariableLockPolicyVariableNameBufferSize On input, the size, in bytes, of the + VariableLockPolicyVariableName buffer. + + On output, the size, in bytes, needed to store the variable + policy variable name. + + If testing for the VariableLockPolicyVariableName buffer + size needed, set this value to zero so EFI_BUFFER_TOO_SMALL + is guaranteed to be returned if the variable policy variable + name is found. + @param[out] VariablePolicy Pointer to a buffer where the policy entry will be written + if found. + @param[out] VariableLockPolicyVariableName Pointer to a buffer where the variable name used for the + variable lock on variable state policy will be written if + a variable name is registered. + + If the lock on variable policy is not associated with a + variable name (e.g. applied to variable vendor namespace) + and this parameter is given, this parameter will not be + modified and VariableLockPolicyVariableNameBufferSize will + be set to zero to indicate a name was not present. + + If the pointer given is not NULL, + VariableLockPolicyVariableNameBufferSize must be non-NULL. + + @retval EFI_SUCCESS A Lock on Variable State variable policy entry was found and returned + successfully. + @retval EFI_BAD_BUFFER_SIZE An internal buffer size caused a calculation error. + @retval EFI_BUFFER_TOO_SMALL The VariableLockPolicyVariableName buffer is too small for the size needed. + The buffer should now point to the size needed. + @retval EFI_NOT_READY Variable policy has not yet been initialized. + @retval EFI_INVALID_PARAMETER A required pointer argument passed is NULL. This will be returned if + VariableLockPolicyVariableName is non-NULL and + VariableLockPolicyVariableNameBufferSize is NULL. + @retval EFI_NOT_FOUND A Lock on Variable State variable policy was not found for the given UEFI + variable name and vendor GUID. + +**/ +EFI_STATUS +EFIAPI +GetLockOnVariableStateVariablePolicyInfo ( + IN CONST CHAR16 *VariableName, + IN CONST EFI_GUID *VendorGuid, + IN OUT UINTN *VariableLockPolicyVariableNameBufferSize OPTIONAL, + OUT VARIABLE_LOCK_ON_VAR_STATE_POLICY *VariablePolicy, + OUT CHAR16 *VariableLockPolicyVariableName OPTIONAL + ); + /** This API function returns whether or not the policy engine is currently being enforced. diff --git a/MdeModulePkg/Include/Protocol/VariablePolicy.h b/MdeModulePkg/Include/Protocol/VariablePolicy.h index 98d739401f83..4b57f70a9da8 100644 --- a/MdeModulePkg/Include/Protocol/VariablePolicy.h +++ b/MdeModulePkg/Include/Protocol/VariablePolicy.h @@ -9,7 +9,17 @@ SPDX-License-Identifier: BSD-2-Clause-Patent #ifndef __EDKII_VARIABLE_POLICY_PROTOCOL__ #define __EDKII_VARIABLE_POLICY_PROTOCOL__ -#define EDKII_VARIABLE_POLICY_PROTOCOL_REVISION 0x0000000000010000 +#define EDKII_VARIABLE_POLICY_PROTOCOL_REVISION 0x0000000000020000 + +/* + Rev 0x0000000000010000: + - Initial protocol definition + + Rev 0x0000000000020000: + - Add GetVariablePolicyInfo() API + - Add GetLockOnVariableStateVariablePolicyInfo() API + +*/ #define EDKII_VARIABLE_POLICY_PROTOCOL_GUID \ { \ @@ -141,13 +151,122 @@ EFI_STATUS VOID ); +/** + This function will return variable policy information for a UEFI variable with a + registered variable policy. + + @param[in] VariableName The name of the variable to use for the policy search. + @param[in] VendorGuid The vendor GUID of the variable to use for the policy search. + @param[in,out] VariablePolicyVariableNameBufferSize On input, the size, in bytes, of the VariablePolicyVariableName + buffer. + + On output, the size, in bytes, needed to store the variable + policy variable name. + + If testing for the VariablePolicyVariableName buffer size + needed, set this value to zero so EFI_BUFFER_TOO_SMALL is + guaranteed to be returned if the variable policy variable name + is found. + @param[out] VariablePolicy Pointer to a buffer where the policy entry will be written + if found. + @param[out] VariablePolicyVariableName Pointer to a buffer where the variable name used for the + variable policy will be written if a variable name is + registered. + + If the variable policy is not associated with a variable name + (e.g. applied to variable vendor namespace) and this parameter + is given, this parameter will not be modified and + VariablePolicyVariableNameBufferSize will be set to zero to + indicate a name was not present. + + If the pointer given is not NULL, + VariablePolicyVariableNameBufferSize must be non-NULL. + + @retval EFI_SUCCESS A variable policy entry was found and returned successfully. + @retval EFI_BAD_BUFFER_SIZE An internal buffer size caused a calculation error. + @retval EFI_BUFFER_TOO_SMALL The VariablePolicyVariableName buffer value is too small for the size needed. + The buffer should now point to the size needed. + @retval EFI_NOT_READY Variable policy has not yet been initialized. + @retval EFI_INVALID_PARAMETER A required pointer argument passed is NULL. This will be returned if + VariablePolicyVariableName is non-NULL and VariablePolicyVariableNameBufferSize + is NULL. + @retval EFI_NOT_FOUND A variable policy was not found for the given UEFI variable name and vendor GUID. + +**/ +typedef +EFI_STATUS +(EFIAPI *GET_VARIABLE_POLICY_INFO)( + IN CONST CHAR16 *VariableName, + IN CONST EFI_GUID *VendorGuid, + IN OUT UINTN *VariablePolicyVariableNameBufferSize OPTIONAL, + OUT VARIABLE_POLICY_ENTRY *VariablePolicy, + OUT CHAR16 *VariablePolicyVariableName OPTIONAL + ); + +/** + This function will return the Lock on Variable State policy information for the policy + associated with the given UEFI variable. + + @param[in] VariableName The name of the variable to use for the policy search. + @param[in] VendorGuid The vendor GUID of the variable to use for the policy + search. + @param[in,out] VariableLockPolicyVariableNameBufferSize On input, the size, in bytes, of the + VariableLockPolicyVariableName buffer. + + On output, the size, in bytes, needed to store the variable + policy variable name. + + If testing for the VariableLockPolicyVariableName buffer + size needed, set this value to zero so EFI_BUFFER_TOO_SMALL + is guaranteed to be returned if the variable policy variable + name is found. + @param[out] VariablePolicy Pointer to a buffer where the policy entry will be written + if found. + @param[out] VariableLockPolicyVariableName Pointer to a buffer where the variable name used for the + variable lock on variable state policy will be written if + a variable name is registered. + + If the lock on variable policy is not associated with a + variable name (e.g. applied to variable vendor namespace) + and this parameter is given, this parameter will not be + modified and VariableLockPolicyVariableNameBufferSize will + be set to zero to indicate a name was not present. + + If the pointer given is not NULL, + VariableLockPolicyVariableNameBufferSize must be non-NULL. + + @retval EFI_SUCCESS A Lock on Variable State variable policy entry was found and returned + successfully. + @retval EFI_BAD_BUFFER_SIZE An internal buffer size caused a calculation error. + @retval EFI_BUFFER_TOO_SMALL The VariableLockPolicyVariableName buffer is too small for the size needed. + The buffer should now point to the size needed. + @retval EFI_NOT_READY Variable policy has not yet been initialized. + @retval EFI_INVALID_PARAMETER A required pointer argument passed is NULL. This will be returned if + VariableLockPolicyVariableName is non-NULL and + VariableLockPolicyVariableNameBufferSize is NULL. + @retval EFI_NOT_FOUND A Lock on Variable State variable policy was not found for the given UEFI + variable name and vendor GUID. + +**/ +typedef +EFI_STATUS +(EFIAPI *GET_LOCK_ON_VARIABLE_STATE_VARIABLE_POLICY_INFO)( + IN CONST CHAR16 *VariableName, + IN CONST EFI_GUID *VendorGuid, + IN OUT UINTN *VariableLockPolicyVariableNameBufferSize OPTIONAL, + OUT VARIABLE_LOCK_ON_VAR_STATE_POLICY *VariablePolicy, + OUT CHAR16 *VariableLockPolicyVariableName OPTIONAL + ); + typedef struct { - UINT64 Revision; - DISABLE_VARIABLE_POLICY DisableVariablePolicy; - IS_VARIABLE_POLICY_ENABLED IsVariablePolicyEnabled; - REGISTER_VARIABLE_POLICY RegisterVariablePolicy; - DUMP_VARIABLE_POLICY DumpVariablePolicy; - LOCK_VARIABLE_POLICY LockVariablePolicy; + UINT64 Revision; + DISABLE_VARIABLE_POLICY DisableVariablePolicy; + IS_VARIABLE_POLICY_ENABLED IsVariablePolicyEnabled; + REGISTER_VARIABLE_POLICY RegisterVariablePolicy; + DUMP_VARIABLE_POLICY DumpVariablePolicy; + LOCK_VARIABLE_POLICY LockVariablePolicy; + GET_VARIABLE_POLICY_INFO GetVariablePolicyInfo; + GET_LOCK_ON_VARIABLE_STATE_VARIABLE_POLICY_INFO GetLockOnVariableStateVariablePolicyInfo; } _EDKII_VARIABLE_POLICY_PROTOCOL; typedef _EDKII_VARIABLE_POLICY_PROTOCOL EDKII_VARIABLE_POLICY_PROTOCOL; diff --git a/MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLib.inf b/MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLib.inf index 3fe6043bf631..7048d555f0a9 100644 --- a/MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLib.inf +++ b/MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLib.inf @@ -32,6 +32,7 @@ [Packages] [LibraryClasses] + BaseLib DebugLib BaseMemoryLib MemoryAllocationLib -- 2.42.0.windows.2 -=-=-=-=-=-=-=-=-=-=-=- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#108841): https://edk2.groups.io/g/devel/message/108841 Mute This Topic: https://groups.io/mt/101457410/21656 Group Owner: devel+ow...@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [arch...@mail-archive.com] -=-=-=-=-=-=-=-=-=-=-=-