18#include <Protocol/VariablePolicy.h>
19#include <Library/VariablePolicyLib.h>
27#ifdef INTERNAL_UNIT_TEST
44UINT8 *mPolicyTable =
NULL;
45STATIC UINT32 mCurrentTableSize = 0;
46STATIC UINT32 mCurrentTableUsage = 0;
47STATIC UINT32 mCurrentTableCount = 0;
49#define POLICY_TABLE_STEP_SIZE 0x1000
53#define GET_NEXT_POLICY(CurPolicy) (VARIABLE_POLICY_ENTRY*)((UINT8*)CurPolicy + CurPolicy->Size)
54#define GET_POLICY_NAME(CurPolicy) (CHAR16*)((UINTN)CurPolicy + CurPolicy->OffsetToName)
56#define MATCH_PRIORITY_EXACT 0
57#define MATCH_PRIORITY_MAX MATCH_PRIORITY_EXACT
58#define MATCH_PRIORITY_MIN MAX_UINT8
69VariablePolicyExtraInit (
82VariablePolicyExtraDeinit (
99IsValidVariablePolicyStructure (
109 if ((NewPolicy ==
NULL) || (NewPolicy->Size == 0) ||
113 (NewPolicy->Version != VARIABLE_POLICY_ENTRY_REVISION))
121 if (EFI_ERROR (Status)) {
126 if (NewPolicy->MaxSize == 0) {
131 if ((NewPolicy->LockPolicyType != VARIABLE_POLICY_TYPE_NO_LOCK) &&
132 (NewPolicy->LockPolicyType != VARIABLE_POLICY_TYPE_LOCK_NOW) &&
133 (NewPolicy->LockPolicyType != VARIABLE_POLICY_TYPE_LOCK_ON_CREATE) &&
134 (NewPolicy->LockPolicyType != VARIABLE_POLICY_TYPE_LOCK_ON_VAR_STATE))
141 if (NewPolicy->LockPolicyType == VARIABLE_POLICY_TYPE_LOCK_ON_VAR_STATE) {
148 if (EFI_ERROR (Status) || (EntryEnd <= (
UINTN)CheckChar)) {
152 while (*CheckChar != CHAR_NULL) {
153 if (EntryEnd <= (
UINTN)CheckChar) {
162 if ((
UINTN)++ CheckChar != (
UINTN)NewPolicy + NewPolicy->OffsetToName) {
176 if (NewPolicy->Size != NewPolicy->OffsetToName) {
177 CheckChar = (CHAR16 *)((
UINTN)NewPolicy + NewPolicy->OffsetToName);
179 while (*CheckChar != CHAR_NULL) {
181 if (*CheckChar == L
'#') {
183 if (WildcardCount > MATCH_PRIORITY_MIN) {
189 if (EntryEnd <= (
UINTN)CheckChar) {
198 if ((
UINTN)++ CheckChar != EntryEnd) {
231 OUT UINT8 *MatchPriority OPTIONAL
236 UINT8 CalculatedPriority;
240 CalculatedPriority = MATCH_PRIORITY_EXACT;
243 if (!
CompareGuid (&EvalEntry->Namespace, VendorGuid)) {
250 if (EvalEntry->Size == EvalEntry->OffsetToName) {
251 CalculatedPriority = MATCH_PRIORITY_MIN;
257 PolicyName = GET_POLICY_NAME (EvalEntry);
264 while (PolicyName[Index] != CHAR_NULL || VariableName[Index] != CHAR_NULL) {
266 if ((PolicyName[Index] != VariableName[Index]) || (PolicyName[Index] == L
'#')) {
269 if ((PolicyName[Index] == L
'#') &&
270 (((L
'0' <= VariableName[Index]) && (VariableName[Index] <= L
'9')) ||
271 ((L
'A' <= VariableName[Index]) && (VariableName[Index] <= L
'F')) ||
272 ((L
'a' <= VariableName[Index]) && (VariableName[Index] <= L
'f'))))
274 if (CalculatedPriority < MATCH_PRIORITY_MIN) {
275 CalculatedPriority++;
289 if (Result && (MatchPriority !=
NULL)) {
290 *MatchPriority = CalculatedPriority;
316 OUT UINT8 *ReturnPriority OPTIONAL
322 UINT8 CurrentPriority;
326 MatchPriority = MATCH_PRIORITY_EXACT;
330 for (Index = 0; Index < mCurrentTableCount; Index++) {
332 if (EvaluatePolicyMatch (CurrentEntry, VariableName, VendorGuid, &CurrentPriority)) {
334 if ((BestResult ==
NULL) || (CurrentPriority < MatchPriority)) {
335 BestResult = CurrentEntry;
336 MatchPriority = CurrentPriority;
340 if (MatchPriority == 0) {
346 CurrentEntry = GET_NEXT_POLICY (CurrentEntry);
350 if (ReturnPriority !=
NULL) {
351 *ReturnPriority = MatchPriority;
375RegisterVariablePolicy (
385 if (!IsVariablePolicyLibInitialized ()) {
386 return EFI_NOT_READY;
389 if (mInterfaceLocked) {
390 return EFI_WRITE_PROTECTED;
393 if (!IsValidVariablePolicyStructure (NewPolicy)) {
394 return EFI_INVALID_PARAMETER;
398 MatchPolicy = GetBestPolicyMatch (
399 GET_POLICY_NAME (NewPolicy),
400 &NewPolicy->Namespace,
403 if ((MatchPolicy !=
NULL) && (MatchPriority == MATCH_PRIORITY_EXACT)) {
404 return EFI_ALREADY_STARTED;
409 Status =
SafeUint32Add (mCurrentTableUsage, NewPolicy->Size, &NewSize);
410 if (EFI_ERROR (Status)) {
414 if (NewSize > mCurrentTableSize) {
416 NewSize = (NewSize % POLICY_TABLE_STEP_SIZE) > 0 ?
417 (NewSize / POLICY_TABLE_STEP_SIZE) + 1 :
418 (NewSize / POLICY_TABLE_STEP_SIZE);
420 Status =
SafeUint32Mult (NewSize, POLICY_TABLE_STEP_SIZE, &NewSize);
421 if (EFI_ERROR (Status)) {
427 if (NewTable ==
NULL) {
428 return EFI_OUT_OF_RESOURCES;
431 CopyMem (NewTable, mPolicyTable, mCurrentTableUsage);
432 mCurrentTableSize = NewSize;
433 if (mPolicyTable !=
NULL) {
437 mPolicyTable = NewTable;
441 CopyMem (mPolicyTable + mCurrentTableUsage, NewPolicy, NewPolicy->Size);
442 mCurrentTableUsage += NewPolicy->Size;
443 mCurrentTableCount += 1;
472 IN CHAR16 *VariableName,
474 IN UINT32 Attributes,
484 CHAR16 *StateVarName;
490 if (!IsVariablePolicyLibInitialized ()) {
491 ReturnStatus = EFI_NOT_READY;
496 if (mProtectionDisabled) {
503 if ((DataSize == 0) && ((Attributes & EFI_VARIABLE_APPEND_WRITE) == 0)) {
510 ActivePolicy = GetBestPolicyMatch (VariableName, VendorGuid,
NULL);
513 if (ActivePolicy !=
NULL) {
518 if (((ActivePolicy->MinSize > 0) && (DataSize < ActivePolicy->MinSize)) ||
519 ((ActivePolicy->MaxSize > 0) && (DataSize > ActivePolicy->MaxSize)))
521 ReturnStatus = EFI_INVALID_PARAMETER;
524 "%a - Bad Size. 0x%X <> 0x%X-0x%X\n",
527 ActivePolicy->MinSize,
528 ActivePolicy->MaxSize
534 if (((ActivePolicy->AttributesMustHave & Attributes) != ActivePolicy->AttributesMustHave) ||
535 ((ActivePolicy->AttributesCantHave & Attributes) != 0))
537 ReturnStatus = EFI_INVALID_PARAMETER;
540 "%a - Bad Attributes. 0x%X <> 0x%X:0x%X\n",
543 ActivePolicy->AttributesMustHave,
544 ActivePolicy->AttributesCantHave
554 if (ActivePolicy->LockPolicyType == VARIABLE_POLICY_TYPE_LOCK_NOW) {
555 ReturnStatus = EFI_WRITE_PROTECTED;
558 }
else if (ActivePolicy->LockPolicyType == VARIABLE_POLICY_TYPE_LOCK_ON_CREATE) {
560 Status = mGetVariableHelper (
567 if (Status == EFI_BUFFER_TOO_SMALL) {
568 ReturnStatus = EFI_WRITE_PROTECTED;
573 }
else if (ActivePolicy->LockPolicyType == VARIABLE_POLICY_TYPE_LOCK_ON_VAR_STATE) {
576 StateVarSize =
sizeof (StateVar);
577 Status = mGetVariableHelper (
579 &StateVarPolicy->Namespace,
586 if (!EFI_ERROR (Status)) {
587 if (StateVar == StateVarPolicy->Value) {
588 ReturnStatus = EFI_WRITE_PROTECTED;
593 }
else if ((Status != EFI_NOT_FOUND) && (Status != EFI_BUFFER_TOO_SMALL)) {
595 ReturnStatus = EFI_ABORTED;
602 DEBUG ((DEBUG_VERBOSE,
"%a - Variable (%g:%s) returning %r.\n", __func__, VendorGuid, VariableName, ReturnStatus));
619DisableVariablePolicy (
623 if (!IsVariablePolicyLibInitialized ()) {
624 return EFI_NOT_READY;
627 if (mProtectionDisabled) {
628 return EFI_ALREADY_STARTED;
631 if (mInterfaceLocked) {
632 return EFI_WRITE_PROTECTED;
635 if (!
PcdGetBool (PcdAllowVariablePolicyEnforcementDisable)) {
636 return EFI_WRITE_PROTECTED;
639 mProtectionDisabled =
TRUE;
666 if (!IsVariablePolicyLibInitialized ()) {
667 return EFI_NOT_READY;
671 if ((Size ==
NULL) || ((*Size > 0) && (Policy ==
NULL))) {
672 return EFI_INVALID_PARAMETER;
676 if (*Size < mCurrentTableUsage) {
677 *Size = mCurrentTableUsage;
678 return EFI_BUFFER_TOO_SMALL;
682 CopyMem (Policy, mPolicyTable, mCurrentTableUsage);
683 *Size = mCurrentTableUsage;
732GetVariablePolicyInfo (
735 IN OUT UINTN *VariablePolicyVariableNameBufferSize OPTIONAL,
737 OUT CHAR16 *VariablePolicyVariableName OPTIONAL
742 UINTN LocalVariablePolicyVariableNameBufferSize;
743 UINTN RequiredVariablePolicyVariableNameBufferSize;
748 if (!IsVariablePolicyLibInitialized ()) {
749 return EFI_NOT_READY;
752 if ((VariableName ==
NULL) || (VendorGuid ==
NULL) || (VariablePolicy ==
NULL)) {
753 return EFI_INVALID_PARAMETER;
756 MatchPolicy = GetBestPolicyMatch (
761 if (MatchPolicy !=
NULL) {
762 CopyMem (VariablePolicy, MatchPolicy,
sizeof (*VariablePolicy));
764 if (VariablePolicyVariableNameBufferSize ==
NULL) {
765 if (VariablePolicyVariableName !=
NULL) {
766 return EFI_INVALID_PARAMETER;
772 if (MatchPolicy->Size != MatchPolicy->OffsetToName) {
773 if (MatchPolicy->Size < MatchPolicy->OffsetToName) {
774 ASSERT (MatchPolicy->Size > MatchPolicy->OffsetToName);
775 return EFI_BAD_BUFFER_SIZE;
778 RequiredVariablePolicyVariableNameBufferSize = (
UINTN)(MatchPolicy->Size - MatchPolicy->OffsetToName);
779 ASSERT (RequiredVariablePolicyVariableNameBufferSize > 0);
781 if (*VariablePolicyVariableNameBufferSize < RequiredVariablePolicyVariableNameBufferSize) {
783 *VariablePolicyVariableNameBufferSize = RequiredVariablePolicyVariableNameBufferSize;
784 return EFI_BUFFER_TOO_SMALL;
787 if (VariablePolicyVariableName ==
NULL) {
789 *VariablePolicyVariableNameBufferSize = RequiredVariablePolicyVariableNameBufferSize;
790 return EFI_INVALID_PARAMETER;
793 LocalVariablePolicyVariableNameBufferSize = *VariablePolicyVariableNameBufferSize;
797 ((
StrnLenS (GET_POLICY_NAME (MatchPolicy), RequiredVariablePolicyVariableNameBufferSize) + 1) *
sizeof (CHAR16))
798 != RequiredVariablePolicyVariableNameBufferSize)
801 return EFI_BAD_BUFFER_SIZE;
804 *VariablePolicyVariableNameBufferSize = RequiredVariablePolicyVariableNameBufferSize;
807 VariablePolicyVariableName,
808 LocalVariablePolicyVariableNameBufferSize /
sizeof (CHAR16),
809 GET_POLICY_NAME (MatchPolicy),
810 RequiredVariablePolicyVariableNameBufferSize /
sizeof (CHAR16)
815 *VariablePolicyVariableNameBufferSize = 0;
821 return EFI_NOT_FOUND;
871GetLockOnVariableStateVariablePolicyInfo (
874 IN OUT UINTN *VariableLockPolicyVariableNameBufferSize OPTIONAL,
876 OUT CHAR16 *VariableLockPolicyVariableName OPTIONAL
881 UINTN RequiredVariablePolicyVariableNameBufferSize;
882 UINTN RequiredVariableLockPolicyVariableNameBufferSize;
883 UINTN LocalVariablePolicyLockVariableNameBufferSize;
884 UINTN LockOnVarStatePolicyEndOffset;
885 CHAR16 *LocalVariableLockPolicyVariableName;
891 if (!IsVariablePolicyLibInitialized ()) {
892 return EFI_NOT_READY;
895 if ((VariableName ==
NULL) || (VendorGuid ==
NULL) || (VariablePolicy ==
NULL)) {
896 return EFI_INVALID_PARAMETER;
899 MatchPolicy = GetBestPolicyMatch (
904 if (MatchPolicy !=
NULL) {
905 if (MatchPolicy->LockPolicyType != VARIABLE_POLICY_TYPE_LOCK_ON_VAR_STATE) {
906 return EFI_NOT_FOUND;
912 &LockOnVarStatePolicyEndOffset
914 if (EFI_ERROR (Status) || (LockOnVarStatePolicyEndOffset > (
UINTN)MatchPolicy->Size)) {
915 return EFI_BAD_BUFFER_SIZE;
919 CopyMem (VariablePolicy, LocalLockOnVarStatePolicy,
sizeof (*LocalLockOnVarStatePolicy));
921 if (VariableLockPolicyVariableNameBufferSize ==
NULL) {
922 if (VariableLockPolicyVariableName !=
NULL) {
923 return EFI_INVALID_PARAMETER;
930 if (MatchPolicy->Size < MatchPolicy->OffsetToName) {
931 return EFI_BAD_BUFFER_SIZE;
934 RequiredVariablePolicyVariableNameBufferSize = (
UINTN)(MatchPolicy->Size - MatchPolicy->OffsetToName);
935 RequiredVariableLockPolicyVariableNameBufferSize = MatchPolicy->Size -
936 (LockOnVarStatePolicyEndOffset + RequiredVariablePolicyVariableNameBufferSize);
938 LocalVariablePolicyLockVariableNameBufferSize = *VariableLockPolicyVariableNameBufferSize;
939 *VariableLockPolicyVariableNameBufferSize = RequiredVariableLockPolicyVariableNameBufferSize;
941 if (LocalVariablePolicyLockVariableNameBufferSize < RequiredVariableLockPolicyVariableNameBufferSize) {
943 return EFI_BUFFER_TOO_SMALL;
946 if (VariableLockPolicyVariableName ==
NULL) {
948 return EFI_INVALID_PARAMETER;
951 if (RequiredVariableLockPolicyVariableNameBufferSize == 0) {
955 LocalVariableLockPolicyVariableName = (CHAR16 *)((UINT8 *)LocalLockOnVarStatePolicy +
sizeof (*LocalLockOnVarStatePolicy));
956 *VariableLockPolicyVariableNameBufferSize = RequiredVariableLockPolicyVariableNameBufferSize;
960 (RequiredVariablePolicyVariableNameBufferSize > 0) &&
961 (((
StrnLenS (GET_POLICY_NAME (MatchPolicy), RequiredVariablePolicyVariableNameBufferSize) + 1) *
sizeof (CHAR16)) !=
962 RequiredVariablePolicyVariableNameBufferSize))
965 return EFI_BAD_BUFFER_SIZE;
970 ((
StrnLenS (LocalVariableLockPolicyVariableName, RequiredVariableLockPolicyVariableNameBufferSize) + 1) *
sizeof (CHAR16)) !=
971 RequiredVariableLockPolicyVariableNameBufferSize)
974 return EFI_BAD_BUFFER_SIZE;
978 VariableLockPolicyVariableName,
979 LocalVariablePolicyLockVariableNameBufferSize /
sizeof (CHAR16),
980 LocalVariableLockPolicyVariableName,
981 RequiredVariableLockPolicyVariableNameBufferSize /
sizeof (CHAR16)
988 return EFI_NOT_FOUND;
1002IsVariablePolicyEnabled (
1006 if (!IsVariablePolicyLibInitialized ()) {
1010 return !mProtectionDisabled;
1027 if (!IsVariablePolicyLibInitialized ()) {
1028 return EFI_NOT_READY;
1031 if (mInterfaceLocked) {
1032 return EFI_WRITE_PROTECTED;
1035 mInterfaceLocked =
TRUE;
1050IsVariablePolicyInterfaceLocked (
1054 if (!IsVariablePolicyLibInitialized ()) {
1058 return mInterfaceLocked;
1077InitVariablePolicyLib (
1085 if (mGetVariableHelper !=
NULL) {
1086 return EFI_ALREADY_STARTED;
1089 if (!EFI_ERROR (Status)) {
1090 Status = VariablePolicyExtraInit ();
1093 if (!EFI_ERROR (Status)) {
1095 mGetVariableHelper = GetVariableHelper;
1098 mInterfaceLocked =
FALSE;
1099 mProtectionDisabled =
FALSE;
1100 mPolicyTable =
NULL;
1101 mCurrentTableSize = 0;
1102 mCurrentTableUsage = 0;
1103 mCurrentTableCount = 0;
1118IsVariablePolicyLibInitialized (
1122 return (mGetVariableHelper !=
NULL);
1136DeinitVariablePolicyLib (
1144 if (mGetVariableHelper ==
NULL) {
1145 return EFI_NOT_READY;
1148 if (!EFI_ERROR (Status)) {
1149 Status = VariablePolicyExtraDeinit ();
1152 if (!EFI_ERROR (Status)) {
1153 mGetVariableHelper =
NULL;
1154 mInterfaceLocked =
FALSE;
1155 mProtectionDisabled =
FALSE;
1156 mCurrentTableSize = 0;
1157 mCurrentTableUsage = 0;
1158 mCurrentTableCount = 0;
1160 if (mPolicyTable !=
NULL) {
1162 mPolicyTable =
NULL;
UINTN EFIAPI StrnLenS(IN CONST CHAR16 *String, IN UINTN MaxSize)
RETURN_STATUS EFIAPI StrnCpyS(OUT CHAR16 *Destination, IN UINTN DestMax, IN CONST CHAR16 *Source, IN UINTN Length)
VOID *EFIAPI CopyMem(OUT VOID *DestinationBuffer, IN CONST VOID *SourceBuffer, IN UINTN Length)
BOOLEAN EFIAPI CompareGuid(IN CONST GUID *Guid1, IN CONST GUID *Guid2)
VOID EFIAPI FreePool(IN VOID *Buffer)
VOID *EFIAPI AllocateRuntimePool(IN UINTN AllocationSize)
#define ASSERT_EFI_ERROR(StatusParameter)
#define DEBUG(Expression)
#define PcdGetBool(TokenName)
RETURN_STATUS EFIAPI SafeUintnAdd(IN UINTN Augend, IN UINTN Addend, OUT UINTN *Result)
RETURN_STATUS EFIAPI SafeUint32Add(IN UINT32 Augend, IN UINT32 Addend, OUT UINT32 *Result)
RETURN_STATUS EFIAPI SafeUint32Mult(IN UINT32 Multiplicand, IN UINT32 Multiplier, OUT UINT32 *Result)
VOID EFIAPI Exit(IN EFI_STATUS Status)
EFI_STATUS(EFIAPI * EFI_GET_VARIABLE)(IN CHAR16 *VariableName, IN EFI_GUID *VendorGuid, OUT UINT32 *Attributes OPTIONAL, IN OUT UINTN *DataSize, OUT VOID *Data OPTIONAL)