mirror of
https://github.com/CloverHackyColor/CloverBootloader.git
synced 2024-12-01 12:53:27 +01:00
1440 lines
46 KiB
C
1440 lines
46 KiB
C
/** @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;
|
|
}
|