1/** @file
2Utility functions for expression evaluation.
3
4Copyright (c) 2007 - 2015, Intel Corporation. All rights reserved.<BR>
5This program and the accompanying materials
6are licensed and made available under the terms and conditions of the BSD License
7which accompanies this distribution.  The full text of the license may be found at
8http://opensource.org/licenses/bsd-license.php
9
10THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11WITHOUT 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//
20EFI_HII_VALUE *mOpCodeScopeStack = NULL;
21EFI_HII_VALUE *mOpCodeScopeStackEnd = NULL;
22EFI_HII_VALUE *mOpCodeScopeStackPointer = NULL;
23
24EFI_HII_VALUE *mExpressionEvaluationStack = NULL;
25EFI_HII_VALUE *mExpressionEvaluationStackEnd = NULL;
26EFI_HII_VALUE *mExpressionEvaluationStackPointer = NULL;
27UINTN         mExpressionEvaluationStackOffset = 0;
28
29EFI_HII_VALUE *mCurrentExpressionStack = NULL;
30EFI_HII_VALUE *mCurrentExpressionEnd = NULL;
31EFI_HII_VALUE *mCurrentExpressionPointer = NULL;
32
33EFI_HII_VALUE *mMapExpressionListStack = NULL;
34EFI_HII_VALUE *mMapExpressionListEnd = NULL;
35EFI_HII_VALUE *mMapExpressionListPointer = NULL;
36
37FORM_EXPRESSION   **mFormExpressionStack = NULL;
38FORM_EXPRESSION   **mFormExpressionEnd = NULL;
39FORM_EXPRESSION   **mFormExpressionPointer = NULL;
40
41FORM_EXPRESSION   **mStatementExpressionStack = NULL;
42FORM_EXPRESSION   **mStatementExpressionEnd = NULL;
43FORM_EXPRESSION   **mStatementExpressionPointer = NULL;
44
45FORM_EXPRESSION   **mOptionExpressionStack = NULL;
46FORM_EXPRESSION   **mOptionExpressionEnd = NULL;
47FORM_EXPRESSION   **mOptionExpressionPointer = NULL;
48
49
50//
51// Unicode collation protocol interface
52//
53EFI_UNICODE_COLLATION_PROTOCOL *mUnicodeCollation = NULL;
54EFI_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**/
70EFI_STATUS
71GrowStack (
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**/
129EFI_STATUS
130PushStack (
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**/
178EFI_STATUS
179PopStack (
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**/
205VOID
206ResetCurrentExpressionStack (
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**/
226EFI_STATUS
227PushCurrentExpression (
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**/
254EFI_STATUS
255PopCurrentExpression (
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**/
277VOID
278ResetMapExpressionListStack (
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**/
301EFI_STATUS
302GrowConditionalStack (
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**/
360EFI_STATUS
361PushConditionalStack (
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**/
404EFI_STATUS
405PopConditionalStack (
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**/
437INTN
438GetConditionalExpressionCount (
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**/
464FORM_EXPRESSION **
465GetConditionalExpressionList (
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**/
494EFI_STATUS
495PushConditionalExpression (
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**/
538EFI_STATUS
539PopConditionalExpression (
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**/
583EFI_STATUS
584PushMapExpressionList (
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**/
611EFI_STATUS
612PopMapExpressionList (
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**/
634VOID
635ResetScopeStack (
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**/
653EFI_STATUS
654PushScope (
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**/
682EFI_STATUS
683PopScope (
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**/
712EFI_STATUS
713PushExpression (
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**/
735EFI_STATUS
736PopExpression (
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**/
752UINTN
753SaveExpressionEvaluationStackOffset (
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**/
768VOID
769RestoreExpressionEvaluationStackOffset (
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**/
786FORM_BROWSER_FORM *
787IdToForm (
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**/
820FORM_BROWSER_STATEMENT *
821IdToQuestion2 (
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**/
862FORM_BROWSER_STATEMENT *
863IdToQuestion (
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**/
917FORM_EXPRESSION *
918RuleIdToExpression (
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**/
948EFI_STATUS
949InitializeUnicodeCollationProtocol (
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**/
978VOID
979IfrStrToUpper (
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**/
1003BOOLEAN
1004IsTypeInBuffer (
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**/
1029BOOLEAN
1030IsTypeInUINT64 (
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**/
1058UINT16
1059GetLengthForValue (
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**/
1092UINT8 *
1093GetBufferForValue (
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**/
1126EFI_STATUS
1127IfrToString (
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**/
1239EFI_STATUS
1240IfrToUint (
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**/
1312EFI_STATUS
1313IfrCatenate (
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  }
1391Done:
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**/
1422EFI_STATUS
1423IfrMatch (
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
1469Done:
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**/
1491EFI_STATUS
1492IfrMatch2 (
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
1639Done:
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**/
1666EFI_STATUS
1667IfrFind (
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
1742Done:
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**/
1764EFI_STATUS
1765IfrMid (
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**/
1865EFI_STATUS
1866IfrToken (
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
1956Done:
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**/
1979EFI_STATUS
1980IfrSpan (
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
2075Done:
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**/
2093VOID
2094ExtendValueToU64 (
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**/
2141UINT64
2142HiiValueToUINT64 (
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**/
2198EFI_STATUS
2199CompareHiiValue (
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**/
2298BOOLEAN
2299CheckUserPrivilege (
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**/
2405BOOLEAN
2406GetQuestionValueFromForm (
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
2494Done:
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**/
2523EFI_STATUS
2524EvaluateExpression (
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 (CompareGuid (&OpCode->Guid, &gZeroGuid) != 0) {
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 (Value != 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
3608Done:
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**/
3629BOOLEAN
3630IsTrue (
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**/
3669EXPRESS_RESULT
3670EvaluateExpressionList (
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