Home | History | Annotate | Download | only in SetupBrowserDxe
      1 /** @file
      2 Utility functions for expression evaluation.
      3 
      4 Copyright (c) 2007 - 2016, Intel Corporation. All rights reserved.<BR>
      5 This program and the accompanying materials
      6 are licensed and made available under the terms and conditions of the BSD License
      7 which accompanies this distribution.  The full text of the license may be found at
      8 http://opensource.org/licenses/bsd-license.php
      9 
     10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
     11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
     12 
     13 **/
     14 
     15 #include "Setup.h"
     16 
     17 //
     18 // Global stack used to evaluate boolean expresions
     19 //
     20 EFI_HII_VALUE *mOpCodeScopeStack = NULL;
     21 EFI_HII_VALUE *mOpCodeScopeStackEnd = NULL;
     22 EFI_HII_VALUE *mOpCodeScopeStackPointer = NULL;
     23 
     24 EFI_HII_VALUE *mExpressionEvaluationStack = NULL;
     25 EFI_HII_VALUE *mExpressionEvaluationStackEnd = NULL;
     26 EFI_HII_VALUE *mExpressionEvaluationStackPointer = NULL;
     27 UINTN         mExpressionEvaluationStackOffset = 0;
     28 
     29 EFI_HII_VALUE *mCurrentExpressionStack = NULL;
     30 EFI_HII_VALUE *mCurrentExpressionEnd = NULL;
     31 EFI_HII_VALUE *mCurrentExpressionPointer = NULL;
     32 
     33 EFI_HII_VALUE *mMapExpressionListStack = NULL;
     34 EFI_HII_VALUE *mMapExpressionListEnd = NULL;
     35 EFI_HII_VALUE *mMapExpressionListPointer = NULL;
     36 
     37 FORM_EXPRESSION   **mFormExpressionStack = NULL;
     38 FORM_EXPRESSION   **mFormExpressionEnd = NULL;
     39 FORM_EXPRESSION   **mFormExpressionPointer = NULL;
     40 
     41 FORM_EXPRESSION   **mStatementExpressionStack = NULL;
     42 FORM_EXPRESSION   **mStatementExpressionEnd = NULL;
     43 FORM_EXPRESSION   **mStatementExpressionPointer = NULL;
     44 
     45 FORM_EXPRESSION   **mOptionExpressionStack = NULL;
     46 FORM_EXPRESSION   **mOptionExpressionEnd = NULL;
     47 FORM_EXPRESSION   **mOptionExpressionPointer = NULL;
     48 
     49 
     50 //
     51 // Unicode collation protocol interface
     52 //
     53 EFI_UNICODE_COLLATION_PROTOCOL *mUnicodeCollation = NULL;
     54 EFI_USER_MANAGER_PROTOCOL      *mUserManager = NULL;
     55 
     56 /**
     57   Grow size of the stack.
     58 
     59   This is an internal function.
     60 
     61   @param  Stack                  On input: old stack; On output: new stack
     62   @param  StackPtr               On input: old stack pointer; On output: new stack
     63                                  pointer
     64   @param  StackEnd               On input: old stack end; On output: new stack end
     65 
     66   @retval EFI_SUCCESS            Grow stack success.
     67   @retval EFI_OUT_OF_RESOURCES   No enough memory for stack space.
     68 
     69 **/
     70 EFI_STATUS
     71 GrowStack (
     72   IN OUT EFI_HII_VALUE  **Stack,
     73   IN OUT EFI_HII_VALUE  **StackPtr,
     74   IN OUT EFI_HII_VALUE  **StackEnd
     75   )
     76 {
     77   UINTN           Size;
     78   EFI_HII_VALUE  *NewStack;
     79 
     80   Size = EXPRESSION_STACK_SIZE_INCREMENT;
     81   if (*StackPtr != NULL) {
     82     Size = Size + (*StackEnd - *Stack);
     83   }
     84 
     85   NewStack = AllocatePool (Size * sizeof (EFI_HII_VALUE));
     86   if (NewStack == NULL) {
     87     return EFI_OUT_OF_RESOURCES;
     88   }
     89 
     90   if (*StackPtr != NULL) {
     91     //
     92     // Copy from Old Stack to the New Stack
     93     //
     94     CopyMem (
     95       NewStack,
     96       *Stack,
     97       (*StackEnd - *Stack) * sizeof (EFI_HII_VALUE)
     98       );
     99 
    100     //
    101     // Free The Old Stack
    102     //
    103     FreePool (*Stack);
    104   }
    105 
    106   //
    107   // Make the Stack pointer point to the old data in the new stack
    108   //
    109   *StackPtr = NewStack + (*StackPtr - *Stack);
    110   *Stack    = NewStack;
    111   *StackEnd = NewStack + Size;
    112 
    113   return EFI_SUCCESS;
    114 }
    115 
    116 
    117 /**
    118   Push an element onto the Boolean Stack.
    119 
    120   @param  Stack                  On input: old stack; On output: new stack
    121   @param  StackPtr               On input: old stack pointer; On output: new stack
    122                                  pointer
    123   @param  StackEnd               On input: old stack end; On output: new stack end
    124   @param  Data                   Data to push.
    125 
    126   @retval EFI_SUCCESS            Push stack success.
    127 
    128 **/
    129 EFI_STATUS
    130 PushStack (
    131   IN OUT EFI_HII_VALUE       **Stack,
    132   IN OUT EFI_HII_VALUE       **StackPtr,
    133   IN OUT EFI_HII_VALUE       **StackEnd,
    134   IN EFI_HII_VALUE           *Data
    135   )
    136 {
    137   EFI_STATUS  Status;
    138 
    139   //
    140   // Check for a stack overflow condition
    141   //
    142   if (*StackPtr >= *StackEnd) {
    143     //
    144     // Grow the stack
    145     //
    146     Status = GrowStack (Stack, StackPtr, StackEnd);
    147     if (EFI_ERROR (Status)) {
    148       return Status;
    149     }
    150   }
    151 
    152   //
    153   // Push the item onto the stack
    154   //
    155   CopyMem (*StackPtr, Data, sizeof (EFI_HII_VALUE));
    156   if (Data->Type == EFI_IFR_TYPE_BUFFER) {
    157     (*StackPtr)->Buffer = AllocateCopyPool(Data->BufferLen, Data->Buffer);
    158     ASSERT ((*StackPtr)->Buffer != NULL);
    159   }
    160 
    161   *StackPtr = *StackPtr + 1;
    162 
    163   return EFI_SUCCESS;
    164 }
    165 
    166 
    167 /**
    168   Pop an element from the stack.
    169 
    170   @param  Stack                  On input: old stack
    171   @param  StackPtr               On input: old stack pointer; On output: new stack pointer
    172   @param  Data                   Data to pop.
    173 
    174   @retval EFI_SUCCESS            The value was popped onto the stack.
    175   @retval EFI_ACCESS_DENIED      The pop operation underflowed the stack
    176 
    177 **/
    178 EFI_STATUS
    179 PopStack (
    180   IN  EFI_HII_VALUE          *Stack,
    181   IN OUT EFI_HII_VALUE       **StackPtr,
    182   OUT EFI_HII_VALUE          *Data
    183   )
    184 {
    185   //
    186   // Check for a stack underflow condition
    187   //
    188   if (*StackPtr == Stack) {
    189     return EFI_ACCESS_DENIED;
    190   }
    191 
    192   //
    193   // Pop the item off the stack
    194   //
    195   *StackPtr = *StackPtr - 1;
    196   CopyMem (Data, *StackPtr, sizeof (EFI_HII_VALUE));
    197   return EFI_SUCCESS;
    198 }
    199 
    200 
    201 /**
    202   Reset stack pointer to begin of the stack.
    203 
    204 **/
    205 VOID
    206 ResetCurrentExpressionStack (
    207   VOID
    208   )
    209 {
    210   mCurrentExpressionPointer   = mCurrentExpressionStack;
    211   mFormExpressionPointer      = mFormExpressionStack;
    212   mStatementExpressionPointer = mStatementExpressionStack;
    213   mOptionExpressionPointer    = mOptionExpressionStack;
    214 }
    215 
    216 
    217 /**
    218   Push current expression onto the Stack
    219 
    220   @param  Pointer                Pointer to current expression.
    221 
    222   @retval EFI_SUCCESS            The value was pushed onto the stack.
    223   @retval EFI_OUT_OF_RESOURCES   There is not enough system memory to grow the stack.
    224 
    225 **/
    226 EFI_STATUS
    227 PushCurrentExpression (
    228   IN VOID  *Pointer
    229   )
    230 {
    231   EFI_HII_VALUE  Data;
    232 
    233   Data.Type = EFI_IFR_TYPE_NUM_SIZE_64;
    234   Data.Value.u64 = (UINT64) (UINTN) Pointer;
    235 
    236   return PushStack (
    237     &mCurrentExpressionStack,
    238     &mCurrentExpressionPointer,
    239     &mCurrentExpressionEnd,
    240     &Data
    241     );
    242 }
    243 
    244 
    245 /**
    246   Pop current expression from the Stack
    247 
    248   @param  Pointer                Pointer to current expression to be pop.
    249 
    250   @retval EFI_SUCCESS            The value was pushed onto the stack.
    251   @retval EFI_OUT_OF_RESOURCES   There is not enough system memory to grow the stack.
    252 
    253 **/
    254 EFI_STATUS
    255 PopCurrentExpression (
    256   OUT VOID    **Pointer
    257   )
    258 {
    259   EFI_STATUS     Status;
    260   EFI_HII_VALUE  Data;
    261 
    262   Status = PopStack (
    263     mCurrentExpressionStack,
    264     &mCurrentExpressionPointer,
    265     &Data
    266     );
    267 
    268   *Pointer = (VOID *) (UINTN) Data.Value.u64;
    269 
    270   return Status;
    271 }
    272 
    273 /**
    274   Reset stack pointer to begin of the stack.
    275 
    276 **/
    277 VOID
    278 ResetMapExpressionListStack (
    279   VOID
    280   )
    281 {
    282   mMapExpressionListPointer = mMapExpressionListStack;
    283 }
    284 
    285 
    286 /**
    287   Grow size of the stack.
    288 
    289   This is an internal function.
    290 
    291   @param  Stack                  On input: old stack; On output: new stack
    292   @param  StackPtr               On input: old stack pointer; On output: new stack
    293                                  pointer
    294   @param  StackEnd               On input: old stack end; On output: new stack end
    295   @param  MemberSize             The stack member size.
    296 
    297   @retval EFI_SUCCESS            Grow stack success.
    298   @retval EFI_OUT_OF_RESOURCES   No enough memory for stack space.
    299 
    300 **/
    301 EFI_STATUS
    302 GrowConditionalStack (
    303   IN OUT FORM_EXPRESSION   ***Stack,
    304   IN OUT FORM_EXPRESSION   ***StackPtr,
    305   IN OUT FORM_EXPRESSION   ***StackEnd,
    306   IN     UINTN             MemberSize
    307   )
    308 {
    309   UINTN             Size;
    310   FORM_EXPRESSION   **NewStack;
    311 
    312   Size = EXPRESSION_STACK_SIZE_INCREMENT;
    313   if (*StackPtr != NULL) {
    314     Size = Size + (*StackEnd - *Stack);
    315   }
    316 
    317   NewStack = AllocatePool (Size * MemberSize);
    318   if (NewStack == NULL) {
    319     return EFI_OUT_OF_RESOURCES;
    320   }
    321 
    322   if (*StackPtr != NULL) {
    323     //
    324     // Copy from Old Stack to the New Stack
    325     //
    326     CopyMem (
    327       NewStack,
    328       *Stack,
    329       (*StackEnd - *Stack) * MemberSize
    330       );
    331 
    332     //
    333     // Free The Old Stack
    334     //
    335     FreePool (*Stack);
    336   }
    337 
    338   //
    339   // Make the Stack pointer point to the old data in the new stack
    340   //
    341   *StackPtr = NewStack + (*StackPtr - *Stack);
    342   *Stack    = NewStack;
    343   *StackEnd = NewStack + Size;
    344 
    345   return EFI_SUCCESS;
    346 }
    347 
    348 /**
    349   Push an element onto the Stack.
    350 
    351   @param  Stack                  On input: old stack; On output: new stack
    352   @param  StackPtr               On input: old stack pointer; On output: new stack
    353                                  pointer
    354   @param  StackEnd               On input: old stack end; On output: new stack end
    355   @param  Data                   Data to push.
    356 
    357   @retval EFI_SUCCESS            Push stack success.
    358 
    359 **/
    360 EFI_STATUS
    361 PushConditionalStack (
    362   IN OUT FORM_EXPRESSION   ***Stack,
    363   IN OUT FORM_EXPRESSION   ***StackPtr,
    364   IN OUT FORM_EXPRESSION   ***StackEnd,
    365   IN     FORM_EXPRESSION   **Data
    366   )
    367 {
    368   EFI_STATUS  Status;
    369 
    370   //
    371   // Check for a stack overflow condition
    372   //
    373   if (*StackPtr >= *StackEnd) {
    374     //
    375     // Grow the stack
    376     //
    377     Status = GrowConditionalStack (Stack, StackPtr, StackEnd, sizeof (FORM_EXPRESSION *));
    378     if (EFI_ERROR (Status)) {
    379       return Status;
    380     }
    381   }
    382 
    383   //
    384   // Push the item onto the stack
    385   //
    386   CopyMem (*StackPtr, Data, sizeof (FORM_EXPRESSION *));
    387   *StackPtr = *StackPtr + 1;
    388 
    389   return EFI_SUCCESS;
    390 
    391 }
    392 
    393 /**
    394   Pop an element from the stack.
    395 
    396   @param  Stack                  On input: old stack
    397   @param  StackPtr               On input: old stack pointer; On output: new stack pointer
    398   @param  Data                   Data to pop.
    399 
    400   @retval EFI_SUCCESS            The value was popped onto the stack.
    401   @retval EFI_ACCESS_DENIED      The pop operation underflowed the stack
    402 
    403 **/
    404 EFI_STATUS
    405 PopConditionalStack (
    406   IN     FORM_EXPRESSION   **Stack,
    407   IN OUT FORM_EXPRESSION   ***StackPtr,
    408   OUT    FORM_EXPRESSION   **Data
    409   )
    410 {
    411   //
    412   // Check for a stack underflow condition
    413   //
    414   if (*StackPtr == Stack) {
    415     return EFI_ACCESS_DENIED;
    416   }
    417 
    418   //
    419   // Pop the item off the stack
    420   //
    421   *StackPtr = *StackPtr - 1;
    422   CopyMem (Data, *StackPtr, sizeof (FORM_EXPRESSION  *));
    423   return EFI_SUCCESS;
    424 
    425 }
    426 
    427 /**
    428   Get the expression list count.
    429 
    430   @param  Level                  Which type this expression belong to. Form,
    431                                  statement or option?
    432 
    433   @retval >=0                    The expression count
    434   @retval -1                     Input parameter error.
    435 
    436 **/
    437 INTN
    438 GetConditionalExpressionCount (
    439   IN EXPRESS_LEVEL       Level
    440   )
    441 {
    442   switch (Level) {
    443     case ExpressForm:
    444       return mFormExpressionPointer - mFormExpressionStack;
    445     case ExpressStatement:
    446       return mStatementExpressionPointer - mStatementExpressionStack;
    447     case ExpressOption:
    448       return mOptionExpressionPointer - mOptionExpressionStack;
    449     default:
    450       ASSERT (FALSE);
    451       return -1;
    452   }
    453 }
    454 
    455 /**
    456   Get the expression Buffer pointer.
    457 
    458   @param  Level                  Which type this expression belong to. Form,
    459                                  statement or option?
    460 
    461   @retval  The start pointer of the expression buffer or NULL.
    462 
    463 **/
    464 FORM_EXPRESSION **
    465 GetConditionalExpressionList (
    466   IN EXPRESS_LEVEL       Level
    467   )
    468 {
    469   switch (Level) {
    470     case ExpressForm:
    471       return mFormExpressionStack;
    472     case ExpressStatement:
    473       return mStatementExpressionStack;
    474     case ExpressOption:
    475       return mOptionExpressionStack;
    476     default:
    477       ASSERT (FALSE);
    478       return NULL;
    479   }
    480 }
    481 
    482 
    483 /**
    484   Push the expression options onto the Stack.
    485 
    486   @param  Pointer                Pointer to the current expression.
    487   @param  Level                  Which type this expression belong to. Form,
    488                                  statement or option?
    489 
    490   @retval EFI_SUCCESS            The value was pushed onto the stack.
    491   @retval EFI_OUT_OF_RESOURCES   There is not enough system memory to grow the stack.
    492 
    493 **/
    494 EFI_STATUS
    495 PushConditionalExpression (
    496   IN FORM_EXPRESSION   *Pointer,
    497   IN EXPRESS_LEVEL     Level
    498   )
    499 {
    500   switch (Level) {
    501     case ExpressForm:
    502       return PushConditionalStack (
    503         &mFormExpressionStack,
    504         &mFormExpressionPointer,
    505         &mFormExpressionEnd,
    506         &Pointer
    507         );
    508     case ExpressStatement:
    509       return PushConditionalStack (
    510         &mStatementExpressionStack,
    511         &mStatementExpressionPointer,
    512         &mStatementExpressionEnd,
    513         &Pointer
    514         );
    515     case ExpressOption:
    516       return PushConditionalStack (
    517         &mOptionExpressionStack,
    518         &mOptionExpressionPointer,
    519         &mOptionExpressionEnd,
    520         &Pointer
    521         );
    522     default:
    523       ASSERT (FALSE);
    524       return EFI_INVALID_PARAMETER;
    525   }
    526 }
    527 
    528 /**
    529   Pop the expression options from the Stack
    530 
    531   @param  Level                  Which type this expression belong to. Form,
    532                                  statement or option?
    533 
    534   @retval EFI_SUCCESS            The value was pushed onto the stack.
    535   @retval EFI_OUT_OF_RESOURCES   There is not enough system memory to grow the stack.
    536 
    537 **/
    538 EFI_STATUS
    539 PopConditionalExpression (
    540   IN  EXPRESS_LEVEL      Level
    541   )
    542 {
    543   FORM_EXPRESSION   *Pointer;
    544 
    545   switch (Level) {
    546     case ExpressForm:
    547       return PopConditionalStack (
    548         mFormExpressionStack,
    549         &mFormExpressionPointer,
    550         &Pointer
    551       );
    552 
    553     case ExpressStatement:
    554       return PopConditionalStack (
    555         mStatementExpressionStack,
    556         &mStatementExpressionPointer,
    557         &Pointer
    558       );
    559 
    560     case ExpressOption:
    561       return PopConditionalStack (
    562         mOptionExpressionStack,
    563         &mOptionExpressionPointer,
    564         &Pointer
    565       );
    566 
    567     default:
    568       ASSERT (FALSE);
    569       return EFI_INVALID_PARAMETER;
    570   }
    571 }
    572 
    573 
    574 /**
    575   Push the list of map expression onto the Stack
    576 
    577   @param  Pointer                Pointer to the list of map expression to be pushed.
    578 
    579   @retval EFI_SUCCESS            The value was pushed onto the stack.
    580   @retval EFI_OUT_OF_RESOURCES   There is not enough system memory to grow the stack.
    581 
    582 **/
    583 EFI_STATUS
    584 PushMapExpressionList (
    585   IN VOID  *Pointer
    586   )
    587 {
    588   EFI_HII_VALUE  Data;
    589 
    590   Data.Type = EFI_IFR_TYPE_NUM_SIZE_64;
    591   Data.Value.u64 = (UINT64) (UINTN) Pointer;
    592 
    593   return PushStack (
    594     &mMapExpressionListStack,
    595     &mMapExpressionListPointer,
    596     &mMapExpressionListEnd,
    597     &Data
    598     );
    599 }
    600 
    601 
    602 /**
    603   Pop the list of map expression from the Stack
    604 
    605   @param  Pointer                Pointer to the list of map expression to be pop.
    606 
    607   @retval EFI_SUCCESS            The value was pushed onto the stack.
    608   @retval EFI_OUT_OF_RESOURCES   There is not enough system memory to grow the stack.
    609 
    610 **/
    611 EFI_STATUS
    612 PopMapExpressionList (
    613   OUT VOID    **Pointer
    614   )
    615 {
    616   EFI_STATUS     Status;
    617   EFI_HII_VALUE  Data;
    618 
    619   Status = PopStack (
    620     mMapExpressionListStack,
    621     &mMapExpressionListPointer,
    622     &Data
    623     );
    624 
    625   *Pointer = (VOID *) (UINTN) Data.Value.u64;
    626 
    627   return Status;
    628 }
    629 
    630 /**
    631   Reset stack pointer to begin of the stack.
    632 
    633 **/
    634 VOID
    635 ResetScopeStack (
    636   VOID
    637   )
    638 {
    639   mOpCodeScopeStackPointer = mOpCodeScopeStack;
    640 }
    641 
    642 
    643 /**
    644   Push an Operand onto the Stack
    645 
    646   @param  Operand                Operand to push.
    647 
    648   @retval EFI_SUCCESS            The value was pushed onto the stack.
    649   @retval EFI_OUT_OF_RESOURCES   There is not enough system memory to grow the
    650                                  stack.
    651 
    652 **/
    653 EFI_STATUS
    654 PushScope (
    655   IN UINT8   Operand
    656   )
    657 {
    658   EFI_HII_VALUE  Data;
    659 
    660   Data.Type = EFI_IFR_TYPE_NUM_SIZE_8;
    661   Data.Value.u8 = Operand;
    662 
    663   return PushStack (
    664            &mOpCodeScopeStack,
    665            &mOpCodeScopeStackPointer,
    666            &mOpCodeScopeStackEnd,
    667            &Data
    668            );
    669 }
    670 
    671 
    672 /**
    673   Pop an Operand from the Stack
    674 
    675   @param  Operand                Operand to pop.
    676 
    677   @retval EFI_SUCCESS            The value was pushed onto the stack.
    678   @retval EFI_OUT_OF_RESOURCES   There is not enough system memory to grow the
    679                                  stack.
    680 
    681 **/
    682 EFI_STATUS
    683 PopScope (
    684   OUT UINT8     *Operand
    685   )
    686 {
    687   EFI_STATUS     Status;
    688   EFI_HII_VALUE  Data;
    689 
    690   Status = PopStack (
    691              mOpCodeScopeStack,
    692              &mOpCodeScopeStackPointer,
    693              &Data
    694              );
    695 
    696   *Operand = Data.Value.u8;
    697 
    698   return Status;
    699 }
    700 
    701 
    702 /**
    703   Push an Expression value onto the Stack
    704 
    705   @param  Value                  Expression value to push.
    706 
    707   @retval EFI_SUCCESS            The value was pushed onto the stack.
    708   @retval EFI_OUT_OF_RESOURCES   There is not enough system memory to grow the
    709                                  stack.
    710 
    711 **/
    712 EFI_STATUS
    713 PushExpression (
    714   IN EFI_HII_VALUE  *Value
    715   )
    716 {
    717   return PushStack (
    718            &mExpressionEvaluationStack,
    719            &mExpressionEvaluationStackPointer,
    720            &mExpressionEvaluationStackEnd,
    721            Value
    722            );
    723 }
    724 
    725 
    726 /**
    727   Pop an Expression value from the stack.
    728 
    729   @param  Value                  Expression value to pop.
    730 
    731   @retval EFI_SUCCESS            The value was popped onto the stack.
    732   @retval EFI_ACCESS_DENIED      The pop operation underflowed the stack
    733 
    734 **/
    735 EFI_STATUS
    736 PopExpression (
    737   OUT EFI_HII_VALUE  *Value
    738   )
    739 {
    740   return PopStack (
    741            mExpressionEvaluationStack + mExpressionEvaluationStackOffset,
    742            &mExpressionEvaluationStackPointer,
    743            Value
    744            );
    745 }
    746 
    747 /**
    748   Get current stack offset from stack start.
    749 
    750   @return Stack offset to stack start.
    751 **/
    752 UINTN
    753 SaveExpressionEvaluationStackOffset (
    754   )
    755 {
    756   UINTN TempStackOffset;
    757   TempStackOffset = mExpressionEvaluationStackOffset;
    758   mExpressionEvaluationStackOffset = mExpressionEvaluationStackPointer - mExpressionEvaluationStack;
    759   return TempStackOffset;
    760 }
    761 
    762 /**
    763   Restore stack offset based on input stack offset
    764 
    765   @param  StackOffset  Offset to stack start.
    766 
    767 **/
    768 VOID
    769 RestoreExpressionEvaluationStackOffset (
    770   UINTN StackOffset
    771   )
    772 {
    773   mExpressionEvaluationStackOffset = StackOffset;
    774 }
    775 
    776 /**
    777   Get Form given its FormId.
    778 
    779   @param  FormSet                The formset which contains this form.
    780   @param  FormId                 Id of this form.
    781 
    782   @retval Pointer                The form.
    783   @retval NULL                   Specified Form is not found in the formset.
    784 
    785 **/
    786 FORM_BROWSER_FORM *
    787 IdToForm (
    788   IN FORM_BROWSER_FORMSET  *FormSet,
    789   IN UINT16                FormId
    790   )
    791 {
    792   LIST_ENTRY         *Link;
    793   FORM_BROWSER_FORM  *Form;
    794 
    795   Link = GetFirstNode (&FormSet->FormListHead);
    796   while (!IsNull (&FormSet->FormListHead, Link)) {
    797     Form = FORM_BROWSER_FORM_FROM_LINK (Link);
    798 
    799     if (Form->FormId == FormId) {
    800       return Form;
    801     }
    802 
    803     Link = GetNextNode (&FormSet->FormListHead, Link);
    804   }
    805 
    806   return NULL;
    807 }
    808 
    809 
    810 /**
    811   Search a Question in Form scope using its QuestionId.
    812 
    813   @param  Form                   The form which contains this Question.
    814   @param  QuestionId             Id of this Question.
    815 
    816   @retval Pointer                The Question.
    817   @retval NULL                   Specified Question not found in the form.
    818 
    819 **/
    820 FORM_BROWSER_STATEMENT *
    821 IdToQuestion2 (
    822   IN FORM_BROWSER_FORM  *Form,
    823   IN UINT16             QuestionId
    824   )
    825 {
    826   LIST_ENTRY              *Link;
    827   FORM_BROWSER_STATEMENT  *Question;
    828 
    829   if (QuestionId == 0 || Form == NULL) {
    830     //
    831     // The value of zero is reserved
    832     //
    833     return NULL;
    834   }
    835 
    836   Link = GetFirstNode (&Form->StatementListHead);
    837   while (!IsNull (&Form->StatementListHead, Link)) {
    838     Question = FORM_BROWSER_STATEMENT_FROM_LINK (Link);
    839 
    840     if (Question->QuestionId == QuestionId) {
    841       return Question;
    842     }
    843 
    844     Link = GetNextNode (&Form->StatementListHead, Link);
    845   }
    846 
    847   return NULL;
    848 }
    849 
    850 
    851 /**
    852   Search a Question in Formset scope using its QuestionId.
    853 
    854   @param  FormSet                The formset which contains this form.
    855   @param  Form                   The form which contains this Question.
    856   @param  QuestionId             Id of this Question.
    857 
    858   @retval Pointer                The Question.
    859   @retval NULL                   Specified Question not found in the form.
    860 
    861 **/
    862 FORM_BROWSER_STATEMENT *
    863 IdToQuestion (
    864   IN FORM_BROWSER_FORMSET  *FormSet,
    865   IN FORM_BROWSER_FORM     *Form,
    866   IN UINT16                QuestionId
    867   )
    868 {
    869   LIST_ENTRY              *Link;
    870   FORM_BROWSER_STATEMENT  *Question;
    871 
    872   //
    873   // Search in the form scope first
    874   //
    875   Question = IdToQuestion2 (Form, QuestionId);
    876   if (Question != NULL) {
    877     return Question;
    878   }
    879 
    880   //
    881   // Search in the formset scope
    882   //
    883   Link = GetFirstNode (&FormSet->FormListHead);
    884   while (!IsNull (&FormSet->FormListHead, Link)) {
    885     Form = FORM_BROWSER_FORM_FROM_LINK (Link);
    886 
    887     Question = IdToQuestion2 (Form, QuestionId);
    888     if (Question != NULL) {
    889       //
    890       // EFI variable storage may be updated by Callback() asynchronous,
    891       // to keep synchronous, always reload the Question Value.
    892       //
    893       if (Question->Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE) {
    894         GetQuestionValue (FormSet, Form, Question, GetSetValueWithHiiDriver);
    895       }
    896 
    897       return Question;
    898     }
    899 
    900     Link = GetNextNode (&FormSet->FormListHead, Link);
    901   }
    902 
    903   return NULL;
    904 }
    905 
    906 
    907 /**
    908   Get Expression given its RuleId.
    909 
    910   @param  Form                   The form which contains this Expression.
    911   @param  RuleId                 Id of this Expression.
    912 
    913   @retval Pointer                The Expression.
    914   @retval NULL                   Specified Expression not found in the form.
    915 
    916 **/
    917 FORM_EXPRESSION *
    918 RuleIdToExpression (
    919   IN FORM_BROWSER_FORM  *Form,
    920   IN UINT8              RuleId
    921   )
    922 {
    923   LIST_ENTRY       *Link;
    924   FORM_EXPRESSION  *Expression;
    925 
    926   Link = GetFirstNode (&Form->ExpressionListHead);
    927   while (!IsNull (&Form->ExpressionListHead, Link)) {
    928     Expression = FORM_EXPRESSION_FROM_LINK (Link);
    929 
    930     if (Expression->Type == EFI_HII_EXPRESSION_RULE && Expression->RuleId == RuleId) {
    931       return Expression;
    932     }
    933 
    934     Link = GetNextNode (&Form->ExpressionListHead, Link);
    935   }
    936 
    937   return NULL;
    938 }
    939 
    940 
    941 /**
    942   Locate the Unicode Collation Protocol interface for later use.
    943 
    944   @retval EFI_SUCCESS            Protocol interface initialize success.
    945   @retval Other                  Protocol interface initialize failed.
    946 
    947 **/
    948 EFI_STATUS
    949 InitializeUnicodeCollationProtocol (
    950   VOID
    951   )
    952 {
    953   EFI_STATUS  Status;
    954 
    955   if (mUnicodeCollation != NULL) {
    956     return EFI_SUCCESS;
    957   }
    958 
    959   //
    960   // BUGBUG: Proper impelmentation is to locate all Unicode Collation Protocol
    961   // instances first and then select one which support English language.
    962   // Current implementation just pick the first instance.
    963   //
    964   Status = gBS->LocateProtocol (
    965                   &gEfiUnicodeCollation2ProtocolGuid,
    966                   NULL,
    967                   (VOID **) &mUnicodeCollation
    968                   );
    969   return Status;
    970 }
    971 
    972 /**
    973   Convert the input Unicode character to upper.
    974 
    975   @param String  Th Unicode character to be converted.
    976 
    977 **/
    978 VOID
    979 IfrStrToUpper (
    980   IN CHAR16                   *String
    981   )
    982 {
    983   while (*String != 0) {
    984     if ((*String >= 'a') && (*String <= 'z')) {
    985       *String = (UINT16) ((*String) & ((UINT16) ~0x20));
    986     }
    987     String++;
    988   }
    989 }
    990 
    991 /**
    992   Check whether this value type can be transfer to EFI_IFR_TYPE_BUFFER type.
    993 
    994   EFI_IFR_TYPE_REF, EFI_IFR_TYPE_DATE and EFI_IFR_TYPE_TIME are converted to
    995   EFI_IFR_TYPE_BUFFER when do the value compare.
    996 
    997   @param  Value                  Expression value to compare on.
    998 
    999   @retval TRUE                   This value type can be transter to EFI_IFR_TYPE_BUFFER type.
   1000   @retval FALSE                  This value type can't be transter to EFI_IFR_TYPE_BUFFER type.
   1001 
   1002 **/
   1003 BOOLEAN
   1004 IsTypeInBuffer (
   1005   IN  EFI_HII_VALUE   *Value
   1006   )
   1007 {
   1008   switch (Value->Type) {
   1009   case EFI_IFR_TYPE_BUFFER:
   1010   case EFI_IFR_TYPE_DATE:
   1011   case EFI_IFR_TYPE_TIME:
   1012   case EFI_IFR_TYPE_REF:
   1013     return TRUE;
   1014 
   1015   default:
   1016     return FALSE;
   1017   }
   1018 }
   1019 
   1020 /**
   1021   Check whether this value type can be transfer to EFI_IFR_TYPE_UINT64
   1022 
   1023   @param  Value                  Expression value to compare on.
   1024 
   1025   @retval TRUE                   This value type can be transter to EFI_IFR_TYPE_BUFFER type.
   1026   @retval FALSE                  This value type can't be transter to EFI_IFR_TYPE_BUFFER type.
   1027 
   1028 **/
   1029 BOOLEAN
   1030 IsTypeInUINT64 (
   1031   IN  EFI_HII_VALUE   *Value
   1032   )
   1033 {
   1034   switch (Value->Type) {
   1035   case EFI_IFR_TYPE_NUM_SIZE_8:
   1036   case EFI_IFR_TYPE_NUM_SIZE_16:
   1037   case EFI_IFR_TYPE_NUM_SIZE_32:
   1038   case EFI_IFR_TYPE_NUM_SIZE_64:
   1039   case EFI_IFR_TYPE_BOOLEAN:
   1040     return TRUE;
   1041 
   1042   default:
   1043     return FALSE;
   1044   }
   1045 }
   1046 
   1047 /**
   1048   Return the buffer length for this value.
   1049 
   1050   EFI_IFR_TYPE_REF, EFI_IFR_TYPE_DATE and EFI_IFR_TYPE_TIME are converted to
   1051   EFI_IFR_TYPE_BUFFER when do the value compare.
   1052 
   1053   @param   Value                  Expression value to compare on.
   1054 
   1055   @retval  BufLen                 Return the buffer length.
   1056 
   1057 **/
   1058 UINT16
   1059 GetLengthForValue (
   1060   IN  EFI_HII_VALUE   *Value
   1061   )
   1062 {
   1063   switch (Value->Type) {
   1064   case EFI_IFR_TYPE_BUFFER:
   1065     return Value->BufferLen;
   1066 
   1067   case EFI_IFR_TYPE_DATE:
   1068     return (UINT16) sizeof (EFI_HII_DATE);
   1069 
   1070   case EFI_IFR_TYPE_TIME:
   1071     return (UINT16) sizeof (EFI_HII_TIME);
   1072 
   1073   case EFI_IFR_TYPE_REF:
   1074     return (UINT16) sizeof (EFI_HII_REF);
   1075 
   1076   default:
   1077     return 0;
   1078   }
   1079 }
   1080 
   1081 /**
   1082   Return the buffer pointer for this value.
   1083 
   1084   EFI_IFR_TYPE_REF, EFI_IFR_TYPE_DATE and EFI_IFR_TYPE_TIME are converted to
   1085   EFI_IFR_TYPE_BUFFER when do the value compare.
   1086 
   1087   @param  Value                  Expression value to compare on.
   1088 
   1089   @retval Buf                    Return the buffer pointer.
   1090 
   1091 **/
   1092 UINT8 *
   1093 GetBufferForValue (
   1094   IN  EFI_HII_VALUE   *Value
   1095   )
   1096 {
   1097   switch (Value->Type) {
   1098   case EFI_IFR_TYPE_BUFFER:
   1099     return Value->Buffer;
   1100 
   1101   case EFI_IFR_TYPE_DATE:
   1102     return (UINT8 *) (&Value->Value.date);
   1103 
   1104   case EFI_IFR_TYPE_TIME:
   1105     return (UINT8 *) (&Value->Value.time);
   1106 
   1107   case EFI_IFR_TYPE_REF:
   1108     return (UINT8 *) (&Value->Value.ref);
   1109 
   1110   default:
   1111     return NULL;
   1112   }
   1113 }
   1114 
   1115 /**
   1116   Evaluate opcode EFI_IFR_TO_STRING.
   1117 
   1118   @param  FormSet                Formset which contains this opcode.
   1119   @param  Format                 String format in EFI_IFR_TO_STRING.
   1120   @param  Result                 Evaluation result for this opcode.
   1121 
   1122   @retval EFI_SUCCESS            Opcode evaluation success.
   1123   @retval Other                  Opcode evaluation failed.
   1124 
   1125 **/
   1126 EFI_STATUS
   1127 IfrToString (
   1128   IN FORM_BROWSER_FORMSET  *FormSet,
   1129   IN UINT8                 Format,
   1130   OUT  EFI_HII_VALUE       *Result
   1131   )
   1132 {
   1133   EFI_STATUS     Status;
   1134   EFI_HII_VALUE  Value;
   1135   CHAR16         *String;
   1136   CHAR16         *PrintFormat;
   1137   CHAR16         Buffer[MAXIMUM_VALUE_CHARACTERS];
   1138   UINT8          *TmpBuf;
   1139   UINT8          *SrcBuf;
   1140   UINTN          SrcLen;
   1141   UINTN          BufferSize;
   1142 
   1143   Status = PopExpression (&Value);
   1144   if (EFI_ERROR (Status)) {
   1145     return Status;
   1146   }
   1147 
   1148   switch (Value.Type) {
   1149   case EFI_IFR_TYPE_NUM_SIZE_8:
   1150   case EFI_IFR_TYPE_NUM_SIZE_16:
   1151   case EFI_IFR_TYPE_NUM_SIZE_32:
   1152   case EFI_IFR_TYPE_NUM_SIZE_64:
   1153     BufferSize = MAXIMUM_VALUE_CHARACTERS * sizeof (CHAR16);
   1154     switch (Format) {
   1155     case EFI_IFR_STRING_UNSIGNED_DEC:
   1156     case EFI_IFR_STRING_SIGNED_DEC:
   1157       PrintFormat = L"%ld";
   1158       break;
   1159 
   1160     case EFI_IFR_STRING_LOWERCASE_HEX:
   1161       PrintFormat = L"%lx";
   1162       break;
   1163 
   1164     case EFI_IFR_STRING_UPPERCASE_HEX:
   1165       PrintFormat = L"%lX";
   1166       break;
   1167 
   1168     default:
   1169       Result->Type = EFI_IFR_TYPE_UNDEFINED;
   1170       return EFI_SUCCESS;
   1171     }
   1172     UnicodeSPrint (Buffer, BufferSize, PrintFormat, Value.Value.u64);
   1173     String = Buffer;
   1174     break;
   1175 
   1176   case EFI_IFR_TYPE_STRING:
   1177     CopyMem (Result, &Value, sizeof (EFI_HII_VALUE));
   1178     return EFI_SUCCESS;
   1179 
   1180   case EFI_IFR_TYPE_BOOLEAN:
   1181     String = (Value.Value.b) ? L"True" : L"False";
   1182     break;
   1183 
   1184   case EFI_IFR_TYPE_BUFFER:
   1185   case EFI_IFR_TYPE_DATE:
   1186   case EFI_IFR_TYPE_TIME:
   1187   case EFI_IFR_TYPE_REF:
   1188     //
   1189     // + 3 is base on the unicode format, the length may be odd number,
   1190     // so need 1 byte to align, also need 2 bytes for L'\0'.
   1191     //
   1192     if (Value.Type == EFI_IFR_TYPE_BUFFER) {
   1193       SrcLen = Value.BufferLen;
   1194       SrcBuf = Value.Buffer;
   1195     } else {
   1196       SrcBuf = GetBufferForValue(&Value);
   1197       SrcLen = GetLengthForValue(&Value);
   1198     }
   1199 
   1200     TmpBuf = AllocateZeroPool (SrcLen + 3);
   1201     ASSERT (TmpBuf != NULL);
   1202     if (Format == EFI_IFR_STRING_ASCII) {
   1203       CopyMem (TmpBuf, SrcBuf, SrcLen);
   1204       PrintFormat = L"%a";
   1205     } else {
   1206       // Format == EFI_IFR_STRING_UNICODE
   1207       CopyMem (TmpBuf, SrcBuf, SrcLen * sizeof (CHAR16));
   1208       PrintFormat = L"%s";
   1209     }
   1210     UnicodeSPrint (Buffer, sizeof (Buffer), PrintFormat, TmpBuf);
   1211     String = Buffer;
   1212     FreePool (TmpBuf);
   1213     if (Value.Type == EFI_IFR_TYPE_BUFFER) {
   1214       FreePool (Value.Buffer);
   1215     }
   1216     break;
   1217 
   1218   default:
   1219     Result->Type = EFI_IFR_TYPE_UNDEFINED;
   1220     return EFI_SUCCESS;
   1221   }
   1222 
   1223   Result->Type = EFI_IFR_TYPE_STRING;
   1224   Result->Value.string = NewString (String, FormSet->HiiHandle);
   1225   return EFI_SUCCESS;
   1226 }
   1227 
   1228 
   1229 /**
   1230   Evaluate opcode EFI_IFR_TO_UINT.
   1231 
   1232   @param  FormSet                Formset which contains this opcode.
   1233   @param  Result                 Evaluation result for this opcode.
   1234 
   1235   @retval EFI_SUCCESS            Opcode evaluation success.
   1236   @retval Other                  Opcode evaluation failed.
   1237 
   1238 **/
   1239 EFI_STATUS
   1240 IfrToUint (
   1241   IN FORM_BROWSER_FORMSET  *FormSet,
   1242   OUT  EFI_HII_VALUE       *Result
   1243   )
   1244 {
   1245   EFI_STATUS     Status;
   1246   EFI_HII_VALUE  Value;
   1247   CHAR16         *String;
   1248   CHAR16         *StringPtr;
   1249 
   1250   Status = PopExpression (&Value);
   1251   if (EFI_ERROR (Status)) {
   1252     return Status;
   1253   }
   1254 
   1255   if (Value.Type >= EFI_IFR_TYPE_OTHER && !IsTypeInBuffer(&Value)) {
   1256     Result->Type = EFI_IFR_TYPE_UNDEFINED;
   1257     return EFI_SUCCESS;
   1258   }
   1259 
   1260   Status = EFI_SUCCESS;
   1261   if (Value.Type == EFI_IFR_TYPE_STRING) {
   1262     String = GetToken (Value.Value.string, FormSet->HiiHandle);
   1263     if (String == NULL) {
   1264       return EFI_NOT_FOUND;
   1265     }
   1266 
   1267     IfrStrToUpper (String);
   1268     StringPtr = StrStr (String, L"0X");
   1269     if (StringPtr != NULL) {
   1270       //
   1271       // Hex string
   1272       //
   1273       Result->Value.u64 = StrHexToUint64 (String);
   1274     } else {
   1275       //
   1276       // decimal string
   1277       //
   1278       Result->Value.u64 = StrDecimalToUint64 (String);
   1279     }
   1280     FreePool (String);
   1281   } else if (IsTypeInBuffer(&Value)) {
   1282     if (GetLengthForValue (&Value) > 8) {
   1283       if (Value.Type == EFI_IFR_TYPE_BUFFER) {
   1284         FreePool (Value.Buffer);
   1285       }
   1286       Result->Type = EFI_IFR_TYPE_UNDEFINED;
   1287       return EFI_SUCCESS;
   1288     }
   1289     Result->Value.u64 = *(UINT64*) GetBufferForValue (&Value);
   1290     if (Value.Type == EFI_IFR_TYPE_BUFFER) {
   1291       FreePool (Value.Buffer);
   1292     }
   1293   } else {
   1294     CopyMem (Result, &Value, sizeof (EFI_HII_VALUE));
   1295   }
   1296 
   1297   Result->Type = EFI_IFR_TYPE_NUM_SIZE_64;
   1298   return Status;
   1299 }
   1300 
   1301 
   1302 /**
   1303   Evaluate opcode EFI_IFR_CATENATE.
   1304 
   1305   @param  FormSet                Formset which contains this opcode.
   1306   @param  Result                 Evaluation result for this opcode.
   1307 
   1308   @retval EFI_SUCCESS            Opcode evaluation success.
   1309   @retval Other                  Opcode evaluation failed.
   1310 
   1311 **/
   1312 EFI_STATUS
   1313 IfrCatenate (
   1314   IN FORM_BROWSER_FORMSET  *FormSet,
   1315   OUT  EFI_HII_VALUE       *Result
   1316   )
   1317 {
   1318   EFI_STATUS     Status;
   1319   EFI_HII_VALUE  Value[2];
   1320   CHAR16         *String[2];
   1321   UINTN          Index;
   1322   CHAR16         *StringPtr;
   1323   UINTN          Size;
   1324   UINT16         Length0;
   1325   UINT16         Length1;
   1326   UINT8          *TmpBuf;
   1327   UINTN          MaxLen;
   1328 
   1329   //
   1330   // String[0] - The second string
   1331   // String[1] - The first string
   1332   //
   1333   String[0] = NULL;
   1334   String[1] = NULL;
   1335   StringPtr = NULL;
   1336   Status = EFI_SUCCESS;
   1337   ZeroMem (Value, sizeof (Value));
   1338 
   1339   Status = PopExpression (&Value[0]);
   1340   if (EFI_ERROR (Status)) {
   1341     goto Done;
   1342   }
   1343 
   1344   Status = PopExpression (&Value[1]);
   1345   if (EFI_ERROR (Status)) {
   1346     goto Done;
   1347   }
   1348 
   1349   for (Index = 0; Index < 2; Index++) {
   1350     if (Value[Index].Type != EFI_IFR_TYPE_STRING && !IsTypeInBuffer(&Value[Index])) {
   1351       Result->Type = EFI_IFR_TYPE_UNDEFINED;
   1352       Status = EFI_SUCCESS;
   1353       goto Done;
   1354     }
   1355 
   1356     if (Value[Index].Type == EFI_IFR_TYPE_STRING) {
   1357       String[Index] = GetToken (Value[Index].Value.string, FormSet->HiiHandle);
   1358       if (String[Index] == NULL) {
   1359         Status = EFI_NOT_FOUND;
   1360         goto Done;
   1361       }
   1362     }
   1363   }
   1364 
   1365   if (Value[0].Type == EFI_IFR_TYPE_STRING) {
   1366     Size = StrSize (String[0]);
   1367     MaxLen = (StrSize (String[1]) + Size) / sizeof (CHAR16);
   1368     StringPtr= AllocatePool (MaxLen * sizeof (CHAR16));
   1369     ASSERT (StringPtr != NULL);
   1370     StrCpyS (StringPtr, MaxLen, String[1]);
   1371     StrCatS (StringPtr, MaxLen, String[0]);
   1372 
   1373     Result->Type = EFI_IFR_TYPE_STRING;
   1374     Result->Value.string = NewString (StringPtr, FormSet->HiiHandle);
   1375   } else {
   1376     Result->Type = EFI_IFR_TYPE_BUFFER;
   1377     Length0 = GetLengthForValue(&Value[0]);
   1378     Length1 = GetLengthForValue(&Value[1]);
   1379     Result->BufferLen = (UINT16) (Length0 + Length1);
   1380 
   1381     Result->Buffer = AllocateZeroPool (Result->BufferLen);
   1382     ASSERT (Result->Buffer != NULL);
   1383 
   1384     TmpBuf = GetBufferForValue(&Value[0]);
   1385     ASSERT (TmpBuf != NULL);
   1386     CopyMem (Result->Buffer, TmpBuf, Length0);
   1387     TmpBuf = GetBufferForValue(&Value[1]);
   1388     ASSERT (TmpBuf != NULL);
   1389     CopyMem (&Result->Buffer[Length0], TmpBuf, Length1);
   1390   }
   1391 Done:
   1392   if (Value[0].Buffer != NULL) {
   1393     FreePool (Value[0].Buffer);
   1394   }
   1395   if (Value[1].Buffer != NULL) {
   1396     FreePool (Value[1].Buffer);
   1397   }
   1398   if (String[0] != NULL) {
   1399     FreePool (String[0]);
   1400   }
   1401   if (String[1] != NULL) {
   1402     FreePool (String[1]);
   1403   }
   1404   if (StringPtr != NULL) {
   1405     FreePool (StringPtr);
   1406   }
   1407 
   1408   return Status;
   1409 }
   1410 
   1411 
   1412 /**
   1413   Evaluate opcode EFI_IFR_MATCH.
   1414 
   1415   @param  FormSet                Formset which contains this opcode.
   1416   @param  Result                 Evaluation result for this opcode.
   1417 
   1418   @retval EFI_SUCCESS            Opcode evaluation success.
   1419   @retval Other                  Opcode evaluation failed.
   1420 
   1421 **/
   1422 EFI_STATUS
   1423 IfrMatch (
   1424   IN FORM_BROWSER_FORMSET  *FormSet,
   1425   OUT  EFI_HII_VALUE       *Result
   1426   )
   1427 {
   1428   EFI_STATUS     Status;
   1429   EFI_HII_VALUE  Value[2];
   1430   CHAR16         *String[2];
   1431   UINTN          Index;
   1432 
   1433   //
   1434   // String[0] - The string to search
   1435   // String[1] - pattern
   1436   //
   1437   String[0] = NULL;
   1438   String[1] = NULL;
   1439   Status = EFI_SUCCESS;
   1440   ZeroMem (Value, sizeof (Value));
   1441 
   1442   Status = PopExpression (&Value[0]);
   1443   if (EFI_ERROR (Status)) {
   1444     goto Done;
   1445   }
   1446 
   1447   Status = PopExpression (&Value[1]);
   1448   if (EFI_ERROR (Status)) {
   1449     goto Done;
   1450   }
   1451 
   1452   for (Index = 0; Index < 2; Index++) {
   1453     if (Value[Index].Type != EFI_IFR_TYPE_STRING) {
   1454       Result->Type = EFI_IFR_TYPE_UNDEFINED;
   1455       Status = EFI_SUCCESS;
   1456       goto Done;
   1457     }
   1458 
   1459     String[Index] = GetToken (Value[Index].Value.string, FormSet->HiiHandle);
   1460     if (String [Index] == NULL) {
   1461       Status = EFI_NOT_FOUND;
   1462       goto Done;
   1463     }
   1464   }
   1465 
   1466   Result->Type = EFI_IFR_TYPE_BOOLEAN;
   1467   Result->Value.b = mUnicodeCollation->MetaiMatch (mUnicodeCollation, String[0], String[1]);
   1468 
   1469 Done:
   1470   if (String[0] != NULL) {
   1471     FreePool (String[0]);
   1472   }
   1473   if (String[1] != NULL) {
   1474     FreePool (String[1]);
   1475   }
   1476 
   1477   return Status;
   1478 }
   1479 
   1480 /**
   1481   Evaluate opcode EFI_IFR_MATCH2.
   1482 
   1483   @param  FormSet                Formset which contains this opcode.
   1484   @param  SyntaxType             Syntax type for match2.
   1485   @param  Result                 Evaluation result for this opcode.
   1486 
   1487   @retval EFI_SUCCESS            Opcode evaluation success.
   1488   @retval Other                  Opcode evaluation failed.
   1489 
   1490 **/
   1491 EFI_STATUS
   1492 IfrMatch2 (
   1493   IN FORM_BROWSER_FORMSET  *FormSet,
   1494   IN EFI_GUID              *SyntaxType,
   1495   OUT  EFI_HII_VALUE       *Result
   1496   )
   1497 {
   1498   EFI_STATUS                       Status;
   1499   EFI_HII_VALUE                    Value[2];
   1500   CHAR16                           *String[2];
   1501   UINTN                            Index;
   1502   UINTN                            GuidIndex;
   1503   EFI_HANDLE                       *HandleBuffer;
   1504   UINTN                            BufferSize;
   1505   EFI_REGULAR_EXPRESSION_PROTOCOL  *RegularExpressionProtocol;
   1506   UINTN                            RegExSyntaxTypeListSize;
   1507   EFI_REGEX_SYNTAX_TYPE            *RegExSyntaxTypeList;
   1508   UINTN                            CapturesCount;
   1509 
   1510   //
   1511   // String[0] - The string to search
   1512   // String[1] - pattern
   1513   //
   1514   String[0] = NULL;
   1515   String[1] = NULL;
   1516   HandleBuffer = NULL;
   1517   RegExSyntaxTypeList = NULL;
   1518   Status = EFI_SUCCESS;
   1519   ZeroMem (Value, sizeof (Value));
   1520 
   1521   Status = PopExpression (&Value[0]);
   1522   if (EFI_ERROR (Status)) {
   1523     goto Done;
   1524   }
   1525 
   1526   Status = PopExpression (&Value[1]);
   1527   if (EFI_ERROR (Status)) {
   1528     goto Done;
   1529   }
   1530 
   1531   for (Index = 0; Index < 2; Index++) {
   1532     if (Value[Index].Type != EFI_IFR_TYPE_STRING) {
   1533       Result->Type = EFI_IFR_TYPE_UNDEFINED;
   1534       Status = EFI_SUCCESS;
   1535       goto Done;
   1536     }
   1537 
   1538     String[Index] = GetToken (Value[Index].Value.string, FormSet->HiiHandle);
   1539     if (String [Index] == NULL) {
   1540       Status = EFI_NOT_FOUND;
   1541       goto Done;
   1542     }
   1543   }
   1544 
   1545   BufferSize    = 0;
   1546   HandleBuffer  = NULL;
   1547   Status = gBS->LocateHandle(
   1548                       ByProtocol,
   1549                       &gEfiRegularExpressionProtocolGuid,
   1550                       NULL,
   1551                       &BufferSize,
   1552                       HandleBuffer);
   1553   if (Status == EFI_BUFFER_TOO_SMALL) {
   1554     HandleBuffer = AllocateZeroPool(BufferSize);
   1555     if (HandleBuffer == NULL) {
   1556       Status = EFI_OUT_OF_RESOURCES;
   1557       goto Done;
   1558     }
   1559     Status = gBS->LocateHandle(
   1560                         ByProtocol,
   1561                         &gEfiRegularExpressionProtocolGuid,
   1562                         NULL,
   1563                         &BufferSize,
   1564                         HandleBuffer);
   1565 
   1566   }
   1567 
   1568   if (EFI_ERROR (Status)) {
   1569     Result->Type = EFI_IFR_TYPE_UNDEFINED;
   1570     Status = EFI_SUCCESS;
   1571     goto Done;
   1572   }
   1573 
   1574   ASSERT (HandleBuffer != NULL);
   1575   for ( Index = 0; Index < BufferSize / sizeof(EFI_HANDLE); Index ++) {
   1576     Status = gBS->HandleProtocol (
   1577                   HandleBuffer[Index],
   1578                   &gEfiRegularExpressionProtocolGuid,
   1579                   (VOID**)&RegularExpressionProtocol
   1580                  );
   1581     if (EFI_ERROR (Status)) {
   1582       goto Done;
   1583     }
   1584 
   1585     RegExSyntaxTypeListSize = 0;
   1586     RegExSyntaxTypeList = NULL;
   1587 
   1588     Status = RegularExpressionProtocol->GetInfo (
   1589                                           RegularExpressionProtocol,
   1590                                           &RegExSyntaxTypeListSize,
   1591                                           RegExSyntaxTypeList
   1592                                           );
   1593     if (Status == EFI_BUFFER_TOO_SMALL) {
   1594       RegExSyntaxTypeList = AllocateZeroPool(RegExSyntaxTypeListSize);
   1595       if (RegExSyntaxTypeList == NULL) {
   1596         Status = EFI_OUT_OF_RESOURCES;
   1597         goto Done;
   1598       }
   1599       Status = RegularExpressionProtocol->GetInfo (
   1600                                             RegularExpressionProtocol,
   1601                                             &RegExSyntaxTypeListSize,
   1602                                             RegExSyntaxTypeList
   1603                                             );
   1604     } else if (EFI_ERROR (Status)) {
   1605       goto Done;
   1606     }
   1607 
   1608     for (GuidIndex = 0; GuidIndex < RegExSyntaxTypeListSize / sizeof(EFI_GUID); GuidIndex++) {
   1609       if (CompareGuid (&RegExSyntaxTypeList[GuidIndex], SyntaxType)) {
   1610         //
   1611         // Find the match type, return the value.
   1612         //
   1613         Result->Type = EFI_IFR_TYPE_BOOLEAN;
   1614         Status = RegularExpressionProtocol->MatchString (
   1615                                               RegularExpressionProtocol,
   1616                                               String[0],
   1617                                               String[1],
   1618                                               SyntaxType,
   1619                                               &Result->Value.b,
   1620                                               NULL,
   1621                                               &CapturesCount
   1622                                               );
   1623         goto Done;
   1624       }
   1625     }
   1626 
   1627     if (RegExSyntaxTypeList != NULL) {
   1628       FreePool (RegExSyntaxTypeList);
   1629     }
   1630   }
   1631 
   1632   //
   1633   // Type specified by SyntaxType is not supported
   1634   // in any of the EFI_REGULAR_EXPRESSION_PROTOCOL instances.
   1635   //
   1636   Result->Type = EFI_IFR_TYPE_UNDEFINED;
   1637   Status = EFI_SUCCESS;
   1638 
   1639 Done:
   1640   if (String[0] != NULL) {
   1641     FreePool (String[0]);
   1642   }
   1643   if (String[1] != NULL) {
   1644     FreePool (String[1]);
   1645   }
   1646   if (RegExSyntaxTypeList != NULL) {
   1647     FreePool (RegExSyntaxTypeList);
   1648   }
   1649   if (HandleBuffer != NULL) {
   1650     FreePool (HandleBuffer);
   1651   }
   1652   return Status;
   1653 }
   1654 
   1655 /**
   1656   Evaluate opcode EFI_IFR_FIND.
   1657 
   1658   @param  FormSet                Formset which contains this opcode.
   1659   @param  Format                 Case sensitive or insensitive.
   1660   @param  Result                 Evaluation result for this opcode.
   1661 
   1662   @retval EFI_SUCCESS            Opcode evaluation success.
   1663   @retval Other                  Opcode evaluation failed.
   1664 
   1665 **/
   1666 EFI_STATUS
   1667 IfrFind (
   1668   IN FORM_BROWSER_FORMSET  *FormSet,
   1669   IN UINT8                 Format,
   1670   OUT  EFI_HII_VALUE       *Result
   1671   )
   1672 {
   1673   EFI_STATUS     Status;
   1674   EFI_HII_VALUE  Value[3];
   1675   CHAR16         *String[2];
   1676   UINTN          Base;
   1677   CHAR16         *StringPtr;
   1678   UINTN          Index;
   1679 
   1680   ZeroMem (Value, sizeof (Value));
   1681 
   1682   if (Format > EFI_IFR_FF_CASE_INSENSITIVE) {
   1683     return EFI_INVALID_PARAMETER;
   1684   }
   1685 
   1686   Status = PopExpression (&Value[0]);
   1687   if (EFI_ERROR (Status)) {
   1688     return Status;
   1689   }
   1690 
   1691   Status = PopExpression (&Value[1]);
   1692   if (EFI_ERROR (Status)) {
   1693     return Status;
   1694   }
   1695 
   1696   Status = PopExpression (&Value[2]);
   1697   if (EFI_ERROR (Status)) {
   1698     return Status;
   1699   }
   1700 
   1701   if (Value[0].Type > EFI_IFR_TYPE_NUM_SIZE_64) {
   1702     Result->Type = EFI_IFR_TYPE_UNDEFINED;
   1703     return EFI_SUCCESS;
   1704   }
   1705   Base = (UINTN) Value[0].Value.u64;
   1706 
   1707   //
   1708   // String[0] - sub-string
   1709   // String[1] - The string to search
   1710   //
   1711   String[0] = NULL;
   1712   String[1] = NULL;
   1713   for (Index = 0; Index < 2; Index++) {
   1714     if (Value[Index + 1].Type != EFI_IFR_TYPE_STRING) {
   1715       Result->Type = EFI_IFR_TYPE_UNDEFINED;
   1716       Status = EFI_SUCCESS;
   1717       goto Done;
   1718     }
   1719 
   1720     String[Index] = GetToken (Value[Index + 1].Value.string, FormSet->HiiHandle);
   1721     if (String[Index] == NULL) {
   1722       Status = EFI_NOT_FOUND;
   1723       goto Done;
   1724     }
   1725 
   1726     if (Format == EFI_IFR_FF_CASE_INSENSITIVE) {
   1727       //
   1728       // Case insensitive, convert both string to upper case
   1729       //
   1730       IfrStrToUpper (String[Index]);
   1731     }
   1732   }
   1733 
   1734   Result->Type = EFI_IFR_TYPE_NUM_SIZE_64;
   1735   if (Base >= StrLen (String[1])) {
   1736     Result->Value.u64 = 0xFFFFFFFFFFFFFFFFULL;
   1737   } else {
   1738     StringPtr = StrStr (String[1] + Base, String[0]);
   1739     Result->Value.u64 = (StringPtr == NULL) ? 0xFFFFFFFFFFFFFFFFULL : (StringPtr - String[1]);
   1740   }
   1741 
   1742 Done:
   1743   if (String[0] != NULL) {
   1744     FreePool (String[0]);
   1745   }
   1746   if (String[1] != NULL) {
   1747     FreePool (String[1]);
   1748   }
   1749 
   1750   return Status;
   1751 }
   1752 
   1753 
   1754 /**
   1755   Evaluate opcode EFI_IFR_MID.
   1756 
   1757   @param  FormSet                Formset which contains this opcode.
   1758   @param  Result                 Evaluation result for this opcode.
   1759 
   1760   @retval EFI_SUCCESS            Opcode evaluation success.
   1761   @retval Other                  Opcode evaluation failed.
   1762 
   1763 **/
   1764 EFI_STATUS
   1765 IfrMid (
   1766   IN FORM_BROWSER_FORMSET  *FormSet,
   1767   OUT  EFI_HII_VALUE       *Result
   1768   )
   1769 {
   1770   EFI_STATUS     Status;
   1771   EFI_HII_VALUE  Value[3];
   1772   CHAR16         *String;
   1773   UINTN          Base;
   1774   UINTN          Length;
   1775   CHAR16         *SubString;
   1776   UINT16         BufferLen;
   1777   UINT8          *Buffer;
   1778 
   1779   ZeroMem (Value, sizeof (Value));
   1780 
   1781   Status = PopExpression (&Value[0]);
   1782   if (EFI_ERROR (Status)) {
   1783     return Status;
   1784   }
   1785 
   1786   Status = PopExpression (&Value[1]);
   1787   if (EFI_ERROR (Status)) {
   1788     return Status;
   1789   }
   1790 
   1791   Status = PopExpression (&Value[2]);
   1792   if (EFI_ERROR (Status)) {
   1793     return Status;
   1794   }
   1795 
   1796   if (Value[0].Type > EFI_IFR_TYPE_NUM_SIZE_64) {
   1797     Result->Type = EFI_IFR_TYPE_UNDEFINED;
   1798     return EFI_SUCCESS;
   1799   }
   1800   Length = (UINTN) Value[0].Value.u64;
   1801 
   1802   if (Value[1].Type > EFI_IFR_TYPE_NUM_SIZE_64) {
   1803     Result->Type = EFI_IFR_TYPE_UNDEFINED;
   1804     return EFI_SUCCESS;
   1805   }
   1806   Base = (UINTN) Value[1].Value.u64;
   1807 
   1808   if (Value[2].Type != EFI_IFR_TYPE_STRING && !IsTypeInBuffer(&Value[2])) {
   1809     Result->Type = EFI_IFR_TYPE_UNDEFINED;
   1810     return EFI_SUCCESS;
   1811   }
   1812   if (Value[2].Type == EFI_IFR_TYPE_STRING) {
   1813     String = GetToken (Value[2].Value.string, FormSet->HiiHandle);
   1814     if (String == NULL) {
   1815       return EFI_NOT_FOUND;
   1816     }
   1817 
   1818     if (Length == 0 || Base >= StrLen (String)) {
   1819       SubString = gEmptyString;
   1820     } else {
   1821       SubString = String + Base;
   1822       if ((Base + Length) < StrLen (String)) {
   1823         SubString[Length] = L'\0';
   1824       }
   1825     }
   1826 
   1827     Result->Type = EFI_IFR_TYPE_STRING;
   1828     Result->Value.string = NewString (SubString, FormSet->HiiHandle);
   1829 
   1830     FreePool (String);
   1831   } else {
   1832     BufferLen = GetLengthForValue (&Value[2]);
   1833     Buffer = GetBufferForValue (&Value[2]);
   1834 
   1835     Result->Type = EFI_IFR_TYPE_BUFFER;
   1836     if (Length == 0 || Base >= BufferLen) {
   1837       Result->BufferLen = 0;
   1838       Result->Buffer = NULL;
   1839     } else {
   1840       Result->BufferLen = (UINT16)((BufferLen - Base) < Length ? (BufferLen - Base) : Length);
   1841       Result->Buffer = AllocateZeroPool (Result->BufferLen);
   1842       ASSERT (Result->Buffer != NULL);
   1843       CopyMem (Result->Buffer, &Buffer[Base], Result->BufferLen);
   1844     }
   1845 
   1846     if (Value[2].Type == EFI_IFR_TYPE_BUFFER) {
   1847       FreePool (Value[2].Buffer);
   1848     }
   1849   }
   1850 
   1851   return Status;
   1852 }
   1853 
   1854 
   1855 /**
   1856   Evaluate opcode EFI_IFR_TOKEN.
   1857 
   1858   @param  FormSet                Formset which contains this opcode.
   1859   @param  Result                 Evaluation result for this opcode.
   1860 
   1861   @retval EFI_SUCCESS            Opcode evaluation success.
   1862   @retval Other                  Opcode evaluation failed.
   1863 
   1864 **/
   1865 EFI_STATUS
   1866 IfrToken (
   1867   IN FORM_BROWSER_FORMSET  *FormSet,
   1868   OUT  EFI_HII_VALUE       *Result
   1869   )
   1870 {
   1871   EFI_STATUS     Status;
   1872   EFI_HII_VALUE  Value[3];
   1873   CHAR16         *String[2];
   1874   UINTN          Count;
   1875   CHAR16         *Delimiter;
   1876   CHAR16         *SubString;
   1877   CHAR16         *StringPtr;
   1878   UINTN          Index;
   1879 
   1880   ZeroMem (Value, sizeof (Value));
   1881 
   1882   Status = PopExpression (&Value[0]);
   1883   if (EFI_ERROR (Status)) {
   1884     return Status;
   1885   }
   1886 
   1887   Status = PopExpression (&Value[1]);
   1888   if (EFI_ERROR (Status)) {
   1889     return Status;
   1890   }
   1891 
   1892   Status = PopExpression (&Value[2]);
   1893   if (EFI_ERROR (Status)) {
   1894     return Status;
   1895   }
   1896 
   1897   if (Value[0].Type > EFI_IFR_TYPE_NUM_SIZE_64) {
   1898     Result->Type = EFI_IFR_TYPE_UNDEFINED;
   1899     return EFI_SUCCESS;
   1900   }
   1901   Count = (UINTN) Value[0].Value.u64;
   1902 
   1903   //
   1904   // String[0] - Delimiter
   1905   // String[1] - The string to search
   1906   //
   1907   String[0] = NULL;
   1908   String[1] = NULL;
   1909   for (Index = 0; Index < 2; Index++) {
   1910     if (Value[Index + 1].Type != EFI_IFR_TYPE_STRING) {
   1911       Result->Type = EFI_IFR_TYPE_UNDEFINED;
   1912       Status = EFI_SUCCESS;
   1913       goto Done;
   1914     }
   1915 
   1916     String[Index] = GetToken (Value[Index + 1].Value.string, FormSet->HiiHandle);
   1917     if (String[Index] == NULL) {
   1918       Status = EFI_NOT_FOUND;
   1919       goto Done;
   1920     }
   1921   }
   1922 
   1923   Delimiter = String[0];
   1924   SubString = String[1];
   1925   while (Count > 0) {
   1926     SubString = StrStr (SubString, Delimiter);
   1927     if (SubString != NULL) {
   1928       //
   1929       // Skip over the delimiter
   1930       //
   1931       SubString = SubString + StrLen (Delimiter);
   1932     } else {
   1933       break;
   1934     }
   1935     Count--;
   1936   }
   1937 
   1938   if (SubString == NULL) {
   1939     //
   1940     // nth delimited sub-string not found, push an empty string
   1941     //
   1942     SubString = gEmptyString;
   1943   } else {
   1944     //
   1945     // Put a NULL terminator for nth delimited sub-string
   1946     //
   1947     StringPtr = StrStr (SubString, Delimiter);
   1948     if (StringPtr != NULL) {
   1949       *StringPtr = L'\0';
   1950     }
   1951   }
   1952 
   1953   Result->Type = EFI_IFR_TYPE_STRING;
   1954   Result->Value.string = NewString (SubString, FormSet->HiiHandle);
   1955 
   1956 Done:
   1957   if (String[0] != NULL) {
   1958     FreePool (String[0]);
   1959   }
   1960   if (String[1] != NULL) {
   1961     FreePool (String[1]);
   1962   }
   1963 
   1964   return Status;
   1965 }
   1966 
   1967 
   1968 /**
   1969   Evaluate opcode EFI_IFR_SPAN.
   1970 
   1971   @param  FormSet                Formset which contains this opcode.
   1972   @param  Flags                  FIRST_MATCHING or FIRST_NON_MATCHING.
   1973   @param  Result                 Evaluation result for this opcode.
   1974 
   1975   @retval EFI_SUCCESS            Opcode evaluation success.
   1976   @retval Other                  Opcode evaluation failed.
   1977 
   1978 **/
   1979 EFI_STATUS
   1980 IfrSpan (
   1981   IN FORM_BROWSER_FORMSET  *FormSet,
   1982   IN UINT8                 Flags,
   1983   OUT  EFI_HII_VALUE       *Result
   1984   )
   1985 {
   1986   EFI_STATUS     Status;
   1987   EFI_HII_VALUE  Value[3];
   1988   CHAR16         *String[2];
   1989   CHAR16         *Charset;
   1990   UINTN          Base;
   1991   UINTN          Index;
   1992   CHAR16         *StringPtr;
   1993   BOOLEAN        Found;
   1994 
   1995   ZeroMem (Value, sizeof (Value));
   1996 
   1997   Status = PopExpression (&Value[0]);
   1998   if (EFI_ERROR (Status)) {
   1999     return Status;
   2000   }
   2001 
   2002   Status = PopExpression (&Value[1]);
   2003   if (EFI_ERROR (Status)) {
   2004     return Status;
   2005   }
   2006 
   2007   Status = PopExpression (&Value[2]);
   2008   if (EFI_ERROR (Status)) {
   2009     return Status;
   2010   }
   2011 
   2012   if (Value[0].Type > EFI_IFR_TYPE_NUM_SIZE_64) {
   2013     Result->Type = EFI_IFR_TYPE_UNDEFINED;
   2014     return EFI_SUCCESS;
   2015   }
   2016   Base = (UINTN) Value[0].Value.u64;
   2017 
   2018   //
   2019   // String[0] - Charset
   2020   // String[1] - The string to search
   2021   //
   2022   String[0] = NULL;
   2023   String[1] = NULL;
   2024   for (Index = 0; Index < 2; Index++) {
   2025     if (Value[Index + 1].Type != EFI_IFR_TYPE_STRING) {
   2026       Result->Type = EFI_IFR_TYPE_UNDEFINED;
   2027       Status = EFI_SUCCESS;
   2028       goto Done;
   2029     }
   2030 
   2031     String[Index] = GetToken (Value[Index + 1].Value.string, FormSet->HiiHandle);
   2032     if (String [Index] == NULL) {
   2033       Status = EFI_NOT_FOUND;
   2034       goto Done;
   2035     }
   2036   }
   2037 
   2038   if (Base >= StrLen (String[1])) {
   2039     Result->Type = EFI_IFR_TYPE_UNDEFINED;
   2040     Status = EFI_SUCCESS;
   2041     goto Done;
   2042   }
   2043 
   2044   Found = FALSE;
   2045   StringPtr = String[1] + Base;
   2046   Charset = String[0];
   2047   while (*StringPtr != 0 && !Found) {
   2048     Index = 0;
   2049     while (Charset[Index] != 0) {
   2050       if (*StringPtr >= Charset[Index] && *StringPtr <= Charset[Index + 1]) {
   2051         if (Flags == EFI_IFR_FLAGS_FIRST_MATCHING) {
   2052           Found = TRUE;
   2053           break;
   2054         }
   2055       } else {
   2056         if (Flags == EFI_IFR_FLAGS_FIRST_NON_MATCHING) {
   2057           Found = TRUE;
   2058           break;
   2059         }
   2060       }
   2061       //
   2062       // Skip characters pair representing low-end of a range and high-end of a range
   2063       //
   2064       Index += 2;
   2065     }
   2066 
   2067     if (!Found) {
   2068       StringPtr++;
   2069     }
   2070   }
   2071 
   2072   Result->Type = EFI_IFR_TYPE_NUM_SIZE_64;
   2073   Result->Value.u64 = StringPtr - String[1];
   2074 
   2075 Done:
   2076   if (String[0] != NULL) {
   2077     FreePool (String[0]);
   2078   }
   2079   if (String[1] != NULL) {
   2080     FreePool (String[1]);
   2081   }
   2082 
   2083   return Status;
   2084 }
   2085 
   2086 
   2087 /**
   2088   Zero extend integer/boolean/date/time to UINT64 for comparing.
   2089 
   2090   @param  Value                  HII Value to be converted.
   2091 
   2092 **/
   2093 VOID
   2094 ExtendValueToU64 (
   2095   IN  EFI_HII_VALUE   *Value
   2096   )
   2097 {
   2098   UINT64  Temp;
   2099 
   2100   Temp = 0;
   2101   switch (Value->Type) {
   2102   case EFI_IFR_TYPE_NUM_SIZE_8:
   2103     Temp = Value->Value.u8;
   2104     break;
   2105 
   2106   case EFI_IFR_TYPE_NUM_SIZE_16:
   2107     Temp = Value->Value.u16;
   2108     break;
   2109 
   2110   case EFI_IFR_TYPE_NUM_SIZE_32:
   2111     Temp = Value->Value.u32;
   2112     break;
   2113 
   2114   case EFI_IFR_TYPE_BOOLEAN:
   2115     Temp = Value->Value.b;
   2116     break;
   2117 
   2118   case EFI_IFR_TYPE_TIME:
   2119     Temp = Value->Value.u32 & 0xffffff;
   2120     break;
   2121 
   2122   case EFI_IFR_TYPE_DATE:
   2123     Temp = Value->Value.u32;
   2124     break;
   2125 
   2126   default:
   2127     return;
   2128   }
   2129 
   2130   Value->Value.u64 = Temp;
   2131 }
   2132 
   2133 /**
   2134   Get UINT64 type value.
   2135 
   2136   @param  Value                  Input Hii value.
   2137 
   2138   @retval UINT64                 Return the UINT64 type value.
   2139 
   2140 **/
   2141 UINT64
   2142 HiiValueToUINT64 (
   2143   IN EFI_HII_VALUE      *Value
   2144   )
   2145 {
   2146   UINT64  RetVal;
   2147 
   2148   RetVal = 0;
   2149 
   2150   switch (Value->Type) {
   2151   case EFI_IFR_TYPE_NUM_SIZE_8:
   2152     RetVal = Value->Value.u8;
   2153     break;
   2154 
   2155   case EFI_IFR_TYPE_NUM_SIZE_16:
   2156     RetVal = Value->Value.u16;
   2157     break;
   2158 
   2159   case EFI_IFR_TYPE_NUM_SIZE_32:
   2160     RetVal = Value->Value.u32;
   2161     break;
   2162 
   2163   case EFI_IFR_TYPE_BOOLEAN:
   2164     RetVal = Value->Value.b;
   2165     break;
   2166 
   2167   case EFI_IFR_TYPE_DATE:
   2168     RetVal = *(UINT64*) &Value->Value.date;
   2169     break;
   2170 
   2171   case EFI_IFR_TYPE_TIME:
   2172     RetVal = (*(UINT64*) &Value->Value.time) & 0xffffff;
   2173     break;
   2174 
   2175   default:
   2176     RetVal = Value->Value.u64;
   2177     break;
   2178   }
   2179 
   2180   return RetVal;
   2181 }
   2182 
   2183 /**
   2184   Compare two Hii value.
   2185 
   2186   @param  Value1                 Expression value to compare on left-hand.
   2187   @param  Value2                 Expression value to compare on right-hand.
   2188   @param  Result                 Return value after compare.
   2189                                  retval 0                      Two operators equal.
   2190                                  return Positive value if Value1 is greater than Value2.
   2191                                  retval Negative value if Value1 is less than Value2.
   2192   @param  HiiHandle              Only required for string compare.
   2193 
   2194   @retval other                  Could not perform compare on two values.
   2195   @retval EFI_SUCCESS            Compare the value success.
   2196 
   2197 **/
   2198 EFI_STATUS
   2199 CompareHiiValue (
   2200   IN  EFI_HII_VALUE   *Value1,
   2201   IN  EFI_HII_VALUE   *Value2,
   2202   OUT INTN            *Result,
   2203   IN  EFI_HII_HANDLE  HiiHandle OPTIONAL
   2204   )
   2205 {
   2206   INT64   Temp64;
   2207   CHAR16  *Str1;
   2208   CHAR16  *Str2;
   2209   UINTN   Len;
   2210   UINT8   *Buf1;
   2211   UINT16  Buf1Len;
   2212   UINT8   *Buf2;
   2213   UINT16  Buf2Len;
   2214 
   2215   if (Value1->Type == EFI_IFR_TYPE_STRING && Value2->Type == EFI_IFR_TYPE_STRING) {
   2216     if (Value1->Value.string == 0 || Value2->Value.string == 0) {
   2217       //
   2218       // StringId 0 is reserved
   2219       //
   2220       return EFI_INVALID_PARAMETER;
   2221     }
   2222 
   2223     if (Value1->Value.string == Value2->Value.string) {
   2224       *Result = 0;
   2225       return EFI_SUCCESS;
   2226     }
   2227 
   2228     Str1 = GetToken (Value1->Value.string, HiiHandle);
   2229     if (Str1 == NULL) {
   2230       //
   2231       // String not found
   2232       //
   2233       return EFI_NOT_FOUND;
   2234     }
   2235 
   2236     Str2 = GetToken (Value2->Value.string, HiiHandle);
   2237     if (Str2 == NULL) {
   2238       FreePool (Str1);
   2239       return EFI_NOT_FOUND;
   2240     }
   2241 
   2242     *Result = StrCmp (Str1, Str2);
   2243 
   2244     FreePool (Str1);
   2245     FreePool (Str2);
   2246 
   2247     return EFI_SUCCESS;
   2248   }
   2249 
   2250   //
   2251   // Take types(date, time, ref, buffer) as buffer
   2252   //
   2253   if (IsTypeInBuffer(Value1) && IsTypeInBuffer(Value2)) {
   2254     Buf1    = GetBufferForValue(Value1);
   2255     Buf1Len = GetLengthForValue(Value1);
   2256     Buf2    = GetBufferForValue(Value2);
   2257     Buf2Len = GetLengthForValue(Value2);
   2258 
   2259     Len = Buf1Len > Buf2Len ? Buf2Len : Buf1Len;
   2260     *Result = CompareMem (Buf1, Buf2, Len);
   2261     if ((*Result == 0) && (Buf1Len != Buf2Len)) {
   2262       //
   2263       // In this case, means base on samll number buffer, the data is same
   2264       // So which value has more data, which value is bigger.
   2265       //
   2266       *Result = Buf1Len > Buf2Len ? 1 : -1;
   2267     }
   2268     return EFI_SUCCESS;
   2269   }
   2270 
   2271   //
   2272   // Take types(integer, boolean) as integer
   2273   //
   2274   if (IsTypeInUINT64(Value1) && IsTypeInUINT64(Value2)) {
   2275     Temp64 = HiiValueToUINT64(Value1) - HiiValueToUINT64(Value2);
   2276     if (Temp64 > 0) {
   2277       *Result = 1;
   2278     } else if (Temp64 < 0) {
   2279       *Result = -1;
   2280     } else {
   2281       *Result = 0;
   2282     }
   2283 
   2284     return EFI_SUCCESS;
   2285   }
   2286 
   2287   return EFI_UNSUPPORTED;
   2288 }
   2289 
   2290 /**
   2291   Check if current user has the privilege specified by the permissions GUID.
   2292 
   2293   @param[in] Guid  A GUID specifying setup access permissions.
   2294 
   2295   @retval TRUE     Current user has the privilege.
   2296   @retval FALSE    Current user does not have the privilege.
   2297 **/
   2298 BOOLEAN
   2299 CheckUserPrivilege (
   2300   IN EFI_GUID *Guid
   2301   )
   2302 {
   2303   EFI_STATUS                   Status;
   2304   EFI_USER_PROFILE_HANDLE      UserProfileHandle;
   2305   EFI_USER_INFO_HANDLE         UserInfoHandle;
   2306   EFI_USER_INFO                *UserInfo;
   2307   EFI_GUID                     *UserPermissionsGuid;
   2308   UINTN                        UserInfoSize;
   2309   UINTN                        AccessControlDataSize;
   2310   EFI_USER_INFO_ACCESS_CONTROL *AccessControl;
   2311   UINTN                        RemainSize;
   2312 
   2313   if (mUserManager == NULL) {
   2314     Status = gBS->LocateProtocol (
   2315                     &gEfiUserManagerProtocolGuid,
   2316                     NULL,
   2317                     (VOID **) &mUserManager
   2318                     );
   2319     if (EFI_ERROR (Status)) {
   2320       ///
   2321       /// If the system does not support user management, then it is assumed that
   2322       /// all users have admin privilege and evaluation of each EFI_IFR_SECURITY
   2323       /// op-code is always TRUE.
   2324       ///
   2325       return TRUE;
   2326     }
   2327   }
   2328 
   2329   Status = mUserManager->Current (mUserManager, &UserProfileHandle);
   2330   ASSERT_EFI_ERROR (Status);
   2331 
   2332   ///
   2333   /// Enumerate all user information of the current user profile
   2334   /// to look for any EFI_USER_INFO_ACCESS_SETUP record.
   2335   ///
   2336 
   2337   for (UserInfoHandle = NULL;;) {
   2338     Status = mUserManager->GetNextInfo (mUserManager, UserProfileHandle, &UserInfoHandle);
   2339     if (EFI_ERROR (Status)) {
   2340       break;
   2341     }
   2342 
   2343     UserInfoSize = 0;
   2344     Status = mUserManager->GetInfo (mUserManager, UserProfileHandle, UserInfoHandle, NULL, &UserInfoSize);
   2345     if (Status != EFI_BUFFER_TOO_SMALL) {
   2346       continue;
   2347     }
   2348 
   2349     UserInfo = (EFI_USER_INFO *) AllocatePool (UserInfoSize);
   2350     if (UserInfo == NULL) {
   2351       break;
   2352     }
   2353 
   2354     Status = mUserManager->GetInfo (mUserManager, UserProfileHandle, UserInfoHandle, UserInfo, &UserInfoSize);
   2355     if (EFI_ERROR (Status) ||
   2356         UserInfo->InfoType != EFI_USER_INFO_ACCESS_POLICY_RECORD ||
   2357         UserInfo->InfoSize <= sizeof (EFI_USER_INFO)) {
   2358       FreePool (UserInfo);
   2359       continue;
   2360     }
   2361 
   2362     RemainSize = UserInfo->InfoSize - sizeof (EFI_USER_INFO);
   2363     AccessControl = (EFI_USER_INFO_ACCESS_CONTROL *)(UserInfo + 1);
   2364     while (RemainSize >= sizeof (EFI_USER_INFO_ACCESS_CONTROL)) {
   2365       if (RemainSize < AccessControl->Size || AccessControl->Size < sizeof (EFI_USER_INFO_ACCESS_CONTROL)) {
   2366         break;
   2367       }
   2368       if (AccessControl->Type == EFI_USER_INFO_ACCESS_SETUP) {
   2369         ///
   2370         /// Check if current user has the privilege specified by the permissions GUID.
   2371         ///
   2372 
   2373         UserPermissionsGuid = (EFI_GUID *)(AccessControl + 1);
   2374         AccessControlDataSize = AccessControl->Size - sizeof (EFI_USER_INFO_ACCESS_CONTROL);
   2375         while (AccessControlDataSize >= sizeof (EFI_GUID)) {
   2376           if (CompareGuid (Guid, UserPermissionsGuid)) {
   2377             FreePool (UserInfo);
   2378             return TRUE;
   2379           }
   2380           UserPermissionsGuid++;
   2381           AccessControlDataSize -= sizeof (EFI_GUID);
   2382         }
   2383       }
   2384       RemainSize -= AccessControl->Size;
   2385       AccessControl = (EFI_USER_INFO_ACCESS_CONTROL *)((UINT8 *)AccessControl + AccessControl->Size);
   2386     }
   2387 
   2388     FreePool (UserInfo);
   2389   }
   2390   return FALSE;
   2391 }
   2392 
   2393 /**
   2394   Get question value from the predefined formset.
   2395 
   2396   @param  DevicePath             The driver's device path which produece the formset data.
   2397   @param  InputHiiHandle         The hii handle associate with the formset data.
   2398   @param  FormSetGuid            The formset guid which include the question.
   2399   @param  QuestionId             The question id which need to get value from.
   2400   @param  Value                  The return data about question's value.
   2401 
   2402   @retval TRUE                   Get the question value success.
   2403   @retval FALSE                  Get the question value failed.
   2404 **/
   2405 BOOLEAN
   2406 GetQuestionValueFromForm (
   2407   IN EFI_DEVICE_PATH_PROTOCOL  *DevicePath,
   2408   IN EFI_HII_HANDLE            InputHiiHandle,
   2409   IN EFI_GUID                  *FormSetGuid,
   2410   IN EFI_QUESTION_ID           QuestionId,
   2411   OUT EFI_HII_VALUE            *Value
   2412   )
   2413 {
   2414   EFI_STATUS                   Status;
   2415   EFI_HII_HANDLE               HiiHandle;
   2416   FORM_BROWSER_STATEMENT       *Question;
   2417   FORM_BROWSER_FORMSET         *FormSet;
   2418   FORM_BROWSER_FORM            *Form;
   2419   BOOLEAN                      GetTheVal;
   2420   LIST_ENTRY                   *Link;
   2421 
   2422   //
   2423   // The input parameter DevicePath or InputHiiHandle must have one valid input.
   2424   //
   2425   ASSERT ((DevicePath != NULL && InputHiiHandle == NULL) ||
   2426           (DevicePath == NULL && InputHiiHandle != NULL) );
   2427 
   2428   GetTheVal    = TRUE;
   2429   HiiHandle    = NULL;
   2430   Question     = NULL;
   2431   Form         = NULL;
   2432 
   2433   //
   2434   // Get HiiHandle.
   2435   //
   2436   if (DevicePath != NULL) {
   2437     HiiHandle = DevicePathToHiiHandle (DevicePath, FormSetGuid);
   2438     if (HiiHandle == NULL) {
   2439       return FALSE;
   2440     }
   2441   } else {
   2442     HiiHandle = InputHiiHandle;
   2443   }
   2444   ASSERT (HiiHandle != NULL);
   2445 
   2446   //
   2447   // Get the formset data include this question.
   2448   //
   2449   FormSet = AllocateZeroPool (sizeof (FORM_BROWSER_FORMSET));
   2450   ASSERT (FormSet != NULL);
   2451   Status = InitializeFormSet(HiiHandle, FormSetGuid, FormSet);
   2452   if (EFI_ERROR (Status)) {
   2453     GetTheVal = FALSE;
   2454     goto Done;
   2455   }
   2456 
   2457   //
   2458   // Base on the Question Id to get the question info.
   2459   //
   2460   Question = IdToQuestion(FormSet, NULL, QuestionId);
   2461   if (Question == NULL) {
   2462     GetTheVal = FALSE;
   2463     goto Done;
   2464   }
   2465 
   2466   //
   2467   // Search form in the formset scope
   2468   //
   2469   Link = GetFirstNode (&FormSet->FormListHead);
   2470   while (!IsNull (&FormSet->FormListHead, Link)) {
   2471     Form = FORM_BROWSER_FORM_FROM_LINK (Link);
   2472 
   2473     Question = IdToQuestion2 (Form, QuestionId);
   2474     if (Question != NULL) {
   2475       break;
   2476     }
   2477 
   2478     Link = GetNextNode (&FormSet->FormListHead, Link);
   2479     Form = NULL;
   2480   }
   2481   ASSERT (Form != NULL);
   2482 
   2483   //
   2484   // Get the question value.
   2485   //
   2486   Status = GetQuestionValue(FormSet, Form, Question, GetSetValueWithEditBuffer);
   2487   if (EFI_ERROR (Status)) {
   2488     GetTheVal = FALSE;
   2489     goto Done;
   2490   }
   2491 
   2492   CopyMem (Value, &Question->HiiValue, sizeof (EFI_HII_VALUE));
   2493 
   2494 Done:
   2495   //
   2496   // Clean the formset structure and restore the global parameter.
   2497   //
   2498   if (FormSet != NULL) {
   2499     DestroyFormSet (FormSet);
   2500   }
   2501 
   2502   return GetTheVal;
   2503 }
   2504 
   2505 /**
   2506   Evaluate the result of a HII expression.
   2507 
   2508   If Expression is NULL, then ASSERT.
   2509 
   2510   @param  FormSet                FormSet associated with this expression.
   2511   @param  Form                   Form associated with this expression.
   2512   @param  Expression             Expression to be evaluated.
   2513 
   2514   @retval EFI_SUCCESS            The expression evaluated successfuly
   2515   @retval EFI_NOT_FOUND          The Question which referenced by a QuestionId
   2516                                  could not be found.
   2517   @retval EFI_OUT_OF_RESOURCES   There is not enough system memory to grow the
   2518                                  stack.
   2519   @retval EFI_ACCESS_DENIED      The pop operation underflowed the stack
   2520   @retval EFI_INVALID_PARAMETER  Syntax error with the Expression
   2521 
   2522 **/
   2523 EFI_STATUS
   2524 EvaluateExpression (
   2525   IN FORM_BROWSER_FORMSET  *FormSet,
   2526   IN FORM_BROWSER_FORM     *Form,
   2527   IN OUT FORM_EXPRESSION   *Expression
   2528   )
   2529 {
   2530   EFI_STATUS              Status;
   2531   LIST_ENTRY              *Link;
   2532   EXPRESSION_OPCODE       *OpCode;
   2533   FORM_BROWSER_STATEMENT  *Question;
   2534   FORM_BROWSER_STATEMENT  *Question2;
   2535   UINT16                  Index;
   2536   EFI_HII_VALUE           Data1;
   2537   EFI_HII_VALUE           Data2;
   2538   EFI_HII_VALUE           Data3;
   2539   FORM_EXPRESSION         *RuleExpression;
   2540   EFI_HII_VALUE           *Value;
   2541   INTN                    Result;
   2542   CHAR16                  *StrPtr;
   2543   CHAR16                  *NameValue;
   2544   UINT32                  TempValue;
   2545   LIST_ENTRY              *SubExpressionLink;
   2546   FORM_EXPRESSION         *SubExpression;
   2547   UINTN                   StackOffset;
   2548   UINTN                   TempLength;
   2549   CHAR16                  TempStr[5];
   2550   UINT8                   DigitUint8;
   2551   UINT8                   *TempBuffer;
   2552   EFI_TIME                EfiTime;
   2553   EFI_HII_VALUE           QuestionVal;
   2554   EFI_DEVICE_PATH_PROTOCOL *DevicePath;
   2555 
   2556   StrPtr = NULL;
   2557 
   2558   //
   2559   // Save current stack offset.
   2560   //
   2561   StackOffset = SaveExpressionEvaluationStackOffset ();
   2562 
   2563   ASSERT (Expression != NULL);
   2564   Expression->Result.Type = EFI_IFR_TYPE_OTHER;
   2565 
   2566   Link = GetFirstNode (&Expression->OpCodeListHead);
   2567   while (!IsNull (&Expression->OpCodeListHead, Link)) {
   2568     OpCode = EXPRESSION_OPCODE_FROM_LINK (Link);
   2569 
   2570     Link = GetNextNode (&Expression->OpCodeListHead, Link);
   2571 
   2572     ZeroMem (&Data1, sizeof (EFI_HII_VALUE));
   2573     ZeroMem (&Data2, sizeof (EFI_HII_VALUE));
   2574     ZeroMem (&Data3, sizeof (EFI_HII_VALUE));
   2575 
   2576     Value = &Data3;
   2577     Value->Type = EFI_IFR_TYPE_BOOLEAN;
   2578     Status = EFI_SUCCESS;
   2579 
   2580     switch (OpCode->Operand) {
   2581     //
   2582     // Built-in functions
   2583     //
   2584     case EFI_IFR_EQ_ID_VAL_OP:
   2585       Question = IdToQuestion (FormSet, Form, OpCode->QuestionId);
   2586       if (Question == NULL) {
   2587         Value->Type = EFI_IFR_TYPE_UNDEFINED;
   2588         break;
   2589       }
   2590 
   2591       Status = CompareHiiValue (&Question->HiiValue, &OpCode->Value, &Result, NULL);
   2592       if (Status == EFI_UNSUPPORTED) {
   2593         Status = EFI_SUCCESS;
   2594         Value->Type = EFI_IFR_TYPE_UNDEFINED;
   2595         break;
   2596       }
   2597 
   2598       if (EFI_ERROR (Status)) {
   2599         goto Done;
   2600       }
   2601       Value->Value.b = (BOOLEAN) ((Result == 0) ? TRUE : FALSE);
   2602       break;
   2603 
   2604     case EFI_IFR_EQ_ID_ID_OP:
   2605       Question = IdToQuestion (FormSet, Form, OpCode->QuestionId);
   2606       if (Question == NULL) {
   2607         Value->Type = EFI_IFR_TYPE_UNDEFINED;
   2608         break;
   2609       }
   2610 
   2611       Question2 = IdToQuestion (FormSet, Form, OpCode->QuestionId2);
   2612       if (Question2 == NULL) {
   2613         Value->Type = EFI_IFR_TYPE_UNDEFINED;
   2614         break;
   2615       }
   2616 
   2617       Status = CompareHiiValue (&Question->HiiValue, &Question2->HiiValue, &Result, FormSet->HiiHandle);
   2618       if (Status == EFI_UNSUPPORTED) {
   2619         Value->Type = EFI_IFR_TYPE_UNDEFINED;
   2620         Status = EFI_SUCCESS;
   2621         break;
   2622       }
   2623       if (EFI_ERROR (Status)) {
   2624         goto Done;
   2625       }
   2626       Value->Value.b = (BOOLEAN) ((Result == 0) ? TRUE : FALSE);
   2627       break;
   2628 
   2629     case EFI_IFR_EQ_ID_VAL_LIST_OP:
   2630       Question = IdToQuestion (FormSet, Form, OpCode->QuestionId);
   2631       if (Question == NULL) {
   2632         Value->Type = EFI_IFR_TYPE_UNDEFINED;
   2633         break;
   2634       }
   2635 
   2636       Value->Value.b = FALSE;
   2637       for (Index =0; Index < OpCode->ListLength; Index++) {
   2638         if (Question->HiiValue.Value.u16 == OpCode->ValueList[Index]) {
   2639           Value->Value.b = TRUE;
   2640           break;
   2641         }
   2642       }
   2643       break;
   2644 
   2645     case EFI_IFR_DUP_OP:
   2646       Status = PopExpression (Value);
   2647       if (EFI_ERROR (Status)) {
   2648         goto Done;
   2649       }
   2650 
   2651       Status = PushExpression (Value);
   2652       break;
   2653 
   2654     case EFI_IFR_QUESTION_REF1_OP:
   2655     case EFI_IFR_THIS_OP:
   2656       Question = IdToQuestion (FormSet, Form, OpCode->QuestionId);
   2657       if (Question == NULL) {
   2658         Status = EFI_NOT_FOUND;
   2659         goto Done;
   2660       }
   2661 
   2662       Value = &Question->HiiValue;
   2663       break;
   2664 
   2665     case EFI_IFR_SECURITY_OP:
   2666       Value->Value.b = CheckUserPrivilege (&OpCode->Guid);
   2667       break;
   2668 
   2669     case EFI_IFR_GET_OP:
   2670       //
   2671       // Get Value from VarStore buffer, EFI VarStore, Name/Value VarStore.
   2672       //
   2673       Value->Type = EFI_IFR_TYPE_UNDEFINED;
   2674       Value->Value.u8 = 0;
   2675       if (OpCode->VarStorage != NULL) {
   2676         switch (OpCode->VarStorage->Type) {
   2677         case EFI_HII_VARSTORE_BUFFER:
   2678         case EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER:
   2679           //
   2680           // Get value from Edit Buffer
   2681           //
   2682           Value->Type = OpCode->ValueType;
   2683           CopyMem (&Value->Value, OpCode->VarStorage->EditBuffer + OpCode->VarStoreInfo.VarOffset, OpCode->ValueWidth);
   2684           break;
   2685         case EFI_HII_VARSTORE_NAME_VALUE:
   2686           if (OpCode->ValueType != EFI_IFR_TYPE_STRING) {
   2687             //
   2688             // Get value from string except for STRING value.
   2689             //
   2690             Status = GetValueByName (OpCode->VarStorage, OpCode->ValueName, &StrPtr, GetSetValueWithEditBuffer);
   2691             if (!EFI_ERROR (Status)) {
   2692               ASSERT (StrPtr != NULL);
   2693               TempLength = StrLen (StrPtr);
   2694               if (OpCode->ValueWidth >= ((TempLength + 1) / 2)) {
   2695                 Value->Type = OpCode->ValueType;
   2696                 TempBuffer = (UINT8 *) &Value->Value;
   2697                 ZeroMem (TempStr, sizeof (TempStr));
   2698                 for (Index = 0; Index < TempLength; Index ++) {
   2699                   TempStr[0] = StrPtr[TempLength - Index - 1];
   2700                   DigitUint8 = (UINT8) StrHexToUint64 (TempStr);
   2701                   if ((Index & 1) == 0) {
   2702                     TempBuffer [Index/2] = DigitUint8;
   2703                   } else {
   2704                     TempBuffer [Index/2] = (UINT8) ((DigitUint8 << 4) + TempBuffer [Index/2]);
   2705                   }
   2706                 }
   2707               }
   2708             }
   2709           }
   2710           break;
   2711         case EFI_HII_VARSTORE_EFI_VARIABLE:
   2712           //
   2713           // Get value from variable.
   2714           //
   2715           TempLength = OpCode->ValueWidth;
   2716           Value->Type = OpCode->ValueType;
   2717           Status = gRT->GetVariable (
   2718                           OpCode->ValueName,
   2719                           &OpCode->VarStorage->Guid,
   2720                           NULL,
   2721                           &TempLength,
   2722                           &Value->Value
   2723                           );
   2724           if (EFI_ERROR (Status)) {
   2725             Value->Type = EFI_IFR_TYPE_UNDEFINED;
   2726             Value->Value.u8 = 0;
   2727           }
   2728           break;
   2729         default:
   2730           //
   2731           // Not recognize storage.
   2732           //
   2733           Status = EFI_UNSUPPORTED;
   2734           goto Done;
   2735         }
   2736       } else {
   2737         //
   2738         // For Time/Date Data
   2739         //
   2740         if (OpCode->ValueType != EFI_IFR_TYPE_DATE && OpCode->ValueType != EFI_IFR_TYPE_TIME) {
   2741           //
   2742           // Only support Data/Time data when storage doesn't exist.
   2743           //
   2744           Status = EFI_UNSUPPORTED;
   2745           goto Done;
   2746         }
   2747         Status = gRT->GetTime (&EfiTime, NULL);
   2748         if (!EFI_ERROR (Status)) {
   2749           if (OpCode->ValueType == EFI_IFR_TYPE_DATE) {
   2750             switch (OpCode->VarStoreInfo.VarOffset) {
   2751             case 0x00:
   2752               Value->Type = EFI_IFR_TYPE_NUM_SIZE_16;
   2753               Value->Value.u16 = EfiTime.Year;
   2754               break;
   2755             case 0x02:
   2756               Value->Type = EFI_IFR_TYPE_NUM_SIZE_8;
   2757               Value->Value.u8 = EfiTime.Month;
   2758               break;
   2759             case 0x03:
   2760               Value->Type = EFI_IFR_TYPE_NUM_SIZE_8;
   2761               Value->Value.u8 = EfiTime.Day;
   2762               break;
   2763             default:
   2764               //
   2765               // Invalid Date field.
   2766               //
   2767               Status = EFI_INVALID_PARAMETER;
   2768               goto Done;
   2769             }
   2770           } else {
   2771             switch (OpCode->VarStoreInfo.VarOffset) {
   2772             case 0x00:
   2773               Value->Type = EFI_IFR_TYPE_NUM_SIZE_8;
   2774               Value->Value.u8 = EfiTime.Hour;
   2775               break;
   2776             case 0x01:
   2777               Value->Type = EFI_IFR_TYPE_NUM_SIZE_8;
   2778               Value->Value.u8 = EfiTime.Minute;
   2779               break;
   2780             case 0x02:
   2781               Value->Type = EFI_IFR_TYPE_NUM_SIZE_8;
   2782               Value->Value.u8 = EfiTime.Second;
   2783               break;
   2784             default:
   2785               //
   2786               // Invalid Time field.
   2787               //
   2788               Status = EFI_INVALID_PARAMETER;
   2789               goto Done;
   2790             }
   2791           }
   2792         }
   2793       }
   2794 
   2795       break;
   2796 
   2797     case EFI_IFR_QUESTION_REF3_OP:
   2798       //
   2799       // EFI_IFR_QUESTION_REF3
   2800       // Pop an expression from the expression stack
   2801       //
   2802       Status = PopExpression (Value);
   2803       if (EFI_ERROR (Status)) {
   2804         goto Done;
   2805       }
   2806 
   2807       //
   2808       // Validate the expression value
   2809       //
   2810       if ((Value->Type > EFI_IFR_TYPE_NUM_SIZE_64) || (Value->Value.u64 > 0xffff)) {
   2811         Value->Type = EFI_IFR_TYPE_UNDEFINED;
   2812         break;
   2813       }
   2814 
   2815       if (OpCode->DevicePath != 0) {
   2816         Value->Type = EFI_IFR_TYPE_UNDEFINED;
   2817 
   2818         StrPtr = GetToken (OpCode->DevicePath, FormSet->HiiHandle);
   2819         if (StrPtr != NULL && mPathFromText != NULL) {
   2820           DevicePath = mPathFromText->ConvertTextToDevicePath(StrPtr);
   2821           if (DevicePath != NULL && GetQuestionValueFromForm(DevicePath, NULL, &OpCode->Guid, Value->Value.u16, &QuestionVal)) {
   2822             Value = &QuestionVal;
   2823           }
   2824           if (DevicePath != NULL) {
   2825             FreePool (DevicePath);
   2826           }
   2827         }
   2828 
   2829         if (StrPtr != NULL) {
   2830           FreePool (StrPtr);
   2831         }
   2832       } else if (IsZeroGuid (&OpCode->Guid)) {
   2833         if (!GetQuestionValueFromForm(NULL, FormSet->HiiHandle, &OpCode->Guid, Value->Value.u16, &QuestionVal)){
   2834           Value->Type = EFI_IFR_TYPE_UNDEFINED;
   2835           break;
   2836         }
   2837         Value = &QuestionVal;
   2838       } else {
   2839         Question = IdToQuestion (FormSet, Form, Value->Value.u16);
   2840         if (Question == NULL) {
   2841           Value->Type = EFI_IFR_TYPE_UNDEFINED;
   2842           break;
   2843         }
   2844 
   2845         //
   2846         // push the questions' value on to the expression stack
   2847         //
   2848         Value = &Question->HiiValue;
   2849       }
   2850       break;
   2851 
   2852     case EFI_IFR_RULE_REF_OP:
   2853       //
   2854       // Find expression for this rule
   2855       //
   2856       RuleExpression = RuleIdToExpression (Form, OpCode->RuleId);
   2857       if (RuleExpression == NULL) {
   2858         Value->Type = EFI_IFR_TYPE_UNDEFINED;
   2859         break;
   2860       }
   2861 
   2862       //
   2863       // Evaluate this rule expression
   2864       //
   2865       Status = EvaluateExpression (FormSet, Form, RuleExpression);
   2866       if (EFI_ERROR (Status) || RuleExpression->Result.Type == EFI_IFR_TYPE_UNDEFINED) {
   2867         Value->Type = EFI_IFR_TYPE_UNDEFINED;
   2868         break;
   2869       }
   2870 
   2871       Value = &RuleExpression->Result;
   2872       break;
   2873 
   2874     case EFI_IFR_STRING_REF1_OP:
   2875       Value->Type = EFI_IFR_TYPE_STRING;
   2876       Value->Value.string = OpCode->Value.Value.string;
   2877       break;
   2878 
   2879     //
   2880     // Constant
   2881     //
   2882     case EFI_IFR_TRUE_OP:
   2883     case EFI_IFR_FALSE_OP:
   2884     case EFI_IFR_ONE_OP:
   2885     case EFI_IFR_ONES_OP:
   2886     case EFI_IFR_UINT8_OP:
   2887     case EFI_IFR_UINT16_OP:
   2888     case EFI_IFR_UINT32_OP:
   2889     case EFI_IFR_UINT64_OP:
   2890     case EFI_IFR_UNDEFINED_OP:
   2891     case EFI_IFR_VERSION_OP:
   2892     case EFI_IFR_ZERO_OP:
   2893       Value = &OpCode->Value;
   2894       break;
   2895 
   2896     //
   2897     // unary-op
   2898     //
   2899     case EFI_IFR_LENGTH_OP:
   2900       Status = PopExpression (Value);
   2901       if (EFI_ERROR (Status)) {
   2902         goto Done;
   2903       }
   2904       if (Value->Type != EFI_IFR_TYPE_STRING && !IsTypeInBuffer (Value)) {
   2905         Value->Type = EFI_IFR_TYPE_UNDEFINED;
   2906         break;
   2907       }
   2908 
   2909       if (Value->Type == EFI_IFR_TYPE_STRING) {
   2910         StrPtr = GetToken (Value->Value.string, FormSet->HiiHandle);
   2911         if (StrPtr == NULL) {
   2912           Status = EFI_INVALID_PARAMETER;
   2913           goto Done;
   2914         }
   2915 
   2916         Value->Type = EFI_IFR_TYPE_NUM_SIZE_64;
   2917         Value->Value.u64 = StrLen (StrPtr);
   2918         FreePool (StrPtr);
   2919       } else {
   2920         Value->Type = EFI_IFR_TYPE_NUM_SIZE_64;
   2921         Value->Value.u64 = GetLengthForValue(Value);
   2922         FreePool (Value->Buffer);
   2923       }
   2924       break;
   2925 
   2926     case EFI_IFR_NOT_OP:
   2927       Status = PopExpression (Value);
   2928       if (EFI_ERROR (Status)) {
   2929         goto Done;
   2930       }
   2931       if (Value->Type != EFI_IFR_TYPE_BOOLEAN) {
   2932         Value->Type = EFI_IFR_TYPE_UNDEFINED;
   2933         break;
   2934       }
   2935       Value->Value.b = (BOOLEAN) (!Value->Value.b);
   2936       break;
   2937 
   2938     case EFI_IFR_QUESTION_REF2_OP:
   2939       //
   2940       // Pop an expression from the expression stack
   2941       //
   2942       Status = PopExpression (Value);
   2943       if (EFI_ERROR (Status)) {
   2944         goto Done;
   2945       }
   2946 
   2947       //
   2948       // Validate the expression value
   2949       //
   2950       if ((Value->Type > EFI_IFR_TYPE_NUM_SIZE_64) || (Value->Value.u64 > 0xffff)) {
   2951         Value->Type = EFI_IFR_TYPE_UNDEFINED;
   2952         break;
   2953       }
   2954 
   2955       Question = IdToQuestion (FormSet, Form, Value->Value.u16);
   2956       if (Question == NULL) {
   2957         Value->Type = EFI_IFR_TYPE_UNDEFINED;
   2958         break;
   2959       }
   2960 
   2961       Value = &Question->HiiValue;
   2962       break;
   2963 
   2964     case EFI_IFR_STRING_REF2_OP:
   2965       //
   2966       // Pop an expression from the expression stack
   2967       //
   2968       Status = PopExpression (Value);
   2969       if (EFI_ERROR (Status)) {
   2970         goto Done;
   2971       }
   2972 
   2973       //
   2974       // Validate the expression value
   2975       //
   2976       if ((Value->Type > EFI_IFR_TYPE_NUM_SIZE_64) || (Value->Value.u64 > 0xffff)) {
   2977         Value->Type = EFI_IFR_TYPE_UNDEFINED;
   2978         break;
   2979       }
   2980 
   2981       Value->Type = EFI_IFR_TYPE_STRING;
   2982       StrPtr = GetToken (Value->Value.u16, FormSet->HiiHandle);
   2983       if (StrPtr == NULL) {
   2984         //
   2985         // If String not exit, push an empty string
   2986         //
   2987         Value->Value.string = NewString (gEmptyString, FormSet->HiiHandle);
   2988       } else {
   2989         Index = (UINT16) Value->Value.u64;
   2990         Value->Value.string = Index;
   2991         FreePool (StrPtr);
   2992       }
   2993       break;
   2994 
   2995     case EFI_IFR_TO_BOOLEAN_OP:
   2996       //
   2997       // Pop an expression from the expression stack
   2998       //
   2999       Status = PopExpression (Value);
   3000       if (EFI_ERROR (Status)) {
   3001         goto Done;
   3002       }
   3003 
   3004       //
   3005       // Convert an expression to a Boolean
   3006       //
   3007       if (Value->Type <= EFI_IFR_TYPE_DATE) {
   3008         //
   3009         // When converting from an unsigned integer, zero will be converted to
   3010         // FALSE and any other value will be converted to TRUE.
   3011         //
   3012         Value->Value.b = (BOOLEAN) (HiiValueToUINT64(Value) != 0);
   3013 
   3014         Value->Type = EFI_IFR_TYPE_BOOLEAN;
   3015       } else if (Value->Type == EFI_IFR_TYPE_STRING) {
   3016         //
   3017         // When converting from a string, if case-insensitive compare
   3018         // with "true" is True, then push True. If a case-insensitive compare
   3019         // with "false" is True, then push False. Otherwise, push Undefined.
   3020         //
   3021         StrPtr = GetToken (Value->Value.string, FormSet->HiiHandle);
   3022         if (StrPtr == NULL) {
   3023           Status = EFI_INVALID_PARAMETER;
   3024           goto Done;
   3025         }
   3026 
   3027         IfrStrToUpper (StrPtr);
   3028         if (StrCmp (StrPtr, L"TRUE") == 0){
   3029           Value->Value.b = TRUE;
   3030           Value->Type = EFI_IFR_TYPE_BOOLEAN;
   3031         } else if (StrCmp (StrPtr, L"FALSE") == 0) {
   3032           Value->Value.b = FALSE;
   3033           Value->Type = EFI_IFR_TYPE_BOOLEAN;
   3034         } else {
   3035           Value->Type = EFI_IFR_TYPE_UNDEFINED;
   3036         }
   3037         FreePool (StrPtr);
   3038       } else if (Value->Type == EFI_IFR_TYPE_BUFFER) {
   3039         //
   3040         // When converting from a buffer, if the buffer is all zeroes,
   3041         // then push False. Otherwise push True.
   3042         //
   3043         for (Index =0; Index < Value->BufferLen; Index ++) {
   3044           if (Value->Buffer[Index] != 0) {
   3045             break;
   3046           }
   3047         }
   3048 
   3049         if (Index >= Value->BufferLen) {
   3050           Value->Value.b = FALSE;
   3051         } else {
   3052           Value->Value.b = TRUE;
   3053         }
   3054         Value->Type = EFI_IFR_TYPE_BOOLEAN;
   3055         FreePool (Value->Buffer);
   3056       }
   3057       break;
   3058 
   3059     case EFI_IFR_TO_STRING_OP:
   3060       Status = IfrToString (FormSet, OpCode->Format, Value);
   3061       break;
   3062 
   3063     case EFI_IFR_TO_UINT_OP:
   3064       Status = IfrToUint (FormSet, Value);
   3065       break;
   3066 
   3067     case EFI_IFR_TO_LOWER_OP:
   3068     case EFI_IFR_TO_UPPER_OP:
   3069       Status = InitializeUnicodeCollationProtocol ();
   3070       if (EFI_ERROR (Status)) {
   3071         goto Done;
   3072       }
   3073 
   3074       Status = PopExpression (Value);
   3075       if (EFI_ERROR (Status)) {
   3076         goto Done;
   3077       }
   3078 
   3079       if (Value->Type != EFI_IFR_TYPE_STRING) {
   3080         Value->Type = EFI_IFR_TYPE_UNDEFINED;
   3081         break;
   3082       }
   3083 
   3084       StrPtr = GetToken (Value->Value.string, FormSet->HiiHandle);
   3085       if (StrPtr == NULL) {
   3086         Status = EFI_NOT_FOUND;
   3087         goto Done;
   3088       }
   3089 
   3090       if (OpCode->Operand == EFI_IFR_TO_LOWER_OP) {
   3091         mUnicodeCollation->StrLwr (mUnicodeCollation, StrPtr);
   3092       } else {
   3093         mUnicodeCollation->StrUpr (mUnicodeCollation, StrPtr);
   3094       }
   3095       Value->Value.string = NewString (StrPtr, FormSet->HiiHandle);
   3096       FreePool (StrPtr);
   3097       break;
   3098 
   3099     case EFI_IFR_BITWISE_NOT_OP:
   3100       //
   3101       // Pop an expression from the expression stack
   3102       //
   3103       Status = PopExpression (Value);
   3104       if (EFI_ERROR (Status)) {
   3105         goto Done;
   3106       }
   3107       if (Value->Type > EFI_IFR_TYPE_DATE) {
   3108         Value->Type = EFI_IFR_TYPE_UNDEFINED;
   3109         break;
   3110       }
   3111 
   3112       Value->Type = EFI_IFR_TYPE_NUM_SIZE_64;
   3113       Value->Value.u64 = ~ HiiValueToUINT64(Value);
   3114       break;
   3115 
   3116     case EFI_IFR_SET_OP:
   3117       //
   3118       // Pop an expression from the expression stack
   3119       //
   3120       Status = PopExpression (Value);
   3121       if (EFI_ERROR (Status)) {
   3122         goto Done;
   3123       }
   3124       Data1.Type = EFI_IFR_TYPE_BOOLEAN;
   3125       Data1.Value.b = FALSE;
   3126       //
   3127       // Set value to var storage buffer
   3128       //
   3129       if (OpCode->VarStorage != NULL) {
   3130         switch (OpCode->VarStorage->Type) {
   3131         case EFI_HII_VARSTORE_BUFFER:
   3132         case EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER:
   3133           CopyMem (OpCode->VarStorage->EditBuffer + OpCode->VarStoreInfo.VarOffset, &Value->Value, OpCode->ValueWidth);
   3134           Data1.Value.b = TRUE;
   3135           break;
   3136         case EFI_HII_VARSTORE_NAME_VALUE:
   3137           if (OpCode->ValueType != EFI_IFR_TYPE_STRING) {
   3138             NameValue = AllocateZeroPool ((OpCode->ValueWidth * 2 + 1) * sizeof (CHAR16));
   3139             ASSERT (NameValue != NULL);
   3140             //
   3141             // Convert Buffer to Hex String
   3142             //
   3143             TempBuffer = (UINT8 *) &Value->Value + OpCode->ValueWidth - 1;
   3144             StrPtr = NameValue;
   3145             for (Index = 0; Index < OpCode->ValueWidth; Index ++, TempBuffer --) {
   3146               StrPtr += UnicodeValueToString (StrPtr, PREFIX_ZERO | RADIX_HEX, *TempBuffer, 2);
   3147             }
   3148             Status = SetValueByName (OpCode->VarStorage, OpCode->ValueName, NameValue, GetSetValueWithEditBuffer, NULL);
   3149             FreePool (NameValue);
   3150             if (!EFI_ERROR (Status)) {
   3151               Data1.Value.b = TRUE;
   3152             }
   3153           }
   3154           break;
   3155         case EFI_HII_VARSTORE_EFI_VARIABLE:
   3156           Status = gRT->SetVariable (
   3157                           OpCode->ValueName,
   3158                           &OpCode->VarStorage->Guid,
   3159                           OpCode->VarStorage->Attributes,
   3160                           OpCode->ValueWidth,
   3161                           &Value->Value
   3162                           );
   3163           if (!EFI_ERROR (Status)) {
   3164             Data1.Value.b = TRUE;
   3165           }
   3166           break;
   3167         default:
   3168           //
   3169           // Not recognize storage.
   3170           //
   3171           Status = EFI_UNSUPPORTED;
   3172           goto Done;
   3173         }
   3174       } else {
   3175         //
   3176         // For Time/Date Data
   3177         //
   3178         if (OpCode->ValueType != EFI_IFR_TYPE_DATE && OpCode->ValueType != EFI_IFR_TYPE_TIME) {
   3179           //
   3180           // Only support Data/Time data when storage doesn't exist.
   3181           //
   3182           Status = EFI_UNSUPPORTED;
   3183           goto Done;
   3184         }
   3185         Status = gRT->GetTime (&EfiTime, NULL);
   3186         if (!EFI_ERROR (Status)) {
   3187           if (OpCode->ValueType == EFI_IFR_TYPE_DATE) {
   3188             switch (OpCode->VarStoreInfo.VarOffset) {
   3189             case 0x00:
   3190               EfiTime.Year = Value->Value.u16;
   3191               break;
   3192             case 0x02:
   3193               EfiTime.Month = Value->Value.u8;
   3194               break;
   3195             case 0x03:
   3196               EfiTime.Day = Value->Value.u8;
   3197               break;
   3198             default:
   3199               //
   3200               // Invalid Date field.
   3201               //
   3202               Status = EFI_INVALID_PARAMETER;
   3203               goto Done;
   3204             }
   3205           } else {
   3206             switch (OpCode->VarStoreInfo.VarOffset) {
   3207             case 0x00:
   3208               EfiTime.Hour = Value->Value.u8;
   3209               break;
   3210             case 0x01:
   3211               EfiTime.Minute = Value->Value.u8;
   3212               break;
   3213             case 0x02:
   3214               EfiTime.Second = Value->Value.u8;
   3215               break;
   3216             default:
   3217               //
   3218               // Invalid Time field.
   3219               //
   3220               Status = EFI_INVALID_PARAMETER;
   3221               goto Done;
   3222             }
   3223           }
   3224           Status = gRT->SetTime (&EfiTime);
   3225           if (!EFI_ERROR (Status)) {
   3226             Data1.Value.b = TRUE;
   3227           }
   3228         }
   3229       }
   3230       Value = &Data1;
   3231       break;
   3232 
   3233     //
   3234     // binary-op
   3235     //
   3236     case EFI_IFR_ADD_OP:
   3237     case EFI_IFR_SUBTRACT_OP:
   3238     case EFI_IFR_MULTIPLY_OP:
   3239     case EFI_IFR_DIVIDE_OP:
   3240     case EFI_IFR_MODULO_OP:
   3241     case EFI_IFR_BITWISE_AND_OP:
   3242     case EFI_IFR_BITWISE_OR_OP:
   3243     case EFI_IFR_SHIFT_LEFT_OP:
   3244     case EFI_IFR_SHIFT_RIGHT_OP:
   3245       //
   3246       // Pop an expression from the expression stack
   3247       //
   3248       Status = PopExpression (&Data2);
   3249       if (EFI_ERROR (Status)) {
   3250         goto Done;
   3251       }
   3252 
   3253       //
   3254       // Pop another expression from the expression stack
   3255       //
   3256       Status = PopExpression (&Data1);
   3257       if (EFI_ERROR (Status)) {
   3258         goto Done;
   3259       }
   3260 
   3261       if (Data2.Type > EFI_IFR_TYPE_DATE) {
   3262         Value->Type = EFI_IFR_TYPE_UNDEFINED;
   3263         break;
   3264       }
   3265 
   3266 
   3267       if (Data1.Type > EFI_IFR_TYPE_DATE) {
   3268         Value->Type = EFI_IFR_TYPE_UNDEFINED;
   3269         break;
   3270       }
   3271 
   3272       Value->Type = EFI_IFR_TYPE_NUM_SIZE_64;
   3273 
   3274       switch (OpCode->Operand) {
   3275         case EFI_IFR_ADD_OP:
   3276           Value->Value.u64 = HiiValueToUINT64(&Data1) + HiiValueToUINT64(&Data2);
   3277           break;
   3278 
   3279         case EFI_IFR_SUBTRACT_OP:
   3280           Value->Value.u64 = HiiValueToUINT64(&Data1) - HiiValueToUINT64(&Data2);
   3281           break;
   3282 
   3283         case EFI_IFR_MULTIPLY_OP:
   3284           Value->Value.u64 = MultU64x32 (HiiValueToUINT64(&Data1), (UINT32) HiiValueToUINT64(&Data2));
   3285           break;
   3286 
   3287         case EFI_IFR_DIVIDE_OP:
   3288           Value->Value.u64 = DivU64x32 (HiiValueToUINT64(&Data1), (UINT32) HiiValueToUINT64(&Data2));
   3289           break;
   3290 
   3291         case EFI_IFR_MODULO_OP:
   3292           DivU64x32Remainder  (HiiValueToUINT64(&Data1), (UINT32) HiiValueToUINT64(&Data2), &TempValue);
   3293           Value->Value.u64 = TempValue;
   3294           break;
   3295 
   3296         case EFI_IFR_BITWISE_AND_OP:
   3297           Value->Value.u64 = HiiValueToUINT64(&Data1) & HiiValueToUINT64(&Data2);
   3298           break;
   3299 
   3300         case EFI_IFR_BITWISE_OR_OP:
   3301           Value->Value.u64 = HiiValueToUINT64(&Data1) | HiiValueToUINT64(&Data2);
   3302           break;
   3303 
   3304         case EFI_IFR_SHIFT_LEFT_OP:
   3305           Value->Value.u64 = LShiftU64 (HiiValueToUINT64(&Data1), (UINTN) HiiValueToUINT64(&Data2));
   3306           break;
   3307 
   3308         case EFI_IFR_SHIFT_RIGHT_OP:
   3309           Value->Value.u64 = RShiftU64 (HiiValueToUINT64(&Data1), (UINTN) HiiValueToUINT64(&Data2));
   3310           break;
   3311 
   3312         default:
   3313           break;
   3314       }
   3315       break;
   3316 
   3317     case EFI_IFR_AND_OP:
   3318     case EFI_IFR_OR_OP:
   3319       //
   3320       // Two Boolean operator
   3321       //
   3322       Status = PopExpression (&Data2);
   3323       if (EFI_ERROR (Status)) {
   3324         goto Done;
   3325       }
   3326 
   3327       //
   3328       // Pop another expression from the expression stack
   3329       //
   3330       Status = PopExpression (&Data1);
   3331       if (EFI_ERROR (Status)) {
   3332         goto Done;
   3333       }
   3334 
   3335       if (Data2.Type != EFI_IFR_TYPE_BOOLEAN) {
   3336         Value->Type = EFI_IFR_TYPE_UNDEFINED;
   3337         break;
   3338       }
   3339 
   3340       if (Data1.Type != EFI_IFR_TYPE_BOOLEAN) {
   3341         Value->Type = EFI_IFR_TYPE_UNDEFINED;
   3342         break;
   3343       }
   3344 
   3345       if (OpCode->Operand == EFI_IFR_AND_OP) {
   3346         Value->Value.b = (BOOLEAN) (Data1.Value.b && Data2.Value.b);
   3347       } else {
   3348         Value->Value.b = (BOOLEAN) (Data1.Value.b || Data2.Value.b);
   3349       }
   3350       break;
   3351 
   3352     case EFI_IFR_EQUAL_OP:
   3353     case EFI_IFR_NOT_EQUAL_OP:
   3354     case EFI_IFR_GREATER_EQUAL_OP:
   3355     case EFI_IFR_GREATER_THAN_OP:
   3356     case EFI_IFR_LESS_EQUAL_OP:
   3357     case EFI_IFR_LESS_THAN_OP:
   3358       //
   3359       // Compare two integer, string, boolean or date/time
   3360       //
   3361       Status = PopExpression (&Data2);
   3362       if (EFI_ERROR (Status)) {
   3363         goto Done;
   3364       }
   3365 
   3366       //
   3367       // Pop another expression from the expression stack
   3368       //
   3369       Status = PopExpression (&Data1);
   3370       if (EFI_ERROR (Status)) {
   3371         goto Done;
   3372       }
   3373 
   3374       if (Data2.Type > EFI_IFR_TYPE_BOOLEAN &&
   3375           Data2.Type != EFI_IFR_TYPE_STRING &&
   3376           !IsTypeInBuffer(&Data2)) {
   3377         Value->Type = EFI_IFR_TYPE_UNDEFINED;
   3378         break;
   3379       }
   3380 
   3381       if (Data1.Type > EFI_IFR_TYPE_BOOLEAN &&
   3382           Data1.Type != EFI_IFR_TYPE_STRING &&
   3383           !IsTypeInBuffer(&Data1)) {
   3384         Value->Type = EFI_IFR_TYPE_UNDEFINED;
   3385         break;
   3386       }
   3387 
   3388       Status = CompareHiiValue (&Data1, &Data2, &Result, FormSet->HiiHandle);
   3389       if (Data1.Type == EFI_IFR_TYPE_BUFFER) {
   3390         FreePool (Data1.Buffer);
   3391       }
   3392       if (Data2.Type == EFI_IFR_TYPE_BUFFER) {
   3393         FreePool (Data2.Buffer);
   3394       }
   3395 
   3396       if (Status == EFI_UNSUPPORTED) {
   3397         Value->Type = EFI_IFR_TYPE_UNDEFINED;
   3398         Status = EFI_SUCCESS;
   3399         break;
   3400       }
   3401 
   3402       if (EFI_ERROR (Status)) {
   3403         goto Done;
   3404       }
   3405 
   3406       switch (OpCode->Operand) {
   3407       case EFI_IFR_EQUAL_OP:
   3408         Value->Value.b = (BOOLEAN) ((Result == 0) ? TRUE : FALSE);
   3409         break;
   3410 
   3411       case EFI_IFR_NOT_EQUAL_OP:
   3412         Value->Value.b = (BOOLEAN) ((Result != 0) ? TRUE : FALSE);
   3413         break;
   3414 
   3415       case EFI_IFR_GREATER_EQUAL_OP:
   3416         Value->Value.b = (BOOLEAN) ((Result >= 0) ? TRUE : FALSE);
   3417         break;
   3418 
   3419       case EFI_IFR_GREATER_THAN_OP:
   3420         Value->Value.b = (BOOLEAN) ((Result > 0) ? TRUE : FALSE);
   3421         break;
   3422 
   3423       case EFI_IFR_LESS_EQUAL_OP:
   3424         Value->Value.b = (BOOLEAN) ((Result <= 0) ? TRUE : FALSE);
   3425         break;
   3426 
   3427       case EFI_IFR_LESS_THAN_OP:
   3428         Value->Value.b = (BOOLEAN) ((Result < 0) ? TRUE : FALSE);
   3429         break;
   3430 
   3431       default:
   3432         break;
   3433       }
   3434       break;
   3435 
   3436     case EFI_IFR_MATCH_OP:
   3437       Status = InitializeUnicodeCollationProtocol ();
   3438       if (EFI_ERROR (Status)) {
   3439         goto Done;
   3440       }
   3441 
   3442       Status = IfrMatch (FormSet, Value);
   3443       break;
   3444 
   3445     case EFI_IFR_MATCH2_OP:
   3446       Status = IfrMatch2 (FormSet, &OpCode->Guid, Value);
   3447       break;
   3448 
   3449     case EFI_IFR_CATENATE_OP:
   3450       Status = IfrCatenate (FormSet, Value);
   3451       break;
   3452 
   3453     //
   3454     // ternary-op
   3455     //
   3456     case EFI_IFR_CONDITIONAL_OP:
   3457       //
   3458       // Pop third expression from the expression stack
   3459       //
   3460       Status = PopExpression (&Data3);
   3461       if (EFI_ERROR (Status)) {
   3462         goto Done;
   3463       }
   3464 
   3465       //
   3466       // Pop second expression from the expression stack
   3467       //
   3468       Status = PopExpression (&Data2);
   3469       if (EFI_ERROR (Status)) {
   3470         goto Done;
   3471       }
   3472 
   3473       //
   3474       // Pop first expression from the expression stack
   3475       //
   3476       Status = PopExpression (&Data1);
   3477       if (EFI_ERROR (Status)) {
   3478         goto Done;
   3479       }
   3480       if (Data1.Type != EFI_IFR_TYPE_BOOLEAN) {
   3481         Value->Type = EFI_IFR_TYPE_UNDEFINED;
   3482         break;
   3483       }
   3484 
   3485       if (Data1.Value.b) {
   3486         Value = &Data3;
   3487       } else {
   3488         Value = &Data2;
   3489       }
   3490       break;
   3491 
   3492     case EFI_IFR_FIND_OP:
   3493       Status = IfrFind (FormSet, OpCode->Format, Value);
   3494       break;
   3495 
   3496     case EFI_IFR_MID_OP:
   3497       Status = IfrMid (FormSet, Value);
   3498       break;
   3499 
   3500     case EFI_IFR_TOKEN_OP:
   3501       Status = IfrToken (FormSet, Value);
   3502       break;
   3503 
   3504     case EFI_IFR_SPAN_OP:
   3505       Status = IfrSpan (FormSet, OpCode->Flags, Value);
   3506       break;
   3507 
   3508     case EFI_IFR_MAP_OP:
   3509       //
   3510       // Pop the check value
   3511       //
   3512       Status = PopExpression (&Data1);
   3513       if (EFI_ERROR (Status)) {
   3514         goto Done;
   3515       }
   3516       //
   3517       // Check MapExpression list is valid.
   3518       //
   3519       if (OpCode->MapExpressionList.ForwardLink == NULL) {
   3520         Status = EFI_INVALID_PARAMETER;
   3521         goto Done;
   3522       }
   3523       //
   3524       // Go through map expression list.
   3525       //
   3526       SubExpressionLink = GetFirstNode(&OpCode->MapExpressionList);
   3527       while (!IsNull (&OpCode->MapExpressionList, SubExpressionLink)) {
   3528         SubExpression = FORM_EXPRESSION_FROM_LINK (SubExpressionLink);
   3529         //
   3530         // Evaluate the first expression in this pair.
   3531         //
   3532         Status = EvaluateExpression (FormSet, Form, SubExpression);
   3533         if (EFI_ERROR (Status)) {
   3534           goto Done;
   3535         }
   3536         //
   3537         // Compare the expression value with current value
   3538         //
   3539         if ((CompareHiiValue (&Data1, &SubExpression->Result, &Result, NULL) == EFI_SUCCESS) && (Result == 0)) {
   3540           //
   3541           // Try get the map value.
   3542           //
   3543           SubExpressionLink = GetNextNode (&OpCode->MapExpressionList, SubExpressionLink);
   3544           if (IsNull (&OpCode->MapExpressionList, SubExpressionLink)) {
   3545             Status = EFI_INVALID_PARAMETER;
   3546             goto Done;
   3547           }
   3548           SubExpression = FORM_EXPRESSION_FROM_LINK (SubExpressionLink);
   3549           Status = EvaluateExpression (FormSet, Form, SubExpression);
   3550           if (EFI_ERROR (Status)) {
   3551             goto Done;
   3552           }
   3553           Value = &SubExpression->Result;
   3554           break;
   3555         }
   3556         //
   3557         // Skip the second expression on this pair.
   3558         //
   3559         SubExpressionLink = GetNextNode (&OpCode->MapExpressionList, SubExpressionLink);
   3560         if (IsNull (&OpCode->MapExpressionList, SubExpressionLink)) {
   3561           Status = EFI_INVALID_PARAMETER;
   3562           goto Done;
   3563         }
   3564         //
   3565         // Goto the first expression on next pair.
   3566         //
   3567         SubExpressionLink = GetNextNode (&OpCode->MapExpressionList, SubExpressionLink);
   3568       }
   3569 
   3570       //
   3571       // No map value is found.
   3572       //
   3573       if (IsNull (&OpCode->MapExpressionList, SubExpressionLink)) {
   3574         Value->Type = EFI_IFR_TYPE_UNDEFINED;
   3575         Value->Value.u8 = 0;
   3576       }
   3577       break;
   3578 
   3579     default:
   3580       break;
   3581     }
   3582     if (EFI_ERROR (Status) || Value->Type == EFI_IFR_TYPE_UNDEFINED) {
   3583       goto Done;
   3584     }
   3585 
   3586     Status = PushExpression (Value);
   3587     if (EFI_ERROR (Status)) {
   3588       goto Done;
   3589     }
   3590   }
   3591 
   3592   //
   3593   // Pop the final result from expression stack
   3594   //
   3595   Value = &Data1;
   3596   Status = PopExpression (Value);
   3597   if (EFI_ERROR (Status)) {
   3598     goto Done;
   3599   }
   3600 
   3601   //
   3602   // After evaluating an expression, there should be only one value left on the expression stack
   3603   //
   3604   if (PopExpression (Value) != EFI_ACCESS_DENIED) {
   3605     Status = EFI_INVALID_PARAMETER;
   3606   }
   3607 
   3608 Done:
   3609   RestoreExpressionEvaluationStackOffset (StackOffset);
   3610   if (!EFI_ERROR (Status)) {
   3611     CopyMem (&Expression->Result, Value, sizeof (EFI_HII_VALUE));
   3612   }
   3613 
   3614   return Status;
   3615 }
   3616 
   3617 /**
   3618   Check whether the result is TRUE or FALSE.
   3619 
   3620   For the EFI_HII_VALUE value type is numeric, return TRUE if the
   3621   value is not 0.
   3622 
   3623   @param  Result             Input the result data.
   3624 
   3625   @retval TRUE               The result is TRUE.
   3626   @retval FALSE              The result is FALSE.
   3627 
   3628 **/
   3629 BOOLEAN
   3630 IsTrue (
   3631   IN EFI_HII_VALUE     *Result
   3632   )
   3633 {
   3634   switch (Result->Type) {
   3635   case EFI_IFR_TYPE_BOOLEAN:
   3636     return Result->Value.b;
   3637 
   3638   case EFI_IFR_TYPE_NUM_SIZE_8:
   3639     return (BOOLEAN)(Result->Value.u8 != 0);
   3640 
   3641   case EFI_IFR_TYPE_NUM_SIZE_16:
   3642     return (BOOLEAN)(Result->Value.u16 != 0);
   3643 
   3644   case EFI_IFR_TYPE_NUM_SIZE_32:
   3645     return (BOOLEAN)(Result->Value.u32 != 0);
   3646 
   3647   case EFI_IFR_TYPE_NUM_SIZE_64:
   3648     return (BOOLEAN)(Result->Value.u64 != 0);
   3649 
   3650   default:
   3651     return FALSE;
   3652   }
   3653 }
   3654 
   3655 /**
   3656   Return the result of the expression list. Check the expression list and
   3657   return the highest priority express result.
   3658   Priority: DisableIf > SuppressIf > GrayOutIf > FALSE
   3659 
   3660   @param  ExpList             The input expression list.
   3661   @param  Evaluate            Whether need to evaluate the expression first.
   3662   @param  FormSet             FormSet associated with this expression.
   3663   @param  Form                Form associated with this expression.
   3664 
   3665   @retval EXPRESS_RESULT      Return the higher priority express result.
   3666                               DisableIf > SuppressIf > GrayOutIf > FALSE
   3667 
   3668 **/
   3669 EXPRESS_RESULT
   3670 EvaluateExpressionList (
   3671   IN FORM_EXPRESSION_LIST *ExpList,
   3672   IN BOOLEAN              Evaluate,
   3673   IN FORM_BROWSER_FORMSET *FormSet, OPTIONAL
   3674   IN FORM_BROWSER_FORM    *Form OPTIONAL
   3675   )
   3676 {
   3677   UINTN              Index;
   3678   EXPRESS_RESULT     ReturnVal;
   3679   EXPRESS_RESULT     CompareOne;
   3680   EFI_STATUS         Status;
   3681 
   3682   if (ExpList == NULL) {
   3683     return ExpressFalse;
   3684   }
   3685 
   3686   ASSERT(ExpList->Signature == FORM_EXPRESSION_LIST_SIGNATURE);
   3687   Index     = 0;
   3688 
   3689   //
   3690   // Check whether need to evaluate the expression first.
   3691   //
   3692   if (Evaluate) {
   3693     while (ExpList->Count > Index) {
   3694       Status = EvaluateExpression (FormSet, Form, ExpList->Expression[Index++]);
   3695       if (EFI_ERROR (Status)) {
   3696         return ExpressFalse;
   3697       }
   3698     }
   3699   }
   3700 
   3701   //
   3702   // Run the list of expressions.
   3703   //
   3704   ReturnVal = ExpressFalse;
   3705   for (Index = 0; Index < ExpList->Count; Index++) {
   3706     if (IsTrue (&ExpList->Expression[Index]->Result)) {
   3707       switch (ExpList->Expression[Index]->Type) {
   3708         case EFI_HII_EXPRESSION_SUPPRESS_IF:
   3709           CompareOne = ExpressSuppress;
   3710           break;
   3711 
   3712         case EFI_HII_EXPRESSION_GRAY_OUT_IF:
   3713           CompareOne = ExpressGrayOut;
   3714           break;
   3715 
   3716         case EFI_HII_EXPRESSION_DISABLE_IF:
   3717           CompareOne = ExpressDisable;
   3718           break;
   3719 
   3720         default:
   3721           return ExpressFalse;
   3722       }
   3723 
   3724       ReturnVal = ReturnVal < CompareOne ? CompareOne : ReturnVal;
   3725     }
   3726   }
   3727 
   3728   return ReturnVal;
   3729 }
   3730