]> git.proxmox.com Git - mirror_edk2.git/blob - BaseTools/Source/C/FCE/Expression.c
BaseTools/FCE: Add a tool FCE
[mirror_edk2.git] / BaseTools / Source / C / FCE / Expression.c
1 /** @file
2
3 Utility functions for expression evaluation.
4
5 Copyright (c) 2011-2019, Intel Corporation. All rights reserved.<BR>
6 SPDX-License-Identifier: BSD-2-Clause-Patent
7
8 **/
9
10 #include "IfrParse.h"
11
12 #define gEmptyString L""
13 //
14 // Global stack used to evaluate boolean expresions
15 //
16 EFI_HII_VALUE *mOpCodeScopeStack = NULL;
17 EFI_HII_VALUE *mOpCodeScopeStackEnd = NULL;
18 EFI_HII_VALUE *mOpCodeScopeStackPointer = NULL;
19
20 EFI_HII_VALUE *mExpressionEvaluationStack = NULL;
21 EFI_HII_VALUE *mExpressionEvaluationStackEnd = NULL;
22 EFI_HII_VALUE *mExpressionEvaluationStackPointer = NULL;
23 UINTN mExpressionEvaluationStackOffset = 0;
24
25 EFI_HII_VALUE *mCurrentExpressionStack = NULL;
26 EFI_HII_VALUE *mCurrentExpressionEnd = NULL;
27 EFI_HII_VALUE *mCurrentExpressionPointer = NULL;
28
29 EFI_HII_VALUE *mMapExpressionListStack = NULL;
30 EFI_HII_VALUE *mMapExpressionListEnd = NULL;
31 EFI_HII_VALUE *mMapExpressionListPointer = NULL;
32
33 /**
34 Get Value for given Name from a NameValue Storage.
35
36 @param Storage The NameValue Storage.
37 @param Name The Name.
38 @param Value The retured Value.
39
40 @retval EFI_SUCCESS Value found for given Name.
41 @retval EFI_NOT_FOUND No such Name found in NameValue storage.
42
43 **/
44 EFI_STATUS
45 GetValueByName (
46 IN FORMSET_STORAGE *Storage,
47 IN CHAR16 *Name,
48 IN OUT CHAR16 **Value
49 )
50 {
51 LIST_ENTRY *Link;
52 NAME_VALUE_NODE *Node;
53
54 *Value = NULL;
55
56 Link = GetFirstNode (&Storage->NameValueListHead);
57 while (!IsNull (&Storage->NameValueListHead, Link)) {
58 Node = NAME_VALUE_NODE_FROM_LINK (Link);
59
60 if (FceStrCmp (Name, Node->Name) == 0) {
61 NewStringCpy (Value, Node->EditValue);
62 return EFI_SUCCESS;
63 }
64
65 Link = GetNextNode (&Storage->NameValueListHead, Link);
66 }
67
68 return EFI_NOT_FOUND;
69 }
70
71 /**
72 Grow size of the stack.
73
74 This is an internal function.
75
76 @param Stack On input: old stack; On output: new stack
77 @param StackPtr On input: old stack pointer; On output: new stack
78 pointer
79 @param StackEnd On input: old stack end; On output: new stack end
80
81 @retval EFI_SUCCESS Grow stack success.
82 @retval EFI_OUT_OF_RESOURCES No enough memory for stack space.
83
84 **/
85 EFI_STATUS
86 GrowStack (
87 IN OUT EFI_HII_VALUE **Stack,
88 IN OUT EFI_HII_VALUE **StackPtr,
89 IN OUT EFI_HII_VALUE **StackEnd
90 )
91 {
92 UINTN Size;
93 EFI_HII_VALUE *NewStack;
94
95 Size = EXPRESSION_STACK_SIZE_INCREMENT;
96 if (*StackPtr != NULL) {
97 Size = Size + (*StackEnd - *Stack);
98 }
99
100 NewStack = AllocatePool (Size * sizeof (EFI_HII_VALUE));
101 if (NewStack == NULL) {
102 return EFI_OUT_OF_RESOURCES;
103 }
104
105 if (*StackPtr != NULL) {
106 //
107 // Copy from Old Stack to the New Stack
108 //
109 CopyMem (
110 NewStack,
111 *Stack,
112 (*StackEnd - *Stack) * sizeof (EFI_HII_VALUE)
113 );
114
115 //
116 // Free The Old Stack
117 //
118 FreePool (*Stack);
119 }
120
121 //
122 // Make the Stack pointer point to the old data in the new stack
123 //
124 *StackPtr = NewStack + (*StackPtr - *Stack);
125 *Stack = NewStack;
126 *StackEnd = NewStack + Size;
127
128 return EFI_SUCCESS;
129 }
130
131
132 /**
133 Push an element onto the Boolean Stack.
134
135 @param Stack On input: old stack; On output: new stack
136 @param StackPtr On input: old stack pointer; On output: new stack
137 pointer
138 @param StackEnd On input: old stack end; On output: new stack end
139 @param Data Data to push.
140
141 @retval EFI_SUCCESS Push stack success.
142
143 **/
144 EFI_STATUS
145 PushStack (
146 IN OUT EFI_HII_VALUE **Stack,
147 IN OUT EFI_HII_VALUE **StackPtr,
148 IN OUT EFI_HII_VALUE **StackEnd,
149 IN EFI_HII_VALUE *Data
150 )
151 {
152 EFI_STATUS Status;
153
154 //
155 // Check for a stack overflow condition
156 //
157 if (*StackPtr >= *StackEnd) {
158 //
159 // Grow the stack
160 //
161 Status = GrowStack (Stack, StackPtr, StackEnd);
162 if (EFI_ERROR (Status)) {
163 return Status;
164 }
165 }
166
167 //
168 // Push the item onto the stack
169 //
170 CopyMem (*StackPtr, Data, sizeof (EFI_HII_VALUE));
171 *StackPtr = *StackPtr + 1;
172
173 return EFI_SUCCESS;
174 }
175
176
177 /**
178 Pop an element from the stack.
179
180 @param Stack On input: old stack
181 @param StackPtr On input: old stack pointer; On output: new stack pointer
182 @param Data Data to pop.
183
184 @retval EFI_SUCCESS The value was popped onto the stack.
185 @retval EFI_ACCESS_DENIED The pop operation underflowed the stack
186
187 **/
188 EFI_STATUS
189 PopStack (
190 IN EFI_HII_VALUE *Stack,
191 IN OUT EFI_HII_VALUE **StackPtr,
192 OUT EFI_HII_VALUE *Data
193 )
194 {
195 //
196 // Check for a stack underflow condition
197 //
198 if (*StackPtr == Stack) {
199 return EFI_ACCESS_DENIED;
200 }
201
202 //
203 // Pop the item off the stack
204 //
205 *StackPtr = *StackPtr - 1;
206 CopyMem (Data, *StackPtr, sizeof (EFI_HII_VALUE));
207 return EFI_SUCCESS;
208 }
209
210
211 /**
212 Reset stack pointer to begin of the stack.
213
214 **/
215 VOID
216 ResetCurrentExpressionStack (
217 VOID
218 )
219 {
220 mCurrentExpressionPointer = mCurrentExpressionStack;
221 }
222
223
224 /**
225 Push current expression onto the Stack
226
227 @param Pointer Pointer to current expression.
228
229 @retval EFI_SUCCESS The value was pushed onto the stack.
230 @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the stack.
231
232 **/
233 EFI_STATUS
234 PushCurrentExpression (
235 IN VOID *Pointer
236 )
237 {
238 EFI_HII_VALUE Data;
239
240 Data.Type = EFI_IFR_TYPE_NUM_SIZE_64;
241 Data.Value.u64 = (UINT64) (UINTN) Pointer;
242
243 return PushStack (
244 &mCurrentExpressionStack,
245 &mCurrentExpressionPointer,
246 &mCurrentExpressionEnd,
247 &Data
248 );
249 }
250
251
252 /**
253 Pop current expression from the Stack
254
255 @param Pointer Pointer to current expression to be pop.
256
257 @retval EFI_SUCCESS The value was pushed onto the stack.
258 @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the stack.
259
260 **/
261 EFI_STATUS
262 PopCurrentExpression (
263 OUT VOID **Pointer
264 )
265 {
266 EFI_STATUS Status;
267 EFI_HII_VALUE Data;
268
269 Status = PopStack (
270 mCurrentExpressionStack,
271 &mCurrentExpressionPointer,
272 &Data
273 );
274
275 *Pointer = (VOID *) (UINTN) Data.Value.u64;
276
277 return Status;
278 }
279
280 /**
281 Reset stack pointer to begin of the stack.
282
283 **/
284 VOID
285 ResetMapExpressionListStack (
286 VOID
287 )
288 {
289 mMapExpressionListPointer = mMapExpressionListStack;
290 }
291
292
293 /**
294 Push the list of map expression onto the Stack
295
296 @param Pointer Pointer to the list of map expression to be pushed.
297
298 @retval EFI_SUCCESS The value was pushed onto the stack.
299 @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the stack.
300
301 **/
302 EFI_STATUS
303 PushMapExpressionList (
304 IN VOID *Pointer
305 )
306 {
307 EFI_HII_VALUE Data;
308
309 Data.Type = EFI_IFR_TYPE_NUM_SIZE_64;
310 Data.Value.u64 = (UINT64) (UINTN) Pointer;
311
312 return PushStack (
313 &mMapExpressionListStack,
314 &mMapExpressionListPointer,
315 &mMapExpressionListEnd,
316 &Data
317 );
318 }
319
320
321 /**
322 Pop the list of map expression from the Stack
323
324 @param Pointer Pointer to the list of map expression to be pop.
325
326 @retval EFI_SUCCESS The value was pushed onto the stack.
327 @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the stack.
328
329 **/
330 EFI_STATUS
331 PopMapExpressionList (
332 OUT VOID **Pointer
333 )
334 {
335 EFI_STATUS Status;
336 EFI_HII_VALUE Data;
337
338 Status = PopStack (
339 mMapExpressionListStack,
340 &mMapExpressionListPointer,
341 &Data
342 );
343
344 *Pointer = (VOID *) (UINTN) Data.Value.u64;
345
346 return Status;
347 }
348
349 /**
350 Reset stack pointer to begin of the stack.
351
352 **/
353 VOID
354 ResetScopeStack (
355 VOID
356 )
357 {
358 mOpCodeScopeStackPointer = mOpCodeScopeStack;
359 }
360
361
362 /**
363 Push an Operand onto the Stack
364
365 @param Operand Operand to push.
366
367 @retval EFI_SUCCESS The value was pushed onto the stack.
368 @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the
369 stack.
370
371 **/
372 EFI_STATUS
373 PushScope (
374 IN UINT8 Operand
375 )
376 {
377 EFI_HII_VALUE Data;
378
379 Data.Type = EFI_IFR_TYPE_NUM_SIZE_8;
380 Data.Value.u8 = Operand;
381
382 return PushStack (
383 &mOpCodeScopeStack,
384 &mOpCodeScopeStackPointer,
385 &mOpCodeScopeStackEnd,
386 &Data
387 );
388 }
389
390
391 /**
392 Pop an Operand from the Stack
393
394 @param Operand Operand to pop.
395
396 @retval EFI_SUCCESS The value was pushed onto the stack.
397 @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the
398 stack.
399
400 **/
401 EFI_STATUS
402 PopScope (
403 OUT UINT8 *Operand
404 )
405 {
406 EFI_STATUS Status;
407 EFI_HII_VALUE Data;
408
409 Status = PopStack (
410 mOpCodeScopeStack,
411 &mOpCodeScopeStackPointer,
412 &Data
413 );
414
415 *Operand = Data.Value.u8;
416
417 return Status;
418 }
419
420
421 /**
422 Push an Expression value onto the Stack
423
424 @param Value Expression value to push.
425
426 @retval EFI_SUCCESS The value was pushed onto the stack.
427 @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the
428 stack.
429
430 **/
431 EFI_STATUS
432 PushExpression (
433 IN EFI_HII_VALUE *Value
434 )
435 {
436 return PushStack (
437 &mExpressionEvaluationStack,
438 &mExpressionEvaluationStackPointer,
439 &mExpressionEvaluationStackEnd,
440 Value
441 );
442 }
443
444
445 /**
446 Pop an Expression value from the stack.
447
448 @param Value Expression value to pop.
449
450 @retval EFI_SUCCESS The value was popped onto the stack.
451 @retval EFI_ACCESS_DENIED The pop operation underflowed the stack
452
453 **/
454 EFI_STATUS
455 PopExpression (
456 OUT EFI_HII_VALUE *Value
457 )
458 {
459 return PopStack (
460 mExpressionEvaluationStack + mExpressionEvaluationStackOffset,
461 &mExpressionEvaluationStackPointer,
462 Value
463 );
464 }
465
466 /**
467 Get current stack offset from stack start.
468
469 @return Stack offset to stack start.
470 **/
471 UINTN
472 SaveExpressionEvaluationStackOffset (
473 )
474 {
475 UINTN TempStackOffset;
476 TempStackOffset = mExpressionEvaluationStackOffset;
477 mExpressionEvaluationStackOffset = mExpressionEvaluationStackPointer - mExpressionEvaluationStack;
478 return TempStackOffset;
479 }
480
481 /**
482 Restore stack offset based on input stack offset
483
484 @param StackOffset Offset to stack start.
485
486 **/
487 VOID
488 RestoreExpressionEvaluationStackOffset (
489 UINTN StackOffset
490 )
491 {
492 mExpressionEvaluationStackOffset = StackOffset;
493 }
494
495
496 /**
497 Search a Question in Form scope using its QuestionId.
498
499 @param Form The form which contains this Question.
500 @param QuestionId Id of this Question.
501
502 @retval Pointer The Question.
503 @retval NULL Specified Question not found in the form.
504
505 **/
506 FORM_BROWSER_STATEMENT *
507 IdToQuestion2 (
508 IN FORM_BROWSER_FORM *Form,
509 IN UINT16 QuestionId
510 )
511 {
512 LIST_ENTRY *Link;
513 FORM_BROWSER_STATEMENT *Question;
514
515 if (QuestionId == 0) {
516 //
517 // The value of zero is reserved
518 //
519 return NULL;
520 }
521
522 Link = GetFirstNode (&Form->StatementListHead);
523 while (!IsNull (&Form->StatementListHead, Link)) {
524 Question = FORM_BROWSER_STATEMENT_FROM_LINK (Link);
525
526 if (Question->QuestionId == QuestionId) {
527 return Question;
528 }
529
530 Link = GetNextNode (&Form->StatementListHead, Link);
531 }
532
533 return NULL;
534 }
535
536
537 /**
538 Search a Question in Formset scope using its QuestionId.
539
540 @param FormSet The formset which contains this form.
541 @param Form The form which contains this Question.
542 @param QuestionId Id of this Question.
543
544 @retval Pointer The Question.
545 @retval NULL Specified Question not found in the form.
546
547 **/
548 FORM_BROWSER_STATEMENT *
549 IdToQuestion (
550 IN FORM_BROWSER_FORMSET *FormSet,
551 IN FORM_BROWSER_FORM *Form,
552 IN UINT16 QuestionId
553 )
554 {
555 LIST_ENTRY *Link;
556 FORM_BROWSER_STATEMENT *Question;
557
558 //
559 // Search in the form scope first
560 //
561 Question = IdToQuestion2 (Form, QuestionId);
562 if (Question != NULL) {
563 return Question;
564 }
565
566 //
567 // Search in the formset scope
568 //
569 Link = GetFirstNode (&FormSet->FormListHead);
570 while (!IsNull (&FormSet->FormListHead, Link)) {
571 Form = FORM_BROWSER_FORM_FROM_LINK (Link);
572
573 Question = IdToQuestion2 (Form, QuestionId);
574 if (Question != NULL) {
575 return Question;
576 }
577
578 Link = GetNextNode (&FormSet->FormListHead, Link);
579 }
580
581 return NULL;
582 }
583
584
585 /**
586 Get Expression given its RuleId.
587
588 @param Form The form which contains this Expression.
589 @param RuleId Id of this Expression.
590
591 @retval Pointer The Expression.
592 @retval NULL Specified Expression not found in the form.
593
594 **/
595 FORM_EXPRESSION *
596 RuleIdToExpression (
597 IN FORM_BROWSER_FORM *Form,
598 IN UINT8 RuleId
599 )
600 {
601 LIST_ENTRY *Link;
602 FORM_EXPRESSION *Expression;
603
604 Link = GetFirstNode (&Form->ExpressionListHead);
605 while (!IsNull (&Form->ExpressionListHead, Link)) {
606 Expression = FORM_EXPRESSION_FROM_LINK (Link);
607
608 if ((Expression->Type == EFI_HII_EXPRESSION_RULE) && (Expression->RuleId == RuleId)) {
609 return Expression;
610 }
611
612 Link = GetNextNode (&Form->ExpressionListHead, Link);
613 }
614
615 return NULL;
616 }
617
618 /**
619 Convert the input Unicode character to upper.
620
621 @param String Th Unicode character to be converted.
622
623 **/
624 VOID
625 IfrStrToUpper (
626 IN CHAR16 *String
627 )
628 {
629 while (*String != 0) {
630 if ((*String >= 'a') && (*String <= 'z')) {
631 *String = (UINT16) ((*String) & ((UINT16) ~0x20));
632 }
633 String++;
634 }
635 }
636
637 /**
638 Evaluate opcode EFI_IFR_TO_STRING.
639
640 @param FormSet Formset which contains this opcode.
641 @param Format String format in EFI_IFR_TO_STRING.
642 @param Result Evaluation result for this opcode.
643
644 @retval EFI_SUCCESS Opcode evaluation success.
645 @retval Other Opcode evaluation failed.
646
647 **/
648 EFI_STATUS
649 IfrToString (
650 IN FORM_BROWSER_FORMSET *FormSet,
651 IN UINT8 Format,
652 OUT EFI_HII_VALUE *Result
653 )
654 {
655 EFI_STATUS Status;
656 EFI_HII_VALUE Value;
657 CHAR16 *PrintFormat;
658 CHAR16 Buffer[MAXIMUM_VALUE_CHARACTERS];
659 UINTN BufferSize;
660
661 Status = PopExpression (&Value);
662 if (EFI_ERROR (Status)) {
663 return Status;
664 }
665
666 switch (Value.Type) {
667 case EFI_IFR_TYPE_NUM_SIZE_8:
668 case EFI_IFR_TYPE_NUM_SIZE_16:
669 case EFI_IFR_TYPE_NUM_SIZE_32:
670 case EFI_IFR_TYPE_NUM_SIZE_64:
671 BufferSize = MAXIMUM_VALUE_CHARACTERS * sizeof (CHAR16);
672 switch (Format) {
673 case EFI_IFR_STRING_UNSIGNED_DEC:
674 case EFI_IFR_STRING_SIGNED_DEC:
675 PrintFormat = L"%ld";
676 break;
677
678 case EFI_IFR_STRING_LOWERCASE_HEX:
679 PrintFormat = L"%lx";
680 break;
681
682 case EFI_IFR_STRING_UPPERCASE_HEX:
683 PrintFormat = L"%lX";
684 break;
685
686 default:
687 return EFI_UNSUPPORTED;
688 }
689 UnicodeSPrint (Buffer, BufferSize, PrintFormat, Value.Value.u64);
690 break;
691
692 case EFI_IFR_TYPE_STRING:
693 CopyMem (Result, &Value, sizeof (EFI_HII_VALUE));
694 return EFI_SUCCESS;
695
696 case EFI_IFR_TYPE_BOOLEAN:
697 break;
698
699 default:
700 return EFI_UNSUPPORTED;
701 }
702
703 Result->Type = EFI_IFR_TYPE_STRING;
704 //Result->Value.string = NewString (String, FormSet->HiiHandle);
705 return EFI_SUCCESS;
706 }
707
708 /**
709 Evaluate opcode EFI_IFR_TO_UINT.
710
711 @param FormSet Formset which contains this opcode.
712 @param Result Evaluation result for this opcode.
713
714 @retval EFI_SUCCESS Opcode evaluation success.
715 @retval Other Opcode evaluation failed.
716
717 **/
718 EFI_STATUS
719 IfrToUint (
720 IN FORM_BROWSER_FORMSET *FormSet,
721 OUT EFI_HII_VALUE *Result
722 )
723 {
724 EFI_STATUS Status;
725 EFI_HII_VALUE Value;
726 CHAR16 *String;
727 CHAR16 *StringPtr;
728
729 Status = PopExpression (&Value);
730 if (EFI_ERROR (Status)) {
731 return Status;
732 }
733
734 if (Value.Type >= EFI_IFR_TYPE_OTHER) {
735 return EFI_UNSUPPORTED;
736 }
737
738 Status = EFI_SUCCESS;
739 if (Value.Type == EFI_IFR_TYPE_STRING) {
740 String = GetToken (Value.Value.string, FormSet->UnicodeBinary);
741 if (String == NULL) {
742 return EFI_NOT_FOUND;
743 }
744
745 IfrStrToUpper (String);
746 StringPtr = StrStr (String, L"0X");
747 if (StringPtr != NULL) {
748 //
749 // Hex string
750 //
751 Result->Value.u64 = FceStrHexToUint64 (String);
752 } else {
753 //
754 // decimal string
755 //
756 Result->Value.u64 = FceStrDecimalToUint64 (String);
757 }
758 FreePool (String);
759 } else {
760 CopyMem (Result, &Value, sizeof (EFI_HII_VALUE));
761 }
762
763 Result->Type = EFI_IFR_TYPE_NUM_SIZE_64;
764 return Status;
765 }
766
767 /**
768 Evaluate opcode EFI_IFR_CATENATE.
769
770 @param FormSet Formset which contains this opcode.
771 @param Result Evaluation result for this opcode.
772
773 @retval EFI_SUCCESS Opcode evaluation success.
774 @retval Other Opcode evaluation failed.
775
776 **/
777 EFI_STATUS
778 IfrCatenate (
779 IN FORM_BROWSER_FORMSET *FormSet,
780 OUT EFI_HII_VALUE *Result
781 )
782 {
783 EFI_STATUS Status;
784 EFI_HII_VALUE Value;
785 CHAR16 *String[2];
786 UINTN Index;
787 CHAR16 *StringPtr;
788 UINTN Size;
789
790 //
791 // String[0] - The second string
792 // String[1] - The first string
793 //
794 String[0] = NULL;
795 String[1] = NULL;
796 StringPtr = NULL;
797 Status = EFI_SUCCESS;
798
799 for (Index = 0; Index < 2; Index++) {
800 Status = PopExpression (&Value);
801 if (EFI_ERROR (Status)) {
802 goto Done;
803 }
804
805 if (Value.Type != EFI_IFR_TYPE_STRING) {
806 Status = EFI_UNSUPPORTED;
807 goto Done;
808 }
809
810 String[Index] = GetToken (Value.Value.string, FormSet->UnicodeBinary);
811 if (String[Index] == NULL) {
812 Status = EFI_NOT_FOUND;
813 goto Done;
814 }
815 }
816
817 Size = FceStrSize (String[0]);
818 StringPtr= AllocatePool (FceStrSize (String[1]) + Size);
819 ASSERT (StringPtr != NULL);
820 StrCpy (StringPtr, String[1]);
821 StrCat (StringPtr, String[0]);
822
823 Result->Type = EFI_IFR_TYPE_STRING;
824 //Result->Value.string = NewString (StringPtr, FormSet->HiiHandle);
825
826 Done:
827 if (String[0] != NULL) {
828 FreePool (String[0]);
829 }
830 if (String[1] != NULL) {
831 FreePool (String[1]);
832 }
833 if (StringPtr != NULL) {
834 FreePool (StringPtr);
835 }
836
837 return Status;
838 }
839
840 /**
841 Evaluate opcode EFI_IFR_MATCH.
842
843 @param FormSet Formset which contains this opcode.
844 @param Result Evaluation result for this opcode.
845
846 @retval EFI_SUCCESS Opcode evaluation success.
847 @retval Other Opcode evaluation failed.
848
849 **/
850 EFI_STATUS
851 IfrMatch (
852 IN FORM_BROWSER_FORMSET *FormSet,
853 OUT EFI_HII_VALUE *Result
854 )
855 {
856 EFI_STATUS Status;
857 EFI_HII_VALUE Value;
858 CHAR16 *String[2];
859 UINTN Index;
860
861 //
862 // String[0] - The string to search
863 // String[1] - pattern
864 //
865 String[0] = NULL;
866 String[1] = NULL;
867 Status = EFI_SUCCESS;
868 for (Index = 0; Index < 2; Index++) {
869 Status = PopExpression (&Value);
870 if (EFI_ERROR (Status)) {
871 goto Done;
872 }
873
874 if (Value.Type != EFI_IFR_TYPE_STRING) {
875 Status = EFI_UNSUPPORTED;
876 goto Done;
877 }
878
879 String[Index] = GetToken (Value.Value.string, FormSet->UnicodeBinary);
880 if (String [Index] == NULL) {
881 Status = EFI_NOT_FOUND;
882 goto Done;
883 }
884 }
885
886 Result->Type = EFI_IFR_TYPE_BOOLEAN;
887 Result->Value.b = MetaiMatch (String[0], String[1]);
888
889 Done:
890 if (String[0] != NULL) {
891 FreePool (String[0]);
892 }
893 if (String[1] != NULL) {
894 FreePool (String[1]);
895 }
896
897 return Status;
898 }
899
900
901 /**
902 Evaluate opcode EFI_IFR_FIND.
903
904 @param FormSet Formset which contains this opcode.
905 @param Format Case sensitive or insensitive.
906 @param Result Evaluation result for this opcode.
907
908 @retval EFI_SUCCESS Opcode evaluation success.
909 @retval Other Opcode evaluation failed.
910
911 **/
912 EFI_STATUS
913 IfrFind (
914 IN FORM_BROWSER_FORMSET *FormSet,
915 IN UINT8 Format,
916 OUT EFI_HII_VALUE *Result
917 )
918 {
919 EFI_STATUS Status;
920 EFI_HII_VALUE Value;
921 CHAR16 *String[2];
922 UINTN Base;
923 CHAR16 *StringPtr;
924 UINTN Index;
925
926 if (Format > EFI_IFR_FF_CASE_INSENSITIVE) {
927 return EFI_UNSUPPORTED;
928 }
929
930 Status = PopExpression (&Value);
931 if (EFI_ERROR (Status)) {
932 return Status;
933 }
934 if (Value.Type > EFI_IFR_TYPE_NUM_SIZE_64) {
935 return EFI_UNSUPPORTED;
936 }
937 Base = (UINTN) Value.Value.u64;
938
939 //
940 // String[0] - sub-string
941 // String[1] - The string to search
942 //
943 String[0] = NULL;
944 String[1] = NULL;
945 for (Index = 0; Index < 2; Index++) {
946 Status = PopExpression (&Value);
947 if (EFI_ERROR (Status)) {
948 goto Done;
949 }
950
951 if (Value.Type != EFI_IFR_TYPE_STRING) {
952 Status = EFI_UNSUPPORTED;
953 goto Done;
954 }
955
956 String[Index] = GetToken (Value.Value.string, FormSet->UnicodeBinary);
957 if (String[Index] == NULL) {
958 Status = EFI_NOT_FOUND;
959 goto Done;
960 }
961
962 if (Format == EFI_IFR_FF_CASE_INSENSITIVE) {
963 //
964 // Case insensitive, convert both string to upper case
965 //
966 IfrStrToUpper (String[Index]);
967 }
968 }
969
970 Result->Type = EFI_IFR_TYPE_NUM_SIZE_64;
971 if (Base >= FceStrLen (String[1])) {
972 Result->Value.u64 = 0xFFFFFFFFFFFFFFFFULL;
973 } else {
974 StringPtr = StrStr (String[1] + Base, String[0]);
975 Result->Value.u64 = (StringPtr == NULL) ? 0xFFFFFFFFFFFFFFFFULL : (StringPtr - String[1]);
976 }
977
978 Done:
979 if (String[0] != NULL) {
980 FreePool (String[0]);
981 }
982 if (String[1] != NULL) {
983 FreePool (String[1]);
984 }
985
986 return Status;
987 }
988
989
990 /**
991 Evaluate opcode EFI_IFR_MID.
992
993 @param FormSet Formset which contains this opcode.
994 @param Result Evaluation result for this opcode.
995
996 @retval EFI_SUCCESS Opcode evaluation success.
997 @retval Other Opcode evaluation failed.
998
999 **/
1000 EFI_STATUS
1001 IfrMid (
1002 IN FORM_BROWSER_FORMSET *FormSet,
1003 OUT EFI_HII_VALUE *Result
1004 )
1005 {
1006 EFI_STATUS Status;
1007 EFI_HII_VALUE Value;
1008 CHAR16 *String;
1009 UINTN Base;
1010 UINTN Length;
1011 CHAR16 *SubString;
1012
1013 Status = PopExpression (&Value);
1014 if (EFI_ERROR (Status)) {
1015 return Status;
1016 }
1017 if (Value.Type > EFI_IFR_TYPE_NUM_SIZE_64) {
1018 return EFI_UNSUPPORTED;
1019 }
1020 Length = (UINTN) Value.Value.u64;
1021
1022 Status = PopExpression (&Value);
1023 if (EFI_ERROR (Status)) {
1024 return Status;
1025 }
1026 if (Value.Type > EFI_IFR_TYPE_NUM_SIZE_64) {
1027 return EFI_UNSUPPORTED;
1028 }
1029 Base = (UINTN) Value.Value.u64;
1030
1031 Status = PopExpression (&Value);
1032 if (EFI_ERROR (Status)) {
1033 return Status;
1034 }
1035 if (Value.Type != EFI_IFR_TYPE_STRING) {
1036 return EFI_UNSUPPORTED;
1037 }
1038 String = GetToken (Value.Value.string, FormSet->UnicodeBinary);
1039 if (String == NULL) {
1040 return EFI_NOT_FOUND;
1041 }
1042
1043 if ((Length == 0) || (Base >= FceStrLen (String))) {
1044 SubString = gEmptyString;
1045 } else {
1046 SubString = String + Base;
1047 if ((Base + Length) < FceStrLen (String)) {
1048 SubString[Length] = L'\0';
1049 }
1050 }
1051
1052 Result->Type = EFI_IFR_TYPE_STRING;
1053 //Result->Value.string = NewString (SubString, FormSet->HiiHandle);
1054
1055 FreePool (String);
1056
1057 return Status;
1058 }
1059
1060 /**
1061 Evaluate opcode EFI_IFR_TOKEN.
1062
1063 @param FormSet Formset which contains this opcode.
1064 @param Result Evaluation result for this opcode.
1065
1066 @retval EFI_SUCCESS Opcode evaluation success.
1067 @retval Other Opcode evaluation failed.
1068
1069 **/
1070 EFI_STATUS
1071 IfrToken (
1072 IN FORM_BROWSER_FORMSET *FormSet,
1073 OUT EFI_HII_VALUE *Result
1074 )
1075 {
1076 EFI_STATUS Status;
1077 EFI_HII_VALUE Value;
1078 CHAR16 *String[2];
1079 UINTN Count;
1080 CHAR16 *Delimiter;
1081 CHAR16 *SubString;
1082 CHAR16 *StringPtr;
1083 UINTN Index;
1084
1085 Status = PopExpression (&Value);
1086 if (EFI_ERROR (Status)) {
1087 return Status;
1088 }
1089 if (Value.Type > EFI_IFR_TYPE_NUM_SIZE_64) {
1090 return EFI_UNSUPPORTED;
1091 }
1092 Count = (UINTN) Value.Value.u64;
1093
1094 //
1095 // String[0] - Delimiter
1096 // String[1] - The string to search
1097 //
1098 String[0] = NULL;
1099 String[1] = NULL;
1100 for (Index = 0; Index < 2; Index++) {
1101 Status = PopExpression (&Value);
1102 if (EFI_ERROR (Status)) {
1103 goto Done;
1104 }
1105
1106 if (Value.Type != EFI_IFR_TYPE_STRING) {
1107 Status = EFI_UNSUPPORTED;
1108 goto Done;
1109 }
1110
1111 String[Index] = GetToken (Value.Value.string, FormSet->UnicodeBinary);
1112 if (String[Index] == NULL) {
1113 Status = EFI_NOT_FOUND;
1114 goto Done;
1115 }
1116 }
1117
1118 Delimiter = String[0];
1119 SubString = String[1];
1120 while (Count > 0) {
1121 SubString = StrStr (SubString, Delimiter);
1122 if (SubString != NULL) {
1123 //
1124 // Skip over the delimiter
1125 //
1126 SubString = SubString + FceStrLen (Delimiter);
1127 } else {
1128 break;
1129 }
1130 Count--;
1131 }
1132
1133 if (SubString == NULL) {
1134 //
1135 // nth delimited sub-string not found, push an empty string
1136 //
1137 SubString = gEmptyString;
1138 } else {
1139 //
1140 // Put a NULL terminator for nth delimited sub-string
1141 //
1142 StringPtr = StrStr (SubString, Delimiter);
1143 if (StringPtr != NULL) {
1144 *StringPtr = L'\0';
1145 }
1146 }
1147
1148 Result->Type = EFI_IFR_TYPE_STRING;
1149 //Result->Value.string = NewString (SubString, FormSet->HiiHandle);
1150
1151 Done:
1152 if (String[0] != NULL) {
1153 FreePool (String[0]);
1154 }
1155 if (String[1] != NULL) {
1156 FreePool (String[1]);
1157 }
1158
1159 return Status;
1160 }
1161
1162
1163 /**
1164 Evaluate opcode EFI_IFR_SPAN.
1165
1166 @param FormSet Formset which contains this opcode.
1167 @param Flags FIRST_MATCHING or FIRST_NON_MATCHING.
1168 @param Result Evaluation result for this opcode.
1169
1170 @retval EFI_SUCCESS Opcode evaluation success.
1171 @retval Other Opcode evaluation failed.
1172
1173 **/
1174 EFI_STATUS
1175 IfrSpan (
1176 IN FORM_BROWSER_FORMSET *FormSet,
1177 IN UINT8 Flags,
1178 OUT EFI_HII_VALUE *Result
1179 )
1180 {
1181 EFI_STATUS Status;
1182 EFI_HII_VALUE Value;
1183 CHAR16 *String[2];
1184 CHAR16 *Charset;
1185 UINTN Base;
1186 UINTN Index;
1187 CHAR16 *StringPtr;
1188 BOOLEAN Found;
1189
1190 Status = PopExpression (&Value);
1191 if (EFI_ERROR (Status)) {
1192 return Status;
1193 }
1194 if (Value.Type > EFI_IFR_TYPE_NUM_SIZE_64) {
1195 return EFI_UNSUPPORTED;
1196 }
1197 Base = (UINTN) Value.Value.u64;
1198
1199 //
1200 // String[0] - Charset
1201 // String[1] - The string to search
1202 //
1203 String[0] = NULL;
1204 String[1] = NULL;
1205 for (Index = 0; Index < 2; Index++) {
1206 Status = PopExpression (&Value);
1207 if (EFI_ERROR (Status)) {
1208 goto Done;
1209 }
1210
1211 if (Value.Type != EFI_IFR_TYPE_STRING) {
1212 Status = EFI_UNSUPPORTED;
1213 goto Done;
1214 }
1215
1216 String[Index] = GetToken (Value.Value.string, FormSet->UnicodeBinary);
1217 if (String [Index] == NULL) {
1218 Status = EFI_NOT_FOUND;
1219 goto Done;
1220 }
1221 }
1222
1223 if (Base >= FceStrLen (String[1])) {
1224 Status = EFI_UNSUPPORTED;
1225 goto Done;
1226 }
1227
1228 Found = FALSE;
1229 StringPtr = String[1] + Base;
1230 Charset = String[0];
1231 while (*StringPtr != 0 && !Found) {
1232 Index = 0;
1233 while (Charset[Index] != 0) {
1234 if ((*StringPtr >= Charset[Index]) && (*StringPtr <= Charset[Index + 1])) {
1235 if (Flags == EFI_IFR_FLAGS_FIRST_MATCHING) {
1236 Found = TRUE;
1237 break;
1238 }
1239 } else {
1240 if (Flags == EFI_IFR_FLAGS_FIRST_NON_MATCHING) {
1241 Found = TRUE;
1242 break;
1243 }
1244 }
1245 //
1246 // Skip characters pair representing low-end of a range and high-end of a range
1247 //
1248 Index += 2;
1249 }
1250
1251 if (!Found) {
1252 StringPtr++;
1253 }
1254 }
1255
1256 Result->Type = EFI_IFR_TYPE_NUM_SIZE_64;
1257 Result->Value.u64 = StringPtr - String[1];
1258
1259 Done:
1260 if (String[0] != NULL) {
1261 FreePool (String[0]);
1262 }
1263 if (String[1] != NULL) {
1264 FreePool (String[1]);
1265 }
1266
1267 return Status;
1268 }
1269
1270
1271 /**
1272 Zero extend integer/boolean/date/time to UINT64 for comparing.
1273
1274 @param Value HII Value to be converted.
1275
1276 **/
1277 VOID
1278 ExtendValueToU64 (
1279 IN EFI_HII_VALUE *Value
1280 )
1281 {
1282 UINT64 Temp;
1283
1284 Temp = 0;
1285 switch (Value->Type) {
1286 case EFI_IFR_TYPE_NUM_SIZE_8:
1287 Temp = Value->Value.u8;
1288 break;
1289
1290 case EFI_IFR_TYPE_NUM_SIZE_16:
1291 Temp = Value->Value.u16;
1292 break;
1293
1294 case EFI_IFR_TYPE_NUM_SIZE_32:
1295 Temp = Value->Value.u32;
1296 break;
1297
1298 case EFI_IFR_TYPE_BOOLEAN:
1299 Temp = Value->Value.b;
1300 break;
1301
1302 case EFI_IFR_TYPE_TIME:
1303 Temp = Value->Value.u32 & 0xffffff;
1304 break;
1305
1306 case EFI_IFR_TYPE_DATE:
1307 Temp = Value->Value.u32;
1308 break;
1309
1310 default:
1311 return;
1312 }
1313
1314 Value->Value.u64 = Temp;
1315 }
1316
1317
1318 /**
1319 Compare two Hii value.
1320
1321 @param Value1 Expression value to compare on left-hand.
1322 @param Value2 Expression value to compare on right-hand.
1323 @param FormSet The pointer to the Formset.
1324
1325 @retval EFI_INVALID_PARAMETER Could not perform compare on two values.
1326 @retval 0 Two operators equal.
1327 @return Positive value if Value1 is greater than Value2.
1328 @retval Negative value if Value1 is less than Value2.
1329
1330 **/
1331 INTN
1332 CompareHiiValue (
1333 IN EFI_HII_VALUE *Value1,
1334 IN EFI_HII_VALUE *Value2,
1335 IN FORM_BROWSER_FORMSET *FormSet
1336 )
1337 {
1338 INTN Result;
1339 INT64 Temp64;
1340 CHAR16 *Str1;
1341 CHAR16 *Str2;
1342
1343 if ((Value1->Type >= EFI_IFR_TYPE_OTHER) || (Value2->Type >= EFI_IFR_TYPE_OTHER) ) {
1344 return EFI_INVALID_PARAMETER;
1345 }
1346
1347 if ((Value1->Type == EFI_IFR_TYPE_STRING) || (Value2->Type == EFI_IFR_TYPE_STRING) ) {
1348 if (Value1->Type != Value2->Type) {
1349 //
1350 // Both Operator should be type of String
1351 //
1352 return EFI_INVALID_PARAMETER;
1353 }
1354
1355 if ((Value1->Value.string == 0) || (Value2->Value.string == 0)) {
1356 //
1357 // StringId 0 is reserved
1358 //
1359 return EFI_INVALID_PARAMETER;
1360 }
1361
1362 if (Value1->Value.string == Value2->Value.string) {
1363 return 0;
1364 }
1365
1366 Str1 = GetToken (Value1->Value.string, FormSet->UnicodeBinary);
1367 if (Str1 == NULL) {
1368 //
1369 // String not found
1370 //
1371 return EFI_INVALID_PARAMETER;
1372 }
1373
1374 Str2 = GetToken (Value2->Value.string, FormSet->UnicodeBinary);
1375 if (Str2 == NULL) {
1376 FreePool (Str1);
1377 return EFI_INVALID_PARAMETER;
1378 }
1379
1380 Result = FceStrCmp (Str1, Str2);
1381
1382 FreePool (Str1);
1383 FreePool (Str2);
1384
1385 return Result;
1386 }
1387
1388 //
1389 // Take remain types(integer, boolean, date/time) as integer
1390 //
1391 Temp64 = (INT64) (Value1->Value.u64 - Value2->Value.u64);
1392 if (Temp64 > 0) {
1393 Result = 1;
1394 } else if (Temp64 < 0) {
1395 Result = -1;
1396 } else {
1397 Result = 0;
1398 }
1399
1400 return Result;
1401 }
1402
1403 /**
1404 Tell whether this Operand is an constant Expression or not
1405
1406 @param Operand Operand of an IFR OpCode.
1407
1408 @retval TRUE This is an Expression OpCode.
1409 @retval FALSE Not an Expression OpCode.
1410
1411 **/
1412 BOOLEAN
1413 IsConstantExpressionOpCode (
1414 IN UINT8 Operand
1415 )
1416 {
1417 if ((Operand == EFI_IFR_EQ_ID_VAL_OP) ||
1418 (Operand == EFI_IFR_EQ_ID_ID_OP) ||
1419 (Operand == EFI_IFR_EQ_ID_VAL_LIST_OP )||
1420 (Operand == EFI_IFR_QUESTION_REF1_OP) ||
1421 (Operand == EFI_IFR_QUESTION_REF2_OP) ||
1422 (Operand == EFI_IFR_QUESTION_REF3_OP) ||
1423 (Operand == EFI_IFR_THIS_OP ) ||
1424 (Operand == EFI_IFR_SECURITY_OP) ||
1425 (Operand == EFI_IFR_GET_OP) ||
1426 (Operand == EFI_IFR_SET_OP)
1427 ) {
1428 return FALSE;
1429 } else {
1430 return TRUE;
1431 }
1432 }
1433
1434 /**
1435 Update the HiiValue of question from its variable.
1436
1437 @param FormSet FormSet associated with this expression.
1438 @param Question The pointer to the Question
1439
1440 @return EFI_SUCCESS
1441 @return EFI_NOT_FOUND
1442 **/
1443 EFI_STATUS
1444 UpdateHiiValue (
1445 IN FORM_BROWSER_FORMSET *FormSet,
1446 IN FORM_BROWSER_STATEMENT *Question
1447 )
1448 {
1449 EFI_STATUS Status;
1450 FORMSET_STORAGE *VarList;
1451 UINT8 *VarBuffer;
1452 EFI_HII_VALUE *HiiValue;
1453
1454 Status = EFI_SUCCESS;
1455 HiiValue = &Question->HiiValue;
1456
1457 Status = SearchVarStorage (
1458 Question,
1459 NULL,
1460 Question->VarStoreInfo.VarOffset,
1461 FormSet->StorageListHead,
1462 (CHAR8 **)&VarBuffer,
1463 &VarList
1464 );
1465 if (EFI_ERROR(Status)) {
1466 return Status;
1467 }
1468 if (Question->QuestionReferToBitField) {
1469 GetBitsQuestionValue (Question, VarBuffer, &HiiValue->Value.u32);
1470 } else {
1471 CopyMem (&HiiValue->Value.u64, VarBuffer, Question->StorageWidth);
1472 }
1473 return Status;
1474 }
1475 /**
1476 Evaluate the result of a HII expression.
1477
1478 If Expression is NULL, then ASSERT.
1479
1480 @param FormSet FormSet associated with this expression.
1481 @param Form Form associated with this expression.
1482 @param Expression Expression to be evaluated.
1483 @param ConstantExpression The pointer to the flag of constant expression. If constant, will return TRUE.
1484
1485 @retval EFI_SUCCESS The expression evaluated successfuly
1486 @retval EFI_NOT_FOUND The Question which referenced by a QuestionId
1487 could not be found.
1488 @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the
1489 stack.
1490 @retval EFI_ACCESS_DENIED The pop operation underflowed the stack
1491 @retval EFI_INVALID_PARAMETER Syntax error with the Expression
1492
1493 **/
1494 EFI_STATUS
1495 EvaluateExpression (
1496 IN FORM_BROWSER_FORMSET *FormSet,
1497 IN FORM_BROWSER_FORM *Form,
1498 IN OUT FORM_EXPRESSION *Expression,
1499 IN OUT BOOLEAN *ConstantExpression
1500 )
1501 {
1502 EFI_STATUS Status;
1503 LIST_ENTRY *Link;
1504 EXPRESSION_OPCODE *OpCode;
1505 FORM_BROWSER_STATEMENT *Question;
1506 FORM_BROWSER_STATEMENT *Question2;
1507 UINT16 Index;
1508 EFI_HII_VALUE Data1;
1509 EFI_HII_VALUE Data2;
1510 EFI_HII_VALUE Data3;
1511 FORM_EXPRESSION *RuleExpression;
1512 EFI_HII_VALUE *Value;
1513 INTN Result;
1514 CHAR16 *StrPtr;
1515 UINT32 TempValue;
1516 LIST_ENTRY *SubExpressionLink;
1517 FORM_EXPRESSION *SubExpression;
1518 UINTN StackOffset;
1519 UINTN TempLength;
1520 CHAR16 TempStr[5];
1521 UINT8 DigitUint8;
1522 UINT8 *TempBuffer;
1523
1524 //
1525 // Save current stack offset.
1526 //
1527 StackOffset = SaveExpressionEvaluationStackOffset ();
1528
1529 ASSERT (Expression != NULL);
1530 Expression->Result.Type = EFI_IFR_TYPE_OTHER;
1531
1532 Link = GetFirstNode (&Expression->OpCodeListHead);
1533 while (!IsNull (&Expression->OpCodeListHead, Link)) {
1534 OpCode = EXPRESSION_OPCODE_FROM_LINK (Link);
1535
1536 Link = GetNextNode (&Expression->OpCodeListHead, Link);
1537
1538 ZeroMem (&Data1, sizeof (EFI_HII_VALUE));
1539 ZeroMem (&Data2, sizeof (EFI_HII_VALUE));
1540 ZeroMem (&Data3, sizeof (EFI_HII_VALUE));
1541
1542 Value = &Data3;
1543 Value->Type = EFI_IFR_TYPE_BOOLEAN;
1544 Status = EFI_SUCCESS;
1545
1546 //
1547 // Check whether it is a constant expression or not
1548 //
1549 if (*ConstantExpression) {
1550 *ConstantExpression = IsConstantExpressionOpCode (OpCode->Operand);
1551 }
1552
1553 switch (OpCode->Operand) {
1554 //
1555 // Built-in functions
1556 //
1557 case EFI_IFR_EQ_ID_VAL_OP:
1558 Question = IdToQuestion (FormSet, Form, OpCode->QuestionId);
1559 if (Question == NULL) {
1560 Status = EFI_NOT_FOUND;
1561 goto Done;
1562 }
1563 UpdateHiiValue (FormSet, Question);
1564 Result = CompareHiiValue (&Question->HiiValue, &OpCode->Value, FormSet);
1565 if ((EFI_STATUS)Result == EFI_INVALID_PARAMETER) {
1566 Status = EFI_INVALID_PARAMETER;
1567 goto Done;
1568 }
1569 Value->Value.b = (BOOLEAN) ((Result == 0) ? TRUE : FALSE);
1570 break;
1571
1572 case EFI_IFR_EQ_ID_ID_OP:
1573 Question = IdToQuestion (FormSet, Form, OpCode->QuestionId);
1574 if (Question == NULL) {
1575 Status = EFI_NOT_FOUND;
1576 goto Done;
1577 }
1578
1579 Question2 = IdToQuestion (FormSet, Form, OpCode->QuestionId2);
1580 if (Question2 == NULL) {
1581 Status = EFI_NOT_FOUND;
1582 goto Done;
1583 }
1584 UpdateHiiValue (FormSet, Question);
1585 UpdateHiiValue (FormSet, Question2);
1586 Result = CompareHiiValue (&Question->HiiValue, &Question2->HiiValue, FormSet);
1587 if ((EFI_STATUS)Result == EFI_INVALID_PARAMETER) {
1588 Status = EFI_INVALID_PARAMETER;
1589 goto Done;
1590 }
1591 Value->Value.b = (BOOLEAN) ((Result == 0) ? TRUE : FALSE);
1592 break;
1593
1594 case EFI_IFR_EQ_ID_VAL_LIST_OP:
1595
1596 Question = IdToQuestion (FormSet, Form, OpCode->QuestionId);
1597 if (Question == NULL) {
1598 Status = EFI_NOT_FOUND;
1599 goto Done;
1600 }
1601 UpdateHiiValue (FormSet, Question);
1602 Value->Value.b = FALSE;
1603 for (Index =0; Index < OpCode->ListLength; Index++) {
1604 if (Question->HiiValue.Value.u16 == OpCode->ValueList[Index]) {
1605 Value->Value.b = TRUE;
1606 break;
1607 }
1608 }
1609 break;
1610
1611 case EFI_IFR_DUP_OP:
1612 Status = PopExpression (Value);
1613 if (EFI_ERROR (Status)) {
1614 goto Done;
1615 }
1616
1617 Status = PushExpression (Value);
1618 break;
1619
1620 case EFI_IFR_QUESTION_REF1_OP:
1621 case EFI_IFR_THIS_OP:
1622 Question = IdToQuestion (FormSet, Form, OpCode->QuestionId);
1623 if (Question == NULL) {
1624 Status = EFI_NOT_FOUND;
1625 goto Done;
1626 }
1627 UpdateHiiValue (FormSet, Question);
1628 Value = &Question->HiiValue;
1629 break;
1630
1631 case EFI_IFR_SECURITY_OP:
1632 //
1633 // Do nothing, as no need for static scaning
1634 //
1635 break;
1636
1637 case EFI_IFR_GET_OP:
1638 //
1639 // Get Value from VarStore buffer, EFI VarStore, Name/Value VarStore.
1640 //
1641 Value->Type = EFI_IFR_TYPE_UNDEFINED;
1642 Value->Value.u8 = 0;
1643 if (OpCode->VarStorage != NULL) {
1644 switch (OpCode->VarStorage->Type) {
1645 case EFI_IFR_VARSTORE_OP:
1646 //
1647 // Get value from Buffer
1648 //
1649 Value->Type = OpCode->ValueType;
1650 CopyMem (&Value->Value, OpCode->VarStorage->Buffer + OpCode->VarStoreInfo.VarOffset, OpCode->ValueWidth);
1651 break;
1652
1653 case EFI_IFR_VARSTORE_EFI_OP:
1654 //
1655 // Get value from Buffer
1656 //
1657 if (OpCode->VarStorage->NewEfiVarstore) {
1658 Value->Type = OpCode->ValueType;
1659 CopyMem (&Value->Value, OpCode->VarStorage->Buffer + OpCode->VarStoreInfo.VarOffset, OpCode->ValueWidth);
1660 } else {
1661 CopyMem (&Value->Value, OpCode->VarStorage->Buffer, OpCode->ValueWidth);
1662 }
1663
1664
1665 break;
1666 case EFI_HII_VARSTORE_NAME_VALUE:
1667 if (OpCode->ValueType != EFI_IFR_TYPE_STRING) {
1668 //
1669 // Get value from string except for STRING value.
1670 //
1671 Status = GetValueByName (OpCode->VarStorage, OpCode->ValueName, &StrPtr);
1672 if (!EFI_ERROR (Status)) {
1673 ASSERT (StrPtr != NULL);
1674 TempLength = FceStrLen (StrPtr);
1675 if (OpCode->ValueWidth >= ((TempLength + 1) / 2)) {
1676 Value->Type = OpCode->ValueType;
1677 TempBuffer = (UINT8 *) &Value->Value;
1678 ZeroMem (TempStr, sizeof (TempStr));
1679 for (Index = 0; Index < TempLength; Index ++) {
1680 TempStr[0] = StrPtr[TempLength - Index - 1];
1681 DigitUint8 = (UINT8) FceStrHexToUint64 (TempStr);
1682 if ((Index & 1) == 0) {
1683 TempBuffer [Index/2] = DigitUint8;
1684 } else {
1685 TempBuffer [Index/2] = (UINT8) ((DigitUint8 << 4) + TempBuffer [Index/2]);
1686 }
1687 }
1688 }
1689 free (StrPtr);
1690 StrPtr = NULL;
1691 }
1692 }
1693 break;
1694 default:
1695 //
1696 // Not recognize storage.
1697 //
1698 Status = EFI_UNSUPPORTED;
1699 goto Done;
1700 }
1701 }
1702
1703 break;
1704
1705 case EFI_IFR_QUESTION_REF3_OP:
1706 if (OpCode->DevicePath == 0) {
1707 //
1708 // EFI_IFR_QUESTION_REF3
1709 // Pop an expression from the expression stack
1710 //
1711 Status = PopExpression (Value);
1712 if (EFI_ERROR (Status)) {
1713 goto Done;
1714 }
1715
1716 //
1717 // Validate the expression value
1718 //
1719 if ((Value->Type > EFI_IFR_TYPE_NUM_SIZE_64) || (Value->Value.u64 > 0xffff)) {
1720 Status = EFI_NOT_FOUND;
1721 goto Done;
1722 }
1723
1724 Question = IdToQuestion (FormSet, Form, Value->Value.u16);
1725 if (Question == NULL) {
1726 Status = EFI_NOT_FOUND;
1727 goto Done;
1728 }
1729
1730 //
1731 // push the questions' value on to the expression stack
1732 //
1733 Value = &Question->HiiValue;
1734 } else {
1735 //
1736 // BUGBUG: push 0 for EFI_IFR_QUESTION_REF3_2 and EFI_IFR_QUESTION_REF3_3,
1737 // since it is impractical to evaluate the value of a Question in another
1738 // Hii Package list.
1739 //
1740 ZeroMem (Value, sizeof (EFI_HII_VALUE));
1741 }
1742 break;
1743
1744 case EFI_IFR_RULE_REF_OP:
1745 //
1746 // Find expression for this rule
1747 //
1748 RuleExpression = RuleIdToExpression (Form, OpCode->RuleId);
1749 if (RuleExpression == NULL) {
1750 Status = EFI_NOT_FOUND;
1751 goto Done;
1752 }
1753
1754 //
1755 // Evaluate this rule expression
1756 //
1757 Status = EvaluateExpression (FormSet, Form, RuleExpression, ConstantExpression);
1758 if (EFI_ERROR (Status)) {
1759 goto Done;
1760 }
1761
1762 Value = &RuleExpression->Result;
1763 break;
1764
1765 case EFI_IFR_STRING_REF1_OP:
1766 Value->Type = EFI_IFR_TYPE_STRING;
1767 Value->Value.string = OpCode->Value.Value.string;
1768 break;
1769
1770 //
1771 // Constant
1772 //
1773 case EFI_IFR_TRUE_OP:
1774 case EFI_IFR_FALSE_OP:
1775 case EFI_IFR_ONE_OP:
1776 case EFI_IFR_ONES_OP:
1777 case EFI_IFR_UINT8_OP:
1778 case EFI_IFR_UINT16_OP:
1779 case EFI_IFR_UINT32_OP:
1780 case EFI_IFR_UINT64_OP:
1781 case EFI_IFR_UNDEFINED_OP:
1782 case EFI_IFR_VERSION_OP:
1783 case EFI_IFR_ZERO_OP:
1784 Value = &OpCode->Value;
1785 break;
1786
1787 //
1788 // unary-op
1789 //
1790 case EFI_IFR_LENGTH_OP:
1791 Status = PopExpression (Value);
1792 if (EFI_ERROR (Status)) {
1793 goto Done;
1794 }
1795 if (Value->Type != EFI_IFR_TYPE_STRING) {
1796 Status = EFI_INVALID_PARAMETER;
1797 goto Done;
1798 }
1799
1800 StrPtr = GetToken (Value->Value.string, FormSet->UnicodeBinary);
1801 if (StrPtr == NULL) {
1802 Status = EFI_INVALID_PARAMETER;
1803 goto Done;
1804 }
1805
1806 Value->Type = EFI_IFR_TYPE_NUM_SIZE_64;
1807 Value->Value.u64 = FceStrLen (StrPtr);
1808 FreePool (StrPtr);
1809 break;
1810
1811 case EFI_IFR_NOT_OP:
1812 Status = PopExpression (Value);
1813 if (EFI_ERROR (Status)) {
1814 goto Done;
1815 }
1816 if (Value->Type != EFI_IFR_TYPE_BOOLEAN) {
1817 Status = EFI_INVALID_PARAMETER;
1818 goto Done;
1819 }
1820 Value->Value.b = (BOOLEAN) (!Value->Value.b);
1821 break;
1822
1823 case EFI_IFR_QUESTION_REF2_OP:
1824 //
1825 // Pop an expression from the expression stack
1826 //
1827 Status = PopExpression (Value);
1828 if (EFI_ERROR (Status)) {
1829 goto Done;
1830 }
1831
1832 //
1833 // Validate the expression value
1834 //
1835 if ((Value->Type > EFI_IFR_TYPE_NUM_SIZE_64) || (Value->Value.u64 > 0xffff)) {
1836 Status = EFI_NOT_FOUND;
1837 goto Done;
1838 }
1839
1840 Question = IdToQuestion (FormSet, Form, Value->Value.u16);
1841 if (Question == NULL) {
1842 Status = EFI_NOT_FOUND;
1843 goto Done;
1844 }
1845
1846 Value = &Question->HiiValue;
1847 break;
1848
1849 case EFI_IFR_STRING_REF2_OP:
1850 //
1851 // Pop an expression from the expression stack
1852 //
1853 Status = PopExpression (Value);
1854 if (EFI_ERROR (Status)) {
1855 goto Done;
1856 }
1857
1858 //
1859 // Validate the expression value
1860 //
1861 if ((Value->Type > EFI_IFR_TYPE_NUM_SIZE_64) || (Value->Value.u64 > 0xffff)) {
1862 Status = EFI_NOT_FOUND;
1863 goto Done;
1864 }
1865
1866 Value->Type = EFI_IFR_TYPE_STRING;
1867 StrPtr = GetToken (Value->Value.u16, FormSet->UnicodeBinary);
1868 if (StrPtr == NULL) {
1869 //
1870 // If String not exit, push an empty string
1871 //
1872 //Value->Value.string = NewString (gEmptyString, FormSet->HiiHandle);
1873 } else {
1874 Index = (UINT16) Value->Value.u64;
1875 Value->Value.string = Index;
1876 FreePool (StrPtr);
1877 }
1878 break;
1879
1880 case EFI_IFR_TO_BOOLEAN_OP:
1881 //
1882 // Pop an expression from the expression stack
1883 //
1884 Status = PopExpression (Value);
1885 if (EFI_ERROR (Status)) {
1886 goto Done;
1887 }
1888
1889 //
1890 // Convert an expression to a Boolean
1891 //
1892 if (Value->Type <= EFI_IFR_TYPE_DATE) {
1893 //
1894 // When converting from an unsigned integer, zero will be converted to
1895 // FALSE and any other value will be converted to TRUE.
1896 //
1897 Value->Value.b = (BOOLEAN) (Value->Value.u64 != 0);
1898
1899 Value->Type = EFI_IFR_TYPE_BOOLEAN;
1900 } else if (Value->Type == EFI_IFR_TYPE_STRING) {
1901 //
1902 // When converting from a string, if case-insensitive compare
1903 // with "true" is True, then push True. If a case-insensitive compare
1904 // with "false" is True, then push False. Otherwise, push Undefined.
1905 //
1906 StrPtr = GetToken (Value->Value.string, FormSet->UnicodeBinary);
1907 if (StrPtr == NULL) {
1908 Status = EFI_INVALID_PARAMETER;
1909 goto Done;
1910 }
1911
1912 IfrStrToUpper (StrPtr);
1913 if (FceStrCmp (StrPtr, L"TRUE") == 0){
1914 Value->Value.b = TRUE;
1915 } else if (FceStrCmp (StrPtr, L"FALSE") == 0) {
1916 Value->Value.b = FALSE;
1917 } else {
1918 Status = EFI_INVALID_PARAMETER;
1919 FreePool (StrPtr);
1920 goto Done;
1921 }
1922 FreePool (StrPtr);
1923 Value->Type = EFI_IFR_TYPE_BOOLEAN;
1924 }
1925 break;
1926
1927 case EFI_IFR_TO_STRING_OP:
1928 //Status = IfrToString (FormSet, OpCode->Format, Value);
1929 break;
1930
1931 case EFI_IFR_TO_UINT_OP:
1932 Status = IfrToUint (FormSet, Value);
1933 break;
1934
1935 case EFI_IFR_TO_LOWER_OP:
1936 case EFI_IFR_TO_UPPER_OP:
1937
1938 Status = PopExpression (Value);
1939 if (EFI_ERROR (Status)) {
1940 goto Done;
1941 }
1942
1943 if (Value->Type != EFI_IFR_TYPE_STRING) {
1944 Status = EFI_UNSUPPORTED;
1945 goto Done;
1946 }
1947
1948 StrPtr = GetToken (Value->Value.string, FormSet->UnicodeBinary);
1949 if (StrPtr == NULL) {
1950 Status = EFI_NOT_FOUND;
1951 goto Done;
1952 }
1953 //
1954 // Do nothing here, as these two Opcode are to change or update the String Package
1955 //
1956 FreePool (StrPtr);
1957 break;
1958
1959 case EFI_IFR_BITWISE_NOT_OP:
1960 //
1961 // Pop an expression from the expression stack
1962 //
1963 Status = PopExpression (Value);
1964 if (EFI_ERROR (Status)) {
1965 goto Done;
1966 }
1967 if (Value->Type > EFI_IFR_TYPE_DATE) {
1968 Status = EFI_INVALID_PARAMETER;
1969 goto Done;
1970 }
1971
1972 Value->Type = EFI_IFR_TYPE_NUM_SIZE_64;
1973 Value->Value.u64 = ~Value->Value.u64;
1974 break;
1975
1976 case EFI_IFR_SET_OP:
1977 //
1978 // Pop an expression from the expression stack
1979 //
1980 Status = PopExpression (Value);
1981 if (EFI_ERROR (Status)) {
1982 goto Done;
1983 }
1984 Data1.Type = EFI_IFR_TYPE_BOOLEAN;
1985 Data1.Value.b = FALSE;
1986 //
1987 // Not support SetOpcode for static scaning
1988 //
1989 if (OpCode->VarStorage != NULL) {
1990 switch (OpCode->VarStorage->Type) {
1991
1992 case EFI_IFR_VARSTORE_OP:
1993 CopyMem (OpCode->VarStorage->Buffer + OpCode->VarStoreInfo.VarOffset, &Value->Value, OpCode->ValueWidth);
1994 Data1.Value.b = TRUE;
1995 break;
1996 case EFI_IFR_VARSTORE_EFI_OP:
1997 if (OpCode->VarStorage->NewEfiVarstore) {
1998 CopyMem (OpCode->VarStorage->Buffer + OpCode->VarStoreInfo.VarOffset, &Value->Value, OpCode->ValueWidth);
1999 Data1.Value.b = TRUE;
2000 } else {
2001 CopyMem (OpCode->VarStorage->Buffer, &Value->Value, OpCode->ValueWidth);
2002 Data1.Value.b = TRUE;
2003 }
2004 break;
2005 case EFI_HII_VARSTORE_NAME_VALUE:
2006
2007 break;
2008 break;
2009 default:
2010 //
2011 // Not recognize storage.
2012 //
2013 Status = EFI_UNSUPPORTED;
2014 goto Done;
2015 break;
2016 }
2017 Value = &Data1;
2018 }
2019 break;
2020
2021 //
2022 // binary-op
2023 //
2024 case EFI_IFR_ADD_OP:
2025 case EFI_IFR_SUBTRACT_OP:
2026 case EFI_IFR_MULTIPLY_OP:
2027 case EFI_IFR_DIVIDE_OP:
2028 case EFI_IFR_MODULO_OP:
2029 case EFI_IFR_BITWISE_AND_OP:
2030 case EFI_IFR_BITWISE_OR_OP:
2031 case EFI_IFR_SHIFT_LEFT_OP:
2032 case EFI_IFR_SHIFT_RIGHT_OP:
2033 //
2034 // Pop an expression from the expression stack
2035 //
2036 Status = PopExpression (&Data2);
2037 if (EFI_ERROR (Status)) {
2038 goto Done;
2039 }
2040 if (Data2.Type > EFI_IFR_TYPE_DATE) {
2041 Status = EFI_INVALID_PARAMETER;
2042 goto Done;
2043 }
2044
2045 //
2046 // Pop another expression from the expression stack
2047 //
2048 Status = PopExpression (&Data1);
2049 if (EFI_ERROR (Status)) {
2050 goto Done;
2051 }
2052 if (Data1.Type > EFI_IFR_TYPE_DATE) {
2053 Status = EFI_INVALID_PARAMETER;
2054 goto Done;
2055 }
2056
2057 Value->Type = EFI_IFR_TYPE_NUM_SIZE_64;
2058
2059 switch (OpCode->Operand) {
2060 case EFI_IFR_ADD_OP:
2061 Value->Value.u64 = Data1.Value.u64 + Data2.Value.u64;
2062 break;
2063
2064 case EFI_IFR_SUBTRACT_OP:
2065 Value->Value.u64 = Data1.Value.u64 - Data2.Value.u64;
2066 break;
2067
2068 case EFI_IFR_MULTIPLY_OP:
2069 Value->Value.u64 = MultU64x32 (Data1.Value.u64, (UINT32) Data2.Value.u64);
2070 break;
2071
2072 case EFI_IFR_DIVIDE_OP:
2073 Value->Value.u64 = DivU64x32 (Data1.Value.u64, (UINT32) Data2.Value.u64);
2074 break;
2075
2076 case EFI_IFR_MODULO_OP:
2077 DivU64x32Remainder (Data1.Value.u64, (UINT32) Data2.Value.u64, &TempValue);
2078 Value->Value.u64 = TempValue;
2079 break;
2080
2081 case EFI_IFR_BITWISE_AND_OP:
2082 Value->Value.u64 = Data1.Value.u64 & Data2.Value.u64;
2083 break;
2084
2085 case EFI_IFR_BITWISE_OR_OP:
2086 Value->Value.u64 = Data1.Value.u64 | Data2.Value.u64;
2087 break;
2088
2089 case EFI_IFR_SHIFT_LEFT_OP:
2090 Value->Value.u64 = LShiftU64 (Data1.Value.u64, (UINTN) Data2.Value.u64);
2091 break;
2092
2093 case EFI_IFR_SHIFT_RIGHT_OP:
2094 Value->Value.u64 = RShiftU64 (Data1.Value.u64, (UINTN) Data2.Value.u64);
2095 break;
2096
2097 default:
2098 break;
2099 }
2100 break;
2101
2102 case EFI_IFR_AND_OP:
2103 case EFI_IFR_OR_OP:
2104 //
2105 // Two Boolean operator
2106 //
2107 Status = PopExpression (&Data2);
2108 if (EFI_ERROR (Status)) {
2109 goto Done;
2110 }
2111 if (Data2.Type != EFI_IFR_TYPE_BOOLEAN) {
2112 Status = EFI_INVALID_PARAMETER;
2113 goto Done;
2114 }
2115
2116 //
2117 // Pop another expression from the expression stack
2118 //
2119 Status = PopExpression (&Data1);
2120 if (EFI_ERROR (Status)) {
2121 goto Done;
2122 }
2123 if (Data1.Type != EFI_IFR_TYPE_BOOLEAN) {
2124 Status = EFI_INVALID_PARAMETER;
2125 goto Done;
2126 }
2127
2128 if (OpCode->Operand == EFI_IFR_AND_OP) {
2129 Value->Value.b = (BOOLEAN) (Data1.Value.b && Data2.Value.b);
2130 } else {
2131 Value->Value.b = (BOOLEAN) (Data1.Value.b || Data2.Value.b);
2132 }
2133 break;
2134
2135 case EFI_IFR_EQUAL_OP:
2136 case EFI_IFR_NOT_EQUAL_OP:
2137 case EFI_IFR_GREATER_EQUAL_OP:
2138 case EFI_IFR_GREATER_THAN_OP:
2139 case EFI_IFR_LESS_EQUAL_OP:
2140 case EFI_IFR_LESS_THAN_OP:
2141 //
2142 // Compare two integer, string, boolean or date/time
2143 //
2144 Status = PopExpression (&Data2);
2145 if (EFI_ERROR (Status)) {
2146 goto Done;
2147 }
2148 if ((Data2.Type > EFI_IFR_TYPE_BOOLEAN) && (Data2.Type != EFI_IFR_TYPE_STRING)) {
2149 Status = EFI_INVALID_PARAMETER;
2150 goto Done;
2151 }
2152
2153 //
2154 // Pop another expression from the expression stack
2155 //
2156 Status = PopExpression (&Data1);
2157 if (EFI_ERROR (Status)) {
2158 goto Done;
2159 }
2160
2161 Result = CompareHiiValue (&Data1, &Data2, FormSet);
2162 if ((EFI_STATUS)Result == EFI_INVALID_PARAMETER) {
2163 Status = EFI_INVALID_PARAMETER;
2164 goto Done;
2165 }
2166
2167 switch (OpCode->Operand) {
2168 case EFI_IFR_EQUAL_OP:
2169 Value->Value.b = (BOOLEAN) ((Result == 0) ? TRUE : FALSE);
2170 break;
2171
2172 case EFI_IFR_NOT_EQUAL_OP:
2173 Value->Value.b = (BOOLEAN) ((Result != 0) ? TRUE : FALSE);
2174 break;
2175
2176 case EFI_IFR_GREATER_EQUAL_OP:
2177 Value->Value.b = (BOOLEAN) ((Result >= 0) ? TRUE : FALSE);
2178 break;
2179
2180 case EFI_IFR_GREATER_THAN_OP:
2181 Value->Value.b = (BOOLEAN) ((Result > 0) ? TRUE : FALSE);
2182 break;
2183
2184 case EFI_IFR_LESS_EQUAL_OP:
2185 Value->Value.b = (BOOLEAN) ((Result <= 0) ? TRUE : FALSE);
2186 break;
2187
2188 case EFI_IFR_LESS_THAN_OP:
2189 Value->Value.b = (BOOLEAN) ((Result < 0) ? TRUE : FALSE);
2190 break;
2191
2192 default:
2193 break;
2194 }
2195 break;
2196
2197 case EFI_IFR_MATCH_OP:
2198 Status = IfrMatch (FormSet, Value);
2199 break;
2200
2201 case EFI_IFR_CATENATE_OP:
2202 Status = IfrCatenate (FormSet, Value);
2203 break;
2204
2205 //
2206 // ternary-op
2207 //
2208 case EFI_IFR_CONDITIONAL_OP:
2209 //
2210 // Pop third expression from the expression stack
2211 //
2212 Status = PopExpression (&Data3);
2213 if (EFI_ERROR (Status)) {
2214 goto Done;
2215 }
2216
2217 //
2218 // Pop second expression from the expression stack
2219 //
2220 Status = PopExpression (&Data2);
2221 if (EFI_ERROR (Status)) {
2222 goto Done;
2223 }
2224
2225 //
2226 // Pop first expression from the expression stack
2227 //
2228 Status = PopExpression (&Data1);
2229 if (EFI_ERROR (Status)) {
2230 goto Done;
2231 }
2232 if (Data1.Type != EFI_IFR_TYPE_BOOLEAN) {
2233 Status = EFI_INVALID_PARAMETER;
2234 goto Done;
2235 }
2236
2237 if (Data1.Value.b) {
2238 Value = &Data3;
2239 } else {
2240 Value = &Data2;
2241 }
2242 break;
2243
2244 case EFI_IFR_FIND_OP:
2245 Status = IfrFind (FormSet, OpCode->Format, Value);
2246 break;
2247
2248 case EFI_IFR_MID_OP:
2249 Status = IfrMid (FormSet, Value);
2250 break;
2251
2252 case EFI_IFR_TOKEN_OP:
2253 Status = IfrToken (FormSet, Value);
2254 break;
2255
2256 case EFI_IFR_SPAN_OP:
2257 Status = IfrSpan (FormSet, OpCode->Flags, Value);
2258 break;
2259
2260 case EFI_IFR_MAP_OP:
2261 //
2262 // Pop the check value
2263 //
2264 Status = PopExpression (&Data1);
2265 if (EFI_ERROR (Status)) {
2266 goto Done;
2267 }
2268 //
2269 // Check MapExpression list is valid.
2270 //
2271 if (OpCode->MapExpressionList.ForwardLink == NULL) {
2272 Status = EFI_INVALID_PARAMETER;
2273 goto Done;
2274 }
2275 //
2276 // Go through map expression list.
2277 //
2278 SubExpressionLink = GetFirstNode(&OpCode->MapExpressionList);
2279 while (!IsNull (&OpCode->MapExpressionList, SubExpressionLink)) {
2280 SubExpression = FORM_EXPRESSION_FROM_LINK (SubExpressionLink);
2281 //
2282 // Evaluate the first expression in this pair.
2283 //
2284 Status = EvaluateExpression (FormSet, Form, SubExpression, ConstantExpression);
2285 if (EFI_ERROR (Status)) {
2286 goto Done;
2287 }
2288 //
2289 // Compare the expression value with current value
2290 //
2291 if (CompareHiiValue (&Data1, &SubExpression->Result, FormSet) == 0) {
2292 //
2293 // Try get the map value.
2294 //
2295 SubExpressionLink = GetNextNode (&OpCode->MapExpressionList, SubExpressionLink);
2296 if (IsNull (&OpCode->MapExpressionList, SubExpressionLink)) {
2297 Status = EFI_INVALID_PARAMETER;
2298 goto Done;
2299 }
2300 SubExpression = FORM_EXPRESSION_FROM_LINK (SubExpressionLink);
2301 Status = EvaluateExpression (FormSet, Form, SubExpression, ConstantExpression);
2302 if (EFI_ERROR (Status)) {
2303 goto Done;
2304 }
2305 Value = &SubExpression->Result;
2306 break;
2307 }
2308 //
2309 // Skip the second expression on this pair.
2310 //
2311 SubExpressionLink = GetNextNode (&OpCode->MapExpressionList, SubExpressionLink);
2312 if (IsNull (&OpCode->MapExpressionList, SubExpressionLink)) {
2313 Status = EFI_INVALID_PARAMETER;
2314 goto Done;
2315 }
2316 //
2317 // Goto the first expression on next pair.
2318 //
2319 SubExpressionLink = GetNextNode (&OpCode->MapExpressionList, SubExpressionLink);
2320 }
2321
2322 //
2323 // No map value is found.
2324 //
2325 if (IsNull (&OpCode->MapExpressionList, SubExpressionLink)) {
2326 Value->Type = EFI_IFR_TYPE_UNDEFINED;
2327 Value->Value.u8 = 0;
2328 }
2329 break;
2330
2331 default:
2332 break;
2333 }
2334 if (EFI_ERROR (Status)) {
2335 goto Done;
2336 }
2337
2338 Status = PushExpression (Value);
2339 if (EFI_ERROR (Status)) {
2340 goto Done;
2341 }
2342 }
2343
2344 //
2345 // Pop the final result from expression stack
2346 //
2347 Value = &Data1;
2348 Status = PopExpression (Value);
2349 if (EFI_ERROR (Status)) {
2350 goto Done;
2351 }
2352
2353 //
2354 // After evaluating an expression, there should be only one value left on the expression stack
2355 //
2356 if (PopExpression (Value) != EFI_ACCESS_DENIED) {
2357 Status = EFI_INVALID_PARAMETER;
2358 }
2359
2360 Done:
2361 RestoreExpressionEvaluationStackOffset (StackOffset);
2362 if (!EFI_ERROR (Status)) {
2363 CopyMem (&Expression->Result, Value, sizeof (EFI_HII_VALUE));
2364 }
2365
2366 return Status;
2367 }