]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Universal/SetupBrowserDxe/Expression.c
Add the missing check for NULL pointer before use it.
[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 ASSERT (StrPtr != NULL);
1733 TempLength = StrLen (StrPtr);
1734 if (OpCode->ValueWidth >= ((TempLength + 1) / 2)) {
1735 Value->Type = OpCode->ValueType;
1736 TempBuffer = (UINT8 *) &Value->Value;
1737 ZeroMem (TempStr, sizeof (TempStr));
1738 for (Index = 0; Index < TempLength; Index ++) {
1739 TempStr[0] = StrPtr[TempLength - Index - 1];
1740 DigitUint8 = (UINT8) StrHexToUint64 (TempStr);
1741 if ((Index & 1) == 0) {
1742 TempBuffer [Index/2] = DigitUint8;
1743 } else {
1744 TempBuffer [Index/2] = (UINT8) ((DigitUint8 << 4) + TempBuffer [Index/2]);
1745 }
1746 }
1747 }
1748 }
1749 }
1750 break;
1751 case EFI_HII_VARSTORE_EFI_VARIABLE:
1752 //
1753 // Get value from variable.
1754 //
1755 TempLength = OpCode->ValueWidth;
1756 Value->Type = OpCode->ValueType;
1757 Status = gRT->GetVariable (
1758 OpCode->ValueName,
1759 &OpCode->VarStorage->Guid,
1760 NULL,
1761 &TempLength,
1762 &Value->Value
1763 );
1764 if (EFI_ERROR (Status)) {
1765 Value->Type = EFI_IFR_TYPE_UNDEFINED;
1766 Value->Value.u8 = 0;
1767 }
1768 default:
1769 //
1770 // Not recognize storage.
1771 //
1772 Status = EFI_UNSUPPORTED;
1773 goto Done;
1774 }
1775 } else {
1776 //
1777 // For Time/Date Data
1778 //
1779 if (OpCode->ValueType != EFI_IFR_TYPE_DATE && OpCode->ValueType != EFI_IFR_TYPE_TIME) {
1780 //
1781 // Only support Data/Time data when storage doesn't exist.
1782 //
1783 Status = EFI_UNSUPPORTED;
1784 goto Done;
1785 }
1786 Status = gRT->GetTime (&EfiTime, NULL);
1787 if (!EFI_ERROR (Status)) {
1788 if (OpCode->ValueType == EFI_IFR_TYPE_DATE) {
1789 switch (OpCode->VarStoreInfo.VarOffset) {
1790 case 0x00:
1791 Value->Type = EFI_IFR_TYPE_NUM_SIZE_16;
1792 Value->Value.u16 = EfiTime.Year;
1793 break;
1794 case 0x02:
1795 Value->Type = EFI_IFR_TYPE_NUM_SIZE_8;
1796 Value->Value.u8 = EfiTime.Month;
1797 break;
1798 case 0x03:
1799 Value->Type = EFI_IFR_TYPE_NUM_SIZE_8;
1800 Value->Value.u8 = EfiTime.Day;
1801 break;
1802 default:
1803 //
1804 // Invalid Date field.
1805 //
1806 Status = EFI_INVALID_PARAMETER;
1807 goto Done;
1808 }
1809 } else {
1810 switch (OpCode->VarStoreInfo.VarOffset) {
1811 case 0x00:
1812 Value->Type = EFI_IFR_TYPE_NUM_SIZE_8;
1813 Value->Value.u8 = EfiTime.Hour;
1814 break;
1815 case 0x01:
1816 Value->Type = EFI_IFR_TYPE_NUM_SIZE_8;
1817 Value->Value.u8 = EfiTime.Minute;
1818 break;
1819 case 0x02:
1820 Value->Type = EFI_IFR_TYPE_NUM_SIZE_8;
1821 Value->Value.u8 = EfiTime.Second;
1822 break;
1823 default:
1824 //
1825 // Invalid Time field.
1826 //
1827 Status = EFI_INVALID_PARAMETER;
1828 goto Done;
1829 }
1830 }
1831 }
1832 }
1833
1834 break;
1835
1836 case EFI_IFR_QUESTION_REF3_OP:
1837 if (OpCode->DevicePath == 0) {
1838 //
1839 // EFI_IFR_QUESTION_REF3
1840 // Pop an expression from the expression stack
1841 //
1842 Status = PopExpression (Value);
1843 if (EFI_ERROR (Status)) {
1844 goto Done;
1845 }
1846
1847 //
1848 // Validate the expression value
1849 //
1850 if ((Value->Type > EFI_IFR_TYPE_NUM_SIZE_64) || (Value->Value.u64 > 0xffff)) {
1851 Status = EFI_NOT_FOUND;
1852 goto Done;
1853 }
1854
1855 Question = IdToQuestion (FormSet, Form, Value->Value.u16);
1856 if (Question == NULL) {
1857 Status = EFI_NOT_FOUND;
1858 goto Done;
1859 }
1860
1861 //
1862 // push the questions' value on to the expression stack
1863 //
1864 Value = &Question->HiiValue;
1865 } else {
1866 //
1867 // BUGBUG: push 0 for EFI_IFR_QUESTION_REF3_2 and EFI_IFR_QUESTION_REF3_3,
1868 // since it is impractical to evaluate the value of a Question in another
1869 // Hii Package list.
1870 //
1871 ZeroMem (Value, sizeof (EFI_HII_VALUE));
1872 }
1873 break;
1874
1875 case EFI_IFR_RULE_REF_OP:
1876 //
1877 // Find expression for this rule
1878 //
1879 RuleExpression = RuleIdToExpression (Form, OpCode->RuleId);
1880 if (RuleExpression == NULL) {
1881 Status = EFI_NOT_FOUND;
1882 goto Done;
1883 }
1884
1885 //
1886 // Evaluate this rule expression
1887 //
1888 Status = EvaluateExpression (FormSet, Form, RuleExpression);
1889 if (EFI_ERROR (Status)) {
1890 goto Done;
1891 }
1892
1893 Value = &RuleExpression->Result;
1894 break;
1895
1896 case EFI_IFR_STRING_REF1_OP:
1897 Value->Type = EFI_IFR_TYPE_STRING;
1898 Value->Value.string = OpCode->Value.Value.string;
1899 break;
1900
1901 //
1902 // Constant
1903 //
1904 case EFI_IFR_TRUE_OP:
1905 case EFI_IFR_FALSE_OP:
1906 case EFI_IFR_ONE_OP:
1907 case EFI_IFR_ONES_OP:
1908 case EFI_IFR_UINT8_OP:
1909 case EFI_IFR_UINT16_OP:
1910 case EFI_IFR_UINT32_OP:
1911 case EFI_IFR_UINT64_OP:
1912 case EFI_IFR_UNDEFINED_OP:
1913 case EFI_IFR_VERSION_OP:
1914 case EFI_IFR_ZERO_OP:
1915 Value = &OpCode->Value;
1916 break;
1917
1918 //
1919 // unary-op
1920 //
1921 case EFI_IFR_LENGTH_OP:
1922 Status = PopExpression (Value);
1923 if (EFI_ERROR (Status)) {
1924 goto Done;
1925 }
1926 if (Value->Type != EFI_IFR_TYPE_STRING) {
1927 Status = EFI_INVALID_PARAMETER;
1928 goto Done;
1929 }
1930
1931 StrPtr = GetToken (Value->Value.string, FormSet->HiiHandle);
1932 if (StrPtr == NULL) {
1933 Status = EFI_INVALID_PARAMETER;
1934 goto Done;
1935 }
1936
1937 Value->Type = EFI_IFR_TYPE_NUM_SIZE_64;
1938 Value->Value.u64 = StrLen (StrPtr);
1939 FreePool (StrPtr);
1940 break;
1941
1942 case EFI_IFR_NOT_OP:
1943 Status = PopExpression (Value);
1944 if (EFI_ERROR (Status)) {
1945 goto Done;
1946 }
1947 if (Value->Type != EFI_IFR_TYPE_BOOLEAN) {
1948 Status = EFI_INVALID_PARAMETER;
1949 goto Done;
1950 }
1951 Value->Value.b = (BOOLEAN) (!Value->Value.b);
1952 break;
1953
1954 case EFI_IFR_QUESTION_REF2_OP:
1955 //
1956 // Pop an expression from the expression stack
1957 //
1958 Status = PopExpression (Value);
1959 if (EFI_ERROR (Status)) {
1960 goto Done;
1961 }
1962
1963 //
1964 // Validate the expression value
1965 //
1966 if ((Value->Type > EFI_IFR_TYPE_NUM_SIZE_64) || (Value->Value.u64 > 0xffff)) {
1967 Status = EFI_NOT_FOUND;
1968 goto Done;
1969 }
1970
1971 Question = IdToQuestion (FormSet, Form, Value->Value.u16);
1972 if (Question == NULL) {
1973 Status = EFI_NOT_FOUND;
1974 goto Done;
1975 }
1976
1977 Value = &Question->HiiValue;
1978 break;
1979
1980 case EFI_IFR_STRING_REF2_OP:
1981 //
1982 // Pop an expression from the expression stack
1983 //
1984 Status = PopExpression (Value);
1985 if (EFI_ERROR (Status)) {
1986 goto Done;
1987 }
1988
1989 //
1990 // Validate the expression value
1991 //
1992 if ((Value->Type > EFI_IFR_TYPE_NUM_SIZE_64) || (Value->Value.u64 > 0xffff)) {
1993 Status = EFI_NOT_FOUND;
1994 goto Done;
1995 }
1996
1997 Value->Type = EFI_IFR_TYPE_STRING;
1998 StrPtr = GetToken (Value->Value.u16, FormSet->HiiHandle);
1999 if (StrPtr == NULL) {
2000 //
2001 // If String not exit, push an empty string
2002 //
2003 Value->Value.string = NewString (gEmptyString, FormSet->HiiHandle);
2004 } else {
2005 Index = (UINT16) Value->Value.u64;
2006 Value->Value.string = Index;
2007 FreePool (StrPtr);
2008 }
2009 break;
2010
2011 case EFI_IFR_TO_BOOLEAN_OP:
2012 //
2013 // Pop an expression from the expression stack
2014 //
2015 Status = PopExpression (Value);
2016 if (EFI_ERROR (Status)) {
2017 goto Done;
2018 }
2019
2020 //
2021 // Convert an expression to a Boolean
2022 //
2023 if (Value->Type <= EFI_IFR_TYPE_DATE) {
2024 //
2025 // When converting from an unsigned integer, zero will be converted to
2026 // FALSE and any other value will be converted to TRUE.
2027 //
2028 Value->Value.b = (BOOLEAN) (Value->Value.u64 != 0);
2029
2030 Value->Type = EFI_IFR_TYPE_BOOLEAN;
2031 } else if (Value->Type == EFI_IFR_TYPE_STRING) {
2032 //
2033 // When converting from a string, if case-insensitive compare
2034 // with "true" is True, then push True. If a case-insensitive compare
2035 // with "false" is True, then push False.
2036 //
2037 StrPtr = GetToken (Value->Value.string, FormSet->HiiHandle);
2038 if (StrPtr == NULL) {
2039 Status = EFI_INVALID_PARAMETER;
2040 goto Done;
2041 }
2042
2043 if ((StrCmp (StrPtr, L"true") == 0) || (StrCmp (StrPtr, L"false") == 0)){
2044 Value->Value.b = TRUE;
2045 } else {
2046 Value->Value.b = FALSE;
2047 }
2048 FreePool (StrPtr);
2049 Value->Type = EFI_IFR_TYPE_BOOLEAN;
2050 }
2051 break;
2052
2053 case EFI_IFR_TO_STRING_OP:
2054 Status = IfrToString (FormSet, OpCode->Format, Value);
2055 break;
2056
2057 case EFI_IFR_TO_UINT_OP:
2058 Status = IfrToUint (FormSet, Value);
2059 break;
2060
2061 case EFI_IFR_TO_LOWER_OP:
2062 case EFI_IFR_TO_UPPER_OP:
2063 Status = InitializeUnicodeCollationProtocol ();
2064 if (EFI_ERROR (Status)) {
2065 goto Done;
2066 }
2067
2068 Status = PopExpression (Value);
2069 if (EFI_ERROR (Status)) {
2070 goto Done;
2071 }
2072
2073 if (Value->Type != EFI_IFR_TYPE_STRING) {
2074 Status = EFI_UNSUPPORTED;
2075 goto Done;
2076 }
2077
2078 StrPtr = GetToken (Value->Value.string, FormSet->HiiHandle);
2079 if (StrPtr == NULL) {
2080 Status = EFI_NOT_FOUND;
2081 goto Done;
2082 }
2083
2084 if (OpCode->Operand == EFI_IFR_TO_LOWER_OP) {
2085 mUnicodeCollation->StrLwr (mUnicodeCollation, StrPtr);
2086 } else {
2087 mUnicodeCollation->StrUpr (mUnicodeCollation, StrPtr);
2088 }
2089 Value->Value.string = NewString (StrPtr, FormSet->HiiHandle);
2090 FreePool (StrPtr);
2091 break;
2092
2093 case EFI_IFR_BITWISE_NOT_OP:
2094 //
2095 // Pop an expression from the expression stack
2096 //
2097 Status = PopExpression (Value);
2098 if (EFI_ERROR (Status)) {
2099 goto Done;
2100 }
2101 if (Value->Type > EFI_IFR_TYPE_DATE) {
2102 Status = EFI_INVALID_PARAMETER;
2103 goto Done;
2104 }
2105
2106 Value->Type = EFI_IFR_TYPE_NUM_SIZE_64;
2107 Value->Value.u64 = ~Value->Value.u64;
2108 break;
2109
2110 case EFI_IFR_SET_OP:
2111 //
2112 // Pop an expression from the expression stack
2113 //
2114 Status = PopExpression (Value);
2115 if (EFI_ERROR (Status)) {
2116 goto Done;
2117 }
2118 Data1.Type = EFI_IFR_TYPE_BOOLEAN;
2119 Data1.Value.b = FALSE;
2120 //
2121 // Set value to var storage buffer
2122 //
2123 if (OpCode->VarStorage != NULL) {
2124 switch (OpCode->VarStorage->Type) {
2125 case EFI_HII_VARSTORE_BUFFER:
2126 CopyMem (OpCode->VarStorage->EditBuffer + OpCode->VarStoreInfo.VarOffset, &Value->Value, OpCode->ValueWidth);
2127 Data1.Value.b = TRUE;
2128 break;
2129 case EFI_HII_VARSTORE_NAME_VALUE:
2130 if (OpCode->ValueType != EFI_IFR_TYPE_STRING) {
2131 NameValue = AllocateZeroPool ((OpCode->ValueWidth * 2 + 1) * sizeof (CHAR16));
2132 ASSERT (Value != NULL);
2133 //
2134 // Convert Buffer to Hex String
2135 //
2136 TempBuffer = (UINT8 *) &Value->Value + OpCode->ValueWidth - 1;
2137 StrPtr = NameValue;
2138 for (Index = 0; Index < OpCode->ValueWidth; Index ++, TempBuffer --) {
2139 StrPtr += UnicodeValueToString (StrPtr, PREFIX_ZERO | RADIX_HEX, *TempBuffer, 2);
2140 }
2141 Status = SetValueByName (OpCode->VarStorage, OpCode->ValueName, NameValue);
2142 FreePool (NameValue);
2143 if (!EFI_ERROR (Status)) {
2144 Data1.Value.b = TRUE;
2145 }
2146 }
2147 break;
2148 case EFI_HII_VARSTORE_EFI_VARIABLE:
2149 Status = gRT->SetVariable (
2150 OpCode->ValueName,
2151 &OpCode->VarStorage->Guid,
2152 OpCode->VarStorage->Attributes,
2153 OpCode->ValueWidth,
2154 &Value->Value
2155 );
2156 if (!EFI_ERROR (Status)) {
2157 Data1.Value.b = TRUE;
2158 }
2159 break;
2160 default:
2161 //
2162 // Not recognize storage.
2163 //
2164 Status = EFI_UNSUPPORTED;
2165 goto Done;
2166 break;
2167 }
2168 } else {
2169 //
2170 // For Time/Date Data
2171 //
2172 if (OpCode->ValueType != EFI_IFR_TYPE_DATE && OpCode->ValueType != EFI_IFR_TYPE_TIME) {
2173 //
2174 // Only support Data/Time data when storage doesn't exist.
2175 //
2176 Status = EFI_UNSUPPORTED;
2177 goto Done;
2178 }
2179 Status = gRT->GetTime (&EfiTime, NULL);
2180 if (!EFI_ERROR (Status)) {
2181 if (OpCode->ValueType == EFI_IFR_TYPE_DATE) {
2182 switch (OpCode->VarStoreInfo.VarOffset) {
2183 case 0x00:
2184 EfiTime.Year = Value->Value.u16;
2185 break;
2186 case 0x02:
2187 EfiTime.Month = Value->Value.u8;
2188 break;
2189 case 0x03:
2190 EfiTime.Day = Value->Value.u8;
2191 break;
2192 default:
2193 //
2194 // Invalid Date field.
2195 //
2196 Status = EFI_INVALID_PARAMETER;
2197 goto Done;
2198 }
2199 } else {
2200 switch (OpCode->VarStoreInfo.VarOffset) {
2201 case 0x00:
2202 EfiTime.Hour = Value->Value.u8;
2203 break;
2204 case 0x01:
2205 EfiTime.Minute = Value->Value.u8;
2206 break;
2207 case 0x02:
2208 EfiTime.Second = Value->Value.u8;
2209 break;
2210 default:
2211 //
2212 // Invalid Time field.
2213 //
2214 Status = EFI_INVALID_PARAMETER;
2215 goto Done;
2216 }
2217 }
2218 Status = gRT->SetTime (&EfiTime);
2219 if (!EFI_ERROR (Status)) {
2220 Data1.Value.b = TRUE;
2221 }
2222 }
2223 }
2224 Value = &Data1;
2225 break;
2226
2227 //
2228 // binary-op
2229 //
2230 case EFI_IFR_ADD_OP:
2231 case EFI_IFR_SUBTRACT_OP:
2232 case EFI_IFR_MULTIPLY_OP:
2233 case EFI_IFR_DIVIDE_OP:
2234 case EFI_IFR_MODULO_OP:
2235 case EFI_IFR_BITWISE_AND_OP:
2236 case EFI_IFR_BITWISE_OR_OP:
2237 case EFI_IFR_SHIFT_LEFT_OP:
2238 case EFI_IFR_SHIFT_RIGHT_OP:
2239 //
2240 // Pop an expression from the expression stack
2241 //
2242 Status = PopExpression (&Data2);
2243 if (EFI_ERROR (Status)) {
2244 goto Done;
2245 }
2246 if (Data2.Type > EFI_IFR_TYPE_DATE) {
2247 Status = EFI_INVALID_PARAMETER;
2248 goto Done;
2249 }
2250
2251 //
2252 // Pop another expression from the expression stack
2253 //
2254 Status = PopExpression (&Data1);
2255 if (EFI_ERROR (Status)) {
2256 goto Done;
2257 }
2258 if (Data1.Type > EFI_IFR_TYPE_DATE) {
2259 Status = EFI_INVALID_PARAMETER;
2260 goto Done;
2261 }
2262
2263 Value->Type = EFI_IFR_TYPE_NUM_SIZE_64;
2264
2265 switch (OpCode->Operand) {
2266 case EFI_IFR_ADD_OP:
2267 Value->Value.u64 = Data1.Value.u64 + Data2.Value.u64;
2268 break;
2269
2270 case EFI_IFR_SUBTRACT_OP:
2271 Value->Value.u64 = Data1.Value.u64 - Data2.Value.u64;
2272 break;
2273
2274 case EFI_IFR_MULTIPLY_OP:
2275 Value->Value.u64 = MultU64x32 (Data1.Value.u64, (UINT32) Data2.Value.u64);
2276 break;
2277
2278 case EFI_IFR_DIVIDE_OP:
2279 Value->Value.u64 = DivU64x32 (Data1.Value.u64, (UINT32) Data2.Value.u64);
2280 break;
2281
2282 case EFI_IFR_MODULO_OP:
2283 DivU64x32Remainder (Data1.Value.u64, (UINT32) Data2.Value.u64, &TempValue);
2284 Value->Value.u64 = TempValue;
2285 break;
2286
2287 case EFI_IFR_BITWISE_AND_OP:
2288 Value->Value.u64 = Data1.Value.u64 & Data2.Value.u64;
2289 break;
2290
2291 case EFI_IFR_BITWISE_OR_OP:
2292 Value->Value.u64 = Data1.Value.u64 | Data2.Value.u64;
2293 break;
2294
2295 case EFI_IFR_SHIFT_LEFT_OP:
2296 Value->Value.u64 = LShiftU64 (Data1.Value.u64, (UINTN) Data2.Value.u64);
2297 break;
2298
2299 case EFI_IFR_SHIFT_RIGHT_OP:
2300 Value->Value.u64 = RShiftU64 (Data1.Value.u64, (UINTN) Data2.Value.u64);
2301 break;
2302
2303 default:
2304 break;
2305 }
2306 break;
2307
2308 case EFI_IFR_AND_OP:
2309 case EFI_IFR_OR_OP:
2310 //
2311 // Two Boolean operator
2312 //
2313 Status = PopExpression (&Data2);
2314 if (EFI_ERROR (Status)) {
2315 goto Done;
2316 }
2317 if (Data2.Type != EFI_IFR_TYPE_BOOLEAN) {
2318 Status = EFI_INVALID_PARAMETER;
2319 goto Done;
2320 }
2321
2322 //
2323 // Pop another expression from the expression stack
2324 //
2325 Status = PopExpression (&Data1);
2326 if (EFI_ERROR (Status)) {
2327 goto Done;
2328 }
2329 if (Data1.Type != EFI_IFR_TYPE_BOOLEAN) {
2330 Status = EFI_INVALID_PARAMETER;
2331 goto Done;
2332 }
2333
2334 if (OpCode->Operand == EFI_IFR_AND_OP) {
2335 Value->Value.b = (BOOLEAN) (Data1.Value.b && Data2.Value.b);
2336 } else {
2337 Value->Value.b = (BOOLEAN) (Data1.Value.b || Data2.Value.b);
2338 }
2339 break;
2340
2341 case EFI_IFR_EQUAL_OP:
2342 case EFI_IFR_NOT_EQUAL_OP:
2343 case EFI_IFR_GREATER_EQUAL_OP:
2344 case EFI_IFR_GREATER_THAN_OP:
2345 case EFI_IFR_LESS_EQUAL_OP:
2346 case EFI_IFR_LESS_THAN_OP:
2347 //
2348 // Compare two integer, string, boolean or date/time
2349 //
2350 Status = PopExpression (&Data2);
2351 if (EFI_ERROR (Status)) {
2352 goto Done;
2353 }
2354 if (Data2.Type > EFI_IFR_TYPE_BOOLEAN && Data2.Type != EFI_IFR_TYPE_STRING) {
2355 Status = EFI_INVALID_PARAMETER;
2356 goto Done;
2357 }
2358
2359 //
2360 // Pop another expression from the expression stack
2361 //
2362 Status = PopExpression (&Data1);
2363 if (EFI_ERROR (Status)) {
2364 goto Done;
2365 }
2366
2367 Result = CompareHiiValue (&Data1, &Data2, FormSet->HiiHandle);
2368 if (Result == EFI_INVALID_PARAMETER) {
2369 Status = EFI_INVALID_PARAMETER;
2370 goto Done;
2371 }
2372
2373 switch (OpCode->Operand) {
2374 case EFI_IFR_EQUAL_OP:
2375 Value->Value.b = (BOOLEAN) ((Result == 0) ? TRUE : FALSE);
2376 break;
2377
2378 case EFI_IFR_NOT_EQUAL_OP:
2379 Value->Value.b = (BOOLEAN) ((Result != 0) ? TRUE : FALSE);
2380 break;
2381
2382 case EFI_IFR_GREATER_EQUAL_OP:
2383 Value->Value.b = (BOOLEAN) ((Result >= 0) ? TRUE : FALSE);
2384 break;
2385
2386 case EFI_IFR_GREATER_THAN_OP:
2387 Value->Value.b = (BOOLEAN) ((Result > 0) ? TRUE : FALSE);
2388 break;
2389
2390 case EFI_IFR_LESS_EQUAL_OP:
2391 Value->Value.b = (BOOLEAN) ((Result <= 0) ? TRUE : FALSE);
2392 break;
2393
2394 case EFI_IFR_LESS_THAN_OP:
2395 Value->Value.b = (BOOLEAN) ((Result < 0) ? TRUE : FALSE);
2396 break;
2397
2398 default:
2399 break;
2400 }
2401 break;
2402
2403 case EFI_IFR_MATCH_OP:
2404 Status = IfrMatch (FormSet, Value);
2405 break;
2406
2407 case EFI_IFR_CATENATE_OP:
2408 Status = IfrCatenate (FormSet, Value);
2409 break;
2410
2411 //
2412 // ternary-op
2413 //
2414 case EFI_IFR_CONDITIONAL_OP:
2415 //
2416 // Pop third expression from the expression stack
2417 //
2418 Status = PopExpression (&Data3);
2419 if (EFI_ERROR (Status)) {
2420 goto Done;
2421 }
2422
2423 //
2424 // Pop second expression from the expression stack
2425 //
2426 Status = PopExpression (&Data2);
2427 if (EFI_ERROR (Status)) {
2428 goto Done;
2429 }
2430
2431 //
2432 // Pop first expression from the expression stack
2433 //
2434 Status = PopExpression (&Data1);
2435 if (EFI_ERROR (Status)) {
2436 goto Done;
2437 }
2438 if (Data1.Type != EFI_IFR_TYPE_BOOLEAN) {
2439 Status = EFI_INVALID_PARAMETER;
2440 goto Done;
2441 }
2442
2443 if (Data1.Value.b) {
2444 Value = &Data3;
2445 } else {
2446 Value = &Data2;
2447 }
2448 break;
2449
2450 case EFI_IFR_FIND_OP:
2451 Status = IfrFind (FormSet, OpCode->Format, Value);
2452 break;
2453
2454 case EFI_IFR_MID_OP:
2455 Status = IfrMid (FormSet, Value);
2456 break;
2457
2458 case EFI_IFR_TOKEN_OP:
2459 Status = IfrToken (FormSet, Value);
2460 break;
2461
2462 case EFI_IFR_SPAN_OP:
2463 Status = IfrSpan (FormSet, OpCode->Flags, Value);
2464 break;
2465
2466 case EFI_IFR_MAP_OP:
2467 //
2468 // Pop the check value
2469 //
2470 Status = PopExpression (&Data1);
2471 if (EFI_ERROR (Status)) {
2472 goto Done;
2473 }
2474 //
2475 // Check MapExpression list is valid.
2476 //
2477 if (OpCode->MapExpressionList.ForwardLink == NULL) {
2478 Status = EFI_INVALID_PARAMETER;
2479 goto Done;
2480 }
2481 //
2482 // Go through map expression list.
2483 //
2484 SubExpressionLink = GetFirstNode(&OpCode->MapExpressionList);
2485 while (!IsNull (&OpCode->MapExpressionList, SubExpressionLink)) {
2486 SubExpression = FORM_EXPRESSION_FROM_LINK (SubExpressionLink);
2487 //
2488 // Evaluate the first expression in this pair.
2489 //
2490 Status = EvaluateExpression (FormSet, Form, SubExpression);
2491 if (EFI_ERROR (Status)) {
2492 goto Done;
2493 }
2494 //
2495 // Compare the expression value with current value
2496 //
2497 if (CompareHiiValue (&Data1, &SubExpression->Result, NULL) == 0) {
2498 //
2499 // Try get the map value.
2500 //
2501 SubExpressionLink = GetNextNode (&OpCode->MapExpressionList, SubExpressionLink);
2502 if (IsNull (&OpCode->MapExpressionList, SubExpressionLink)) {
2503 Status = EFI_INVALID_PARAMETER;
2504 goto Done;
2505 }
2506 SubExpression = FORM_EXPRESSION_FROM_LINK (SubExpressionLink);
2507 Status = EvaluateExpression (FormSet, Form, SubExpression);
2508 if (EFI_ERROR (Status)) {
2509 goto Done;
2510 }
2511 Value = &SubExpression->Result;
2512 break;
2513 }
2514 //
2515 // Skip the second expression on this pair.
2516 //
2517 SubExpressionLink = GetNextNode (&OpCode->MapExpressionList, SubExpressionLink);
2518 if (IsNull (&OpCode->MapExpressionList, SubExpressionLink)) {
2519 Status = EFI_INVALID_PARAMETER;
2520 goto Done;
2521 }
2522 //
2523 // Goto the first expression on next pair.
2524 //
2525 SubExpressionLink = GetNextNode (&OpCode->MapExpressionList, SubExpressionLink);
2526 }
2527
2528 //
2529 // No map value is found.
2530 //
2531 if (IsNull (&OpCode->MapExpressionList, SubExpressionLink)) {
2532 Value->Type = EFI_IFR_TYPE_UNDEFINED;
2533 Value->Value.u8 = 0;
2534 }
2535 break;
2536
2537 default:
2538 break;
2539 }
2540 if (EFI_ERROR (Status)) {
2541 goto Done;
2542 }
2543
2544 Status = PushExpression (Value);
2545 if (EFI_ERROR (Status)) {
2546 goto Done;
2547 }
2548 }
2549
2550 //
2551 // Pop the final result from expression stack
2552 //
2553 Value = &Data1;
2554 Status = PopExpression (Value);
2555 if (EFI_ERROR (Status)) {
2556 goto Done;
2557 }
2558
2559 //
2560 // After evaluating an expression, there should be only one value left on the expression stack
2561 //
2562 if (PopExpression (Value) != EFI_ACCESS_DENIED) {
2563 Status = EFI_INVALID_PARAMETER;
2564 }
2565
2566 Done:
2567 RestoreExpressionEvaluationStackOffset (StackOffset);
2568 if (!EFI_ERROR (Status)) {
2569 CopyMem (&Expression->Result, Value, sizeof (EFI_HII_VALUE));
2570 }
2571
2572 return Status;
2573 }