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