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