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