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