/** @file | |
The implementation of HII expression. | |
Copyright (c) 2019, Intel Corporation. All rights reserved.<BR> | |
(C) Copyright 2021 Hewlett Packard Enterprise Development LP<BR> | |
Copyright (c) 2022-2023, NVIDIA CORPORATION & AFFILIATES. All rights reserved. | |
SPDX-License-Identifier: BSD-2-Clause-Patent | |
**/ | |
#include "HiiInternal.h" | |
// | |
// Global stack used to evaluate boolean expressions | |
// | |
EFI_HII_VALUE *mOpCodeScopeStack = NULL; | |
EFI_HII_VALUE *mOpCodeScopeStackEnd = NULL; | |
EFI_HII_VALUE *mOpCodeScopeStackPointer = NULL; | |
// | |
// Stack used for Suppressif/grayoutif/disableif expression list. | |
// | |
HII_EXPRESSION **mFormExpressionStack = NULL; | |
HII_EXPRESSION **mFormExpressionEnd = NULL; | |
HII_EXPRESSION **mFormExpressionPointer = NULL; | |
HII_EXPRESSION **mStatementExpressionStack = NULL; | |
HII_EXPRESSION **mStatementExpressionEnd = NULL; | |
HII_EXPRESSION **mStatementExpressionPointer = NULL; | |
HII_EXPRESSION **mOptionExpressionStack = NULL; | |
HII_EXPRESSION **mOptionExpressionEnd = NULL; | |
HII_EXPRESSION **mOptionExpressionPointer = NULL; | |
// | |
// Stack used for the sub expresion in map expression. | |
// | |
EFI_HII_VALUE *mCurrentExpressionStack = NULL; | |
EFI_HII_VALUE *mCurrentExpressionEnd = NULL; | |
EFI_HII_VALUE *mCurrentExpressionPointer = NULL; | |
// | |
// Stack used for the map expression list. | |
// | |
EFI_HII_VALUE *mMapExpressionListStack = NULL; | |
EFI_HII_VALUE *mMapExpressionListEnd = NULL; | |
EFI_HII_VALUE *mMapExpressionListPointer = NULL; | |
// | |
// Stack used for dependency expression. | |
// | |
HII_DEPENDENCY_EXPRESSION **mExpressionDependencyStack = NULL; | |
HII_DEPENDENCY_EXPRESSION **mExpressionDependencyEnd = NULL; | |
HII_DEPENDENCY_EXPRESSION **mExpressionDependencyPointer = NULL; | |
/** | |
Grow size of the stack. | |
This is an internal function. | |
@param Stack On input: old stack; On output: new stack | |
@param StackPtr On input: old stack pointer; On output: new stack | |
pointer | |
@param StackEnd On input: old stack end; On output: new stack end | |
@retval EFI_SUCCESS Grow stack success. | |
@retval EFI_OUT_OF_RESOURCES No enough memory for stack space. | |
**/ | |
EFI_STATUS | |
GrowStack ( | |
IN OUT EFI_HII_VALUE **Stack, | |
IN OUT EFI_HII_VALUE **StackPtr, | |
IN OUT EFI_HII_VALUE **StackEnd | |
) | |
{ | |
UINTN Size; | |
EFI_HII_VALUE *NewStack; | |
Size = EXPRESSION_STACK_SIZE_INCREMENT; | |
if (*StackPtr != NULL) { | |
Size = Size + (*StackEnd - *Stack); | |
} | |
NewStack = AllocatePool (Size * sizeof (EFI_HII_VALUE)); | |
if (NewStack == NULL) { | |
return EFI_OUT_OF_RESOURCES; | |
} | |
if (*StackPtr != NULL) { | |
// | |
// Copy from Old Stack to the New Stack | |
// | |
CopyMem ( | |
NewStack, | |
*Stack, | |
(*StackEnd - *Stack) * sizeof (EFI_HII_VALUE) | |
); | |
// | |
// Free The Old Stack | |
// | |
FreePool (*Stack); | |
} | |
// | |
// Make the Stack pointer point to the old data in the new stack | |
// | |
*StackPtr = NewStack + (*StackPtr - *Stack); | |
*Stack = NewStack; | |
*StackEnd = NewStack + Size; | |
return EFI_SUCCESS; | |
} | |
/** | |
Push an element onto the Boolean Stack. | |
@param Stack On input: old stack; On output: new stack | |
@param StackPtr On input: old stack pointer; On output: new stack | |
pointer | |
@param StackEnd On input: old stack end; On output: new stack end | |
@param Data Data to push. | |
@retval EFI_SUCCESS Push stack success. | |
**/ | |
EFI_STATUS | |
PushStack ( | |
IN OUT EFI_HII_VALUE **Stack, | |
IN OUT EFI_HII_VALUE **StackPtr, | |
IN OUT EFI_HII_VALUE **StackEnd, | |
IN EFI_HII_VALUE *Data | |
) | |
{ | |
EFI_STATUS Status; | |
// | |
// Check for a stack overflow condition | |
// | |
if (*StackPtr >= *StackEnd) { | |
// | |
// Grow the stack | |
// | |
Status = GrowStack (Stack, StackPtr, StackEnd); | |
if (EFI_ERROR (Status)) { | |
return Status; | |
} | |
} | |
// | |
// Push the item onto the stack | |
// | |
CopyMem (*StackPtr, Data, sizeof (EFI_HII_VALUE)); | |
if (Data->Type == EFI_IFR_TYPE_BUFFER) { | |
(*StackPtr)->Buffer = AllocateCopyPool (Data->BufferLen, Data->Buffer); | |
if ((*StackPtr)->Buffer == NULL) { | |
return EFI_OUT_OF_RESOURCES; | |
} | |
} | |
*StackPtr = *StackPtr + 1; | |
return EFI_SUCCESS; | |
} | |
/** | |
Pop an element from the stack. | |
@param Stack On input: old stack | |
@param StackPtr On input: old stack pointer; On output: new stack pointer | |
@param Data Data to pop. | |
@retval EFI_SUCCESS The value was popped onto the stack. | |
@retval EFI_ACCESS_DENIED The pop operation underflowed the stack | |
**/ | |
EFI_STATUS | |
PopStack ( | |
IN EFI_HII_VALUE *Stack, | |
IN OUT EFI_HII_VALUE **StackPtr, | |
OUT EFI_HII_VALUE *Data | |
) | |
{ | |
// | |
// Check for a stack underflow condition | |
// | |
if (*StackPtr == Stack) { | |
return EFI_ACCESS_DENIED; | |
} | |
// | |
// Pop the item off the stack | |
// | |
*StackPtr = *StackPtr - 1; | |
CopyMem (Data, *StackPtr, sizeof (EFI_HII_VALUE)); | |
return EFI_SUCCESS; | |
} | |
/** | |
Reset stack pointer to begin of the stack. | |
**/ | |
VOID | |
ResetCurrentExpressionStack ( | |
VOID | |
) | |
{ | |
mCurrentExpressionPointer = mCurrentExpressionStack; | |
mFormExpressionPointer = mFormExpressionStack; | |
mStatementExpressionPointer = mStatementExpressionStack; | |
mOptionExpressionPointer = mOptionExpressionStack; | |
} | |
/** | |
Push current expression onto the Stack | |
@param Pointer Pointer to current expression. | |
@retval EFI_SUCCESS The value was pushed onto the stack. | |
@retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the stack. | |
**/ | |
EFI_STATUS | |
PushCurrentExpression ( | |
IN VOID *Pointer | |
) | |
{ | |
EFI_HII_VALUE Data; | |
Data.Type = EFI_IFR_TYPE_NUM_SIZE_64; | |
Data.Value.u64 = (UINT64)(UINTN)Pointer; | |
return PushStack ( | |
&mCurrentExpressionStack, | |
&mCurrentExpressionPointer, | |
&mCurrentExpressionEnd, | |
&Data | |
); | |
} | |
/** | |
Pop current expression from the Stack | |
@param Pointer Pointer to current expression to be pop. | |
@retval EFI_SUCCESS The value was pushed onto the stack. | |
@retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the stack. | |
**/ | |
EFI_STATUS | |
PopCurrentExpression ( | |
OUT VOID **Pointer | |
) | |
{ | |
EFI_STATUS Status; | |
EFI_HII_VALUE Data; | |
Status = PopStack ( | |
mCurrentExpressionStack, | |
&mCurrentExpressionPointer, | |
&Data | |
); | |
*Pointer = (VOID *)(UINTN)Data.Value.u64; | |
return Status; | |
} | |
/** | |
Reset stack pointer to begin of the stack. | |
**/ | |
VOID | |
ResetMapExpressionListStack ( | |
VOID | |
) | |
{ | |
mMapExpressionListPointer = mMapExpressionListStack; | |
} | |
/** | |
Grow size of the stack. | |
This is an internal function. | |
@param Stack On input: old stack; On output: new stack | |
@param StackPtr On input: old stack pointer; On output: new stack | |
pointer | |
@param StackEnd On input: old stack end; On output: new stack end | |
@param MemberSize The stack member size. | |
@retval EFI_SUCCESS Grow stack success. | |
@retval EFI_OUT_OF_RESOURCES No enough memory for stack space. | |
**/ | |
EFI_STATUS | |
GrowConditionalStack ( | |
IN OUT HII_EXPRESSION ***Stack, | |
IN OUT HII_EXPRESSION ***StackPtr, | |
IN OUT HII_EXPRESSION ***StackEnd, | |
IN UINTN MemberSize | |
) | |
{ | |
UINTN Size; | |
HII_EXPRESSION **NewStack; | |
Size = EXPRESSION_STACK_SIZE_INCREMENT; | |
if (*StackPtr != NULL) { | |
Size = Size + (*StackEnd - *Stack); | |
} | |
NewStack = AllocatePool (Size * MemberSize); | |
if (NewStack == NULL) { | |
return EFI_OUT_OF_RESOURCES; | |
} | |
if (*StackPtr != NULL) { | |
// | |
// Copy from Old Stack to the New Stack | |
// | |
CopyMem ( | |
NewStack, | |
*Stack, | |
(*StackEnd - *Stack) * MemberSize | |
); | |
// | |
// Free The Old Stack | |
// | |
FreePool (*Stack); | |
} | |
// | |
// Make the Stack pointer point to the old data in the new stack | |
// | |
*StackPtr = NewStack + (*StackPtr - *Stack); | |
*Stack = NewStack; | |
*StackEnd = NewStack + Size; | |
return EFI_SUCCESS; | |
} | |
/** | |
Push an element onto the Stack. | |
@param Stack On input: old stack; On output: new stack | |
@param StackPtr On input: old stack pointer; On output: new stack | |
pointer | |
@param StackEnd On input: old stack end; On output: new stack end | |
@param Data Data to push. | |
@retval EFI_SUCCESS Push stack success. | |
**/ | |
EFI_STATUS | |
PushConditionalStack ( | |
IN OUT HII_EXPRESSION ***Stack, | |
IN OUT HII_EXPRESSION ***StackPtr, | |
IN OUT HII_EXPRESSION ***StackEnd, | |
IN HII_EXPRESSION **Data | |
) | |
{ | |
EFI_STATUS Status; | |
// | |
// Check for a stack overflow condition | |
// | |
if (*StackPtr >= *StackEnd) { | |
// | |
// Grow the stack | |
// | |
Status = GrowConditionalStack (Stack, StackPtr, StackEnd, sizeof (HII_EXPRESSION *)); | |
if (EFI_ERROR (Status)) { | |
return Status; | |
} | |
} | |
// | |
// Push the item onto the stack | |
// | |
CopyMem (*StackPtr, Data, sizeof (HII_EXPRESSION *)); | |
*StackPtr = *StackPtr + 1; | |
return EFI_SUCCESS; | |
} | |
/** | |
Pop an element from the stack. | |
@param Stack On input: old stack | |
@param StackPtr On input: old stack pointer; On output: new stack pointer | |
@param Data Data to pop. | |
@retval EFI_SUCCESS The value was popped onto the stack. | |
@retval EFI_ACCESS_DENIED The pop operation underflowed the stack | |
**/ | |
EFI_STATUS | |
PopConditionalStack ( | |
IN HII_EXPRESSION **Stack, | |
IN OUT HII_EXPRESSION ***StackPtr, | |
OUT HII_EXPRESSION **Data | |
) | |
{ | |
// | |
// Check for a stack underflow condition | |
// | |
if (*StackPtr == Stack) { | |
return EFI_ACCESS_DENIED; | |
} | |
// | |
// Pop the item off the stack | |
// | |
*StackPtr = *StackPtr - 1; | |
CopyMem (Data, *StackPtr, sizeof (HII_EXPRESSION *)); | |
return EFI_SUCCESS; | |
} | |
/** | |
Get the expression list count. | |
@param Level Which type this expression belong to. Form, | |
statement or option? | |
@retval >=0 The expression count | |
@retval -1 Input parameter error. | |
**/ | |
INTN | |
GetConditionalExpressionCount ( | |
IN EXPRESS_LEVEL Level | |
) | |
{ | |
switch (Level) { | |
case ExpressForm: | |
return mFormExpressionPointer - mFormExpressionStack; | |
case ExpressStatement: | |
return mStatementExpressionPointer - mStatementExpressionStack; | |
case ExpressOption: | |
return mOptionExpressionPointer - mOptionExpressionStack; | |
default: | |
ASSERT (FALSE); | |
return -1; | |
} | |
} | |
/** | |
Get the expression Buffer pointer. | |
@param Level Which type this expression belong to. Form, | |
statement or option? | |
@retval The start pointer of the expression buffer or NULL. | |
**/ | |
HII_EXPRESSION ** | |
GetConditionalExpressionList ( | |
IN EXPRESS_LEVEL Level | |
) | |
{ | |
switch (Level) { | |
case ExpressForm: | |
return mFormExpressionStack; | |
case ExpressStatement: | |
return mStatementExpressionStack; | |
case ExpressOption: | |
return mOptionExpressionStack; | |
default: | |
ASSERT (FALSE); | |
return NULL; | |
} | |
} | |
/** | |
Push the expression options onto the Stack. | |
@param Pointer Pointer to the current expression. | |
@param Level Which type this expression belong to. Form, | |
statement or option? | |
@retval EFI_SUCCESS The value was pushed onto the stack. | |
@retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the stack. | |
**/ | |
EFI_STATUS | |
PushConditionalExpression ( | |
IN HII_EXPRESSION *Pointer, | |
IN EXPRESS_LEVEL Level | |
) | |
{ | |
switch (Level) { | |
case ExpressForm: | |
return PushConditionalStack ( | |
&mFormExpressionStack, | |
&mFormExpressionPointer, | |
&mFormExpressionEnd, | |
&Pointer | |
); | |
case ExpressStatement: | |
return PushConditionalStack ( | |
&mStatementExpressionStack, | |
&mStatementExpressionPointer, | |
&mStatementExpressionEnd, | |
&Pointer | |
); | |
case ExpressOption: | |
return PushConditionalStack ( | |
&mOptionExpressionStack, | |
&mOptionExpressionPointer, | |
&mOptionExpressionEnd, | |
&Pointer | |
); | |
default: | |
ASSERT (FALSE); | |
return EFI_INVALID_PARAMETER; | |
} | |
} | |
/** | |
Pop the expression options from the Stack | |
@param Level Which type this expression belong to. Form, | |
statement or option? | |
@retval EFI_SUCCESS The value was pushed onto the stack. | |
@retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the stack. | |
**/ | |
EFI_STATUS | |
PopConditionalExpression ( | |
IN EXPRESS_LEVEL Level | |
) | |
{ | |
HII_EXPRESSION *Pointer; | |
switch (Level) { | |
case ExpressForm: | |
return PopConditionalStack ( | |
mFormExpressionStack, | |
&mFormExpressionPointer, | |
&Pointer | |
); | |
case ExpressStatement: | |
return PopConditionalStack ( | |
mStatementExpressionStack, | |
&mStatementExpressionPointer, | |
&Pointer | |
); | |
case ExpressOption: | |
return PopConditionalStack ( | |
mOptionExpressionStack, | |
&mOptionExpressionPointer, | |
&Pointer | |
); | |
default: | |
ASSERT (FALSE); | |
return EFI_INVALID_PARAMETER; | |
} | |
} | |
/** | |
Push the list of map expression onto the Stack | |
@param Pointer Pointer to the list of map expression to be pushed. | |
@retval EFI_SUCCESS The value was pushed onto the stack. | |
@retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the stack. | |
**/ | |
EFI_STATUS | |
PushMapExpressionList ( | |
IN VOID *Pointer | |
) | |
{ | |
EFI_HII_VALUE Data; | |
Data.Type = EFI_IFR_TYPE_NUM_SIZE_64; | |
Data.Value.u64 = (UINT64)(UINTN)Pointer; | |
return PushStack ( | |
&mMapExpressionListStack, | |
&mMapExpressionListPointer, | |
&mMapExpressionListEnd, | |
&Data | |
); | |
} | |
/** | |
Pop the list of map expression from the Stack | |
@param Pointer Pointer to the list of map expression to be pop. | |
@retval EFI_SUCCESS The value was pushed onto the stack. | |
@retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the stack. | |
**/ | |
EFI_STATUS | |
PopMapExpressionList ( | |
OUT VOID **Pointer | |
) | |
{ | |
EFI_STATUS Status; | |
EFI_HII_VALUE Data; | |
Status = PopStack ( | |
mMapExpressionListStack, | |
&mMapExpressionListPointer, | |
&Data | |
); | |
*Pointer = (VOID *)(UINTN)Data.Value.u64; | |
return Status; | |
} | |
/** | |
Reset stack pointer to begin of the stack. | |
**/ | |
VOID | |
ResetScopeStack ( | |
VOID | |
) | |
{ | |
mOpCodeScopeStackPointer = mOpCodeScopeStack; | |
} | |
/** | |
Push an Operand onto the Stack | |
@param Operand Operand to push. | |
@retval EFI_SUCCESS The value was pushed onto the stack. | |
@retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the | |
stack. | |
**/ | |
EFI_STATUS | |
PushScope ( | |
IN UINT8 Operand | |
) | |
{ | |
EFI_HII_VALUE Data; | |
Data.Type = EFI_IFR_TYPE_NUM_SIZE_8; | |
Data.Value.u8 = Operand; | |
return PushStack ( | |
&mOpCodeScopeStack, | |
&mOpCodeScopeStackPointer, | |
&mOpCodeScopeStackEnd, | |
&Data | |
); | |
} | |
/** | |
Pop an Operand from the Stack | |
@param Operand Operand to pop. | |
@retval EFI_SUCCESS The value was pushed onto the stack. | |
@retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the | |
stack. | |
**/ | |
EFI_STATUS | |
PopScope ( | |
OUT UINT8 *Operand | |
) | |
{ | |
EFI_STATUS Status; | |
EFI_HII_VALUE Data; | |
Status = PopStack ( | |
mOpCodeScopeStack, | |
&mOpCodeScopeStackPointer, | |
&Data | |
); | |
*Operand = Data.Value.u8; | |
return Status; | |
} | |
/** | |
Grow size of the stack for Expression Dependencies. | |
This is an internal function. | |
@param Stack On input: old stack; On output: new stack | |
@param StackPtr On input: old stack pointer; On output: new stack | |
pointer | |
@param StackEnd On input: old stack end; On output: new stack end | |
@retval EFI_SUCCESS Grow Dependency stack success. | |
@retval EFI_OUT_OF_RESOURCES No enough memory for stack space. | |
**/ | |
EFI_STATUS | |
GrowDependencyStack ( | |
IN OUT HII_DEPENDENCY_EXPRESSION ***Stack, | |
IN OUT HII_DEPENDENCY_EXPRESSION ***StackPtr, | |
IN OUT HII_DEPENDENCY_EXPRESSION ***StackEnd | |
) | |
{ | |
UINTN Size; | |
HII_DEPENDENCY_EXPRESSION **NewStack; | |
Size = EXPRESSION_STACK_SIZE_INCREMENT; | |
if (*StackPtr != NULL) { | |
Size = Size + (*StackEnd - *Stack); | |
} | |
NewStack = AllocatePool (Size * sizeof (HII_DEPENDENCY_EXPRESSION *)); | |
if (NewStack == NULL) { | |
return EFI_OUT_OF_RESOURCES; | |
} | |
if (*StackPtr != NULL) { | |
// | |
// Copy from Old Stack to the New Stack | |
// | |
CopyMem ( | |
NewStack, | |
*Stack, | |
(*StackEnd - *Stack) * sizeof (HII_DEPENDENCY_EXPRESSION *) | |
); | |
// | |
// Free The Old Stack | |
// | |
FreePool (*Stack); | |
} | |
// | |
// Make the Stack pointer point to the old data in the new stack | |
// | |
*StackPtr = NewStack + (*StackPtr - *Stack); | |
*Stack = NewStack; | |
*StackEnd = NewStack + Size; | |
return EFI_SUCCESS; | |
} | |
/** | |
Push an element onto the Stack for Expression Dependencies. | |
@param Stack On input: old stack; On output: new stack | |
@param StackPtr On input: old stack pointer; On output: new stack | |
pointer | |
@param StackEnd On input: old stack end; On output: new stack end | |
@param Data Data to push. | |
@retval EFI_SUCCESS Push stack success. | |
**/ | |
EFI_STATUS | |
PushDependencyStack ( | |
IN OUT HII_DEPENDENCY_EXPRESSION ***Stack, | |
IN OUT HII_DEPENDENCY_EXPRESSION ***StackPtr, | |
IN OUT HII_DEPENDENCY_EXPRESSION ***StackEnd, | |
IN HII_DEPENDENCY_EXPRESSION **Data | |
) | |
{ | |
EFI_STATUS Status; | |
// | |
// Check for a stack overflow condition | |
// | |
if (*StackPtr >= *StackEnd) { | |
// | |
// Grow the stack | |
// | |
Status = GrowDependencyStack (Stack, StackPtr, StackEnd); | |
if (EFI_ERROR (Status)) { | |
return Status; | |
} | |
} | |
// | |
// Push the item onto the stack | |
// | |
CopyMem (*StackPtr, Data, sizeof (HII_DEPENDENCY_EXPRESSION *)); | |
*StackPtr = *StackPtr + 1; | |
return EFI_SUCCESS; | |
} | |
/** | |
Pop the Expression Dependency options from the Stack | |
@param Stack On input: old stack; On output: new stack | |
@param StackPtr On input: old stack pointer; On output: new stack | |
pointer | |
@param Data Data to push. | |
@retval EFI_SUCCESS The value was pushed onto the stack. | |
@retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the stack. | |
**/ | |
EFI_STATUS | |
PopDependencyStack ( | |
IN HII_DEPENDENCY_EXPRESSION **Stack, | |
IN OUT HII_DEPENDENCY_EXPRESSION ***StackPtr, | |
OUT HII_DEPENDENCY_EXPRESSION **Data | |
) | |
{ | |
// | |
// Check for a stack underflow condition | |
// | |
if (*StackPtr == Stack) { | |
return EFI_ACCESS_DENIED; | |
} | |
// | |
// Pop the item off the stack | |
// | |
*StackPtr = *StackPtr - 1; | |
CopyMem (Data, *StackPtr, sizeof (HII_DEPENDENCY_EXPRESSION *)); | |
return EFI_SUCCESS; | |
} | |
/** | |
Push the list of Expression Dependencies onto the Stack | |
@param Pointer Pointer to the list of map expression to be pushed. | |
@retval EFI_SUCCESS The value was pushed onto the stack. | |
@retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the stack. | |
**/ | |
EFI_STATUS | |
PushDependencyExpDes ( | |
IN HII_DEPENDENCY_EXPRESSION **Pointer | |
) | |
{ | |
return PushDependencyStack ( | |
&mExpressionDependencyStack, | |
&mExpressionDependencyPointer, | |
&mExpressionDependencyEnd, | |
Pointer | |
); | |
} | |
/** | |
Pop the list of Expression Dependencies from the Stack | |
@param Pointer Pointer to the list of map expression to be pop. | |
@retval EFI_SUCCESS The value was pushed onto the stack. | |
@retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the stack. | |
**/ | |
EFI_STATUS | |
PopDependencyExpDes ( | |
OUT HII_DEPENDENCY_EXPRESSION **Pointer | |
) | |
{ | |
return PopDependencyStack ( | |
mExpressionDependencyStack, | |
&mExpressionDependencyPointer, | |
Pointer | |
); | |
} | |
/** | |
Retrieve dependencies within an expression. These dependencies can express how | |
this expression will be evaluated. | |
@param[in,out] Expression Expression to retrieve dependencies. | |
@retval EFI_SUCCESS The dependencies were successfully retrieved. | |
@retval EFI_OUT_OF_RESOURCES There is not enough system memory. | |
**/ | |
EFI_STATUS | |
GetHiiExpressionDependency ( | |
IN OUT HII_EXPRESSION *Expression | |
) | |
{ | |
EFI_STATUS Status; | |
LIST_ENTRY *Link; | |
HII_EXPRESSION_OPCODE *ExpressionOpCode; | |
HII_DEPENDENCY_EXPRESSION *DepExpressionOpCode; | |
LIST_ENTRY *SubExpressionLink; | |
HII_EXPRESSION *SubExpression; | |
UINT8 MapPairCount; | |
Link = GetFirstNode (&Expression->OpCodeListHead); | |
while (!IsNull (&Expression->OpCodeListHead, Link)) { | |
ExpressionOpCode = HII_EXPRESSION_OPCODE_FROM_LINK (Link); | |
Link = GetNextNode (&Expression->OpCodeListHead, Link); | |
Status = EFI_SUCCESS; | |
DepExpressionOpCode = (HII_DEPENDENCY_EXPRESSION *)AllocateZeroPool (sizeof (HII_DEPENDENCY_EXPRESSION)); | |
if (DepExpressionOpCode == NULL) { | |
return EFI_OUT_OF_RESOURCES; | |
} | |
switch (ExpressionOpCode->Operand) { | |
// | |
// Constant | |
// | |
case EFI_IFR_FALSE_OP: | |
case EFI_IFR_ONE_OP: | |
case EFI_IFR_ONES_OP: | |
case EFI_IFR_TRUE_OP: | |
case EFI_IFR_UINT8_OP: | |
case EFI_IFR_UINT16_OP: | |
case EFI_IFR_UINT32_OP: | |
case EFI_IFR_UINT64_OP: | |
case EFI_IFR_UNDEFINED_OP: | |
case EFI_IFR_VERSION_OP: | |
case EFI_IFR_ZERO_OP: | |
DepExpressionOpCode->ConstantExp.Operand = ExpressionOpCode->Operand; | |
CopyMem (&DepExpressionOpCode->ConstantExp.Value, &ExpressionOpCode->ExtraData.Value, sizeof (EFI_HII_VALUE)); | |
PushDependencyExpDes (&DepExpressionOpCode); | |
break; | |
// | |
// Built-in functions | |
// | |
case EFI_IFR_DUP_OP: | |
DepExpressionOpCode->DupExp.Operand = ExpressionOpCode->Operand; | |
PushDependencyExpDes (&DepExpressionOpCode); | |
break; | |
case EFI_IFR_EQ_ID_VAL_OP: | |
DepExpressionOpCode->EqIdValExp.Operand = ExpressionOpCode->Operand; | |
CopyMem (&DepExpressionOpCode->EqIdValExp.QuestionId, &ExpressionOpCode->ExtraData.EqIdValData.QuestionId, sizeof (EFI_QUESTION_ID)); | |
CopyMem (&DepExpressionOpCode->EqIdValExp.Value, &ExpressionOpCode->ExtraData.EqIdValData.Value, sizeof (EFI_HII_VALUE)); | |
PushDependencyExpDes (&DepExpressionOpCode); | |
break; | |
case EFI_IFR_EQ_ID_ID_OP: | |
DepExpressionOpCode->EqIdIdExp.Operand = ExpressionOpCode->Operand; | |
CopyMem (&DepExpressionOpCode->EqIdIdExp.QuestionId1, &ExpressionOpCode->ExtraData.EqIdIdData.QuestionId1, sizeof (EFI_QUESTION_ID)); | |
CopyMem (&DepExpressionOpCode->EqIdIdExp.QuestionId2, &ExpressionOpCode->ExtraData.EqIdIdData.QuestionId2, sizeof (EFI_QUESTION_ID)); | |
PushDependencyExpDes (&DepExpressionOpCode); | |
break; | |
case EFI_IFR_EQ_ID_VAL_LIST_OP: | |
DepExpressionOpCode->EqIdListExp.Operand = ExpressionOpCode->Operand; | |
DepExpressionOpCode->EqIdListExp.ListLength = ExpressionOpCode->ExtraData.EqIdListData.ListLength; | |
CopyMem (&DepExpressionOpCode->EqIdListExp.QuestionId, &ExpressionOpCode->ExtraData.EqIdListData.QuestionId, sizeof (EFI_QUESTION_ID)); | |
PushDependencyExpDes (&DepExpressionOpCode); | |
DepExpressionOpCode->EqIdListExp.ValueList = AllocateCopyPool ( | |
DepExpressionOpCode->EqIdListExp.ListLength * sizeof (UINT16), | |
ExpressionOpCode->ExtraData.EqIdListData.ValueList | |
); | |
if (DepExpressionOpCode->EqIdListExp.ValueList == NULL) { | |
return EFI_OUT_OF_RESOURCES; | |
} | |
PushDependencyExpDes (&DepExpressionOpCode); | |
break; | |
case EFI_IFR_GET_OP: | |
DepExpressionOpCode->GetExp.Operand = ExpressionOpCode->Operand; | |
DepExpressionOpCode->GetExp.VarStorage = ExpressionOpCode->ExtraData.GetSetData.VarStorage; | |
CopyMem (&DepExpressionOpCode->GetExp.VarStoreInfo.VarName, &ExpressionOpCode->ExtraData.GetSetData.VarStoreInfo.VarName, sizeof (EFI_STRING_ID)); | |
CopyMem (&DepExpressionOpCode->GetExp.VarStoreInfo.VarOffset, &ExpressionOpCode->ExtraData.GetSetData.VarStoreInfo.VarOffset, sizeof (UINT16)); | |
DepExpressionOpCode->GetExp.VarStoreInfo = ExpressionOpCode->ExtraData.GetSetData.VarStoreInfo; | |
if (ExpressionOpCode->ExtraData.GetSetData.ValueName != NULL) { | |
DepExpressionOpCode->GetExp.ValueName = (CHAR16 *)AllocateCopyPool (sizeof (ExpressionOpCode->ExtraData.GetSetData.ValueName), ExpressionOpCode->ExtraData.GetSetData.ValueName); | |
if (DepExpressionOpCode->GetExp.ValueName == NULL) { | |
return EFI_OUT_OF_RESOURCES; | |
} | |
} | |
DepExpressionOpCode->GetExp.ValueType = ExpressionOpCode->ExtraData.GetSetData.ValueType; | |
DepExpressionOpCode->GetExp.ValueWidth = ExpressionOpCode->ExtraData.GetSetData.ValueWidth; | |
PushDependencyExpDes (&DepExpressionOpCode); | |
break; | |
case EFI_IFR_QUESTION_REF1_OP: | |
DepExpressionOpCode->QuestionRef1Exp.Operand = ExpressionOpCode->Operand; | |
CopyMem (&DepExpressionOpCode->QuestionRef1Exp.QuestionId, &ExpressionOpCode->ExtraData.QuestionRef1Data.QuestionId, sizeof (EFI_QUESTION_ID)); | |
PushDependencyExpDes (&DepExpressionOpCode); | |
break; | |
case EFI_IFR_RULE_REF_OP: | |
DepExpressionOpCode->RuleRefExp.Operand = ExpressionOpCode->Operand; | |
DepExpressionOpCode->RuleRefExp.RuleId = ExpressionOpCode->ExtraData.RuleId; | |
PushDependencyExpDes (&DepExpressionOpCode); | |
break; | |
case EFI_IFR_STRING_REF1_OP: | |
DepExpressionOpCode->StringRef1Exp.Operand = ExpressionOpCode->Operand; | |
CopyMem (&DepExpressionOpCode->StringRef1Exp.Value.Value.string, &ExpressionOpCode->ExtraData.Value.Value.string, sizeof (EFI_STRING_ID)); | |
PushDependencyExpDes (&DepExpressionOpCode); | |
break; | |
case EFI_IFR_THIS_OP: | |
DepExpressionOpCode->ThisExp.Operand = ExpressionOpCode->Operand; | |
CopyMem (&DepExpressionOpCode->ThisExp.QuestionId, &ExpressionOpCode->ExtraData.QuestionRef1Data.QuestionId, sizeof (EFI_QUESTION_ID)); | |
PushDependencyExpDes (&DepExpressionOpCode); | |
break; | |
case EFI_IFR_SECURITY_OP: | |
DepExpressionOpCode->SecurityExp.Operand = ExpressionOpCode->Operand; | |
CopyMem (&DepExpressionOpCode->SecurityExp.Permissions, &ExpressionOpCode->ExtraData.Guid, sizeof (EFI_GUID)); | |
PushDependencyExpDes (&DepExpressionOpCode); | |
break; | |
// | |
// unary-op | |
// | |
case EFI_IFR_LENGTH_OP: | |
DepExpressionOpCode->LengthExp.Operand = ExpressionOpCode->Operand; | |
PopDependencyExpDes (&DepExpressionOpCode->LengthExp.SubExpression); | |
PushDependencyExpDes (&DepExpressionOpCode); | |
break; | |
case EFI_IFR_NOT_OP: | |
DepExpressionOpCode->NotExp.Operand = ExpressionOpCode->Operand; | |
PopDependencyExpDes (&DepExpressionOpCode->NotExp.SubExpression); | |
PushDependencyExpDes (&DepExpressionOpCode); | |
break; | |
case EFI_IFR_BITWISE_NOT_OP: | |
DepExpressionOpCode->BitWiseNotExp.Operand = ExpressionOpCode->Operand; | |
PopDependencyExpDes (&DepExpressionOpCode->BitWiseNotExp.SubExpression); | |
PushDependencyExpDes (&DepExpressionOpCode); | |
break; | |
case EFI_IFR_QUESTION_REF2_OP: | |
DepExpressionOpCode->QuestionRef2Exp.Operand = ExpressionOpCode->Operand; | |
PopDependencyExpDes (&DepExpressionOpCode->QuestionRef2Exp.SubExpression); | |
PushDependencyExpDes (&DepExpressionOpCode); | |
break; | |
case EFI_IFR_QUESTION_REF3_OP: | |
DepExpressionOpCode->QuestionRef3Exp.Operand = ExpressionOpCode->Operand; | |
CopyMem (&DepExpressionOpCode->QuestionRef3Exp.DevicePath, &ExpressionOpCode->ExtraData.QuestionRef3Data.DevicePath, sizeof (EFI_DEVICE_PATH)); | |
CopyMem (&DepExpressionOpCode->QuestionRef3Exp.Guid, &ExpressionOpCode->ExtraData.QuestionRef3Data.Guid, sizeof (EFI_GUID)); | |
PopDependencyExpDes (&DepExpressionOpCode->QuestionRef3Exp.SubExpression); | |
PushDependencyExpDes (&DepExpressionOpCode); | |
break; | |
case EFI_IFR_SET_OP: | |
DepExpressionOpCode->SetExp.Operand = ExpressionOpCode->Operand; | |
DepExpressionOpCode->SetExp.VarStorage = ExpressionOpCode->ExtraData.GetSetData.VarStorage; | |
CopyMem (&DepExpressionOpCode->SetExp.VarStoreInfo.VarName, &ExpressionOpCode->ExtraData.GetSetData.VarStoreInfo.VarName, sizeof (EFI_STRING_ID)); | |
CopyMem (&DepExpressionOpCode->SetExp.VarStoreInfo.VarOffset, &ExpressionOpCode->ExtraData.GetSetData.VarStoreInfo.VarOffset, sizeof (UINT16)); | |
DepExpressionOpCode->SetExp.VarStoreInfo = ExpressionOpCode->ExtraData.GetSetData.VarStoreInfo; | |
if (ExpressionOpCode->ExtraData.GetSetData.ValueName != NULL) { | |
DepExpressionOpCode->SetExp.ValueName = (CHAR16 *)AllocateCopyPool (sizeof (ExpressionOpCode->ExtraData.GetSetData.ValueName), ExpressionOpCode->ExtraData.GetSetData.ValueName); | |
if (DepExpressionOpCode->SetExp.ValueName == NULL) { | |
return EFI_OUT_OF_RESOURCES; | |
} | |
} | |
DepExpressionOpCode->SetExp.ValueType = ExpressionOpCode->ExtraData.GetSetData.ValueType; | |
DepExpressionOpCode->SetExp.ValueWidth = ExpressionOpCode->ExtraData.GetSetData.ValueWidth; | |
PopDependencyExpDes (&DepExpressionOpCode->SetExp.SubExpression); | |
PushDependencyExpDes (&DepExpressionOpCode); | |
break; | |
case EFI_IFR_STRING_REF2_OP: | |
DepExpressionOpCode->StringRef2Exp.Operand = ExpressionOpCode->Operand; | |
PopDependencyExpDes (&DepExpressionOpCode->StringRef2Exp.SubExpression); | |
PushDependencyExpDes (&DepExpressionOpCode); | |
break; | |
case EFI_IFR_TO_BOOLEAN_OP: | |
DepExpressionOpCode->ToBooleanExp.Operand = ExpressionOpCode->Operand; | |
PopDependencyExpDes (&DepExpressionOpCode->ToBooleanExp.SubExpression); | |
PushDependencyExpDes (&DepExpressionOpCode); | |
break; | |
case EFI_IFR_TO_STRING_OP: | |
DepExpressionOpCode->ToStringExp.Operand = ExpressionOpCode->Operand; | |
DepExpressionOpCode->ToStringExp.Format = ExpressionOpCode->ExtraData.Format; | |
PopDependencyExpDes (&DepExpressionOpCode->ToStringExp.SubExpression); | |
PushDependencyExpDes (&DepExpressionOpCode); | |
break; | |
case EFI_IFR_TO_UINT_OP: | |
DepExpressionOpCode->ToUintExp.Operand = ExpressionOpCode->Operand; | |
PopDependencyExpDes (&DepExpressionOpCode->ToUintExp.SubExpression); | |
PushDependencyExpDes (&DepExpressionOpCode); | |
break; | |
case EFI_IFR_TO_LOWER_OP: | |
DepExpressionOpCode->ToLowerExp.Operand = ExpressionOpCode->Operand; | |
PopDependencyExpDes (&DepExpressionOpCode->ToLowerExp.SubExpression); | |
PushDependencyExpDes (&DepExpressionOpCode); | |
break; | |
case EFI_IFR_TO_UPPER_OP: | |
DepExpressionOpCode->ToUpperExp.Operand = ExpressionOpCode->Operand; | |
PopDependencyExpDes (&DepExpressionOpCode->ToUpperExp.SubExpression); | |
PushDependencyExpDes (&DepExpressionOpCode); | |
break; | |
// | |
// binary-op | |
// | |
case EFI_IFR_ADD_OP: | |
DepExpressionOpCode->AddExp.Operand = ExpressionOpCode->Operand; | |
PopDependencyExpDes (&DepExpressionOpCode->AddExp.LeftHandExp); | |
PopDependencyExpDes (&DepExpressionOpCode->AddExp.RightHandExp); | |
PushDependencyExpDes (&DepExpressionOpCode); | |
break; | |
case EFI_IFR_AND_OP: | |
DepExpressionOpCode->AndExp.Operand = ExpressionOpCode->Operand; | |
PopDependencyExpDes (&DepExpressionOpCode->AndExp.SubExpression1); | |
PopDependencyExpDes (&DepExpressionOpCode->AndExp.SubExpression2); | |
PushDependencyExpDes (&DepExpressionOpCode); | |
break; | |
case EFI_IFR_BITWISE_AND_OP: | |
DepExpressionOpCode->BitwiseAndExp.Operand = ExpressionOpCode->Operand; | |
PopDependencyExpDes (&DepExpressionOpCode->BitwiseAndExp.SubExpression1); | |
PopDependencyExpDes (&DepExpressionOpCode->BitwiseAndExp.SubExpression2); | |
PushDependencyExpDes (&DepExpressionOpCode); | |
break; | |
case EFI_IFR_BITWISE_OR_OP: | |
DepExpressionOpCode->BitwiseOrExp.Operand = ExpressionOpCode->Operand; | |
PopDependencyExpDes (&DepExpressionOpCode->BitwiseOrExp.SubExpression1); | |
PopDependencyExpDes (&DepExpressionOpCode->BitwiseOrExp.SubExpression2); | |
PushDependencyExpDes (&DepExpressionOpCode); | |
break; | |
case EFI_IFR_CATENATE_OP: | |
DepExpressionOpCode->CatenateExp.Operand = ExpressionOpCode->Operand; | |
PopDependencyExpDes (&DepExpressionOpCode->CatenateExp.LeftStringExp); | |
PopDependencyExpDes (&DepExpressionOpCode->CatenateExp.RightStringExp); | |
PushDependencyExpDes (&DepExpressionOpCode); | |
break; | |
case EFI_IFR_DIVIDE_OP: | |
DepExpressionOpCode->DivExp.Operand = ExpressionOpCode->Operand; | |
PopDependencyExpDes (&DepExpressionOpCode->DivExp.LeftHandExp); | |
PopDependencyExpDes (&DepExpressionOpCode->DivExp.RightHandExp); | |
PushDependencyExpDes (&DepExpressionOpCode); | |
break; | |
case EFI_IFR_EQUAL_OP: | |
DepExpressionOpCode->EqualExp.Operand = ExpressionOpCode->Operand; | |
PopDependencyExpDes (&DepExpressionOpCode->EqualExp.SubExpression1); | |
PopDependencyExpDes (&DepExpressionOpCode->EqualExp.SubExpression2); | |
PushDependencyExpDes (&DepExpressionOpCode); | |
break; | |
case EFI_IFR_GREATER_EQUAL_OP: | |
DepExpressionOpCode->GreaterEqualExp.Operand = ExpressionOpCode->Operand; | |
PopDependencyExpDes (&DepExpressionOpCode->GreaterEqualExp.LeftHandExp); | |
PopDependencyExpDes (&DepExpressionOpCode->GreaterEqualExp.RightHandExp); | |
PushDependencyExpDes (&DepExpressionOpCode); | |
break; | |
case EFI_IFR_GREATER_THAN_OP: | |
DepExpressionOpCode->GreaterThanExp.Operand = ExpressionOpCode->Operand; | |
PopDependencyExpDes (&DepExpressionOpCode->GreaterThanExp.LeftHandExp); | |
PopDependencyExpDes (&DepExpressionOpCode->GreaterThanExp.RightHandExp); | |
PushDependencyExpDes (&DepExpressionOpCode); | |
break; | |
case EFI_IFR_LESS_EQUAL_OP: | |
DepExpressionOpCode->LessEqualExp.Operand = ExpressionOpCode->Operand; | |
PopDependencyExpDes (&DepExpressionOpCode->LessEqualExp.LeftHandExp); | |
PopDependencyExpDes (&DepExpressionOpCode->LessEqualExp.RightHandExp); | |
PushDependencyExpDes (&DepExpressionOpCode); | |
break; | |
case EFI_IFR_LESS_THAN_OP: | |
DepExpressionOpCode->LessThanExp.Operand = ExpressionOpCode->Operand; | |
PopDependencyExpDes (&DepExpressionOpCode->LessThanExp.LeftHandExp); | |
PopDependencyExpDes (&DepExpressionOpCode->LessThanExp.RightHandExp); | |
PushDependencyExpDes (&DepExpressionOpCode); | |
break; | |
case EFI_IFR_MATCH_OP: | |
DepExpressionOpCode->MatchExp.Operand = ExpressionOpCode->Operand; | |
PopDependencyExpDes (&DepExpressionOpCode->MatchExp.PatternExp); | |
PopDependencyExpDes (&DepExpressionOpCode->MatchExp.StringExp); | |
PushDependencyExpDes (&DepExpressionOpCode); | |
break; | |
case EFI_IFR_MATCH2_OP: | |
DepExpressionOpCode->Match2Exp.Operand = ExpressionOpCode->Operand; | |
CopyMem (&DepExpressionOpCode->Match2Exp.SyntaxType, &ExpressionOpCode->ExtraData.Guid, sizeof (EFI_GUID)); | |
PopDependencyExpDes (&DepExpressionOpCode->Match2Exp.PatternExp); | |
PopDependencyExpDes (&DepExpressionOpCode->Match2Exp.StringExp); | |
PushDependencyExpDes (&DepExpressionOpCode); | |
break; | |
case EFI_IFR_MODULO_OP: | |
DepExpressionOpCode->ModExp.Operand = ExpressionOpCode->Operand; | |
PopDependencyExpDes (&DepExpressionOpCode->ModExp.LeftHandExp); | |
PopDependencyExpDes (&DepExpressionOpCode->ModExp.RightHandExp); | |
PushDependencyExpDes (&DepExpressionOpCode); | |
break; | |
case EFI_IFR_MULTIPLY_OP: | |
DepExpressionOpCode->MultExp.Operand = ExpressionOpCode->Operand; | |
PopDependencyExpDes (&DepExpressionOpCode->MultExp.LeftHandExp); | |
PopDependencyExpDes (&DepExpressionOpCode->MultExp.RightHandExp); | |
PushDependencyExpDes (&DepExpressionOpCode); | |
break; | |
case EFI_IFR_NOT_EQUAL_OP: | |
DepExpressionOpCode->NotEqualExp.Operand = ExpressionOpCode->Operand; | |
PopDependencyExpDes (&DepExpressionOpCode->NotEqualExp.SubExpression1); | |
PopDependencyExpDes (&DepExpressionOpCode->NotEqualExp.SubExpression2); | |
PushDependencyExpDes (&DepExpressionOpCode); | |
break; | |
case EFI_IFR_OR_OP: | |
DepExpressionOpCode->OrExp.Operand = ExpressionOpCode->Operand; | |
PopDependencyExpDes (&DepExpressionOpCode->OrExp.SubExpression1); | |
PopDependencyExpDes (&DepExpressionOpCode->OrExp.SubExpression2); | |
PushDependencyExpDes (&DepExpressionOpCode); | |
break; | |
case EFI_IFR_SHIFT_LEFT_OP: | |
DepExpressionOpCode->ShiftLeftExp.Operand = ExpressionOpCode->Operand; | |
PopDependencyExpDes (&DepExpressionOpCode->ShiftLeftExp.LeftHandExp); | |
PopDependencyExpDes (&DepExpressionOpCode->ShiftLeftExp.RightHandExp); | |
PushDependencyExpDes (&DepExpressionOpCode); | |
break; | |
case EFI_IFR_SHIFT_RIGHT_OP: | |
DepExpressionOpCode->ShiftRightExp.Operand = ExpressionOpCode->Operand; | |
PopDependencyExpDes (&DepExpressionOpCode->ShiftRightExp.LeftHandExp); | |
PopDependencyExpDes (&DepExpressionOpCode->ShiftRightExp.RightHandExp); | |
PushDependencyExpDes (&DepExpressionOpCode); | |
break; | |
case EFI_IFR_SUBTRACT_OP: | |
DepExpressionOpCode->SubtractExp.Operand = ExpressionOpCode->Operand; | |
PopDependencyExpDes (&DepExpressionOpCode->SubtractExp.LeftHandExp); | |
PopDependencyExpDes (&DepExpressionOpCode->SubtractExp.RightHandExp); | |
PushDependencyExpDes (&DepExpressionOpCode); | |
break; | |
// | |
// ternary-op | |
// | |
case EFI_IFR_CONDITIONAL_OP: | |
DepExpressionOpCode->ConditionalExp.Operand = ExpressionOpCode->Operand; | |
PopDependencyExpDes (&DepExpressionOpCode->ConditionalExp.CondTrueValExp); | |
PopDependencyExpDes (&DepExpressionOpCode->ConditionalExp.CondFalseValExp); | |
PopDependencyExpDes (&DepExpressionOpCode->ConditionalExp.ConditionExp); | |
PushDependencyExpDes (&DepExpressionOpCode); | |
break; | |
case EFI_IFR_FIND_OP: | |
DepExpressionOpCode->FindExp.Operand = ExpressionOpCode->Operand; | |
PopDependencyExpDes (&DepExpressionOpCode->FindExp.StringToSearchExp); | |
PopDependencyExpDes (&DepExpressionOpCode->FindExp.StringToCompWithExp); | |
PopDependencyExpDes (&DepExpressionOpCode->FindExp.IndexExp); | |
PushDependencyExpDes (&DepExpressionOpCode); | |
break; | |
case EFI_IFR_MID_OP: | |
DepExpressionOpCode->MidExp.Operand = ExpressionOpCode->Operand; | |
PopDependencyExpDes (&DepExpressionOpCode->MidExp.StringOrBufferExp); | |
PopDependencyExpDes (&DepExpressionOpCode->MidExp.IndexExp); | |
PopDependencyExpDes (&DepExpressionOpCode->MidExp.LengthExp); | |
PushDependencyExpDes (&DepExpressionOpCode); | |
break; | |
case EFI_IFR_TOKEN_OP: | |
DepExpressionOpCode->TokenExp.Operand = ExpressionOpCode->Operand; | |
PopDependencyExpDes (&DepExpressionOpCode->TokenExp.StringToSearchExp); | |
PopDependencyExpDes (&DepExpressionOpCode->TokenExp.DelimiterExp); | |
PopDependencyExpDes (&DepExpressionOpCode->TokenExp.IndexExp); | |
PushDependencyExpDes (&DepExpressionOpCode); | |
break; | |
case EFI_IFR_SPAN_OP: | |
DepExpressionOpCode->SpanExp.Operand = ExpressionOpCode->Operand; | |
PopDependencyExpDes (&DepExpressionOpCode->SpanExp.StringToSearchExp); | |
PopDependencyExpDes (&DepExpressionOpCode->SpanExp.CharsetExp); | |
PopDependencyExpDes (&DepExpressionOpCode->SpanExp.IndexExp); | |
PushDependencyExpDes (&DepExpressionOpCode); | |
break; | |
// | |
// Map | |
// | |
case EFI_IFR_MAP_OP: | |
// | |
// Go through map expression list. | |
// | |
DepExpressionOpCode->MapExp.Operand = ExpressionOpCode->Operand; | |
MapPairCount = 0; | |
SubExpressionLink = GetFirstNode (&ExpressionOpCode->MapExpressionList); | |
while (!IsNull (&ExpressionOpCode->MapExpressionList, SubExpressionLink)) { | |
MapPairCount++; | |
SubExpressionLink = GetNextNode (&ExpressionOpCode->MapExpressionList, SubExpressionLink); | |
if (IsNull (&ExpressionOpCode->MapExpressionList, SubExpressionLink)) { | |
Status = EFI_INVALID_PARAMETER; | |
goto Done; | |
} | |
// | |
// Goto the first expression on next pair. | |
// | |
SubExpressionLink = GetNextNode (&ExpressionOpCode->MapExpressionList, SubExpressionLink); | |
} | |
DepExpressionOpCode->MapExp.ExpPair = (HII_DEPENDENCY_EXPRESSION_PAIR *)AllocateZeroPool ( | |
MapPairCount * sizeof (HII_DEPENDENCY_EXPRESSION_PAIR) | |
); | |
if (DepExpressionOpCode->MapExp.ExpPair == NULL) { | |
Status = EFI_OUT_OF_RESOURCES; | |
goto Done; | |
} | |
DepExpressionOpCode->MapExp.ExpPairNo = MapPairCount; | |
MapPairCount = 0; | |
PopDependencyExpDes (&DepExpressionOpCode->MapExp.SubExp); | |
// | |
// Go through map expression list. | |
// | |
SubExpressionLink = GetFirstNode (&ExpressionOpCode->MapExpressionList); | |
while (!IsNull (&ExpressionOpCode->MapExpressionList, SubExpressionLink)) { | |
SubExpression = HII_EXPRESSION_FROM_LINK (SubExpressionLink); | |
// | |
// Get the first expression description in this pair. | |
// | |
GetHiiExpressionDependency (SubExpression); | |
DepExpressionOpCode->MapExp.ExpPair[MapPairCount].MatchExp = SubExpression->RootDependencyExp; | |
// | |
// Get the second expression description in this pair. | |
// | |
SubExpressionLink = GetNextNode (&ExpressionOpCode->MapExpressionList, SubExpressionLink); | |
SubExpression = HII_EXPRESSION_FROM_LINK (SubExpressionLink); | |
GetHiiExpressionDependency (SubExpression); | |
DepExpressionOpCode->MapExp.ExpPair[MapPairCount].ReturnExp = SubExpression->RootDependencyExp; | |
// | |
// Goto the first expression on next pair. | |
// | |
SubExpressionLink = GetNextNode (&ExpressionOpCode->MapExpressionList, SubExpressionLink); | |
MapPairCount++; | |
} | |
PushDependencyExpDes (&DepExpressionOpCode); | |
break; | |
default: | |
break; | |
} | |
} | |
PopDependencyExpDes (&Expression->RootDependencyExp); | |
Done: | |
return Status; | |
} | |
/** | |
Return the result of the expression list. Check the expression list and | |
return the highest priority express result. | |
Priority: DisableIf > SuppressIf > GrayOutIf > FALSE | |
@param[in] ExpList The input expression list. | |
@param[in] Evaluate Whether need to evaluate the expression first. | |
@param[in] FormSet FormSet associated with this expression. | |
@param[in] Form Form associated with this expression. | |
@retval EXPRESS_RESULT Return the higher priority express result. | |
DisableIf > SuppressIf > GrayOutIf > FALSE | |
**/ | |
EXPRESS_RESULT | |
EvaluateExpressionList ( | |
IN HII_EXPRESSION_LIST *ExpList, | |
IN BOOLEAN Evaluate, | |
IN HII_FORMSET *FormSet OPTIONAL, | |
IN HII_FORM *Form OPTIONAL | |
) | |
{ | |
UINTN Index; | |
EXPRESS_RESULT ReturnVal; | |
EXPRESS_RESULT CompareOne; | |
EFI_STATUS Status; | |
if (ExpList == NULL) { | |
return ExpressFalse; | |
} | |
ASSERT (ExpList->Signature == HII_EXPRESSION_LIST_SIGNATURE); | |
Index = 0; | |
// | |
// Check whether need to evaluate the expression first. | |
// | |
if (Evaluate) { | |
while (ExpList->Count > Index) { | |
Status = EvaluateHiiExpression (FormSet, Form, ExpList->Expression[Index++]); | |
if (EFI_ERROR (Status)) { | |
return ExpressFalse; | |
} | |
} | |
} | |
// | |
// Run the list of expressions. | |
// | |
ReturnVal = ExpressFalse; | |
for (Index = 0; Index < ExpList->Count; Index++) { | |
if (IsHiiValueTrue (&ExpList->Expression[Index]->Result)) { | |
switch (ExpList->Expression[Index]->Type) { | |
case EFI_HII_EXPRESSION_SUPPRESS_IF: | |
CompareOne = ExpressSuppress; | |
break; | |
case EFI_HII_EXPRESSION_GRAY_OUT_IF: | |
CompareOne = ExpressGrayOut; | |
break; | |
case EFI_HII_EXPRESSION_DISABLE_IF: | |
CompareOne = ExpressDisable; | |
break; | |
default: | |
return ExpressFalse; | |
} | |
ReturnVal = ReturnVal < CompareOne ? CompareOne : ReturnVal; | |
} | |
} | |
return ReturnVal; | |
} |