]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Universal/SetupBrowserDxe/Expression.c
UefiCpuPkg: Move AsmRelocateApLoopStart from Mpfuncs.nasm to AmdSev.nasm
[mirror_edk2.git] / MdeModulePkg / Universal / SetupBrowserDxe / Expression.c
1 /** @file
2 Utility functions for expression evaluation.
3
4 Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.<BR>
5 SPDX-License-Identifier: BSD-2-Clause-Patent
6
7 **/
8
9 #include "Setup.h"
10
11 //
12 // Global stack used to evaluate boolean expresions
13 //
14 EFI_HII_VALUE *mOpCodeScopeStack = NULL;
15 EFI_HII_VALUE *mOpCodeScopeStackEnd = NULL;
16 EFI_HII_VALUE *mOpCodeScopeStackPointer = NULL;
17
18 EFI_HII_VALUE *mExpressionEvaluationStack = NULL;
19 EFI_HII_VALUE *mExpressionEvaluationStackEnd = NULL;
20 EFI_HII_VALUE *mExpressionEvaluationStackPointer = NULL;
21 UINTN mExpressionEvaluationStackOffset = 0;
22
23 EFI_HII_VALUE *mCurrentExpressionStack = NULL;
24 EFI_HII_VALUE *mCurrentExpressionEnd = NULL;
25 EFI_HII_VALUE *mCurrentExpressionPointer = NULL;
26
27 EFI_HII_VALUE *mMapExpressionListStack = NULL;
28 EFI_HII_VALUE *mMapExpressionListEnd = NULL;
29 EFI_HII_VALUE *mMapExpressionListPointer = NULL;
30
31 FORM_EXPRESSION **mFormExpressionStack = NULL;
32 FORM_EXPRESSION **mFormExpressionEnd = NULL;
33 FORM_EXPRESSION **mFormExpressionPointer = NULL;
34
35 FORM_EXPRESSION **mStatementExpressionStack = NULL;
36 FORM_EXPRESSION **mStatementExpressionEnd = NULL;
37 FORM_EXPRESSION **mStatementExpressionPointer = NULL;
38
39 FORM_EXPRESSION **mOptionExpressionStack = NULL;
40 FORM_EXPRESSION **mOptionExpressionEnd = NULL;
41 FORM_EXPRESSION **mOptionExpressionPointer = NULL;
42
43
44 //
45 // Unicode collation protocol interface
46 //
47 EFI_UNICODE_COLLATION_PROTOCOL *mUnicodeCollation = NULL;
48 EFI_USER_MANAGER_PROTOCOL *mUserManager = NULL;
49
50 /**
51 Grow size of the stack.
52
53 This is an internal function.
54
55 @param Stack On input: old stack; On output: new stack
56 @param StackPtr On input: old stack pointer; On output: new stack
57 pointer
58 @param StackEnd On input: old stack end; On output: new stack end
59
60 @retval EFI_SUCCESS Grow stack success.
61 @retval EFI_OUT_OF_RESOURCES No enough memory for stack space.
62
63 **/
64 EFI_STATUS
65 GrowStack (
66 IN OUT EFI_HII_VALUE **Stack,
67 IN OUT EFI_HII_VALUE **StackPtr,
68 IN OUT EFI_HII_VALUE **StackEnd
69 )
70 {
71 UINTN Size;
72 EFI_HII_VALUE *NewStack;
73
74 Size = EXPRESSION_STACK_SIZE_INCREMENT;
75 if (*StackPtr != NULL) {
76 Size = Size + (*StackEnd - *Stack);
77 }
78
79 NewStack = AllocatePool (Size * sizeof (EFI_HII_VALUE));
80 if (NewStack == NULL) {
81 return EFI_OUT_OF_RESOURCES;
82 }
83
84 if (*StackPtr != NULL) {
85 //
86 // Copy from Old Stack to the New Stack
87 //
88 CopyMem (
89 NewStack,
90 *Stack,
91 (*StackEnd - *Stack) * sizeof (EFI_HII_VALUE)
92 );
93
94 //
95 // Free The Old Stack
96 //
97 FreePool (*Stack);
98 }
99
100 //
101 // Make the Stack pointer point to the old data in the new stack
102 //
103 *StackPtr = NewStack + (*StackPtr - *Stack);
104 *Stack = NewStack;
105 *StackEnd = NewStack + Size;
106
107 return EFI_SUCCESS;
108 }
109
110
111 /**
112 Push an element onto the Boolean Stack.
113
114 @param Stack On input: old stack; On output: new stack
115 @param StackPtr On input: old stack pointer; On output: new stack
116 pointer
117 @param StackEnd On input: old stack end; On output: new stack end
118 @param Data Data to push.
119
120 @retval EFI_SUCCESS Push stack success.
121
122 **/
123 EFI_STATUS
124 PushStack (
125 IN OUT EFI_HII_VALUE **Stack,
126 IN OUT EFI_HII_VALUE **StackPtr,
127 IN OUT EFI_HII_VALUE **StackEnd,
128 IN EFI_HII_VALUE *Data
129 )
130 {
131 EFI_STATUS Status;
132
133 //
134 // Check for a stack overflow condition
135 //
136 if (*StackPtr >= *StackEnd) {
137 //
138 // Grow the stack
139 //
140 Status = GrowStack (Stack, StackPtr, StackEnd);
141 if (EFI_ERROR (Status)) {
142 return Status;
143 }
144 }
145
146 //
147 // Push the item onto the stack
148 //
149 CopyMem (*StackPtr, Data, sizeof (EFI_HII_VALUE));
150 if (Data->Type == EFI_IFR_TYPE_BUFFER) {
151 (*StackPtr)->Buffer = AllocateCopyPool(Data->BufferLen, Data->Buffer);
152 ASSERT ((*StackPtr)->Buffer != NULL);
153 }
154
155 *StackPtr = *StackPtr + 1;
156
157 return EFI_SUCCESS;
158 }
159
160
161 /**
162 Pop an element from the stack.
163
164 @param Stack On input: old stack
165 @param StackPtr On input: old stack pointer; On output: new stack pointer
166 @param Data Data to pop.
167
168 @retval EFI_SUCCESS The value was popped onto the stack.
169 @retval EFI_ACCESS_DENIED The pop operation underflowed the stack
170
171 **/
172 EFI_STATUS
173 PopStack (
174 IN EFI_HII_VALUE *Stack,
175 IN OUT EFI_HII_VALUE **StackPtr,
176 OUT EFI_HII_VALUE *Data
177 )
178 {
179 //
180 // Check for a stack underflow condition
181 //
182 if (*StackPtr == Stack) {
183 return EFI_ACCESS_DENIED;
184 }
185
186 //
187 // Pop the item off the stack
188 //
189 *StackPtr = *StackPtr - 1;
190 CopyMem (Data, *StackPtr, sizeof (EFI_HII_VALUE));
191 return EFI_SUCCESS;
192 }
193
194
195 /**
196 Reset stack pointer to begin of the stack.
197
198 **/
199 VOID
200 ResetCurrentExpressionStack (
201 VOID
202 )
203 {
204 mCurrentExpressionPointer = mCurrentExpressionStack;
205 mFormExpressionPointer = mFormExpressionStack;
206 mStatementExpressionPointer = mStatementExpressionStack;
207 mOptionExpressionPointer = mOptionExpressionStack;
208 }
209
210
211 /**
212 Push current expression onto the Stack
213
214 @param Pointer Pointer to current expression.
215
216 @retval EFI_SUCCESS The value was pushed onto the stack.
217 @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the stack.
218
219 **/
220 EFI_STATUS
221 PushCurrentExpression (
222 IN VOID *Pointer
223 )
224 {
225 EFI_HII_VALUE Data;
226
227 Data.Type = EFI_IFR_TYPE_NUM_SIZE_64;
228 Data.Value.u64 = (UINT64) (UINTN) Pointer;
229
230 return PushStack (
231 &mCurrentExpressionStack,
232 &mCurrentExpressionPointer,
233 &mCurrentExpressionEnd,
234 &Data
235 );
236 }
237
238
239 /**
240 Pop current expression from the Stack
241
242 @param Pointer Pointer to current expression to be pop.
243
244 @retval EFI_SUCCESS The value was pushed onto the stack.
245 @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the stack.
246
247 **/
248 EFI_STATUS
249 PopCurrentExpression (
250 OUT VOID **Pointer
251 )
252 {
253 EFI_STATUS Status;
254 EFI_HII_VALUE Data;
255
256 Status = PopStack (
257 mCurrentExpressionStack,
258 &mCurrentExpressionPointer,
259 &Data
260 );
261
262 *Pointer = (VOID *) (UINTN) Data.Value.u64;
263
264 return Status;
265 }
266
267 /**
268 Reset stack pointer to begin of the stack.
269
270 **/
271 VOID
272 ResetMapExpressionListStack (
273 VOID
274 )
275 {
276 mMapExpressionListPointer = mMapExpressionListStack;
277 }
278
279
280 /**
281 Grow size of the stack.
282
283 This is an internal function.
284
285 @param Stack On input: old stack; On output: new stack
286 @param StackPtr On input: old stack pointer; On output: new stack
287 pointer
288 @param StackEnd On input: old stack end; On output: new stack end
289 @param MemberSize The stack member size.
290
291 @retval EFI_SUCCESS Grow stack success.
292 @retval EFI_OUT_OF_RESOURCES No enough memory for stack space.
293
294 **/
295 EFI_STATUS
296 GrowConditionalStack (
297 IN OUT FORM_EXPRESSION ***Stack,
298 IN OUT FORM_EXPRESSION ***StackPtr,
299 IN OUT FORM_EXPRESSION ***StackEnd,
300 IN UINTN MemberSize
301 )
302 {
303 UINTN Size;
304 FORM_EXPRESSION **NewStack;
305
306 Size = EXPRESSION_STACK_SIZE_INCREMENT;
307 if (*StackPtr != NULL) {
308 Size = Size + (*StackEnd - *Stack);
309 }
310
311 NewStack = AllocatePool (Size * MemberSize);
312 if (NewStack == NULL) {
313 return EFI_OUT_OF_RESOURCES;
314 }
315
316 if (*StackPtr != NULL) {
317 //
318 // Copy from Old Stack to the New Stack
319 //
320 CopyMem (
321 NewStack,
322 *Stack,
323 (*StackEnd - *Stack) * MemberSize
324 );
325
326 //
327 // Free The Old Stack
328 //
329 FreePool (*Stack);
330 }
331
332 //
333 // Make the Stack pointer point to the old data in the new stack
334 //
335 *StackPtr = NewStack + (*StackPtr - *Stack);
336 *Stack = NewStack;
337 *StackEnd = NewStack + Size;
338
339 return EFI_SUCCESS;
340 }
341
342 /**
343 Push an element onto the Stack.
344
345 @param Stack On input: old stack; On output: new stack
346 @param StackPtr On input: old stack pointer; On output: new stack
347 pointer
348 @param StackEnd On input: old stack end; On output: new stack end
349 @param Data Data to push.
350
351 @retval EFI_SUCCESS Push stack success.
352
353 **/
354 EFI_STATUS
355 PushConditionalStack (
356 IN OUT FORM_EXPRESSION ***Stack,
357 IN OUT FORM_EXPRESSION ***StackPtr,
358 IN OUT FORM_EXPRESSION ***StackEnd,
359 IN FORM_EXPRESSION **Data
360 )
361 {
362 EFI_STATUS Status;
363
364 //
365 // Check for a stack overflow condition
366 //
367 if (*StackPtr >= *StackEnd) {
368 //
369 // Grow the stack
370 //
371 Status = GrowConditionalStack (Stack, StackPtr, StackEnd, sizeof (FORM_EXPRESSION *));
372 if (EFI_ERROR (Status)) {
373 return Status;
374 }
375 }
376
377 //
378 // Push the item onto the stack
379 //
380 CopyMem (*StackPtr, Data, sizeof (FORM_EXPRESSION *));
381 *StackPtr = *StackPtr + 1;
382
383 return EFI_SUCCESS;
384
385 }
386
387 /**
388 Pop an element from the stack.
389
390 @param Stack On input: old stack
391 @param StackPtr On input: old stack pointer; On output: new stack pointer
392 @param Data Data to pop.
393
394 @retval EFI_SUCCESS The value was popped onto the stack.
395 @retval EFI_ACCESS_DENIED The pop operation underflowed the stack
396
397 **/
398 EFI_STATUS
399 PopConditionalStack (
400 IN FORM_EXPRESSION **Stack,
401 IN OUT FORM_EXPRESSION ***StackPtr,
402 OUT FORM_EXPRESSION **Data
403 )
404 {
405 //
406 // Check for a stack underflow condition
407 //
408 if (*StackPtr == Stack) {
409 return EFI_ACCESS_DENIED;
410 }
411
412 //
413 // Pop the item off the stack
414 //
415 *StackPtr = *StackPtr - 1;
416 CopyMem (Data, *StackPtr, sizeof (FORM_EXPRESSION *));
417 return EFI_SUCCESS;
418
419 }
420
421 /**
422 Get the expression list count.
423
424 @param Level Which type this expression belong to. Form,
425 statement or option?
426
427 @retval >=0 The expression count
428 @retval -1 Input parameter error.
429
430 **/
431 INTN
432 GetConditionalExpressionCount (
433 IN EXPRESS_LEVEL Level
434 )
435 {
436 switch (Level) {
437 case ExpressForm:
438 return mFormExpressionPointer - mFormExpressionStack;
439 case ExpressStatement:
440 return mStatementExpressionPointer - mStatementExpressionStack;
441 case ExpressOption:
442 return mOptionExpressionPointer - mOptionExpressionStack;
443 default:
444 ASSERT (FALSE);
445 return -1;
446 }
447 }
448
449 /**
450 Get the expression Buffer pointer.
451
452 @param Level Which type this expression belong to. Form,
453 statement or option?
454
455 @retval The start pointer of the expression buffer or NULL.
456
457 **/
458 FORM_EXPRESSION **
459 GetConditionalExpressionList (
460 IN EXPRESS_LEVEL Level
461 )
462 {
463 switch (Level) {
464 case ExpressForm:
465 return mFormExpressionStack;
466 case ExpressStatement:
467 return mStatementExpressionStack;
468 case ExpressOption:
469 return mOptionExpressionStack;
470 default:
471 ASSERT (FALSE);
472 return NULL;
473 }
474 }
475
476
477 /**
478 Push the expression options onto the Stack.
479
480 @param Pointer Pointer to the current expression.
481 @param Level Which type this expression belong to. Form,
482 statement or option?
483
484 @retval EFI_SUCCESS The value was pushed onto the stack.
485 @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the stack.
486
487 **/
488 EFI_STATUS
489 PushConditionalExpression (
490 IN FORM_EXPRESSION *Pointer,
491 IN EXPRESS_LEVEL Level
492 )
493 {
494 switch (Level) {
495 case ExpressForm:
496 return PushConditionalStack (
497 &mFormExpressionStack,
498 &mFormExpressionPointer,
499 &mFormExpressionEnd,
500 &Pointer
501 );
502 case ExpressStatement:
503 return PushConditionalStack (
504 &mStatementExpressionStack,
505 &mStatementExpressionPointer,
506 &mStatementExpressionEnd,
507 &Pointer
508 );
509 case ExpressOption:
510 return PushConditionalStack (
511 &mOptionExpressionStack,
512 &mOptionExpressionPointer,
513 &mOptionExpressionEnd,
514 &Pointer
515 );
516 default:
517 ASSERT (FALSE);
518 return EFI_INVALID_PARAMETER;
519 }
520 }
521
522 /**
523 Pop the expression options from the Stack
524
525 @param Level Which type this expression belong to. Form,
526 statement or option?
527
528 @retval EFI_SUCCESS The value was pushed onto the stack.
529 @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the stack.
530
531 **/
532 EFI_STATUS
533 PopConditionalExpression (
534 IN EXPRESS_LEVEL Level
535 )
536 {
537 FORM_EXPRESSION *Pointer;
538
539 switch (Level) {
540 case ExpressForm:
541 return PopConditionalStack (
542 mFormExpressionStack,
543 &mFormExpressionPointer,
544 &Pointer
545 );
546
547 case ExpressStatement:
548 return PopConditionalStack (
549 mStatementExpressionStack,
550 &mStatementExpressionPointer,
551 &Pointer
552 );
553
554 case ExpressOption:
555 return PopConditionalStack (
556 mOptionExpressionStack,
557 &mOptionExpressionPointer,
558 &Pointer
559 );
560
561 default:
562 ASSERT (FALSE);
563 return EFI_INVALID_PARAMETER;
564 }
565 }
566
567
568 /**
569 Push the list of map expression onto the Stack
570
571 @param Pointer Pointer to the list of map expression to be pushed.
572
573 @retval EFI_SUCCESS The value was pushed onto the stack.
574 @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the stack.
575
576 **/
577 EFI_STATUS
578 PushMapExpressionList (
579 IN VOID *Pointer
580 )
581 {
582 EFI_HII_VALUE Data;
583
584 Data.Type = EFI_IFR_TYPE_NUM_SIZE_64;
585 Data.Value.u64 = (UINT64) (UINTN) Pointer;
586
587 return PushStack (
588 &mMapExpressionListStack,
589 &mMapExpressionListPointer,
590 &mMapExpressionListEnd,
591 &Data
592 );
593 }
594
595
596 /**
597 Pop the list of map expression from the Stack
598
599 @param Pointer Pointer to the list of map expression to be pop.
600
601 @retval EFI_SUCCESS The value was pushed onto the stack.
602 @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the stack.
603
604 **/
605 EFI_STATUS
606 PopMapExpressionList (
607 OUT VOID **Pointer
608 )
609 {
610 EFI_STATUS Status;
611 EFI_HII_VALUE Data;
612
613 Status = PopStack (
614 mMapExpressionListStack,
615 &mMapExpressionListPointer,
616 &Data
617 );
618
619 *Pointer = (VOID *) (UINTN) Data.Value.u64;
620
621 return Status;
622 }
623
624 /**
625 Reset stack pointer to begin of the stack.
626
627 **/
628 VOID
629 ResetScopeStack (
630 VOID
631 )
632 {
633 mOpCodeScopeStackPointer = mOpCodeScopeStack;
634 }
635
636
637 /**
638 Push an Operand onto the Stack
639
640 @param Operand Operand to push.
641
642 @retval EFI_SUCCESS The value was pushed onto the stack.
643 @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the
644 stack.
645
646 **/
647 EFI_STATUS
648 PushScope (
649 IN UINT8 Operand
650 )
651 {
652 EFI_HII_VALUE Data;
653
654 Data.Type = EFI_IFR_TYPE_NUM_SIZE_8;
655 Data.Value.u8 = Operand;
656
657 return PushStack (
658 &mOpCodeScopeStack,
659 &mOpCodeScopeStackPointer,
660 &mOpCodeScopeStackEnd,
661 &Data
662 );
663 }
664
665
666 /**
667 Pop an Operand from the Stack
668
669 @param Operand Operand to pop.
670
671 @retval EFI_SUCCESS The value was pushed onto the stack.
672 @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the
673 stack.
674
675 **/
676 EFI_STATUS
677 PopScope (
678 OUT UINT8 *Operand
679 )
680 {
681 EFI_STATUS Status;
682 EFI_HII_VALUE Data;
683
684 Status = PopStack (
685 mOpCodeScopeStack,
686 &mOpCodeScopeStackPointer,
687 &Data
688 );
689
690 *Operand = Data.Value.u8;
691
692 return Status;
693 }
694
695
696 /**
697 Push an Expression value onto the Stack
698
699 @param Value Expression value to push.
700
701 @retval EFI_SUCCESS The value was pushed onto the stack.
702 @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the
703 stack.
704
705 **/
706 EFI_STATUS
707 PushExpression (
708 IN EFI_HII_VALUE *Value
709 )
710 {
711 return PushStack (
712 &mExpressionEvaluationStack,
713 &mExpressionEvaluationStackPointer,
714 &mExpressionEvaluationStackEnd,
715 Value
716 );
717 }
718
719
720 /**
721 Pop an Expression value from the stack.
722
723 @param Value Expression value to pop.
724
725 @retval EFI_SUCCESS The value was popped onto the stack.
726 @retval EFI_ACCESS_DENIED The pop operation underflowed the stack
727
728 **/
729 EFI_STATUS
730 PopExpression (
731 OUT EFI_HII_VALUE *Value
732 )
733 {
734 return PopStack (
735 mExpressionEvaluationStack + mExpressionEvaluationStackOffset,
736 &mExpressionEvaluationStackPointer,
737 Value
738 );
739 }
740
741 /**
742 Get current stack offset from stack start.
743
744 @return Stack offset to stack start.
745 **/
746 UINTN
747 SaveExpressionEvaluationStackOffset (
748 VOID
749 )
750 {
751 UINTN TempStackOffset;
752 TempStackOffset = mExpressionEvaluationStackOffset;
753 mExpressionEvaluationStackOffset = mExpressionEvaluationStackPointer - mExpressionEvaluationStack;
754 return TempStackOffset;
755 }
756
757 /**
758 Restore stack offset based on input stack offset
759
760 @param StackOffset Offset to stack start.
761
762 **/
763 VOID
764 RestoreExpressionEvaluationStackOffset (
765 UINTN StackOffset
766 )
767 {
768 mExpressionEvaluationStackOffset = StackOffset;
769 }
770
771 /**
772 Get Form given its FormId.
773
774 @param FormSet The formset which contains this form.
775 @param FormId Id of this form.
776
777 @retval Pointer The form.
778 @retval NULL Specified Form is not found in the formset.
779
780 **/
781 FORM_BROWSER_FORM *
782 IdToForm (
783 IN FORM_BROWSER_FORMSET *FormSet,
784 IN UINT16 FormId
785 )
786 {
787 LIST_ENTRY *Link;
788 FORM_BROWSER_FORM *Form;
789
790 Link = GetFirstNode (&FormSet->FormListHead);
791 while (!IsNull (&FormSet->FormListHead, Link)) {
792 Form = FORM_BROWSER_FORM_FROM_LINK (Link);
793
794 if (Form->FormId == FormId) {
795 return Form;
796 }
797
798 Link = GetNextNode (&FormSet->FormListHead, Link);
799 }
800
801 return NULL;
802 }
803
804
805 /**
806 Search a Question in Form scope using its QuestionId.
807
808 @param Form The form which contains this Question.
809 @param QuestionId Id of this Question.
810
811 @retval Pointer The Question.
812 @retval NULL Specified Question not found in the form.
813
814 **/
815 FORM_BROWSER_STATEMENT *
816 IdToQuestion2 (
817 IN FORM_BROWSER_FORM *Form,
818 IN UINT16 QuestionId
819 )
820 {
821 LIST_ENTRY *Link;
822 FORM_BROWSER_STATEMENT *Question;
823
824 if (QuestionId == 0 || Form == NULL) {
825 //
826 // The value of zero is reserved
827 //
828 return NULL;
829 }
830
831 Link = GetFirstNode (&Form->StatementListHead);
832 while (!IsNull (&Form->StatementListHead, Link)) {
833 Question = FORM_BROWSER_STATEMENT_FROM_LINK (Link);
834
835 if (Question->QuestionId == QuestionId) {
836 return Question;
837 }
838
839 Link = GetNextNode (&Form->StatementListHead, Link);
840 }
841
842 return NULL;
843 }
844
845
846 /**
847 Search a Question in Formset scope using its QuestionId.
848
849 @param FormSet The formset which contains this form.
850 @param Form The form which contains this Question.
851 @param QuestionId Id of this Question.
852
853 @retval Pointer The Question.
854 @retval NULL Specified Question not found in the form.
855
856 **/
857 FORM_BROWSER_STATEMENT *
858 IdToQuestion (
859 IN FORM_BROWSER_FORMSET *FormSet,
860 IN FORM_BROWSER_FORM *Form,
861 IN UINT16 QuestionId
862 )
863 {
864 LIST_ENTRY *Link;
865 FORM_BROWSER_STATEMENT *Question;
866
867 //
868 // Search in the form scope first
869 //
870 Question = IdToQuestion2 (Form, QuestionId);
871 if (Question != NULL) {
872 return Question;
873 }
874
875 //
876 // Search in the formset scope
877 //
878 Link = GetFirstNode (&FormSet->FormListHead);
879 while (!IsNull (&FormSet->FormListHead, Link)) {
880 Form = FORM_BROWSER_FORM_FROM_LINK (Link);
881
882 Question = IdToQuestion2 (Form, QuestionId);
883 if (Question != NULL) {
884 //
885 // EFI variable storage may be updated by Callback() asynchronous,
886 // to keep synchronous, always reload the Question Value.
887 //
888 if (Question->Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE) {
889 GetQuestionValue (FormSet, Form, Question, GetSetValueWithHiiDriver);
890 }
891
892 return Question;
893 }
894
895 Link = GetNextNode (&FormSet->FormListHead, Link);
896 }
897
898 return NULL;
899 }
900
901
902 /**
903 Get Expression given its RuleId.
904
905 @param Form The form which contains this Expression.
906 @param RuleId Id of this Expression.
907
908 @retval Pointer The Expression.
909 @retval NULL Specified Expression not found in the form.
910
911 **/
912 FORM_EXPRESSION *
913 RuleIdToExpression (
914 IN FORM_BROWSER_FORM *Form,
915 IN UINT8 RuleId
916 )
917 {
918 LIST_ENTRY *Link;
919 FORM_EXPRESSION *Expression;
920
921 Link = GetFirstNode (&Form->ExpressionListHead);
922 while (!IsNull (&Form->ExpressionListHead, Link)) {
923 Expression = FORM_EXPRESSION_FROM_LINK (Link);
924
925 if (Expression->Type == EFI_HII_EXPRESSION_RULE && Expression->RuleId == RuleId) {
926 return Expression;
927 }
928
929 Link = GetNextNode (&Form->ExpressionListHead, Link);
930 }
931
932 return NULL;
933 }
934
935
936 /**
937 Locate the Unicode Collation Protocol interface for later use.
938
939 @retval EFI_SUCCESS Protocol interface initialize success.
940 @retval Other Protocol interface initialize failed.
941
942 **/
943 EFI_STATUS
944 InitializeUnicodeCollationProtocol (
945 VOID
946 )
947 {
948 EFI_STATUS Status;
949
950 if (mUnicodeCollation != NULL) {
951 return EFI_SUCCESS;
952 }
953
954 //
955 // BUGBUG: Proper impelmentation is to locate all Unicode Collation Protocol
956 // instances first and then select one which support English language.
957 // Current implementation just pick the first instance.
958 //
959 Status = gBS->LocateProtocol (
960 &gEfiUnicodeCollation2ProtocolGuid,
961 NULL,
962 (VOID **) &mUnicodeCollation
963 );
964 return Status;
965 }
966
967 /**
968 Convert the input Unicode character to upper.
969
970 @param String Th Unicode character to be converted.
971
972 **/
973 VOID
974 IfrStrToUpper (
975 IN CHAR16 *String
976 )
977 {
978 while (*String != 0) {
979 if ((*String >= 'a') && (*String <= 'z')) {
980 *String = (UINT16) ((*String) & ((UINT16) ~0x20));
981 }
982 String++;
983 }
984 }
985
986 /**
987 Check whether this value type can be transfer to EFI_IFR_TYPE_BUFFER type.
988
989 EFI_IFR_TYPE_REF, EFI_IFR_TYPE_DATE and EFI_IFR_TYPE_TIME are converted to
990 EFI_IFR_TYPE_BUFFER when do the value compare.
991
992 @param Value Expression value to compare on.
993
994 @retval TRUE This value type can be transter to EFI_IFR_TYPE_BUFFER type.
995 @retval FALSE This value type can't be transter to EFI_IFR_TYPE_BUFFER type.
996
997 **/
998 BOOLEAN
999 IsTypeInBuffer (
1000 IN EFI_HII_VALUE *Value
1001 )
1002 {
1003 switch (Value->Type) {
1004 case EFI_IFR_TYPE_BUFFER:
1005 case EFI_IFR_TYPE_DATE:
1006 case EFI_IFR_TYPE_TIME:
1007 case EFI_IFR_TYPE_REF:
1008 return TRUE;
1009
1010 default:
1011 return FALSE;
1012 }
1013 }
1014
1015 /**
1016 Check whether this value type can be transfer to EFI_IFR_TYPE_UINT64
1017
1018 @param Value Expression value to compare on.
1019
1020 @retval TRUE This value type can be transter to EFI_IFR_TYPE_BUFFER type.
1021 @retval FALSE This value type can't be transter to EFI_IFR_TYPE_BUFFER type.
1022
1023 **/
1024 BOOLEAN
1025 IsTypeInUINT64 (
1026 IN EFI_HII_VALUE *Value
1027 )
1028 {
1029 switch (Value->Type) {
1030 case EFI_IFR_TYPE_NUM_SIZE_8:
1031 case EFI_IFR_TYPE_NUM_SIZE_16:
1032 case EFI_IFR_TYPE_NUM_SIZE_32:
1033 case EFI_IFR_TYPE_NUM_SIZE_64:
1034 case EFI_IFR_TYPE_BOOLEAN:
1035 return TRUE;
1036
1037 default:
1038 return FALSE;
1039 }
1040 }
1041
1042 /**
1043 Return the buffer length for this value.
1044
1045 EFI_IFR_TYPE_REF, EFI_IFR_TYPE_DATE and EFI_IFR_TYPE_TIME are converted to
1046 EFI_IFR_TYPE_BUFFER when do the value compare.
1047
1048 @param Value Expression value to compare on.
1049
1050 @retval BufLen Return the buffer length.
1051
1052 **/
1053 UINT16
1054 GetLengthForValue (
1055 IN EFI_HII_VALUE *Value
1056 )
1057 {
1058 switch (Value->Type) {
1059 case EFI_IFR_TYPE_BUFFER:
1060 return Value->BufferLen;
1061
1062 case EFI_IFR_TYPE_DATE:
1063 return (UINT16) sizeof (EFI_HII_DATE);
1064
1065 case EFI_IFR_TYPE_TIME:
1066 return (UINT16) sizeof (EFI_HII_TIME);
1067
1068 case EFI_IFR_TYPE_REF:
1069 return (UINT16) sizeof (EFI_HII_REF);
1070
1071 default:
1072 return 0;
1073 }
1074 }
1075
1076 /**
1077 Return the buffer pointer for this value.
1078
1079 EFI_IFR_TYPE_REF, EFI_IFR_TYPE_DATE and EFI_IFR_TYPE_TIME are converted to
1080 EFI_IFR_TYPE_BUFFER when do the value compare.
1081
1082 @param Value Expression value to compare on.
1083
1084 @retval Buf Return the buffer pointer.
1085
1086 **/
1087 UINT8 *
1088 GetBufferForValue (
1089 IN EFI_HII_VALUE *Value
1090 )
1091 {
1092 switch (Value->Type) {
1093 case EFI_IFR_TYPE_BUFFER:
1094 return Value->Buffer;
1095
1096 case EFI_IFR_TYPE_DATE:
1097 return (UINT8 *) (&Value->Value.date);
1098
1099 case EFI_IFR_TYPE_TIME:
1100 return (UINT8 *) (&Value->Value.time);
1101
1102 case EFI_IFR_TYPE_REF:
1103 return (UINT8 *) (&Value->Value.ref);
1104
1105 default:
1106 return NULL;
1107 }
1108 }
1109
1110 /**
1111 Evaluate opcode EFI_IFR_TO_STRING.
1112
1113 @param FormSet Formset which contains this opcode.
1114 @param Format String format in EFI_IFR_TO_STRING.
1115 @param Result Evaluation result for this opcode.
1116
1117 @retval EFI_SUCCESS Opcode evaluation success.
1118 @retval Other Opcode evaluation failed.
1119
1120 **/
1121 EFI_STATUS
1122 IfrToString (
1123 IN FORM_BROWSER_FORMSET *FormSet,
1124 IN UINT8 Format,
1125 OUT EFI_HII_VALUE *Result
1126 )
1127 {
1128 EFI_STATUS Status;
1129 EFI_HII_VALUE Value;
1130 CHAR16 *String;
1131 CHAR16 *PrintFormat;
1132 CHAR16 Buffer[MAXIMUM_VALUE_CHARACTERS];
1133 UINT8 *TmpBuf;
1134 UINT8 *SrcBuf;
1135 UINTN SrcLen;
1136 UINTN BufferSize;
1137
1138 Status = PopExpression (&Value);
1139 if (EFI_ERROR (Status)) {
1140 return Status;
1141 }
1142
1143 switch (Value.Type) {
1144 case EFI_IFR_TYPE_NUM_SIZE_8:
1145 case EFI_IFR_TYPE_NUM_SIZE_16:
1146 case EFI_IFR_TYPE_NUM_SIZE_32:
1147 case EFI_IFR_TYPE_NUM_SIZE_64:
1148 BufferSize = MAXIMUM_VALUE_CHARACTERS * sizeof (CHAR16);
1149 switch (Format) {
1150 case EFI_IFR_STRING_UNSIGNED_DEC:
1151 case EFI_IFR_STRING_SIGNED_DEC:
1152 PrintFormat = L"%ld";
1153 break;
1154
1155 case EFI_IFR_STRING_LOWERCASE_HEX:
1156 PrintFormat = L"%lx";
1157 break;
1158
1159 case EFI_IFR_STRING_UPPERCASE_HEX:
1160 PrintFormat = L"%lX";
1161 break;
1162
1163 default:
1164 Result->Type = EFI_IFR_TYPE_UNDEFINED;
1165 return EFI_SUCCESS;
1166 }
1167 UnicodeSPrint (Buffer, BufferSize, PrintFormat, Value.Value.u64);
1168 String = Buffer;
1169 break;
1170
1171 case EFI_IFR_TYPE_STRING:
1172 CopyMem (Result, &Value, sizeof (EFI_HII_VALUE));
1173 return EFI_SUCCESS;
1174
1175 case EFI_IFR_TYPE_BOOLEAN:
1176 String = (Value.Value.b) ? L"True" : L"False";
1177 break;
1178
1179 case EFI_IFR_TYPE_BUFFER:
1180 case EFI_IFR_TYPE_DATE:
1181 case EFI_IFR_TYPE_TIME:
1182 case EFI_IFR_TYPE_REF:
1183 //
1184 // + 3 is base on the unicode format, the length may be odd number,
1185 // so need 1 byte to align, also need 2 bytes for L'\0'.
1186 //
1187 if (Value.Type == EFI_IFR_TYPE_BUFFER) {
1188 SrcLen = Value.BufferLen;
1189 SrcBuf = Value.Buffer;
1190 } else {
1191 SrcBuf = GetBufferForValue(&Value);
1192 SrcLen = GetLengthForValue(&Value);
1193 }
1194
1195 TmpBuf = AllocateZeroPool (SrcLen + 3);
1196 ASSERT (TmpBuf != NULL);
1197 if (Format == EFI_IFR_STRING_ASCII) {
1198 CopyMem (TmpBuf, SrcBuf, SrcLen);
1199 PrintFormat = L"%a";
1200 } else {
1201 // Format == EFI_IFR_STRING_UNICODE
1202 CopyMem (TmpBuf, SrcBuf, SrcLen * sizeof (CHAR16));
1203 PrintFormat = L"%s";
1204 }
1205 UnicodeSPrint (Buffer, sizeof (Buffer), PrintFormat, TmpBuf);
1206 String = Buffer;
1207 FreePool (TmpBuf);
1208 if (Value.Type == EFI_IFR_TYPE_BUFFER) {
1209 FreePool (Value.Buffer);
1210 }
1211 break;
1212
1213 default:
1214 Result->Type = EFI_IFR_TYPE_UNDEFINED;
1215 return EFI_SUCCESS;
1216 }
1217
1218 Result->Type = EFI_IFR_TYPE_STRING;
1219 Result->Value.string = NewString (String, FormSet->HiiHandle);
1220 return EFI_SUCCESS;
1221 }
1222
1223
1224 /**
1225 Evaluate opcode EFI_IFR_TO_UINT.
1226
1227 @param FormSet Formset which contains this opcode.
1228 @param Result Evaluation result for this opcode.
1229
1230 @retval EFI_SUCCESS Opcode evaluation success.
1231 @retval Other Opcode evaluation failed.
1232
1233 **/
1234 EFI_STATUS
1235 IfrToUint (
1236 IN FORM_BROWSER_FORMSET *FormSet,
1237 OUT EFI_HII_VALUE *Result
1238 )
1239 {
1240 EFI_STATUS Status;
1241 EFI_HII_VALUE Value;
1242 CHAR16 *String;
1243 CHAR16 *StringPtr;
1244
1245 Status = PopExpression (&Value);
1246 if (EFI_ERROR (Status)) {
1247 return Status;
1248 }
1249
1250 if (Value.Type >= EFI_IFR_TYPE_OTHER && !IsTypeInBuffer(&Value)) {
1251 Result->Type = EFI_IFR_TYPE_UNDEFINED;
1252 return EFI_SUCCESS;
1253 }
1254
1255 Status = EFI_SUCCESS;
1256 if (Value.Type == EFI_IFR_TYPE_STRING) {
1257 String = GetToken (Value.Value.string, FormSet->HiiHandle);
1258 if (String == NULL) {
1259 return EFI_NOT_FOUND;
1260 }
1261
1262 IfrStrToUpper (String);
1263 StringPtr = StrStr (String, L"0X");
1264 if (StringPtr != NULL) {
1265 //
1266 // Hex string
1267 //
1268 Result->Value.u64 = StrHexToUint64 (String);
1269 } else {
1270 //
1271 // decimal string
1272 //
1273 Result->Value.u64 = StrDecimalToUint64 (String);
1274 }
1275 FreePool (String);
1276 } else if (IsTypeInBuffer(&Value)) {
1277 if (GetLengthForValue (&Value) > 8) {
1278 if (Value.Type == EFI_IFR_TYPE_BUFFER) {
1279 FreePool (Value.Buffer);
1280 }
1281 Result->Type = EFI_IFR_TYPE_UNDEFINED;
1282 return EFI_SUCCESS;
1283 }
1284
1285 ASSERT (GetBufferForValue (&Value) != NULL);
1286 Result->Value.u64 = *(UINT64*) GetBufferForValue (&Value);
1287
1288 if (Value.Type == EFI_IFR_TYPE_BUFFER) {
1289 FreePool (Value.Buffer);
1290 }
1291 } else {
1292 CopyMem (Result, &Value, sizeof (EFI_HII_VALUE));
1293 }
1294
1295 Result->Type = EFI_IFR_TYPE_NUM_SIZE_64;
1296 return Status;
1297 }
1298
1299
1300 /**
1301 Evaluate opcode EFI_IFR_CATENATE.
1302
1303 @param FormSet Formset which contains this opcode.
1304 @param Result Evaluation result for this opcode.
1305
1306 @retval EFI_SUCCESS Opcode evaluation success.
1307 @retval Other Opcode evaluation failed.
1308
1309 **/
1310 EFI_STATUS
1311 IfrCatenate (
1312 IN FORM_BROWSER_FORMSET *FormSet,
1313 OUT EFI_HII_VALUE *Result
1314 )
1315 {
1316 EFI_STATUS Status;
1317 EFI_HII_VALUE Value[2];
1318 CHAR16 *String[2];
1319 UINTN Index;
1320 CHAR16 *StringPtr;
1321 UINTN Size;
1322 UINT16 Length0;
1323 UINT16 Length1;
1324 UINT8 *TmpBuf;
1325 UINTN MaxLen;
1326
1327 //
1328 // String[0] - The second string
1329 // String[1] - The first string
1330 //
1331 String[0] = NULL;
1332 String[1] = NULL;
1333 StringPtr = NULL;
1334 Status = EFI_SUCCESS;
1335 ZeroMem (Value, sizeof (Value));
1336
1337 Status = PopExpression (&Value[0]);
1338 if (EFI_ERROR (Status)) {
1339 goto Done;
1340 }
1341
1342 Status = PopExpression (&Value[1]);
1343 if (EFI_ERROR (Status)) {
1344 goto Done;
1345 }
1346
1347 for (Index = 0; Index < 2; Index++) {
1348 if (Value[Index].Type != EFI_IFR_TYPE_STRING && !IsTypeInBuffer(&Value[Index])) {
1349 Result->Type = EFI_IFR_TYPE_UNDEFINED;
1350 Status = EFI_SUCCESS;
1351 goto Done;
1352 }
1353
1354 if (Value[Index].Type == EFI_IFR_TYPE_STRING) {
1355 String[Index] = GetToken (Value[Index].Value.string, FormSet->HiiHandle);
1356 if (String[Index] == NULL) {
1357 Status = EFI_NOT_FOUND;
1358 goto Done;
1359 }
1360 }
1361 }
1362
1363 if (Value[0].Type == EFI_IFR_TYPE_STRING) {
1364 Size = StrSize (String[0]);
1365 MaxLen = (StrSize (String[1]) + Size) / sizeof (CHAR16);
1366 StringPtr= AllocatePool (MaxLen * sizeof (CHAR16));
1367 ASSERT (StringPtr != NULL);
1368 StrCpyS (StringPtr, MaxLen, String[1]);
1369 StrCatS (StringPtr, MaxLen, 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, GetSetValueWithEditBuffer);
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 (IsZeroGuid (&OpCode->Guid)) {
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 (NameValue != 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 UnicodeValueToStringS (
3145 StrPtr,
3146 (OpCode->ValueWidth * 2 + 1) * sizeof (CHAR16) - ((UINTN)StrPtr - (UINTN)NameValue),
3147 PREFIX_ZERO | RADIX_HEX,
3148 *TempBuffer,
3149 2
3150 );
3151 StrPtr += StrnLenS (StrPtr, OpCode->ValueWidth * 2 + 1 - ((UINTN)StrPtr - (UINTN)NameValue) / sizeof (CHAR16));
3152 }
3153 Status = SetValueByName (OpCode->VarStorage, OpCode->ValueName, NameValue, GetSetValueWithEditBuffer, NULL);
3154 FreePool (NameValue);
3155 if (!EFI_ERROR (Status)) {
3156 Data1.Value.b = TRUE;
3157 }
3158 }
3159 break;
3160 case EFI_HII_VARSTORE_EFI_VARIABLE:
3161 Status = gRT->SetVariable (
3162 OpCode->ValueName,
3163 &OpCode->VarStorage->Guid,
3164 OpCode->VarStorage->Attributes,
3165 OpCode->ValueWidth,
3166 &Value->Value
3167 );
3168 if (!EFI_ERROR (Status)) {
3169 Data1.Value.b = TRUE;
3170 }
3171 break;
3172 default:
3173 //
3174 // Not recognize storage.
3175 //
3176 Status = EFI_UNSUPPORTED;
3177 goto Done;
3178 }
3179 } else {
3180 //
3181 // For Time/Date Data
3182 //
3183 if (OpCode->ValueType != EFI_IFR_TYPE_DATE && OpCode->ValueType != EFI_IFR_TYPE_TIME) {
3184 //
3185 // Only support Data/Time data when storage doesn't exist.
3186 //
3187 Status = EFI_UNSUPPORTED;
3188 goto Done;
3189 }
3190 Status = gRT->GetTime (&EfiTime, NULL);
3191 if (!EFI_ERROR (Status)) {
3192 if (OpCode->ValueType == EFI_IFR_TYPE_DATE) {
3193 switch (OpCode->VarStoreInfo.VarOffset) {
3194 case 0x00:
3195 EfiTime.Year = Value->Value.u16;
3196 break;
3197 case 0x02:
3198 EfiTime.Month = Value->Value.u8;
3199 break;
3200 case 0x03:
3201 EfiTime.Day = Value->Value.u8;
3202 break;
3203 default:
3204 //
3205 // Invalid Date field.
3206 //
3207 Status = EFI_INVALID_PARAMETER;
3208 goto Done;
3209 }
3210 } else {
3211 switch (OpCode->VarStoreInfo.VarOffset) {
3212 case 0x00:
3213 EfiTime.Hour = Value->Value.u8;
3214 break;
3215 case 0x01:
3216 EfiTime.Minute = Value->Value.u8;
3217 break;
3218 case 0x02:
3219 EfiTime.Second = Value->Value.u8;
3220 break;
3221 default:
3222 //
3223 // Invalid Time field.
3224 //
3225 Status = EFI_INVALID_PARAMETER;
3226 goto Done;
3227 }
3228 }
3229 Status = gRT->SetTime (&EfiTime);
3230 if (!EFI_ERROR (Status)) {
3231 Data1.Value.b = TRUE;
3232 }
3233 }
3234 }
3235 Value = &Data1;
3236 break;
3237
3238 //
3239 // binary-op
3240 //
3241 case EFI_IFR_ADD_OP:
3242 case EFI_IFR_SUBTRACT_OP:
3243 case EFI_IFR_MULTIPLY_OP:
3244 case EFI_IFR_DIVIDE_OP:
3245 case EFI_IFR_MODULO_OP:
3246 case EFI_IFR_BITWISE_AND_OP:
3247 case EFI_IFR_BITWISE_OR_OP:
3248 case EFI_IFR_SHIFT_LEFT_OP:
3249 case EFI_IFR_SHIFT_RIGHT_OP:
3250 //
3251 // Pop an expression from the expression stack
3252 //
3253 Status = PopExpression (&Data2);
3254 if (EFI_ERROR (Status)) {
3255 goto Done;
3256 }
3257
3258 //
3259 // Pop another expression from the expression stack
3260 //
3261 Status = PopExpression (&Data1);
3262 if (EFI_ERROR (Status)) {
3263 goto Done;
3264 }
3265
3266 if (Data2.Type > EFI_IFR_TYPE_DATE) {
3267 Value->Type = EFI_IFR_TYPE_UNDEFINED;
3268 break;
3269 }
3270
3271
3272 if (Data1.Type > EFI_IFR_TYPE_DATE) {
3273 Value->Type = EFI_IFR_TYPE_UNDEFINED;
3274 break;
3275 }
3276
3277 Value->Type = EFI_IFR_TYPE_NUM_SIZE_64;
3278
3279 switch (OpCode->Operand) {
3280 case EFI_IFR_ADD_OP:
3281 Value->Value.u64 = HiiValueToUINT64(&Data1) + HiiValueToUINT64(&Data2);
3282 break;
3283
3284 case EFI_IFR_SUBTRACT_OP:
3285 Value->Value.u64 = HiiValueToUINT64(&Data1) - HiiValueToUINT64(&Data2);
3286 break;
3287
3288 case EFI_IFR_MULTIPLY_OP:
3289 Value->Value.u64 = MultU64x32 (HiiValueToUINT64(&Data1), (UINT32) HiiValueToUINT64(&Data2));
3290 break;
3291
3292 case EFI_IFR_DIVIDE_OP:
3293 Value->Value.u64 = DivU64x32 (HiiValueToUINT64(&Data1), (UINT32) HiiValueToUINT64(&Data2));
3294 break;
3295
3296 case EFI_IFR_MODULO_OP:
3297 DivU64x32Remainder (HiiValueToUINT64(&Data1), (UINT32) HiiValueToUINT64(&Data2), &TempValue);
3298 Value->Value.u64 = TempValue;
3299 break;
3300
3301 case EFI_IFR_BITWISE_AND_OP:
3302 Value->Value.u64 = HiiValueToUINT64(&Data1) & HiiValueToUINT64(&Data2);
3303 break;
3304
3305 case EFI_IFR_BITWISE_OR_OP:
3306 Value->Value.u64 = HiiValueToUINT64(&Data1) | HiiValueToUINT64(&Data2);
3307 break;
3308
3309 case EFI_IFR_SHIFT_LEFT_OP:
3310 Value->Value.u64 = LShiftU64 (HiiValueToUINT64(&Data1), (UINTN) HiiValueToUINT64(&Data2));
3311 break;
3312
3313 case EFI_IFR_SHIFT_RIGHT_OP:
3314 Value->Value.u64 = RShiftU64 (HiiValueToUINT64(&Data1), (UINTN) HiiValueToUINT64(&Data2));
3315 break;
3316
3317 default:
3318 break;
3319 }
3320 break;
3321
3322 case EFI_IFR_AND_OP:
3323 case EFI_IFR_OR_OP:
3324 //
3325 // Two Boolean operator
3326 //
3327 Status = PopExpression (&Data2);
3328 if (EFI_ERROR (Status)) {
3329 goto Done;
3330 }
3331
3332 //
3333 // Pop another expression from the expression stack
3334 //
3335 Status = PopExpression (&Data1);
3336 if (EFI_ERROR (Status)) {
3337 goto Done;
3338 }
3339
3340 if (Data2.Type != EFI_IFR_TYPE_BOOLEAN) {
3341 Value->Type = EFI_IFR_TYPE_UNDEFINED;
3342 break;
3343 }
3344
3345 if (Data1.Type != EFI_IFR_TYPE_BOOLEAN) {
3346 Value->Type = EFI_IFR_TYPE_UNDEFINED;
3347 break;
3348 }
3349
3350 if (OpCode->Operand == EFI_IFR_AND_OP) {
3351 Value->Value.b = (BOOLEAN) (Data1.Value.b && Data2.Value.b);
3352 } else {
3353 Value->Value.b = (BOOLEAN) (Data1.Value.b || Data2.Value.b);
3354 }
3355 break;
3356
3357 case EFI_IFR_EQUAL_OP:
3358 case EFI_IFR_NOT_EQUAL_OP:
3359 case EFI_IFR_GREATER_EQUAL_OP:
3360 case EFI_IFR_GREATER_THAN_OP:
3361 case EFI_IFR_LESS_EQUAL_OP:
3362 case EFI_IFR_LESS_THAN_OP:
3363 //
3364 // Compare two integer, string, boolean or date/time
3365 //
3366 Status = PopExpression (&Data2);
3367 if (EFI_ERROR (Status)) {
3368 goto Done;
3369 }
3370
3371 //
3372 // Pop another expression from the expression stack
3373 //
3374 Status = PopExpression (&Data1);
3375 if (EFI_ERROR (Status)) {
3376 goto Done;
3377 }
3378
3379 if (Data2.Type > EFI_IFR_TYPE_BOOLEAN &&
3380 Data2.Type != EFI_IFR_TYPE_STRING &&
3381 !IsTypeInBuffer(&Data2)) {
3382 Value->Type = EFI_IFR_TYPE_UNDEFINED;
3383 break;
3384 }
3385
3386 if (Data1.Type > EFI_IFR_TYPE_BOOLEAN &&
3387 Data1.Type != EFI_IFR_TYPE_STRING &&
3388 !IsTypeInBuffer(&Data1)) {
3389 Value->Type = EFI_IFR_TYPE_UNDEFINED;
3390 break;
3391 }
3392
3393 Status = CompareHiiValue (&Data1, &Data2, &Result, FormSet->HiiHandle);
3394 if (Data1.Type == EFI_IFR_TYPE_BUFFER) {
3395 FreePool (Data1.Buffer);
3396 }
3397 if (Data2.Type == EFI_IFR_TYPE_BUFFER) {
3398 FreePool (Data2.Buffer);
3399 }
3400
3401 if (Status == EFI_UNSUPPORTED) {
3402 Value->Type = EFI_IFR_TYPE_UNDEFINED;
3403 Status = EFI_SUCCESS;
3404 break;
3405 }
3406
3407 if (EFI_ERROR (Status)) {
3408 goto Done;
3409 }
3410
3411 switch (OpCode->Operand) {
3412 case EFI_IFR_EQUAL_OP:
3413 Value->Value.b = (BOOLEAN) ((Result == 0) ? TRUE : FALSE);
3414 break;
3415
3416 case EFI_IFR_NOT_EQUAL_OP:
3417 Value->Value.b = (BOOLEAN) ((Result != 0) ? TRUE : FALSE);
3418 break;
3419
3420 case EFI_IFR_GREATER_EQUAL_OP:
3421 Value->Value.b = (BOOLEAN) ((Result >= 0) ? TRUE : FALSE);
3422 break;
3423
3424 case EFI_IFR_GREATER_THAN_OP:
3425 Value->Value.b = (BOOLEAN) ((Result > 0) ? TRUE : FALSE);
3426 break;
3427
3428 case EFI_IFR_LESS_EQUAL_OP:
3429 Value->Value.b = (BOOLEAN) ((Result <= 0) ? TRUE : FALSE);
3430 break;
3431
3432 case EFI_IFR_LESS_THAN_OP:
3433 Value->Value.b = (BOOLEAN) ((Result < 0) ? TRUE : FALSE);
3434 break;
3435
3436 default:
3437 break;
3438 }
3439 break;
3440
3441 case EFI_IFR_MATCH_OP:
3442 Status = InitializeUnicodeCollationProtocol ();
3443 if (EFI_ERROR (Status)) {
3444 goto Done;
3445 }
3446
3447 Status = IfrMatch (FormSet, Value);
3448 break;
3449
3450 case EFI_IFR_MATCH2_OP:
3451 Status = IfrMatch2 (FormSet, &OpCode->Guid, Value);
3452 break;
3453
3454 case EFI_IFR_CATENATE_OP:
3455 Status = IfrCatenate (FormSet, Value);
3456 break;
3457
3458 //
3459 // ternary-op
3460 //
3461 case EFI_IFR_CONDITIONAL_OP:
3462 //
3463 // Pop third expression from the expression stack
3464 //
3465 Status = PopExpression (&Data3);
3466 if (EFI_ERROR (Status)) {
3467 goto Done;
3468 }
3469
3470 //
3471 // Pop second expression from the expression stack
3472 //
3473 Status = PopExpression (&Data2);
3474 if (EFI_ERROR (Status)) {
3475 goto Done;
3476 }
3477
3478 //
3479 // Pop first expression from the expression stack
3480 //
3481 Status = PopExpression (&Data1);
3482 if (EFI_ERROR (Status)) {
3483 goto Done;
3484 }
3485 if (Data1.Type != EFI_IFR_TYPE_BOOLEAN) {
3486 Value->Type = EFI_IFR_TYPE_UNDEFINED;
3487 break;
3488 }
3489
3490 if (Data1.Value.b) {
3491 Value = &Data3;
3492 } else {
3493 Value = &Data2;
3494 }
3495 break;
3496
3497 case EFI_IFR_FIND_OP:
3498 Status = IfrFind (FormSet, OpCode->Format, Value);
3499 break;
3500
3501 case EFI_IFR_MID_OP:
3502 Status = IfrMid (FormSet, Value);
3503 break;
3504
3505 case EFI_IFR_TOKEN_OP:
3506 Status = IfrToken (FormSet, Value);
3507 break;
3508
3509 case EFI_IFR_SPAN_OP:
3510 Status = IfrSpan (FormSet, OpCode->Flags, Value);
3511 break;
3512
3513 case EFI_IFR_MAP_OP:
3514 //
3515 // Pop the check value
3516 //
3517 Status = PopExpression (&Data1);
3518 if (EFI_ERROR (Status)) {
3519 goto Done;
3520 }
3521 //
3522 // Check MapExpression list is valid.
3523 //
3524 if (OpCode->MapExpressionList.ForwardLink == NULL) {
3525 Status = EFI_INVALID_PARAMETER;
3526 goto Done;
3527 }
3528 //
3529 // Go through map expression list.
3530 //
3531 SubExpressionLink = GetFirstNode(&OpCode->MapExpressionList);
3532 while (!IsNull (&OpCode->MapExpressionList, SubExpressionLink)) {
3533 SubExpression = FORM_EXPRESSION_FROM_LINK (SubExpressionLink);
3534 //
3535 // Evaluate the first expression in this pair.
3536 //
3537 Status = EvaluateExpression (FormSet, Form, SubExpression);
3538 if (EFI_ERROR (Status)) {
3539 goto Done;
3540 }
3541 //
3542 // Compare the expression value with current value
3543 //
3544 if ((CompareHiiValue (&Data1, &SubExpression->Result, &Result, NULL) == EFI_SUCCESS) && (Result == 0)) {
3545 //
3546 // Try get the map value.
3547 //
3548 SubExpressionLink = GetNextNode (&OpCode->MapExpressionList, SubExpressionLink);
3549 if (IsNull (&OpCode->MapExpressionList, SubExpressionLink)) {
3550 Status = EFI_INVALID_PARAMETER;
3551 goto Done;
3552 }
3553 SubExpression = FORM_EXPRESSION_FROM_LINK (SubExpressionLink);
3554 Status = EvaluateExpression (FormSet, Form, SubExpression);
3555 if (EFI_ERROR (Status)) {
3556 goto Done;
3557 }
3558 Value = &SubExpression->Result;
3559 break;
3560 }
3561 //
3562 // Skip the second expression on this pair.
3563 //
3564 SubExpressionLink = GetNextNode (&OpCode->MapExpressionList, SubExpressionLink);
3565 if (IsNull (&OpCode->MapExpressionList, SubExpressionLink)) {
3566 Status = EFI_INVALID_PARAMETER;
3567 goto Done;
3568 }
3569 //
3570 // Goto the first expression on next pair.
3571 //
3572 SubExpressionLink = GetNextNode (&OpCode->MapExpressionList, SubExpressionLink);
3573 }
3574
3575 //
3576 // No map value is found.
3577 //
3578 if (IsNull (&OpCode->MapExpressionList, SubExpressionLink)) {
3579 Value->Type = EFI_IFR_TYPE_UNDEFINED;
3580 Value->Value.u8 = 0;
3581 }
3582 break;
3583
3584 default:
3585 break;
3586 }
3587 if (EFI_ERROR (Status) || Value->Type == EFI_IFR_TYPE_UNDEFINED) {
3588 goto Done;
3589 }
3590
3591 Status = PushExpression (Value);
3592 if (EFI_ERROR (Status)) {
3593 goto Done;
3594 }
3595 }
3596
3597 //
3598 // Pop the final result from expression stack
3599 //
3600 Value = &Data1;
3601 Status = PopExpression (Value);
3602 if (EFI_ERROR (Status)) {
3603 goto Done;
3604 }
3605
3606 //
3607 // After evaluating an expression, there should be only one value left on the expression stack
3608 //
3609 if (PopExpression (Value) != EFI_ACCESS_DENIED) {
3610 Status = EFI_INVALID_PARAMETER;
3611 }
3612
3613 Done:
3614 RestoreExpressionEvaluationStackOffset (StackOffset);
3615 if (!EFI_ERROR (Status)) {
3616 CopyMem (&Expression->Result, Value, sizeof (EFI_HII_VALUE));
3617 }
3618
3619 return Status;
3620 }
3621
3622 /**
3623 Check whether the result is TRUE or FALSE.
3624
3625 For the EFI_HII_VALUE value type is numeric, return TRUE if the
3626 value is not 0.
3627
3628 @param Result Input the result data.
3629
3630 @retval TRUE The result is TRUE.
3631 @retval FALSE The result is FALSE.
3632
3633 **/
3634 BOOLEAN
3635 IsTrue (
3636 IN EFI_HII_VALUE *Result
3637 )
3638 {
3639 switch (Result->Type) {
3640 case EFI_IFR_TYPE_BOOLEAN:
3641 return Result->Value.b;
3642
3643 case EFI_IFR_TYPE_NUM_SIZE_8:
3644 return (BOOLEAN)(Result->Value.u8 != 0);
3645
3646 case EFI_IFR_TYPE_NUM_SIZE_16:
3647 return (BOOLEAN)(Result->Value.u16 != 0);
3648
3649 case EFI_IFR_TYPE_NUM_SIZE_32:
3650 return (BOOLEAN)(Result->Value.u32 != 0);
3651
3652 case EFI_IFR_TYPE_NUM_SIZE_64:
3653 return (BOOLEAN)(Result->Value.u64 != 0);
3654
3655 default:
3656 return FALSE;
3657 }
3658 }
3659
3660 /**
3661 Return the result of the expression list. Check the expression list and
3662 return the highest priority express result.
3663 Priority: DisableIf > SuppressIf > GrayOutIf > FALSE
3664
3665 @param ExpList The input expression list.
3666 @param Evaluate Whether need to evaluate the expression first.
3667 @param FormSet FormSet associated with this expression.
3668 @param Form Form associated with this expression.
3669
3670 @retval EXPRESS_RESULT Return the higher priority express result.
3671 DisableIf > SuppressIf > GrayOutIf > FALSE
3672
3673 **/
3674 EXPRESS_RESULT
3675 EvaluateExpressionList (
3676 IN FORM_EXPRESSION_LIST *ExpList,
3677 IN BOOLEAN Evaluate,
3678 IN FORM_BROWSER_FORMSET *FormSet, OPTIONAL
3679 IN FORM_BROWSER_FORM *Form OPTIONAL
3680 )
3681 {
3682 UINTN Index;
3683 EXPRESS_RESULT ReturnVal;
3684 EXPRESS_RESULT CompareOne;
3685 EFI_STATUS Status;
3686
3687 if (ExpList == NULL) {
3688 return ExpressFalse;
3689 }
3690
3691 ASSERT(ExpList->Signature == FORM_EXPRESSION_LIST_SIGNATURE);
3692 Index = 0;
3693
3694 //
3695 // Check whether need to evaluate the expression first.
3696 //
3697 if (Evaluate) {
3698 while (ExpList->Count > Index) {
3699 Status = EvaluateExpression (FormSet, Form, ExpList->Expression[Index++]);
3700 if (EFI_ERROR (Status)) {
3701 return ExpressFalse;
3702 }
3703 }
3704 }
3705
3706 //
3707 // Run the list of expressions.
3708 //
3709 ReturnVal = ExpressFalse;
3710 for (Index = 0; Index < ExpList->Count; Index++) {
3711 if (IsTrue (&ExpList->Expression[Index]->Result)) {
3712 switch (ExpList->Expression[Index]->Type) {
3713 case EFI_HII_EXPRESSION_SUPPRESS_IF:
3714 CompareOne = ExpressSuppress;
3715 break;
3716
3717 case EFI_HII_EXPRESSION_GRAY_OUT_IF:
3718 CompareOne = ExpressGrayOut;
3719 break;
3720
3721 case EFI_HII_EXPRESSION_DISABLE_IF:
3722 CompareOne = ExpressDisable;
3723 break;
3724
3725 default:
3726 return ExpressFalse;
3727 }
3728
3729 ReturnVal = ReturnVal < CompareOne ? CompareOne : ReturnVal;
3730 }
3731 }
3732
3733 return ReturnVal;
3734 }