mirror of
https://github.com/CloverHackyColor/CloverBootloader.git
synced 2024-12-01 12:53:27 +01:00
411 lines
16 KiB
C
411 lines
16 KiB
C
/** @file -- VariablePolicyHelperLib.c
|
|
This library contains helper functions for marshalling and registering
|
|
new policies with the VariablePolicy infrastructure.
|
|
|
|
This library is currently written against VariablePolicy revision 0x00010000.
|
|
|
|
Copyright (c) Microsoft Corporation.
|
|
SPDX-License-Identifier: BSD-2-Clause-Patent
|
|
|
|
**/
|
|
|
|
#include <Uefi.h>
|
|
|
|
#include <Library/BaseLib.h>
|
|
#include <Library/DebugLib.h>
|
|
#include <Library/BaseMemoryLib.h>
|
|
#include <Library/MemoryAllocationLib.h>
|
|
|
|
#include <Protocol/VariablePolicy.h>
|
|
|
|
/**
|
|
This internal helper function populates the header structure,
|
|
all common fields, and takes care of fix-ups.
|
|
|
|
NOTE: Only use this internally. Assumes correctly-sized buffers.
|
|
|
|
@param[out] EntPtr Pointer to the buffer to be populated.
|
|
@param[in] Namespace Pointer to an EFI_GUID for the target variable namespace that this policy will protect.
|
|
@param[in] MinSize MinSize for the VariablePolicy.
|
|
@param[in] MaxSize MaxSize for the VariablePolicy.
|
|
@param[in] AttributesMustHave AttributesMustHave for the VariablePolicy.
|
|
@param[in] AttributesCantHave AttributesCantHave for the VariablePolicy.
|
|
@param[in] LockPolicyType LockPolicyType for the VariablePolicy.
|
|
|
|
**/
|
|
STATIC
|
|
VOID
|
|
PopulateCommonData (
|
|
OUT VARIABLE_POLICY_ENTRY *EntPtr,
|
|
IN CONST EFI_GUID *Namespace,
|
|
IN UINT32 MinSize,
|
|
IN UINT32 MaxSize,
|
|
IN UINT32 AttributesMustHave,
|
|
IN UINT32 AttributesCantHave,
|
|
IN UINT8 LockPolicyType
|
|
)
|
|
{
|
|
EntPtr->Version = VARIABLE_POLICY_ENTRY_REVISION;
|
|
CopyGuid (&EntPtr->Namespace, Namespace);
|
|
EntPtr->MinSize = MinSize;
|
|
EntPtr->MaxSize = MaxSize;
|
|
EntPtr->AttributesMustHave = AttributesMustHave;
|
|
EntPtr->AttributesCantHave = AttributesCantHave;
|
|
EntPtr->LockPolicyType = LockPolicyType;
|
|
|
|
// NOTE: As a heler, fix up MaxSize for compatibility with the old model.
|
|
if (EntPtr->MaxSize == 0) {
|
|
EntPtr->MaxSize = VARIABLE_POLICY_NO_MAX_SIZE;
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
/**
|
|
This helper function will allocate and populate a new VariablePolicy
|
|
structure for a policy that does not contain any sub-structures (such as
|
|
VARIABLE_LOCK_ON_VAR_STATE_POLICY).
|
|
|
|
NOTE: Caller will need to free structure once finished.
|
|
|
|
@param[in] Namespace Pointer to an EFI_GUID for the target variable namespace that this policy will protect.
|
|
@param[in] Name [Optional] If provided, a pointer to the CHAR16 array for the target variable name.
|
|
Otherwise, will create a policy that targets an entire namespace.
|
|
@param[in] MinSize MinSize for the VariablePolicy.
|
|
@param[in] MaxSize MaxSize for the VariablePolicy.
|
|
@param[in] AttributesMustHave AttributesMustHave for the VariablePolicy.
|
|
@param[in] AttributesCantHave AttributesCantHave for the VariablePolicy.
|
|
@param[in] LockPolicyType LockPolicyType for the VariablePolicy.
|
|
@param[out] NewEntry If successful, will be set to a pointer to the allocated buffer containing the
|
|
new policy.
|
|
|
|
@retval EFI_SUCCESS Operation completed successfully and structure is populated.
|
|
@retval EFI_INVALID_PARAMETER Namespace is NULL.
|
|
@retval EFI_INVALID_PARAMETER LockPolicyType is invalid for a basic structure.
|
|
@retval EFI_BUFFER_TOO_SMALL Finished structure would not fit in UINT16 size.
|
|
@retval EFI_OUT_OF_RESOURCES Could not allocate sufficient space for structure.
|
|
|
|
**/
|
|
EFI_STATUS
|
|
EFIAPI
|
|
CreateBasicVariablePolicy (
|
|
IN CONST EFI_GUID *Namespace,
|
|
IN CONST CHAR16 *Name OPTIONAL,
|
|
IN UINT32 MinSize,
|
|
IN UINT32 MaxSize,
|
|
IN UINT32 AttributesMustHave,
|
|
IN UINT32 AttributesCantHave,
|
|
IN UINT8 LockPolicyType,
|
|
OUT VARIABLE_POLICY_ENTRY **NewEntry
|
|
)
|
|
{
|
|
UINTN TotalSize;
|
|
UINTN NameSize;
|
|
VARIABLE_POLICY_ENTRY *EntPtr;
|
|
CHAR16 *CopyName;
|
|
|
|
// Check some initial invalid parameters for this function.
|
|
if ((Namespace == NULL) || (NewEntry == NULL)) {
|
|
return EFI_INVALID_PARAMETER;
|
|
}
|
|
|
|
if ((LockPolicyType != VARIABLE_POLICY_TYPE_NO_LOCK) &&
|
|
(LockPolicyType != VARIABLE_POLICY_TYPE_LOCK_NOW) &&
|
|
(LockPolicyType != VARIABLE_POLICY_TYPE_LOCK_ON_CREATE))
|
|
{
|
|
return EFI_INVALID_PARAMETER;
|
|
}
|
|
|
|
//
|
|
// Set NameSize to suppress incorrect compiler/analyzer warnings
|
|
//
|
|
NameSize = 0;
|
|
|
|
// Now we've gotta determine the total size of the buffer required for
|
|
// the VariablePolicy structure.
|
|
TotalSize = sizeof (VARIABLE_POLICY_ENTRY);
|
|
if (Name != NULL) {
|
|
NameSize = StrnSizeS (Name, MAX_UINT16);
|
|
TotalSize += NameSize;
|
|
}
|
|
|
|
// Make sure the size fits within a VARIABLE_POLICY_ENTRY.Size.
|
|
ASSERT (TotalSize <= MAX_UINT16);
|
|
if (TotalSize > MAX_UINT16) {
|
|
return EFI_BUFFER_TOO_SMALL;
|
|
}
|
|
|
|
// Allocate a buffer to hold all the data. We're on the home stretch.
|
|
*NewEntry = AllocatePool (TotalSize);
|
|
if (*NewEntry == NULL) {
|
|
return EFI_OUT_OF_RESOURCES;
|
|
}
|
|
|
|
// If we're still here, we're basically done.
|
|
// Copy the data and GET... OUT....
|
|
EntPtr = *NewEntry;
|
|
PopulateCommonData (
|
|
EntPtr,
|
|
Namespace,
|
|
MinSize,
|
|
MaxSize,
|
|
AttributesMustHave,
|
|
AttributesCantHave,
|
|
LockPolicyType
|
|
);
|
|
EntPtr->Size = (UINT16)TotalSize; // This is safe because we've already checked.
|
|
EntPtr->OffsetToName = sizeof (VARIABLE_POLICY_ENTRY);
|
|
if (Name != NULL) {
|
|
CopyName = (CHAR16 *)((UINT8 *)EntPtr + EntPtr->OffsetToName);
|
|
CopyMem (CopyName, Name, NameSize);
|
|
}
|
|
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
This helper function will allocate and populate a new VariablePolicy
|
|
structure for a policy with a lock type of VARIABLE_POLICY_TYPE_LOCK_ON_VAR_STATE.
|
|
|
|
NOTE: Caller will need to free structure once finished.
|
|
|
|
@param[in] Namespace Pointer to an EFI_GUID for the target variable namespace that this policy will protect.
|
|
@param[in] Name [Optional] If provided, a pointer to the CHAR16 array for the target variable name.
|
|
Otherwise, will create a policy that targets an entire namespace.
|
|
@param[in] MinSize MinSize for the VariablePolicy.
|
|
@param[in] MaxSize MaxSize for the VariablePolicy.
|
|
@param[in] AttributesMustHave AttributesMustHave for the VariablePolicy.
|
|
@param[in] AttributesCantHave AttributesCantHave for the VariablePolicy.
|
|
@param[in] VarStateNamespace Pointer to the EFI_GUID for the VARIABLE_LOCK_ON_VAR_STATE_POLICY.Namespace.
|
|
@param[in] VarStateValue Value for the VARIABLE_LOCK_ON_VAR_STATE_POLICY.Value.
|
|
@param[in] VarStateName Pointer to the CHAR16 array for the VARIABLE_LOCK_ON_VAR_STATE_POLICY.Name.
|
|
@param[out] NewEntry If successful, will be set to a pointer to the allocated buffer containing the
|
|
new policy.
|
|
|
|
@retval EFI_SUCCESS Operation completed successfully and structure is populated.
|
|
@retval EFI_INVALID_PARAMETER Namespace, VarStateNamespace, VarStateName is NULL.
|
|
@retval EFI_BUFFER_TOO_SMALL Finished structure would not fit in UINT16 size.
|
|
@retval EFI_OUT_OF_RESOURCES Could not allocate sufficient space for structure.
|
|
|
|
**/
|
|
EFI_STATUS
|
|
EFIAPI
|
|
CreateVarStateVariablePolicy (
|
|
IN CONST EFI_GUID *Namespace,
|
|
IN CONST CHAR16 *Name OPTIONAL,
|
|
IN UINT32 MinSize,
|
|
IN UINT32 MaxSize,
|
|
IN UINT32 AttributesMustHave,
|
|
IN UINT32 AttributesCantHave,
|
|
IN CONST EFI_GUID *VarStateNamespace,
|
|
IN UINT8 VarStateValue,
|
|
IN CONST CHAR16 *VarStateName,
|
|
OUT VARIABLE_POLICY_ENTRY **NewEntry
|
|
)
|
|
{
|
|
UINTN TotalSize;
|
|
UINTN NameSize;
|
|
UINTN VarStateNameSize;
|
|
VARIABLE_POLICY_ENTRY *EntPtr;
|
|
CHAR16 *CopyName;
|
|
VARIABLE_LOCK_ON_VAR_STATE_POLICY *CopyPolicy;
|
|
|
|
// Check some initial invalid parameters for this function.
|
|
if ((Namespace == NULL) || (VarStateNamespace == NULL) ||
|
|
(VarStateName == NULL) || (NewEntry == NULL))
|
|
{
|
|
return EFI_INVALID_PARAMETER;
|
|
}
|
|
|
|
// Now we've gotta determine the total size of the buffer required for
|
|
// the VariablePolicy structure.
|
|
VarStateNameSize = StrnSizeS (VarStateName, MAX_UINT16);
|
|
TotalSize = sizeof (VARIABLE_POLICY_ENTRY) +
|
|
sizeof (VARIABLE_LOCK_ON_VAR_STATE_POLICY) +
|
|
VarStateNameSize;
|
|
if (Name != NULL) {
|
|
NameSize = StrnSizeS (Name, MAX_UINT16);
|
|
TotalSize += NameSize;
|
|
}
|
|
|
|
// Make sure the size fits within a VARIABLE_POLICY_ENTRY.Size.
|
|
ASSERT (TotalSize <= MAX_UINT16);
|
|
if (TotalSize > MAX_UINT16) {
|
|
return EFI_BUFFER_TOO_SMALL;
|
|
}
|
|
|
|
// Allocate a buffer to hold all the data. We're on the home stretch.
|
|
*NewEntry = AllocatePool (TotalSize);
|
|
if (*NewEntry == NULL) {
|
|
return EFI_OUT_OF_RESOURCES;
|
|
}
|
|
|
|
// If we're still here, we're basically done.
|
|
// Copy the data and GET... OUT....
|
|
EntPtr = *NewEntry;
|
|
PopulateCommonData (
|
|
EntPtr,
|
|
Namespace,
|
|
MinSize,
|
|
MaxSize,
|
|
AttributesMustHave,
|
|
AttributesCantHave,
|
|
VARIABLE_POLICY_TYPE_LOCK_ON_VAR_STATE
|
|
);
|
|
EntPtr->Size = (UINT16)TotalSize; // This is safe because we've already checked.
|
|
EntPtr->OffsetToName = sizeof (VARIABLE_POLICY_ENTRY) +
|
|
sizeof (VARIABLE_LOCK_ON_VAR_STATE_POLICY) +
|
|
(UINT16)VarStateNameSize;
|
|
|
|
CopyPolicy = (VARIABLE_LOCK_ON_VAR_STATE_POLICY *)((UINT8 *)EntPtr + sizeof (VARIABLE_POLICY_ENTRY));
|
|
CopyName = (CHAR16 *)((UINT8 *)CopyPolicy + sizeof (VARIABLE_LOCK_ON_VAR_STATE_POLICY));
|
|
CopyGuid (&CopyPolicy->Namespace, VarStateNamespace);
|
|
CopyPolicy->Value = VarStateValue;
|
|
CopyMem (CopyName, VarStateName, VarStateNameSize);
|
|
|
|
if (Name != NULL) {
|
|
CopyName = (CHAR16 *)((UINT8 *)EntPtr + EntPtr->OffsetToName);
|
|
CopyMem (CopyName, Name, NameSize);
|
|
}
|
|
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
This helper function does everything that CreateBasicVariablePolicy() does, but also
|
|
uses the passed in protocol to register the policy with the infrastructure.
|
|
Does not return a buffer, does not require the caller to free anything.
|
|
|
|
@param[in] VariablePolicy Pointer to a valid instance of the VariablePolicy protocol.
|
|
@param[in] Namespace Pointer to an EFI_GUID for the target variable namespace that this policy will protect.
|
|
@param[in] Name [Optional] If provided, a pointer to the CHAR16 array for the target variable name.
|
|
Otherwise, will create a policy that targets an entire namespace.
|
|
@param[in] MinSize MinSize for the VariablePolicy.
|
|
@param[in] MaxSize MaxSize for the VariablePolicy.
|
|
@param[in] AttributesMustHave AttributesMustHave for the VariablePolicy.
|
|
@param[in] AttributesCantHave AttributesCantHave for the VariablePolicy.
|
|
@param[in] LockPolicyType LockPolicyType for the VariablePolicy.
|
|
|
|
@retval EFI_INVALID_PARAMETER VariablePolicy pointer is NULL.
|
|
@retval EFI_STATUS Status returned by CreateBasicVariablePolicy() or RegisterVariablePolicy().
|
|
|
|
**/
|
|
EFI_STATUS
|
|
EFIAPI
|
|
RegisterBasicVariablePolicy (
|
|
IN EDKII_VARIABLE_POLICY_PROTOCOL *VariablePolicy,
|
|
IN CONST EFI_GUID *Namespace,
|
|
IN CONST CHAR16 *Name OPTIONAL,
|
|
IN UINT32 MinSize,
|
|
IN UINT32 MaxSize,
|
|
IN UINT32 AttributesMustHave,
|
|
IN UINT32 AttributesCantHave,
|
|
IN UINT8 LockPolicyType
|
|
)
|
|
{
|
|
VARIABLE_POLICY_ENTRY *NewEntry;
|
|
EFI_STATUS Status;
|
|
|
|
// Check the simple things.
|
|
if (VariablePolicy == NULL) {
|
|
return EFI_INVALID_PARAMETER;
|
|
}
|
|
|
|
// Create the new entry and make sure that everything worked.
|
|
NewEntry = NULL;
|
|
Status = CreateBasicVariablePolicy (
|
|
Namespace,
|
|
Name,
|
|
MinSize,
|
|
MaxSize,
|
|
AttributesMustHave,
|
|
AttributesCantHave,
|
|
LockPolicyType,
|
|
&NewEntry
|
|
);
|
|
|
|
// If that was successful, attempt to register the new policy.
|
|
if (!EFI_ERROR (Status)) {
|
|
Status = VariablePolicy->RegisterVariablePolicy (NewEntry);
|
|
}
|
|
|
|
// If we allocated the buffer, free the buffer.
|
|
if (NewEntry != NULL) {
|
|
FreePool (NewEntry);
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|
|
/**
|
|
This helper function does everything that CreateBasicVariablePolicy() does, but also
|
|
uses the passed in protocol to register the policy with the infrastructure.
|
|
Does not return a buffer, does not require the caller to free anything.
|
|
|
|
@param[in] VariablePolicy Pointer to a valid instance of the VariablePolicy protocol.
|
|
@param[in] Namespace Pointer to an EFI_GUID for the target variable namespace that this policy will protect.
|
|
@param[in] Name [Optional] If provided, a pointer to the CHAR16 array for the target variable name.
|
|
Otherwise, will create a policy that targets an entire namespace.
|
|
@param[in] MinSize MinSize for the VariablePolicy.
|
|
@param[in] MaxSize MaxSize for the VariablePolicy.
|
|
@param[in] AttributesMustHave AttributesMustHave for the VariablePolicy.
|
|
@param[in] AttributesCantHave AttributesCantHave for the VariablePolicy.
|
|
@param[in] VarStateNamespace Pointer to the EFI_GUID for the VARIABLE_LOCK_ON_VAR_STATE_POLICY.Namespace.
|
|
@param[in] VarStateName Pointer to the CHAR16 array for the VARIABLE_LOCK_ON_VAR_STATE_POLICY.Name.
|
|
@param[in] VarStateValue Value for the VARIABLE_LOCK_ON_VAR_STATE_POLICY.Value.
|
|
|
|
@retval EFI_INVALID_PARAMETER VariablePolicy pointer is NULL.
|
|
@retval EFI_STATUS Status returned by CreateBasicVariablePolicy() or RegisterVariablePolicy().
|
|
|
|
**/
|
|
EFI_STATUS
|
|
EFIAPI
|
|
RegisterVarStateVariablePolicy (
|
|
IN EDKII_VARIABLE_POLICY_PROTOCOL *VariablePolicy,
|
|
IN CONST EFI_GUID *Namespace,
|
|
IN CONST CHAR16 *Name OPTIONAL,
|
|
IN UINT32 MinSize,
|
|
IN UINT32 MaxSize,
|
|
IN UINT32 AttributesMustHave,
|
|
IN UINT32 AttributesCantHave,
|
|
IN CONST EFI_GUID *VarStateNamespace,
|
|
IN CONST CHAR16 *VarStateName,
|
|
IN UINT8 VarStateValue
|
|
)
|
|
{
|
|
VARIABLE_POLICY_ENTRY *NewEntry;
|
|
EFI_STATUS Status;
|
|
|
|
// Check the simple things.
|
|
if (VariablePolicy == NULL) {
|
|
return EFI_INVALID_PARAMETER;
|
|
}
|
|
|
|
// Create the new entry and make sure that everything worked.
|
|
NewEntry = NULL;
|
|
Status = CreateVarStateVariablePolicy (
|
|
Namespace,
|
|
Name,
|
|
MinSize,
|
|
MaxSize,
|
|
AttributesMustHave,
|
|
AttributesCantHave,
|
|
VarStateNamespace,
|
|
VarStateValue,
|
|
VarStateName,
|
|
&NewEntry
|
|
);
|
|
|
|
// If that was successful, attempt to register the new policy.
|
|
if (!EFI_ERROR (Status)) {
|
|
Status = VariablePolicy->RegisterVariablePolicy (NewEntry);
|
|
}
|
|
|
|
// If we allocated the buffer, free the buffer.
|
|
if (NewEntry != NULL) {
|
|
FreePool (NewEntry);
|
|
}
|
|
|
|
return Status;
|
|
}
|