VirtualBox

source: vbox/trunk/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/SetupBrowserDxe/Expression.c@ 48674

Last change on this file since 48674 was 48674, checked in by vboxsync, 11 years ago

EFI: Export newly imported tinaocore UEFI sources to OSE.

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

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette