REF: https://bugzilla.tianocore.org/show_bug.cgi?id=3737 Apply uncrustify changes to .c/.h files in the MdeModulePkg package Cc: Andrew Fish <afish@apple.com> Cc: Leif Lindholm <leif@nuviainc.com> Cc: Michael D Kinney <michael.d.kinney@intel.com> Signed-off-by: Michael Kubacki <michael.kubacki@microsoft.com> Reviewed-by: Liming Gao <gaoliming@byosoft.com.cn>
		
			
				
	
	
		
			3792 lines
		
	
	
		
			100 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			3792 lines
		
	
	
		
			100 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /** @file
 | |
| Utility functions for expression evaluation.
 | |
| 
 | |
| Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.<BR>
 | |
| SPDX-License-Identifier: BSD-2-Clause-Patent
 | |
| 
 | |
| **/
 | |
| 
 | |
| #include "Setup.h"
 | |
| 
 | |
| //
 | |
| // Global stack used to evaluate boolean expresions
 | |
| //
 | |
| EFI_HII_VALUE  *mOpCodeScopeStack        = NULL;
 | |
| EFI_HII_VALUE  *mOpCodeScopeStackEnd     = NULL;
 | |
| EFI_HII_VALUE  *mOpCodeScopeStackPointer = NULL;
 | |
| 
 | |
| EFI_HII_VALUE  *mExpressionEvaluationStack        = NULL;
 | |
| EFI_HII_VALUE  *mExpressionEvaluationStackEnd     = NULL;
 | |
| EFI_HII_VALUE  *mExpressionEvaluationStackPointer = NULL;
 | |
| UINTN          mExpressionEvaluationStackOffset   = 0;
 | |
| 
 | |
| EFI_HII_VALUE  *mCurrentExpressionStack   = NULL;
 | |
| EFI_HII_VALUE  *mCurrentExpressionEnd     = NULL;
 | |
| EFI_HII_VALUE  *mCurrentExpressionPointer = NULL;
 | |
| 
 | |
| EFI_HII_VALUE  *mMapExpressionListStack   = NULL;
 | |
| EFI_HII_VALUE  *mMapExpressionListEnd     = NULL;
 | |
| EFI_HII_VALUE  *mMapExpressionListPointer = NULL;
 | |
| 
 | |
| FORM_EXPRESSION  **mFormExpressionStack   = NULL;
 | |
| FORM_EXPRESSION  **mFormExpressionEnd     = NULL;
 | |
| FORM_EXPRESSION  **mFormExpressionPointer = NULL;
 | |
| 
 | |
| FORM_EXPRESSION  **mStatementExpressionStack   = NULL;
 | |
| FORM_EXPRESSION  **mStatementExpressionEnd     = NULL;
 | |
| FORM_EXPRESSION  **mStatementExpressionPointer = NULL;
 | |
| 
 | |
| FORM_EXPRESSION  **mOptionExpressionStack   = NULL;
 | |
| FORM_EXPRESSION  **mOptionExpressionEnd     = NULL;
 | |
| FORM_EXPRESSION  **mOptionExpressionPointer = NULL;
 | |
| 
 | |
| //
 | |
| // Unicode collation protocol interface
 | |
| //
 | |
| EFI_UNICODE_COLLATION_PROTOCOL  *mUnicodeCollation = NULL;
 | |
| EFI_USER_MANAGER_PROTOCOL       *mUserManager      = 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);
 | |
|     ASSERT ((*StackPtr)->Buffer != NULL);
 | |
|   }
 | |
| 
 | |
|   *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 FORM_EXPRESSION  ***Stack,
 | |
|   IN OUT FORM_EXPRESSION  ***StackPtr,
 | |
|   IN OUT FORM_EXPRESSION  ***StackEnd,
 | |
|   IN     UINTN            MemberSize
 | |
|   )
 | |
| {
 | |
|   UINTN            Size;
 | |
|   FORM_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 FORM_EXPRESSION  ***Stack,
 | |
|   IN OUT FORM_EXPRESSION  ***StackPtr,
 | |
|   IN OUT FORM_EXPRESSION  ***StackEnd,
 | |
|   IN     FORM_EXPRESSION  **Data
 | |
|   )
 | |
| {
 | |
|   EFI_STATUS  Status;
 | |
| 
 | |
|   //
 | |
|   // Check for a stack overflow condition
 | |
|   //
 | |
|   if (*StackPtr >= *StackEnd) {
 | |
|     //
 | |
|     // Grow the stack
 | |
|     //
 | |
|     Status = GrowConditionalStack (Stack, StackPtr, StackEnd, sizeof (FORM_EXPRESSION *));
 | |
|     if (EFI_ERROR (Status)) {
 | |
|       return Status;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Push the item onto the stack
 | |
|   //
 | |
|   CopyMem (*StackPtr, Data, sizeof (FORM_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     FORM_EXPRESSION  **Stack,
 | |
|   IN OUT FORM_EXPRESSION  ***StackPtr,
 | |
|   OUT    FORM_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 (FORM_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.
 | |
| 
 | |
| **/
 | |
| FORM_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 FORM_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
 | |
|   )
 | |
| {
 | |
|   FORM_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;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Push an Expression value onto the Stack
 | |
| 
 | |
|   @param  Value                  Expression value 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
 | |
| PushExpression (
 | |
|   IN EFI_HII_VALUE  *Value
 | |
|   )
 | |
| {
 | |
|   return PushStack (
 | |
|            &mExpressionEvaluationStack,
 | |
|            &mExpressionEvaluationStackPointer,
 | |
|            &mExpressionEvaluationStackEnd,
 | |
|            Value
 | |
|            );
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Pop an Expression value from the stack.
 | |
| 
 | |
|   @param  Value                  Expression value to pop.
 | |
| 
 | |
|   @retval EFI_SUCCESS            The value was popped onto the stack.
 | |
|   @retval EFI_ACCESS_DENIED      The pop operation underflowed the stack
 | |
| 
 | |
| **/
 | |
| EFI_STATUS
 | |
| PopExpression (
 | |
|   OUT EFI_HII_VALUE  *Value
 | |
|   )
 | |
| {
 | |
|   return PopStack (
 | |
|            mExpressionEvaluationStack + mExpressionEvaluationStackOffset,
 | |
|            &mExpressionEvaluationStackPointer,
 | |
|            Value
 | |
|            );
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Get current stack offset from stack start.
 | |
| 
 | |
|   @return Stack offset to stack start.
 | |
| **/
 | |
| UINTN
 | |
| SaveExpressionEvaluationStackOffset (
 | |
|   VOID
 | |
|   )
 | |
| {
 | |
|   UINTN  TempStackOffset;
 | |
| 
 | |
|   TempStackOffset                  = mExpressionEvaluationStackOffset;
 | |
|   mExpressionEvaluationStackOffset = mExpressionEvaluationStackPointer - mExpressionEvaluationStack;
 | |
|   return TempStackOffset;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Restore stack offset based on input stack offset
 | |
| 
 | |
|   @param  StackOffset  Offset to stack start.
 | |
| 
 | |
| **/
 | |
| VOID
 | |
| RestoreExpressionEvaluationStackOffset (
 | |
|   UINTN  StackOffset
 | |
|   )
 | |
| {
 | |
|   mExpressionEvaluationStackOffset = StackOffset;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Get Form given its FormId.
 | |
| 
 | |
|   @param  FormSet                The formset which contains this form.
 | |
|   @param  FormId                 Id of this form.
 | |
| 
 | |
|   @retval Pointer                The form.
 | |
|   @retval NULL                   Specified Form is not found in the formset.
 | |
| 
 | |
| **/
 | |
| FORM_BROWSER_FORM *
 | |
| IdToForm (
 | |
|   IN FORM_BROWSER_FORMSET  *FormSet,
 | |
|   IN UINT16                FormId
 | |
|   )
 | |
| {
 | |
|   LIST_ENTRY         *Link;
 | |
|   FORM_BROWSER_FORM  *Form;
 | |
| 
 | |
|   Link = GetFirstNode (&FormSet->FormListHead);
 | |
|   while (!IsNull (&FormSet->FormListHead, Link)) {
 | |
|     Form = FORM_BROWSER_FORM_FROM_LINK (Link);
 | |
| 
 | |
|     if (Form->FormId == FormId) {
 | |
|       return Form;
 | |
|     }
 | |
| 
 | |
|     Link = GetNextNode (&FormSet->FormListHead, Link);
 | |
|   }
 | |
| 
 | |
|   return NULL;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Search a Question in Form scope using its QuestionId.
 | |
| 
 | |
|   @param  Form                   The form which contains this Question.
 | |
|   @param  QuestionId             Id of this Question.
 | |
| 
 | |
|   @retval Pointer                The Question.
 | |
|   @retval NULL                   Specified Question not found in the form.
 | |
| 
 | |
| **/
 | |
| FORM_BROWSER_STATEMENT *
 | |
| IdToQuestion2 (
 | |
|   IN FORM_BROWSER_FORM  *Form,
 | |
|   IN UINT16             QuestionId
 | |
|   )
 | |
| {
 | |
|   LIST_ENTRY              *Link;
 | |
|   FORM_BROWSER_STATEMENT  *Question;
 | |
| 
 | |
|   if ((QuestionId == 0) || (Form == NULL)) {
 | |
|     //
 | |
|     // The value of zero is reserved
 | |
|     //
 | |
|     return NULL;
 | |
|   }
 | |
| 
 | |
|   Link = GetFirstNode (&Form->StatementListHead);
 | |
|   while (!IsNull (&Form->StatementListHead, Link)) {
 | |
|     Question = FORM_BROWSER_STATEMENT_FROM_LINK (Link);
 | |
| 
 | |
|     if (Question->QuestionId == QuestionId) {
 | |
|       return Question;
 | |
|     }
 | |
| 
 | |
|     Link = GetNextNode (&Form->StatementListHead, Link);
 | |
|   }
 | |
| 
 | |
|   return NULL;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Search a Question in Formset scope using its QuestionId.
 | |
| 
 | |
|   @param  FormSet                The formset which contains this form.
 | |
|   @param  Form                   The form which contains this Question.
 | |
|   @param  QuestionId             Id of this Question.
 | |
| 
 | |
|   @retval Pointer                The Question.
 | |
|   @retval NULL                   Specified Question not found in the form.
 | |
| 
 | |
| **/
 | |
| FORM_BROWSER_STATEMENT *
 | |
| IdToQuestion (
 | |
|   IN FORM_BROWSER_FORMSET  *FormSet,
 | |
|   IN FORM_BROWSER_FORM     *Form,
 | |
|   IN UINT16                QuestionId
 | |
|   )
 | |
| {
 | |
|   LIST_ENTRY              *Link;
 | |
|   FORM_BROWSER_STATEMENT  *Question;
 | |
| 
 | |
|   //
 | |
|   // Search in the form scope first
 | |
|   //
 | |
|   Question = IdToQuestion2 (Form, QuestionId);
 | |
|   if (Question != NULL) {
 | |
|     return Question;
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Search in the formset scope
 | |
|   //
 | |
|   Link = GetFirstNode (&FormSet->FormListHead);
 | |
|   while (!IsNull (&FormSet->FormListHead, Link)) {
 | |
|     Form = FORM_BROWSER_FORM_FROM_LINK (Link);
 | |
| 
 | |
|     Question = IdToQuestion2 (Form, QuestionId);
 | |
|     if (Question != NULL) {
 | |
|       //
 | |
|       // EFI variable storage may be updated by Callback() asynchronous,
 | |
|       // to keep synchronous, always reload the Question Value.
 | |
|       //
 | |
|       if (Question->Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE) {
 | |
|         GetQuestionValue (FormSet, Form, Question, GetSetValueWithHiiDriver);
 | |
|       }
 | |
| 
 | |
|       return Question;
 | |
|     }
 | |
| 
 | |
|     Link = GetNextNode (&FormSet->FormListHead, Link);
 | |
|   }
 | |
| 
 | |
|   return NULL;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Get Expression given its RuleId.
 | |
| 
 | |
|   @param  Form                   The form which contains this Expression.
 | |
|   @param  RuleId                 Id of this Expression.
 | |
| 
 | |
|   @retval Pointer                The Expression.
 | |
|   @retval NULL                   Specified Expression not found in the form.
 | |
| 
 | |
| **/
 | |
| FORM_EXPRESSION *
 | |
| RuleIdToExpression (
 | |
|   IN FORM_BROWSER_FORM  *Form,
 | |
|   IN UINT8              RuleId
 | |
|   )
 | |
| {
 | |
|   LIST_ENTRY       *Link;
 | |
|   FORM_EXPRESSION  *Expression;
 | |
| 
 | |
|   Link = GetFirstNode (&Form->ExpressionListHead);
 | |
|   while (!IsNull (&Form->ExpressionListHead, Link)) {
 | |
|     Expression = FORM_EXPRESSION_FROM_LINK (Link);
 | |
| 
 | |
|     if ((Expression->Type == EFI_HII_EXPRESSION_RULE) && (Expression->RuleId == RuleId)) {
 | |
|       return Expression;
 | |
|     }
 | |
| 
 | |
|     Link = GetNextNode (&Form->ExpressionListHead, Link);
 | |
|   }
 | |
| 
 | |
|   return NULL;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Locate the Unicode Collation Protocol interface for later use.
 | |
| 
 | |
|   @retval EFI_SUCCESS            Protocol interface initialize success.
 | |
|   @retval Other                  Protocol interface initialize failed.
 | |
| 
 | |
| **/
 | |
| EFI_STATUS
 | |
| InitializeUnicodeCollationProtocol (
 | |
|   VOID
 | |
|   )
 | |
| {
 | |
|   EFI_STATUS  Status;
 | |
| 
 | |
|   if (mUnicodeCollation != NULL) {
 | |
|     return EFI_SUCCESS;
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // BUGBUG: Proper impelmentation is to locate all Unicode Collation Protocol
 | |
|   // instances first and then select one which support English language.
 | |
|   // Current implementation just pick the first instance.
 | |
|   //
 | |
|   Status = gBS->LocateProtocol (
 | |
|                   &gEfiUnicodeCollation2ProtocolGuid,
 | |
|                   NULL,
 | |
|                   (VOID **)&mUnicodeCollation
 | |
|                   );
 | |
|   return Status;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Convert the input Unicode character to upper.
 | |
| 
 | |
|   @param String  Th Unicode character to be converted.
 | |
| 
 | |
| **/
 | |
| VOID
 | |
| IfrStrToUpper (
 | |
|   IN CHAR16  *String
 | |
|   )
 | |
| {
 | |
|   while (*String != 0) {
 | |
|     if ((*String >= 'a') && (*String <= 'z')) {
 | |
|       *String = (UINT16)((*String) & ((UINT16) ~0x20));
 | |
|     }
 | |
| 
 | |
|     String++;
 | |
|   }
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Check whether this value type can be transfer to EFI_IFR_TYPE_BUFFER type.
 | |
| 
 | |
|   EFI_IFR_TYPE_REF, EFI_IFR_TYPE_DATE and EFI_IFR_TYPE_TIME are converted to
 | |
|   EFI_IFR_TYPE_BUFFER when do the value compare.
 | |
| 
 | |
|   @param  Value                  Expression value to compare on.
 | |
| 
 | |
|   @retval TRUE                   This value type can be transter to EFI_IFR_TYPE_BUFFER type.
 | |
|   @retval FALSE                  This value type can't be transter to EFI_IFR_TYPE_BUFFER type.
 | |
| 
 | |
| **/
 | |
| BOOLEAN
 | |
| IsTypeInBuffer (
 | |
|   IN  EFI_HII_VALUE  *Value
 | |
|   )
 | |
| {
 | |
|   switch (Value->Type) {
 | |
|     case EFI_IFR_TYPE_BUFFER:
 | |
|     case EFI_IFR_TYPE_DATE:
 | |
|     case EFI_IFR_TYPE_TIME:
 | |
|     case EFI_IFR_TYPE_REF:
 | |
|       return TRUE;
 | |
| 
 | |
|     default:
 | |
|       return FALSE;
 | |
|   }
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Check whether this value type can be transfer to EFI_IFR_TYPE_UINT64
 | |
| 
 | |
|   @param  Value                  Expression value to compare on.
 | |
| 
 | |
|   @retval TRUE                   This value type can be transter to EFI_IFR_TYPE_BUFFER type.
 | |
|   @retval FALSE                  This value type can't be transter to EFI_IFR_TYPE_BUFFER type.
 | |
| 
 | |
| **/
 | |
| BOOLEAN
 | |
| IsTypeInUINT64 (
 | |
|   IN  EFI_HII_VALUE  *Value
 | |
|   )
 | |
| {
 | |
|   switch (Value->Type) {
 | |
|     case EFI_IFR_TYPE_NUM_SIZE_8:
 | |
|     case EFI_IFR_TYPE_NUM_SIZE_16:
 | |
|     case EFI_IFR_TYPE_NUM_SIZE_32:
 | |
|     case EFI_IFR_TYPE_NUM_SIZE_64:
 | |
|     case EFI_IFR_TYPE_BOOLEAN:
 | |
|       return TRUE;
 | |
| 
 | |
|     default:
 | |
|       return FALSE;
 | |
|   }
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Return the buffer length for this value.
 | |
| 
 | |
|   EFI_IFR_TYPE_REF, EFI_IFR_TYPE_DATE and EFI_IFR_TYPE_TIME are converted to
 | |
|   EFI_IFR_TYPE_BUFFER when do the value compare.
 | |
| 
 | |
|   @param   Value                  Expression value to compare on.
 | |
| 
 | |
|   @retval  BufLen                 Return the buffer length.
 | |
| 
 | |
| **/
 | |
| UINT16
 | |
| GetLengthForValue (
 | |
|   IN  EFI_HII_VALUE  *Value
 | |
|   )
 | |
| {
 | |
|   switch (Value->Type) {
 | |
|     case EFI_IFR_TYPE_BUFFER:
 | |
|       return Value->BufferLen;
 | |
| 
 | |
|     case EFI_IFR_TYPE_DATE:
 | |
|       return (UINT16)sizeof (EFI_HII_DATE);
 | |
| 
 | |
|     case EFI_IFR_TYPE_TIME:
 | |
|       return (UINT16)sizeof (EFI_HII_TIME);
 | |
| 
 | |
|     case EFI_IFR_TYPE_REF:
 | |
|       return (UINT16)sizeof (EFI_HII_REF);
 | |
| 
 | |
|     default:
 | |
|       return 0;
 | |
|   }
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Return the buffer pointer for this value.
 | |
| 
 | |
|   EFI_IFR_TYPE_REF, EFI_IFR_TYPE_DATE and EFI_IFR_TYPE_TIME are converted to
 | |
|   EFI_IFR_TYPE_BUFFER when do the value compare.
 | |
| 
 | |
|   @param  Value                  Expression value to compare on.
 | |
| 
 | |
|   @retval Buf                    Return the buffer pointer.
 | |
| 
 | |
| **/
 | |
| UINT8 *
 | |
| GetBufferForValue (
 | |
|   IN  EFI_HII_VALUE  *Value
 | |
|   )
 | |
| {
 | |
|   switch (Value->Type) {
 | |
|     case EFI_IFR_TYPE_BUFFER:
 | |
|       return Value->Buffer;
 | |
| 
 | |
|     case EFI_IFR_TYPE_DATE:
 | |
|       return (UINT8 *)(&Value->Value.date);
 | |
| 
 | |
|     case EFI_IFR_TYPE_TIME:
 | |
|       return (UINT8 *)(&Value->Value.time);
 | |
| 
 | |
|     case EFI_IFR_TYPE_REF:
 | |
|       return (UINT8 *)(&Value->Value.ref);
 | |
| 
 | |
|     default:
 | |
|       return NULL;
 | |
|   }
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Evaluate opcode EFI_IFR_TO_STRING.
 | |
| 
 | |
|   @param  FormSet                Formset which contains this opcode.
 | |
|   @param  Format                 String format in EFI_IFR_TO_STRING.
 | |
|   @param  Result                 Evaluation result for this opcode.
 | |
| 
 | |
|   @retval EFI_SUCCESS            Opcode evaluation success.
 | |
|   @retval Other                  Opcode evaluation failed.
 | |
| 
 | |
| **/
 | |
| EFI_STATUS
 | |
| IfrToString (
 | |
|   IN FORM_BROWSER_FORMSET  *FormSet,
 | |
|   IN UINT8                 Format,
 | |
|   OUT  EFI_HII_VALUE       *Result
 | |
|   )
 | |
| {
 | |
|   EFI_STATUS     Status;
 | |
|   EFI_HII_VALUE  Value;
 | |
|   CHAR16         *String;
 | |
|   CHAR16         *PrintFormat;
 | |
|   CHAR16         Buffer[MAXIMUM_VALUE_CHARACTERS];
 | |
|   UINT8          *TmpBuf;
 | |
|   UINT8          *SrcBuf;
 | |
|   UINTN          SrcLen;
 | |
|   UINTN          BufferSize;
 | |
| 
 | |
|   Status = PopExpression (&Value);
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     return Status;
 | |
|   }
 | |
| 
 | |
|   switch (Value.Type) {
 | |
|     case EFI_IFR_TYPE_NUM_SIZE_8:
 | |
|     case EFI_IFR_TYPE_NUM_SIZE_16:
 | |
|     case EFI_IFR_TYPE_NUM_SIZE_32:
 | |
|     case EFI_IFR_TYPE_NUM_SIZE_64:
 | |
|       BufferSize = MAXIMUM_VALUE_CHARACTERS * sizeof (CHAR16);
 | |
|       switch (Format) {
 | |
|         case EFI_IFR_STRING_UNSIGNED_DEC:
 | |
|         case EFI_IFR_STRING_SIGNED_DEC:
 | |
|           PrintFormat = L"%ld";
 | |
|           break;
 | |
| 
 | |
|         case EFI_IFR_STRING_LOWERCASE_HEX:
 | |
|           PrintFormat = L"%lx";
 | |
|           break;
 | |
| 
 | |
|         case EFI_IFR_STRING_UPPERCASE_HEX:
 | |
|           PrintFormat = L"%lX";
 | |
|           break;
 | |
| 
 | |
|         default:
 | |
|           Result->Type = EFI_IFR_TYPE_UNDEFINED;
 | |
|           return EFI_SUCCESS;
 | |
|       }
 | |
| 
 | |
|       UnicodeSPrint (Buffer, BufferSize, PrintFormat, Value.Value.u64);
 | |
|       String = Buffer;
 | |
|       break;
 | |
| 
 | |
|     case EFI_IFR_TYPE_STRING:
 | |
|       CopyMem (Result, &Value, sizeof (EFI_HII_VALUE));
 | |
|       return EFI_SUCCESS;
 | |
| 
 | |
|     case EFI_IFR_TYPE_BOOLEAN:
 | |
|       String = (Value.Value.b) ? L"True" : L"False";
 | |
|       break;
 | |
| 
 | |
|     case EFI_IFR_TYPE_BUFFER:
 | |
|     case EFI_IFR_TYPE_DATE:
 | |
|     case EFI_IFR_TYPE_TIME:
 | |
|     case EFI_IFR_TYPE_REF:
 | |
|       //
 | |
|       // + 3 is base on the unicode format, the length may be odd number,
 | |
|       // so need 1 byte to align, also need 2 bytes for L'\0'.
 | |
|       //
 | |
|       if (Value.Type == EFI_IFR_TYPE_BUFFER) {
 | |
|         SrcLen = Value.BufferLen;
 | |
|         SrcBuf = Value.Buffer;
 | |
|       } else {
 | |
|         SrcBuf = GetBufferForValue (&Value);
 | |
|         SrcLen = GetLengthForValue (&Value);
 | |
|       }
 | |
| 
 | |
|       TmpBuf = AllocateZeroPool (SrcLen + 3);
 | |
|       ASSERT (TmpBuf != NULL);
 | |
|       if (Format == EFI_IFR_STRING_ASCII) {
 | |
|         CopyMem (TmpBuf, SrcBuf, SrcLen);
 | |
|         PrintFormat = L"%a";
 | |
|       } else {
 | |
|         // Format == EFI_IFR_STRING_UNICODE
 | |
|         CopyMem (TmpBuf, SrcBuf, SrcLen * sizeof (CHAR16));
 | |
|         PrintFormat = L"%s";
 | |
|       }
 | |
| 
 | |
|       UnicodeSPrint (Buffer, sizeof (Buffer), PrintFormat, TmpBuf);
 | |
|       String = Buffer;
 | |
|       FreePool (TmpBuf);
 | |
|       if (Value.Type == EFI_IFR_TYPE_BUFFER) {
 | |
|         FreePool (Value.Buffer);
 | |
|       }
 | |
| 
 | |
|       break;
 | |
| 
 | |
|     default:
 | |
|       Result->Type = EFI_IFR_TYPE_UNDEFINED;
 | |
|       return EFI_SUCCESS;
 | |
|   }
 | |
| 
 | |
|   Result->Type         = EFI_IFR_TYPE_STRING;
 | |
|   Result->Value.string = NewString (String, FormSet->HiiHandle);
 | |
|   return EFI_SUCCESS;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Evaluate opcode EFI_IFR_TO_UINT.
 | |
| 
 | |
|   @param  FormSet                Formset which contains this opcode.
 | |
|   @param  Result                 Evaluation result for this opcode.
 | |
| 
 | |
|   @retval EFI_SUCCESS            Opcode evaluation success.
 | |
|   @retval Other                  Opcode evaluation failed.
 | |
| 
 | |
| **/
 | |
| EFI_STATUS
 | |
| IfrToUint (
 | |
|   IN FORM_BROWSER_FORMSET  *FormSet,
 | |
|   OUT  EFI_HII_VALUE       *Result
 | |
|   )
 | |
| {
 | |
|   EFI_STATUS     Status;
 | |
|   EFI_HII_VALUE  Value;
 | |
|   CHAR16         *String;
 | |
|   CHAR16         *StringPtr;
 | |
| 
 | |
|   Status = PopExpression (&Value);
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     return Status;
 | |
|   }
 | |
| 
 | |
|   if ((Value.Type >= EFI_IFR_TYPE_OTHER) && !IsTypeInBuffer (&Value)) {
 | |
|     Result->Type = EFI_IFR_TYPE_UNDEFINED;
 | |
|     return EFI_SUCCESS;
 | |
|   }
 | |
| 
 | |
|   Status = EFI_SUCCESS;
 | |
|   if (Value.Type == EFI_IFR_TYPE_STRING) {
 | |
|     String = GetToken (Value.Value.string, FormSet->HiiHandle);
 | |
|     if (String == NULL) {
 | |
|       return EFI_NOT_FOUND;
 | |
|     }
 | |
| 
 | |
|     IfrStrToUpper (String);
 | |
|     StringPtr = StrStr (String, L"0X");
 | |
|     if (StringPtr != NULL) {
 | |
|       //
 | |
|       // Hex string
 | |
|       //
 | |
|       Result->Value.u64 = StrHexToUint64 (String);
 | |
|     } else {
 | |
|       //
 | |
|       // decimal string
 | |
|       //
 | |
|       Result->Value.u64 = StrDecimalToUint64 (String);
 | |
|     }
 | |
| 
 | |
|     FreePool (String);
 | |
|   } else if (IsTypeInBuffer (&Value)) {
 | |
|     if (GetLengthForValue (&Value) > 8) {
 | |
|       if (Value.Type == EFI_IFR_TYPE_BUFFER) {
 | |
|         FreePool (Value.Buffer);
 | |
|       }
 | |
| 
 | |
|       Result->Type = EFI_IFR_TYPE_UNDEFINED;
 | |
|       return EFI_SUCCESS;
 | |
|     }
 | |
| 
 | |
|     ASSERT (GetBufferForValue (&Value) != NULL);
 | |
|     Result->Value.u64 = *(UINT64 *)GetBufferForValue (&Value);
 | |
| 
 | |
|     if (Value.Type == EFI_IFR_TYPE_BUFFER) {
 | |
|       FreePool (Value.Buffer);
 | |
|     }
 | |
|   } else {
 | |
|     CopyMem (Result, &Value, sizeof (EFI_HII_VALUE));
 | |
|   }
 | |
| 
 | |
|   Result->Type = EFI_IFR_TYPE_NUM_SIZE_64;
 | |
|   return Status;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Evaluate opcode EFI_IFR_CATENATE.
 | |
| 
 | |
|   @param  FormSet                Formset which contains this opcode.
 | |
|   @param  Result                 Evaluation result for this opcode.
 | |
| 
 | |
|   @retval EFI_SUCCESS            Opcode evaluation success.
 | |
|   @retval Other                  Opcode evaluation failed.
 | |
| 
 | |
| **/
 | |
| EFI_STATUS
 | |
| IfrCatenate (
 | |
|   IN FORM_BROWSER_FORMSET  *FormSet,
 | |
|   OUT  EFI_HII_VALUE       *Result
 | |
|   )
 | |
| {
 | |
|   EFI_STATUS     Status;
 | |
|   EFI_HII_VALUE  Value[2];
 | |
|   CHAR16         *String[2];
 | |
|   UINTN          Index;
 | |
|   CHAR16         *StringPtr;
 | |
|   UINTN          Size;
 | |
|   UINT16         Length0;
 | |
|   UINT16         Length1;
 | |
|   UINT8          *TmpBuf;
 | |
|   UINTN          MaxLen;
 | |
| 
 | |
|   //
 | |
|   // String[0] - The second string
 | |
|   // String[1] - The first string
 | |
|   //
 | |
|   String[0] = NULL;
 | |
|   String[1] = NULL;
 | |
|   StringPtr = NULL;
 | |
|   Status    = EFI_SUCCESS;
 | |
|   ZeroMem (Value, sizeof (Value));
 | |
| 
 | |
|   Status = PopExpression (&Value[0]);
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     goto Done;
 | |
|   }
 | |
| 
 | |
|   Status = PopExpression (&Value[1]);
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     goto Done;
 | |
|   }
 | |
| 
 | |
|   for (Index = 0; Index < 2; Index++) {
 | |
|     if ((Value[Index].Type != EFI_IFR_TYPE_STRING) && !IsTypeInBuffer (&Value[Index])) {
 | |
|       Result->Type = EFI_IFR_TYPE_UNDEFINED;
 | |
|       Status       = EFI_SUCCESS;
 | |
|       goto Done;
 | |
|     }
 | |
| 
 | |
|     if (Value[Index].Type == EFI_IFR_TYPE_STRING) {
 | |
|       String[Index] = GetToken (Value[Index].Value.string, FormSet->HiiHandle);
 | |
|       if (String[Index] == NULL) {
 | |
|         Status = EFI_NOT_FOUND;
 | |
|         goto Done;
 | |
|       }
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   if (Value[0].Type == EFI_IFR_TYPE_STRING) {
 | |
|     Size      = StrSize (String[0]);
 | |
|     MaxLen    = (StrSize (String[1]) + Size) / sizeof (CHAR16);
 | |
|     StringPtr = AllocatePool (MaxLen * sizeof (CHAR16));
 | |
|     ASSERT (StringPtr != NULL);
 | |
|     StrCpyS (StringPtr, MaxLen, String[1]);
 | |
|     StrCatS (StringPtr, MaxLen, String[0]);
 | |
| 
 | |
|     Result->Type         = EFI_IFR_TYPE_STRING;
 | |
|     Result->Value.string = NewString (StringPtr, FormSet->HiiHandle);
 | |
|   } else {
 | |
|     Result->Type      = EFI_IFR_TYPE_BUFFER;
 | |
|     Length0           = GetLengthForValue (&Value[0]);
 | |
|     Length1           = GetLengthForValue (&Value[1]);
 | |
|     Result->BufferLen = (UINT16)(Length0 + Length1);
 | |
| 
 | |
|     Result->Buffer = AllocateZeroPool (Result->BufferLen);
 | |
|     ASSERT (Result->Buffer != NULL);
 | |
| 
 | |
|     TmpBuf = GetBufferForValue (&Value[0]);
 | |
|     ASSERT (TmpBuf != NULL);
 | |
|     CopyMem (Result->Buffer, TmpBuf, Length0);
 | |
|     TmpBuf = GetBufferForValue (&Value[1]);
 | |
|     ASSERT (TmpBuf != NULL);
 | |
|     CopyMem (&Result->Buffer[Length0], TmpBuf, Length1);
 | |
|   }
 | |
| 
 | |
| Done:
 | |
|   if (Value[0].Buffer != NULL) {
 | |
|     FreePool (Value[0].Buffer);
 | |
|   }
 | |
| 
 | |
|   if (Value[1].Buffer != NULL) {
 | |
|     FreePool (Value[1].Buffer);
 | |
|   }
 | |
| 
 | |
|   if (String[0] != NULL) {
 | |
|     FreePool (String[0]);
 | |
|   }
 | |
| 
 | |
|   if (String[1] != NULL) {
 | |
|     FreePool (String[1]);
 | |
|   }
 | |
| 
 | |
|   if (StringPtr != NULL) {
 | |
|     FreePool (StringPtr);
 | |
|   }
 | |
| 
 | |
|   return Status;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Evaluate opcode EFI_IFR_MATCH.
 | |
| 
 | |
|   @param  FormSet                Formset which contains this opcode.
 | |
|   @param  Result                 Evaluation result for this opcode.
 | |
| 
 | |
|   @retval EFI_SUCCESS            Opcode evaluation success.
 | |
|   @retval Other                  Opcode evaluation failed.
 | |
| 
 | |
| **/
 | |
| EFI_STATUS
 | |
| IfrMatch (
 | |
|   IN FORM_BROWSER_FORMSET  *FormSet,
 | |
|   OUT  EFI_HII_VALUE       *Result
 | |
|   )
 | |
| {
 | |
|   EFI_STATUS     Status;
 | |
|   EFI_HII_VALUE  Value[2];
 | |
|   CHAR16         *String[2];
 | |
|   UINTN          Index;
 | |
| 
 | |
|   //
 | |
|   // String[0] - The string to search
 | |
|   // String[1] - pattern
 | |
|   //
 | |
|   String[0] = NULL;
 | |
|   String[1] = NULL;
 | |
|   Status    = EFI_SUCCESS;
 | |
|   ZeroMem (Value, sizeof (Value));
 | |
| 
 | |
|   Status = PopExpression (&Value[0]);
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     goto Done;
 | |
|   }
 | |
| 
 | |
|   Status = PopExpression (&Value[1]);
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     goto Done;
 | |
|   }
 | |
| 
 | |
|   for (Index = 0; Index < 2; Index++) {
 | |
|     if (Value[Index].Type != EFI_IFR_TYPE_STRING) {
 | |
|       Result->Type = EFI_IFR_TYPE_UNDEFINED;
 | |
|       Status       = EFI_SUCCESS;
 | |
|       goto Done;
 | |
|     }
 | |
| 
 | |
|     String[Index] = GetToken (Value[Index].Value.string, FormSet->HiiHandle);
 | |
|     if (String[Index] == NULL) {
 | |
|       Status = EFI_NOT_FOUND;
 | |
|       goto Done;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   Result->Type    = EFI_IFR_TYPE_BOOLEAN;
 | |
|   Result->Value.b = mUnicodeCollation->MetaiMatch (mUnicodeCollation, String[0], String[1]);
 | |
| 
 | |
| Done:
 | |
|   if (String[0] != NULL) {
 | |
|     FreePool (String[0]);
 | |
|   }
 | |
| 
 | |
|   if (String[1] != NULL) {
 | |
|     FreePool (String[1]);
 | |
|   }
 | |
| 
 | |
|   return Status;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Evaluate opcode EFI_IFR_MATCH2.
 | |
| 
 | |
|   @param  FormSet                Formset which contains this opcode.
 | |
|   @param  SyntaxType             Syntax type for match2.
 | |
|   @param  Result                 Evaluation result for this opcode.
 | |
| 
 | |
|   @retval EFI_SUCCESS            Opcode evaluation success.
 | |
|   @retval Other                  Opcode evaluation failed.
 | |
| 
 | |
| **/
 | |
| EFI_STATUS
 | |
| IfrMatch2 (
 | |
|   IN FORM_BROWSER_FORMSET  *FormSet,
 | |
|   IN EFI_GUID              *SyntaxType,
 | |
|   OUT  EFI_HII_VALUE       *Result
 | |
|   )
 | |
| {
 | |
|   EFI_STATUS                       Status;
 | |
|   EFI_HII_VALUE                    Value[2];
 | |
|   CHAR16                           *String[2];
 | |
|   UINTN                            Index;
 | |
|   UINTN                            GuidIndex;
 | |
|   EFI_HANDLE                       *HandleBuffer;
 | |
|   UINTN                            BufferSize;
 | |
|   EFI_REGULAR_EXPRESSION_PROTOCOL  *RegularExpressionProtocol;
 | |
|   UINTN                            RegExSyntaxTypeListSize;
 | |
|   EFI_REGEX_SYNTAX_TYPE            *RegExSyntaxTypeList;
 | |
|   UINTN                            CapturesCount;
 | |
| 
 | |
|   //
 | |
|   // String[0] - The string to search
 | |
|   // String[1] - pattern
 | |
|   //
 | |
|   String[0]           = NULL;
 | |
|   String[1]           = NULL;
 | |
|   HandleBuffer        = NULL;
 | |
|   RegExSyntaxTypeList = NULL;
 | |
|   Status              = EFI_SUCCESS;
 | |
|   ZeroMem (Value, sizeof (Value));
 | |
| 
 | |
|   Status = PopExpression (&Value[0]);
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     goto Done;
 | |
|   }
 | |
| 
 | |
|   Status = PopExpression (&Value[1]);
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     goto Done;
 | |
|   }
 | |
| 
 | |
|   for (Index = 0; Index < 2; Index++) {
 | |
|     if (Value[Index].Type != EFI_IFR_TYPE_STRING) {
 | |
|       Result->Type = EFI_IFR_TYPE_UNDEFINED;
 | |
|       Status       = EFI_SUCCESS;
 | |
|       goto Done;
 | |
|     }
 | |
| 
 | |
|     String[Index] = GetToken (Value[Index].Value.string, FormSet->HiiHandle);
 | |
|     if (String[Index] == NULL) {
 | |
|       Status = EFI_NOT_FOUND;
 | |
|       goto Done;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   BufferSize   = 0;
 | |
|   HandleBuffer = NULL;
 | |
|   Status       = gBS->LocateHandle (
 | |
|                         ByProtocol,
 | |
|                         &gEfiRegularExpressionProtocolGuid,
 | |
|                         NULL,
 | |
|                         &BufferSize,
 | |
|                         HandleBuffer
 | |
|                         );
 | |
|   if (Status == EFI_BUFFER_TOO_SMALL) {
 | |
|     HandleBuffer = AllocateZeroPool (BufferSize);
 | |
|     if (HandleBuffer == NULL) {
 | |
|       Status = EFI_OUT_OF_RESOURCES;
 | |
|       goto Done;
 | |
|     }
 | |
| 
 | |
|     Status = gBS->LocateHandle (
 | |
|                     ByProtocol,
 | |
|                     &gEfiRegularExpressionProtocolGuid,
 | |
|                     NULL,
 | |
|                     &BufferSize,
 | |
|                     HandleBuffer
 | |
|                     );
 | |
|   }
 | |
| 
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     Result->Type = EFI_IFR_TYPE_UNDEFINED;
 | |
|     Status       = EFI_SUCCESS;
 | |
|     goto Done;
 | |
|   }
 | |
| 
 | |
|   ASSERT (HandleBuffer != NULL);
 | |
|   for ( Index = 0; Index < BufferSize / sizeof (EFI_HANDLE); Index++) {
 | |
|     Status = gBS->HandleProtocol (
 | |
|                     HandleBuffer[Index],
 | |
|                     &gEfiRegularExpressionProtocolGuid,
 | |
|                     (VOID **)&RegularExpressionProtocol
 | |
|                     );
 | |
|     if (EFI_ERROR (Status)) {
 | |
|       goto Done;
 | |
|     }
 | |
| 
 | |
|     RegExSyntaxTypeListSize = 0;
 | |
|     RegExSyntaxTypeList     = NULL;
 | |
| 
 | |
|     Status = RegularExpressionProtocol->GetInfo (
 | |
|                                           RegularExpressionProtocol,
 | |
|                                           &RegExSyntaxTypeListSize,
 | |
|                                           RegExSyntaxTypeList
 | |
|                                           );
 | |
|     if (Status == EFI_BUFFER_TOO_SMALL) {
 | |
|       RegExSyntaxTypeList = AllocateZeroPool (RegExSyntaxTypeListSize);
 | |
|       if (RegExSyntaxTypeList == NULL) {
 | |
|         Status = EFI_OUT_OF_RESOURCES;
 | |
|         goto Done;
 | |
|       }
 | |
| 
 | |
|       Status = RegularExpressionProtocol->GetInfo (
 | |
|                                             RegularExpressionProtocol,
 | |
|                                             &RegExSyntaxTypeListSize,
 | |
|                                             RegExSyntaxTypeList
 | |
|                                             );
 | |
|     } else if (EFI_ERROR (Status)) {
 | |
|       goto Done;
 | |
|     }
 | |
| 
 | |
|     for (GuidIndex = 0; GuidIndex < RegExSyntaxTypeListSize / sizeof (EFI_GUID); GuidIndex++) {
 | |
|       if (CompareGuid (&RegExSyntaxTypeList[GuidIndex], SyntaxType)) {
 | |
|         //
 | |
|         // Find the match type, return the value.
 | |
|         //
 | |
|         Result->Type = EFI_IFR_TYPE_BOOLEAN;
 | |
|         Status       = RegularExpressionProtocol->MatchString (
 | |
|                                                     RegularExpressionProtocol,
 | |
|                                                     String[0],
 | |
|                                                     String[1],
 | |
|                                                     SyntaxType,
 | |
|                                                     &Result->Value.b,
 | |
|                                                     NULL,
 | |
|                                                     &CapturesCount
 | |
|                                                     );
 | |
|         goto Done;
 | |
|       }
 | |
|     }
 | |
| 
 | |
|     if (RegExSyntaxTypeList != NULL) {
 | |
|       FreePool (RegExSyntaxTypeList);
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Type specified by SyntaxType is not supported
 | |
|   // in any of the EFI_REGULAR_EXPRESSION_PROTOCOL instances.
 | |
|   //
 | |
|   Result->Type = EFI_IFR_TYPE_UNDEFINED;
 | |
|   Status       = EFI_SUCCESS;
 | |
| 
 | |
| Done:
 | |
|   if (String[0] != NULL) {
 | |
|     FreePool (String[0]);
 | |
|   }
 | |
| 
 | |
|   if (String[1] != NULL) {
 | |
|     FreePool (String[1]);
 | |
|   }
 | |
| 
 | |
|   if (RegExSyntaxTypeList != NULL) {
 | |
|     FreePool (RegExSyntaxTypeList);
 | |
|   }
 | |
| 
 | |
|   if (HandleBuffer != NULL) {
 | |
|     FreePool (HandleBuffer);
 | |
|   }
 | |
| 
 | |
|   return Status;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Evaluate opcode EFI_IFR_FIND.
 | |
| 
 | |
|   @param  FormSet                Formset which contains this opcode.
 | |
|   @param  Format                 Case sensitive or insensitive.
 | |
|   @param  Result                 Evaluation result for this opcode.
 | |
| 
 | |
|   @retval EFI_SUCCESS            Opcode evaluation success.
 | |
|   @retval Other                  Opcode evaluation failed.
 | |
| 
 | |
| **/
 | |
| EFI_STATUS
 | |
| IfrFind (
 | |
|   IN FORM_BROWSER_FORMSET  *FormSet,
 | |
|   IN UINT8                 Format,
 | |
|   OUT  EFI_HII_VALUE       *Result
 | |
|   )
 | |
| {
 | |
|   EFI_STATUS     Status;
 | |
|   EFI_HII_VALUE  Value[3];
 | |
|   CHAR16         *String[2];
 | |
|   UINTN          Base;
 | |
|   CHAR16         *StringPtr;
 | |
|   UINTN          Index;
 | |
| 
 | |
|   ZeroMem (Value, sizeof (Value));
 | |
| 
 | |
|   if (Format > EFI_IFR_FF_CASE_INSENSITIVE) {
 | |
|     return EFI_INVALID_PARAMETER;
 | |
|   }
 | |
| 
 | |
|   Status = PopExpression (&Value[0]);
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     return Status;
 | |
|   }
 | |
| 
 | |
|   Status = PopExpression (&Value[1]);
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     return Status;
 | |
|   }
 | |
| 
 | |
|   Status = PopExpression (&Value[2]);
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     return Status;
 | |
|   }
 | |
| 
 | |
|   if (Value[0].Type > EFI_IFR_TYPE_NUM_SIZE_64) {
 | |
|     Result->Type = EFI_IFR_TYPE_UNDEFINED;
 | |
|     return EFI_SUCCESS;
 | |
|   }
 | |
| 
 | |
|   Base = (UINTN)Value[0].Value.u64;
 | |
| 
 | |
|   //
 | |
|   // String[0] - sub-string
 | |
|   // String[1] - The string to search
 | |
|   //
 | |
|   String[0] = NULL;
 | |
|   String[1] = NULL;
 | |
|   for (Index = 0; Index < 2; Index++) {
 | |
|     if (Value[Index + 1].Type != EFI_IFR_TYPE_STRING) {
 | |
|       Result->Type = EFI_IFR_TYPE_UNDEFINED;
 | |
|       Status       = EFI_SUCCESS;
 | |
|       goto Done;
 | |
|     }
 | |
| 
 | |
|     String[Index] = GetToken (Value[Index + 1].Value.string, FormSet->HiiHandle);
 | |
|     if (String[Index] == NULL) {
 | |
|       Status = EFI_NOT_FOUND;
 | |
|       goto Done;
 | |
|     }
 | |
| 
 | |
|     if (Format == EFI_IFR_FF_CASE_INSENSITIVE) {
 | |
|       //
 | |
|       // Case insensitive, convert both string to upper case
 | |
|       //
 | |
|       IfrStrToUpper (String[Index]);
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   Result->Type = EFI_IFR_TYPE_NUM_SIZE_64;
 | |
|   if (Base >= StrLen (String[1])) {
 | |
|     Result->Value.u64 = 0xFFFFFFFFFFFFFFFFULL;
 | |
|   } else {
 | |
|     StringPtr         = StrStr (String[1] + Base, String[0]);
 | |
|     Result->Value.u64 = (StringPtr == NULL) ? 0xFFFFFFFFFFFFFFFFULL : (StringPtr - String[1]);
 | |
|   }
 | |
| 
 | |
| Done:
 | |
|   if (String[0] != NULL) {
 | |
|     FreePool (String[0]);
 | |
|   }
 | |
| 
 | |
|   if (String[1] != NULL) {
 | |
|     FreePool (String[1]);
 | |
|   }
 | |
| 
 | |
|   return Status;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Evaluate opcode EFI_IFR_MID.
 | |
| 
 | |
|   @param  FormSet                Formset which contains this opcode.
 | |
|   @param  Result                 Evaluation result for this opcode.
 | |
| 
 | |
|   @retval EFI_SUCCESS            Opcode evaluation success.
 | |
|   @retval Other                  Opcode evaluation failed.
 | |
| 
 | |
| **/
 | |
| EFI_STATUS
 | |
| IfrMid (
 | |
|   IN FORM_BROWSER_FORMSET  *FormSet,
 | |
|   OUT  EFI_HII_VALUE       *Result
 | |
|   )
 | |
| {
 | |
|   EFI_STATUS     Status;
 | |
|   EFI_HII_VALUE  Value[3];
 | |
|   CHAR16         *String;
 | |
|   UINTN          Base;
 | |
|   UINTN          Length;
 | |
|   CHAR16         *SubString;
 | |
|   UINT16         BufferLen;
 | |
|   UINT8          *Buffer;
 | |
| 
 | |
|   ZeroMem (Value, sizeof (Value));
 | |
| 
 | |
|   Status = PopExpression (&Value[0]);
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     return Status;
 | |
|   }
 | |
| 
 | |
|   Status = PopExpression (&Value[1]);
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     return Status;
 | |
|   }
 | |
| 
 | |
|   Status = PopExpression (&Value[2]);
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     return Status;
 | |
|   }
 | |
| 
 | |
|   if (Value[0].Type > EFI_IFR_TYPE_NUM_SIZE_64) {
 | |
|     Result->Type = EFI_IFR_TYPE_UNDEFINED;
 | |
|     return EFI_SUCCESS;
 | |
|   }
 | |
| 
 | |
|   Length = (UINTN)Value[0].Value.u64;
 | |
| 
 | |
|   if (Value[1].Type > EFI_IFR_TYPE_NUM_SIZE_64) {
 | |
|     Result->Type = EFI_IFR_TYPE_UNDEFINED;
 | |
|     return EFI_SUCCESS;
 | |
|   }
 | |
| 
 | |
|   Base = (UINTN)Value[1].Value.u64;
 | |
| 
 | |
|   if ((Value[2].Type != EFI_IFR_TYPE_STRING) && !IsTypeInBuffer (&Value[2])) {
 | |
|     Result->Type = EFI_IFR_TYPE_UNDEFINED;
 | |
|     return EFI_SUCCESS;
 | |
|   }
 | |
| 
 | |
|   if (Value[2].Type == EFI_IFR_TYPE_STRING) {
 | |
|     String = GetToken (Value[2].Value.string, FormSet->HiiHandle);
 | |
|     if (String == NULL) {
 | |
|       return EFI_NOT_FOUND;
 | |
|     }
 | |
| 
 | |
|     if ((Length == 0) || (Base >= StrLen (String))) {
 | |
|       SubString = gEmptyString;
 | |
|     } else {
 | |
|       SubString = String + Base;
 | |
|       if ((Base + Length) < StrLen (String)) {
 | |
|         SubString[Length] = L'\0';
 | |
|       }
 | |
|     }
 | |
| 
 | |
|     Result->Type         = EFI_IFR_TYPE_STRING;
 | |
|     Result->Value.string = NewString (SubString, FormSet->HiiHandle);
 | |
| 
 | |
|     FreePool (String);
 | |
|   } else {
 | |
|     BufferLen = GetLengthForValue (&Value[2]);
 | |
|     Buffer    = GetBufferForValue (&Value[2]);
 | |
| 
 | |
|     Result->Type = EFI_IFR_TYPE_BUFFER;
 | |
|     if ((Length == 0) || (Base >= BufferLen)) {
 | |
|       Result->BufferLen = 0;
 | |
|       Result->Buffer    = NULL;
 | |
|     } else {
 | |
|       Result->BufferLen = (UINT16)((BufferLen - Base) < Length ? (BufferLen - Base) : Length);
 | |
|       Result->Buffer    = AllocateZeroPool (Result->BufferLen);
 | |
|       ASSERT (Result->Buffer != NULL);
 | |
|       CopyMem (Result->Buffer, &Buffer[Base], Result->BufferLen);
 | |
|     }
 | |
| 
 | |
|     if (Value[2].Type == EFI_IFR_TYPE_BUFFER) {
 | |
|       FreePool (Value[2].Buffer);
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   return Status;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Evaluate opcode EFI_IFR_TOKEN.
 | |
| 
 | |
|   @param  FormSet                Formset which contains this opcode.
 | |
|   @param  Result                 Evaluation result for this opcode.
 | |
| 
 | |
|   @retval EFI_SUCCESS            Opcode evaluation success.
 | |
|   @retval Other                  Opcode evaluation failed.
 | |
| 
 | |
| **/
 | |
| EFI_STATUS
 | |
| IfrToken (
 | |
|   IN FORM_BROWSER_FORMSET  *FormSet,
 | |
|   OUT  EFI_HII_VALUE       *Result
 | |
|   )
 | |
| {
 | |
|   EFI_STATUS     Status;
 | |
|   EFI_HII_VALUE  Value[3];
 | |
|   CHAR16         *String[2];
 | |
|   UINTN          Count;
 | |
|   CHAR16         *Delimiter;
 | |
|   CHAR16         *SubString;
 | |
|   CHAR16         *StringPtr;
 | |
|   UINTN          Index;
 | |
| 
 | |
|   ZeroMem (Value, sizeof (Value));
 | |
| 
 | |
|   Status = PopExpression (&Value[0]);
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     return Status;
 | |
|   }
 | |
| 
 | |
|   Status = PopExpression (&Value[1]);
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     return Status;
 | |
|   }
 | |
| 
 | |
|   Status = PopExpression (&Value[2]);
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     return Status;
 | |
|   }
 | |
| 
 | |
|   if (Value[0].Type > EFI_IFR_TYPE_NUM_SIZE_64) {
 | |
|     Result->Type = EFI_IFR_TYPE_UNDEFINED;
 | |
|     return EFI_SUCCESS;
 | |
|   }
 | |
| 
 | |
|   Count = (UINTN)Value[0].Value.u64;
 | |
| 
 | |
|   //
 | |
|   // String[0] - Delimiter
 | |
|   // String[1] - The string to search
 | |
|   //
 | |
|   String[0] = NULL;
 | |
|   String[1] = NULL;
 | |
|   for (Index = 0; Index < 2; Index++) {
 | |
|     if (Value[Index + 1].Type != EFI_IFR_TYPE_STRING) {
 | |
|       Result->Type = EFI_IFR_TYPE_UNDEFINED;
 | |
|       Status       = EFI_SUCCESS;
 | |
|       goto Done;
 | |
|     }
 | |
| 
 | |
|     String[Index] = GetToken (Value[Index + 1].Value.string, FormSet->HiiHandle);
 | |
|     if (String[Index] == NULL) {
 | |
|       Status = EFI_NOT_FOUND;
 | |
|       goto Done;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   Delimiter = String[0];
 | |
|   SubString = String[1];
 | |
|   while (Count > 0) {
 | |
|     SubString = StrStr (SubString, Delimiter);
 | |
|     if (SubString != NULL) {
 | |
|       //
 | |
|       // Skip over the delimiter
 | |
|       //
 | |
|       SubString = SubString + StrLen (Delimiter);
 | |
|     } else {
 | |
|       break;
 | |
|     }
 | |
| 
 | |
|     Count--;
 | |
|   }
 | |
| 
 | |
|   if (SubString == NULL) {
 | |
|     //
 | |
|     // nth delimited sub-string not found, push an empty string
 | |
|     //
 | |
|     SubString = gEmptyString;
 | |
|   } else {
 | |
|     //
 | |
|     // Put a NULL terminator for nth delimited sub-string
 | |
|     //
 | |
|     StringPtr = StrStr (SubString, Delimiter);
 | |
|     if (StringPtr != NULL) {
 | |
|       *StringPtr = L'\0';
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   Result->Type         = EFI_IFR_TYPE_STRING;
 | |
|   Result->Value.string = NewString (SubString, FormSet->HiiHandle);
 | |
| 
 | |
| Done:
 | |
|   if (String[0] != NULL) {
 | |
|     FreePool (String[0]);
 | |
|   }
 | |
| 
 | |
|   if (String[1] != NULL) {
 | |
|     FreePool (String[1]);
 | |
|   }
 | |
| 
 | |
|   return Status;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Evaluate opcode EFI_IFR_SPAN.
 | |
| 
 | |
|   @param  FormSet                Formset which contains this opcode.
 | |
|   @param  Flags                  FIRST_MATCHING or FIRST_NON_MATCHING.
 | |
|   @param  Result                 Evaluation result for this opcode.
 | |
| 
 | |
|   @retval EFI_SUCCESS            Opcode evaluation success.
 | |
|   @retval Other                  Opcode evaluation failed.
 | |
| 
 | |
| **/
 | |
| EFI_STATUS
 | |
| IfrSpan (
 | |
|   IN FORM_BROWSER_FORMSET  *FormSet,
 | |
|   IN UINT8                 Flags,
 | |
|   OUT  EFI_HII_VALUE       *Result
 | |
|   )
 | |
| {
 | |
|   EFI_STATUS     Status;
 | |
|   EFI_HII_VALUE  Value[3];
 | |
|   CHAR16         *String[2];
 | |
|   CHAR16         *Charset;
 | |
|   UINTN          Base;
 | |
|   UINTN          Index;
 | |
|   CHAR16         *StringPtr;
 | |
|   BOOLEAN        Found;
 | |
| 
 | |
|   ZeroMem (Value, sizeof (Value));
 | |
| 
 | |
|   Status = PopExpression (&Value[0]);
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     return Status;
 | |
|   }
 | |
| 
 | |
|   Status = PopExpression (&Value[1]);
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     return Status;
 | |
|   }
 | |
| 
 | |
|   Status = PopExpression (&Value[2]);
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     return Status;
 | |
|   }
 | |
| 
 | |
|   if (Value[0].Type > EFI_IFR_TYPE_NUM_SIZE_64) {
 | |
|     Result->Type = EFI_IFR_TYPE_UNDEFINED;
 | |
|     return EFI_SUCCESS;
 | |
|   }
 | |
| 
 | |
|   Base = (UINTN)Value[0].Value.u64;
 | |
| 
 | |
|   //
 | |
|   // String[0] - Charset
 | |
|   // String[1] - The string to search
 | |
|   //
 | |
|   String[0] = NULL;
 | |
|   String[1] = NULL;
 | |
|   for (Index = 0; Index < 2; Index++) {
 | |
|     if (Value[Index + 1].Type != EFI_IFR_TYPE_STRING) {
 | |
|       Result->Type = EFI_IFR_TYPE_UNDEFINED;
 | |
|       Status       = EFI_SUCCESS;
 | |
|       goto Done;
 | |
|     }
 | |
| 
 | |
|     String[Index] = GetToken (Value[Index + 1].Value.string, FormSet->HiiHandle);
 | |
|     if (String[Index] == NULL) {
 | |
|       Status = EFI_NOT_FOUND;
 | |
|       goto Done;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   if (Base >= StrLen (String[1])) {
 | |
|     Result->Type = EFI_IFR_TYPE_UNDEFINED;
 | |
|     Status       = EFI_SUCCESS;
 | |
|     goto Done;
 | |
|   }
 | |
| 
 | |
|   Found     = FALSE;
 | |
|   StringPtr = String[1] + Base;
 | |
|   Charset   = String[0];
 | |
|   while (*StringPtr != 0 && !Found) {
 | |
|     Index = 0;
 | |
|     while (Charset[Index] != 0) {
 | |
|       if ((*StringPtr >= Charset[Index]) && (*StringPtr <= Charset[Index + 1])) {
 | |
|         if (Flags == EFI_IFR_FLAGS_FIRST_MATCHING) {
 | |
|           Found = TRUE;
 | |
|           break;
 | |
|         }
 | |
|       } else {
 | |
|         if (Flags == EFI_IFR_FLAGS_FIRST_NON_MATCHING) {
 | |
|           Found = TRUE;
 | |
|           break;
 | |
|         }
 | |
|       }
 | |
| 
 | |
|       //
 | |
|       // Skip characters pair representing low-end of a range and high-end of a range
 | |
|       //
 | |
|       Index += 2;
 | |
|     }
 | |
| 
 | |
|     if (!Found) {
 | |
|       StringPtr++;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   Result->Type      = EFI_IFR_TYPE_NUM_SIZE_64;
 | |
|   Result->Value.u64 = StringPtr - String[1];
 | |
| 
 | |
| Done:
 | |
|   if (String[0] != NULL) {
 | |
|     FreePool (String[0]);
 | |
|   }
 | |
| 
 | |
|   if (String[1] != NULL) {
 | |
|     FreePool (String[1]);
 | |
|   }
 | |
| 
 | |
|   return Status;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Zero extend integer/boolean/date/time to UINT64 for comparing.
 | |
| 
 | |
|   @param  Value                  HII Value to be converted.
 | |
| 
 | |
| **/
 | |
| VOID
 | |
| ExtendValueToU64 (
 | |
|   IN  EFI_HII_VALUE  *Value
 | |
|   )
 | |
| {
 | |
|   UINT64  Temp;
 | |
| 
 | |
|   Temp = 0;
 | |
|   switch (Value->Type) {
 | |
|     case EFI_IFR_TYPE_NUM_SIZE_8:
 | |
|       Temp = Value->Value.u8;
 | |
|       break;
 | |
| 
 | |
|     case EFI_IFR_TYPE_NUM_SIZE_16:
 | |
|       Temp = Value->Value.u16;
 | |
|       break;
 | |
| 
 | |
|     case EFI_IFR_TYPE_NUM_SIZE_32:
 | |
|       Temp = Value->Value.u32;
 | |
|       break;
 | |
| 
 | |
|     case EFI_IFR_TYPE_BOOLEAN:
 | |
|       Temp = Value->Value.b;
 | |
|       break;
 | |
| 
 | |
|     case EFI_IFR_TYPE_TIME:
 | |
|       Temp = Value->Value.u32 & 0xffffff;
 | |
|       break;
 | |
| 
 | |
|     case EFI_IFR_TYPE_DATE:
 | |
|       Temp = Value->Value.u32;
 | |
|       break;
 | |
| 
 | |
|     default:
 | |
|       return;
 | |
|   }
 | |
| 
 | |
|   Value->Value.u64 = Temp;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Get UINT64 type value.
 | |
| 
 | |
|   @param  Value                  Input Hii value.
 | |
| 
 | |
|   @retval UINT64                 Return the UINT64 type value.
 | |
| 
 | |
| **/
 | |
| UINT64
 | |
| HiiValueToUINT64 (
 | |
|   IN EFI_HII_VALUE  *Value
 | |
|   )
 | |
| {
 | |
|   UINT64  RetVal;
 | |
| 
 | |
|   RetVal = 0;
 | |
| 
 | |
|   switch (Value->Type) {
 | |
|     case EFI_IFR_TYPE_NUM_SIZE_8:
 | |
|       RetVal = Value->Value.u8;
 | |
|       break;
 | |
| 
 | |
|     case EFI_IFR_TYPE_NUM_SIZE_16:
 | |
|       RetVal = Value->Value.u16;
 | |
|       break;
 | |
| 
 | |
|     case EFI_IFR_TYPE_NUM_SIZE_32:
 | |
|       RetVal = Value->Value.u32;
 | |
|       break;
 | |
| 
 | |
|     case EFI_IFR_TYPE_BOOLEAN:
 | |
|       RetVal = Value->Value.b;
 | |
|       break;
 | |
| 
 | |
|     case EFI_IFR_TYPE_DATE:
 | |
|       RetVal = *(UINT64 *)&Value->Value.date;
 | |
|       break;
 | |
| 
 | |
|     case EFI_IFR_TYPE_TIME:
 | |
|       RetVal = (*(UINT64 *)&Value->Value.time) & 0xffffff;
 | |
|       break;
 | |
| 
 | |
|     default:
 | |
|       RetVal = Value->Value.u64;
 | |
|       break;
 | |
|   }
 | |
| 
 | |
|   return RetVal;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Compare two Hii value.
 | |
| 
 | |
|   @param  Value1                 Expression value to compare on left-hand.
 | |
|   @param  Value2                 Expression value to compare on right-hand.
 | |
|   @param  Result                 Return value after compare.
 | |
|                                  retval 0                      Two operators equal.
 | |
|                                  return Positive value if Value1 is greater than Value2.
 | |
|                                  retval Negative value if Value1 is less than Value2.
 | |
|   @param  HiiHandle              Only required for string compare.
 | |
| 
 | |
|   @retval other                  Could not perform compare on two values.
 | |
|   @retval EFI_SUCCESS            Compare the value success.
 | |
| 
 | |
| **/
 | |
| EFI_STATUS
 | |
| CompareHiiValue (
 | |
|   IN  EFI_HII_VALUE   *Value1,
 | |
|   IN  EFI_HII_VALUE   *Value2,
 | |
|   OUT INTN            *Result,
 | |
|   IN  EFI_HII_HANDLE  HiiHandle OPTIONAL
 | |
|   )
 | |
| {
 | |
|   INT64   Temp64;
 | |
|   CHAR16  *Str1;
 | |
|   CHAR16  *Str2;
 | |
|   UINTN   Len;
 | |
|   UINT8   *Buf1;
 | |
|   UINT16  Buf1Len;
 | |
|   UINT8   *Buf2;
 | |
|   UINT16  Buf2Len;
 | |
| 
 | |
|   if ((Value1->Type == EFI_IFR_TYPE_STRING) && (Value2->Type == EFI_IFR_TYPE_STRING)) {
 | |
|     if ((Value1->Value.string == 0) || (Value2->Value.string == 0)) {
 | |
|       //
 | |
|       // StringId 0 is reserved
 | |
|       //
 | |
|       return EFI_INVALID_PARAMETER;
 | |
|     }
 | |
| 
 | |
|     if (Value1->Value.string == Value2->Value.string) {
 | |
|       *Result = 0;
 | |
|       return EFI_SUCCESS;
 | |
|     }
 | |
| 
 | |
|     Str1 = GetToken (Value1->Value.string, HiiHandle);
 | |
|     if (Str1 == NULL) {
 | |
|       //
 | |
|       // String not found
 | |
|       //
 | |
|       return EFI_NOT_FOUND;
 | |
|     }
 | |
| 
 | |
|     Str2 = GetToken (Value2->Value.string, HiiHandle);
 | |
|     if (Str2 == NULL) {
 | |
|       FreePool (Str1);
 | |
|       return EFI_NOT_FOUND;
 | |
|     }
 | |
| 
 | |
|     *Result = StrCmp (Str1, Str2);
 | |
| 
 | |
|     FreePool (Str1);
 | |
|     FreePool (Str2);
 | |
| 
 | |
|     return EFI_SUCCESS;
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Take types(date, time, ref, buffer) as buffer
 | |
|   //
 | |
|   if (IsTypeInBuffer (Value1) && IsTypeInBuffer (Value2)) {
 | |
|     Buf1    = GetBufferForValue (Value1);
 | |
|     Buf1Len = GetLengthForValue (Value1);
 | |
|     Buf2    = GetBufferForValue (Value2);
 | |
|     Buf2Len = GetLengthForValue (Value2);
 | |
| 
 | |
|     Len     = Buf1Len > Buf2Len ? Buf2Len : Buf1Len;
 | |
|     *Result = CompareMem (Buf1, Buf2, Len);
 | |
|     if ((*Result == 0) && (Buf1Len != Buf2Len)) {
 | |
|       //
 | |
|       // In this case, means base on samll number buffer, the data is same
 | |
|       // So which value has more data, which value is bigger.
 | |
|       //
 | |
|       *Result = Buf1Len > Buf2Len ? 1 : -1;
 | |
|     }
 | |
| 
 | |
|     return EFI_SUCCESS;
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Take types(integer, boolean) as integer
 | |
|   //
 | |
|   if (IsTypeInUINT64 (Value1) && IsTypeInUINT64 (Value2)) {
 | |
|     Temp64 = HiiValueToUINT64 (Value1) - HiiValueToUINT64 (Value2);
 | |
|     if (Temp64 > 0) {
 | |
|       *Result = 1;
 | |
|     } else if (Temp64 < 0) {
 | |
|       *Result = -1;
 | |
|     } else {
 | |
|       *Result = 0;
 | |
|     }
 | |
| 
 | |
|     return EFI_SUCCESS;
 | |
|   }
 | |
| 
 | |
|   return EFI_UNSUPPORTED;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Check if current user has the privilege specified by the permissions GUID.
 | |
| 
 | |
|   @param[in] Guid  A GUID specifying setup access permissions.
 | |
| 
 | |
|   @retval TRUE     Current user has the privilege.
 | |
|   @retval FALSE    Current user does not have the privilege.
 | |
| **/
 | |
| BOOLEAN
 | |
| CheckUserPrivilege (
 | |
|   IN EFI_GUID  *Guid
 | |
|   )
 | |
| {
 | |
|   EFI_STATUS                    Status;
 | |
|   EFI_USER_PROFILE_HANDLE       UserProfileHandle;
 | |
|   EFI_USER_INFO_HANDLE          UserInfoHandle;
 | |
|   EFI_USER_INFO                 *UserInfo;
 | |
|   EFI_GUID                      *UserPermissionsGuid;
 | |
|   UINTN                         UserInfoSize;
 | |
|   UINTN                         AccessControlDataSize;
 | |
|   EFI_USER_INFO_ACCESS_CONTROL  *AccessControl;
 | |
|   UINTN                         RemainSize;
 | |
| 
 | |
|   if (mUserManager == NULL) {
 | |
|     Status = gBS->LocateProtocol (
 | |
|                     &gEfiUserManagerProtocolGuid,
 | |
|                     NULL,
 | |
|                     (VOID **)&mUserManager
 | |
|                     );
 | |
|     if (EFI_ERROR (Status)) {
 | |
|       ///
 | |
|       /// If the system does not support user management, then it is assumed that
 | |
|       /// all users have admin privilege and evaluation of each EFI_IFR_SECURITY
 | |
|       /// op-code is always TRUE.
 | |
|       ///
 | |
|       return TRUE;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   Status = mUserManager->Current (mUserManager, &UserProfileHandle);
 | |
|   ASSERT_EFI_ERROR (Status);
 | |
| 
 | |
|   ///
 | |
|   /// Enumerate all user information of the current user profile
 | |
|   /// to look for any EFI_USER_INFO_ACCESS_SETUP record.
 | |
|   ///
 | |
| 
 | |
|   for (UserInfoHandle = NULL; ;) {
 | |
|     Status = mUserManager->GetNextInfo (mUserManager, UserProfileHandle, &UserInfoHandle);
 | |
|     if (EFI_ERROR (Status)) {
 | |
|       break;
 | |
|     }
 | |
| 
 | |
|     UserInfoSize = 0;
 | |
|     Status       = mUserManager->GetInfo (mUserManager, UserProfileHandle, UserInfoHandle, NULL, &UserInfoSize);
 | |
|     if (Status != EFI_BUFFER_TOO_SMALL) {
 | |
|       continue;
 | |
|     }
 | |
| 
 | |
|     UserInfo = (EFI_USER_INFO *)AllocatePool (UserInfoSize);
 | |
|     if (UserInfo == NULL) {
 | |
|       break;
 | |
|     }
 | |
| 
 | |
|     Status = mUserManager->GetInfo (mUserManager, UserProfileHandle, UserInfoHandle, UserInfo, &UserInfoSize);
 | |
|     if (EFI_ERROR (Status) ||
 | |
|         (UserInfo->InfoType != EFI_USER_INFO_ACCESS_POLICY_RECORD) ||
 | |
|         (UserInfo->InfoSize <= sizeof (EFI_USER_INFO)))
 | |
|     {
 | |
|       FreePool (UserInfo);
 | |
|       continue;
 | |
|     }
 | |
| 
 | |
|     RemainSize    = UserInfo->InfoSize - sizeof (EFI_USER_INFO);
 | |
|     AccessControl = (EFI_USER_INFO_ACCESS_CONTROL *)(UserInfo + 1);
 | |
|     while (RemainSize >= sizeof (EFI_USER_INFO_ACCESS_CONTROL)) {
 | |
|       if ((RemainSize < AccessControl->Size) || (AccessControl->Size < sizeof (EFI_USER_INFO_ACCESS_CONTROL))) {
 | |
|         break;
 | |
|       }
 | |
| 
 | |
|       if (AccessControl->Type == EFI_USER_INFO_ACCESS_SETUP) {
 | |
|         ///
 | |
|         /// Check if current user has the privilege specified by the permissions GUID.
 | |
|         ///
 | |
| 
 | |
|         UserPermissionsGuid   = (EFI_GUID *)(AccessControl + 1);
 | |
|         AccessControlDataSize = AccessControl->Size - sizeof (EFI_USER_INFO_ACCESS_CONTROL);
 | |
|         while (AccessControlDataSize >= sizeof (EFI_GUID)) {
 | |
|           if (CompareGuid (Guid, UserPermissionsGuid)) {
 | |
|             FreePool (UserInfo);
 | |
|             return TRUE;
 | |
|           }
 | |
| 
 | |
|           UserPermissionsGuid++;
 | |
|           AccessControlDataSize -= sizeof (EFI_GUID);
 | |
|         }
 | |
|       }
 | |
| 
 | |
|       RemainSize   -= AccessControl->Size;
 | |
|       AccessControl = (EFI_USER_INFO_ACCESS_CONTROL *)((UINT8 *)AccessControl + AccessControl->Size);
 | |
|     }
 | |
| 
 | |
|     FreePool (UserInfo);
 | |
|   }
 | |
| 
 | |
|   return FALSE;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Get question value from the predefined formset.
 | |
| 
 | |
|   @param  DevicePath             The driver's device path which produece the formset data.
 | |
|   @param  InputHiiHandle         The hii handle associate with the formset data.
 | |
|   @param  FormSetGuid            The formset guid which include the question.
 | |
|   @param  QuestionId             The question id which need to get value from.
 | |
|   @param  Value                  The return data about question's value.
 | |
| 
 | |
|   @retval TRUE                   Get the question value success.
 | |
|   @retval FALSE                  Get the question value failed.
 | |
| **/
 | |
| BOOLEAN
 | |
| GetQuestionValueFromForm (
 | |
|   IN EFI_DEVICE_PATH_PROTOCOL  *DevicePath,
 | |
|   IN EFI_HII_HANDLE            InputHiiHandle,
 | |
|   IN EFI_GUID                  *FormSetGuid,
 | |
|   IN EFI_QUESTION_ID           QuestionId,
 | |
|   OUT EFI_HII_VALUE            *Value
 | |
|   )
 | |
| {
 | |
|   EFI_STATUS              Status;
 | |
|   EFI_HII_HANDLE          HiiHandle;
 | |
|   FORM_BROWSER_STATEMENT  *Question;
 | |
|   FORM_BROWSER_FORMSET    *FormSet;
 | |
|   FORM_BROWSER_FORM       *Form;
 | |
|   BOOLEAN                 GetTheVal;
 | |
|   LIST_ENTRY              *Link;
 | |
| 
 | |
|   //
 | |
|   // The input parameter DevicePath or InputHiiHandle must have one valid input.
 | |
|   //
 | |
|   ASSERT (
 | |
|     (DevicePath != NULL && InputHiiHandle == NULL) ||
 | |
|     (DevicePath == NULL && InputHiiHandle != NULL)
 | |
|     );
 | |
| 
 | |
|   GetTheVal = TRUE;
 | |
|   HiiHandle = NULL;
 | |
|   Question  = NULL;
 | |
|   Form      = NULL;
 | |
| 
 | |
|   //
 | |
|   // Get HiiHandle.
 | |
|   //
 | |
|   if (DevicePath != NULL) {
 | |
|     HiiHandle = DevicePathToHiiHandle (DevicePath, FormSetGuid);
 | |
|     if (HiiHandle == NULL) {
 | |
|       return FALSE;
 | |
|     }
 | |
|   } else {
 | |
|     HiiHandle = InputHiiHandle;
 | |
|   }
 | |
| 
 | |
|   ASSERT (HiiHandle != NULL);
 | |
| 
 | |
|   //
 | |
|   // Get the formset data include this question.
 | |
|   //
 | |
|   FormSet = AllocateZeroPool (sizeof (FORM_BROWSER_FORMSET));
 | |
|   ASSERT (FormSet != NULL);
 | |
|   Status = InitializeFormSet (HiiHandle, FormSetGuid, FormSet);
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     GetTheVal = FALSE;
 | |
|     goto Done;
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Base on the Question Id to get the question info.
 | |
|   //
 | |
|   Question = IdToQuestion (FormSet, NULL, QuestionId);
 | |
|   if (Question == NULL) {
 | |
|     GetTheVal = FALSE;
 | |
|     goto Done;
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Search form in the formset scope
 | |
|   //
 | |
|   Link = GetFirstNode (&FormSet->FormListHead);
 | |
|   while (!IsNull (&FormSet->FormListHead, Link)) {
 | |
|     Form = FORM_BROWSER_FORM_FROM_LINK (Link);
 | |
| 
 | |
|     Question = IdToQuestion2 (Form, QuestionId);
 | |
|     if (Question != NULL) {
 | |
|       break;
 | |
|     }
 | |
| 
 | |
|     Link = GetNextNode (&FormSet->FormListHead, Link);
 | |
|     Form = NULL;
 | |
|   }
 | |
| 
 | |
|   ASSERT (Form != NULL);
 | |
| 
 | |
|   //
 | |
|   // Get the question value.
 | |
|   //
 | |
|   Status = GetQuestionValue (FormSet, Form, Question, GetSetValueWithEditBuffer);
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     GetTheVal = FALSE;
 | |
|     goto Done;
 | |
|   }
 | |
| 
 | |
|   CopyMem (Value, &Question->HiiValue, sizeof (EFI_HII_VALUE));
 | |
| 
 | |
| Done:
 | |
|   //
 | |
|   // Clean the formset structure and restore the global parameter.
 | |
|   //
 | |
|   if (FormSet != NULL) {
 | |
|     DestroyFormSet (FormSet);
 | |
|   }
 | |
| 
 | |
|   return GetTheVal;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Evaluate the result of a HII expression.
 | |
| 
 | |
|   If Expression is NULL, then ASSERT.
 | |
| 
 | |
|   @param  FormSet                FormSet associated with this expression.
 | |
|   @param  Form                   Form associated with this expression.
 | |
|   @param  Expression             Expression to be evaluated.
 | |
| 
 | |
|   @retval EFI_SUCCESS            The expression evaluated successfuly
 | |
|   @retval EFI_NOT_FOUND          The Question which referenced by a QuestionId
 | |
|                                  could not be found.
 | |
|   @retval EFI_OUT_OF_RESOURCES   There is not enough system memory to grow the
 | |
|                                  stack.
 | |
|   @retval EFI_ACCESS_DENIED      The pop operation underflowed the stack
 | |
|   @retval EFI_INVALID_PARAMETER  Syntax error with the Expression
 | |
| 
 | |
| **/
 | |
| EFI_STATUS
 | |
| EvaluateExpression (
 | |
|   IN FORM_BROWSER_FORMSET  *FormSet,
 | |
|   IN FORM_BROWSER_FORM     *Form,
 | |
|   IN OUT FORM_EXPRESSION   *Expression
 | |
|   )
 | |
| {
 | |
|   EFI_STATUS                Status;
 | |
|   LIST_ENTRY                *Link;
 | |
|   EXPRESSION_OPCODE         *OpCode;
 | |
|   FORM_BROWSER_STATEMENT    *Question;
 | |
|   FORM_BROWSER_STATEMENT    *Question2;
 | |
|   UINT16                    Index;
 | |
|   EFI_HII_VALUE             Data1;
 | |
|   EFI_HII_VALUE             Data2;
 | |
|   EFI_HII_VALUE             Data3;
 | |
|   FORM_EXPRESSION           *RuleExpression;
 | |
|   EFI_HII_VALUE             *Value;
 | |
|   INTN                      Result;
 | |
|   CHAR16                    *StrPtr;
 | |
|   CHAR16                    *NameValue;
 | |
|   UINT32                    TempValue;
 | |
|   LIST_ENTRY                *SubExpressionLink;
 | |
|   FORM_EXPRESSION           *SubExpression;
 | |
|   UINTN                     StackOffset;
 | |
|   UINTN                     TempLength;
 | |
|   CHAR16                    TempStr[5];
 | |
|   UINT8                     DigitUint8;
 | |
|   UINT8                     *TempBuffer;
 | |
|   EFI_TIME                  EfiTime;
 | |
|   EFI_HII_VALUE             QuestionVal;
 | |
|   EFI_DEVICE_PATH_PROTOCOL  *DevicePath;
 | |
| 
 | |
|   StrPtr = NULL;
 | |
| 
 | |
|   //
 | |
|   // Save current stack offset.
 | |
|   //
 | |
|   StackOffset = SaveExpressionEvaluationStackOffset ();
 | |
| 
 | |
|   ASSERT (Expression != NULL);
 | |
|   Expression->Result.Type = EFI_IFR_TYPE_OTHER;
 | |
| 
 | |
|   Link = GetFirstNode (&Expression->OpCodeListHead);
 | |
|   while (!IsNull (&Expression->OpCodeListHead, Link)) {
 | |
|     OpCode = EXPRESSION_OPCODE_FROM_LINK (Link);
 | |
| 
 | |
|     Link = GetNextNode (&Expression->OpCodeListHead, Link);
 | |
| 
 | |
|     ZeroMem (&Data1, sizeof (EFI_HII_VALUE));
 | |
|     ZeroMem (&Data2, sizeof (EFI_HII_VALUE));
 | |
|     ZeroMem (&Data3, sizeof (EFI_HII_VALUE));
 | |
| 
 | |
|     Value       = &Data3;
 | |
|     Value->Type = EFI_IFR_TYPE_BOOLEAN;
 | |
|     Status      = EFI_SUCCESS;
 | |
| 
 | |
|     switch (OpCode->Operand) {
 | |
|       //
 | |
|       // Built-in functions
 | |
|       //
 | |
|       case EFI_IFR_EQ_ID_VAL_OP:
 | |
|         Question = IdToQuestion (FormSet, Form, OpCode->QuestionId);
 | |
|         if (Question == NULL) {
 | |
|           Value->Type = EFI_IFR_TYPE_UNDEFINED;
 | |
|           break;
 | |
|         }
 | |
| 
 | |
|         Status = CompareHiiValue (&Question->HiiValue, &OpCode->Value, &Result, NULL);
 | |
|         if (Status == EFI_UNSUPPORTED) {
 | |
|           Status      = EFI_SUCCESS;
 | |
|           Value->Type = EFI_IFR_TYPE_UNDEFINED;
 | |
|           break;
 | |
|         }
 | |
| 
 | |
|         if (EFI_ERROR (Status)) {
 | |
|           goto Done;
 | |
|         }
 | |
| 
 | |
|         Value->Value.b = (BOOLEAN)((Result == 0) ? TRUE : FALSE);
 | |
|         break;
 | |
| 
 | |
|       case EFI_IFR_EQ_ID_ID_OP:
 | |
|         Question = IdToQuestion (FormSet, Form, OpCode->QuestionId);
 | |
|         if (Question == NULL) {
 | |
|           Value->Type = EFI_IFR_TYPE_UNDEFINED;
 | |
|           break;
 | |
|         }
 | |
| 
 | |
|         Question2 = IdToQuestion (FormSet, Form, OpCode->QuestionId2);
 | |
|         if (Question2 == NULL) {
 | |
|           Value->Type = EFI_IFR_TYPE_UNDEFINED;
 | |
|           break;
 | |
|         }
 | |
| 
 | |
|         Status = CompareHiiValue (&Question->HiiValue, &Question2->HiiValue, &Result, FormSet->HiiHandle);
 | |
|         if (Status == EFI_UNSUPPORTED) {
 | |
|           Value->Type = EFI_IFR_TYPE_UNDEFINED;
 | |
|           Status      = EFI_SUCCESS;
 | |
|           break;
 | |
|         }
 | |
| 
 | |
|         if (EFI_ERROR (Status)) {
 | |
|           goto Done;
 | |
|         }
 | |
| 
 | |
|         Value->Value.b = (BOOLEAN)((Result == 0) ? TRUE : FALSE);
 | |
|         break;
 | |
| 
 | |
|       case EFI_IFR_EQ_ID_VAL_LIST_OP:
 | |
|         Question = IdToQuestion (FormSet, Form, OpCode->QuestionId);
 | |
|         if (Question == NULL) {
 | |
|           Value->Type = EFI_IFR_TYPE_UNDEFINED;
 | |
|           break;
 | |
|         }
 | |
| 
 | |
|         Value->Value.b = FALSE;
 | |
|         for (Index = 0; Index < OpCode->ListLength; Index++) {
 | |
|           if (Question->HiiValue.Value.u16 == OpCode->ValueList[Index]) {
 | |
|             Value->Value.b = TRUE;
 | |
|             break;
 | |
|           }
 | |
|         }
 | |
| 
 | |
|         break;
 | |
| 
 | |
|       case EFI_IFR_DUP_OP:
 | |
|         Status = PopExpression (Value);
 | |
|         if (EFI_ERROR (Status)) {
 | |
|           goto Done;
 | |
|         }
 | |
| 
 | |
|         Status = PushExpression (Value);
 | |
|         break;
 | |
| 
 | |
|       case EFI_IFR_QUESTION_REF1_OP:
 | |
|       case EFI_IFR_THIS_OP:
 | |
|         Question = IdToQuestion (FormSet, Form, OpCode->QuestionId);
 | |
|         if (Question == NULL) {
 | |
|           Status = EFI_NOT_FOUND;
 | |
|           goto Done;
 | |
|         }
 | |
| 
 | |
|         Value = &Question->HiiValue;
 | |
|         break;
 | |
| 
 | |
|       case EFI_IFR_SECURITY_OP:
 | |
|         Value->Value.b = CheckUserPrivilege (&OpCode->Guid);
 | |
|         break;
 | |
| 
 | |
|       case EFI_IFR_GET_OP:
 | |
|         //
 | |
|         // Get Value from VarStore buffer, EFI VarStore, Name/Value VarStore.
 | |
|         //
 | |
|         Value->Type     = EFI_IFR_TYPE_UNDEFINED;
 | |
|         Value->Value.u8 = 0;
 | |
|         if (OpCode->VarStorage != NULL) {
 | |
|           switch (OpCode->VarStorage->Type) {
 | |
|             case EFI_HII_VARSTORE_BUFFER:
 | |
|             case EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER:
 | |
|               //
 | |
|               // Get value from Edit Buffer
 | |
|               //
 | |
|               Value->Type = OpCode->ValueType;
 | |
|               CopyMem (&Value->Value, OpCode->VarStorage->EditBuffer + OpCode->VarStoreInfo.VarOffset, OpCode->ValueWidth);
 | |
|               break;
 | |
|             case EFI_HII_VARSTORE_NAME_VALUE:
 | |
|               if (OpCode->ValueType != EFI_IFR_TYPE_STRING) {
 | |
|                 //
 | |
|                 // Get value from string except for STRING value.
 | |
|                 //
 | |
|                 Status = GetValueByName (OpCode->VarStorage, OpCode->ValueName, &StrPtr, GetSetValueWithEditBuffer);
 | |
|                 if (!EFI_ERROR (Status)) {
 | |
|                   ASSERT (StrPtr != NULL);
 | |
|                   TempLength = StrLen (StrPtr);
 | |
|                   if (OpCode->ValueWidth >= ((TempLength + 1) / 2)) {
 | |
|                     Value->Type = OpCode->ValueType;
 | |
|                     TempBuffer  = (UINT8 *)&Value->Value;
 | |
|                     ZeroMem (TempStr, sizeof (TempStr));
 | |
|                     for (Index = 0; Index < TempLength; Index++) {
 | |
|                       TempStr[0] = StrPtr[TempLength - Index - 1];
 | |
|                       DigitUint8 = (UINT8)StrHexToUint64 (TempStr);
 | |
|                       if ((Index & 1) == 0) {
 | |
|                         TempBuffer[Index/2] = DigitUint8;
 | |
|                       } else {
 | |
|                         TempBuffer[Index/2] = (UINT8)((DigitUint8 << 4) + TempBuffer[Index/2]);
 | |
|                       }
 | |
|                     }
 | |
|                   }
 | |
|                 }
 | |
|               }
 | |
| 
 | |
|               break;
 | |
|             case EFI_HII_VARSTORE_EFI_VARIABLE:
 | |
|               //
 | |
|               // Get value from variable.
 | |
|               //
 | |
|               TempLength  = OpCode->ValueWidth;
 | |
|               Value->Type = OpCode->ValueType;
 | |
|               Status      = gRT->GetVariable (
 | |
|                                    OpCode->ValueName,
 | |
|                                    &OpCode->VarStorage->Guid,
 | |
|                                    NULL,
 | |
|                                    &TempLength,
 | |
|                                    &Value->Value
 | |
|                                    );
 | |
|               if (EFI_ERROR (Status)) {
 | |
|                 Value->Type     = EFI_IFR_TYPE_UNDEFINED;
 | |
|                 Value->Value.u8 = 0;
 | |
|               }
 | |
| 
 | |
|               break;
 | |
|             default:
 | |
|               //
 | |
|               // Not recognize storage.
 | |
|               //
 | |
|               Status = EFI_UNSUPPORTED;
 | |
|               goto Done;
 | |
|           }
 | |
|         } else {
 | |
|           //
 | |
|           // For Time/Date Data
 | |
|           //
 | |
|           if ((OpCode->ValueType != EFI_IFR_TYPE_DATE) && (OpCode->ValueType != EFI_IFR_TYPE_TIME)) {
 | |
|             //
 | |
|             // Only support Data/Time data when storage doesn't exist.
 | |
|             //
 | |
|             Status = EFI_UNSUPPORTED;
 | |
|             goto Done;
 | |
|           }
 | |
| 
 | |
|           Status = gRT->GetTime (&EfiTime, NULL);
 | |
|           if (!EFI_ERROR (Status)) {
 | |
|             if (OpCode->ValueType == EFI_IFR_TYPE_DATE) {
 | |
|               switch (OpCode->VarStoreInfo.VarOffset) {
 | |
|                 case 0x00:
 | |
|                   Value->Type      = EFI_IFR_TYPE_NUM_SIZE_16;
 | |
|                   Value->Value.u16 = EfiTime.Year;
 | |
|                   break;
 | |
|                 case 0x02:
 | |
|                   Value->Type     = EFI_IFR_TYPE_NUM_SIZE_8;
 | |
|                   Value->Value.u8 = EfiTime.Month;
 | |
|                   break;
 | |
|                 case 0x03:
 | |
|                   Value->Type     = EFI_IFR_TYPE_NUM_SIZE_8;
 | |
|                   Value->Value.u8 = EfiTime.Day;
 | |
|                   break;
 | |
|                 default:
 | |
|                   //
 | |
|                   // Invalid Date field.
 | |
|                   //
 | |
|                   Status = EFI_INVALID_PARAMETER;
 | |
|                   goto Done;
 | |
|               }
 | |
|             } else {
 | |
|               switch (OpCode->VarStoreInfo.VarOffset) {
 | |
|                 case 0x00:
 | |
|                   Value->Type     = EFI_IFR_TYPE_NUM_SIZE_8;
 | |
|                   Value->Value.u8 = EfiTime.Hour;
 | |
|                   break;
 | |
|                 case 0x01:
 | |
|                   Value->Type     = EFI_IFR_TYPE_NUM_SIZE_8;
 | |
|                   Value->Value.u8 = EfiTime.Minute;
 | |
|                   break;
 | |
|                 case 0x02:
 | |
|                   Value->Type     = EFI_IFR_TYPE_NUM_SIZE_8;
 | |
|                   Value->Value.u8 = EfiTime.Second;
 | |
|                   break;
 | |
|                 default:
 | |
|                   //
 | |
|                   // Invalid Time field.
 | |
|                   //
 | |
|                   Status = EFI_INVALID_PARAMETER;
 | |
|                   goto Done;
 | |
|               }
 | |
|             }
 | |
|           }
 | |
|         }
 | |
| 
 | |
|         break;
 | |
| 
 | |
|       case EFI_IFR_QUESTION_REF3_OP:
 | |
|         //
 | |
|         // EFI_IFR_QUESTION_REF3
 | |
|         // Pop an expression from the expression stack
 | |
|         //
 | |
|         Status = PopExpression (Value);
 | |
|         if (EFI_ERROR (Status)) {
 | |
|           goto Done;
 | |
|         }
 | |
| 
 | |
|         //
 | |
|         // Validate the expression value
 | |
|         //
 | |
|         if ((Value->Type > EFI_IFR_TYPE_NUM_SIZE_64) || (Value->Value.u64 > 0xffff)) {
 | |
|           Value->Type = EFI_IFR_TYPE_UNDEFINED;
 | |
|           break;
 | |
|         }
 | |
| 
 | |
|         if (OpCode->DevicePath != 0) {
 | |
|           Value->Type = EFI_IFR_TYPE_UNDEFINED;
 | |
| 
 | |
|           StrPtr = GetToken (OpCode->DevicePath, FormSet->HiiHandle);
 | |
|           if ((StrPtr != NULL) && (mPathFromText != NULL)) {
 | |
|             DevicePath = mPathFromText->ConvertTextToDevicePath (StrPtr);
 | |
|             if ((DevicePath != NULL) && GetQuestionValueFromForm (DevicePath, NULL, &OpCode->Guid, Value->Value.u16, &QuestionVal)) {
 | |
|               Value = &QuestionVal;
 | |
|             }
 | |
| 
 | |
|             if (DevicePath != NULL) {
 | |
|               FreePool (DevicePath);
 | |
|             }
 | |
|           }
 | |
| 
 | |
|           if (StrPtr != NULL) {
 | |
|             FreePool (StrPtr);
 | |
|           }
 | |
|         } else if (IsZeroGuid (&OpCode->Guid)) {
 | |
|           if (!GetQuestionValueFromForm (NULL, FormSet->HiiHandle, &OpCode->Guid, Value->Value.u16, &QuestionVal)) {
 | |
|             Value->Type = EFI_IFR_TYPE_UNDEFINED;
 | |
|             break;
 | |
|           }
 | |
| 
 | |
|           Value = &QuestionVal;
 | |
|         } else {
 | |
|           Question = IdToQuestion (FormSet, Form, Value->Value.u16);
 | |
|           if (Question == NULL) {
 | |
|             Value->Type = EFI_IFR_TYPE_UNDEFINED;
 | |
|             break;
 | |
|           }
 | |
| 
 | |
|           //
 | |
|           // push the questions' value on to the expression stack
 | |
|           //
 | |
|           Value = &Question->HiiValue;
 | |
|         }
 | |
| 
 | |
|         break;
 | |
| 
 | |
|       case EFI_IFR_RULE_REF_OP:
 | |
|         //
 | |
|         // Find expression for this rule
 | |
|         //
 | |
|         RuleExpression = RuleIdToExpression (Form, OpCode->RuleId);
 | |
|         if (RuleExpression == NULL) {
 | |
|           Value->Type = EFI_IFR_TYPE_UNDEFINED;
 | |
|           break;
 | |
|         }
 | |
| 
 | |
|         //
 | |
|         // Evaluate this rule expression
 | |
|         //
 | |
|         Status = EvaluateExpression (FormSet, Form, RuleExpression);
 | |
|         if (EFI_ERROR (Status) || (RuleExpression->Result.Type == EFI_IFR_TYPE_UNDEFINED)) {
 | |
|           Value->Type = EFI_IFR_TYPE_UNDEFINED;
 | |
|           break;
 | |
|         }
 | |
| 
 | |
|         Value = &RuleExpression->Result;
 | |
|         break;
 | |
| 
 | |
|       case EFI_IFR_STRING_REF1_OP:
 | |
|         Value->Type         = EFI_IFR_TYPE_STRING;
 | |
|         Value->Value.string = OpCode->Value.Value.string;
 | |
|         break;
 | |
| 
 | |
|       //
 | |
|       // Constant
 | |
|       //
 | |
|       case EFI_IFR_TRUE_OP:
 | |
|       case EFI_IFR_FALSE_OP:
 | |
|       case EFI_IFR_ONE_OP:
 | |
|       case EFI_IFR_ONES_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:
 | |
|         Value = &OpCode->Value;
 | |
|         break;
 | |
| 
 | |
|       //
 | |
|       // unary-op
 | |
|       //
 | |
|       case EFI_IFR_LENGTH_OP:
 | |
|         Status = PopExpression (Value);
 | |
|         if (EFI_ERROR (Status)) {
 | |
|           goto Done;
 | |
|         }
 | |
| 
 | |
|         if ((Value->Type != EFI_IFR_TYPE_STRING) && !IsTypeInBuffer (Value)) {
 | |
|           Value->Type = EFI_IFR_TYPE_UNDEFINED;
 | |
|           break;
 | |
|         }
 | |
| 
 | |
|         if (Value->Type == EFI_IFR_TYPE_STRING) {
 | |
|           StrPtr = GetToken (Value->Value.string, FormSet->HiiHandle);
 | |
|           if (StrPtr == NULL) {
 | |
|             Status = EFI_INVALID_PARAMETER;
 | |
|             goto Done;
 | |
|           }
 | |
| 
 | |
|           Value->Type      = EFI_IFR_TYPE_NUM_SIZE_64;
 | |
|           Value->Value.u64 = StrLen (StrPtr);
 | |
|           FreePool (StrPtr);
 | |
|         } else {
 | |
|           Value->Type      = EFI_IFR_TYPE_NUM_SIZE_64;
 | |
|           Value->Value.u64 = GetLengthForValue (Value);
 | |
|           FreePool (Value->Buffer);
 | |
|         }
 | |
| 
 | |
|         break;
 | |
| 
 | |
|       case EFI_IFR_NOT_OP:
 | |
|         Status = PopExpression (Value);
 | |
|         if (EFI_ERROR (Status)) {
 | |
|           goto Done;
 | |
|         }
 | |
| 
 | |
|         if (Value->Type != EFI_IFR_TYPE_BOOLEAN) {
 | |
|           Value->Type = EFI_IFR_TYPE_UNDEFINED;
 | |
|           break;
 | |
|         }
 | |
| 
 | |
|         Value->Value.b = (BOOLEAN)(!Value->Value.b);
 | |
|         break;
 | |
| 
 | |
|       case EFI_IFR_QUESTION_REF2_OP:
 | |
|         //
 | |
|         // Pop an expression from the expression stack
 | |
|         //
 | |
|         Status = PopExpression (Value);
 | |
|         if (EFI_ERROR (Status)) {
 | |
|           goto Done;
 | |
|         }
 | |
| 
 | |
|         //
 | |
|         // Validate the expression value
 | |
|         //
 | |
|         if ((Value->Type > EFI_IFR_TYPE_NUM_SIZE_64) || (Value->Value.u64 > 0xffff)) {
 | |
|           Value->Type = EFI_IFR_TYPE_UNDEFINED;
 | |
|           break;
 | |
|         }
 | |
| 
 | |
|         Question = IdToQuestion (FormSet, Form, Value->Value.u16);
 | |
|         if (Question == NULL) {
 | |
|           Value->Type = EFI_IFR_TYPE_UNDEFINED;
 | |
|           break;
 | |
|         }
 | |
| 
 | |
|         Value = &Question->HiiValue;
 | |
|         break;
 | |
| 
 | |
|       case EFI_IFR_STRING_REF2_OP:
 | |
|         //
 | |
|         // Pop an expression from the expression stack
 | |
|         //
 | |
|         Status = PopExpression (Value);
 | |
|         if (EFI_ERROR (Status)) {
 | |
|           goto Done;
 | |
|         }
 | |
| 
 | |
|         //
 | |
|         // Validate the expression value
 | |
|         //
 | |
|         if ((Value->Type > EFI_IFR_TYPE_NUM_SIZE_64) || (Value->Value.u64 > 0xffff)) {
 | |
|           Value->Type = EFI_IFR_TYPE_UNDEFINED;
 | |
|           break;
 | |
|         }
 | |
| 
 | |
|         Value->Type = EFI_IFR_TYPE_STRING;
 | |
|         StrPtr      = GetToken (Value->Value.u16, FormSet->HiiHandle);
 | |
|         if (StrPtr == NULL) {
 | |
|           //
 | |
|           // If String not exit, push an empty string
 | |
|           //
 | |
|           Value->Value.string = NewString (gEmptyString, FormSet->HiiHandle);
 | |
|         } else {
 | |
|           Index               = (UINT16)Value->Value.u64;
 | |
|           Value->Value.string = Index;
 | |
|           FreePool (StrPtr);
 | |
|         }
 | |
| 
 | |
|         break;
 | |
| 
 | |
|       case EFI_IFR_TO_BOOLEAN_OP:
 | |
|         //
 | |
|         // Pop an expression from the expression stack
 | |
|         //
 | |
|         Status = PopExpression (Value);
 | |
|         if (EFI_ERROR (Status)) {
 | |
|           goto Done;
 | |
|         }
 | |
| 
 | |
|         //
 | |
|         // Convert an expression to a Boolean
 | |
|         //
 | |
|         if (Value->Type <= EFI_IFR_TYPE_DATE) {
 | |
|           //
 | |
|           // When converting from an unsigned integer, zero will be converted to
 | |
|           // FALSE and any other value will be converted to TRUE.
 | |
|           //
 | |
|           Value->Value.b = (BOOLEAN)(HiiValueToUINT64 (Value) != 0);
 | |
| 
 | |
|           Value->Type = EFI_IFR_TYPE_BOOLEAN;
 | |
|         } else if (Value->Type == EFI_IFR_TYPE_STRING) {
 | |
|           //
 | |
|           // When converting from a string, if case-insensitive compare
 | |
|           // with "true" is True, then push True. If a case-insensitive compare
 | |
|           // with "false" is True, then push False. Otherwise, push Undefined.
 | |
|           //
 | |
|           StrPtr = GetToken (Value->Value.string, FormSet->HiiHandle);
 | |
|           if (StrPtr == NULL) {
 | |
|             Status = EFI_INVALID_PARAMETER;
 | |
|             goto Done;
 | |
|           }
 | |
| 
 | |
|           IfrStrToUpper (StrPtr);
 | |
|           if (StrCmp (StrPtr, L"TRUE") == 0) {
 | |
|             Value->Value.b = TRUE;
 | |
|             Value->Type    = EFI_IFR_TYPE_BOOLEAN;
 | |
|           } else if (StrCmp (StrPtr, L"FALSE") == 0) {
 | |
|             Value->Value.b = FALSE;
 | |
|             Value->Type    = EFI_IFR_TYPE_BOOLEAN;
 | |
|           } else {
 | |
|             Value->Type = EFI_IFR_TYPE_UNDEFINED;
 | |
|           }
 | |
| 
 | |
|           FreePool (StrPtr);
 | |
|         } else if (Value->Type == EFI_IFR_TYPE_BUFFER) {
 | |
|           //
 | |
|           // When converting from a buffer, if the buffer is all zeroes,
 | |
|           // then push False. Otherwise push True.
 | |
|           //
 | |
|           for (Index = 0; Index < Value->BufferLen; Index++) {
 | |
|             if (Value->Buffer[Index] != 0) {
 | |
|               break;
 | |
|             }
 | |
|           }
 | |
| 
 | |
|           if (Index >= Value->BufferLen) {
 | |
|             Value->Value.b = FALSE;
 | |
|           } else {
 | |
|             Value->Value.b = TRUE;
 | |
|           }
 | |
| 
 | |
|           Value->Type = EFI_IFR_TYPE_BOOLEAN;
 | |
|           FreePool (Value->Buffer);
 | |
|         }
 | |
| 
 | |
|         break;
 | |
| 
 | |
|       case EFI_IFR_TO_STRING_OP:
 | |
|         Status = IfrToString (FormSet, OpCode->Format, Value);
 | |
|         break;
 | |
| 
 | |
|       case EFI_IFR_TO_UINT_OP:
 | |
|         Status = IfrToUint (FormSet, Value);
 | |
|         break;
 | |
| 
 | |
|       case EFI_IFR_TO_LOWER_OP:
 | |
|       case EFI_IFR_TO_UPPER_OP:
 | |
|         Status = InitializeUnicodeCollationProtocol ();
 | |
|         if (EFI_ERROR (Status)) {
 | |
|           goto Done;
 | |
|         }
 | |
| 
 | |
|         Status = PopExpression (Value);
 | |
|         if (EFI_ERROR (Status)) {
 | |
|           goto Done;
 | |
|         }
 | |
| 
 | |
|         if (Value->Type != EFI_IFR_TYPE_STRING) {
 | |
|           Value->Type = EFI_IFR_TYPE_UNDEFINED;
 | |
|           break;
 | |
|         }
 | |
| 
 | |
|         StrPtr = GetToken (Value->Value.string, FormSet->HiiHandle);
 | |
|         if (StrPtr == NULL) {
 | |
|           Status = EFI_NOT_FOUND;
 | |
|           goto Done;
 | |
|         }
 | |
| 
 | |
|         if (OpCode->Operand == EFI_IFR_TO_LOWER_OP) {
 | |
|           mUnicodeCollation->StrLwr (mUnicodeCollation, StrPtr);
 | |
|         } else {
 | |
|           mUnicodeCollation->StrUpr (mUnicodeCollation, StrPtr);
 | |
|         }
 | |
| 
 | |
|         Value->Value.string = NewString (StrPtr, FormSet->HiiHandle);
 | |
|         FreePool (StrPtr);
 | |
|         break;
 | |
| 
 | |
|       case EFI_IFR_BITWISE_NOT_OP:
 | |
|         //
 | |
|         // Pop an expression from the expression stack
 | |
|         //
 | |
|         Status = PopExpression (Value);
 | |
|         if (EFI_ERROR (Status)) {
 | |
|           goto Done;
 | |
|         }
 | |
| 
 | |
|         if (Value->Type > EFI_IFR_TYPE_DATE) {
 | |
|           Value->Type = EFI_IFR_TYPE_UNDEFINED;
 | |
|           break;
 | |
|         }
 | |
| 
 | |
|         Value->Type      = EFI_IFR_TYPE_NUM_SIZE_64;
 | |
|         Value->Value.u64 = ~HiiValueToUINT64(Value);
 | |
|         break;
 | |
| 
 | |
|       case EFI_IFR_SET_OP:
 | |
|         //
 | |
|         // Pop an expression from the expression stack
 | |
|         //
 | |
|         Status = PopExpression (Value);
 | |
|         if (EFI_ERROR (Status)) {
 | |
|           goto Done;
 | |
|         }
 | |
| 
 | |
|         Data1.Type    = EFI_IFR_TYPE_BOOLEAN;
 | |
|         Data1.Value.b = FALSE;
 | |
|         //
 | |
|         // Set value to var storage buffer
 | |
|         //
 | |
|         if (OpCode->VarStorage != NULL) {
 | |
|           switch (OpCode->VarStorage->Type) {
 | |
|             case EFI_HII_VARSTORE_BUFFER:
 | |
|             case EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER:
 | |
|               CopyMem (OpCode->VarStorage->EditBuffer + OpCode->VarStoreInfo.VarOffset, &Value->Value, OpCode->ValueWidth);
 | |
|               Data1.Value.b = TRUE;
 | |
|               break;
 | |
|             case EFI_HII_VARSTORE_NAME_VALUE:
 | |
|               if (OpCode->ValueType != EFI_IFR_TYPE_STRING) {
 | |
|                 NameValue = AllocateZeroPool ((OpCode->ValueWidth * 2 + 1) * sizeof (CHAR16));
 | |
|                 ASSERT (NameValue != NULL);
 | |
|                 //
 | |
|                 // Convert Buffer to Hex String
 | |
|                 //
 | |
|                 TempBuffer = (UINT8 *)&Value->Value + OpCode->ValueWidth - 1;
 | |
|                 StrPtr     = NameValue;
 | |
|                 for (Index = 0; Index < OpCode->ValueWidth; Index++, TempBuffer--) {
 | |
|                   UnicodeValueToStringS (
 | |
|                     StrPtr,
 | |
|                     (OpCode->ValueWidth * 2 + 1) * sizeof (CHAR16) - ((UINTN)StrPtr - (UINTN)NameValue),
 | |
|                     PREFIX_ZERO | RADIX_HEX,
 | |
|                     *TempBuffer,
 | |
|                     2
 | |
|                     );
 | |
|                   StrPtr += StrnLenS (StrPtr, OpCode->ValueWidth * 2 + 1 - ((UINTN)StrPtr - (UINTN)NameValue) / sizeof (CHAR16));
 | |
|                 }
 | |
| 
 | |
|                 Status = SetValueByName (OpCode->VarStorage, OpCode->ValueName, NameValue, GetSetValueWithEditBuffer, NULL);
 | |
|                 FreePool (NameValue);
 | |
|                 if (!EFI_ERROR (Status)) {
 | |
|                   Data1.Value.b = TRUE;
 | |
|                 }
 | |
|               }
 | |
| 
 | |
|               break;
 | |
|             case EFI_HII_VARSTORE_EFI_VARIABLE:
 | |
|               Status = gRT->SetVariable (
 | |
|                               OpCode->ValueName,
 | |
|                               &OpCode->VarStorage->Guid,
 | |
|                               OpCode->VarStorage->Attributes,
 | |
|                               OpCode->ValueWidth,
 | |
|                               &Value->Value
 | |
|                               );
 | |
|               if (!EFI_ERROR (Status)) {
 | |
|                 Data1.Value.b = TRUE;
 | |
|               }
 | |
| 
 | |
|               break;
 | |
|             default:
 | |
|               //
 | |
|               // Not recognize storage.
 | |
|               //
 | |
|               Status = EFI_UNSUPPORTED;
 | |
|               goto Done;
 | |
|           }
 | |
|         } else {
 | |
|           //
 | |
|           // For Time/Date Data
 | |
|           //
 | |
|           if ((OpCode->ValueType != EFI_IFR_TYPE_DATE) && (OpCode->ValueType != EFI_IFR_TYPE_TIME)) {
 | |
|             //
 | |
|             // Only support Data/Time data when storage doesn't exist.
 | |
|             //
 | |
|             Status = EFI_UNSUPPORTED;
 | |
|             goto Done;
 | |
|           }
 | |
| 
 | |
|           Status = gRT->GetTime (&EfiTime, NULL);
 | |
|           if (!EFI_ERROR (Status)) {
 | |
|             if (OpCode->ValueType == EFI_IFR_TYPE_DATE) {
 | |
|               switch (OpCode->VarStoreInfo.VarOffset) {
 | |
|                 case 0x00:
 | |
|                   EfiTime.Year = Value->Value.u16;
 | |
|                   break;
 | |
|                 case 0x02:
 | |
|                   EfiTime.Month = Value->Value.u8;
 | |
|                   break;
 | |
|                 case 0x03:
 | |
|                   EfiTime.Day = Value->Value.u8;
 | |
|                   break;
 | |
|                 default:
 | |
|                   //
 | |
|                   // Invalid Date field.
 | |
|                   //
 | |
|                   Status = EFI_INVALID_PARAMETER;
 | |
|                   goto Done;
 | |
|               }
 | |
|             } else {
 | |
|               switch (OpCode->VarStoreInfo.VarOffset) {
 | |
|                 case 0x00:
 | |
|                   EfiTime.Hour = Value->Value.u8;
 | |
|                   break;
 | |
|                 case 0x01:
 | |
|                   EfiTime.Minute = Value->Value.u8;
 | |
|                   break;
 | |
|                 case 0x02:
 | |
|                   EfiTime.Second = Value->Value.u8;
 | |
|                   break;
 | |
|                 default:
 | |
|                   //
 | |
|                   // Invalid Time field.
 | |
|                   //
 | |
|                   Status = EFI_INVALID_PARAMETER;
 | |
|                   goto Done;
 | |
|               }
 | |
|             }
 | |
| 
 | |
|             Status = gRT->SetTime (&EfiTime);
 | |
|             if (!EFI_ERROR (Status)) {
 | |
|               Data1.Value.b = TRUE;
 | |
|             }
 | |
|           }
 | |
|         }
 | |
| 
 | |
|         Value = &Data1;
 | |
|         break;
 | |
| 
 | |
|       //
 | |
|       // binary-op
 | |
|       //
 | |
|       case EFI_IFR_ADD_OP:
 | |
|       case EFI_IFR_SUBTRACT_OP:
 | |
|       case EFI_IFR_MULTIPLY_OP:
 | |
|       case EFI_IFR_DIVIDE_OP:
 | |
|       case EFI_IFR_MODULO_OP:
 | |
|       case EFI_IFR_BITWISE_AND_OP:
 | |
|       case EFI_IFR_BITWISE_OR_OP:
 | |
|       case EFI_IFR_SHIFT_LEFT_OP:
 | |
|       case EFI_IFR_SHIFT_RIGHT_OP:
 | |
|         //
 | |
|         // Pop an expression from the expression stack
 | |
|         //
 | |
|         Status = PopExpression (&Data2);
 | |
|         if (EFI_ERROR (Status)) {
 | |
|           goto Done;
 | |
|         }
 | |
| 
 | |
|         //
 | |
|         // Pop another expression from the expression stack
 | |
|         //
 | |
|         Status = PopExpression (&Data1);
 | |
|         if (EFI_ERROR (Status)) {
 | |
|           goto Done;
 | |
|         }
 | |
| 
 | |
|         if (Data2.Type > EFI_IFR_TYPE_DATE) {
 | |
|           Value->Type = EFI_IFR_TYPE_UNDEFINED;
 | |
|           break;
 | |
|         }
 | |
| 
 | |
|         if (Data1.Type > EFI_IFR_TYPE_DATE) {
 | |
|           Value->Type = EFI_IFR_TYPE_UNDEFINED;
 | |
|           break;
 | |
|         }
 | |
| 
 | |
|         Value->Type = EFI_IFR_TYPE_NUM_SIZE_64;
 | |
| 
 | |
|         switch (OpCode->Operand) {
 | |
|           case EFI_IFR_ADD_OP:
 | |
|             Value->Value.u64 = HiiValueToUINT64 (&Data1) + HiiValueToUINT64 (&Data2);
 | |
|             break;
 | |
| 
 | |
|           case EFI_IFR_SUBTRACT_OP:
 | |
|             Value->Value.u64 = HiiValueToUINT64 (&Data1) - HiiValueToUINT64 (&Data2);
 | |
|             break;
 | |
| 
 | |
|           case EFI_IFR_MULTIPLY_OP:
 | |
|             Value->Value.u64 = MultU64x32 (HiiValueToUINT64 (&Data1), (UINT32)HiiValueToUINT64 (&Data2));
 | |
|             break;
 | |
| 
 | |
|           case EFI_IFR_DIVIDE_OP:
 | |
|             Value->Value.u64 = DivU64x32 (HiiValueToUINT64 (&Data1), (UINT32)HiiValueToUINT64 (&Data2));
 | |
|             break;
 | |
| 
 | |
|           case EFI_IFR_MODULO_OP:
 | |
|             DivU64x32Remainder (HiiValueToUINT64 (&Data1), (UINT32)HiiValueToUINT64 (&Data2), &TempValue);
 | |
|             Value->Value.u64 = TempValue;
 | |
|             break;
 | |
| 
 | |
|           case EFI_IFR_BITWISE_AND_OP:
 | |
|             Value->Value.u64 = HiiValueToUINT64 (&Data1) & HiiValueToUINT64 (&Data2);
 | |
|             break;
 | |
| 
 | |
|           case EFI_IFR_BITWISE_OR_OP:
 | |
|             Value->Value.u64 = HiiValueToUINT64 (&Data1) | HiiValueToUINT64 (&Data2);
 | |
|             break;
 | |
| 
 | |
|           case EFI_IFR_SHIFT_LEFT_OP:
 | |
|             Value->Value.u64 = LShiftU64 (HiiValueToUINT64 (&Data1), (UINTN)HiiValueToUINT64 (&Data2));
 | |
|             break;
 | |
| 
 | |
|           case EFI_IFR_SHIFT_RIGHT_OP:
 | |
|             Value->Value.u64 = RShiftU64 (HiiValueToUINT64 (&Data1), (UINTN)HiiValueToUINT64 (&Data2));
 | |
|             break;
 | |
| 
 | |
|           default:
 | |
|             break;
 | |
|         }
 | |
| 
 | |
|         break;
 | |
| 
 | |
|       case EFI_IFR_AND_OP:
 | |
|       case EFI_IFR_OR_OP:
 | |
|         //
 | |
|         // Two Boolean operator
 | |
|         //
 | |
|         Status = PopExpression (&Data2);
 | |
|         if (EFI_ERROR (Status)) {
 | |
|           goto Done;
 | |
|         }
 | |
| 
 | |
|         //
 | |
|         // Pop another expression from the expression stack
 | |
|         //
 | |
|         Status = PopExpression (&Data1);
 | |
|         if (EFI_ERROR (Status)) {
 | |
|           goto Done;
 | |
|         }
 | |
| 
 | |
|         if (Data2.Type != EFI_IFR_TYPE_BOOLEAN) {
 | |
|           Value->Type = EFI_IFR_TYPE_UNDEFINED;
 | |
|           break;
 | |
|         }
 | |
| 
 | |
|         if (Data1.Type != EFI_IFR_TYPE_BOOLEAN) {
 | |
|           Value->Type = EFI_IFR_TYPE_UNDEFINED;
 | |
|           break;
 | |
|         }
 | |
| 
 | |
|         if (OpCode->Operand == EFI_IFR_AND_OP) {
 | |
|           Value->Value.b = (BOOLEAN)(Data1.Value.b && Data2.Value.b);
 | |
|         } else {
 | |
|           Value->Value.b = (BOOLEAN)(Data1.Value.b || Data2.Value.b);
 | |
|         }
 | |
| 
 | |
|         break;
 | |
| 
 | |
|       case EFI_IFR_EQUAL_OP:
 | |
|       case EFI_IFR_NOT_EQUAL_OP:
 | |
|       case EFI_IFR_GREATER_EQUAL_OP:
 | |
|       case EFI_IFR_GREATER_THAN_OP:
 | |
|       case EFI_IFR_LESS_EQUAL_OP:
 | |
|       case EFI_IFR_LESS_THAN_OP:
 | |
|         //
 | |
|         // Compare two integer, string, boolean or date/time
 | |
|         //
 | |
|         Status = PopExpression (&Data2);
 | |
|         if (EFI_ERROR (Status)) {
 | |
|           goto Done;
 | |
|         }
 | |
| 
 | |
|         //
 | |
|         // Pop another expression from the expression stack
 | |
|         //
 | |
|         Status = PopExpression (&Data1);
 | |
|         if (EFI_ERROR (Status)) {
 | |
|           goto Done;
 | |
|         }
 | |
| 
 | |
|         if ((Data2.Type > EFI_IFR_TYPE_BOOLEAN) &&
 | |
|             (Data2.Type != EFI_IFR_TYPE_STRING) &&
 | |
|             !IsTypeInBuffer (&Data2))
 | |
|         {
 | |
|           Value->Type = EFI_IFR_TYPE_UNDEFINED;
 | |
|           break;
 | |
|         }
 | |
| 
 | |
|         if ((Data1.Type > EFI_IFR_TYPE_BOOLEAN) &&
 | |
|             (Data1.Type != EFI_IFR_TYPE_STRING) &&
 | |
|             !IsTypeInBuffer (&Data1))
 | |
|         {
 | |
|           Value->Type = EFI_IFR_TYPE_UNDEFINED;
 | |
|           break;
 | |
|         }
 | |
| 
 | |
|         Status = CompareHiiValue (&Data1, &Data2, &Result, FormSet->HiiHandle);
 | |
|         if (Data1.Type == EFI_IFR_TYPE_BUFFER) {
 | |
|           FreePool (Data1.Buffer);
 | |
|         }
 | |
| 
 | |
|         if (Data2.Type == EFI_IFR_TYPE_BUFFER) {
 | |
|           FreePool (Data2.Buffer);
 | |
|         }
 | |
| 
 | |
|         if (Status == EFI_UNSUPPORTED) {
 | |
|           Value->Type = EFI_IFR_TYPE_UNDEFINED;
 | |
|           Status      = EFI_SUCCESS;
 | |
|           break;
 | |
|         }
 | |
| 
 | |
|         if (EFI_ERROR (Status)) {
 | |
|           goto Done;
 | |
|         }
 | |
| 
 | |
|         switch (OpCode->Operand) {
 | |
|           case EFI_IFR_EQUAL_OP:
 | |
|             Value->Value.b = (BOOLEAN)((Result == 0) ? TRUE : FALSE);
 | |
|             break;
 | |
| 
 | |
|           case EFI_IFR_NOT_EQUAL_OP:
 | |
|             Value->Value.b = (BOOLEAN)((Result != 0) ? TRUE : FALSE);
 | |
|             break;
 | |
| 
 | |
|           case EFI_IFR_GREATER_EQUAL_OP:
 | |
|             Value->Value.b = (BOOLEAN)((Result >= 0) ? TRUE : FALSE);
 | |
|             break;
 | |
| 
 | |
|           case EFI_IFR_GREATER_THAN_OP:
 | |
|             Value->Value.b = (BOOLEAN)((Result > 0) ? TRUE : FALSE);
 | |
|             break;
 | |
| 
 | |
|           case EFI_IFR_LESS_EQUAL_OP:
 | |
|             Value->Value.b = (BOOLEAN)((Result <= 0) ? TRUE : FALSE);
 | |
|             break;
 | |
| 
 | |
|           case EFI_IFR_LESS_THAN_OP:
 | |
|             Value->Value.b = (BOOLEAN)((Result < 0) ? TRUE : FALSE);
 | |
|             break;
 | |
| 
 | |
|           default:
 | |
|             break;
 | |
|         }
 | |
| 
 | |
|         break;
 | |
| 
 | |
|       case EFI_IFR_MATCH_OP:
 | |
|         Status = InitializeUnicodeCollationProtocol ();
 | |
|         if (EFI_ERROR (Status)) {
 | |
|           goto Done;
 | |
|         }
 | |
| 
 | |
|         Status = IfrMatch (FormSet, Value);
 | |
|         break;
 | |
| 
 | |
|       case EFI_IFR_MATCH2_OP:
 | |
|         Status = IfrMatch2 (FormSet, &OpCode->Guid, Value);
 | |
|         break;
 | |
| 
 | |
|       case EFI_IFR_CATENATE_OP:
 | |
|         Status = IfrCatenate (FormSet, Value);
 | |
|         break;
 | |
| 
 | |
|       //
 | |
|       // ternary-op
 | |
|       //
 | |
|       case EFI_IFR_CONDITIONAL_OP:
 | |
|         //
 | |
|         // Pop third expression from the expression stack
 | |
|         //
 | |
|         Status = PopExpression (&Data3);
 | |
|         if (EFI_ERROR (Status)) {
 | |
|           goto Done;
 | |
|         }
 | |
| 
 | |
|         //
 | |
|         // Pop second expression from the expression stack
 | |
|         //
 | |
|         Status = PopExpression (&Data2);
 | |
|         if (EFI_ERROR (Status)) {
 | |
|           goto Done;
 | |
|         }
 | |
| 
 | |
|         //
 | |
|         // Pop first expression from the expression stack
 | |
|         //
 | |
|         Status = PopExpression (&Data1);
 | |
|         if (EFI_ERROR (Status)) {
 | |
|           goto Done;
 | |
|         }
 | |
| 
 | |
|         if (Data1.Type != EFI_IFR_TYPE_BOOLEAN) {
 | |
|           Value->Type = EFI_IFR_TYPE_UNDEFINED;
 | |
|           break;
 | |
|         }
 | |
| 
 | |
|         if (Data1.Value.b) {
 | |
|           Value = &Data3;
 | |
|         } else {
 | |
|           Value = &Data2;
 | |
|         }
 | |
| 
 | |
|         break;
 | |
| 
 | |
|       case EFI_IFR_FIND_OP:
 | |
|         Status = IfrFind (FormSet, OpCode->Format, Value);
 | |
|         break;
 | |
| 
 | |
|       case EFI_IFR_MID_OP:
 | |
|         Status = IfrMid (FormSet, Value);
 | |
|         break;
 | |
| 
 | |
|       case EFI_IFR_TOKEN_OP:
 | |
|         Status = IfrToken (FormSet, Value);
 | |
|         break;
 | |
| 
 | |
|       case EFI_IFR_SPAN_OP:
 | |
|         Status = IfrSpan (FormSet, OpCode->Flags, Value);
 | |
|         break;
 | |
| 
 | |
|       case EFI_IFR_MAP_OP:
 | |
|         //
 | |
|         // Pop the check value
 | |
|         //
 | |
|         Status = PopExpression (&Data1);
 | |
|         if (EFI_ERROR (Status)) {
 | |
|           goto Done;
 | |
|         }
 | |
| 
 | |
|         //
 | |
|         // Check MapExpression list is valid.
 | |
|         //
 | |
|         if (OpCode->MapExpressionList.ForwardLink == NULL) {
 | |
|           Status = EFI_INVALID_PARAMETER;
 | |
|           goto Done;
 | |
|         }
 | |
| 
 | |
|         //
 | |
|         // Go through map expression list.
 | |
|         //
 | |
|         SubExpressionLink = GetFirstNode (&OpCode->MapExpressionList);
 | |
|         while (!IsNull (&OpCode->MapExpressionList, SubExpressionLink)) {
 | |
|           SubExpression = FORM_EXPRESSION_FROM_LINK (SubExpressionLink);
 | |
|           //
 | |
|           // Evaluate the first expression in this pair.
 | |
|           //
 | |
|           Status = EvaluateExpression (FormSet, Form, SubExpression);
 | |
|           if (EFI_ERROR (Status)) {
 | |
|             goto Done;
 | |
|           }
 | |
| 
 | |
|           //
 | |
|           // Compare the expression value with current value
 | |
|           //
 | |
|           if ((CompareHiiValue (&Data1, &SubExpression->Result, &Result, NULL) == EFI_SUCCESS) && (Result == 0)) {
 | |
|             //
 | |
|             // Try get the map value.
 | |
|             //
 | |
|             SubExpressionLink = GetNextNode (&OpCode->MapExpressionList, SubExpressionLink);
 | |
|             if (IsNull (&OpCode->MapExpressionList, SubExpressionLink)) {
 | |
|               Status = EFI_INVALID_PARAMETER;
 | |
|               goto Done;
 | |
|             }
 | |
| 
 | |
|             SubExpression = FORM_EXPRESSION_FROM_LINK (SubExpressionLink);
 | |
|             Status        = EvaluateExpression (FormSet, Form, SubExpression);
 | |
|             if (EFI_ERROR (Status)) {
 | |
|               goto Done;
 | |
|             }
 | |
| 
 | |
|             Value = &SubExpression->Result;
 | |
|             break;
 | |
|           }
 | |
| 
 | |
|           //
 | |
|           // Skip the second expression on this pair.
 | |
|           //
 | |
|           SubExpressionLink = GetNextNode (&OpCode->MapExpressionList, SubExpressionLink);
 | |
|           if (IsNull (&OpCode->MapExpressionList, SubExpressionLink)) {
 | |
|             Status = EFI_INVALID_PARAMETER;
 | |
|             goto Done;
 | |
|           }
 | |
| 
 | |
|           //
 | |
|           // Goto the first expression on next pair.
 | |
|           //
 | |
|           SubExpressionLink = GetNextNode (&OpCode->MapExpressionList, SubExpressionLink);
 | |
|         }
 | |
| 
 | |
|         //
 | |
|         // No map value is found.
 | |
|         //
 | |
|         if (IsNull (&OpCode->MapExpressionList, SubExpressionLink)) {
 | |
|           Value->Type     = EFI_IFR_TYPE_UNDEFINED;
 | |
|           Value->Value.u8 = 0;
 | |
|         }
 | |
| 
 | |
|         break;
 | |
| 
 | |
|       default:
 | |
|         break;
 | |
|     }
 | |
| 
 | |
|     if (EFI_ERROR (Status) || (Value->Type == EFI_IFR_TYPE_UNDEFINED)) {
 | |
|       goto Done;
 | |
|     }
 | |
| 
 | |
|     Status = PushExpression (Value);
 | |
|     if (EFI_ERROR (Status)) {
 | |
|       goto Done;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Pop the final result from expression stack
 | |
|   //
 | |
|   Value  = &Data1;
 | |
|   Status = PopExpression (Value);
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     goto Done;
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // After evaluating an expression, there should be only one value left on the expression stack
 | |
|   //
 | |
|   if (PopExpression (Value) != EFI_ACCESS_DENIED) {
 | |
|     Status = EFI_INVALID_PARAMETER;
 | |
|   }
 | |
| 
 | |
| Done:
 | |
|   RestoreExpressionEvaluationStackOffset (StackOffset);
 | |
|   if (!EFI_ERROR (Status)) {
 | |
|     CopyMem (&Expression->Result, Value, sizeof (EFI_HII_VALUE));
 | |
|   }
 | |
| 
 | |
|   return Status;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Check whether the result is TRUE or FALSE.
 | |
| 
 | |
|   For the EFI_HII_VALUE value type is numeric, return TRUE if the
 | |
|   value is not 0.
 | |
| 
 | |
|   @param  Result             Input the result data.
 | |
| 
 | |
|   @retval TRUE               The result is TRUE.
 | |
|   @retval FALSE              The result is FALSE.
 | |
| 
 | |
| **/
 | |
| BOOLEAN
 | |
| IsTrue (
 | |
|   IN EFI_HII_VALUE  *Result
 | |
|   )
 | |
| {
 | |
|   switch (Result->Type) {
 | |
|     case EFI_IFR_TYPE_BOOLEAN:
 | |
|       return Result->Value.b;
 | |
| 
 | |
|     case EFI_IFR_TYPE_NUM_SIZE_8:
 | |
|       return (BOOLEAN)(Result->Value.u8 != 0);
 | |
| 
 | |
|     case EFI_IFR_TYPE_NUM_SIZE_16:
 | |
|       return (BOOLEAN)(Result->Value.u16 != 0);
 | |
| 
 | |
|     case EFI_IFR_TYPE_NUM_SIZE_32:
 | |
|       return (BOOLEAN)(Result->Value.u32 != 0);
 | |
| 
 | |
|     case EFI_IFR_TYPE_NUM_SIZE_64:
 | |
|       return (BOOLEAN)(Result->Value.u64 != 0);
 | |
| 
 | |
|     default:
 | |
|       return FALSE;
 | |
|   }
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Return the result of the expression list. Check the expression list and
 | |
|   return the highest priority express result.
 | |
|   Priority: DisableIf > SuppressIf > GrayOutIf > FALSE
 | |
| 
 | |
|   @param  ExpList             The input expression list.
 | |
|   @param  Evaluate            Whether need to evaluate the expression first.
 | |
|   @param  FormSet             FormSet associated with this expression.
 | |
|   @param  Form                Form associated with this expression.
 | |
| 
 | |
|   @retval EXPRESS_RESULT      Return the higher priority express result.
 | |
|                               DisableIf > SuppressIf > GrayOutIf > FALSE
 | |
| 
 | |
| **/
 | |
| EXPRESS_RESULT
 | |
| EvaluateExpressionList (
 | |
|   IN FORM_EXPRESSION_LIST  *ExpList,
 | |
|   IN BOOLEAN               Evaluate,
 | |
|   IN FORM_BROWSER_FORMSET  *FormSet  OPTIONAL,
 | |
|   IN FORM_BROWSER_FORM     *Form OPTIONAL
 | |
|   )
 | |
| {
 | |
|   UINTN           Index;
 | |
|   EXPRESS_RESULT  ReturnVal;
 | |
|   EXPRESS_RESULT  CompareOne;
 | |
|   EFI_STATUS      Status;
 | |
| 
 | |
|   if (ExpList == NULL) {
 | |
|     return ExpressFalse;
 | |
|   }
 | |
| 
 | |
|   ASSERT (ExpList->Signature == FORM_EXPRESSION_LIST_SIGNATURE);
 | |
|   Index = 0;
 | |
| 
 | |
|   //
 | |
|   // Check whether need to evaluate the expression first.
 | |
|   //
 | |
|   if (Evaluate) {
 | |
|     while (ExpList->Count > Index) {
 | |
|       Status = EvaluateExpression (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 (IsTrue (&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;
 | |
| }
 |