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