adeada2b292a41141d5f12e17b682be626ce185d
[people/mcb30/edk2.git] / edk2 / MdeModulePkg / Universal / SetupBrowserDxe / Expression.c
1 /** @file
2
3 Copyright (c) 2007, Intel Corporation
4 All rights reserved. This program and the accompanying materials
5 are licensed and made available under the terms and conditions of the BSD License
6 which accompanies this distribution.  The full text of the license may be found at
7 http://opensource.org/licenses/bsd-license.php
8
9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
11
12 Module Name:
13
14   Expression.c
15
16 Abstract:
17
18   Expression evaluation.
19
20
21 **/
22
23 #include "Ui.h"
24 #include "Setup.h"
25
26 //
27 // Global stack used to evaluate boolean expresions
28 //
29 EFI_HII_VALUE *mOpCodeScopeStack = NULL;
30 EFI_HII_VALUE *mOpCodeScopeStackEnd = NULL;
31 EFI_HII_VALUE *mOpCodeScopeStackPointer = NULL;
32
33 EFI_HII_VALUE *mExpressionEvaluationStack = NULL;
34 EFI_HII_VALUE *mExpressionEvaluationStackEnd = NULL;
35 EFI_HII_VALUE *mExpressionEvaluationStackPointer = NULL;
36
37 //
38 // Unicode collation protocol interface
39 //
40 EFI_UNICODE_COLLATION_PROTOCOL *mUnicodeCollation = NULL;
41
42
43 /**
44   Grow size of the stack
45
46   @param  Stack                  On input: old stack; On output: new stack
47   @param  StackPtr               On input: old stack pointer; On output: new stack
48                                  pointer
49   @param  StackPtr               On input: old stack end; On output: new stack end
50
51   @retval EFI_SUCCESS            Grow stack success.
52   @retval EFI_OUT_OF_RESOURCES   No enough memory for stack space.
53
54 **/
55 STATIC
56 EFI_STATUS
57 GrowStack (
58   IN OUT EFI_HII_VALUE  **Stack,
59   IN OUT EFI_HII_VALUE  **StackPtr,
60   IN OUT EFI_HII_VALUE  **StackEnd
61   )
62 {
63   UINTN           Size;
64   EFI_HII_VALUE  *NewStack;
65
66   Size = EXPRESSION_STACK_SIZE_INCREMENT;
67   if (*StackPtr != NULL) {
68     Size = Size + (*StackEnd - *Stack);
69   }
70
71   NewStack = AllocatePool (Size * sizeof (EFI_HII_VALUE));
72   if (NewStack == NULL) {
73     return EFI_OUT_OF_RESOURCES;
74   }
75
76   if (*StackPtr != NULL) {
77     //
78     // Copy from Old Stack to the New Stack
79     //
80     CopyMem (
81       NewStack,
82       *Stack,
83       (*StackEnd - *Stack) * sizeof (EFI_HII_VALUE)
84       );
85
86     //
87     // Free The Old Stack
88     //
89     gBS->FreePool (*Stack);
90   }
91
92   //
93   // Make the Stack pointer point to the old data in the new stack
94   //
95   *StackPtr = NewStack + (*StackPtr - *Stack);
96   *Stack    = NewStack;
97   *StackEnd = NewStack + Size;
98
99   return EFI_SUCCESS;
100 }
101
102
103 /**
104   Push an element onto the Boolean Stack
105
106   @param  Stack                  On input: old stack; On output: new stack
107   @param  StackPtr               On input: old stack pointer; On output: new stack
108                                  pointer
109   @param  StackPtr               On input: old stack end; On output: new stack end
110   @param  Data                   Data to push.
111
112   @retval EFI_SUCCESS            Push stack success.
113
114 **/
115 EFI_STATUS
116 PushStack (
117   IN OUT EFI_HII_VALUE       **Stack,
118   IN OUT EFI_HII_VALUE       **StackPtr,
119   IN OUT EFI_HII_VALUE       **StackEnd,
120   IN EFI_HII_VALUE           *Data
121   )
122 {
123   EFI_STATUS  Status;
124
125   //
126   // Check for a stack overflow condition
127   //
128   if (*StackPtr >= *StackEnd) {
129     //
130     // Grow the stack
131     //
132     Status = GrowStack (Stack, StackPtr, StackEnd);
133     if (EFI_ERROR (Status)) {
134       return Status;
135     }
136   }
137
138   //
139   // Push the item onto the stack
140   //
141   CopyMem (*StackPtr, Data, sizeof (EFI_HII_VALUE));
142   *StackPtr = *StackPtr + 1;
143
144   return EFI_SUCCESS;
145 }
146
147
148 /**
149   Pop an element from the stack.
150
151   @param  Stack                  On input: old stack; On output: new stack
152   @param  StackPtr               On input: old stack pointer; On output: new stack
153                                  pointer
154   @param  StackPtr               On input: old stack end; On output: new stack end
155   @param  Data                   Data to pop.
156
157   @retval EFI_SUCCESS            The value was popped onto the stack.
158   @retval EFI_ACCESS_DENIED      The pop operation underflowed the stack
159
160 **/
161 EFI_STATUS
162 PopStack (
163   IN OUT EFI_HII_VALUE       **Stack,
164   IN OUT EFI_HII_VALUE       **StackPtr,
165   IN OUT EFI_HII_VALUE       **StackEnd,
166   OUT EFI_HII_VALUE          *Data
167   )
168 {
169   //
170   // Check for a stack underflow condition
171   //
172   if (*StackPtr == *Stack) {
173     return EFI_ACCESS_DENIED;
174   }
175
176   //
177   // Pop the item off the stack
178   //
179   *StackPtr = *StackPtr - 1;
180   CopyMem (Data, *StackPtr, sizeof (EFI_HII_VALUE));
181   return EFI_SUCCESS;
182 }
183
184
185 /**
186   Reset stack pointer to begin of the stack.
187
188   None.
189
190   @return None.
191
192 **/
193 VOID
194 ResetScopeStack (
195   VOID
196   )
197 {
198   mOpCodeScopeStackPointer = mOpCodeScopeStack;
199 }
200
201
202 /**
203   Push an Operand onto the Stack
204
205   @param  Operand                Operand to push.
206
207   @retval EFI_SUCCESS            The value was pushed onto the stack.
208   @retval EFI_OUT_OF_RESOURCES   There is not enough system memory to grow the
209                                  stack.
210
211 **/
212 EFI_STATUS
213 PushScope (
214   IN UINT8   Operand
215   )
216 {
217   EFI_HII_VALUE  Data;
218
219   Data.Type = EFI_IFR_TYPE_NUM_SIZE_8;
220   Data.Value.u8 = Operand;
221
222   return PushStack (
223            &mOpCodeScopeStack,
224            &mOpCodeScopeStackPointer,
225            &mOpCodeScopeStackEnd,
226            &Data
227            );
228 }
229
230
231 /**
232   Pop an Operand from the Stack
233
234   @param  Operand                Operand to pop.
235
236   @retval EFI_SUCCESS            The value was pushed onto the stack.
237   @retval EFI_OUT_OF_RESOURCES   There is not enough system memory to grow the
238                                  stack.
239
240 **/
241 EFI_STATUS
242 PopScope (
243   OUT UINT8     *Operand
244   )
245 {
246   EFI_STATUS     Status;
247   EFI_HII_VALUE  Data;
248
249   Status = PopStack (
250              &mOpCodeScopeStack,
251              &mOpCodeScopeStackPointer,
252              &mOpCodeScopeStackEnd,
253              &Data
254              );
255
256   *Operand = Data.Value.u8;
257
258   return Status;
259 }
260
261
262 /**
263   Reset stack pointer to begin of the stack.
264
265   None.
266
267   @return None.
268
269 **/
270 VOID
271 ResetExpressionStack (
272   VOID
273   )
274 {
275   mExpressionEvaluationStackPointer = mExpressionEvaluationStack;
276 }
277
278
279 /**
280   Push an Expression value onto the Stack
281
282   @param  Value                  Expression value to push.
283
284   @retval EFI_SUCCESS            The value was pushed onto the stack.
285   @retval EFI_OUT_OF_RESOURCES   There is not enough system memory to grow the
286                                  stack.
287
288 **/
289 EFI_STATUS
290 PushExpression (
291   IN EFI_HII_VALUE  *Value
292   )
293 {
294   return PushStack (
295            &mExpressionEvaluationStack,
296            &mExpressionEvaluationStackPointer,
297            &mExpressionEvaluationStackEnd,
298            Value
299            );
300 }
301
302
303 /**
304   Pop an Expression value from the stack.
305
306   @param  Value                  Expression value to pop.
307
308   @retval EFI_SUCCESS            The value was popped onto the stack.
309   @retval EFI_ACCESS_DENIED      The pop operation underflowed the stack
310
311 **/
312 EFI_STATUS
313 PopExpression (
314   OUT EFI_HII_VALUE  *Value
315   )
316 {
317   return PopStack (
318            &mExpressionEvaluationStack,
319            &mExpressionEvaluationStackPointer,
320            &mExpressionEvaluationStackEnd,
321            Value
322            );
323 }
324
325
326 /**
327   Get Form given its FormId.
328
329   @param  FormSet                The formset which contains this form.
330   @param  FormId                 Id of this form.
331
332   @retval Pointer                The form.
333   @retval NULL                   Specified Form is not found in the formset.
334
335 **/
336 FORM_BROWSER_FORM *
337 IdToForm (
338   IN FORM_BROWSER_FORMSET  *FormSet,
339   IN UINT16                FormId
340 )
341 {
342   LIST_ENTRY         *Link;
343   FORM_BROWSER_FORM  *Form;
344
345   Link = GetFirstNode (&FormSet->FormListHead);
346   while (!IsNull (&FormSet->FormListHead, Link)) {
347     Form = FORM_BROWSER_FORM_FROM_LINK (Link);
348
349     if (Form->FormId == FormId) {
350       return Form;
351     }
352
353     Link = GetNextNode (&FormSet->FormListHead, Link);
354   }
355
356   return NULL;
357 }
358
359
360 /**
361   Search a Question in Form scope using its QuestionId.
362
363   @param  Form                   The form which contains this Question.
364   @param  QuestionId             Id of this Question.
365
366   @retval Pointer                The Question.
367   @retval NULL                   Specified Question not found in the form.
368
369 **/
370 FORM_BROWSER_STATEMENT *
371 IdToQuestion2 (
372   IN FORM_BROWSER_FORM  *Form,
373   IN UINT16             QuestionId
374   )
375 {
376   LIST_ENTRY              *Link;
377   FORM_BROWSER_STATEMENT  *Question;
378
379   if (QuestionId == 0) {
380     //
381     // The value of zero is reserved
382     //
383     return NULL;
384   }
385
386   Link = GetFirstNode (&Form->StatementListHead);
387   while (!IsNull (&Form->StatementListHead, Link)) {
388     Question = FORM_BROWSER_STATEMENT_FROM_LINK (Link);
389
390     if (Question->QuestionId == QuestionId) {
391       return Question;
392     }
393
394     Link = GetNextNode (&Form->StatementListHead, Link);
395   }
396
397   return NULL;
398 }
399
400
401 /**
402   Search a Question in Formset scope using its QuestionId.
403
404   @param  FormSet                The formset which contains this form.
405   @param  Form                   The form which contains this Question.
406   @param  QuestionId             Id of this Question.
407
408   @retval Pointer                The Question.
409   @retval NULL                   Specified Question not found in the form.
410
411 **/
412 FORM_BROWSER_STATEMENT *
413 IdToQuestion (
414   IN FORM_BROWSER_FORMSET  *FormSet,
415   IN FORM_BROWSER_FORM     *Form,
416   IN UINT16                QuestionId
417   )
418 {
419   LIST_ENTRY              *Link;
420   FORM_BROWSER_STATEMENT  *Question;
421
422   //
423   // Search in the form scope first
424   //
425   Question = IdToQuestion2 (Form, QuestionId);
426   if (Question != NULL) {
427     return Question;
428   }
429
430   //
431   // Search in the formset scope
432   //
433   Link = GetFirstNode (&FormSet->FormListHead);
434   while (!IsNull (&FormSet->FormListHead, Link)) {
435     Form = FORM_BROWSER_FORM_FROM_LINK (Link);
436
437     Question = IdToQuestion2 (Form, QuestionId);
438     if (Question != NULL) {
439       return Question;
440     }
441
442     Link = GetNextNode (&FormSet->FormListHead, Link);
443   }
444
445   return NULL;
446 }
447
448
449 /**
450   Get Expression given its RuleId.
451
452   @param  Form                   The form which contains this Expression.
453   @param  RuleId                 Id of this Expression.
454
455   @retval Pointer                The Expression.
456   @retval NULL                   Specified Expression not found in the form.
457
458 **/
459 FORM_EXPRESSION *
460 RuleIdToExpression (
461   IN FORM_BROWSER_FORM  *Form,
462   IN UINT8              RuleId
463   )
464 {
465   LIST_ENTRY       *Link;
466   FORM_EXPRESSION  *Expression;
467
468   Link = GetFirstNode (&Form->ExpressionListHead);
469   while (!IsNull (&Form->ExpressionListHead, Link)) {
470     Expression = FORM_EXPRESSION_FROM_LINK (Link);
471
472     if (Expression->Type == EFI_HII_EXPRESSION_RULE && Expression->RuleId == RuleId) {
473       return Expression;
474     }
475
476     Link = GetNextNode (&Form->ExpressionListHead, Link);
477   }
478
479   return NULL;
480 }
481
482
483 /**
484   Locate the Unicode Collation Protocol interface for later use.
485
486   None.
487
488   @retval EFI_SUCCESS            Protocol interface initialize success.
489   @retval Other                  Protocol interface initialize failed.
490
491 **/
492 EFI_STATUS
493 InitializeUnicodeCollationProtocol (
494   VOID
495   )
496 {
497   EFI_STATUS  Status;
498
499   if (mUnicodeCollation != NULL) {
500     return EFI_SUCCESS;
501   }
502
503   //
504   // BUGBUG: Proper impelmentation is to locate all Unicode Collation Protocol
505   // instances first and then select one which support English language.
506   // Current implementation just pick the first instance.
507   //
508   Status = gBS->LocateProtocol (
509                   &gEfiUnicodeCollation2ProtocolGuid,
510                   NULL,
511                   (VOID **) &mUnicodeCollation
512                   );
513   return Status;
514 }
515
516 VOID
517 IfrStrToUpper (
518   CHAR16                   *String
519   )
520 {
521   while (*String != 0) {
522     if ((*String >= 'a') && (*String <= 'z')) {
523       *String = (UINT16) ((*String) & ((UINT16) ~0x20));
524     }
525     String++;
526   }
527 }
528
529
530 /**
531   Evaluate opcode EFI_IFR_TO_STRING.
532
533   @param  FormSet                Formset which contains this opcode.
534   @param  Format                 String format in EFI_IFR_TO_STRING.
535   @param  Result                 Evaluation result for this opcode.
536
537   @retval EFI_SUCCESS            Opcode evaluation success.
538   @retval Other                  Opcode evaluation failed.
539
540 **/
541 EFI_STATUS
542 IfrToString (
543   IN FORM_BROWSER_FORMSET  *FormSet,
544   IN UINT8                 Format,
545   OUT  EFI_HII_VALUE       *Result
546   )
547 {
548   EFI_STATUS     Status;
549   EFI_HII_VALUE  Value;
550   CHAR16         *String;
551   CHAR16         *PrintFormat;
552   CHAR16         Buffer[MAXIMUM_VALUE_CHARACTERS];
553   UINTN          BufferSize;
554
555   Status = PopExpression (&Value);
556   if (EFI_ERROR (Status)) {
557     return Status;
558   }
559
560   switch (Value.Type) {
561   case EFI_IFR_TYPE_NUM_SIZE_8:
562   case EFI_IFR_TYPE_NUM_SIZE_16:
563   case EFI_IFR_TYPE_NUM_SIZE_32:
564   case EFI_IFR_TYPE_NUM_SIZE_64:
565     BufferSize = MAXIMUM_VALUE_CHARACTERS * sizeof (CHAR16);
566     switch (Format) {
567     case EFI_IFR_STRING_UNSIGNED_DEC:
568     case EFI_IFR_STRING_SIGNED_DEC:
569       PrintFormat = L"%ld";
570       break;
571
572     case EFI_IFR_STRING_LOWERCASE_HEX:
573       PrintFormat = L"%lx";
574       break;
575
576     case EFI_IFR_STRING_UPPERCASE_HEX:
577       PrintFormat = L"%lX";
578       break;
579
580     default:
581       return EFI_UNSUPPORTED;
582     }
583     UnicodeSPrint (Buffer, BufferSize, PrintFormat, Value.Value.u64);
584     String = Buffer;
585     break;
586
587   case EFI_IFR_TYPE_STRING:
588     CopyMem (Result, &Value, sizeof (EFI_HII_VALUE));
589     return EFI_SUCCESS;
590
591   case EFI_IFR_TYPE_BOOLEAN:
592     String = (Value.Value.b) ? L"True" : L"False";
593     break;
594
595   default:
596     return EFI_UNSUPPORTED;
597   }
598
599   Result->Type = EFI_IFR_TYPE_STRING;
600   Result->Value.string = NewString (String, FormSet->HiiHandle);
601   return EFI_SUCCESS;
602 }
603
604
605 /**
606   Evaluate opcode EFI_IFR_TO_UINT.
607
608   @param  FormSet                Formset which contains this opcode.
609   @param  Result                 Evaluation result for this opcode.
610
611   @retval EFI_SUCCESS            Opcode evaluation success.
612   @retval Other                  Opcode evaluation failed.
613
614 **/
615 EFI_STATUS
616 IfrToUint (
617   IN FORM_BROWSER_FORMSET  *FormSet,
618   OUT  EFI_HII_VALUE       *Result
619   )
620 {
621   EFI_STATUS     Status;
622   EFI_HII_VALUE  Value;
623   CHAR16         *String;
624   CHAR16         *StringPtr;
625   UINTN          BufferSize;
626
627   Status = PopExpression (&Value);
628   if (EFI_ERROR (Status)) {
629     return Status;
630   }
631
632   if (Value.Type >= EFI_IFR_TYPE_OTHER) {
633     return EFI_UNSUPPORTED;
634   }
635
636   Status = EFI_SUCCESS;
637   if (Value.Type == EFI_IFR_TYPE_STRING) {
638     String = GetToken (Value.Value.string, FormSet->HiiHandle);
639     if (String == NULL) {
640       return EFI_NOT_FOUND;
641     }
642
643     IfrStrToUpper (String);
644     StringPtr = StrStr (String, L"0X");
645     if (StringPtr != NULL) {
646       //
647       // Hex string
648       //
649       BufferSize = sizeof (UINT64);
650       Status = R8_HexStringToBuf ((UINT8 *) &Result->Value.u64, &BufferSize, StringPtr + 2, NULL);
651     } else {
652       //
653       // BUGBUG: Need handle decimal string
654       //
655     }
656     gBS->FreePool (String);
657   } else {
658     CopyMem (Result, &Value, sizeof (EFI_HII_VALUE));
659   }
660
661   Result->Type = EFI_IFR_TYPE_NUM_SIZE_64;
662   return Status;
663 }
664
665
666 /**
667   Evaluate opcode EFI_IFR_CATENATE.
668
669   @param  FormSet                Formset which contains this opcode.
670   @param  Result                 Evaluation result for this opcode.
671
672   @retval EFI_SUCCESS            Opcode evaluation success.
673   @retval Other                  Opcode evaluation failed.
674
675 **/
676 EFI_STATUS
677 IfrCatenate (
678   IN FORM_BROWSER_FORMSET  *FormSet,
679   OUT  EFI_HII_VALUE       *Result
680   )
681 {
682   EFI_STATUS     Status;
683   EFI_HII_VALUE  Value;
684   CHAR16         *String[2];
685   UINTN          Index;
686   CHAR16         *StringPtr;
687   UINTN          Size;
688
689   //
690   // String[0] - The second string
691   // String[1] - The first string
692   //
693   String[0] = NULL;
694   String[1] = NULL;
695   StringPtr = NULL;
696   Status = EFI_SUCCESS;
697
698   for (Index = 0; Index < 2; Index++) {
699     Status = PopExpression (&Value);
700     if (EFI_ERROR (Status)) {
701       goto Done;
702     }
703
704     if (Value.Type != EFI_IFR_TYPE_STRING) {
705       Status = EFI_UNSUPPORTED;
706       goto Done;
707     }
708
709     String[Index] = GetToken (Value.Value.string, FormSet->HiiHandle);
710     if (String== NULL) {
711       Status = EFI_NOT_FOUND;
712       goto Done;
713     }
714   }
715
716   Size = StrSize (String[0]);
717   StringPtr= AllocatePool (StrSize (String[1]) + Size);
718   ASSERT (StringPtr != NULL);
719   StrCpy (StringPtr, String[1]);
720   StrCat (StringPtr, String[0]);
721
722   Result->Type = EFI_IFR_TYPE_STRING;
723   Result->Value.string = NewString (StringPtr, FormSet->HiiHandle);
724
725 Done:
726   SafeFreePool (String[0]);
727   SafeFreePool (String[1]);
728   SafeFreePool (StringPtr);
729
730   return Status;
731 }
732
733
734 /**
735   Evaluate opcode EFI_IFR_MATCH.
736
737   @param  FormSet                Formset which contains this opcode.
738   @param  Result                 Evaluation result for this opcode.
739
740   @retval EFI_SUCCESS            Opcode evaluation success.
741   @retval Other                  Opcode evaluation failed.
742
743 **/
744 EFI_STATUS
745 IfrMatch (
746   IN FORM_BROWSER_FORMSET  *FormSet,
747   OUT  EFI_HII_VALUE       *Result
748   )
749 {
750   EFI_STATUS     Status;
751   EFI_HII_VALUE  Value;
752   CHAR16         *String[2];
753   UINTN          Index;
754
755   //
756   // String[0] - The string to search
757   // String[1] - pattern
758   //
759   String[0] = NULL;
760   String[1] = NULL;
761   Status = EFI_SUCCESS;
762   for (Index = 0; Index < 2; Index++) {
763     Status = PopExpression (&Value);
764     if (EFI_ERROR (Status)) {
765       goto Done;
766     }
767
768     if (Value.Type != EFI_IFR_TYPE_STRING) {
769       Status = EFI_UNSUPPORTED;
770       goto Done;
771     }
772
773     String[Index] = GetToken (Value.Value.string, FormSet->HiiHandle);
774     if (String== NULL) {
775       Status = EFI_NOT_FOUND;
776       goto Done;
777     }
778   }
779
780   Result->Type = EFI_IFR_TYPE_BOOLEAN;
781   Result->Value.b = mUnicodeCollation->MetaiMatch (mUnicodeCollation, String[0], String[1]);
782
783 Done:
784   SafeFreePool (String[0]);
785   SafeFreePool (String[1]);
786
787   return Status;
788 }
789
790
791 /**
792   Evaluate opcode EFI_IFR_FIND.
793
794   @param  FormSet                Formset which contains this opcode.
795   @param  Format                 Case sensitive or insensitive.
796   @param  Result                 Evaluation result for this opcode.
797
798   @retval EFI_SUCCESS            Opcode evaluation success.
799   @retval Other                  Opcode evaluation failed.
800
801 **/
802 EFI_STATUS
803 IfrFind (
804   IN FORM_BROWSER_FORMSET  *FormSet,
805   IN UINT8                 Format,
806   OUT  EFI_HII_VALUE       *Result
807   )
808 {
809   EFI_STATUS     Status;
810   EFI_HII_VALUE  Value;
811   CHAR16         *String[2];
812   UINTN          Base;
813   CHAR16         *StringPtr;
814   UINTN          Index;
815
816   if (Format > EFI_IFR_FF_CASE_INSENSITIVE) {
817     return EFI_UNSUPPORTED;
818   }
819
820   Status = PopExpression (&Value);
821   if (EFI_ERROR (Status)) {
822     return Status;
823   }
824   if (Value.Type > EFI_IFR_TYPE_NUM_SIZE_64) {
825     return EFI_UNSUPPORTED;
826   }
827   Base = (UINTN) Value.Value.u64;
828
829   //
830   // String[0] - sub-string
831   // String[1] - The string to search
832   //
833   String[0] = NULL;
834   String[1] = NULL;
835   for (Index = 0; Index < 2; Index++) {
836     Status = PopExpression (&Value);
837     if (EFI_ERROR (Status)) {
838       goto Done;
839     }
840
841     if (Value.Type != EFI_IFR_TYPE_STRING) {
842       Status = EFI_UNSUPPORTED;
843       goto Done;
844     }
845
846     String[Index] = GetToken (Value.Value.string, FormSet->HiiHandle);
847     if (String== NULL) {
848       Status = EFI_NOT_FOUND;
849       goto Done;
850     }
851
852     if (Format == EFI_IFR_FF_CASE_INSENSITIVE) {
853       //
854       // Case insensitive, convert both string to upper case
855       //
856       IfrStrToUpper (String[Index]);
857     }
858   }
859
860   Result->Type = EFI_IFR_TYPE_NUM_SIZE_64;
861   if (Base >= StrLen (String[1])) {
862     Result->Value.u64 = 0xFFFFFFFFFFFFFFFF;
863   } else {
864     StringPtr = StrStr (String[1] + Base, String[0]);
865     Result->Value.u64 = (StringPtr == NULL) ? 0xFFFFFFFFFFFFFFFF : (StringPtr - String[1]);
866   }
867
868 Done:
869   SafeFreePool (String[0]);
870   SafeFreePool (String[1]);
871
872   return Status;
873 }
874
875
876 /**
877   Evaluate opcode EFI_IFR_MID.
878
879   @param  FormSet                Formset which contains this opcode.
880   @param  Result                 Evaluation result for this opcode.
881
882   @retval EFI_SUCCESS            Opcode evaluation success.
883   @retval Other                  Opcode evaluation failed.
884
885 **/
886 EFI_STATUS
887 IfrMid (
888   IN FORM_BROWSER_FORMSET  *FormSet,
889   OUT  EFI_HII_VALUE       *Result
890   )
891 {
892   EFI_STATUS     Status;
893   EFI_HII_VALUE  Value;
894   CHAR16         *String;
895   UINTN          Base;
896   UINTN          Length;
897   CHAR16         *SubString;
898
899   Status = PopExpression (&Value);
900   if (EFI_ERROR (Status)) {
901     return Status;
902   }
903   if (Value.Type > EFI_IFR_TYPE_NUM_SIZE_64) {
904     return EFI_UNSUPPORTED;
905   }
906   Length = (UINTN) Value.Value.u64;
907
908   Status = PopExpression (&Value);
909   if (EFI_ERROR (Status)) {
910     return Status;
911   }
912   if (Value.Type > EFI_IFR_TYPE_NUM_SIZE_64) {
913     return EFI_UNSUPPORTED;
914   }
915   Base = (UINTN) Value.Value.u64;
916
917   Status = PopExpression (&Value);
918   if (EFI_ERROR (Status)) {
919     return Status;
920   }
921   if (Value.Type != EFI_IFR_TYPE_STRING) {
922     return EFI_UNSUPPORTED;
923   }
924   String = GetToken (Value.Value.string, FormSet->HiiHandle);
925   if (String == NULL) {
926     return EFI_NOT_FOUND;
927   }
928
929   if (Length == 0 || Base >= StrLen (String)) {
930     SubString = gEmptyString;
931   } else {
932     SubString = String + Base;
933     if ((Base + Length) < StrLen (String)) {
934       SubString[Length] = L'\0';
935     }
936   }
937
938   Result->Type = EFI_IFR_TYPE_STRING;
939   Result->Value.string = NewString (SubString, FormSet->HiiHandle);
940
941   gBS->FreePool (String);
942
943   return Status;
944 }
945
946
947 /**
948   Evaluate opcode EFI_IFR_TOKEN.
949
950   @param  FormSet                Formset which contains this opcode.
951   @param  Result                 Evaluation result for this opcode.
952
953   @retval EFI_SUCCESS            Opcode evaluation success.
954   @retval Other                  Opcode evaluation failed.
955
956 **/
957 EFI_STATUS
958 IfrToken (
959   IN FORM_BROWSER_FORMSET  *FormSet,
960   OUT  EFI_HII_VALUE       *Result
961   )
962 {
963   EFI_STATUS     Status;
964   EFI_HII_VALUE  Value;
965   CHAR16         *String[2];
966   UINTN          Count;
967   CHAR16         *Delimiter;
968   CHAR16         *SubString;
969   CHAR16         *StringPtr;
970   UINTN          Index;
971
972   Status = PopExpression (&Value);
973   if (EFI_ERROR (Status)) {
974     return Status;
975   }
976   if (Value.Type > EFI_IFR_TYPE_NUM_SIZE_64) {
977     return EFI_UNSUPPORTED;
978   }
979   Count = (UINTN) Value.Value.u64;
980
981   //
982   // String[0] - Delimiter
983   // String[1] - The string to search
984   //
985   String[0] = NULL;
986   String[1] = NULL;
987   for (Index = 0; Index < 2; Index++) {
988     Status = PopExpression (&Value);
989     if (EFI_ERROR (Status)) {
990       goto Done;
991     }
992
993     if (Value.Type != EFI_IFR_TYPE_STRING) {
994       Status = EFI_UNSUPPORTED;
995       goto Done;
996     }
997
998     String[Index] = GetToken (Value.Value.string, FormSet->HiiHandle);
999     if (String== NULL) {
1000       Status = EFI_NOT_FOUND;
1001       goto Done;
1002     }
1003   }
1004
1005   Delimiter = String[0];
1006   SubString = String[1];
1007   while (Count > 0) {
1008     SubString = StrStr (SubString, Delimiter);
1009     if (SubString != NULL) {
1010       //
1011       // Skip over the delimiter
1012       //
1013       SubString = SubString + StrLen (Delimiter);
1014     } else {
1015       break;
1016     }
1017     Count--;
1018   }
1019
1020   if (SubString == NULL) {
1021     //
1022     // nth delimited sub-string not found, push an empty string
1023     //
1024     SubString = gEmptyString;
1025   } else {
1026     //
1027     // Put a NULL terminator for nth delimited sub-string
1028     //
1029     StringPtr = StrStr (SubString, Delimiter);
1030     if (StringPtr != NULL) {
1031       *StringPtr = L'\0';
1032     }
1033   }
1034
1035   Result->Type = EFI_IFR_TYPE_STRING;
1036   Result->Value.string = NewString (SubString, FormSet->HiiHandle);
1037
1038 Done:
1039   SafeFreePool (String[0]);
1040   SafeFreePool (String[1]);
1041
1042   return Status;
1043 }
1044
1045
1046 /**
1047   Evaluate opcode EFI_IFR_SPAN.
1048
1049   @param  FormSet                Formset which contains this opcode.
1050   @param  Flags                  FIRST_MATCHING or FIRST_NON_MATCHING.
1051   @param  Result                 Evaluation result for this opcode.
1052
1053   @retval EFI_SUCCESS            Opcode evaluation success.
1054   @retval Other                  Opcode evaluation failed.
1055
1056 **/
1057 EFI_STATUS
1058 IfrSpan (
1059   IN FORM_BROWSER_FORMSET  *FormSet,
1060   IN UINT8                 Flags,
1061   OUT  EFI_HII_VALUE       *Result
1062   )
1063 {
1064   EFI_STATUS     Status;
1065   EFI_HII_VALUE  Value;
1066   CHAR16         *String[2];
1067   CHAR16         *Charset;
1068   UINTN          Base;
1069   UINTN          Index;
1070   CHAR16         *StringPtr;
1071   BOOLEAN        Found;
1072
1073   Status = PopExpression (&Value);
1074   if (EFI_ERROR (Status)) {
1075     return Status;
1076   }
1077   if (Value.Type > EFI_IFR_TYPE_NUM_SIZE_64) {
1078     return EFI_UNSUPPORTED;
1079   }
1080   Base = (UINTN) Value.Value.u64;
1081
1082   //
1083   // String[0] - Charset
1084   // String[1] - The string to search
1085   //
1086   String[0] = NULL;
1087   String[1] = NULL;
1088   for (Index = 0; Index < 2; Index++) {
1089     Status = PopExpression (&Value);
1090     if (EFI_ERROR (Status)) {
1091       goto Done;
1092     }
1093
1094     if (Value.Type != EFI_IFR_TYPE_STRING) {
1095       Status = EFI_UNSUPPORTED;
1096       goto Done;
1097     }
1098
1099     String[Index] = GetToken (Value.Value.string, FormSet->HiiHandle);
1100     if (String== NULL) {
1101       Status = EFI_NOT_FOUND;
1102       goto Done;
1103     }
1104   }
1105
1106   if (Base >= StrLen (String[1])) {
1107     Status = EFI_UNSUPPORTED;
1108     goto Done;
1109   }
1110
1111   Found = FALSE;
1112   StringPtr = String[1] + Base;
1113   Charset = String[0];
1114   while (*StringPtr != 0 && !Found) {
1115     Index = 0;
1116     while (Charset[Index] != 0) {
1117       if (*StringPtr >= Charset[Index] && *StringPtr <= Charset[Index + 1]) {
1118         if (Flags == EFI_IFR_FLAGS_FIRST_MATCHING) {
1119           Found = TRUE;
1120           break;
1121         }
1122       } else {
1123         if (Flags == EFI_IFR_FLAGS_FIRST_NON_MATCHING) {
1124           Found = TRUE;
1125           break;
1126         }
1127       }
1128       //
1129       // Skip characters pair representing low-end of a range and high-end of a range
1130       //
1131       Index += 2;
1132     }
1133
1134     if (!Found) {
1135       StringPtr++;
1136     }
1137   }
1138
1139   Result->Type = EFI_IFR_TYPE_NUM_SIZE_64;
1140   Result->Value.u64 = StringPtr - String[1];
1141
1142 Done:
1143   SafeFreePool (String[0]);
1144   SafeFreePool (String[1]);
1145
1146   return Status;
1147 }
1148
1149
1150 /**
1151   Zero extend integer/boolean/date/time to UINT64 for comparing.
1152
1153   @param  Value                  HII Value to be converted.
1154
1155   @return None.
1156
1157 **/
1158 VOID
1159 ExtendValueToU64 (
1160   IN  EFI_HII_VALUE   *Value
1161   )
1162 {
1163   UINT64  Temp;
1164
1165   Temp = 0;
1166   switch (Value->Type) {
1167   case EFI_IFR_TYPE_NUM_SIZE_8:
1168     Temp = Value->Value.u8;
1169     break;
1170
1171   case EFI_IFR_TYPE_NUM_SIZE_16:
1172     Temp = Value->Value.u16;
1173     break;
1174
1175   case EFI_IFR_TYPE_NUM_SIZE_32:
1176     Temp = Value->Value.u32;
1177     break;
1178
1179   case EFI_IFR_TYPE_BOOLEAN:
1180     Temp = Value->Value.b;
1181     break;
1182
1183   case EFI_IFR_TYPE_TIME:
1184     Temp = Value->Value.u32 & 0xffffff;
1185     break;
1186
1187   case EFI_IFR_TYPE_DATE:
1188     Temp = Value->Value.u32;
1189     break;
1190
1191   default:
1192     return;
1193   }
1194
1195   Value->Value.u64 = Temp;
1196 }
1197
1198
1199 /**
1200   Compare two Hii value.
1201
1202   @param  Value1                 Expression value to compare on left-hand
1203   @param  Value2                 Expression value to compare on right-hand
1204   @param  HiiHandle              Only required for string compare
1205
1206   @retval EFI_INVALID_PARAMETER  Could not perform comparation on two values
1207   @retval 0                      Two operators equeal
1208   @retval 0                      Value1 is greater than Value2
1209   @retval 0                      Value1 is less than Value2
1210
1211 **/
1212 INTN
1213 CompareHiiValue (
1214   IN  EFI_HII_VALUE   *Value1,
1215   IN  EFI_HII_VALUE   *Value2,
1216   IN  EFI_HII_HANDLE  HiiHandle OPTIONAL
1217   )
1218 {
1219   INTN    Result;
1220   INT64   Temp64;
1221   CHAR16  *Str1;
1222   CHAR16  *Str2;
1223
1224   if (Value1->Type >= EFI_IFR_TYPE_OTHER || Value2->Type >= EFI_IFR_TYPE_OTHER ) {
1225     return EFI_INVALID_PARAMETER;
1226   }
1227
1228   if (Value1->Type == EFI_IFR_TYPE_STRING || Value2->Type == EFI_IFR_TYPE_STRING ) {
1229     if (Value1->Type != Value2->Type) {
1230       //
1231       // Both Operator should be type of String
1232       //
1233       return EFI_INVALID_PARAMETER;
1234     }
1235
1236     if (Value1->Value.string == 0 || Value2->Value.string == 0) {
1237       //
1238       // StringId 0 is reserved
1239       //
1240       return EFI_INVALID_PARAMETER;
1241     }
1242
1243     if (Value1->Value.string == Value2->Value.string) {
1244       return 0;
1245     }
1246
1247     Str1 = GetToken (Value1->Value.string, HiiHandle);
1248     if (Str1 == NULL) {
1249       //
1250       // String not found
1251       //
1252       return EFI_INVALID_PARAMETER;
1253     }
1254
1255     Str2 = GetToken (Value2->Value.string, HiiHandle);
1256     if (Str2 == NULL) {
1257       gBS->FreePool (Str1);
1258       return EFI_INVALID_PARAMETER;
1259     }
1260
1261     Result = StrCmp (Str1, Str2);
1262
1263     gBS->FreePool (Str1);
1264     gBS->FreePool (Str2);
1265
1266     return Result;
1267   }
1268
1269   //
1270   // Take remain types(integer, boolean, date/time) as integer
1271   //
1272   Temp64 = (INT64) (Value1->Value.u64 - Value2->Value.u64);
1273   if (Temp64 > 0) {
1274     Result = 1;
1275   } else if (Temp64 < 0) {
1276     Result = -1;
1277   } else {
1278     Result = 0;
1279   }
1280
1281   return Result;
1282 }
1283
1284
1285 /**
1286   Evaluate the result of a HII expression
1287
1288   @param  FormSet                FormSet associated with this expression.
1289   @param  Form                   Form associated with this expression.
1290   @param  Expression             Expression to be evaluated.
1291
1292   @retval EFI_SUCCESS            The expression evaluated successfuly
1293   @retval EFI_NOT_FOUND          The Question which referenced by a QuestionId
1294                                  could not be found.
1295   @retval EFI_OUT_OF_RESOURCES   There is not enough system memory to grow the
1296                                  stack.
1297   @retval EFI_ACCESS_DENIED      The pop operation underflowed the stack
1298   @retval EFI_INVALID_PARAMETER  Syntax error with the Expression
1299
1300 **/
1301 EFI_STATUS
1302 EvaluateExpression (
1303   IN FORM_BROWSER_FORMSET  *FormSet,
1304   IN FORM_BROWSER_FORM     *Form,
1305   IN OUT FORM_EXPRESSION   *Expression
1306   )
1307 {
1308   EFI_STATUS              Status;
1309   LIST_ENTRY              *Link;
1310   EXPRESSION_OPCODE       *OpCode;
1311   FORM_BROWSER_STATEMENT  *Question;
1312   FORM_BROWSER_STATEMENT  *Question2;
1313   UINT16                  Index;
1314   EFI_HII_VALUE           Data1;
1315   EFI_HII_VALUE           Data2;
1316   EFI_HII_VALUE           Data3;
1317   FORM_EXPRESSION         *RuleExpression;
1318   EFI_HII_VALUE           *Value;
1319   INTN                    Result;
1320   CHAR16                  *StrPtr;
1321   UINT32                  TempValue;
1322
1323   //
1324   // Always reset the stack before evaluating an Expression
1325   //
1326   ResetExpressionStack ();
1327
1328   Expression->Result.Type = EFI_IFR_TYPE_OTHER;
1329
1330   Link = GetFirstNode (&Expression->OpCodeListHead);
1331   while (!IsNull (&Expression->OpCodeListHead, Link)) {
1332     OpCode = EXPRESSION_OPCODE_FROM_LINK (Link);
1333
1334     Link = GetNextNode (&Expression->OpCodeListHead, Link);
1335
1336     ZeroMem (&Data1, sizeof (EFI_HII_VALUE));
1337     ZeroMem (&Data2, sizeof (EFI_HII_VALUE));
1338     ZeroMem (&Data3, sizeof (EFI_HII_VALUE));
1339
1340     Value = &Data3;
1341     Value->Type = EFI_IFR_TYPE_BOOLEAN;
1342     Status = EFI_SUCCESS;
1343
1344     switch (OpCode->Operand) {
1345     //
1346     // Built-in functions
1347     //
1348     case EFI_IFR_EQ_ID_VAL_OP:
1349       Question = IdToQuestion (FormSet, Form, OpCode->QuestionId);
1350       if (Question == NULL) {
1351         return EFI_NOT_FOUND;
1352       }
1353
1354       Result = CompareHiiValue (&Question->HiiValue, &OpCode->Value, NULL);
1355       if (Result == EFI_INVALID_PARAMETER) {
1356         return EFI_INVALID_PARAMETER;
1357       }
1358       Value->Value.b = (BOOLEAN) ((Result == 0) ? TRUE : FALSE);
1359       break;
1360
1361     case EFI_IFR_EQ_ID_ID_OP:
1362       Question = IdToQuestion (FormSet, Form, OpCode->QuestionId);
1363       if (Question == NULL) {
1364         return EFI_NOT_FOUND;
1365       }
1366
1367       Question2 = IdToQuestion (FormSet, Form, OpCode->QuestionId2);
1368       if (Question2 == NULL) {
1369         return EFI_NOT_FOUND;
1370       }
1371
1372       Result = CompareHiiValue (&Question->HiiValue, &Question2->HiiValue, FormSet->HiiHandle);
1373       if (Result == EFI_INVALID_PARAMETER) {
1374         return EFI_INVALID_PARAMETER;
1375       }
1376       Value->Value.b = (BOOLEAN) ((Result == 0) ? TRUE : FALSE);
1377       break;
1378
1379     case EFI_IFR_EQ_ID_LIST_OP:
1380       Question = IdToQuestion (FormSet, Form, OpCode->QuestionId);
1381       if (Question == NULL) {
1382         return EFI_NOT_FOUND;
1383       }
1384
1385       Value->Value.b = FALSE;
1386       for (Index =0; Index < OpCode->ListLength; Index++) {
1387         if (Question->HiiValue.Value.u16 == OpCode->ValueList[Index]) {
1388           Value->Value.b = TRUE;
1389           break;
1390         }
1391       }
1392       break;
1393
1394     case EFI_IFR_DUP_OP:
1395       Status = PopExpression (Value);
1396       if (EFI_ERROR (Status)) {
1397         return Status;
1398       }
1399
1400       Status = PushExpression (Value);
1401       break;
1402
1403     case EFI_IFR_QUESTION_REF1_OP:
1404     case EFI_IFR_THIS_OP:
1405       Question = IdToQuestion (FormSet, Form, OpCode->QuestionId);
1406       if (Question == NULL) {
1407         return EFI_NOT_FOUND;
1408       }
1409
1410       Value = &Question->HiiValue;
1411       break;
1412
1413     case EFI_IFR_QUESTION_REF3_OP:
1414       if (OpCode->DevicePath == 0) {
1415         //
1416         // EFI_IFR_QUESTION_REF3
1417         // Pop an expression from the expression stack
1418         //
1419         Status = PopExpression (Value);
1420         if (EFI_ERROR (Status)) {
1421           return Status;
1422         }
1423
1424         //
1425         // Validate the expression value
1426         //
1427         if ((Value->Type > EFI_IFR_TYPE_NUM_SIZE_64) || (Value->Value.u64 > 0xffff)) {
1428           return EFI_NOT_FOUND;
1429         }
1430
1431         Question = IdToQuestion (FormSet, Form, Value->Value.u16);
1432         if (Question == NULL) {
1433           return EFI_NOT_FOUND;
1434         }
1435
1436         //
1437         // push the questions' value on to the expression stack
1438         //
1439         Value = &Question->HiiValue;
1440       } else {
1441         //
1442         // BUGBUG: push 0 for EFI_IFR_QUESTION_REF3_2 and EFI_IFR_QUESTION_REF3_3,
1443         // since it is impractical to evaluate the value of a Question in another
1444         // Hii Package list.
1445         //
1446         ZeroMem (Value, sizeof (EFI_HII_VALUE));
1447       }
1448       break;
1449
1450     case EFI_IFR_RULE_REF_OP:
1451       //
1452       // Find expression for this rule
1453       //
1454       RuleExpression = RuleIdToExpression (Form, OpCode->RuleId);
1455       if (RuleExpression == NULL) {
1456         return EFI_NOT_FOUND;
1457       }
1458
1459       //
1460       // Evaluate this rule expression
1461       //
1462       Status = EvaluateExpression (FormSet, Form, RuleExpression);
1463       if (EFI_ERROR (Status)) {
1464         return Status;
1465       }
1466
1467       Value = &RuleExpression->Result;
1468       break;
1469
1470     case EFI_IFR_STRING_REF1_OP:
1471       Value->Type = EFI_IFR_TYPE_STRING;
1472       Value->Value.string = OpCode->Value.Value.string;
1473       break;
1474
1475     //
1476     // Constant
1477     //
1478     case EFI_IFR_TRUE_OP:
1479     case EFI_IFR_FALSE_OP:
1480     case EFI_IFR_ONE_OP:
1481     case EFI_IFR_ONES_OP:
1482     case EFI_IFR_UINT8_OP:
1483     case EFI_IFR_UINT16_OP:
1484     case EFI_IFR_UINT32_OP:
1485     case EFI_IFR_UINT64_OP:
1486     case EFI_IFR_UNDEFINED_OP:
1487     case EFI_IFR_VERSION_OP:
1488     case EFI_IFR_ZERO_OP:
1489       Value = &OpCode->Value;
1490       break;
1491
1492     //
1493     // unary-op
1494     //
1495     case EFI_IFR_LENGTH_OP:
1496       Status = PopExpression (Value);
1497       if (EFI_ERROR (Status)) {
1498         return Status;
1499       }
1500       if (Value->Type != EFI_IFR_TYPE_STRING) {
1501         return EFI_INVALID_PARAMETER;
1502       }
1503
1504       StrPtr = GetToken (Value->Value.string, FormSet->HiiHandle);
1505       if (StrPtr == NULL) {
1506         return EFI_INVALID_PARAMETER;
1507       }
1508
1509       Value->Type = EFI_IFR_TYPE_NUM_SIZE_64;
1510       Value->Value.u64 = StrLen (StrPtr);
1511       gBS->FreePool (StrPtr);
1512       break;
1513
1514     case EFI_IFR_NOT_OP:
1515       Status = PopExpression (Value);
1516       if (EFI_ERROR (Status)) {
1517         return Status;
1518       }
1519       if (Value->Type != EFI_IFR_TYPE_BOOLEAN) {
1520         return EFI_INVALID_PARAMETER;
1521       }
1522       Value->Value.b = (BOOLEAN) (!Value->Value.b);
1523       break;
1524
1525     case EFI_IFR_QUESTION_REF2_OP:
1526       //
1527       // Pop an expression from the expression stack
1528       //
1529       Status = PopExpression (Value);
1530       if (EFI_ERROR (Status)) {
1531         return Status;
1532       }
1533
1534       //
1535       // Validate the expression value
1536       //
1537       if ((Value->Type > EFI_IFR_TYPE_NUM_SIZE_64) || (Value->Value.u64 > 0xffff)) {
1538         return EFI_NOT_FOUND;
1539       }
1540
1541       Question = IdToQuestion (FormSet, Form, Value->Value.u16);
1542       if (Question == NULL) {
1543         return EFI_NOT_FOUND;
1544       }
1545
1546       Value = &Question->HiiValue;
1547       break;
1548
1549     case EFI_IFR_STRING_REF2_OP:
1550       //
1551       // Pop an expression from the expression stack
1552       //
1553       Status = PopExpression (Value);
1554       if (EFI_ERROR (Status)) {
1555         return Status;
1556       }
1557
1558       //
1559       // Validate the expression value
1560       //
1561       if ((Value->Type > EFI_IFR_TYPE_NUM_SIZE_64) || (Value->Value.u64 > 0xffff)) {
1562         return EFI_NOT_FOUND;
1563       }
1564
1565       Value->Type = EFI_IFR_TYPE_STRING;
1566       StrPtr = GetToken (Value->Value.u16, FormSet->HiiHandle);
1567       if (StrPtr == NULL) {
1568         //
1569         // If String not exit, push an empty string
1570         //
1571         Value->Value.string = NewString (gEmptyString, FormSet->HiiHandle);
1572       } else {
1573         Index = (UINT16) Value->Value.u64;
1574         Value->Value.string = Index;
1575         gBS->FreePool (StrPtr);
1576       }
1577       break;
1578
1579     case EFI_IFR_TO_BOOLEAN_OP:
1580       //
1581       // Pop an expression from the expression stack
1582       //
1583       Status = PopExpression (Value);
1584       if (EFI_ERROR (Status)) {
1585         return Status;
1586       }
1587
1588       //
1589       // Convert an expression to a Boolean
1590       //
1591       if (Value->Type <= EFI_IFR_TYPE_DATE) {
1592         //
1593         // When converting from an unsigned integer, zero will be converted to
1594         // FALSE and any other value will be converted to TRUE.
1595         //
1596         Value->Value.b = (BOOLEAN) ((Value->Value.u64) ? TRUE : FALSE);
1597
1598         Value->Type = EFI_IFR_TYPE_BOOLEAN;
1599       } else if (Value->Type == EFI_IFR_TYPE_STRING) {
1600         //
1601         // When converting from a string, if case-insensitive compare
1602         // with "true" is True, then push True. If a case-insensitive compare
1603         // with "false" is True, then push False.
1604         //
1605         StrPtr = GetToken (Value->Value.string, FormSet->HiiHandle);
1606         if (StrPtr == NULL) {
1607           return EFI_INVALID_PARAMETER;
1608         }
1609
1610         if ((StrCmp (StrPtr, L"true") == 0) || (StrCmp (StrPtr, L"false") == 0)){
1611           Value->Value.b = TRUE;
1612         } else {
1613           Value->Value.b = FALSE;
1614         }
1615         gBS->FreePool (StrPtr);
1616         Value->Type = EFI_IFR_TYPE_BOOLEAN;
1617       }
1618       break;
1619
1620     case EFI_IFR_TO_STRING_OP:
1621       Status = IfrToString (FormSet, OpCode->Format, Value);
1622       break;
1623
1624     case EFI_IFR_TO_UINT_OP:
1625       Status = IfrToUint (FormSet, Value);
1626       break;
1627
1628     case EFI_IFR_TO_LOWER_OP:
1629     case EFI_IFR_TO_UPPER_OP:
1630       Status = InitializeUnicodeCollationProtocol ();
1631       if (EFI_ERROR (Status)) {
1632         return Status;
1633       }
1634
1635       Status = PopExpression (Value);
1636       if (EFI_ERROR (Status)) {
1637         return Status;
1638       }
1639
1640       if (Value->Type != EFI_IFR_TYPE_STRING) {
1641         return EFI_UNSUPPORTED;
1642       }
1643
1644       StrPtr = GetToken (Value->Value.string, FormSet->HiiHandle);
1645       if (StrPtr == NULL) {
1646         return EFI_NOT_FOUND;
1647       }
1648
1649       if (OpCode->Operand == EFI_IFR_TO_LOWER_OP) {
1650         mUnicodeCollation->StrLwr (mUnicodeCollation, StrPtr);
1651       } else {
1652         mUnicodeCollation->StrUpr (mUnicodeCollation, StrPtr);
1653       }
1654       Value->Value.string = NewString (StrPtr, FormSet->HiiHandle);
1655       gBS->FreePool (StrPtr);
1656       break;
1657
1658     case EFI_IFR_BITWISE_NOT_OP:
1659       //
1660       // Pop an expression from the expression stack
1661       //
1662       Status = PopExpression (Value);
1663       if (EFI_ERROR (Status)) {
1664         return Status;
1665       }
1666       if (Value->Type > EFI_IFR_TYPE_DATE) {
1667         return EFI_INVALID_PARAMETER;
1668       }
1669
1670       Value->Type = EFI_IFR_TYPE_NUM_SIZE_64;
1671       Value->Value.u64 = ~Value->Value.u64;
1672       break;
1673
1674     //
1675     // binary-op
1676     //
1677     case EFI_IFR_ADD_OP:
1678     case EFI_IFR_SUBTRACT_OP:
1679     case EFI_IFR_MULTIPLY_OP:
1680     case EFI_IFR_DIVIDE_OP:
1681     case EFI_IFR_MODULO_OP:
1682     case EFI_IFR_BITWISE_AND_OP:
1683     case EFI_IFR_BITWISE_OR_OP:
1684     case EFI_IFR_SHIFT_LEFT_OP:
1685     case EFI_IFR_SHIFT_RIGHT_OP:
1686       //
1687       // Pop an expression from the expression stack
1688       //
1689       Status = PopExpression (&Data2);
1690       if (EFI_ERROR (Status)) {
1691         return Status;
1692       }
1693       if (Data2.Type > EFI_IFR_TYPE_DATE) {
1694         return EFI_INVALID_PARAMETER;
1695       }
1696
1697       //
1698       // Pop another expression from the expression stack
1699       //
1700       Status = PopExpression (&Data1);
1701       if (EFI_ERROR (Status)) {
1702         return Status;
1703       }
1704       if (Data1.Type > EFI_IFR_TYPE_DATE) {
1705         return EFI_INVALID_PARAMETER;
1706       }
1707
1708       Value->Type = EFI_IFR_TYPE_NUM_SIZE_64;
1709
1710       switch (OpCode->Operand) {
1711         case EFI_IFR_ADD_OP:
1712           Value->Value.u64 = Data1.Value.u64 + Data2.Value.u64;
1713           break;
1714
1715         case EFI_IFR_SUBTRACT_OP:
1716           Value->Value.u64 = Data1.Value.u64 - Data2.Value.u64;
1717           break;
1718
1719         case EFI_IFR_MULTIPLY_OP:
1720           Value->Value.u64 = MultU64x32 (Data1.Value.u64, (UINT32) Data2.Value.u64);
1721           break;
1722
1723         case EFI_IFR_DIVIDE_OP:
1724           Value->Value.u64 = DivU64x32 (Data1.Value.u64, (UINT32) Data2.Value.u64);
1725           break;
1726
1727         case EFI_IFR_MODULO_OP:
1728           DivU64x32Remainder  (Data1.Value.u64, (UINT32) Data2.Value.u64, &TempValue);
1729           Value->Value.u64 = TempValue;
1730           break;
1731
1732         case EFI_IFR_BITWISE_AND_OP:
1733           Value->Value.u64 = Data1.Value.u64 & Data2.Value.u64;
1734           break;
1735
1736         case EFI_IFR_BITWISE_OR_OP:
1737           Value->Value.u64 = Data1.Value.u64 | Data2.Value.u64;
1738           break;
1739
1740         case EFI_IFR_SHIFT_LEFT_OP:
1741           Value->Value.u64 = LShiftU64 (Data1.Value.u64, (UINTN) Data2.Value.u64);
1742           break;
1743
1744         case EFI_IFR_SHIFT_RIGHT_OP:
1745           Value->Value.u64 = RShiftU64 (Data1.Value.u64, (UINTN) Data2.Value.u64);
1746           break;
1747
1748         default:
1749           break;
1750       }
1751       break;
1752
1753     case EFI_IFR_AND_OP:
1754     case EFI_IFR_OR_OP:
1755       //
1756       // Two Boolean operator
1757       //
1758       Status = PopExpression (&Data2);
1759       if (EFI_ERROR (Status)) {
1760         return Status;
1761       }
1762       if (Data2.Type != EFI_IFR_TYPE_BOOLEAN) {
1763         return EFI_INVALID_PARAMETER;
1764       }
1765
1766       //
1767       // Pop another expression from the expression stack
1768       //
1769       Status = PopExpression (&Data1);
1770       if (EFI_ERROR (Status)) {
1771         return Status;
1772       }
1773       if (Data1.Type != EFI_IFR_TYPE_BOOLEAN) {
1774         return EFI_INVALID_PARAMETER;
1775       }
1776
1777       if (OpCode->Operand == EFI_IFR_AND_OP) {
1778         Value->Value.b = (BOOLEAN) (Data1.Value.b && Data2.Value.b);
1779       } else {
1780         Value->Value.b = (BOOLEAN) (Data1.Value.b || Data2.Value.b);
1781       }
1782       break;
1783
1784     case EFI_IFR_EQUAL_OP:
1785     case EFI_IFR_NOT_EQUAL_OP:
1786     case EFI_IFR_GREATER_EQUAL_OP:
1787     case EFI_IFR_GREATER_THAN_OP:
1788     case EFI_IFR_LESS_EQUAL_OP:
1789     case EFI_IFR_LESS_THAN_OP:
1790       //
1791       // Compare two integer, string, boolean or date/time
1792       //
1793       Status = PopExpression (&Data2);
1794       if (EFI_ERROR (Status)) {
1795         return Status;
1796       }
1797       if (Data2.Type > EFI_IFR_TYPE_BOOLEAN && Data2.Type != EFI_IFR_TYPE_STRING) {
1798         return EFI_INVALID_PARAMETER;
1799       }
1800
1801       //
1802       // Pop another expression from the expression stack
1803       //
1804       Status = PopExpression (&Data1);
1805       if (EFI_ERROR (Status)) {
1806         return Status;
1807       }
1808
1809       Result = CompareHiiValue (&Data1, &Data2, FormSet->HiiHandle);
1810       if (Result == EFI_INVALID_PARAMETER) {
1811         return EFI_INVALID_PARAMETER;
1812       }
1813
1814       switch (OpCode->Operand) {
1815       case EFI_IFR_EQUAL_OP:
1816         Value->Value.b = (BOOLEAN) ((Result == 0) ? TRUE : FALSE);
1817         break;
1818
1819       case EFI_IFR_NOT_EQUAL_OP:
1820         Value->Value.b = (BOOLEAN) ((Result == 0) ? TRUE : FALSE);
1821         break;
1822
1823       case EFI_IFR_GREATER_EQUAL_OP:
1824         Value->Value.b = (BOOLEAN) ((Result >= 0) ? TRUE : FALSE);
1825         break;
1826
1827       case EFI_IFR_GREATER_THAN_OP:
1828         Value->Value.b = (BOOLEAN) ((Result > 0) ? TRUE : FALSE);
1829         break;
1830
1831       case EFI_IFR_LESS_EQUAL_OP:
1832         Value->Value.b = (BOOLEAN) ((Result <= 0) ? TRUE : FALSE);
1833         break;
1834
1835       case EFI_IFR_LESS_THAN_OP:
1836         Value->Value.b = (BOOLEAN) ((Result < 0) ? TRUE : FALSE);
1837         break;
1838
1839       default:
1840         break;
1841       }
1842       break;
1843
1844     case EFI_IFR_MATCH_OP:
1845       Status = IfrMatch (FormSet, Value);
1846       break;
1847
1848     case EFI_IFR_CATENATE_OP:
1849       Status = IfrCatenate (FormSet, Value);
1850       break;
1851
1852     //
1853     // ternary-op
1854     //
1855     case EFI_IFR_CONDITIONAL_OP:
1856       //
1857       // Pop third expression from the expression stack
1858       //
1859       Status = PopExpression (&Data3);
1860       if (EFI_ERROR (Status)) {
1861         return Status;
1862       }
1863
1864       //
1865       // Pop second expression from the expression stack
1866       //
1867       Status = PopExpression (&Data2);
1868       if (EFI_ERROR (Status)) {
1869         return Status;
1870       }
1871
1872       //
1873       // Pop first expression from the expression stack
1874       //
1875       Status = PopExpression (&Data1);
1876       if (EFI_ERROR (Status)) {
1877         return Status;
1878       }
1879       if (Data1.Type != EFI_IFR_TYPE_BOOLEAN) {
1880         return EFI_INVALID_PARAMETER;
1881       }
1882
1883       if (Data1.Value.b) {
1884         Value = &Data3;
1885       } else {
1886         Value = &Data2;
1887       }
1888       break;
1889
1890     case EFI_IFR_FIND_OP:
1891       Status = IfrFind (FormSet, OpCode->Format, Value);
1892       break;
1893
1894     case EFI_IFR_MID_OP:
1895       Status = IfrMid (FormSet, Value);
1896       break;
1897
1898     case EFI_IFR_TOKEN_OP:
1899       Status = IfrToken (FormSet, Value);
1900       break;
1901
1902     case EFI_IFR_SPAN_OP:
1903       Status = IfrSpan (FormSet, OpCode->Flags, Value);
1904       break;
1905
1906     default:
1907       break;
1908     }
1909     if (EFI_ERROR (Status)) {
1910       return Status;
1911     }
1912
1913     Status = PushExpression (Value);
1914     if (EFI_ERROR (Status)) {
1915       return Status;
1916     }
1917   }
1918
1919   //
1920   // Pop the final result from expression stack
1921   //
1922   Value = &Data1;
1923   Status = PopExpression (Value);
1924   if (EFI_ERROR (Status)) {
1925     return Status;
1926   }
1927
1928   //
1929   // After evaluating an expression, there should be only one value left on the expression stack
1930   //
1931   if (PopExpression (Value) != EFI_ACCESS_DENIED) {
1932     return EFI_INVALID_PARAMETER;
1933   }
1934
1935   CopyMem (&Expression->Result, Value, sizeof (EFI_HII_VALUE));
1936
1937   return EFI_SUCCESS;
1938 }