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