| /** @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; | |
| } |