+/**\r
+ Reset stack pointer to begin of the stack.\r
+\r
+**/\r
+VOID\r
+ResetCurrentExpressionStack (\r
+ VOID\r
+ )\r
+{\r
+ mCurrentExpressionPointer = mCurrentExpressionStack;\r
+ mFormExpressionPointer = mFormExpressionStack;\r
+ mStatementExpressionPointer = mStatementExpressionStack;\r
+ mOptionExpressionPointer = mOptionExpressionStack; \r
+}\r
+\r
+\r
+/**\r
+ Push current expression onto the Stack\r
+\r
+ @param Pointer Pointer to current expression.\r
+\r
+ @retval EFI_SUCCESS The value was pushed onto the stack.\r
+ @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the stack.\r
+\r
+**/\r
+EFI_STATUS\r
+PushCurrentExpression (\r
+ IN VOID *Pointer\r
+ )\r
+{\r
+ EFI_HII_VALUE Data;\r
+\r
+ Data.Type = EFI_IFR_TYPE_NUM_SIZE_64;\r
+ Data.Value.u64 = (UINT64) (UINTN) Pointer;\r
+\r
+ return PushStack (\r
+ &mCurrentExpressionStack,\r
+ &mCurrentExpressionPointer,\r
+ &mCurrentExpressionEnd,\r
+ &Data\r
+ );\r
+}\r
+\r
+\r
+/**\r
+ Pop current expression from the Stack\r
+\r
+ @param Pointer Pointer to current expression to be pop.\r
+\r
+ @retval EFI_SUCCESS The value was pushed onto the stack.\r
+ @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the stack.\r
+\r
+**/\r
+EFI_STATUS\r
+PopCurrentExpression (\r
+ OUT VOID **Pointer\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_HII_VALUE Data;\r
+\r
+ Status = PopStack (\r
+ mCurrentExpressionStack,\r
+ &mCurrentExpressionPointer,\r
+ &Data\r
+ );\r
+\r
+ *Pointer = (VOID *) (UINTN) Data.Value.u64;\r
+\r
+ return Status;\r
+}\r
+\r
+/**\r
+ Reset stack pointer to begin of the stack.\r
+\r
+**/\r
+VOID\r
+ResetMapExpressionListStack (\r
+ VOID\r
+ )\r
+{\r
+ mMapExpressionListPointer = mMapExpressionListStack;\r
+}\r
+\r
+\r
+/**\r
+ Grow size of the stack.\r
+\r
+ This is an internal function.\r
+\r
+ @param Stack On input: old stack; On output: new stack\r
+ @param StackPtr On input: old stack pointer; On output: new stack\r
+ pointer\r
+ @param StackEnd On input: old stack end; On output: new stack end\r
+ @param MemberSize The stack member size.\r
+ \r
+ @retval EFI_SUCCESS Grow stack success.\r
+ @retval EFI_OUT_OF_RESOURCES No enough memory for stack space.\r
+\r
+**/\r
+EFI_STATUS\r
+GrowConditionalStack (\r
+ IN OUT FORM_EXPRESSION ***Stack,\r
+ IN OUT FORM_EXPRESSION ***StackPtr,\r
+ IN OUT FORM_EXPRESSION ***StackEnd,\r
+ IN UINTN MemberSize\r
+ )\r
+{\r
+ UINTN Size;\r
+ FORM_EXPRESSION **NewStack;\r
+\r
+ Size = EXPRESSION_STACK_SIZE_INCREMENT;\r
+ if (*StackPtr != NULL) {\r
+ Size = Size + (*StackEnd - *Stack);\r
+ }\r
+\r
+ NewStack = AllocatePool (Size * MemberSize);\r
+ if (NewStack == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ if (*StackPtr != NULL) {\r
+ //\r
+ // Copy from Old Stack to the New Stack\r
+ //\r
+ CopyMem (\r
+ NewStack,\r
+ *Stack,\r
+ (*StackEnd - *Stack) * MemberSize\r
+ );\r
+\r
+ //\r
+ // Free The Old Stack\r
+ //\r
+ FreePool (*Stack);\r
+ }\r
+\r
+ //\r
+ // Make the Stack pointer point to the old data in the new stack\r
+ //\r
+ *StackPtr = NewStack + (*StackPtr - *Stack);\r
+ *Stack = NewStack;\r
+ *StackEnd = NewStack + Size;\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Push an element onto the Stack.\r
+\r
+ @param Stack On input: old stack; On output: new stack\r
+ @param StackPtr On input: old stack pointer; On output: new stack\r
+ pointer\r
+ @param StackEnd On input: old stack end; On output: new stack end\r
+ @param Data Data to push.\r
+\r
+ @retval EFI_SUCCESS Push stack success.\r
+\r
+**/\r
+EFI_STATUS\r
+PushConditionalStack (\r
+ IN OUT FORM_EXPRESSION ***Stack,\r
+ IN OUT FORM_EXPRESSION ***StackPtr,\r
+ IN OUT FORM_EXPRESSION ***StackEnd,\r
+ IN FORM_EXPRESSION **Data\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+\r
+ //\r
+ // Check for a stack overflow condition\r
+ //\r
+ if (*StackPtr >= *StackEnd) {\r
+ //\r
+ // Grow the stack\r
+ //\r
+ Status = GrowConditionalStack (Stack, StackPtr, StackEnd, sizeof (FORM_EXPRESSION *));\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ }\r
+\r
+ //\r
+ // Push the item onto the stack\r
+ //\r
+ CopyMem (*StackPtr, Data, sizeof (FORM_EXPRESSION *)); \r
+ *StackPtr = *StackPtr + 1;\r
+\r
+ return EFI_SUCCESS;\r
+\r
+}\r
+\r
+/**\r
+ Pop an element from the stack.\r
+\r
+ @param Stack On input: old stack\r
+ @param StackPtr On input: old stack pointer; On output: new stack pointer\r
+ @param Data Data to pop.\r
+\r
+ @retval EFI_SUCCESS The value was popped onto the stack.\r
+ @retval EFI_ACCESS_DENIED The pop operation underflowed the stack\r
+\r
+**/\r
+EFI_STATUS\r
+PopConditionalStack (\r
+ IN FORM_EXPRESSION **Stack,\r
+ IN OUT FORM_EXPRESSION ***StackPtr,\r
+ OUT FORM_EXPRESSION **Data\r
+ )\r
+{\r
+ //\r
+ // Check for a stack underflow condition\r
+ //\r
+ if (*StackPtr == Stack) {\r
+ return EFI_ACCESS_DENIED;\r
+ }\r
+\r
+ //\r
+ // Pop the item off the stack\r
+ //\r
+ *StackPtr = *StackPtr - 1;\r
+ CopyMem (Data, *StackPtr, sizeof (FORM_EXPRESSION *));\r
+ return EFI_SUCCESS;\r
+\r
+}\r
+\r
+/**\r
+ Get the expression list count.\r
+ \r
+ @param Level Which type this expression belong to. Form, \r
+ statement or option?\r
+\r
+ @retval >=0 The expression count\r
+ @retval -1 Input parameter error.\r
+\r
+**/\r
+INTN \r
+GetConditionalExpressionCount (\r
+ IN EXPRESS_LEVEL Level\r
+ )\r
+{\r
+ switch (Level) {\r
+ case ExpressForm:\r
+ return mFormExpressionPointer - mFormExpressionStack;\r
+ case ExpressStatement:\r
+ return mStatementExpressionPointer - mStatementExpressionStack;\r
+ case ExpressOption:\r
+ return mOptionExpressionPointer - mOptionExpressionStack;\r
+ default:\r
+ ASSERT (FALSE);\r
+ return -1;\r
+ } \r
+}\r
+\r
+/**\r
+ Get the expression Buffer pointer.\r
+ \r
+ @param Level Which type this expression belong to. Form, \r
+ statement or option?\r
+\r
+ @retval The start pointer of the expression buffer or NULL.\r
+\r
+**/\r
+FORM_EXPRESSION **\r
+GetConditionalExpressionList (\r
+ IN EXPRESS_LEVEL Level\r
+ )\r
+{\r
+ switch (Level) {\r
+ case ExpressForm:\r
+ return mFormExpressionStack;\r
+ case ExpressStatement:\r
+ return mStatementExpressionStack;\r
+ case ExpressOption:\r
+ return mOptionExpressionStack;\r
+ default:\r
+ ASSERT (FALSE);\r
+ return NULL;\r
+ } \r
+}\r
+\r
+\r
+/**\r
+ Push the expression options onto the Stack.\r
+\r
+ @param Pointer Pointer to the current expression.\r
+ @param Level Which type this expression belong to. Form, \r
+ statement or option?\r
+\r
+ @retval EFI_SUCCESS The value was pushed onto the stack.\r
+ @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the stack.\r
+\r
+**/\r
+EFI_STATUS\r
+PushConditionalExpression (\r
+ IN FORM_EXPRESSION *Pointer,\r
+ IN EXPRESS_LEVEL Level\r
+ )\r
+{\r
+ switch (Level) {\r
+ case ExpressForm:\r
+ return PushConditionalStack (\r
+ &mFormExpressionStack,\r
+ &mFormExpressionPointer,\r
+ &mFormExpressionEnd,\r
+ &Pointer\r
+ );\r
+ case ExpressStatement:\r
+ return PushConditionalStack (\r
+ &mStatementExpressionStack,\r
+ &mStatementExpressionPointer,\r
+ &mStatementExpressionEnd,\r
+ &Pointer\r
+ );\r
+ case ExpressOption:\r
+ return PushConditionalStack (\r
+ &mOptionExpressionStack,\r
+ &mOptionExpressionPointer,\r
+ &mOptionExpressionEnd,\r
+ &Pointer\r
+ );\r
+ default:\r
+ ASSERT (FALSE);\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+}\r
+\r
+/**\r
+ Pop the expression options from the Stack\r
+\r
+ @param Level Which type this expression belong to. Form, \r
+ statement or option?\r
+\r
+ @retval EFI_SUCCESS The value was pushed onto the stack.\r
+ @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the stack.\r
+\r
+**/\r
+EFI_STATUS\r
+PopConditionalExpression (\r
+ IN EXPRESS_LEVEL Level\r
+ )\r
+{\r
+ FORM_EXPRESSION *Pointer;\r
+\r
+ switch (Level) {\r
+ case ExpressForm:\r
+ return PopConditionalStack (\r
+ mFormExpressionStack,\r
+ &mFormExpressionPointer,\r
+ &Pointer\r
+ );\r
+\r
+ case ExpressStatement:\r
+ return PopConditionalStack (\r
+ mStatementExpressionStack,\r
+ &mStatementExpressionPointer,\r
+ &Pointer\r
+ );\r
+\r
+ case ExpressOption:\r
+ return PopConditionalStack (\r
+ mOptionExpressionStack,\r
+ &mOptionExpressionPointer,\r
+ &Pointer\r
+ );\r
+\r
+ default:\r
+ ASSERT (FALSE);\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+}\r
+\r
+\r
+/**\r
+ Push the list of map expression onto the Stack\r
+\r
+ @param Pointer Pointer to the list of map expression to be pushed.\r
+\r
+ @retval EFI_SUCCESS The value was pushed onto the stack.\r
+ @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the stack.\r
+\r
+**/\r
+EFI_STATUS\r
+PushMapExpressionList (\r
+ IN VOID *Pointer\r
+ )\r
+{\r
+ EFI_HII_VALUE Data;\r
+\r
+ Data.Type = EFI_IFR_TYPE_NUM_SIZE_64;\r
+ Data.Value.u64 = (UINT64) (UINTN) Pointer;\r
+\r
+ return PushStack (\r
+ &mMapExpressionListStack,\r
+ &mMapExpressionListPointer,\r
+ &mMapExpressionListEnd,\r
+ &Data\r
+ );\r
+}\r
+\r
+\r
+/**\r
+ Pop the list of map expression from the Stack\r
+\r
+ @param Pointer Pointer to the list of map expression to be pop.\r
+\r
+ @retval EFI_SUCCESS The value was pushed onto the stack.\r
+ @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the stack.\r
+\r
+**/\r
+EFI_STATUS\r
+PopMapExpressionList (\r
+ OUT VOID **Pointer\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_HII_VALUE Data;\r
+\r
+ Status = PopStack (\r
+ mMapExpressionListStack,\r
+ &mMapExpressionListPointer,\r
+ &Data\r
+ );\r
+\r
+ *Pointer = (VOID *) (UINTN) Data.Value.u64;\r
+\r
+ return Status;\r
+}\r
+\r