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